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

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


The following commit(s) were added to refs/heads/postgresql by this push:
     new decec6ffc5 JAMES-2586 PostgresDelegationStore (#1851)
decec6ffc5 is described below

commit decec6ffc5ac8f5037572d47a099e257ed644029
Author: hungphan227 <45198168+hungphan...@users.noreply.github.com>
AuthorDate: Wed Dec 13 16:24:11 2023 +0700

    JAMES-2586 PostgresDelegationStore (#1851)
---
 .../org/apache/james/PostgresJamesServerMain.java  |  3 +-
 ...ule.java => PostgresDelegationStoreModule.java} | 25 +++---
 .../data/PostgresUsersRepositoryModule.java        | 22 -----
 .../user/postgres/PostgresDelegationStore.java     | 89 ++++++++++++++++++++
 .../james/user/postgres/PostgresUserModule.java    |  8 +-
 .../james/user/postgres/PostgresUsersDAO.java      | 98 ++++++++++++++++++++++
 .../user/postgres/PostgresDelegationStoreTest.java | 67 +++++++++++++++
 7 files changed, 272 insertions(+), 40 deletions(-)

diff --git 
a/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
 
b/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
index 1191382350..24cfa7d1cd 100644
--- 
a/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
+++ 
b/server/apps/postgres-app/src/main/java/org/apache/james/PostgresJamesServerMain.java
@@ -24,6 +24,7 @@ import org.apache.james.modules.MailboxModule;
 import org.apache.james.modules.MailetProcessingModule;
 import org.apache.james.modules.RunArgumentsModule;
 import org.apache.james.modules.data.PostgresDataModule;
+import org.apache.james.modules.data.PostgresDelegationStoreModule;
 import org.apache.james.modules.data.PostgresUsersRepositoryModule;
 import org.apache.james.modules.data.SievePostgresRepositoryModules;
 import org.apache.james.modules.mailbox.DefaultEventModule;
@@ -79,7 +80,7 @@ public class PostgresJamesServerMain implements 
JamesServerMain {
 
     private static final Module POSTGRES_SERVER_MODULE = Modules.combine(
         new ActiveMQQueueModule(),
-        new NaiveDelegationStoreModule(),
+        new PostgresDelegationStoreModule(),
         new DefaultProcessorsConfigurationProviderModule(),
         new PostgresMailboxModule(),
         new PostgresDataModule(),
diff --git 
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
 
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresDelegationStoreModule.java
similarity index 74%
copy from 
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
copy to 
server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresDelegationStoreModule.java
index 575f7621f0..f6e5521ead 100644
--- 
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
+++ 
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresDelegationStoreModule.java
@@ -22,27 +22,29 @@ package org.apache.james.modules.data;
 import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.james.backends.postgres.PostgresModule;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
-import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.DelegationStore;
+import org.apache.james.user.api.DelegationUsernameChangeTaskStep;
+import org.apache.james.user.api.UsernameChangeTaskStep;
 import org.apache.james.user.lib.UsersDAO;
+import org.apache.james.user.postgres.PostgresDelegationStore;
 import org.apache.james.user.postgres.PostgresUserModule;
 import org.apache.james.user.postgres.PostgresUsersDAO;
-import org.apache.james.user.postgres.PostgresUsersRepository;
 import org.apache.james.user.postgres.PostgresUsersRepositoryConfiguration;
-import org.apache.james.utils.InitializationOperation;
-import org.apache.james.utils.InitilizationOperationBuilder;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 import com.google.inject.Scopes;
 import com.google.inject.Singleton;
 import com.google.inject.multibindings.Multibinder;
-import com.google.inject.multibindings.ProvidesIntoSet;
 
-public class PostgresUsersRepositoryModule extends AbstractModule {
+public class PostgresDelegationStoreModule extends AbstractModule {
     @Override
     public void configure() {
-        bind(PostgresUsersRepository.class).in(Scopes.SINGLETON);
-        bind(UsersRepository.class).to(PostgresUsersRepository.class);
+        bind(DelegationStore.class).to(PostgresDelegationStore.class);
+        
bind(PostgresDelegationStore.UserExistencePredicate.class).to(PostgresDelegationStore.UserExistencePredicateImplementation.class);
+
+        Multibinder.newSetBinder(binder(), UsernameChangeTaskStep.class)
+            .addBinding().to(DelegationUsernameChangeTaskStep.class);
 
         bind(PostgresUsersDAO.class).in(Scopes.SINGLETON);
         bind(UsersDAO.class).to(PostgresUsersDAO.class);
@@ -57,11 +59,4 @@ public class PostgresUsersRepositoryModule extends 
AbstractModule {
         return PostgresUsersRepositoryConfiguration.from(
             configurationProvider.getConfiguration("usersrepository"));
     }
-
-    @ProvidesIntoSet
-    InitializationOperation configureInitialization(ConfigurationProvider 
configurationProvider, PostgresUsersRepository usersRepository) {
-        return InitilizationOperationBuilder
-            .forClass(PostgresUsersRepository.class)
-            .init(() -> 
usersRepository.configure(configurationProvider.getConfiguration("usersrepository")));
-    }
 }
diff --git 
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
 
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
index 575f7621f0..ff30223bb8 100644
--- 
a/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
+++ 
b/server/container/guice/postgres-common/src/main/java/org/apache/james/modules/data/PostgresUsersRepositoryModule.java
@@ -19,23 +19,14 @@
 
 package org.apache.james.modules.data;
 
-import org.apache.commons.configuration2.ex.ConfigurationException;
-import org.apache.james.backends.postgres.PostgresModule;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.lib.UsersDAO;
-import org.apache.james.user.postgres.PostgresUserModule;
-import org.apache.james.user.postgres.PostgresUsersDAO;
 import org.apache.james.user.postgres.PostgresUsersRepository;
-import org.apache.james.user.postgres.PostgresUsersRepositoryConfiguration;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
 import com.google.inject.Scopes;
-import com.google.inject.Singleton;
-import com.google.inject.multibindings.Multibinder;
 import com.google.inject.multibindings.ProvidesIntoSet;
 
 public class PostgresUsersRepositoryModule extends AbstractModule {
@@ -43,19 +34,6 @@ public class PostgresUsersRepositoryModule extends 
AbstractModule {
     public void configure() {
         bind(PostgresUsersRepository.class).in(Scopes.SINGLETON);
         bind(UsersRepository.class).to(PostgresUsersRepository.class);
-
-        bind(PostgresUsersDAO.class).in(Scopes.SINGLETON);
-        bind(UsersDAO.class).to(PostgresUsersDAO.class);
-
-        Multibinder<PostgresModule> postgresDataDefinitions = 
Multibinder.newSetBinder(binder(), PostgresModule.class);
-        
postgresDataDefinitions.addBinding().toInstance(PostgresUserModule.MODULE);
-    }
-
-    @Provides
-    @Singleton
-    public PostgresUsersRepositoryConfiguration 
provideConfiguration(ConfigurationProvider configurationProvider) throws 
ConfigurationException {
-        return PostgresUsersRepositoryConfiguration.from(
-            configurationProvider.getConfiguration("usersrepository"));
     }
 
     @ProvidesIntoSet
diff --git 
a/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresDelegationStore.java
 
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresDelegationStore.java
new file mode 100644
index 0000000000..4f04f45075
--- /dev/null
+++ 
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresDelegationStore.java
@@ -0,0 +1,89 @@
+/****************************************************************
+ * 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.user.postgres;
+
+import javax.inject.Inject;
+
+import org.apache.james.core.Username;
+import org.apache.james.user.api.DelegationStore;
+import org.apache.james.user.api.UsersRepository;
+import org.reactivestreams.Publisher;
+
+import reactor.core.publisher.Mono;
+
+public class PostgresDelegationStore implements DelegationStore {
+    public interface UserExistencePredicate {
+        Mono<Boolean> exists(Username username);
+    }
+
+    public static class UserExistencePredicateImplementation implements 
UserExistencePredicate {
+        private final UsersRepository usersRepository;
+
+        @Inject
+        UserExistencePredicateImplementation(UsersRepository usersRepository) {
+            this.usersRepository = usersRepository;
+        }
+
+        @Override
+        public Mono<Boolean> exists(Username username) {
+            return Mono.from(usersRepository.containsReactive(username));
+        }
+    }
+
+    private PostgresUsersDAO postgresUsersDAO;
+    private final UserExistencePredicate userExistencePredicate;
+
+    @Inject
+    public PostgresDelegationStore(PostgresUsersDAO postgresUsersDAO, 
UserExistencePredicate userExistencePredicate) {
+        this.postgresUsersDAO = postgresUsersDAO;
+        this.userExistencePredicate = userExistencePredicate;
+    }
+
+    @Override
+    public Publisher<Username> authorizedUsers(Username baseUser) {
+        return postgresUsersDAO.getAuthorizedUsers(baseUser);
+    }
+
+    @Override
+    public Publisher<Void> clear(Username baseUser) {
+        return postgresUsersDAO.removeAllAuthorizedUsers(baseUser);
+    }
+
+    @Override
+    public Publisher<Void> addAuthorizedUser(Username baseUser, Username 
userWithAccess) {
+        return userExistencePredicate.exists(userWithAccess)
+            .flatMap(targetUserExists -> 
postgresUsersDAO.addAuthorizedUser(baseUser, userWithAccess, targetUserExists));
+    }
+
+    @Override
+    public Publisher<Void> removeAuthorizedUser(Username baseUser, Username 
userWithAccess) {
+        return postgresUsersDAO.removeAuthorizedUser(baseUser, userWithAccess);
+    }
+
+    @Override
+    public Publisher<Username> delegatedUsers(Username baseUser) {
+        return postgresUsersDAO.getDelegatedToUsers(baseUser);
+    }
+
+    @Override
+    public Publisher<Void> removeDelegatedUser(Username baseUser, Username 
delegatedToUser) {
+        return postgresUsersDAO.removeDelegatedToUser(baseUser, 
delegatedToUser);
+    }
+}
diff --git 
a/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
 
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
index 6aae9183f8..e5bc618d31 100644
--- 
a/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
+++ 
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUserModule.java
@@ -32,14 +32,18 @@ public interface PostgresUserModule {
         Table<Record> TABLE_NAME = DSL.table("users");
 
         Field<String> USERNAME = DSL.field("username", 
SQLDataType.VARCHAR(255).notNull());
-        Field<String> HASHED_PASSWORD = DSL.field("hashed_password", 
SQLDataType.VARCHAR.notNull());
-        Field<String> ALGORITHM = DSL.field("algorithm", 
SQLDataType.VARCHAR(100).notNull());
+        Field<String> HASHED_PASSWORD = DSL.field("hashed_password", 
SQLDataType.VARCHAR);
+        Field<String> ALGORITHM = DSL.field("algorithm", 
SQLDataType.VARCHAR(100));
+        Field<String[]> AUTHORIZED_USERS = DSL.field("authorized_users", 
SQLDataType.VARCHAR.getArrayDataType());
+        Field<String[]> DELEGATED_USERS = DSL.field("delegated_users", 
SQLDataType.VARCHAR.getArrayDataType());
 
         PostgresTable TABLE = PostgresTable.name(TABLE_NAME.getName())
             .createTableStep(((dsl, tableName) -> 
dsl.createTableIfNotExists(tableName)
                 .column(USERNAME)
                 .column(HASHED_PASSWORD)
                 .column(ALGORITHM)
+                .column(AUTHORIZED_USERS)
+                .column(DELEGATED_USERS)
                 .constraint(DSL.primaryKey(USERNAME))))
             .disableRowLevelSecurity();
     }
diff --git 
a/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
 
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
index d8447e527f..d0467bf847 100644
--- 
a/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
+++ 
b/server/data/data-postgres/src/main/java/org/apache/james/user/postgres/PostgresUsersDAO.java
@@ -22,7 +22,10 @@ package org.apache.james.user.postgres;
 import static 
org.apache.james.backends.postgres.utils.PostgresExecutor.DEFAULT_INJECT;
 import static 
org.apache.james.backends.postgres.utils.PostgresUtils.UNIQUE_CONSTRAINT_VIOLATION_PREDICATE;
 import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.ALGORITHM;
+import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.AUTHORIZED_USERS;
+import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.DELEGATED_USERS;
 import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.HASHED_PASSWORD;
+import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.TABLE;
 import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.TABLE_NAME;
 import static 
org.apache.james.user.postgres.PostgresUserModule.PostgresUserTable.USERNAME;
 import static org.jooq.impl.DSL.count;
@@ -41,8 +44,14 @@ import org.apache.james.user.api.model.User;
 import org.apache.james.user.lib.UsersDAO;
 import org.apache.james.user.lib.model.Algorithm;
 import org.apache.james.user.lib.model.DefaultUser;
+import org.jooq.DSLContext;
+import org.jooq.Field;
+import org.jooq.Record;
+import org.jooq.UpdateConditionStep;
+import org.jooq.impl.DSL;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
@@ -141,4 +150,93 @@ public class PostgresUsersDAO implements UsersDAO {
                 e -> new AlreadyExistInUsersRepositoryException("User with 
username " + username + " already exist!"))
             .block();
     }
+
+    public Mono<Void> addAuthorizedUser(Username baseUser, Username 
userWithAccess, boolean targetUserExists) {
+        return addUserToList(AUTHORIZED_USERS, baseUser, userWithAccess)
+            .then(addDelegatedUser(baseUser, userWithAccess, 
targetUserExists));
+    }
+
+    private Mono<Void> addDelegatedUser(Username baseUser, Username 
userWithAccess, boolean targetUserExists) {
+        if (targetUserExists) {
+            return addUserToList(DELEGATED_USERS, userWithAccess, baseUser);
+        } else {
+            return Mono.empty();
+        }
+    }
+
+    private Mono<Void> addUserToList(Field<String[]> field, Username baseUser, 
Username targetUser) {
+        String fullAuthorizedUsersColumnName = TABLE.getName() + "." + 
field.getName();
+        return postgresExecutor.executeVoid(dslContext ->
+            Mono.from(dslContext.insertInto(TABLE_NAME)
+                .set(USERNAME, baseUser.asString())
+                .set(field, DSL.array(targetUser.asString()))
+                .onConflict(USERNAME)
+                .doUpdate()
+                .set(DSL.field(field.getName()),
+                    (Object) DSL.field("array_append(coalesce(" + 
fullAuthorizedUsersColumnName + ", array[]::varchar[]), ?)",
+                        targetUser.asString()))
+                .where(DSL.field(fullAuthorizedUsersColumnName).isNull()
+                    
.or(DSL.field(fullAuthorizedUsersColumnName).notContains(new 
String[]{targetUser.asString()})))));
+    }
+
+    public Mono<Void> removeAuthorizedUser(Username baseUser, Username 
userWithAccess) {
+        return removeUserInAuthorizedList(baseUser, userWithAccess)
+            .then(removeUserInDelegatedList(userWithAccess, baseUser));
+    }
+
+    public Mono<Void> removeDelegatedToUser(Username baseUser, Username 
delegatedToUser) {
+        return removeUserInDelegatedList(baseUser, delegatedToUser)
+            .then(removeUserInAuthorizedList(delegatedToUser, baseUser));
+    }
+
+    private Mono<Void> removeUserInAuthorizedList(Username baseUser, Username 
targetUser) {
+        return removeUserFromList(AUTHORIZED_USERS, baseUser, targetUser);
+    }
+
+    private Mono<Void> removeUserInDelegatedList(Username baseUser, Username 
targetUser) {
+        return removeUserFromList(DELEGATED_USERS, baseUser, targetUser);
+    }
+
+    private Mono<Void> removeUserFromList(Field<String[]> field, Username 
baseUser, Username targetUser) {
+        return postgresExecutor.executeVoid(dslContext ->
+            Mono.from(createQueryRemoveUserFromList(dslContext, field, 
baseUser, targetUser)));
+    }
+
+    private UpdateConditionStep<Record> 
createQueryRemoveUserFromList(DSLContext dslContext, Field<String[]> field, 
Username baseUser, Username targetUser) {
+        return dslContext.update(TABLE_NAME)
+            .set(DSL.field(field.getName()),
+                (Object) DSL.field("array_remove(" + field.getName() + ", ?)",
+                    targetUser.asString()))
+            .where(USERNAME.eq(baseUser.asString()))
+            .and(DSL.field(field.getName()).isNotNull());
+    }
+
+    public Mono<Void> removeAllAuthorizedUsers(Username baseUser) {
+        return getAuthorizedUsers(baseUser)
+            .collect(ImmutableList.toImmutableList())
+            .flatMap(usernames -> postgresExecutor.executeVoid(dslContext ->
+                Mono.from(dslContext.batch(usernames.stream()
+                    .map(username -> createQueryRemoveUserFromList(dslContext, 
DELEGATED_USERS, username, baseUser))
+                    .collect(ImmutableList.toImmutableList())))))
+            .then(postgresExecutor.executeVoid(dslContext -> 
Mono.from(dslContext.update(TABLE_NAME)
+                .setNull(AUTHORIZED_USERS)
+                .where(USERNAME.eq(baseUser.asString())))));
+    }
+
+    public Flux<Username> getAuthorizedUsers(Username name) {
+        return getUsersFromList(AUTHORIZED_USERS, name);
+    }
+
+    public Flux<Username> getDelegatedToUsers(Username name) {
+        return getUsersFromList(DELEGATED_USERS, name);
+    }
+
+    public Flux<Username> getUsersFromList(Field<String[]> field, Username 
name) {
+        return postgresExecutor.executeRow(dslContext -> 
Mono.from(dslContext.select(field)
+                .from(TABLE_NAME)
+                .where(USERNAME.eq(name.asString()))))
+            .flatMapMany(record -> Optional.ofNullable(record.get(field))
+                .map(Flux::fromArray).orElse(Flux.empty()))
+            .map(Username::of);
+    }
 }
diff --git 
a/server/data/data-postgres/src/test/java/org/apache/james/user/postgres/PostgresDelegationStoreTest.java
 
b/server/data/data-postgres/src/test/java/org/apache/james/user/postgres/PostgresDelegationStoreTest.java
new file mode 100644
index 0000000000..cae65185a6
--- /dev/null
+++ 
b/server/data/data-postgres/src/test/java/org/apache/james/user/postgres/PostgresDelegationStoreTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.user.postgres;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.backends.postgres.PostgresExtension;
+import org.apache.james.core.Username;
+import org.apache.james.user.api.DelegationStore;
+import org.apache.james.user.api.DelegationStoreContract;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import reactor.core.publisher.Mono;
+
+public class PostgresDelegationStoreTest implements DelegationStoreContract {
+    @RegisterExtension
+    static PostgresExtension postgresExtension = 
PostgresExtension.withoutRowLevelSecurity(PostgresUserModule.MODULE);
+
+    private PostgresUsersDAO postgresUsersDAO;
+    private PostgresDelegationStore postgresDelegationStore;
+
+    @BeforeEach
+    void beforeEach() {
+        postgresUsersDAO = new 
PostgresUsersDAO(postgresExtension.getPostgresExecutor(), 
PostgresUsersRepositoryConfiguration.DEFAULT);
+        postgresDelegationStore = new 
PostgresDelegationStore(postgresUsersDAO, any -> Mono.just(true));
+    }
+
+    @Override
+    public DelegationStore testee() {
+        return postgresDelegationStore;
+    }
+
+    @Override
+    public void addUser(Username username) {
+        postgresUsersDAO.addUser(username, "password");
+    }
+
+    @Test
+    void virtualUsersShouldNotBeListed() {
+        postgresDelegationStore = new 
PostgresDelegationStore(postgresUsersDAO, any -> Mono.just(false));
+        addUser(BOB);
+
+        Mono.from(testee().addAuthorizedUser(ALICE).forUser(BOB)).block();
+
+        assertThat(postgresUsersDAO.listReactive().collectList().block())
+            .containsOnly(BOB);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org
For additional commands, e-mail: notifications-h...@james.apache.org

Reply via email to