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 2023/02/22 02:47:55 UTC
[james-project] 01/03: JAMES-3885 Username change should adapt delegation
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 548011f49ec81a7df4590729bdae0646d1d27698
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Feb 20 15:57:42 2023 +0700
JAMES-3885 Username change should adapt delegation
---
.../data/CassandraUsersRepositoryModule.java | 5 ++
.../modules/data/MemoryUsersRepositoryModule.java | 7 ++
.../james/rrt/ForwardUsernameChangeTaskStep.java | 2 +-
.../user/api/DelegationUsernameChangeTaskStep.java | 66 ++++++++++++++++++
.../DelegationUsernameChangeTaskStepTest.java | 81 ++++++++++++++++++++++
.../MemoryUsernameChangeIntegrationTest.java | 21 ++++++
6 files changed, 181 insertions(+), 1 deletion(-)
diff --git a/server/container/guice/data-cassandra/src/main/java/org/apache/james/modules/data/CassandraUsersRepositoryModule.java b/server/container/guice/data-cassandra/src/main/java/org/apache/james/modules/data/CassandraUsersRepositoryModule.java
index 0f4b3f0906..5f4424f652 100644
--- a/server/container/guice/data-cassandra/src/main/java/org/apache/james/modules/data/CassandraUsersRepositoryModule.java
+++ b/server/container/guice/data-cassandra/src/main/java/org/apache/james/modules/data/CassandraUsersRepositoryModule.java
@@ -25,6 +25,8 @@ import org.apache.james.backends.cassandra.components.CassandraModule;
import org.apache.james.mailbox.Authorizator;
import org.apache.james.server.core.configuration.ConfigurationProvider;
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.api.UsersRepository;
import org.apache.james.user.cassandra.CassandraDelegationStore;
import org.apache.james.user.cassandra.CassandraRepositoryConfiguration;
@@ -53,6 +55,9 @@ public class CassandraUsersRepositoryModule extends AbstractModule {
cassandraDataDefinitions.addBinding().toInstance(org.apache.james.user.cassandra.CassandraUsersRepositoryModule.MODULE);
bind(DelegationStore.class).to(CassandraDelegationStore.class);
bind(Authorizator.class).to(DelegationStoreAuthorizator.class);
+
+ Multibinder.newSetBinder(binder(), UsernameChangeTaskStep.class)
+ .addBinding().to(DelegationUsernameChangeTaskStep.class);
}
@Provides
diff --git a/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryUsersRepositoryModule.java b/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryUsersRepositoryModule.java
index d80f1a30ff..9bf747823d 100644
--- a/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryUsersRepositoryModule.java
+++ b/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryUsersRepositoryModule.java
@@ -23,6 +23,8 @@ import org.apache.james.UserEntityValidator;
import org.apache.james.domainlist.api.DomainList;
import org.apache.james.server.core.configuration.ConfigurationProvider;
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.api.UsersRepository;
import org.apache.james.user.memory.MemoryDelegationStore;
import org.apache.james.user.memory.MemoryUsersRepository;
@@ -33,6 +35,7 @@ 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 MemoryUsersRepositoryModule extends AbstractModule {
@@ -41,6 +44,10 @@ public class MemoryUsersRepositoryModule extends AbstractModule {
bind(MemoryDelegationStore.class).in(Scopes.SINGLETON);
bind(UsersRepository.class).to(MemoryUsersRepository.class);
bind(DelegationStore.class).to(MemoryDelegationStore.class);
+
+
+ Multibinder.newSetBinder(binder(), UsernameChangeTaskStep.class)
+ .addBinding().to(DelegationUsernameChangeTaskStep.class);
}
@Provides
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/ForwardUsernameChangeTaskStep.java b/server/data/data-api/src/main/java/org/apache/james/rrt/ForwardUsernameChangeTaskStep.java
index 2319f24d09..86bc80c83b 100644
--- a/server/data/data-api/src/main/java/org/apache/james/rrt/ForwardUsernameChangeTaskStep.java
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/ForwardUsernameChangeTaskStep.java
@@ -81,6 +81,6 @@ public class ForwardUsernameChangeTaskStep implements UsernameChangeTaskStep {
@Override
public int priority() {
- return 10;
+ return 0;
}
}
diff --git a/server/data/data-api/src/main/java/org/apache/james/user/api/DelegationUsernameChangeTaskStep.java b/server/data/data-api/src/main/java/org/apache/james/user/api/DelegationUsernameChangeTaskStep.java
new file mode 100644
index 0000000000..5b2e32438a
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/user/api/DelegationUsernameChangeTaskStep.java
@@ -0,0 +1,66 @@
+/****************************************************************
+ * 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.api;
+
+import javax.inject.Inject;
+
+import org.apache.james.core.Username;
+import org.reactivestreams.Publisher;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class DelegationUsernameChangeTaskStep implements UsernameChangeTaskStep {
+ private final DelegationStore delegationStore;
+
+ @Inject
+ public DelegationUsernameChangeTaskStep(DelegationStore delegationStore) {
+ this.delegationStore = delegationStore;
+ }
+
+ @Override
+ public StepName name() {
+ return new StepName("DelegationUsernameChangeTaskStep");
+ }
+
+ @Override
+ public int priority() {
+ return 1;
+ }
+
+ @Override
+ public Publisher<Void> changeUsername(Username oldUsername, Username newUsername) {
+ return migrateDelegatees(oldUsername, newUsername)
+ .then(migrateDelegators(oldUsername, newUsername));
+ }
+
+ private Mono<Void> migrateDelegators(Username oldUsername, Username newUsername) {
+ return Flux.from(delegationStore.delegatedUsers(oldUsername))
+ .concatMap(delegator -> Mono.from(delegationStore.addAuthorizedUser(delegator, newUsername))
+ .then(Mono.from(delegationStore.removeAuthorizedUser(delegator, oldUsername))))
+ .then();
+ }
+
+ private Flux<Void> migrateDelegatees(Username oldUsername, Username newUsername) {
+ return Flux.from(delegationStore.authorizedUsers(oldUsername))
+ .concatMap(delegatee -> Mono.from(delegationStore.addAuthorizedUser(newUsername, delegatee))
+ .then(Mono.from(delegationStore.removeAuthorizedUser(oldUsername, delegatee))));
+ }
+}
diff --git a/server/data/data-memory/src/test/java/org/apache/james/user/memory/DelegationUsernameChangeTaskStepTest.java b/server/data/data-memory/src/test/java/org/apache/james/user/memory/DelegationUsernameChangeTaskStepTest.java
new file mode 100644
index 0000000000..1ba073e6d2
--- /dev/null
+++ b/server/data/data-memory/src/test/java/org/apache/james/user/memory/DelegationUsernameChangeTaskStepTest.java
@@ -0,0 +1,81 @@
+/****************************************************************
+ * 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.memory;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.Username;
+import org.apache.james.user.api.DelegationUsernameChangeTaskStep;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+class DelegationUsernameChangeTaskStepTest {
+ private static final Username ALICE_OLD = Username.of("alice-old@domain.tld");
+ private static final Username ALICE_NEW = Username.of("alice-new@domain.tld");
+ private static final Username BOB = Username.of("bob@domain.tld");
+
+ private MemoryDelegationStore delegationStore;
+ private DelegationUsernameChangeTaskStep testee;
+
+ @BeforeEach
+ void setUp() {
+ delegationStore = new MemoryDelegationStore();
+ testee = new DelegationUsernameChangeTaskStep(delegationStore);
+ }
+
+ @Test
+ void shouldMigrateDelegationToNewUser() {
+ Mono.from(delegationStore.addAuthorizedUser(BOB)
+ .forUser(ALICE_OLD))
+ .block();
+
+ Mono.from(testee.changeUsername(ALICE_OLD, ALICE_NEW)).block();
+
+ assertThat(Flux.from(delegationStore.authorizedUsers(ALICE_NEW)).collectList().block())
+ .containsOnly(BOB);
+ }
+
+ @Test
+ void shouldRemoveDelegationForOldUser() {
+ Mono.from(delegationStore.addAuthorizedUser(BOB)
+ .forUser(ALICE_OLD))
+ .block();
+
+ Mono.from(testee.changeUsername(ALICE_OLD, ALICE_NEW)).block();
+
+ assertThat(Flux.from(delegationStore.authorizedUsers(ALICE_OLD)).collectList().block())
+ .isEmpty();
+ }
+
+ @Test
+ void shouldMigrateChangesForDelegators() {
+ Mono.from(delegationStore.addAuthorizedUser(ALICE_OLD)
+ .forUser(BOB))
+ .block();
+
+ Mono.from(testee.changeUsername(ALICE_OLD, ALICE_NEW)).block();
+
+ assertThat(Flux.from(delegationStore.authorizedUsers(BOB)).collectList().block())
+ .containsOnly(ALICE_NEW);
+ }
+}
diff --git a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUsernameChangeIntegrationTest.java b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUsernameChangeIntegrationTest.java
index f4c8a91aef..a16b75b904 100644
--- a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUsernameChangeIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUsernameChangeIntegrationTest.java
@@ -105,4 +105,25 @@ class MemoryUsernameChangeIntegrationTest {
.body(".", hasSize(1))
.body("[0].mailAddress", is(BOB.asString()));
}
+
+ @Test
+ void shouldAdaptDelegation() {
+ webAdminApi.put("/users/" + ALICE.asString() + "/authorizedUsers/" + CEDRIC.asString());
+
+ String taskId = webAdminApi
+ .queryParam("action", "rename")
+ .post("/users/" + ALICE.asString() + "/rename/" + BOB.asString())
+ .jsonPath()
+ .get("taskId");
+
+ webAdminApi.get("/tasks/" + taskId + "/await");
+
+ webAdminApi.get("/users/" + ALICE.asString() + "/authorizedUsers")
+ .then()
+ .body(".", hasSize(0));
+ webAdminApi.get("/users/" + BOB.asString() + "/authorizedUsers")
+ .then()
+ .body(".", hasSize(1))
+ .body("[0]", is(CEDRIC.asString()));
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org