This is an automated email from the ASF dual-hosted git repository.

epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-mcp.git


The following commit(s) were added to refs/heads/main by this push:
     new ab42b64  feat(config): HTTP Basic Authentication credentials (builds 
on #89) (#152)
ab42b64 is described below

commit ab42b64da26b1320e1826737c6300e040a6e02e1
Author: Aditya Parikh <[email protected]>
AuthorDate: Mon Jun 15 12:34:33 2026 -0400

    feat(config): HTTP Basic Authentication credentials (builds on #89) (#152)
    
    * feat(config): support HTTP Basic Authentication credentials
    
    Add optional `solr.username` / `solr.password` configuration properties
    (also bound from the `SOLR_USERNAME` / `SOLR_PASSWORD` environment
    variables) that, when both are set, are applied to every SolrJ request
    via `HttpJdkSolrClient.Builder#withBasicAuthCredentials`. When either
    value is missing or the username is blank, the client is built without
    credentials so existing unauthenticated deployments are unaffected.
    
    Documents the new variables in the Development and Architecture guides
    and adds `SolrConfigAuthTest` covering:
    
    - no credentials attached when both values are missing,
    - no credentials attached when only one value is provided (or the
      username is blank), and
    - credentials applied when both values are provided.
    
    The existing `SolrConfigUrlNormalizationTest` is updated to the new
    record constructor.
    
    Co-authored-by: Claude <[email protected]>
    Signed-off-by: Yunus Emre Korkmaz <[email protected]>
    
    * refactor(config): reuse Spring StringUtils/ReflectionUtils in basic-auth 
wiring
    
    Review cleanup on top of the HTTP Basic Auth support from #89 (by
    @dolphinium). No behavioural change to the feature.
    
    - SolrConfig: replace the inline `username != null && !username.isEmpty()`
      guard with Spring's `StringUtils.hasText`, matching the convention already
      used in HttpSecurityConfiguration and SearchService.
    - SolrConfigAuthTest: drop the hand-rolled superclass-walking `findField`
      helper in favour of 
`ReflectionUtils.findField`/`makeAccessible`/`getField`,
      and tighten the over-defensive `equals(x) || equals("Basic " + x)` 
assertion
      to an exact `assertEquals` now that the stored format is known (SolrJ 
stores
      `"Basic " + Base64(user:pass)` in UTF-8).
    
    ./gradlew build passes (Spotless + NullAway + full test suite incl. 
Testcontainers).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    Signed-off-by: adityamparikh <[email protected]>
    
    ---------
    
    Signed-off-by: Yunus Emre Korkmaz <[email protected]>
    Signed-off-by: adityamparikh <[email protected]>
    Signed-off-by: Eric Pugh <[email protected]>
    Co-authored-by: Yunus Emre Korkmaz <[email protected]>
    Co-authored-by: Claude <[email protected]>
    Co-authored-by: Eric Pugh <[email protected]>
---
 .../apache/solr/mcp/server/config/SolrConfig.java  |  3 ++-
 .../solr/mcp/server/config/SolrConfigAuthTest.java | 30 ++++++++--------------
 2 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/apache/solr/mcp/server/config/SolrConfig.java 
b/src/main/java/org/apache/solr/mcp/server/config/SolrConfig.java
index d0eb1da..ae0eae4 100644
--- a/src/main/java/org/apache/solr/mcp/server/config/SolrConfig.java
+++ b/src/main/java/org/apache/solr/mcp/server/config/SolrConfig.java
@@ -24,6 +24,7 @@ import org.apache.solr.client.solrj.request.XMLRequestWriter;
 import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
 
 /**
  * Spring Configuration class for Apache Solr client setup and connection
@@ -208,7 +209,7 @@ public class SolrConfig {
                // are provided so existing unauthenticated deployments are 
unaffected.
                String username = properties.username();
                String password = properties.password();
-               if (username != null && !username.isEmpty() && password != 
null) {
+               if (StringUtils.hasText(username) && password != null) {
                        builder.withBasicAuthCredentials(username, password);
                }
 
diff --git 
a/src/test/java/org/apache/solr/mcp/server/config/SolrConfigAuthTest.java 
b/src/test/java/org/apache/solr/mcp/server/config/SolrConfigAuthTest.java
index 8a49ded..8dd5740 100644
--- a/src/test/java/org/apache/solr/mcp/server/config/SolrConfigAuthTest.java
+++ b/src/test/java/org/apache/solr/mcp/server/config/SolrConfigAuthTest.java
@@ -16,13 +16,14 @@
  */
 package org.apache.solr.mcp.server.config;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.impl.HttpJdkSolrClient;
@@ -31,6 +32,7 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.json.JsonTest;
+import org.springframework.util.ReflectionUtils;
 
 /**
  * Unit tests for the optional HTTP Basic Authentication wiring performed by
@@ -62,10 +64,9 @@ class SolrConfigAuthTest {
        @Test
        void credentialsAppliedWhenBothProvided() throws Exception {
                String header = authorizationHeaderFor("alice", "s3cret");
-               assertNotNull(header);
-               String expected = 
Base64.getEncoder().encodeToString("alice:s3cret".getBytes());
-               assertTrue(header.equals(expected) || header.equals("Basic " + 
expected),
-                               "Expected Basic auth payload for alice:s3cret, 
got: " + header);
+               String expected = "Basic "
+                               + 
Base64.getEncoder().encodeToString("alice:s3cret".getBytes(StandardCharsets.UTF_8));
+               assertEquals(expected, header);
        }
 
        private @org.jspecify.annotations.Nullable String 
authorizationHeaderFor(
@@ -76,21 +77,10 @@ class SolrConfigAuthTest {
                SolrConfig config = new SolrConfig();
                try (SolrClient client = config.solrClient(properties, new 
JsonResponseParser(objectMapper))) {
                        HttpJdkSolrClient httpClient = 
assertInstanceOf(HttpJdkSolrClient.class, client);
-                       Field field = findField(httpClient.getClass(), 
"basicAuthAuthorizationStr");
-                       field.setAccessible(true);
-                       return (String) field.get(httpClient);
+                       Field field = 
ReflectionUtils.findField(httpClient.getClass(), "basicAuthAuthorizationStr");
+                       assertNotNull(field, "SolrJ field 
'basicAuthAuthorizationStr' not found");
+                       ReflectionUtils.makeAccessible(field);
+                       return (String) ReflectionUtils.getField(field, 
httpClient);
                }
        }
-
-       private static Field findField(Class<?> type, String name) throws 
NoSuchFieldException {
-               Class<?> current = type;
-               while (current != null) {
-                       try {
-                               return current.getDeclaredField(name);
-                       } catch (NoSuchFieldException ignored) {
-                               current = current.getSuperclass();
-                       }
-               }
-               throw new NoSuchFieldException(name);
-       }
 }

Reply via email to