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 2422d3ef92a6c74e9da233039613d38fd833e632
Author: duc91 <duc91....@gmail.com>
AuthorDate: Wed Feb 5 17:19:32 2020 +0700

    JAMES-3040: change behavior of uploadDocument directly to userTargetSpace
---
 CHANGELOG.md                                       |   1 +
 .../destination/conf/blob.properties               |   9 +-
 .../destination/conf/blob.properties               |   9 +-
 .../destination/conf/blob.properties               |   9 +-
 .../cassandra/destination/conf/blob.properties     |   9 +-
 .../james/modules/LinshareGuiceExtension.java      |  34 +++-
 ...LinshareBlobExportMechanismIntegrationTest.java |   4 +-
 ...LinshareBlobExportMechanismIntegrationTest.java |   5 +-
 ...LinshareBlobExportMechanismIntegrationTest.java |  98 ++----------
 .../james/webadmin/vault/routes/ExportService.java |   2 +-
 .../linshare/LinshareBlobExportMechanism.java      |  22 ++-
 .../james/linshare/LinshareConfiguration.java      |  60 ++++---
 .../apache/james/linshare/client/LinshareAPI.java  |  60 ++-----
 .../linshare/LinshareBlobExportMechanismTest.java  |  64 ++------
 .../james/linshare/LinshareConfigurationTest.java  |  92 +++++++++--
 .../apache/james/linshare/LinshareExtension.java   | 167 +++++++++++++------
 .../org/apache/james/linshare/LinshareTest.java    |   4 +-
 .../james/linshare/client/LinshareAPITest.java     | 176 +++++----------------
 .../client/TechnicalAccountCreationRequest.java    |   1 -
 upgrade-instructions.md                            |  21 +++
 20 files changed, 402 insertions(+), 445 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 205ce27..9ad4ae1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ of tasks being currently executed.
 - Unhealthy health checks now return HTTP 503 instead of 500, degraded now 
returns 200 instead of 500. See JAMES-2576.
 - In order to fasten JMAP-draft message retrieval upon calls on properties 
expected to be fast to fetch, we now compute the preview and hasAttachment 
properties asynchronously and persist them in Cassandra to improve performance. 
See JAMES-2919.
 - It is now forbidden to create new Usernames with the following set of 
characters in its local part : `"(),:; <>@\[]`, as we prefer it to stay simple 
to handle. However, the read of Usernames already existing with some of those 
characters is still allowed, to not introduce any breaking change. See 
JAMES-2950.
+- Linshare blob export configuration and mechanism change. See JAMES-3040.
 
 ### Fixed
 - JAMES-2828 & JAMES-2929 bugs affecting JDBCMailRepository usage with 
PostgresSQL thanks to Jörg Thomas & Sergey B
diff --git 
a/dockerfiles/run/guice/cassandra-ldap/destination/conf/blob.properties 
b/dockerfiles/run/guice/cassandra-ldap/destination/conf/blob.properties
index 4600510..90c5135 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/blob.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/blob.properties
@@ -18,6 +18,9 @@ blob.export.localFile.directory=file://var/blobExporting
 # Mandatory if you choose LinShare, url to connect to LinShare service
 # blob.export.linshare.url=http://linshare:8080
 
-# Mandatory if you choose LinShare, access token to connect to LinShare 
service. It will be formalized to `Bearer` + a space + access token
-# So, no need to pass (`Bearer` + <space>) prefix
-# blob.export.linshare.token=LinShare-Access-Token-In-String
\ No newline at end of file
+# ======================================= LinShare Configuration 
BasicAuthentication ===================================
+# Authentication is mandatory if you choose LinShare, TechnicalAccount is need 
to connect to LinShare specific service.
+# For Example: It will be formalized to 'Authorization: Basic {Credential of 
UUID/password}'
+
+# blob.export.linshare.technical.account.uuid=Technical_Account_UUID
+# blob.export.linshare.technical.account.password=password
\ No newline at end of file
diff --git 
a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/blob.properties
 
b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/blob.properties
index ea41c7f..d7509a5 100644
--- 
a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/blob.properties
+++ 
b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/blob.properties
@@ -131,6 +131,9 @@ blob.export.localFile.directory=file://var/blobExporting
 # Mandatory if you choose LinShare, url to connect to LinShare service
 # blob.export.linshare.url=http://linshare:8080
 
-# Mandatory if you choose LinShare, access token to connect to LinShare 
service. It will be formalized to `Bearer` + a space + access token
-# So, no need to pass (`Bearer` + <space>) prefix
-# blob.export.linshare.token=LinShare-Access-Token-In-String
+# ======================================= LinShare Configuration 
BasicAuthentication ===================================
+# Authentication is mandatory if you choose LinShare, TechnicalAccount is need 
to connect to LinShare specific service.
+# For Example: It will be formalized to 'Authorization: Basic {Credential of 
UUID/password}'
+
+# blob.export.linshare.technical.account.uuid=Technical_Account_UUID
+# blob.export.linshare.technical.account.password=password
diff --git 
a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/blob.properties 
b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/blob.properties
index ea41c7f..d7509a5 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/blob.properties
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/blob.properties
@@ -131,6 +131,9 @@ blob.export.localFile.directory=file://var/blobExporting
 # Mandatory if you choose LinShare, url to connect to LinShare service
 # blob.export.linshare.url=http://linshare:8080
 
-# Mandatory if you choose LinShare, access token to connect to LinShare 
service. It will be formalized to `Bearer` + a space + access token
-# So, no need to pass (`Bearer` + <space>) prefix
-# blob.export.linshare.token=LinShare-Access-Token-In-String
+# ======================================= LinShare Configuration 
BasicAuthentication ===================================
+# Authentication is mandatory if you choose LinShare, TechnicalAccount is need 
to connect to LinShare specific service.
+# For Example: It will be formalized to 'Authorization: Basic {Credential of 
UUID/password}'
+
+# blob.export.linshare.technical.account.uuid=Technical_Account_UUID
+# blob.export.linshare.technical.account.password=password
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/blob.properties 
b/dockerfiles/run/guice/cassandra/destination/conf/blob.properties
index 4600510..90c5135 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/blob.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/blob.properties
@@ -18,6 +18,9 @@ blob.export.localFile.directory=file://var/blobExporting
 # Mandatory if you choose LinShare, url to connect to LinShare service
 # blob.export.linshare.url=http://linshare:8080
 
-# Mandatory if you choose LinShare, access token to connect to LinShare 
service. It will be formalized to `Bearer` + a space + access token
-# So, no need to pass (`Bearer` + <space>) prefix
-# blob.export.linshare.token=LinShare-Access-Token-In-String
\ No newline at end of file
+# ======================================= LinShare Configuration 
BasicAuthentication ===================================
+# Authentication is mandatory if you choose LinShare, TechnicalAccount is need 
to connect to LinShare specific service.
+# For Example: It will be formalized to 'Authorization: Basic {Credential of 
UUID/password}'
+
+# blob.export.linshare.technical.account.uuid=Technical_Account_UUID
+# blob.export.linshare.technical.account.password=password
\ No newline at end of file
diff --git 
a/server/container/guice/blob-export-guice/src/test/java/org/apache/james/modules/LinshareGuiceExtension.java
 
b/server/container/guice/blob-export-guice/src/test/java/org/apache/james/modules/LinshareGuiceExtension.java
index 856e0fb..8a21402 100644
--- 
a/server/container/guice/blob-export-guice/src/test/java/org/apache/james/modules/LinshareGuiceExtension.java
+++ 
b/server/container/guice/blob-export-guice/src/test/java/org/apache/james/modules/LinshareGuiceExtension.java
@@ -24,11 +24,15 @@ import org.apache.james.linshare.LinshareConfiguration;
 import org.apache.james.linshare.LinshareExtension;
 import org.apache.james.linshare.LinshareFixture;
 import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
 
 import com.google.inject.Module;
 import com.google.inject.util.Modules;
 
-public class LinshareGuiceExtension implements GuiceModuleTestExtension {
+public class LinshareGuiceExtension implements GuiceModuleTestExtension, 
ParameterResolver {
+
     private final LinshareExtension linshareExtension;
 
     public LinshareGuiceExtension() {
@@ -36,14 +40,18 @@ public class LinshareGuiceExtension implements 
GuiceModuleTestExtension {
     }
 
     @Override
-    public void beforeEach(ExtensionContext extensionContext) throws Exception 
{
+    public void beforeAll(ExtensionContext extensionContext) {
+        linshareExtension.beforeAll(extensionContext);
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext extensionContext) {
         linshareExtension.beforeEach(extensionContext);
     }
 
     @Override
-    public void afterAll(ExtensionContext extensionContext) throws Exception {
-        linshareExtension.getLinshare()
-            .stop();
+    public void afterAll(ExtensionContext extensionContext) {
+        linshareExtension.getLinshare().stop();
     }
 
     @Override
@@ -54,7 +62,11 @@ public class LinshareGuiceExtension implements 
GuiceModuleTestExtension {
             binder -> {
                 try {
                     binder.bind(LinshareConfiguration.class)
-                        
.toInstance(linshareExtension.configurationWithJwtFor(LinshareFixture.USER_1));
+                        
.toInstance(linshareExtension.configurationWithBasicAuthFor(
+                            new LinshareFixture.Credential(
+                                
linshareExtension.getTechnicalAccountUUID().toString(),
+                                
LinshareFixture.TECHNICAL_ACCOUNT.getPassword()))
+                        );
                 } catch (Exception e) {
                     throw new RuntimeException(e);
                 }
@@ -62,7 +74,13 @@ public class LinshareGuiceExtension implements 
GuiceModuleTestExtension {
         );
     }
 
-    public LinshareExtension getLinshareJunitExtension() {
-        return linshareExtension;
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext) throws ParameterResolutionException {
+        return linshareExtension.supportsParameter(parameterContext, 
extensionContext);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext) throws ParameterResolutionException {
+        return linshareExtension.resolveParameter(parameterContext, 
extensionContext);
     }
 }
diff --git 
a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
 
b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
index e7fd6db..75b8d77 100644
--- 
a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
+++ 
b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/vault/RabbitMQLinshareBlobExportMechanismIntegrationTest.java
@@ -31,6 +31,7 @@ import 
org.apache.james.backends.rabbitmq.DockerRabbitMQSingleton;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.mailbox.store.search.PDFTextExtractor;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
+import org.apache.james.modules.LinshareGuiceExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.TestRabbitMQModule;
@@ -40,14 +41,13 @@ import 
org.apache.james.webadmin.integration.vault.LinshareBlobExportMechanismIn
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class RabbitMQLinshareBlobExportMechanismIntegrationTest extends 
LinshareBlobExportMechanismIntegrationTest {
-
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder()
         .extension(new DockerElasticSearchExtension())
         .extension(new CassandraExtension())
         .extension(new RabbitMQExtension())
         .extension(new AwsS3BlobStoreExtension())
-        
.extension(LinshareBlobExportMechanismIntegrationTest.linshareGuiceExtension)
+        .extension(new LinshareGuiceExtension())
         .server(configuration -> 
GuiceJamesServer.forConfiguration(configuration)
             .combineWith(CassandraRabbitMQJamesServerMain.MODULES)
             .overrideWith(binder -> 
binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
diff --git 
a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/vault/MemoryLinshareBlobExportMechanismIntegrationTest.java
 
b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/vault/MemoryLinshareBlobExportMechanismIntegrationTest.java
index b6961e5..090944b 100644
--- 
a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/vault/MemoryLinshareBlobExportMechanismIntegrationTest.java
+++ 
b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/vault/MemoryLinshareBlobExportMechanismIntegrationTest.java
@@ -31,12 +31,9 @@ import 
org.apache.james.webadmin.integration.vault.LinshareBlobExportMechanismIn
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class MemoryLinshareBlobExportMechanismIntegrationTest extends 
LinshareBlobExportMechanismIntegrationTest {
-
-    private static final LinshareGuiceExtension linshareGuiceExtension = new 
LinshareGuiceExtension();
-
     @RegisterExtension
     static JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-        .extension(linshareGuiceExtension)
+        .extension(new LinshareGuiceExtension())
         .server(configuration -> 
GuiceJamesServer.forConfiguration(configuration)
             
.combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
             .overrideWith(TestJMAPServerModule.limitToTenMessages())
diff --git 
a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/LinshareBlobExportMechanismIntegrationTest.java
 
b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/LinshareBlobExportMechanismIntegrationTest.java
index c55f60c..2fa6fec 100644
--- 
a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/LinshareBlobExportMechanismIntegrationTest.java
+++ 
b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/LinshareBlobExportMechanismIntegrationTest.java
@@ -19,7 +19,6 @@
 
 package org.apache.james.webadmin.integration.vault;
 
-import static io.restassured.RestAssured.given;
 import static io.restassured.RestAssured.with;
 import static 
org.apache.james.jmap.HttpJmapAuthentication.authenticateJamesUser;
 import static org.apache.james.jmap.JMAPTestingConstants.ARGUMENTS;
@@ -31,14 +30,13 @@ import static 
org.apache.james.jmap.JmapCommonRequests.deleteMessages;
 import static org.apache.james.jmap.JmapCommonRequests.getOutboxId;
 import static 
org.apache.james.jmap.JmapCommonRequests.listMessageIdsForAccount;
 import static org.apache.james.jmap.LocalHostURIBuilder.baseUri;
+import static 
org.apache.james.linshare.LinshareExtension.LinshareAPIForTechnicalAccountTesting;
+import static 
org.apache.james.linshare.LinshareExtension.LinshareAPIForUserTesting;
 import static org.apache.james.linshare.LinshareFixture.MATCH_ALL_QUERY;
 import static org.apache.james.linshare.LinshareFixture.USER_1;
 import static org.apache.james.mailbox.backup.ZipAssert.assertThatZip;
 import static 
org.apache.james.webadmin.integration.vault.DeletedMessagesVaultRequests.exportVaultContent;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.hasItem;
-import static org.hamcrest.Matchers.hasSize;
 
 import java.io.ByteArrayInputStream;
 import java.util.List;
@@ -48,12 +46,10 @@ import org.apache.james.core.Username;
 import org.apache.james.jmap.AccessToken;
 import org.apache.james.jmap.draft.JmapGuiceProbe;
 import org.apache.james.linshare.client.Document;
-import org.apache.james.linshare.client.LinshareAPI;
 import org.apache.james.mailbox.DefaultMailboxes;
 import org.apache.james.mailbox.backup.ZipAssert;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.probe.MailboxProbe;
-import org.apache.james.modules.LinshareGuiceExtension;
 import org.apache.james.modules.MailboxProbeImpl;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.util.Port;
@@ -84,8 +80,6 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
         .exportTo(USER_1.getUsername())
         .query(MATCH_ALL_QUERY);
 
-    protected static final LinshareGuiceExtension linshareGuiceExtension = new 
LinshareGuiceExtension();
-
     @RegisterExtension
     IMAPMessageReader imapMessageReader = new IMAPMessageReader();
 
@@ -93,8 +87,7 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
     private AccessToken bartAccessToken;
     private GuiceJamesServer jmapServer;
     private RequestSpecification webAdminApi;
-    private RequestSpecification fakeSmtpRequestSpecification;
-    private LinshareAPI user1LinshareAPI;
+    private LinshareAPIForUserTesting user1LinshareAPI;
 
     @BeforeEach
     void setup(GuiceJamesServer jmapServer) throws Throwable {
@@ -119,10 +112,8 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
 
         homerAccessToken = authenticateJamesUser(baseUri(jmapPort), 
Username.of(HOMER), HOMER_PASSWORD);
         bartAccessToken = authenticateJamesUser(baseUri(jmapPort), 
Username.of(BART), BART_PASSWORD);
-        user1LinshareAPI = 
linshareGuiceExtension.getLinshareJunitExtension().getAPIFor(USER_1);
 
-        fakeSmtpRequestSpecification = 
given(linshareGuiceExtension.getLinshareJunitExtension()
-            .getLinshare().fakeSmtpRequestSpecification());
+        user1LinshareAPI = LinshareAPIForUserTesting.from(USER_1);
     }
 
     @Test
@@ -136,10 +127,9 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
 
         exportVaultContent(webAdminApi, EXPORT_ALL_HOMER_MESSAGES_TO_USER_1);
 
-        assertThat(user1LinshareAPI.receivedShares())
+        assertThat(user1LinshareAPI.listAllDocuments())
             .hasSize(1)
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getDocument().getName()).endsWith(".zip"))
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getSender().getMail()).isEqualTo(USER_1.getUsername()));
+            .allSatisfy(uploadedDoc -> 
assertThat(uploadedDoc.getName()).endsWith(".zip"));
     }
 
     @Test
@@ -158,67 +148,13 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
 
         exportVaultContent(webAdminApi, EXPORT_ALL_HOMER_MESSAGES_TO_USER_1);
 
-        assertThat(user1LinshareAPI.receivedShares())
+        assertThat(user1LinshareAPI.listAllDocuments())
             .hasSize(1)
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getDocument().getName()).endsWith(".zip"))
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getSender().getMail()).isEqualTo(USER_1.getUsername()));
-    }
-
-    @Test
-    void exportShouldSendAnEmailToShareeWhenJmapDelete() {
-        bartSendMessageToHomer();
-
-        WAIT_TEN_SECONDS.until(() -> 
listMessageIdsForAccount(homerAccessToken).size() == 1);
-
-        homerDeletesMessages(listMessageIdsForAccount(homerAccessToken));
-        WAIT_TEN_SECONDS.until(() -> 
listMessageIdsForAccount(homerAccessToken).isEmpty());
-
-        exportVaultContent(webAdminApi, EXPORT_ALL_HOMER_MESSAGES_TO_USER_1);
-
-        WAIT_TEN_SECONDS.untilAsserted(
-            () -> fakeSmtpRequestSpecification
-                .get("/api/email")
-            .then()
-                .body("", hasSize(2)));
-
-        fakeSmtpRequestSpecification
-            .get("/api/email")
-        .then()
-            .body("[1].subject", containsString("John Doe has shared a file 
with you"))
-            .body("[1].to", hasItem(USER_1.getUsername()));
-    }
-
-    @Test
-    void exportShouldSendAnEmailToShareeWhenImapDelete() throws Exception {
-        bartSendMessageToHomer();
-
-        WAIT_TEN_SECONDS.until(() -> 
listMessageIdsForAccount(homerAccessToken).size() == 1);
-
-        imapMessageReader.connect(LOCALHOST_IP, 
jmapServer.getProbe(ImapGuiceProbe.class).getImapPort())
-            .login(HOMER, HOMER_PASSWORD)
-            .select(IMAPMessageReader.INBOX)
-            .setFlagsForAllMessagesInMailbox("\\Deleted");
-        imapMessageReader.expunge();
-
-        WAIT_TEN_SECONDS.until(() -> 
listMessageIdsForAccount(homerAccessToken).isEmpty());
-
-        exportVaultContent(webAdminApi, EXPORT_ALL_HOMER_MESSAGES_TO_USER_1);
-
-        WAIT_TEN_SECONDS.untilAsserted(
-            () -> fakeSmtpRequestSpecification
-                .get("/api/email")
-            .then()
-                .body("", hasSize(2)));
-
-        fakeSmtpRequestSpecification
-            .get("/api/email")
-        .then()
-            .body("[1].subject", containsString("John Doe has shared a file 
with you"))
-            .body("[1].to", hasItem(USER_1.getUsername()));
+            .allSatisfy(uploadedDoc -> 
assertThat(uploadedDoc.getName()).endsWith(".zip"));
     }
 
     @Test
-    void exportShouldShareNonEmptyZipViaLinshareWhenJmapDelete() throws 
Exception {
+    void 
exportShouldShareNonEmptyZipViaLinshareWhenJmapDelete(LinshareAPIForTechnicalAccountTesting
 linshareAPIForTechnicalAccountTesting) throws Exception {
         bartSendMessageToHomer();
 
         WAIT_TEN_SECONDS.until(() -> 
listMessageIdsForAccount(homerAccessToken).size() == 1);
@@ -228,9 +164,9 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
 
         exportVaultContent(webAdminApi, EXPORT_ALL_HOMER_MESSAGES_TO_USER_1);
 
-        Document sharedDoc = 
user1LinshareAPI.receivedShares().get(0).getDocument();
-        byte[] sharedFile =  linshareGuiceExtension.getLinshareJunitExtension()
-            .downloadSharedFile(USER_1, sharedDoc.getId(), 
sharedDoc.getName());
+        Document sharedDoc = user1LinshareAPI.listAllDocuments().get(0);
+        byte[] sharedFile = linshareAPIForTechnicalAccountTesting
+            .downloadFileFrom(USER_1, sharedDoc.getId());
 
         try (ZipAssert zipAssert = assertThatZip(new 
ByteArrayInputStream(sharedFile))) {
             zipAssert.hasEntriesSize(1);
@@ -238,7 +174,7 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
     }
 
     @Test
-    void exportShouldShareNonEmptyZipViaLinshareWhenImapDelete() throws 
Exception {
+    void 
exportShouldShareNonEmptyZipViaLinshareWhenImapDelete(LinshareAPIForTechnicalAccountTesting
 linshareAPIForTechnicalAccountTesting) throws Exception {
         bartSendMessageToHomer();
 
         WAIT_TEN_SECONDS.until(() -> 
listMessageIdsForAccount(homerAccessToken).size() == 1);
@@ -253,9 +189,9 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
 
         exportVaultContent(webAdminApi, EXPORT_ALL_HOMER_MESSAGES_TO_USER_1);
 
-        Document sharedDoc = 
user1LinshareAPI.receivedShares().get(0).getDocument();
-        byte[] sharedFile =  linshareGuiceExtension.getLinshareJunitExtension()
-            .downloadSharedFile(USER_1, sharedDoc.getId(), 
sharedDoc.getName());
+        Document sharedDoc = user1LinshareAPI.listAllDocuments().get(0);
+        byte[] sharedFile = linshareAPIForTechnicalAccountTesting
+            .downloadFileFrom(USER_1, sharedDoc.getId());
 
         try (ZipAssert zipAssert = assertThatZip(new 
ByteArrayInputStream(sharedFile))) {
             zipAssert.hasEntriesSize(1);
@@ -270,7 +206,7 @@ public abstract class 
LinshareBlobExportMechanismIntegrationTest {
             "  [" +
             "    \"setMessages\"," +
             "    {" +
-            "      \"create\": { \"" + messageCreationId  + "\" : {" +
+            "      \"create\": { \"" + messageCreationId + "\" : {" +
             "        \"from\": { \"name\": \"user2\", \"email\": \"" + BART + 
"\"}," +
             "        \"to\": [{ \"name\": \"user1\", \"email\": \"" + HOMER + 
"\"}]," +
             "        \"subject\": \"" + SUBJECT + "\"," +
diff --git 
a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/ExportService.java
 
b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/ExportService.java
index 34d55f1..f3ca133 100644
--- 
a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/ExportService.java
+++ 
b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/ExportService.java
@@ -78,7 +78,7 @@ class ExportService {
         blobExport.blobId(blobId)
             .with(exportToAddress)
             .explanation(exportMessage(username))
-            .filePrefix(Optional.of("deleted-message-of-" + 
username.asString() + "_"))
+            .filePrefix(Optional.of(String.format("deleted-message-of-%s_", 
username.asString())))
             .fileExtension(FileExtension.ZIP)
             .export();
     }
diff --git 
a/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareBlobExportMechanism.java
 
b/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareBlobExportMechanism.java
index f01c301..92c280a 100644
--- 
a/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareBlobExportMechanism.java
+++ 
b/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareBlobExportMechanism.java
@@ -32,9 +32,8 @@ import org.apache.james.blob.export.api.BlobExportMechanism;
 import org.apache.james.blob.export.api.ExportedFileNamesGenerator;
 import org.apache.james.blob.export.api.FileExtension;
 import org.apache.james.core.MailAddress;
-import org.apache.james.linshare.client.Document;
 import org.apache.james.linshare.client.LinshareAPI;
-import org.apache.james.linshare.client.ShareRequest;
+import org.apache.james.linshare.client.User;
 
 import com.google.common.io.Files;
 
@@ -55,31 +54,28 @@ public class LinshareBlobExportMechanism implements 
BlobExportMechanism {
     public ShareeStage blobId(BlobId blobId) {
         return mailAddress -> explanation -> fileCustomPrefix -> fileExtension 
-> () ->  {
             try {
-                exportBlob(blobId, mailAddress, fileCustomPrefix, 
fileExtension, explanation);
+                exportBlob(blobId, mailAddress, fileCustomPrefix, 
fileExtension);
             } catch (Exception e) {
-                throw new BlobExportException("Error while exporting blob " + 
blobId.asString() + " to " + mailAddress.asString(), e);
+                throw new BlobExportException(String.format("Error while 
exporting blob %s to %s", blobId.asString(),
+                    mailAddress.asString()), e);
             }
         };
     }
 
     private void exportBlob(BlobId blobId, MailAddress mailAddress, 
Optional<String> fileCustomPrefix,
-                            Optional<FileExtension> fileExtension, String 
explanation) throws IOException {
+                            Optional<FileExtension> fileExtension) throws 
IOException {
         String fileName = 
ExportedFileNamesGenerator.generateFileName(fileCustomPrefix, blobId, 
fileExtension);
         File tempFile = new File(tempDir, fileName);
         try {
             
FileUtils.copyInputStreamToFile(blobStore.read(blobStore.getDefaultBucketName(),
 blobId), tempFile);
-            uploadAndShare(mailAddress, tempFile, explanation);
+            uploadDocumentToTargetMail(mailAddress, tempFile);
         } finally {
             FileUtils.forceDelete(tempFile);
         }
     }
 
-    private void uploadAndShare(MailAddress mailAddress, File tempFile, String 
explanation) {
-        Document document = linshareAPI.uploadDocument(tempFile);
-        linshareAPI.share(ShareRequest.builder()
-            .message(explanation)
-            .addDocumentId(document.getId())
-            .addRecipient(mailAddress)
-            .build());
+    private void uploadDocumentToTargetMail(MailAddress mailAddress, File 
tempFile) {
+        User targetUser = linshareAPI.getUserByMail(mailAddress.asString());
+        linshareAPI.uploadDocumentByDelegation(targetUser, tempFile);
     }
 }
diff --git 
a/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareConfiguration.java
 
b/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareConfiguration.java
index a619284..44f3add 100644
--- 
a/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareConfiguration.java
+++ 
b/third-party/linshare/src/main/java/org/apache/james/linshare/LinshareConfiguration.java
@@ -22,6 +22,7 @@ package org.apache.james.linshare;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Objects;
+import java.util.UUID;
 
 import org.apache.commons.configuration2.Configuration;
 
@@ -30,67 +31,81 @@ import com.google.common.base.Preconditions;
 
 public class LinshareConfiguration {
 
-    public static final String URL = "blob.export.linshare.url";
-    public static final String TOKEN = "blob.export.linshare.token";
+    public static final String URL_PROPERTY = "blob.export.linshare.url";
+    public static final String UUID_PROPERTY = 
"blob.export.linshare.technical.account.uuid";
+    public static final String PASSWORD_PROPERTY = 
"blob.export.linshare.technical.account.password";
 
     public static class Builder {
         @FunctionalInterface
         public interface RequireUrl {
-            RequireAuthorizationToken url(URL url);
+            RequireBasicAuthorization url(URL url);
 
-            default RequireAuthorizationToken urlAsString(String url) throws 
MalformedURLException {
+            default RequireBasicAuthorization urlAsString(String url) throws 
MalformedURLException {
                 return url(new URL(url));
             }
         }
 
-        public interface RequireAuthorizationToken {
-            ReadyToBuild authorizationToken(AuthorizationToken token);
+        public interface RequireBasicAuthorization {
+            ReadyToBuild basicAuthorization(String uuid, String password);
         }
 
         public static class ReadyToBuild {
             private final URL url;
-            private final AuthorizationToken token;
+            private final UUID uuid;
+            private final String password;
 
-            ReadyToBuild(URL url, AuthorizationToken token) {
+            ReadyToBuild(URL url, UUID uuid, String password) {
                 this.url = url;
-                this.token = token;
+                this.uuid = uuid;
+                this.password = password;
             }
 
             public LinshareConfiguration build() {
-                return new LinshareConfiguration(url, token);
+                return new LinshareConfiguration(url, uuid, password);
             }
         }
     }
 
     public static Builder.RequireUrl builder() {
-        return url -> credential -> new Builder.ReadyToBuild(url, credential);
+        return url -> (uuid, password) -> new Builder.ReadyToBuild(url, 
UUID.fromString(uuid), password);
     }
 
     public static LinshareConfiguration from(Configuration configuration) 
throws MalformedURLException {
         return builder()
-            .urlAsString(configuration.getString(URL, null))
-            .authorizationToken(new 
AuthorizationToken(configuration.getString(TOKEN, null)))
+            .urlAsString(configuration.getString(URL_PROPERTY, null))
+            .basicAuthorization(
+                configuration.getString(UUID_PROPERTY),
+                configuration.getString(PASSWORD_PROPERTY))
             .build();
     }
 
     private final URL url;
-    private final AuthorizationToken token;
+    private final UUID uuid;
+    private final String password;
 
     @VisibleForTesting
-    LinshareConfiguration(URL url, AuthorizationToken token) {
-        Preconditions.checkNotNull(url, "'" + URL + "' can not be null");
-        Preconditions.checkNotNull(token, "'" + TOKEN + "' can not be null");
+    LinshareConfiguration(URL url, UUID uuid, String password) {
+        Preconditions.checkNotNull(url, "'%s' can not be null", URL_PROPERTY);
+        Preconditions.checkNotNull(uuid, "'%s' can not be null", 
UUID_PROPERTY);
+
+        Preconditions.checkNotNull(password, "'%s' can not be null", 
PASSWORD_PROPERTY);
+        Preconditions.checkArgument(!password.isEmpty(), "'%s' can not be 
empty", PASSWORD_PROPERTY);
 
         this.url = url;
-        this.token = token;
+        this.uuid = uuid;
+        this.password = password;
     }
 
     public URL getUrl() {
         return url;
     }
 
-    public AuthorizationToken getToken() {
-        return token;
+    public UUID getUuid() {
+        return uuid;
+    }
+
+    public String getPassword() {
+        return password;
     }
 
     @Override
@@ -99,13 +114,14 @@ public class LinshareConfiguration {
             LinshareConfiguration that = (LinshareConfiguration) o;
 
             return Objects.equals(this.url, that.url)
-                && Objects.equals(this.token, that.token);
+                && Objects.equals(this.uuid, that.uuid)
+                && Objects.equals(this.password, that.password);
         }
         return false;
     }
 
     @Override
     public final int hashCode() {
-        return Objects.hash(url, token);
+        return Objects.hash(url, uuid, password);
     }
 }
diff --git 
a/third-party/linshare/src/main/java/org/apache/james/linshare/client/LinshareAPI.java
 
b/third-party/linshare/src/main/java/org/apache/james/linshare/client/LinshareAPI.java
index 7c1a3d2..9d7b1bd 100644
--- 
a/third-party/linshare/src/main/java/org/apache/james/linshare/client/LinshareAPI.java
+++ 
b/third-party/linshare/src/main/java/org/apache/james/linshare/client/LinshareAPI.java
@@ -24,9 +24,7 @@ import static 
org.apache.james.linshare.client.LinshareAPI.Headers.CONTENT_TYPE_
 import static 
org.apache.james.linshare.client.LinshareAPI.Headers.CONTENT_TYPE_MULTIPART;
 
 import java.io.File;
-import java.util.List;
 
-import org.apache.james.linshare.AuthorizationToken;
 import org.apache.james.linshare.LinshareConfiguration;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -35,9 +33,8 @@ import com.google.common.base.Preconditions;
 import feign.Feign;
 import feign.Logger;
 import feign.Param;
-import feign.RequestInterceptor;
 import feign.RequestLine;
-import feign.RequestTemplate;
+import feign.auth.BasicAuthRequestInterceptor;
 import feign.form.FormEncoder;
 import feign.jackson.JacksonDecoder;
 import feign.jackson.JacksonEncoder;
@@ -51,24 +48,13 @@ public interface LinshareAPI {
         String CONTENT_TYPE_APPLICATION_JSON = "Content-Type: 
application/json";
     }
 
-    class AuthorizationInterceptor implements RequestInterceptor {
-
-        private final AuthorizationToken authorizationToken;
-
-        AuthorizationInterceptor(AuthorizationToken authorizationToken) {
-            this.authorizationToken = authorizationToken;
-        }
-
-        @Override
-        public void apply(RequestTemplate template) {
-            template.header("Authorization", 
authorizationToken.asBearerHeader());
-        }
-    }
-
     @VisibleForTesting
     static LinshareAPI from(LinshareConfiguration configuration) {
         return Feign.builder()
-            .requestInterceptor(new 
AuthorizationInterceptor(configuration.getToken()))
+            .requestInterceptor(
+                new BasicAuthRequestInterceptor(
+                    configuration.getUuid().toString(),
+                    configuration.getPassword()))
             .logger(new Slf4jLogger(LinshareAPI.class))
             .logLevel(Logger.Level.FULL)
             .encoder(new FormEncoder(new JacksonEncoder()))
@@ -76,40 +62,18 @@ public interface LinshareAPI {
             .target(LinshareAPI.class, configuration.getUrl().toString());
     }
 
-    @RequestLine("GET /linshare/webservice/rest/user/v2/documents")
-    @feign.Headers(ACCEPT_APPLICATION_JSON)
-    List<Document> listAllDocuments();
+    @RequestLine("GET 
/linshare/webservice/rest/delegation/v2/users/{targetUserMail}")
+    @feign.Headers({ ACCEPT_APPLICATION_JSON, CONTENT_TYPE_APPLICATION_JSON })
+    User getUserByMail(@Param("targetUserMail") String mail);
 
-    @RequestLine("POST /linshare/webservice/rest/user/v2/documents")
+    @RequestLine("POST 
linshare/webservice/rest/delegation/v2/{userUuid}/documents")
     @feign.Headers({ ACCEPT_APPLICATION_JSON, CONTENT_TYPE_MULTIPART })
-    Document uploadDocument(@Param("file") File file, @Param("filesize") long 
fileSize);
+    Document uploadDocumentByDelegation(@Param("userUuid") String userUuid, 
@Param("file") File file, @Param("filesize") long fileSize);
 
-    default Document uploadDocument(File file) {
+    default Document uploadDocumentByDelegation(User targetUser, File file) {
         Preconditions.checkNotNull(file);
         Preconditions.checkArgument(file.exists(), "File to upload does not 
exist: %s", file.getAbsolutePath());
 
-        return uploadDocument(file, file.length());
+        return uploadDocumentByDelegation(targetUser.getUuid(), file, 
file.length());
     }
-
-    @RequestLine("POST /linshare/webservice/rest/user/v2/shares")
-    @feign.Headers({ ACCEPT_APPLICATION_JSON, CONTENT_TYPE_APPLICATION_JSON })
-    List<ShareResult> share(ShareRequest request);
-
-    @RequestLine("DELETE 
/linshare/webservice/rest/user/v2/documents/{documentId}")
-    @feign.Headers({ ACCEPT_APPLICATION_JSON, CONTENT_TYPE_APPLICATION_JSON })
-    Document delete(@Param("documentId") String documentId);
-
-    default Document delete(Document.DocumentId documentId) {
-        return delete(documentId.asString());
-    }
-
-    @VisibleForTesting
-    default void deleteAllDocuments() {
-        listAllDocuments()
-            .forEach(document -> delete(document.getId()));
-    }
-
-    @RequestLine("GET /linshare/webservice/rest/user/v2/received_shares")
-    @feign.Headers({ ACCEPT_APPLICATION_JSON, CONTENT_TYPE_APPLICATION_JSON })
-    List<ReceivedShare> receivedShares();
 }
diff --git 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
index 2988281..736707c 100644
--- 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
+++ 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
@@ -19,15 +19,12 @@
 
 package org.apache.james.linshare;
 
-import static io.restassured.RestAssured.given;
 import static org.apache.james.blob.api.BlobStore.StoragePolicy.LOW_COST;
-import static org.apache.james.linshare.LinshareFixture.USER_1;
+import static 
org.apache.james.linshare.LinshareExtension.LinshareAPIForTechnicalAccountTesting;
+import static 
org.apache.james.linshare.LinshareExtension.LinshareAPIForUserTesting;
 import static org.apache.james.linshare.LinshareFixture.USER_2;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.hasItem;
-import static org.hamcrest.Matchers.hasSize;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Optional;
@@ -40,15 +37,10 @@ import org.apache.james.blob.memory.MemoryBlobStore;
 import org.apache.james.blob.memory.MemoryDumbBlobStore;
 import org.apache.james.core.MailAddress;
 import org.apache.james.linshare.client.Document;
-import org.apache.james.linshare.client.LinshareAPI;
-import org.awaitility.Awaitility;
-import org.awaitility.Duration;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-import io.restassured.specification.RequestSpecification;
-
 class LinshareBlobExportMechanismTest {
     private static final String FILE_CONTENT = "content";
     private static final String EXPLANATION = "Explanation about the file 
being shared";
@@ -60,7 +52,7 @@ class LinshareBlobExportMechanismTest {
     private MemoryBlobStore blobStore;
     private LinshareBlobExportMechanism testee;
     private HashBlobId.Factory blobIdFactory;
-    private LinshareAPI user2API;
+    private LinshareAPIForUserTesting user2API;
 
     @BeforeEach
     void setUp() throws Exception {
@@ -68,14 +60,14 @@ class LinshareBlobExportMechanismTest {
         blobStore = new MemoryBlobStore(blobIdFactory, new 
MemoryDumbBlobStore());
 
         testee = new LinshareBlobExportMechanism(
-            linshareExtension.getAPIFor(USER_1),
+            linshareExtension.getDelegationAccountAPI(),
             blobStore);
 
-        user2API = linshareExtension.getAPIFor(USER_2);
+        user2API = LinshareAPIForUserTesting.from(USER_2);
     }
 
     @Test
-    void exportShouldShareTheDocumentViaLinshare() throws Exception {
+    void exportShouldUploadTheDocumentToTargetUserViaLinshare() throws 
Exception {
         BlobId blobId = blobStore.save(blobStore.getDefaultBucketName(), 
FILE_CONTENT, LOW_COST).block();
         String filePrefix = "deleted-message-of-...@james.org-";
 
@@ -86,44 +78,14 @@ class LinshareBlobExportMechanismTest {
             .fileExtension(FILE_TEXT_EXTENSION)
             .export();
 
-        assertThat(user2API.receivedShares())
+        assertThat(user2API.listAllDocuments())
             .hasSize(1)
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getDocument().getName()).endsWith(".txt"))
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getDocument().getName()).startsWith(filePrefix))
-            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getSender().getMail()).isEqualTo(USER_1.getUsername()));
-    }
-
-    @Test
-    void exportShouldSendAnEmailToSharee() throws Exception {
-        BlobId blobId = blobStore.save(blobStore.getDefaultBucketName(), 
FILE_CONTENT, LOW_COST).block();
-
-        testee.blobId(blobId)
-            .with(new MailAddress(USER_2.getUsername()))
-            .explanation(EXPLANATION)
-            .noFileCustomPrefix()
-            .fileExtension(FILE_TEXT_EXTENSION)
-            .export();
-
-        RequestSpecification request = 
given(linshareExtension.getLinshare().fakeSmtpRequestSpecification());
-
-        Awaitility.waitAtMost(Duration.TEN_SECONDS)
-            .pollInterval(Duration.ONE_SECOND)
-            .untilAsserted(
-                () -> request
-                    .get("/api/email")
-                .then()
-                    .body("", hasSize(2)));
-
-        request
-            .get("/api/email")
-        .then()
-            .body("[1].subject", containsString("John Doe has shared a file 
with you"))
-            .body("[1].to", hasItem(USER_2.getUsername()))
-            .body("[1].html", containsString(EXPLANATION));
+            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getName()).endsWith(".txt"))
+            .allSatisfy(receivedShare -> 
assertThat(receivedShare.getName()).startsWith(filePrefix));
     }
 
     @Test
-    void exportShouldShareTheDocumentAndAllowDownloadViaLinshare() throws 
Exception {
+    void 
exportShouldUploadTheDocumentAndAllowDownloadViaLinshare(LinshareAPIForTechnicalAccountTesting
 delegationAPIForTesting) throws Exception {
         BlobId blobId = blobStore.save(blobStore.getDefaultBucketName(), 
FILE_CONTENT, LOW_COST).block();
 
         testee.blobId(blobId)
@@ -133,8 +95,8 @@ class LinshareBlobExportMechanismTest {
             .fileExtension(FILE_TEXT_EXTENSION)
             .export();
 
-        Document sharedDoc = user2API.receivedShares().get(0).getDocument();
-        byte[] sharedFile =  linshareExtension.downloadSharedFile(USER_2, 
sharedDoc.getId(), sharedDoc.getName());
+        Document sharedDoc = user2API.listAllDocuments().get(0);
+        byte[] sharedFile = delegationAPIForTesting.downloadFileFrom(USER_2, 
sharedDoc.getId());
         
assertThat(sharedFile).isEqualTo(FILE_CONTENT.getBytes(StandardCharsets.UTF_8));
     }
 
@@ -164,7 +126,7 @@ class LinshareBlobExportMechanismTest {
             .fileExtension(FILE_TEXT_EXTENSION)
             .export();
 
-        Document sharedDoc = user2API.receivedShares().get(0).getDocument();
+        Document sharedDoc = user2API.listAllDocuments().get(0);
         assertThat(sharedDoc.getName())
             .startsWith(filePrefix);
     }
diff --git 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareConfigurationTest.java
 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareConfigurationTest.java
index 81d5d66..093bceb 100644
--- 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareConfigurationTest.java
+++ 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareConfigurationTest.java
@@ -24,6 +24,7 @@ import static 
org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.UUID;
 
 import org.apache.commons.configuration2.PropertiesConfiguration;
 import org.junit.jupiter.api.Test;
@@ -31,6 +32,12 @@ import org.junit.jupiter.api.Test;
 import nl.jqno.equalsverifier.EqualsVerifier;
 
 class LinshareConfigurationTest {
+
+    private final static String EMPTY_STRING = "";
+    private final static String SOME_RANDOM_STRING = "laksdhfdksd";
+    private final String DEFAULT_URL = "http://127.0.0.1:8080";;
+    private final static String DEFAULT_UUID = UUID.randomUUID().toString();
+
     @Test
     void shouldMatchBeanContract() {
         EqualsVerifier.forClass(LinshareConfiguration.class)
@@ -40,17 +47,59 @@ class LinshareConfigurationTest {
     @Test
     void fromShouldThrowWhenUrlIsNull() {
         PropertiesConfiguration configuration = new PropertiesConfiguration();
-        configuration.addProperty("blob.export.linshare.token", "token");
-        configuration.addProperty("blob.export.linshare.url", null);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, null);
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
DEFAULT_UUID);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
LinshareFixture.TECHNICAL_ACCOUNT.getPassword());
 
         assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(MalformedURLException.class);
     }
 
     @Test
-    void fromShouldThrowWhenTokenIsNull() {
+    void fromShouldThrowWhenBasicAuthIsNull() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, null);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
null);
+
+        assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void fromShouldThrowWhenUUIDIsNull() {
         PropertiesConfiguration configuration = new PropertiesConfiguration();
-        configuration.addProperty("blob.export.linshare.token", null);
-        configuration.addProperty("blob.export.linshare.url", 
"http://127.0.0.1:8080";);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
SOME_RANDOM_STRING);
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, null);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
+
+        assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void fromShouldThrowWhenUUIDIsEmpty() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
EMPTY_STRING);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
SOME_RANDOM_STRING);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
+
+        assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void fromShouldThrowWhenUUIDIsWrongFormat() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
SOME_RANDOM_STRING);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
SOME_RANDOM_STRING);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
+
+        assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void fromShouldThrowWhenUUIDIsTooLong() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
"way-too-long-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
SOME_RANDOM_STRING);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
 
         assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(IllegalArgumentException.class);
     }
@@ -58,33 +107,46 @@ class LinshareConfigurationTest {
     @Test
     void fromShouldThrowWhenURLIsInvalid() {
         PropertiesConfiguration configuration = new PropertiesConfiguration();
-        configuration.addProperty("blob.export.linshare.token", "token");
-        configuration.addProperty("blob.export.linshare.url", "invalid");
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
DEFAULT_UUID);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
LinshareFixture.TECHNICAL_ACCOUNT.getPassword());
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
"invalid");
 
         assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(MalformedURLException.class);
     }
 
     @Test
-    void fromShouldThrowWhenTokenIsEmpty() {
+    void fromShouldThrowWhenPasswordIsNull() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
DEFAULT_UUID);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
null);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
+
+        assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void fromShouldThrowWhenPasswordIsEmpty() {
         PropertiesConfiguration configuration = new PropertiesConfiguration();
-        configuration.addProperty("blob.export.linshare.token", "");
-        configuration.addProperty("blob.export.linshare.url", 
"http://127.0.0.1:8080";);
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
DEFAULT_UUID);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
EMPTY_STRING);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, 
DEFAULT_URL);
 
         assertThatThrownBy(() -> 
LinshareConfiguration.from(configuration)).isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
     void fromShouldReturnProvidedConfiguration() throws Exception {
-        String token = "token";
-        String url = "http://127.0.0.1:8080";;
+        String password = LinshareFixture.TECHNICAL_ACCOUNT.getPassword();
+        String url = DEFAULT_URL;
 
         PropertiesConfiguration configuration = new PropertiesConfiguration();
-        configuration.addProperty("blob.export.linshare.token", token);
-        configuration.addProperty("blob.export.linshare.url", url);
+        configuration.addProperty(LinshareConfiguration.UUID_PROPERTY, 
DEFAULT_UUID);
+        configuration.addProperty(LinshareConfiguration.PASSWORD_PROPERTY, 
password);
+        configuration.addProperty(LinshareConfiguration.URL_PROPERTY, url);
 
         
assertThat(LinshareConfiguration.from(configuration)).isEqualTo(LinshareConfiguration.builder()
             .url(new URL(url))
-            .authorizationToken(new AuthorizationToken(token))
+            .basicAuthorization(DEFAULT_UUID, password)
             .build());
     }
 }
diff --git 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareExtension.java
 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareExtension.java
index 103ef3d..92dade8 100644
--- 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareExtension.java
+++ 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareExtension.java
@@ -19,6 +19,7 @@
 package org.apache.james.linshare;
 
 import static org.apache.james.linshare.LinshareFixture.ADMIN_ACCOUNT;
+import static org.apache.james.linshare.LinshareFixture.TECHNICAL_ACCOUNT;
 import static org.apache.james.linshare.LinshareFixture.USER_1;
 import static org.apache.james.linshare.LinshareFixture.USER_CREDENTIAL_MAP;
 import static 
org.apache.james.linshare.client.LinshareAPI.Headers.ACCEPT_APPLICATION_JSON;
@@ -26,6 +27,7 @@ import static 
org.apache.james.linshare.client.LinshareAPI.Headers.CONTENT_TYPE_
 
 import java.util.List;
 import java.util.Optional;
+import java.util.UUID;
 
 import org.apache.james.linshare.client.Document;
 import org.apache.james.linshare.client.LinshareAPI;
@@ -37,8 +39,12 @@ import org.apache.james.utils.FakeSmtp;
 import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
 
-import com.github.fge.lambdas.Throwing;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
 
 import feign.Feign;
 import feign.Headers;
@@ -51,43 +57,32 @@ import feign.jackson.JacksonDecoder;
 import feign.jackson.JacksonEncoder;
 import feign.slf4j.Slf4jLogger;
 
-public class LinshareExtension implements BeforeEachCallback, 
BeforeAllCallback {
+public class LinshareExtension implements BeforeEachCallback, 
BeforeAllCallback, ParameterResolver {
 
-    private interface LinshareAPIForTesting {
+    private static final Linshare linshare = LinshareSingleton.singleton;
 
-        String CONTENT_DISPOSITION_ATTACHMENT = "Content-Disposition: 
attachment; filename=\"{filename}\"";
-        String CONTENT_TYPE_APPLICATION_OCTET_STREAM = "Content-Type: 
application/octet-stream";
+    private UUID technicalAccountUUID;
 
-        static LinshareAPIForTesting from(LinshareFixture.Credential 
credential, Linshare linshare) {
+    public interface LinshareAPIForAdminTesting {
+        @VisibleForTesting
+        static LinshareAPIForAdminTesting from(LinshareFixture.Credential 
credential) {
 
             return Feign.builder()
                 .requestInterceptor(new 
BasicAuthRequestInterceptor(credential.getUsername(), credential.getPassword()))
-                .logger(new Slf4jLogger(LinshareAPIForTesting.class))
+                .logger(new Slf4jLogger(LinshareAPIForAdminTesting.class))
                 .logLevel(Logger.Level.FULL)
                 .encoder(new FormEncoder(new JacksonEncoder()))
                 .decoder(CombinedDecoder.builder()
                     .defaultDecoder(new JacksonDecoder())
                     .registerSingleTypeDecoder(new ByteArrayDecoder())
                     .build())
-                .target(LinshareAPIForTesting.class, linshare.getUrl());
+                .target(LinshareAPIForAdminTesting.class, linshare.getUrl());
         }
 
-        @RequestLine("GET 
/linshare/webservice/rest/user/v2/authentication/jwt")
-        @Headers(ACCEPT_APPLICATION_JSON)
-        AuthorizationToken jwt();
-
-        @RequestLine("GET /linshare/webservice/rest/user/v2/users")
-        @Headers(ACCEPT_APPLICATION_JSON)
-        List<User> allUsers();
-
         @RequestLine("GET /linshare/webservice/rest/admin/technical_accounts")
         @Headers(ACCEPT_APPLICATION_JSON)
         List<TechnicalAccountResponse> allTechnicalAccounts();
 
-        @RequestLine("GET 
/linshare/webservice/rest/user/v2/received_shares/{documentId}/download")
-        @Headers({ CONTENT_TYPE_APPLICATION_OCTET_STREAM, 
CONTENT_DISPOSITION_ATTACHMENT })
-        byte[] downloadShare(@Param("documentId") String documentId, 
@Param("filename") String filename);
-
         @RequestLine("POST /linshare/webservice/rest/admin/technical_accounts")
         @Headers({ ACCEPT_APPLICATION_JSON, CONTENT_TYPE_APPLICATION_JSON })
         TechnicalAccountResponse 
createTechnicalAccount(TechnicalAccountCreationRequest accountCreationRequest);
@@ -97,7 +92,72 @@ public class LinshareExtension implements 
BeforeEachCallback, BeforeAllCallback
         TechnicalAccountResponse 
grantTechnicalAccountPermissions(TechnicalAccountGrantPermissionsRequest 
accountGrantPermissionsRequest);
     }
 
-    private final Linshare linshare = LinshareSingleton.singleton;
+    public interface LinshareAPIForTechnicalAccountTesting {
+        @VisibleForTesting
+        static LinshareAPIForTechnicalAccountTesting 
from(LinshareFixture.Credential credential) {
+
+            return Feign.builder()
+                .requestInterceptor(new 
BasicAuthRequestInterceptor(credential.getUsername(), credential.getPassword()))
+                .logger(new 
Slf4jLogger(LinshareAPIForTechnicalAccountTesting.class))
+                .logLevel(Logger.Level.FULL)
+                .encoder(new FormEncoder(new JacksonEncoder()))
+                .decoder(CombinedDecoder.builder()
+                    .defaultDecoder(new JacksonDecoder())
+                    .registerSingleTypeDecoder(new ByteArrayDecoder())
+                    .build())
+                .target(LinshareAPIForTechnicalAccountTesting.class, 
linshare.getUrl());
+        }
+
+        @RequestLine("GET 
/linshare/webservice/rest/user/documents/{documentId}/download")
+        @Headers({ACCEPT_APPLICATION_JSON, CONTENT_TYPE_APPLICATION_JSON})
+        byte[] download(@Param("documentId") String documentId);
+
+        default byte[] downloadFileFrom(LinshareFixture.Credential credential, 
Document.DocumentId document) {
+            return from(credential).download(document.asString());
+        }
+    }
+
+    public interface LinshareAPIForUserTesting {
+        @VisibleForTesting
+         static LinshareAPIForUserTesting from(LinshareFixture.Credential 
credential) {
+
+            return Feign.builder()
+                .requestInterceptor(new 
BasicAuthRequestInterceptor(credential.getUsername(), credential.getPassword()))
+                .logger(new Slf4jLogger(LinshareAPIForUserTesting.class))
+                .logLevel(Logger.Level.FULL)
+                .encoder(new FormEncoder(new JacksonEncoder()))
+                .decoder(CombinedDecoder.builder()
+                    .defaultDecoder(new JacksonDecoder())
+                    .registerSingleTypeDecoder(new ByteArrayDecoder())
+                    .build())
+                .target(LinshareAPIForUserTesting.class, linshare.getUrl());
+        }
+
+        @RequestLine("GET /linshare/webservice/rest/user/v2/documents")
+        @feign.Headers(ACCEPT_APPLICATION_JSON)
+        List<Document> listAllDocuments();
+
+        @RequestLine("DELETE 
/linshare/webservice/rest/user/v2/documents/{documentId}")
+        @feign.Headers({ ACCEPT_APPLICATION_JSON, 
CONTENT_TYPE_APPLICATION_JSON })
+        Document delete(@Param("documentId") String documentId);
+
+        default Document delete(Document.DocumentId documentId) {
+            return delete(documentId.asString());
+        }
+
+        default void deleteAllDocuments() {
+            listAllDocuments().forEach(document -> delete(document.getId()));
+        }
+
+        @RequestLine("GET /linshare/webservice/rest/user/v2/users")
+        @Headers(ACCEPT_APPLICATION_JSON)
+        List<User> allUsers();
+    }
+
+    @Override
+    public void beforeAll(ExtensionContext extensionContext) {
+        
createTechnicalAccount(TechnicalAccountCreationRequest.defaultAccount());
+    }
 
     @Override
     public void beforeEach(ExtensionContext context) {
@@ -105,56 +165,65 @@ public class LinshareExtension implements 
BeforeEachCallback, BeforeAllCallback
         FakeSmtp.clean(linshare.fakeSmtpRequestSpecification());
     }
 
-    public Linshare getLinshare() {
-        return linshare;
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext) throws ParameterResolutionException {
+        return (parameterContext.getParameter().getType() == 
LinshareAPIForTechnicalAccountTesting.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext) throws ParameterResolutionException {
+        Preconditions.checkArgument(parameterContext.getParameter().getType() 
== LinshareAPIForTechnicalAccountTesting.class);
+        return getDelegationAccountTestingAPI();
     }
 
-    public LinshareAPI getAPIFor(LinshareFixture.Credential credential) throws 
Exception {
-        return LinshareAPI.from(configurationWithJwtFor(credential));
+    public LinshareAPI getDelegationAccountAPI() throws Exception {
+        return LinshareAPI.from(configurationWithBasicAuthFor(
+            new LinshareFixture.Credential(
+                technicalAccountUUID.toString(),
+                TECHNICAL_ACCOUNT.getPassword())));
     }
 
-    public LinshareConfiguration 
configurationWithJwtFor(LinshareFixture.Credential credential) throws Exception 
{
-        AuthorizationToken token = LinshareAPIForTesting.from(credential, 
linshare).jwt();
+    public LinshareAPIForTechnicalAccountTesting 
getDelegationAccountTestingAPI() {
+        return LinshareAPIForTechnicalAccountTesting.from(
+            new LinshareFixture.Credential(
+                technicalAccountUUID.toString(),
+                TECHNICAL_ACCOUNT.getPassword()));
+    }
 
+    public LinshareConfiguration 
configurationWithBasicAuthFor(LinshareFixture.Credential credential) throws 
Exception {
         return LinshareConfiguration.builder()
             .urlAsString(linshare.getUrl())
-            .authorizationToken(token)
+            .basicAuthorization(credential.getUsername(), 
credential.getPassword())
             .build();
     }
 
-    public byte[] downloadSharedFile(LinshareFixture.Credential credential, 
Document.DocumentId document, String filename) {
-        return LinshareAPIForTesting.from(credential, linshare)
-            .downloadShare(document.asString(), filename);
-    }
-
-    @Override
-    public void beforeAll(ExtensionContext extensionContext){
-        
createTechnicalAccount(TechnicalAccountCreationRequest.defaultAccount());
-    }
-
-    private void createTechnicalAccount(TechnicalAccountCreationRequest 
technicalAccountDTO) {
-        TechnicalAccountResponse technicalAccountResponse = 
LinshareAPIForTesting.from(ADMIN_ACCOUNT, 
linshare).createTechnicalAccount(technicalAccountDTO);
+    private void createTechnicalAccount(TechnicalAccountCreationRequest 
technicalAccountCreationRequest) {
+        TechnicalAccountResponse technicalAccountResponse = 
LinshareAPIForAdminTesting.from(ADMIN_ACCOUNT).createTechnicalAccount(technicalAccountCreationRequest);
 
         TechnicalAccountGrantPermissionsRequest 
technicalAccountGrantPermissionsRequest = new 
TechnicalAccountGrantPermissionsRequest(technicalAccountResponse);
-        LinshareAPIForTesting.from(ADMIN_ACCOUNT, 
linshare).grantTechnicalAccountPermissions(technicalAccountGrantPermissionsRequest);
-    }
-
-    public List<TechnicalAccountResponse> 
getAllTechnicalAccounts(LinshareFixture.Credential credential) {
-        return LinshareAPIForTesting.from(credential, 
linshare).allTechnicalAccounts();
+        
LinshareAPIForAdminTesting.from(ADMIN_ACCOUNT).grantTechnicalAccountPermissions(technicalAccountGrantPermissionsRequest);
+        this.technicalAccountUUID = 
UUID.fromString(technicalAccountResponse.getUuid());
     }
 
     private void deleteAllUsersDocuments() {
-        LinshareAPIForTesting.from(USER_1, linshare)
+        LinshareAPIForUserTesting.from(USER_1)
             .allUsers()
             .stream()
             .map(this::getUsernamePassword)
-            .map(Throwing.function(this::configurationWithJwtFor))
-            .map(LinshareAPI::from)
-            .forEach(LinshareAPI::deleteAllDocuments);
+            .map(LinshareAPIForUserTesting::from)
+            .forEach(LinshareAPIForUserTesting::deleteAllDocuments);
     }
 
     private LinshareFixture.Credential getUsernamePassword(User user) {
         return Optional.ofNullable(USER_CREDENTIAL_MAP.get(user.getMail()))
             .orElseThrow(() -> new RuntimeException("cannot get token of user 
" + user.getMail()));
     }
+
+    public UUID getTechnicalAccountUUID() {
+        return technicalAccountUUID;
+    }
+
+    public Linshare getLinshare() {
+        return linshare;
+    }
 }
diff --git 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareTest.java
 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareTest.java
index 27d55e4..0e9fd3a 100644
--- 
a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareTest.java
+++ 
b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareTest.java
@@ -22,9 +22,11 @@ import static io.restassured.RestAssured.given;
 import static io.restassured.config.EncoderConfig.encoderConfig;
 import static io.restassured.config.RestAssuredConfig.newConfig;
 import static org.apache.james.linshare.LinshareFixture.ACCOUNT_ENABLED;
+import static org.apache.james.linshare.LinshareFixture.ADMIN_ACCOUNT;
 import static org.apache.james.linshare.LinshareFixture.TECHNICAL_ACCOUNT;
 import static org.apache.james.linshare.LinshareFixture.TECHNICAL_PERMISSIONS;
 import static org.assertj.core.api.Assertions.assertThat;
+import static 
org.apache.james.linshare.LinshareExtension.LinshareAPIForAdminTesting;
 
 import java.nio.charset.StandardCharsets;
 import java.util.List;
@@ -69,7 +71,7 @@ class LinshareTest {
 
     @Test
     void linshareShouldHaveATechnicalAccountConfigured() {
-        List<TechnicalAccountResponse> technicalAccounts = 
linshareExtension.getAllTechnicalAccounts(LinshareFixture.ADMIN_ACCOUNT);
+        List<TechnicalAccountResponse> technicalAccounts = 
LinshareAPIForAdminTesting.from(ADMIN_ACCOUNT).allTechnicalAccounts();
 
         assertThat(technicalAccounts).anySatisfy(account -> 
SoftAssertions.assertSoftly(softly -> {
             
softly.assertThat(account.getName()).isEqualTo(TECHNICAL_ACCOUNT.getUsername());
diff --git 
a/third-party/linshare/src/test/java/org/apache/james/linshare/client/LinshareAPITest.java
 
b/third-party/linshare/src/test/java/org/apache/james/linshare/client/LinshareAPITest.java
index b93e4b8..0ca47af 100644
--- 
a/third-party/linshare/src/test/java/org/apache/james/linshare/client/LinshareAPITest.java
+++ 
b/third-party/linshare/src/test/java/org/apache/james/linshare/client/LinshareAPITest.java
@@ -19,60 +19,47 @@
 
 package org.apache.james.linshare.client;
 
-import static io.restassured.RestAssured.given;
+import static 
org.apache.james.linshare.LinshareExtension.LinshareAPIForUserTesting;
 import static org.apache.james.linshare.LinshareFixture.USER_1;
 import static org.apache.james.linshare.LinshareFixture.USER_2;
-import static org.apache.james.linshare.LinshareFixture.USER_3;
-import static org.apache.james.linshare.LinshareFixture.USER_4;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.hasSize;
 
 import java.io.File;
 import java.nio.file.Files;
-import java.util.Collection;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.james.core.MailAddress;
 import org.apache.james.linshare.LinshareExtension;
 import org.assertj.core.api.SoftAssertions;
-import org.awaitility.Awaitility;
-import org.awaitility.Duration;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
-import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
-
-import com.github.steveash.guavate.Guavate;
 
 import feign.FeignException;
-import io.restassured.specification.RequestSpecification;
 
 class LinshareAPITest {
-    private static final String MESSAGE = "message";
+    private static final String USER1_MAIL = "us...@linshare.org";
+    private static final String USER2_MAIL = "us...@linshare.org";
+
 
     @RegisterExtension
     static LinshareExtension linshareExtension = new LinshareExtension();
 
-    private LinshareAPI user1LinshareAPI;
-    private LinshareAPI user2LinshareAPI;
-    private LinshareAPI user3LinshareAPI;
-    private LinshareAPI user4LinshareAPI;
+    private LinshareAPIForUserTesting user1LinshareAPI;
+    private LinshareAPIForUserTesting user2LinshareAPI;
+    private LinshareAPI technicalLinshareAPI;
 
     @BeforeEach
     void setup() throws Exception {
-        user1LinshareAPI = linshareExtension.getAPIFor(USER_1);
-        user2LinshareAPI = linshareExtension.getAPIFor(USER_2);
-        user3LinshareAPI = linshareExtension.getAPIFor(USER_3);
-        user4LinshareAPI = linshareExtension.getAPIFor(USER_4);
+        user1LinshareAPI = LinshareAPIForUserTesting.from(USER_1);
+        user2LinshareAPI = LinshareAPIForUserTesting.from(USER_2);
+        technicalLinshareAPI = linshareExtension.getDelegationAccountAPI();
     }
 
     @Test
     void uploadDocumentShouldReturnUploaded() throws Exception {
         File uploadFile = templateFile();
-        Document uploadedDocument = 
user1LinshareAPI.uploadDocument(uploadFile);
+        Document uploadedDocument = uploadDocumentToUserSpace(USER1_MAIL, 
uploadFile);
 
         SoftAssertions.assertSoftly(softly -> {
             
softly.assertThat(uploadedDocument.getName()).isEqualTo(uploadFile.getName());
@@ -82,11 +69,11 @@ class LinshareAPITest {
 
     @Test
     void uploadDocumentShouldMakeListingReturnUploaded() throws Exception {
-        Document uploadedDocument = 
user1LinshareAPI.uploadDocument(templateFile());
+        Document uploadedDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
 
         assertThat(user1LinshareAPI.listAllDocuments())
             .hasSize(1)
-            .containsExactly(uploadedDocument);
+            .containsExactlyInAnyOrder(uploadedDocument);
     }
 
     @Test
@@ -97,27 +84,27 @@ class LinshareAPITest {
 
     @Test
     void listAllShouldReturnAllUploadedDocuments() throws Exception {
-        Document firstDocument = 
user1LinshareAPI.uploadDocument(templateFile());
-        Document secondDocument = 
user1LinshareAPI.uploadDocument(templateFile());
+        Document firstDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
+        Document secondDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
 
         assertThat(user1LinshareAPI.listAllDocuments())
-            .containsExactly(firstDocument, secondDocument);
+            .containsExactlyInAnyOrder(firstDocument, secondDocument);
     }
 
     @Test
     void listAllShouldNotReturnDocumentsOfOtherUsers() throws Exception {
-        Document firstDocument = 
user1LinshareAPI.uploadDocument(templateFile());
-        Document secondDocument = 
user1LinshareAPI.uploadDocument(templateFile());
+        Document firstDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
+        Document secondDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
 
-        user2LinshareAPI.uploadDocument(templateFile());
+        uploadDocumentToUserSpace(USER2_MAIL, templateFile());
 
         assertThat(user1LinshareAPI.listAllDocuments())
-            .containsExactly(firstDocument, secondDocument);
+            .containsExactlyInAnyOrder(firstDocument, secondDocument);
     }
 
     @Test
     void deleteShouldDeleteUploadedDocument() throws Exception {
-        Document firstDocument = 
user1LinshareAPI.uploadDocument(templateFile());
+        Document firstDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
         user1LinshareAPI.delete(firstDocument.getId());
 
         assertThat(user1LinshareAPI.listAllDocuments())
@@ -126,17 +113,17 @@ class LinshareAPITest {
 
     @Test
     void deleteShouldNotDeleteOtherUserDocuments() throws Exception {
-        Document user1Document = 
user1LinshareAPI.uploadDocument(templateFile());
-        Document user2Document = 
user2LinshareAPI.uploadDocument(templateFile());
+        Document user1Document = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
+        Document user2Document = uploadDocumentToUserSpace(USER2_MAIL, 
templateFile());
         user1LinshareAPI.delete(user1Document.getId());
 
         assertThat(user2LinshareAPI.listAllDocuments())
-            .containsExactly(user2Document);
+            .containsExactlyInAnyOrder(user2Document);
     }
 
     @Test
     void deleteShouldReturnErrorWhenDeleteOtherUserDocuments() throws 
Exception {
-        Document user1Document = 
user1LinshareAPI.uploadDocument(templateFile());
+        Document user1Document = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
 
         assertThatThrownBy(() -> 
user2LinshareAPI.delete(user1Document.getId()))
             .isInstanceOf(FeignException.Forbidden.class);
@@ -144,8 +131,8 @@ class LinshareAPITest {
 
     @Test
     void deleteAllShouldClearAllDocumentsOfAnUser() throws Exception {
-        user1LinshareAPI.uploadDocument(templateFile());
-        user1LinshareAPI.uploadDocument(templateFile());
+        uploadDocumentToUserSpace(USER1_MAIL, templateFile());
+        uploadDocumentToUserSpace(USER1_MAIL, templateFile());
 
         user1LinshareAPI.deleteAllDocuments();
 
@@ -154,112 +141,27 @@ class LinshareAPITest {
     }
 
     @Test
-    void shareShouldTriggerAnEmail() throws Exception {
-        Document user1Document = 
user1LinshareAPI.uploadDocument(templateFile());
-
-        String message = "Very specific message";
-        ShareRequest shareRequest = ShareRequest.builder()
-            .message(message)
-            .addDocumentId(user1Document.getId())
-            .addRecipient(new MailAddress(USER_2.getUsername()))
-            .build();
-
-        user1LinshareAPI.share(shareRequest);
-
-        RequestSpecification request = 
given(linshareExtension.getLinshare().fakeSmtpRequestSpecification());
-
-        Awaitility.waitAtMost(Duration.TEN_SECONDS)
-            .pollInterval(Duration.ONE_SECOND)
-            .untilAsserted(
-                () -> request
-                    .get("/api/email")
-                .then()
-                    .body("", hasSize(2)));
-
-        request
-            .get("/api/email")
-        .then()
-            .body("[1].subject", containsString("John Doe has shared a file 
with you"))
-            .body("[1].html", containsString(message));
-    }
-
-
-    @Test
-    void shareShouldShareToTargetedRecipient() throws Exception {
-        Document user1Document = 
user1LinshareAPI.uploadDocument(templateFile());
+    void uploadDocumentShouldUploadToUserSpace() throws Exception {
+        Document uploadedDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
 
-        ShareRequest shareRequest = ShareRequest.builder()
-            .message(MESSAGE)
-            .addDocumentId(user1Document.getId())
-            .addRecipient(new MailAddress(USER_2.getUsername()))
-            .build();
-
-        user1LinshareAPI.share(shareRequest);
-        assertThat(user2LinshareAPI.receivedShares())
-            .hasSize(1)
-            .allSatisfy(shareReceived -> {
-                Document sharedDoc = shareReceived.getDocument();
-                
assertThat(sharedDoc.getName()).isEqualTo(user1Document.getName());
-                
assertThat(sharedDoc.getSize()).isEqualTo(user1Document.getSize());
-            });
+        List<Document> user1Documents = user1LinshareAPI.listAllDocuments();
+        assertThat(user1Documents).containsAnyOf(uploadedDocument);
     }
 
     @Test
-    void shareShouldWorkWithMultipleRecipients() throws Exception {
-        Document user1Document = 
user1LinshareAPI.uploadDocument(templateFile());
-
-        ShareRequest shareRequest = ShareRequest.builder()
-            .message(MESSAGE)
-            .addDocumentId(user1Document.getId())
-            .addRecipient(new MailAddress(USER_2.getUsername()))
-            .addRecipient(new MailAddress(USER_3.getUsername()))
-            .addRecipient(new MailAddress(USER_4.getUsername()))
-            .build();
-
-        user1LinshareAPI.share(shareRequest);
-        List<ReceivedShare> user2Shares = user2LinshareAPI.receivedShares();
-        List<ReceivedShare> user3Shares = user3LinshareAPI.receivedShares();
-        List<ReceivedShare> user4Shares = user4LinshareAPI.receivedShares();
-
-        assertThat(user2Shares)
-            .hasSameSizeAs(user3Shares)
-            .hasSameSizeAs(user4Shares)
-            .hasSize(1);
-
-        assertThat(sharedDocs(user2Shares, user3Shares, user4Shares))
-            .allSatisfy(sharedDoc -> {
-                
assertThat(sharedDoc.getName()).isEqualTo(user1Document.getName());
-                
assertThat(sharedDoc.getSize()).isEqualTo(user1Document.getSize());
-            });
-    }
-
-    @Test
-    void downloadShareShouldGetUploadedSharedFile() throws Exception {
-        File user1File = templateFile();
-        Document user1Document = user1LinshareAPI.uploadDocument(user1File);
-
-        ShareRequest shareRequest = ShareRequest.builder()
-            .message(MESSAGE)
-            .addDocumentId(user1Document.getId())
-            .addRecipient(new MailAddress(USER_2.getUsername()))
-            .build();
+    void uploadDocumentShouldPerformByDelegationAccount() throws Exception {
+        Document uploadedDocument = uploadDocumentToUserSpace(USER1_MAIL, 
templateFile());
 
-        user1LinshareAPI.share(shareRequest);
-        Document sharedDoc = 
user2LinshareAPI.receivedShares().get(0).getDocument();
+        List<Document> user1Documents = user1LinshareAPI.listAllDocuments();
+        assertThat(user1Documents).containsAnyOf(uploadedDocument);
+    }
 
-        byte[] sharedFile =  linshareExtension.downloadSharedFile(USER_2, 
sharedDoc.getId(), sharedDoc.getName());
-        
assertThat(sharedFile).isEqualTo(FileUtils.readFileToByteArray(user1File));
+    private Document uploadDocumentToUserSpace(String targetUserEmail, File 
userFile) {
+        User targetUser = technicalLinshareAPI.getUserByMail(targetUserEmail);
+        return technicalLinshareAPI.uploadDocumentByDelegation(targetUser, 
userFile);
     }
 
     private File templateFile() throws Exception {
         return Files.createTempFile("linshare-api-test", ".temp").toFile();
     }
-
-    @SafeVarargs
-    private final List<Document> sharedDocs(List<ReceivedShare>... shares) {
-        return ImmutableList.copyOf(shares).stream()
-            .flatMap(Collection::stream)
-            .map(ReceivedShare::getDocument)
-            .collect(Guavate.toImmutableList());
-    }
 }
diff --git 
a/third-party/linshare/src/test/java/org/apache/james/linshare/client/TechnicalAccountCreationRequest.java
 
b/third-party/linshare/src/test/java/org/apache/james/linshare/client/TechnicalAccountCreationRequest.java
index ad52803..f92c2b3 100644
--- 
a/third-party/linshare/src/test/java/org/apache/james/linshare/client/TechnicalAccountCreationRequest.java
+++ 
b/third-party/linshare/src/test/java/org/apache/james/linshare/client/TechnicalAccountCreationRequest.java
@@ -72,5 +72,4 @@ public class TechnicalAccountCreationRequest {
     public String getRole() {
         return role;
     }
-
 }
diff --git a/upgrade-instructions.md b/upgrade-instructions.md
index c1ca041..e77d568 100644
--- a/upgrade-instructions.md
+++ b/upgrade-instructions.md
@@ -16,6 +16,7 @@ Changes to apply between 3.4.x and 3.5.x will be reported 
here.
 
 Change list:
 
+ - [LinShare blob export mechanism should rely on delegation](#LinShare blob 
export mechanism should rely on delegation)
  - [RabbitMQ minimal version](#rabbitmq-minimal-version)
  - [Enforce usernames to be lower cased](#enforce-usernames-to-be-lower-cased)
  - [Cassandra keyspace creation 
configuration](#cassandra-keyspace-creation-configuration)
@@ -39,6 +40,26 @@ Even if this set of characters should be allowed for the 
local part of a Usernam
 
 However, the read of Usernames already existing with some of those characters 
is still allowed, to not introduce any breaking change.
 
+### LinShare blob export mechanism should rely on delegation
+Date 12/02/2020
+
+SHA-1 XXX
+
+Concerned products: Guice server, experimental LinShare blob export feature.
+
+JIRA: https://issues.apache.org/jira/browse/JAMES-3040
+
+Blob Export Configuration changed:
+
+File configuration need to be adjusted: `blob.properties`
+
+-You need to add new mandatory properties when `blob.export.implementation` 
property is set to `linshare`:
+```
+blob.export.linshare.technical.account.uuid
+blob.export.linshare.technical.account.password
+```
+
+-The legacy property `blob.export.linshare.token` will not used anymore, you 
can remove it.
 ### Hybrid blobStore replaces Union blobStore
 
 Date 6/01/2020


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

Reply via email to