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 7761e48b02056c486bd6253a231953e2505fa786 Author: Quan Tran <hqt...@linagora.com> AuthorDate: Mon Dec 23 17:02:06 2024 +0700 JAMES-4098 ReadOnlyUsersLDAPRepository::isAdministrator should take into account the multiple administrators if configured Default to the current LDAP configuration `administrator` entry, if empty fallback to the multiple administrators one. --- .../user/ldap/ReadOnlyUsersLDAPRepository.java | 23 +++++++-- .../user/ldap/ReadOnlyUsersLDAPRepositoryTest.java | 56 ++++++++++++++++++++++ .../james/user/lib/UsersRepositoryContract.java | 8 ++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java index bffa18e32a..f13518c5ba 100644 --- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java +++ b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepository.java @@ -33,6 +33,7 @@ import org.apache.james.user.api.InvalidUsernameException; import org.apache.james.user.api.UsersRepositoryException; import org.apache.james.user.lib.UsersRepositoryImpl; +import com.github.fge.lambdas.Throwing; import com.unboundid.ldap.sdk.LDAPConnectionPool; import com.unboundid.ldap.sdk.LDAPException; @@ -211,14 +212,28 @@ public class ReadOnlyUsersLDAPRepository extends UsersRepositoryImpl<ReadOnlyLDA return ldapConfiguration.supportsVirtualHosting(); } + /** + * Determines if the given username has administrator privileges. + * <p> + * If the {@code administratorId} is set in the LDAP configuration, the method will return + * {@code true} only if the given username matches the configured administrator ID. + * <p> + * If the {@code administratorId} is not set, the method falls back to the default + * administrator determination provided by the parent implementation which could + * support a list of administrators. + * </p> + * + * @param username The {@link Username} to check for administrator privileges. + * @return {@code true} if the username has administrator privileges, {@code false} otherwise. + * @throws UsersRepositoryException If an error occurs while validating the username. + */ @Override public boolean isAdministrator(Username username) throws UsersRepositoryException { assertValid(username); - if (ldapConfiguration.getAdministratorId().isPresent()) { - return ldapConfiguration.getAdministratorId().get().equals(username); - } - return false; + return ldapConfiguration.getAdministratorId() + .map(ldapAdministratorAttribute -> ldapAdministratorAttribute.equals(username)) + .orElseGet(Throwing.supplier(() -> super.isAdministrator(username))); } @Override diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java index bbad94794f..6673bc1361 100644 --- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java +++ b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/ReadOnlyUsersLDAPRepositoryTest.java @@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.Optional; +import java.util.Set; import org.apache.commons.configuration2.HierarchicalConfiguration; import org.apache.commons.configuration2.ex.ConversionException; @@ -259,11 +260,31 @@ class ReadOnlyUsersLDAPRepositoryTest { return startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer, administrator), testSystem.getDomainList()); } + @Override + public UsersRepository testee(Set<Username> administrators) throws Exception { + return startUsersRepository(ldapRepositoryConfigurationWithVirtualHosting(ldapContainer, administrators), testSystem.getDomainList()); + } + @Test void isAdministratorShouldReturnTrueWhenConfiguredAndUserIsAdmin(TestSystem testSystem) throws Exception { assertThat(testee().isAdministrator(testSystem.getAdmin())).isTrue(); } + @Test + void isAdministratorShouldReturnTrueWhenConfiguredMultipleAdminsAndUserIsAdmin(TestSystem testSystem) throws Exception { + UsersRepository testee = testee(Set.of(testSystem.getAdmin(), testSystem.getUser1())); + + assertThat(testee.isAdministrator(testSystem.getAdmin())).isTrue(); + assertThat(testee.isAdministrator(testSystem.getUser1())).isTrue(); + } + + @Test + void isAdministratorShouldReturnFalseWhenConfiguredAndUserIsNotAdmin(TestSystem testSystem) throws Exception { + UsersRepository testee = testee(Set.of(testSystem.getAdmin(), testSystem.getUser1())); + + assertThat(testee.isAdministrator(testSystem.getUser2())).isFalse(); + } + @Test void knownUserShouldBeAbleToLogInWhenPasswordIsCorrectWithVirtualHosting() throws Exception { assertThat(usersRepository.test(JAMES_USER_MAIL, PASSWORD)).isEqualTo(Optional.of(JAMES_USER_MAIL)); @@ -365,6 +386,11 @@ class ReadOnlyUsersLDAPRepositoryTest { return startUsersRepository(ldapRepositoryConfiguration(ldapContainer, administrator), testSystem.getDomainList()); } + @Override + public UsersRepository testee(Set<Username> administrators) throws Exception { + return startUsersRepository(ldapRepositoryConfiguration(ldapContainer, administrators), testSystem.getDomainList()); + } + @Test void knownUserShouldBeAbleToLogInWhenPasswordIsCorrect() throws Exception { assertThat(usersRepository.test(JAMES_USER, PASSWORD)).isEqualTo(Optional.of(JAMES_USER)); @@ -415,6 +441,21 @@ class ReadOnlyUsersLDAPRepositoryTest { assertThat(testee().isAdministrator(testSystem.getAdmin())).isTrue(); } + @Test + void isAdministratorShouldReturnTrueWhenConfiguredMultipleAdminsAndUserIsAdmin(TestSystem testSystem) throws Exception { + UsersRepository testee = testee(Set.of(testSystem.getAdmin(), testSystem.getUser1())); + + assertThat(testee.isAdministrator(testSystem.getAdmin())).isTrue(); + assertThat(testee.isAdministrator(testSystem.getUser1())).isTrue(); + } + + @Test + void isAdministratorShouldReturnFalseWhenConfiguredAndUserIsNotAdmin(TestSystem testSystem) throws Exception { + UsersRepository testee = testee(Set.of(testSystem.getAdmin(), testSystem.getUser1())); + + assertThat(testee.isAdministrator(testSystem.getUser2())).isFalse(); + } + @Disabled("JAMES-3088 Users are provisioned by default from Dockerfile, cannot setup this test case," + "See @link{ReadOnlyUsersLDAPRepositoryEmptyListTest}") @Override @@ -524,6 +565,13 @@ class ReadOnlyUsersLDAPRepositoryTest { return configuration; } + static HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfiguration(LdapGenericContainer ldapContainer, Set<Username> administrators) { + PropertyListConfiguration configuration = baseConfiguration(ldapContainer); + configuration.addProperty("[@userIdAttribute]", "uid"); + administrators.forEach(admin -> configuration.addProperty("administratorIds.administratorId", admin.asString())); + return configuration; + } + static HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfigurationWithVirtualHosting(LdapGenericContainer ldapContainer) { return ldapRepositoryConfigurationWithVirtualHosting(ldapContainer, Optional.of(ADMIN)); } @@ -536,6 +584,14 @@ class ReadOnlyUsersLDAPRepositoryTest { return configuration; } + static HierarchicalConfiguration<ImmutableNode> ldapRepositoryConfigurationWithVirtualHosting(LdapGenericContainer ldapContainer, Set<Username> administrators) { + PropertyListConfiguration configuration = baseConfiguration(ldapContainer); + configuration.addProperty("[@userIdAttribute]", "mail"); + configuration.addProperty("supportsVirtualHosting", true); + administrators.forEach(admin -> configuration.addProperty("administratorIds.administratorId", admin.asString())); + return configuration; + } + private static PropertyListConfiguration baseConfiguration(LdapGenericContainer ldapContainer) { PropertyListConfiguration configuration = new PropertyListConfiguration(); configuration.addProperty("[@ldapHost]", ldapContainer.getLdapHost()); diff --git a/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryContract.java b/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryContract.java index 9f2816baa5..61f062c453 100644 --- a/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryContract.java +++ b/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryContract.java @@ -141,6 +141,14 @@ public interface UsersRepositoryContract { return admin; } + public Username getUser1() { + return user1; + } + + public Username getUser2() { + return user2; + } + public Username getUserWithUnknownDomain() { return userWithUnknownDomain; } --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org