You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2026/01/12 08:35:08 UTC
(james-project) 01/03: JAMES-4158 Allow protocols to add their own delegation logic
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 420665b66aab7da35ed481054ed089d634336e71
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Mon Jan 5 14:58:51 2026 +0100
JAMES-4158 Allow protocols to add their own delegation logic
Because we want to be able to do admin impersonation only on private network.
---
.../org/apache/james/mailbox/Authorizator.java | 18 ++++++++-
.../org/apache/james/mailbox/SessionProvider.java | 2 +
.../org/apache/james/mailbox/AuthorizatorTest.java | 45 ++++++++++++++++++++++
.../james/mailbox/store/SessionProviderImpl.java | 5 +++
.../james/mailbox/store/StoreMailboxManager.java | 6 +++
5 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/Authorizator.java b/mailbox/api/src/main/java/org/apache/james/mailbox/Authorizator.java
index 38cd4c40f5..575162f91d 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/Authorizator.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/Authorizator.java
@@ -38,7 +38,17 @@ public interface Authorizator {
enum AuthorizationState {
ALLOWED,
FORBIDDEN,
- UNKNOWN_USER
+ UNKNOWN_USER;
+
+ static AuthorizationState combine(AuthorizationState a, AuthorizationState b) {
+ if (a == AuthorizationState.FORBIDDEN) {
+ return b;
+ }
+ if (a == UNKNOWN_USER && b == ALLOWED) {
+ return b;
+ }
+ return a;
+ }
}
AuthorizationState canLoginAsOtherUser(Username userId, Username otherUserId) throws MailboxException;
@@ -50,5 +60,11 @@ public interface Authorizator {
default Collection<Username> delegatedUsers(Username username) {
return ImmutableList.of();
}
+
+ static Authorizator combine(Authorizator a, Authorizator b) {
+ return (userA, userB) -> AuthorizationState.combine(
+ a.canLoginAsOtherUser(userA, userB),
+ b.canLoginAsOtherUser(userA, userB));
+ }
}
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/SessionProvider.java b/mailbox/api/src/main/java/org/apache/james/mailbox/SessionProvider.java
index 5c8b9ec1b4..c0833462a6 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/SessionProvider.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/SessionProvider.java
@@ -75,4 +75,6 @@ public interface SessionProvider {
* when the creation fails for other reasons
*/
AuthorizationStep authenticate(Username givenUserid);
+
+ SessionProvider withExtraAuthorizator(Authorizator authorizator);
}
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/AuthorizatorTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/AuthorizatorTest.java
new file mode 100644
index 0000000000..ab8bdd8b18
--- /dev/null
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/AuthorizatorTest.java
@@ -0,0 +1,45 @@
+/******************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ******************************************************************/
+
+package org.apache.james.mailbox;
+
+import static org.apache.james.mailbox.Authorizator.AuthorizationState.ALLOWED;
+import static org.apache.james.mailbox.Authorizator.AuthorizationState.FORBIDDEN;
+import static org.apache.james.mailbox.Authorizator.AuthorizationState.UNKNOWN_USER;
+
+import org.apache.james.mailbox.Authorizator.AuthorizationState;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
+
+class AuthorizatorTest {
+ @Test
+ void combineShouldAggregateResults() {
+ SoftAssertions.assertSoftly(softly -> {
+ softly.assertThat(AuthorizationState.combine(ALLOWED, ALLOWED)).isEqualTo(ALLOWED);
+ softly.assertThat(AuthorizationState.combine(ALLOWED, FORBIDDEN)).isEqualTo(ALLOWED);
+ softly.assertThat(AuthorizationState.combine(FORBIDDEN, ALLOWED)).isEqualTo(ALLOWED);
+ softly.assertThat(AuthorizationState.combine(FORBIDDEN, FORBIDDEN)).isEqualTo(FORBIDDEN);
+ softly.assertThat(AuthorizationState.combine(UNKNOWN_USER, FORBIDDEN)).isEqualTo(UNKNOWN_USER);
+ softly.assertThat(AuthorizationState.combine(FORBIDDEN, UNKNOWN_USER)).isEqualTo(UNKNOWN_USER);
+ softly.assertThat(AuthorizationState.combine(UNKNOWN_USER, UNKNOWN_USER)).isEqualTo(UNKNOWN_USER);
+ softly.assertThat(AuthorizationState.combine(UNKNOWN_USER, ALLOWED)).isEqualTo(ALLOWED);
+ softly.assertThat(AuthorizationState.combine(ALLOWED, UNKNOWN_USER)).isEqualTo(ALLOWED);
+ });
+ }
+}
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java
index b0eea7c0a3..9a250499eb 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java
@@ -148,4 +148,9 @@ public class SessionProviderImpl implements SessionProvider {
private Optional<Username> isValidLogin(Username userid, String passwd) throws MailboxException {
return authenticator.isAuthentic(userid, passwd);
}
+
+ @Override
+ public SessionProvider withExtraAuthorizator(Authorizator authorizator) {
+ return new SessionProviderImpl(authenticator, Authorizator.combine(this.authorizator, authorizator));
+ }
}
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index 02daa0eb21..16bf7c12cd 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -37,6 +37,7 @@ import org.apache.james.core.Username;
import org.apache.james.core.quota.QuotaCountUsage;
import org.apache.james.core.quota.QuotaSizeUsage;
import org.apache.james.events.EventBus;
+import org.apache.james.mailbox.Authorizator;
import org.apache.james.mailbox.DefaultMailboxes;
import org.apache.james.mailbox.MailboxAnnotationManager;
import org.apache.james.mailbox.MailboxManager;
@@ -250,6 +251,11 @@ public class StoreMailboxManager implements MailboxManager {
return sessionProvider.authenticate(givenUserid, passwd);
}
+ @Override
+ public SessionProvider withExtraAuthorizator(Authorizator authorizator) {
+ return sessionProvider.withExtraAuthorizator(authorizator);
+ }
+
@Override
public AuthorizationStep authenticate(Username givenUserid) {
return sessionProvider.authenticate(givenUserid);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org