From 5dc96d32ad68a3fb8805cd2c7a54a0259f921dac Mon Sep 17 00:00:00 2001 From: HoussemNasri Date: Wed, 15 Jan 2025 14:11:58 +0100 Subject: [PATCH] Encapsulate Card/Cal dav server interactions into DavClient --- .../tmail/james/app/DistributedServer.java | 2 +- .../tmail/james/app/MemoryServer.java | 2 +- .../tmail-third-party/openpaas/pom.xml | 4 + .../com/linagora/tmail/OpenPaasModule.java | 11 +- .../linagora/tmail/carddav/CardDavClient.java | 110 ------------------ .../com/linagora/tmail/dav/DavClient.java | 34 ++++++ .../DavClientException.java} | 8 +- .../com/linagora/tmail/dav/DavClientImpl.java | 69 +++++++++++ .../tmail/dav/calendar/CalDavHandler.java | 33 ++++++ .../card}/CardDavCreationObjectRequest.java | 2 +- .../tmail/dav/card/CardDavHandler.java | 99 ++++++++++++++++ .../card/CardDavUtils.java} | 16 +-- .../tmail/mailet/CardDavCollectedContact.java | 18 +-- ...ardDavCollectedContactIntegrationTest.java | 22 ++-- .../CardDavCreationObjectRequestTest.java | 4 +- .../DavClientTest.java} | 18 +-- .../DavServerExtension.java} | 4 +- 17 files changed, 295 insertions(+), 161 deletions(-) delete mode 100644 tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClient.java create mode 100644 tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClient.java rename tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/{carddav/CardDavClientException.java => dav/DavClientException.java} (85%) create mode 100644 tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientImpl.java create mode 100644 tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/calendar/CalDavHandler.java rename tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/{carddav => dav/card}/CardDavCreationObjectRequest.java (98%) create mode 100644 tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavHandler.java rename tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/{carddav/CardDavCreationFactory.java => dav/card/CardDavUtils.java} (76%) rename tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/{carddav => dav}/CardDavCreationObjectRequestTest.java (96%) rename tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/{carddav/CardDavClientTest.java => dav/DavClientTest.java} (91%) rename tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/{carddav/CardDavServerExtension.java => dav/DavServerExtension.java} (98%) diff --git a/tmail-backend/apps/distributed/src/main/java/com/linagora/tmail/james/app/DistributedServer.java b/tmail-backend/apps/distributed/src/main/java/com/linagora/tmail/james/app/DistributedServer.java index aa83c76f39c..4741a9b0254 100644 --- a/tmail-backend/apps/distributed/src/main/java/com/linagora/tmail/james/app/DistributedServer.java +++ b/tmail-backend/apps/distributed/src/main/java/com/linagora/tmail/james/app/DistributedServer.java @@ -493,7 +493,7 @@ private static List chooseOpenPaasModule(OpenPaasModuleChooserConfigurat if (openPaasModuleChooserConfiguration.enabled()) { ImmutableList.Builder moduleBuilder = ImmutableList.builder().add(new OpenPaasModule()); if (openPaasModuleChooserConfiguration.cardDavCollectedContactEnabled()) { - moduleBuilder.add(new OpenPaasModule.CardDavModule()); + moduleBuilder.add(new OpenPaasModule.DavModule()); } if (openPaasModuleChooserConfiguration.contactsConsumerEnabled()) { moduleBuilder.add(new OpenPaasContactsConsumerModule()); diff --git a/tmail-backend/apps/memory/src/main/java/com/linagora/tmail/james/app/MemoryServer.java b/tmail-backend/apps/memory/src/main/java/com/linagora/tmail/james/app/MemoryServer.java index 127e83bc9f4..4a3181813a6 100644 --- a/tmail-backend/apps/memory/src/main/java/com/linagora/tmail/james/app/MemoryServer.java +++ b/tmail-backend/apps/memory/src/main/java/com/linagora/tmail/james/app/MemoryServer.java @@ -264,7 +264,7 @@ private static List chooseOpenPaas(OpenPaasModuleChooserConfiguration mo ImmutableList.Builder moduleBuilder = ImmutableList.builder().add(new OpenPaasModule()); if (moduleChooserConfiguration.cardDavCollectedContactEnabled()) { - moduleBuilder.add(new OpenPaasModule.CardDavModule()); + moduleBuilder.add(new OpenPaasModule.DavModule()); } if (moduleChooserConfiguration.contactsConsumerEnabled()) { moduleBuilder.add(Modules.override(new OpenPaasContactsConsumerModule()) diff --git a/tmail-backend/tmail-third-party/openpaas/pom.xml b/tmail-backend/tmail-third-party/openpaas/pom.xml index 9b6584fce8b..c145f5a4ab0 100644 --- a/tmail-backend/tmail-third-party/openpaas/pom.xml +++ b/tmail-backend/tmail-third-party/openpaas/pom.xml @@ -37,6 +37,10 @@ ${james.groupId} apache-james-backends-rabbitmq + + ${project.groupId} + jmap-extensions + ${james.groupId} apache-james-backends-rabbitmq diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/OpenPaasModule.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/OpenPaasModule.java index 347c6b522af..0aab8d847a9 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/OpenPaasModule.java +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/OpenPaasModule.java @@ -33,8 +33,9 @@ import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.linagora.tmail.api.OpenPaasRestClient; -import com.linagora.tmail.carddav.CardDavClient; import com.linagora.tmail.configuration.OpenPaasConfiguration; +import com.linagora.tmail.dav.DavClient; +import com.linagora.tmail.dav.DavClientImpl; public class OpenPaasModule extends AbstractModule { private static final Logger LOGGER = LoggerFactory.getLogger(OpenPaasModule.class); @@ -65,14 +66,14 @@ public OpenPaasRestClient provideOpenPaasRestCLient(OpenPaasConfiguration openPa return new OpenPaasRestClient(openPaasConfiguration); } - public static class CardDavModule extends AbstractModule { + public static class DavModule extends AbstractModule { @Provides @Singleton - public CardDavClient provideCardDavClient(OpenPaasConfiguration openPaasConfiguration) { + public DavClient provideDavClient(OpenPaasConfiguration openPaasConfiguration) { Preconditions.checkArgument(openPaasConfiguration.cardDavConfiguration().isPresent(), - "OpenPaasConfiguration should have a carddav configuration"); - return new CardDavClient.OpenpaasCardDavClient(openPaasConfiguration.cardDavConfiguration().get()); + "OpenPaasConfiguration should have dav configuration"); + return new DavClientImpl(openPaasConfiguration.cardDavConfiguration().get()); } } } diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClient.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClient.java deleted file mode 100644 index afb5ddc9ffe..00000000000 --- a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClient.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************** - * As a subpart of Twake Mail, this file is edited by Linagora. * - * * - * https://twake-mail.com/ * - * https://linagora.com * - * * - * This file is subject to The Affero Gnu Public License * - * version 3. * - * * - * https://www.gnu.org/licenses/agpl-3.0.en.html * - * * - * This program is distributed in the hope that it will be * - * useful, but WITHOUT ANY WARRANTY; without even the implied * - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * - * PURPOSE. See the GNU Affero General Public License for * - * more details. * - ********************************************************************/ - -package com.linagora.tmail.carddav; - -import java.time.Duration; -import java.util.function.Function; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; -import com.linagora.tmail.HttpUtils; -import com.linagora.tmail.configuration.CardDavConfiguration; - -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import reactor.core.publisher.Mono; -import reactor.netty.http.client.HttpClient; - -public interface CardDavClient { - - Mono existsCollectedContact(String username, String userId, String collectedId); - - Mono createCollectedContact(String username, String userId, CardDavCreationObjectRequest creationObjectRequest); - - class OpenpaasCardDavClient implements CardDavClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(OpenpaasCardDavClient.class); - private static final Duration RESPONSE_TIMEOUT_DEFAULT = Duration.ofSeconds(10); - private static final String COLLECTED_ADDRESS_BOOK_PATH = "/addressbooks/%s/collected/%s.vcf"; - - private final HttpClient client; - - private final Function adminCredentialWithDelegatedFunction; - - public OpenpaasCardDavClient(CardDavConfiguration cardDavConfiguration) { - this.client = HttpClient.create() - .baseUrl(cardDavConfiguration.baseUrl().toString()) - .headers(headers -> headers.add(HttpHeaderNames.ACCEPT, "application/vcard+json")) - .responseTimeout(cardDavConfiguration.responseTimeout().orElse(RESPONSE_TIMEOUT_DEFAULT)); - - cardDavConfiguration.trustAllSslCerts().ifPresent(trustAllSslCerts -> - client.secure(sslContextSpec -> sslContextSpec.sslContext( - SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)))); - - this.adminCredentialWithDelegatedFunction = openPaasUsername -> new UsernamePasswordCredentials(cardDavConfiguration.adminCredential().getUserName() + "&" + openPaasUsername, - cardDavConfiguration.adminCredential().getPassword()); - } - - @Override - public Mono existsCollectedContact(String username, String userId, String collectedId) { - Preconditions.checkArgument(StringUtils.isNotEmpty(userId), "OpenPaas user id should not be empty"); - Preconditions.checkArgument(StringUtils.isNotEmpty(collectedId), "Collected id should not be empty"); - - return client - .headers(headers -> headers.add(HttpHeaderNames.AUTHORIZATION, HttpUtils.createBasicAuthenticationToken(adminCredentialWithDelegatedFunction.apply(username)))) - .get() - .uri(String.format(COLLECTED_ADDRESS_BOOK_PATH, userId, collectedId)) - .responseSingle((response, byteBufMono) -> switch (response.status().code()) { - case 200 -> Mono.just(true); - case 404 -> Mono.just(false); - default -> - Mono.error(new CardDavClientException("Unexpected status code: " + response.status().code() - + " when checking contact exists for openPaasUserId: " + userId + " and collectedId: " + collectedId)); - }); - } - - @Override - public Mono createCollectedContact(String username, String userId, CardDavCreationObjectRequest creationObjectRequest) { - return client - .headers(headers -> { - headers.add(HttpHeaderNames.CONTENT_TYPE, "text/vcard"); - headers.add(HttpHeaderNames.AUTHORIZATION, HttpUtils.createBasicAuthenticationToken(adminCredentialWithDelegatedFunction.apply(username))); - }) - .put() - .uri(String.format(COLLECTED_ADDRESS_BOOK_PATH, userId, creationObjectRequest.uid())) - .send(Mono.just(Unpooled.wrappedBuffer(creationObjectRequest.toVCard().getBytes()))) - .responseSingle((response, byteBufMono) -> switch (response.status().code()) { - case 201 -> Mono.empty(); - case 204 -> { - LOGGER.info("Contact for user {} and collected id {} already exists", userId, creationObjectRequest.uid()); - yield Mono.empty(); - } - default -> - Mono.error(new CardDavClientException("Unexpected status code: " + response.status().code() - + " when creating contact for user: " + userId + " and collected id: " + creationObjectRequest.uid())); - }); - } - } -} diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClient.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClient.java new file mode 100644 index 00000000000..1bea40e4004 --- /dev/null +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClient.java @@ -0,0 +1,34 @@ +/******************************************************************** + * As a subpart of Twake Mail, this file is edited by Linagora. * + * * + * https://twake-mail.com/ * + * https://linagora.com * + * * + * This file is subject to The Affero Gnu Public License * + * version 3. * + * * + * https://www.gnu.org/licenses/agpl-3.0.en.html * + * * + * This program is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * + * PURPOSE. See the GNU Affero General Public License for * + * more details. * + ********************************************************************/ + +package com.linagora.tmail.dav; + +import com.linagora.tmail.dav.card.CardDavCreationObjectRequest; + +import net.fortuna.ical4j.model.parameter.PartStat; +import reactor.core.publisher.Mono; + +public interface DavClient { + Mono existsCollectedContact(String username, String userId, String collectedId); + + Mono createCollectedContact(String username, String userId, CardDavCreationObjectRequest creationObjectRequest); + + Mono getUserParticipationStatus(String userId, String eventUuid); + + Mono setUserParticipationStatus(String userId, String eventUuid, PartStat partStat); +} diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClientException.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientException.java similarity index 85% rename from tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClientException.java rename to tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientException.java index a1c6c425a5f..1107ff641ee 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavClientException.java +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientException.java @@ -16,15 +16,15 @@ * more details. * ********************************************************************/ -package com.linagora.tmail.carddav; +package com.linagora.tmail.dav; -public class CardDavClientException extends RuntimeException { +public class DavClientException extends RuntimeException { - public CardDavClientException(String message) { + public DavClientException(String message) { super(message); } - public CardDavClientException(String message, Throwable cause) { + public DavClientException(String message, Throwable cause) { super(message, cause); } } diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientImpl.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientImpl.java new file mode 100644 index 00000000000..155fa302da2 --- /dev/null +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/DavClientImpl.java @@ -0,0 +1,69 @@ +/******************************************************************** + * As a subpart of Twake Mail, this file is edited by Linagora. * + * * + * https://twake-mail.com/ * + * https://linagora.com * + * * + * This file is subject to The Affero Gnu Public License * + * version 3. * + * * + * https://www.gnu.org/licenses/agpl-3.0.en.html * + * * + * This program is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * + * PURPOSE. See the GNU Affero General Public License for * + * more details. * + ********************************************************************/ + +package com.linagora.tmail.dav; + +import java.time.Duration; + +import com.linagora.tmail.configuration.CardDavConfiguration; +import com.linagora.tmail.dav.calendar.CalDavHandler; +import com.linagora.tmail.dav.card.CardDavCreationObjectRequest; +import com.linagora.tmail.dav.card.CardDavHandler; + +import net.fortuna.ical4j.model.parameter.PartStat; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; + +public class DavClientImpl implements DavClient { + private static final Duration RESPONSE_TIMEOUT_DEFAULT = Duration.ofSeconds(10); + + private final CardDavHandler cardDavHandler; + private final CalDavHandler calDavHandler; + + public DavClientImpl(CardDavConfiguration cardDavConfiguration) { + HttpClient client = HttpClient.create() + .baseUrl(cardDavConfiguration.baseUrl().toString()) + .responseTimeout(cardDavConfiguration.responseTimeout().orElse(RESPONSE_TIMEOUT_DEFAULT)); + + this.cardDavHandler = new CardDavHandler(cardDavConfiguration, client); + this.calDavHandler = new CalDavHandler(); + } + + @Override + public Mono existsCollectedContact(String username, String userId, + String collectedId) { + return cardDavHandler.existsCollectedContact(username, userId, collectedId); + } + + @Override + public Mono createCollectedContact(String username, String userId, + CardDavCreationObjectRequest creationObjectRequest) { + return cardDavHandler.createCollectedContact(username, userId, creationObjectRequest); + } + + @Override + public Mono getUserParticipationStatus(String userId, String eventUuid) { + return calDavHandler.getUserParticipationStatus(userId, eventUuid); + } + + @Override + public Mono setUserParticipationStatus(String userId, String eventUuid, + PartStat partStat) { + return calDavHandler.setUserParticipationStatus(userId, eventUuid, partStat); + } +} diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/calendar/CalDavHandler.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/calendar/CalDavHandler.java new file mode 100644 index 00000000000..a09dc3c7672 --- /dev/null +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/calendar/CalDavHandler.java @@ -0,0 +1,33 @@ +/******************************************************************** + * As a subpart of Twake Mail, this file is edited by Linagora. * + * * + * https://twake-mail.com/ * + * https://linagora.com * + * * + * This file is subject to The Affero Gnu Public License * + * version 3. * + * * + * https://www.gnu.org/licenses/agpl-3.0.en.html * + * * + * This program is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * + * PURPOSE. See the GNU Affero General Public License for * + * more details. * + ********************************************************************/ + +package com.linagora.tmail.dav.calendar; + +import net.fortuna.ical4j.model.parameter.PartStat; +import reactor.core.publisher.Mono; + +public class CalDavHandler { + + public Mono getUserParticipationStatus(String userId, String eventUuid) { + return null; + } + + public Mono setUserParticipationStatus(String userId, String eventUuid, PartStat partStat) { + return null; + } +} diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavCreationObjectRequest.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavCreationObjectRequest.java similarity index 98% rename from tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavCreationObjectRequest.java rename to tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavCreationObjectRequest.java index fb541cc4ea3..99b63916ebe 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavCreationObjectRequest.java +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavCreationObjectRequest.java @@ -16,7 +16,7 @@ * more details. * ********************************************************************/ -package com.linagora.tmail.carddav; +package com.linagora.tmail.dav.card; import java.util.List; import java.util.Optional; diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavHandler.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavHandler.java new file mode 100644 index 00000000000..1715d1139d2 --- /dev/null +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavHandler.java @@ -0,0 +1,99 @@ +/******************************************************************** + * As a subpart of Twake Mail, this file is edited by Linagora. * + * * + * https://twake-mail.com/ * + * https://linagora.com * + * * + * This file is subject to The Affero Gnu Public License * + * version 3. * + * * + * https://www.gnu.org/licenses/agpl-3.0.en.html * + * * + * This program is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * + * PURPOSE. See the GNU Affero General Public License for * + * more details. * + ********************************************************************/ + +package com.linagora.tmail.dav.card; + +import java.util.function.Function; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.linagora.tmail.HttpUtils; +import com.linagora.tmail.configuration.CardDavConfiguration; +import com.linagora.tmail.dav.DavClientException; + +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; + +public class CardDavHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(CardDavHandler.class); + private static final String COLLECTED_ADDRESS_BOOK_PATH = "/addressbooks/%s/collected/%s.vcf"; + + private final HttpClient client; + + private final Function + adminCredentialWithDelegatedFunction; + + public CardDavHandler(CardDavConfiguration cardDavConfiguration, HttpClient davHttpClient) { + this.client = davHttpClient + .headers(headers -> headers.add(HttpHeaderNames.ACCEPT, "application/vcard+json")); + + cardDavConfiguration.trustAllSslCerts().ifPresent(trustAllSslCerts -> + client.secure(sslContextSpec -> sslContextSpec.sslContext( + SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)))); + + this.adminCredentialWithDelegatedFunction = openPaasUsername -> new UsernamePasswordCredentials(cardDavConfiguration.adminCredential().getUserName() + "&" + openPaasUsername, + cardDavConfiguration.adminCredential().getPassword()); + } + + public Mono existsCollectedContact(String username, String userId, String collectedId) { + Preconditions.checkArgument(StringUtils.isNotEmpty(userId), "OpenPaas user id should not be empty"); + Preconditions.checkArgument(StringUtils.isNotEmpty(collectedId), "Collected id should not be empty"); + + return client + .headers(headers -> headers.add(HttpHeaderNames.AUTHORIZATION, HttpUtils.createBasicAuthenticationToken(adminCredentialWithDelegatedFunction.apply(username)))) + .get() + .uri(String.format(COLLECTED_ADDRESS_BOOK_PATH, userId, collectedId)) + .responseSingle((response, byteBufMono) -> switch (response.status().code()) { + case 200 -> Mono.just(true); + case 404 -> Mono.just(false); + default -> + Mono.error(new DavClientException("Unexpected status code: " + response.status().code() + + " when checking contact exists for openPaasUserId: " + userId + " and collectedId: " + collectedId)); + }); + } + + public Mono createCollectedContact(String username, String userId, CardDavCreationObjectRequest creationObjectRequest) { + return client + .headers(headers -> { + headers.add(HttpHeaderNames.CONTENT_TYPE, "text/vcard"); + headers.add(HttpHeaderNames.AUTHORIZATION, HttpUtils.createBasicAuthenticationToken(adminCredentialWithDelegatedFunction.apply(username))); + }) + .put() + .uri(String.format(COLLECTED_ADDRESS_BOOK_PATH, userId, creationObjectRequest.uid())) + .send(Mono.just(Unpooled.wrappedBuffer(creationObjectRequest.toVCard().getBytes()))) + .responseSingle((response, byteBufMono) -> switch (response.status().code()) { + case 201 -> Mono.empty(); + case 204 -> { + LOGGER.info("Contact for user {} and collected id {} already exists", userId, creationObjectRequest.uid()); + yield Mono.empty(); + } + default -> + Mono.error(new DavClientException("Unexpected status code: " + response.status().code() + + " when creating contact for user: " + userId + " and collected id: " + creationObjectRequest.uid())); + }); + } + +} diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavCreationFactory.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavUtils.java similarity index 76% rename from tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavCreationFactory.java rename to tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavUtils.java index 8727208eee5..17a30826de7 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/carddav/CardDavCreationFactory.java +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/dav/card/CardDavUtils.java @@ -16,7 +16,7 @@ * more details. * ********************************************************************/ -package com.linagora.tmail.carddav; +package com.linagora.tmail.dav.card; import java.nio.charset.StandardCharsets; import java.util.List; @@ -28,17 +28,17 @@ import ezvcard.parameter.EmailType; -public class CardDavCreationFactory { +public class CardDavUtils { private static final String VERSION = "4.0"; - private static final EmailType EMAIL_TYPE_DEFAULT = EmailType.WORK; + private static final EmailType DEFAULT_EMAIL_TYPE = EmailType.WORK; - public static CardDavCreationObjectRequest create(Optional fullName, MailAddress email) { - CardDavCreationObjectRequest.Email emailObject = new CardDavCreationObjectRequest.Email(List.of(EMAIL_TYPE_DEFAULT), email); - return new CardDavCreationObjectRequest(VERSION, createContactUid(email), fullName, Optional.empty(), emailObject); + public static CardDavCreationObjectRequest createObjectCreationRequest(Optional maybeFullName, MailAddress email) { + CardDavCreationObjectRequest.Email emailObject = new CardDavCreationObjectRequest.Email(List.of(DEFAULT_EMAIL_TYPE), email); + return new CardDavCreationObjectRequest(VERSION, createContactUid(email), maybeFullName, Optional.empty(), emailObject); } - public static CardDavCreationObjectRequest create(MailAddress email) { - return create(Optional.empty(), email); + public static CardDavCreationObjectRequest createObjectCreationRequest(MailAddress email) { + return createObjectCreationRequest(Optional.empty(), email); } public static String createContactUid(MailAddress email) { diff --git a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/mailet/CardDavCollectedContact.java b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/mailet/CardDavCollectedContact.java index 09ca3f0b51b..65168c29eb4 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/mailet/CardDavCollectedContact.java +++ b/tmail-backend/tmail-third-party/openpaas/src/main/java/com/linagora/tmail/mailet/CardDavCollectedContact.java @@ -32,9 +32,9 @@ import com.google.common.collect.ImmutableList; import com.linagora.tmail.api.OpenPaasRestClient; -import com.linagora.tmail.carddav.CardDavClient; -import com.linagora.tmail.carddav.CardDavCreationFactory; -import com.linagora.tmail.carddav.CardDavCreationObjectRequest; +import com.linagora.tmail.dav.DavClient; +import com.linagora.tmail.dav.card.CardDavCreationObjectRequest; +import com.linagora.tmail.dav.card.CardDavUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -46,12 +46,12 @@ public class CardDavCollectedContact extends GenericMailet { private static final Logger LOGGER = LoggerFactory.getLogger(CardDavCollectedContact.class); private final OpenPaasRestClient openPaasRestClient; - private final CardDavClient cardDavClient; + private final DavClient davClient; @Inject - public CardDavCollectedContact(OpenPaasRestClient openPaasRestClient, CardDavClient cardDavClient) { + public CardDavCollectedContact(OpenPaasRestClient openPaasRestClient, DavClient davClient) { this.openPaasRestClient = openPaasRestClient; - this.cardDavClient = cardDavClient; + this.davClient = davClient; } @Override @@ -66,15 +66,15 @@ public void service(Mail mail) throws MessagingException { private Mono collectedContactProcess(MailAddress sender, List recipients) { return openPaasRestClient.searchOpenPaasUserId(sender.asString()) .flatMapMany(openPassUserId -> Flux.fromIterable(recipients) - .map(CardDavCreationFactory::create) + .map(CardDavUtils::createObjectCreationRequest) .flatMap(cardDavCreationObjectRequest -> createCollectedContactIfNotExists(sender, openPassUserId, cardDavCreationObjectRequest))) .then(); } private Mono createCollectedContactIfNotExists(MailAddress sender, String openPassUserId, CardDavCreationObjectRequest cardDavCreationObjectRequest) { - return cardDavClient.existsCollectedContact(sender.asString(), openPassUserId, cardDavCreationObjectRequest.uid()) + return davClient.existsCollectedContact(sender.asString(), openPassUserId, cardDavCreationObjectRequest.uid()) .filter(FunctionalUtils.identityPredicate().negate()) - .flatMap(exists -> cardDavClient.createCollectedContact(sender.asString(), openPassUserId, cardDavCreationObjectRequest)) + .flatMap(exists -> davClient.createCollectedContact(sender.asString(), openPassUserId, cardDavCreationObjectRequest)) .onErrorResume(error -> { LOGGER.error("Error while creating collected contact if not exists.", error); return Mono.empty(); diff --git a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/CardDavCollectedContactIntegrationTest.java b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/CardDavCollectedContactIntegrationTest.java index e91f1aabb64..04d0b050275 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/CardDavCollectedContactIntegrationTest.java +++ b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/CardDavCollectedContactIntegrationTest.java @@ -58,8 +58,8 @@ import com.google.inject.Provides; import com.google.inject.util.Modules; import com.linagora.tmail.api.OpenPaasServerExtension; -import com.linagora.tmail.carddav.CardDavCreationFactory; -import com.linagora.tmail.carddav.CardDavServerExtension; +import com.linagora.tmail.dav.card.CardDavUtils; +import com.linagora.tmail.dav.DavServerExtension; import com.linagora.tmail.configuration.OpenPaasConfiguration; import com.linagora.tmail.james.jmap.contact.InMemoryEmailAddressContactSearchEngineModule; import com.linagora.tmail.mailet.CardDavCollectedContact; @@ -75,7 +75,7 @@ public class CardDavCollectedContactIntegrationTest { static OpenPaasServerExtension openPaasServerExtension = new OpenPaasServerExtension(); @RegisterExtension - static CardDavServerExtension cardDavServerExtension = new CardDavServerExtension(); + static DavServerExtension cardDavServerExtension = new DavServerExtension(); private TemporaryJamesServer jamesServer; @@ -94,7 +94,7 @@ void setup(@TempDir File temporaryFolder) throws Exception { .withOverrides(new AbstractModule() { @Override protected void configure() { - install(new OpenPaasModule.CardDavModule()); + install(new OpenPaasModule.DavModule()); } @Provides @@ -133,7 +133,7 @@ void tearDown() { @Test void shouldPUTCreateCollectedContactWhenContactDoesNotExist() throws Exception { // Setup mock server - String contactUid = CardDavCreationFactory.createContactUid(BOB.asMailAddress()); + String contactUid = CardDavUtils.createContactUid(BOB.asMailAddress()); String openPassUid = UUID.randomUUID().toString(); openPaasServerExtension.setSearchEmailExist(ALICE.asString(), openPassUid); // Contact does not exist @@ -150,7 +150,7 @@ void shouldPUTCreateCollectedContactWhenContactDoesNotExist() throws Exception { @Test void shouldNotPUTCreateCollectedContactWhenContactExists() throws Exception { // Setup mock server - String contactUid = CardDavCreationFactory.createContactUid(BOB.asMailAddress()); + String contactUid = CardDavUtils.createContactUid(BOB.asMailAddress()); String openPassUid = UUID.randomUUID().toString(); openPaasServerExtension.setSearchEmailExist(ALICE.asString(), openPassUid); // Contact exists @@ -167,7 +167,7 @@ void shouldNotPUTCreateCollectedContactWhenContactExists() throws Exception { @Test void shouldNotPUTCreateCollectedContactWhenSearchEmailDoesNotExist() throws Exception { // Setup mock server - String contactUid = CardDavCreationFactory.createContactUid(BOB.asMailAddress()); + String contactUid = CardDavUtils.createContactUid(BOB.asMailAddress()); String openPassUid = UUID.randomUUID().toString(); openPaasServerExtension.setSearchEmailNotFound(ALICE.asString()); cardDavServerExtension.setCollectedContactExists(ALICE_OPENPAAS_USER_NAME, openPassUid, contactUid, !COLLECTED_CONTACT_EXISTS); @@ -183,8 +183,8 @@ void shouldNotPUTCreateCollectedContactWhenSearchEmailDoesNotExist() throws Exce @Test void shouldPUTCreateCollectedContactMultipleTimesWhenMultipleRecipients() throws Exception { // Setup mock server - String bobContactUid = CardDavCreationFactory.createContactUid(BOB.asMailAddress()); - String cedricContactUid = CardDavCreationFactory.createContactUid(CEDRIC.asMailAddress()); + String bobContactUid = CardDavUtils.createContactUid(BOB.asMailAddress()); + String cedricContactUid = CardDavUtils.createContactUid(CEDRIC.asMailAddress()); String aliceOpenPassId = UUID.randomUUID().toString(); openPaasServerExtension.setSearchEmailExist(ALICE.asString(), aliceOpenPassId); cardDavServerExtension.setCollectedContactExists(ALICE_OPENPAAS_USER_NAME, aliceOpenPassId, bobContactUid, !COLLECTED_CONTACT_EXISTS); @@ -224,8 +224,8 @@ void shouldPUTCreateCollectedContactMultipleTimesWhenMultipleRecipients() throws @Test void shouldPUTCreateCollectedContactForContactDoesNotExistWhenMultipleRecipients() throws Exception { // Setup mock server - String bobContactUid = CardDavCreationFactory.createContactUid(BOB.asMailAddress()); - String cedricContactUid = CardDavCreationFactory.createContactUid(CEDRIC.asMailAddress()); + String bobContactUid = CardDavUtils.createContactUid(BOB.asMailAddress()); + String cedricContactUid = CardDavUtils.createContactUid(CEDRIC.asMailAddress()); String aliceOpenPassId = UUID.randomUUID().toString(); openPaasServerExtension.setSearchEmailExist(ALICE.asString(), aliceOpenPassId); cardDavServerExtension.setCollectedContactExists(ALICE_OPENPAAS_USER_NAME, aliceOpenPassId, bobContactUid, COLLECTED_CONTACT_EXISTS); diff --git a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavCreationObjectRequestTest.java b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/CardDavCreationObjectRequestTest.java similarity index 96% rename from tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavCreationObjectRequestTest.java rename to tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/CardDavCreationObjectRequestTest.java index a87dbce0320..1b8cbe95432 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavCreationObjectRequestTest.java +++ b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/CardDavCreationObjectRequestTest.java @@ -16,7 +16,7 @@ * more details. * ********************************************************************/ -package com.linagora.tmail.carddav; +package com.linagora.tmail.dav; import static org.assertj.core.api.Assertions.assertThat; @@ -28,6 +28,8 @@ import ezvcard.parameter.EmailType; +import com.linagora.tmail.dav.card.CardDavCreationObjectRequest; + public class CardDavCreationObjectRequestTest { @Test diff --git a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavClientTest.java b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/DavClientTest.java similarity index 91% rename from tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavClientTest.java rename to tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/DavClientTest.java index 0bc5ce09de5..309d988bcc9 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavClientTest.java +++ b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/DavClientTest.java @@ -16,9 +16,9 @@ * more details. * ********************************************************************/ -package com.linagora.tmail.carddav; +package com.linagora.tmail.dav; -import static com.linagora.tmail.carddav.CardDavServerExtension.CARD_DAV_ADMIN_WITH_DELEGATED_AUTHORIZATION; +import static com.linagora.tmail.dav.DavServerExtension.CARD_DAV_ADMIN_WITH_DELEGATED_AUTHORIZATION; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; @@ -38,18 +38,20 @@ import ezvcard.parameter.EmailType; -public class CardDavClientTest { +import com.linagora.tmail.dav.card.CardDavCreationObjectRequest; + +public class DavClientTest { private static final String OPENPAAS_USER_NAME = "openpaasUserName1"; private static final String OPENPAAS_USER_ID = "openpaasUserId1"; @RegisterExtension - static CardDavServerExtension cardDavServerExtension = new CardDavServerExtension(); + static DavServerExtension cardDavServerExtension = new DavServerExtension(); - private CardDavClient client; + private DavClient client; @BeforeEach void setup() { - client = new CardDavClient.OpenpaasCardDavClient(cardDavServerExtension.getCardDavConfiguration()); + client = new DavClientImpl(cardDavServerExtension.getCardDavConfiguration()); } @Test @@ -79,7 +81,7 @@ void existsCollectedContactShouldReturnFalseWhenHTTPResponseIs500(ClientAndServe .withStatusCode(500)); assertThatThrownBy(() -> client.existsCollectedContact(OPENPAAS_USER_NAME, OPENPAAS_USER_ID, collectedContactUid).block()) - .isInstanceOf(CardDavClientException.class); + .isInstanceOf(DavClientException.class); } @Test @@ -120,6 +122,6 @@ void createCollectedContactShouldThrowWhenHTTPResponseIs404(ClientAndServer mock new MailAddress("anbach4@lina.com"))); assertThatThrownBy(() -> client.createCollectedContact(OPENPAAS_USER_NAME, OPENPAAS_USER_ID, request).block()) - .isInstanceOf(CardDavClientException.class); + .isInstanceOf(DavClientException.class); } } diff --git a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavServerExtension.java b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/DavServerExtension.java similarity index 98% rename from tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavServerExtension.java rename to tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/DavServerExtension.java index 69209e0fe33..c9d710dc1d1 100644 --- a/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/carddav/CardDavServerExtension.java +++ b/tmail-backend/tmail-third-party/openpaas/src/test/java/com/linagora/tmail/dav/DavServerExtension.java @@ -16,7 +16,7 @@ * more details. * ********************************************************************/ -package com.linagora.tmail.carddav; +package com.linagora.tmail.dav; import static org.mockserver.model.NottableString.string; @@ -42,7 +42,7 @@ import com.linagora.tmail.HttpUtils; import com.linagora.tmail.configuration.CardDavConfiguration; -public class CardDavServerExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver { +public class DavServerExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver { public static final String CARD_DAV_ADMIN = "admin"; public static final String CARD_DAV_ADMIN_PASSWORD = "secret123";