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

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit eff0d9f0c96087f65a4750c43ed7329250982d98
Author: Rene Cordier <[email protected]>
AuthorDate: Fri Apr 10 15:05:11 2026 +0700

    JAMES-4201 Add password.readonly and password.nodelete options to webadmin 
configuration
---
 .../james/modules/server/WebAdminServerModule.java |  2 +
 .../james/webadmin/WebAdminConfiguration.java      | 45 ++++++++++++-
 .../james/webadmin/WebAdminConfigurationTest.java  | 76 ++++++++++++++++++++++
 3 files changed, 121 insertions(+), 2 deletions(-)

diff --git 
a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
 
b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 9b9dcca561..bf42c4f701 100644
--- 
a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ 
b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -156,6 +156,8 @@ public class WebAdminServerModule extends AbstractModule {
                 
.maxThreadCount(Optional.ofNullable(configurationFile.getInteger("maxThreadCount",
 null)))
                 
.minThreadCount(Optional.ofNullable(configurationFile.getInteger("minThreadCount",
 null)))
                 
.password(Optional.ofNullable(configurationFile.getString("password", null)))
+                
.readOnlyPassword(Optional.ofNullable(configurationFile.getString("password.readonly",
 null)))
+                
.noDeletePassword(Optional.ofNullable(configurationFile.getString("password.nodelete",
 null)))
                 .build();
         } catch (FileNotFoundException e) {
             LOGGER.info("No webadmin.properties file. Disabling WebAdmin 
interface.");
diff --git 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index 820a8cc826..1a6bc158b6 100644
--- 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -58,6 +58,8 @@ public class WebAdminConfiguration {
         private Optional<String> urlCORSOrigin = Optional.empty();
         private Optional<String> host = Optional.empty();
         private Optional<String> password = Optional.empty();
+        private Optional<String> readOnlyPassword = Optional.empty();
+        private Optional<String> noDeletePassword = Optional.empty();
         private ImmutableList.Builder<String> additionalRoutes = 
ImmutableList.builder();
         private Optional<String> jwtPublicKey = Optional.empty();
         private Optional<Integer> maxThreadCount = Optional.empty();
@@ -134,6 +136,26 @@ public class WebAdminConfiguration {
             return this;
         }
 
+        public Builder readOnlyPassword(String readOnlyPassword) {
+            this.readOnlyPassword = Optional.ofNullable(readOnlyPassword);
+            return this;
+        }
+
+        public Builder readOnlyPassword(Optional<String> readOnlyPassword) {
+            this.readOnlyPassword = readOnlyPassword;
+            return this;
+        }
+
+        public Builder noDeletePassword(String noDeletePassword) {
+            this.noDeletePassword = Optional.ofNullable(noDeletePassword);
+            return this;
+        }
+
+        public Builder noDeletePassword(Optional<String> noDeletePassword) {
+            this.noDeletePassword = noDeletePassword;
+            return this;
+        }
+
         public Builder additionalRoute(String additionalRoute) {
             this.additionalRoutes.add(additionalRoute);
             return this;
@@ -167,6 +189,8 @@ public class WebAdminConfiguration {
                 additionalRoutes.build(),
                 jwtPublicKey,
                 password,
+                readOnlyPassword,
+                noDeletePassword,
                 maxThreadCount,
                 minThreadCount);
         }
@@ -181,12 +205,16 @@ public class WebAdminConfiguration {
     private final List<String> additionalRoutes;
     private final Optional<String> jwtPublicKey;
     private final Optional<String> password;
+    private final Optional<String> readOnlyPassword;
+    private final Optional<String> noDeletePassword;
     private final Optional<Integer> maxThreadCount;
     private final Optional<Integer> minThreadCount;
 
     @VisibleForTesting
     WebAdminConfiguration(boolean enabled, Optional<PortSupplier> port, 
Optional<TlsConfiguration> tlsConfiguration,
-                          boolean enableCORS, String urlCORSOrigin, String 
host, List<String> additionalRoutes, Optional<String> jwtPublicKey, 
Optional<String> password, Optional<Integer> maxThreadCount, Optional<Integer> 
minThreadCount) {
+                          boolean enableCORS, String urlCORSOrigin, String 
host, List<String> additionalRoutes, 
+                          Optional<String> jwtPublicKey, Optional<String> 
password, Optional<String> readOnlyPassword, 
+                          Optional<String> noDeletePassword, Optional<Integer> 
maxThreadCount, Optional<Integer> minThreadCount) {
         this.enabled = enabled;
         this.port = port;
         this.tlsConfiguration = tlsConfiguration;
@@ -196,6 +224,8 @@ public class WebAdminConfiguration {
         this.additionalRoutes = additionalRoutes;
         this.jwtPublicKey = jwtPublicKey;
         this.password = password;
+        this.readOnlyPassword = readOnlyPassword;
+        this.noDeletePassword = noDeletePassword;
         this.maxThreadCount = maxThreadCount;
         this.minThreadCount = minThreadCount;
     }
@@ -248,6 +278,14 @@ public class WebAdminConfiguration {
         return password;
     }
 
+    public Optional<String> getReadOnlyPassword() {
+        return readOnlyPassword;
+    }
+
+    public Optional<String> getNoDeletePassword() {
+        return noDeletePassword;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof WebAdminConfiguration) {
@@ -261,6 +299,8 @@ public class WebAdminConfiguration {
                 && Objects.equals(this.urlCORSOrigin, that.urlCORSOrigin)
                 && Objects.equals(this.host, that.host)
                 && Objects.equals(this.password, that.password)
+                && Objects.equals(this.readOnlyPassword, that.readOnlyPassword)
+                && Objects.equals(this.noDeletePassword, that.noDeletePassword)
                 && Objects.equals(this.additionalRoutes, that.additionalRoutes)
                 && Objects.equals(this.minThreadCount, that.minThreadCount)
                 && Objects.equals(this.maxThreadCount, that.maxThreadCount);
@@ -270,6 +310,7 @@ public class WebAdminConfiguration {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(enabled, port, tlsConfiguration, enableCORS, 
jwtPublicKey, urlCORSOrigin, host, additionalRoutes, minThreadCount, 
maxThreadCount, password);
+        return Objects.hash(enabled, port, tlsConfiguration, enableCORS, 
jwtPublicKey, urlCORSOrigin, host, 
+            password, readOnlyPassword, noDeletePassword, additionalRoutes, 
minThreadCount, maxThreadCount);
     }
 }
diff --git 
a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
 
b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index 3b390f20fe..b8736c9061 100644
--- 
a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ 
b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -22,6 +22,8 @@ package org.apache.james.webadmin;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import java.util.Optional;
+
 import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
@@ -190,6 +192,80 @@ class WebAdminConfigurationTest {
             .isEqualTo(host);
     }
 
+    @Test
+    void builderShouldAcceptReadOnlyPassword() {
+        String password = "readonly123";
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .readOnlyPassword(password)
+                .build())
+            .extracting(WebAdminConfiguration::getReadOnlyPassword)
+            .isEqualTo(Optional.of(password));
+    }
+
+    @Test
+    void builderShouldAcceptReadOnlyPasswordAsOptional() {
+        Optional<String> password = Optional.of("readonly456");
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .readOnlyPassword(password)
+                .build())
+            .extracting(WebAdminConfiguration::getReadOnlyPassword)
+            .isEqualTo(password);
+    }
+
+    @Test
+    void builderShouldReturnEmptyReadOnlyPasswordByDefault() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .build())
+            .extracting(WebAdminConfiguration::getReadOnlyPassword)
+            .isEqualTo(Optional.empty());
+    }
+
+    @Test
+    void builderShouldAcceptNoDeletePassword() {
+        String password = "nodelete123";
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .noDeletePassword(password)
+                .build())
+            .extracting(WebAdminConfiguration::getNoDeletePassword)
+            .isEqualTo(Optional.of(password));
+    }
+
+    @Test
+    void builderShouldAcceptNoDeletePasswordAsOptional() {
+        Optional<String> password = Optional.of("nodelete456");
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .noDeletePassword(password)
+                .build())
+            .extracting(WebAdminConfiguration::getNoDeletePassword)
+            .isEqualTo(password);
+    }
+
+    @Test
+    void builderShouldReturnEmptyNoDeletePasswordByDefault() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .build())
+            .extracting(WebAdminConfiguration::getNoDeletePassword)
+            .isEqualTo(Optional.empty());
+    }
+
     @Test
     void shouldMatchBeanContract() {
         EqualsVerifier.forClass(WebAdminConfiguration.class).verify();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to