You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2023/05/26 10:30:49 UTC
[james-project] 04/07: JAMES-3909 PushDeleteUserDataTaskStep
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 08b5e1a8e800cdec8a443c2166651a2c5a04beb7
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri May 19 16:25:12 2023 +0700
JAMES-3909 PushDeleteUserDataTaskStep
---
.../CassandraPushSubscriptionDAO.java | 10 ++++
.../CassandraPushSubscriptionRepository.java | 5 ++
...sitory.java => PushDeleteUserDataTaskStep.java} | 37 +++++++------
.../PushSubscriptionRepository.java | 2 +
.../MemoryPushSubscriptionRepository.java | 5 ++
.../PushDeleteUserDataTaskStepTest.scala | 63 ++++++++++++++++++++++
.../PushSubscriptionRepositoryContract.scala | 23 ++++++++
7 files changed, 128 insertions(+), 17 deletions(-)
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionDAO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionDAO.java
index d3eb92afd7..2738600992 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionDAO.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionDAO.java
@@ -73,6 +73,7 @@ public class CassandraPushSubscriptionDAO {
private final PreparedStatement insert;
private final PreparedStatement selectAll;
private final PreparedStatement deleteOne;
+ private final PreparedStatement deleteAll;
@Inject
public CassandraPushSubscriptionDAO(CqlSession session, TypeStateFactory typeStateFactory) {
@@ -100,6 +101,10 @@ public class CassandraPushSubscriptionDAO {
.whereColumn(DEVICE_CLIENT_ID).isEqualTo(bindMarker(DEVICE_CLIENT_ID))
.build());
+ deleteAll = session.prepare(deleteFrom(TABLE_NAME)
+ .whereColumn(USER).isEqualTo(bindMarker(USER))
+ .build());
+
this.typeStateFactory = typeStateFactory;
}
@@ -138,6 +143,11 @@ public class CassandraPushSubscriptionDAO {
.setString(DEVICE_CLIENT_ID, deviceClientId));
}
+ public Mono<Void> deleteAll(Username username) {
+ return executor.executeVoid(deleteAll.bind()
+ .setString(USER, username.asString()));
+ }
+
private PushSubscription toPushSubscription(Row row) {
return PushSubscription.apply(
PushSubscriptionId.apply(row.getUuid(ID)),
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionRepository.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionRepository.java
index ab901e1b62..47dd50f047 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionRepository.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/pushsubscription/CassandraPushSubscriptionRepository.java
@@ -122,6 +122,11 @@ public class CassandraPushSubscriptionRepository implements PushSubscriptionRepo
.switchIfEmpty(Mono.empty());
}
+ @Override
+ public Publisher<Void> delete(Username username) {
+ return dao.deleteAll(username);
+ }
+
@Override
public Publisher<PushSubscription> get(Username username, Set<PushSubscriptionId> ids) {
return dao.selectAll(username)
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushDeleteUserDataTaskStep.java
similarity index 56%
copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java
copy to server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushDeleteUserDataTaskStep.java
index f8fa49f08f..21d06def90 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushDeleteUserDataTaskStep.java
@@ -19,29 +19,32 @@
package org.apache.james.jmap.api.pushsubscription;
-import java.time.ZonedDateTime;
-import java.util.Set;
+import javax.inject.Inject;
import org.apache.james.core.Username;
-import org.apache.james.jmap.api.model.PushSubscription;
-import org.apache.james.jmap.api.model.PushSubscriptionCreationRequest;
-import org.apache.james.jmap.api.model.PushSubscriptionExpiredTime;
-import org.apache.james.jmap.api.model.PushSubscriptionId;
-import org.apache.james.jmap.api.model.TypeName;
+import org.apache.james.user.api.DeleteUserDataTaskStep;
import org.reactivestreams.Publisher;
-public interface PushSubscriptionRepository {
- Publisher<PushSubscription> save(Username username, PushSubscriptionCreationRequest pushSubscriptionCreationRequest);
+public class PushDeleteUserDataTaskStep implements DeleteUserDataTaskStep {
+ private final PushSubscriptionRepository pushSubscriptionRepository;
- Publisher<PushSubscriptionExpiredTime> updateExpireTime(Username username, PushSubscriptionId id, ZonedDateTime newExpire);
+ @Inject
+ public PushDeleteUserDataTaskStep(PushSubscriptionRepository pushSubscriptionRepository) {
+ this.pushSubscriptionRepository = pushSubscriptionRepository;
+ }
- Publisher<Void> updateTypes(Username username, PushSubscriptionId id, Set<TypeName> types);
+ @Override
+ public StepName name() {
+ return new StepName("PushDeleteUserDataTaskStep");
+ }
- Publisher<Void> validateVerificationCode(Username username, PushSubscriptionId id);
+ @Override
+ public int priority() {
+ return 3;
+ }
- Publisher<Void> revoke(Username username, PushSubscriptionId id);
-
- Publisher<PushSubscription> get(Username username, Set<PushSubscriptionId> ids);
-
- Publisher<PushSubscription> list(Username username);
+ @Override
+ public Publisher<Void> deleteUserData(Username username) {
+ return pushSubscriptionRepository.delete(username);
+ }
}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java
index f8fa49f08f..f1766cc9e9 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepository.java
@@ -41,6 +41,8 @@ public interface PushSubscriptionRepository {
Publisher<Void> revoke(Username username, PushSubscriptionId id);
+ Publisher<Void> delete(Username username);
+
Publisher<PushSubscription> get(Username username, Set<PushSubscriptionId> ids);
Publisher<PushSubscription> list(Username username);
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/pushsubscription/MemoryPushSubscriptionRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/pushsubscription/MemoryPushSubscriptionRepository.java
index aff9a18454..c7cf16ac85 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/pushsubscription/MemoryPushSubscriptionRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/pushsubscription/MemoryPushSubscriptionRepository.java
@@ -117,6 +117,11 @@ public class MemoryPushSubscriptionRepository implements PushSubscriptionReposit
return Mono.fromCallable(() -> table.remove(username, id)).then();
}
+ @Override
+ public Publisher<Void> delete(Username username) {
+ return Mono.fromCallable(() -> table.rowMap().remove(username)).then();
+ }
+
@Override
public Publisher<PushSubscription> get(Username username, Set<PushSubscriptionId> ids) {
return Flux.fromStream(table.row(username).entrySet().stream())
diff --git a/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushDeleteUserDataTaskStepTest.scala b/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushDeleteUserDataTaskStepTest.scala
new file mode 100644
index 0000000000..e369becf43
--- /dev/null
+++ b/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushDeleteUserDataTaskStepTest.scala
@@ -0,0 +1,63 @@
+/** ****************************************************************
+ * 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.jmap.api.pushsubscription
+
+import java.net.URL
+import java.time.Clock
+
+import org.apache.james.jmap.api.identity.CustomIdentityDAOContract.bob
+import org.apache.james.jmap.api.model.{DeviceClientId, PushSubscriptionCreationRequest, PushSubscriptionServerURL}
+import org.apache.james.jmap.api.pushsubscription.PushSubscriptionRepositoryContract.ALICE
+import org.apache.james.jmap.memory.pushsubscription.MemoryPushSubscriptionRepository
+import org.assertj.core.api.Assertions.{assertThat, assertThatCode}
+import org.junit.jupiter.api.{BeforeEach, Test}
+import reactor.core.publisher.Flux
+import reactor.core.scala.publisher.SMono
+
+class PushDeleteUserDataTaskStepTest {
+ var pushSubscriptionRepository: PushSubscriptionRepository = _
+ var testee: PushDeleteUserDataTaskStep = _
+
+ @BeforeEach
+ def beforeEach(): Unit = {
+ pushSubscriptionRepository = new MemoryPushSubscriptionRepository(Clock.systemUTC())
+ testee = new PushDeleteUserDataTaskStep(pushSubscriptionRepository)
+ }
+
+ @Test
+ def shouldBeIdempotent(): Unit = {
+ assertThatCode(() => SMono(testee.deleteUserData(bob)).block())
+ .doesNotThrowAnyException()
+ }
+
+ @Test
+ def shouldDeleteUserData(): Unit = {
+ val validRequest = PushSubscriptionCreationRequest(
+ deviceClientId = DeviceClientId("1"),
+ url = PushSubscriptionServerURL(new URL("https://example.com/push")),
+ types = Seq(CustomTypeName1))
+ SMono.fromPublisher(pushSubscriptionRepository.save(ALICE, validRequest)).block().id
+
+ SMono(testee.deleteUserData(ALICE)).block()
+
+ assertThat(Flux.from(pushSubscriptionRepository.list(ALICE)).collectList().block())
+ .isEmpty()
+ }
+}
diff --git a/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepositoryContract.scala b/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepositoryContract.scala
index 0ff84ad8e7..209563d0e9 100644
--- a/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepositoryContract.scala
+++ b/server/data/data-jmap/src/test/scala/org/apache/james/jmap/api/pushsubscription/PushSubscriptionRepositoryContract.scala
@@ -247,6 +247,22 @@ trait PushSubscriptionRepositoryContract {
assertThat(remaining).isEmpty()
}
+ @Test
+ def deleteStoredSubscriptionShouldSucceed(): Unit = {
+ val validRequest = PushSubscriptionCreationRequest(
+ deviceClientId = DeviceClientId("1"),
+ url = PushSubscriptionServerURL(new URL("https://example.com/push")),
+ types = Seq(CustomTypeName1))
+ val pushSubscriptionId = SMono.fromPublisher(testee.save(ALICE, validRequest)).block().id
+ val singleRecordSaved = SFlux.fromPublisher(testee.get(ALICE, Set(pushSubscriptionId).asJava)).count().block()
+ assertThat(singleRecordSaved).isEqualTo(1)
+
+ SMono.fromPublisher(testee.delete(ALICE)).block()
+ val remaining = SFlux.fromPublisher(testee.get(ALICE, Set(pushSubscriptionId).asJava)).collectSeq().block().asJava
+
+ assertThat(remaining).isEmpty()
+ }
+
@Test
def revokeNotFoundShouldNotFail(): Unit = {
val pushSubscriptionId = PushSubscriptionId.generate()
@@ -254,6 +270,13 @@ trait PushSubscriptionRepositoryContract {
.doesNotThrowAnyException()
}
+ @Test
+ def deleteNotFoundShouldNotFail(): Unit = {
+ val pushSubscriptionId = PushSubscriptionId.generate()
+ assertThatCode(() => SMono.fromPublisher(testee.delete(ALICE)).block())
+ .doesNotThrowAnyException()
+ }
+
@Test
def getStoredSubscriptionShouldSucceed(): Unit = {
val deviceClientId1 = DeviceClientId("1")
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org