JAMES-1784 Add integration tests when downloading attachment with access token
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/85aeb1e4 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/85aeb1e4 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/85aeb1e4 Branch: refs/heads/master Commit: 85aeb1e45b5d5cbffbe40b7c71f7ed264e57b5a6 Parents: b6f6ac9 Author: Antoine Duprat <adup...@linagora.com> Authored: Fri Jul 1 14:56:30 2016 +0200 Committer: Antoine Duprat <adup...@linagora.com> Committed: Fri Jul 8 09:54:07 2016 +0200 ---------------------------------------------------------------------- .../integration/cucumber/DownloadStepdefs.java | 170 ++++++++++++++++--- .../resources/cucumber/DownloadEndpoint.feature | 51 ++++-- .../test/resources/cucumber/DownloadGet.feature | 5 +- .../java/org/apache/james/jmap/JMAPServer.java | 2 +- .../james/jmap/crypto/SignedTokenFactory.java | 4 +- .../james/jmap/model/AttachmentAccessToken.java | 20 ++- .../jmap/crypto/SignedTokenFactoryTest.java | 3 +- .../jmap/crypto/SignedTokenManagerTest.java | 10 ++ 8 files changed, 220 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java index b414de9..53fe11d 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java @@ -20,7 +20,7 @@ package org.apache.james.jmap.methods.integration.cucumber; import static com.jayway.restassured.RestAssured.with; -import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.isIn; import static org.hamcrest.Matchers.notNullValue; import java.util.Date; @@ -31,10 +31,14 @@ import javax.inject.Inject; import javax.mail.Flags; import org.apache.james.jmap.api.access.AccessToken; +import org.apache.james.jmap.model.AttachmentAccessToken; import org.apache.james.mailbox.model.MailboxConstants; import org.apache.james.mailbox.model.MailboxPath; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Multimap; import com.jayway.restassured.http.ContentType; import com.jayway.restassured.response.Response; @@ -49,12 +53,21 @@ import cucumber.runtime.java.guice.ScenarioScoped; @ScenarioScoped public class DownloadStepdefs { + private static final String ONE_ATTACHMENT_EML_ATTACHEMENT_BLOB_ID = "4000c5145f633410b80be368c44e1c394bff9437"; + private static final String EXPIRED_ATTACHMENT_TOKEN = "usera@domain.tld_" + + "2016-06-29T13:41:22.124Z_" + + "DiZa0O14MjLWrAA8P6MG35Gt5CBp7mt5U1EH/M++rIoZK7nlGJ4dPW0dvZD7h4m3o5b/Yd8DXU5x2x4+s0HOOKzD7X0RMlsU7JHJMNLvTvRGWF/C+MUyC8Zce7DtnRVPEQX2uAZhL2PBABV07Vpa8kH+NxoS9CL955Bc1Obr4G+KN2JorADlocFQA6ElXryF5YS/HPZSvq1MTC6aJIP0ku8WRpRnbwgwJnn26YpcHXcJjbkCBtd9/BhlMV6xNd2hTBkfZmYdoNo+UKBaXWzLxAlbLuxjpxwvDNJfOEyWFPgHDoRvzP+G7KzhVWjanHAHrhF0GilEa/MKpOI1qHBSwA=="; + private static final String INVALID_ATTACHMENT_TOKEN = "usera@domain.tld_" + + "2015-06-29T13:41:22.124Z_" + + "DiZa0O14MjLWrAA8P6MG35Gt5CBp7mt5U1EH/M++rIoZK7nlGJ4dPW0dvZD7h4m3o5b/Yd8DXU5x2x4+s0HOOKzD7X0RMlsU7JHJMNLvTvRGWF/C+MUyC8Zce7DtnRVPEQX2uAZhL2PBABV07Vpa8kH+NxoS9CL955Bc1Obr4G+KN2JorADlocFQA6ElXryF5YS/HPZSvq1MTC6aJIP0ku8WRpRnbwgwJnn26YpcHXcJjbkCBtd9/BhlMV6xNd2hTBkfZmYdoNo+UKBaXWzLxAlbLuxjpxwvDNJfOEyWFPgHDoRvzP+G7KzhVWjanHAHrhF0GilEa/MKpOI1qHBSwA=="; + private final UserStepdefs userStepdefs; private final MainStepdefs mainStepdefs; private Response response; private Multimap<String, String> attachmentsByMessageId; private Map<String, String> blobIdByAttachmentId; private ValidatableResponse validatableResponse; + private Map<AttachmentAccessTokenKey, AttachmentAccessToken> attachmentAccessTokens; @Inject private DownloadStepdefs(MainStepdefs mainStepdefs, UserStepdefs userStepdefs) { @@ -62,6 +75,7 @@ public class DownloadStepdefs { this.userStepdefs = userStepdefs; this.attachmentsByMessageId = ArrayListMultimap.create(); this.blobIdByAttachmentId = new HashMap<>(); + this.attachmentAccessTokens = new HashMap<>(); } @Given("^\"([^\"]*)\" mailbox \"([^\"]*)\" contains a message \"([^\"]*)\" with an attachment \"([^\"]*)\"$") @@ -95,38 +109,144 @@ public class DownloadStepdefs { with.header("Authorization", accessToken.serialize()); } - response = with.options("/download/myBlob"); + response = with + .options("/download/" + ONE_ATTACHMENT_EML_ATTACHEMENT_BLOB_ID); } @When("^\"([^\"]*)\" downloads \"([^\"]*)\"$") public void downloads(String username, String attachmentId) throws Throwable { String blobId = blobIdByAttachmentId.get(attachmentId); + response = authenticatedDownloadRequest(blobId, username) + .get("/download/" + blobId); + } + + private RequestSpecification authenticatedDownloadRequest(String blobId, String username) { AccessToken accessToken = userStepdefs.tokenByUser.get(username); - RequestSpecification with = with(); + AttachmentAccessTokenKey key = new AttachmentAccessTokenKey(username, blobId); + if (attachmentAccessTokens.containsKey(key)) { + return with().param("access_token", attachmentAccessTokens.get(key).serialize()); + } if (accessToken != null) { - with.header("Authorization", accessToken.serialize()); + return with().header("Authorization", accessToken.serialize()); } - response = with.get("/download/" + blobId); + return with(); } - - @When("^\"([^\"]*)\" asks for an attachment without blobId parameter$") - public void getDownloadWithoutBlobId(String username) throws Throwable { - AccessToken accessToken = userStepdefs.tokenByUser.get(username); + @When("^\"([^\"]*)\" is trusted for attachment \"([^\"]*)\"$") + public void attachmentAccessTokenFor(String username, String attachmentId) throws Throwable { + userStepdefs.connectUser(username); + trustForBlobId(blobIdByAttachmentId.get(attachmentId), username); + } + + private static class AttachmentAccessTokenKey { + + private String username; + private String blobId; + + public AttachmentAccessTokenKey(String username, String blobId) { + this.username = username; + this.blobId = blobId; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AttachmentAccessTokenKey) { + AttachmentAccessTokenKey other = (AttachmentAccessTokenKey) obj; + return Objects.equal(username, other.username) + && Objects.equal(blobId, other.blobId); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(username, blobId); + } + + @Override + public String toString() { + return MoreObjects + .toStringHelper(this) + .add("username", username) + .add("blobId", blobId) + .toString(); + } + } + + private void trustForBlobId(String blobId, String username) { + String serializedAttachmentAccessToken = + with() + .header("Authorization", userStepdefs.tokenByUser.get(username).serialize()) + .post("/download/" + blobId) + .then() + .extract() + .asString(); + attachmentAccessTokens.put( + new AttachmentAccessTokenKey(username, blobId), + AttachmentAccessToken.from( + serializedAttachmentAccessToken, + blobId)); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with a valid authentication token$") + public void downloadsWithValidToken(String username, String attachmentId) throws Throwable { + String blobId = blobIdByAttachmentId.get(attachmentId); + + response = requestWithQueryParameterAuthentication(username, blobId) + .get("/download/" + attachmentId); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" without any authentication token$") + public void getDownloadWithoutToken(String username, String attachmentId) { + String blobId = blobIdByAttachmentId.get(attachmentId); + response = with().get("/download/" + blobId); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with an empty authentication token$") + public void getDownloadWithEmptyToken(String username, String attachmentId) { + String blobId = blobIdByAttachmentId.get(attachmentId); response = with() - .header("Authorization", accessToken.serialize()) - .get("/download/"); + .param("access_token", "") + .get("/download/" + blobId); } - - @When("^\"([^\"]*)\" asks for an attachment with wrong blobId$") - public void getDownloadWithWrongBlobId(String username) throws Throwable { - AccessToken accessToken = userStepdefs.tokenByUser.get(username); + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with a bad authentication token$") + public void getDownloadWithBadToken(String username, String attachmentId) { + String blobId = blobIdByAttachmentId.get(attachmentId); response = with() - .header("Authorization", accessToken.serialize()) + .param("access_token", "bad") + .get("/download/" + blobId); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with an invalid authentication token$") + public void getDownloadWithUnknownToken(String username, String attachmentId) { + String blobId = blobIdByAttachmentId.get(attachmentId); + response = with() + .param("access_token", INVALID_ATTACHMENT_TOKEN) + .get("/download/" + blobId); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" without blobId parameter$") + public void getDownloadWithoutBlobId(String username, String attachmentId) throws Throwable { + String blobId = blobIdByAttachmentId.get(attachmentId); + + response = requestWithQueryParameterAuthentication(username, blobId) + .get("/download/"); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with wrong blobId$") + public void getDownloadWithWrongBlobId(String username, String attachmentId) throws Throwable { + String blobId = blobIdByAttachmentId.get(attachmentId); + + response = requestWithQueryParameterAuthentication(username, blobId) .get("/download/badbadbadbadbadbadbadbadbadbadbadbadbadb"); } + private RequestSpecification requestWithQueryParameterAuthentication(String username, String blobId) { + trustForBlobId(blobId, username); + return authenticatedDownloadRequest(blobId, username); + } + @When("^\"([^\"]*)\" asks for a token for attachment \"([^\"]*)\"$") public void postDownload(String username, String attachmentId) throws Throwable { String blobId = blobIdByAttachmentId.get(attachmentId); @@ -142,18 +262,22 @@ public class DownloadStepdefs { @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with \"([^\"]*)\" name$") public void downloadsWithName(String username, String attachmentId, String name) { String blobId = blobIdByAttachmentId.get(attachmentId); - AccessToken accessToken = userStepdefs.tokenByUser.get(username); - RequestSpecification with = with(); - if (accessToken != null) { - with.header("Authorization", accessToken.serialize()); - } - response = with.get("/download/" + blobId + "/" + name); + response = authenticatedDownloadRequest(blobId, username) + .get("/download/" + blobId + "/" + name); + } + + @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with an expired token$") + public void getDownloadWithExpiredToken(String username, String attachmentId) { + String blobId = blobIdByAttachmentId.get(attachmentId); + response = with() + .param("access_token", EXPIRED_ATTACHMENT_TOKEN) + .get("/download/" + blobId); } @Then("^the user should be authorized$") public void httpStatusDifferentFromUnauthorized() { response.then() - .statusCode(not(401)); + .statusCode(isIn(ImmutableList.of(200, 404))); } @Then("^the user should not be authorized$") http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature index d059572..e46a4fe 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature @@ -17,35 +17,58 @@ Feature: Download endpoint When "us...@domain.tld" checks for the availability of the attachment endpoint Then the user should be authorized - Scenario: An authenticated user should have access to the download endpoint - Given "us...@domain.tld" is connected - When "us...@domain.tld" downloads "a1" - Then the user should be authorized - - @Ignore Scenario: An unauthenticated user should not have access to the download endpoint When "us...@domain.tld" downloads "a1" Then the user should not be authorized - Scenario: A authenticated user should not have access to the download endpoint without a blobId - Given "us...@domain.tld" is connected - When "us...@domain.tld" asks for an attachment without blobId parameter - Then the user should receive a bad request response + Scenario: A user should not have access to the download endpoint without the authentication token + When "us...@domain.tld" downloads "a1" without any authentication token + Then the user should not be authorized + + Scenario: A user should not have access to the download endpoint with an empty authentication token + When "us...@domain.tld" downloads "a1" with an empty authentication token + Then the user should not be authorized + + Scenario: A user should not have access to the download endpoint with a bad authentication token + When "us...@domain.tld" downloads "a1" with a bad authentication token + Then the user should not be authorized + + Scenario: A user should not have access to the download endpoint with an unknown authentication token + When "us...@domain.tld" downloads "a1" with an invalid authentication token + Then the user should not be authorized + + Scenario: A user should not have access to the download endpoint when an authentication token has expired + When "us...@domain.tld" downloads "a1" with an expired token + Then the user should not be authorized + Scenario: A user should not have access to the download endpoint without a blobId + Given "us...@domain.tld" is trusted for attachment "a1" + When "us...@domain.tld" downloads "a1" without blobId parameter + Then the user should not be authorized Scenario: A user should not retrieve anything when using wrong blobId + Given "us...@domain.tld" is trusted for attachment "a1" + When "us...@domain.tld" downloads "a1" with wrong blobId + Then the user should not be authorized + + Scenario: A user should have access to the download endpoint when an authentication token is valid + Given "us...@domain.tld" is trusted for attachment "a1" + When "us...@domain.tld" downloads "a1" + Then the user should be authorized + + Scenario: An authenticated user should have access to the download endpoint Given "us...@domain.tld" is connected - When "us...@domain.tld" asks for an attachment with wrong blobId - Then the user should receive a not found response + When "us...@domain.tld" downloads "a1" + Then the user should be authorized @Ignore - Scenario: A user should not have access to someone else attachment + Scenario: An authenticated user should not have access to someone else attachment Given "us...@domain.tld" is connected When "us...@domain.tld" downloads "a1" Then the user should receive a not found response @Ignore - Scenario: A user should have access to a shared attachment + Scenario: An authenticated user should have access to a shared attachment Given "us...@domain.tld" shares its mailbox "INBOX" with "us...@domain.tld" And "us...@domain.tld" is connected When "us...@domain.tld" downloads "a1" http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature index bf3d21a..ccd7eef 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature @@ -13,8 +13,9 @@ Feature: Download GET Then the user should receive that attachment Scenario: Getting an attachment with an unknown blobId - When "usern...@domain.tld" downloads "123" - Then the user should receive a not found response + Given "usern...@domain.tld" mailbox "inbox" contains a message "1" with an attachment "2" + When "usern...@domain.tld" downloads "2" with a valid authentication token + Then the user should not be authorized Scenario: Getting an attachment previously stored with a desired name Given "usern...@domain.tld" mailbox "inbox" contains a message "1" with an attachment "2" http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java index 7d235a4..e1c3ba5 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java @@ -58,7 +58,7 @@ public class JMAPServer implements Configurable { .serveAsOneLevelTemplate(JMAPUrls.DOWNLOAD) .with(downloadServlet) .filterAsOneLevelTemplate(JMAPUrls.DOWNLOAD) - .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("GET").and("OPTIONS").only())) + .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only())) .only() .serve(JMAPUrls.UPLOAD) .with(uploadServlet) http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java index 7154a32..594bff3 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java @@ -65,8 +65,8 @@ public class SignedTokenFactory implements SimpleTokenFactory { .blobId(blobId) .expirationDate(expirationTime) .signature(signatureHandler.sign(Joiner.on(AttachmentAccessToken.SEPARATOR) - .join(username, - blobId, + .join(blobId, + username, DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(expirationTime)))) .build(); } http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java index 4d13c75..2188b1e 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java @@ -21,11 +21,15 @@ package org.apache.james.jmap.model; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.List; import java.util.Objects; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import com.google.common.collect.Iterables; public class AttachmentAccessToken implements SignedExpiringToken { @@ -34,7 +38,21 @@ public class AttachmentAccessToken implements SignedExpiringToken { public static Builder builder() { return new Builder(); } - + + public static AttachmentAccessToken from(String serializedAttachmentAccessToken, String blobId) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(serializedAttachmentAccessToken), "'AttachmentAccessToken' is mandatory"); + List<String> split = Splitter.on(SEPARATOR).splitToList(serializedAttachmentAccessToken); + Preconditions.checkArgument(split.size() == 3, "Wrong 'AttachmentAccessToken'"); + + String defaultValue = null; + return builder() + .blobId(blobId) + .username(Iterables.get(split, 0, defaultValue)) + .expirationDate(ZonedDateTime.parse(Iterables.get(split, 1, defaultValue))) + .signature(Iterables.get(split, 2, defaultValue)) + .build(); + } + public static class Builder { private String username; private String blobId; http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java index 371083f..dfe8c18 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java @@ -73,7 +73,6 @@ public class SignedTokenFactoryTest { public void generateAttachmentAccessTokenShouldHaveTheRightOutPut() throws Exception { zonedDateTimeProvider.setFixedDateTime(DATE); assertThat(toKenFactory.generateAttachmentAccessToken("user", "blobId").serialize()) - .isEqualTo("user_2011-12-03T10:20:30+01:00_UAmjTzvmmIwvE1Yw54tE7jC1Q2nCJ1l3XX1703kYmLIeOZe7fNSLM6V8CzPFEvZ+Y4H+UD4UTkNHbmgcPbxesITnby+UfT/tIiTppJhXJvtTxSoTy9vuAJrW9/kJh6CruqtSM+BUEkLKuuzJySmvDkaHSaXwot4egGXaJ9yHgjEh2PT3uA0O0JjRNB2x8oa370fFSZsT2QgXrqeqHWWO1j6IrAf4UcyhvjNkJBK9TVNubfqGKuCZ4dz2Rm/CUvp13CpzUoVqBS1nJ1VaIw94L2rX8RkAMTlV7AXKB3kPiBX7MdGp2NBiAUlYlOLjflYl8plnv/QrRCmfGxnsvv4WVQ=="); + .isEqualTo("user_2011-12-03T10:20:30+01:00_eSg1mVxMpqw5/u6wsTAatP7hoHDoI7blEW0hxGPrRMMj3hECT+YhbUCdhz9Lb4U+jsYPgNLDuAHwxin79xXfLoq0nVsogEE32svRYVvbaDpro+EOtkAHhYnYxWnAGxB/70u7Zyw0oYGmWOwkCkLDFsWKglMp9IUpOJQP50zbzbdW+4dKlAi/8VmN8jFyZx40envRbgEn4Q2QQbnUH/7F9+vdLIl+bAfcj6QlevqFRsUkmTZelkv1rtGUAvnPSBQL4TeBx5Qk/eEiw8IbB2lbCIAoIFZC6Vl8QOO5Y6LFzmqHL9i0BjvuoiZ8FKQS0pGd5CU6pwc7sv0xD82Vx1eFiw=="); } - } http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java index c371f0b..b31f0df 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java @@ -27,6 +27,7 @@ import java.time.format.DateTimeFormatter; import org.apache.james.jmap.FixedDateZonedDateTimeProvider; import org.apache.james.jmap.api.SimpleTokenManager.TokenStatus; +import org.apache.james.jmap.model.AttachmentAccessToken; import org.apache.james.jmap.model.ContinuationToken; import org.junit.Before; import org.junit.Test; @@ -168,4 +169,13 @@ public class SignedTokenManagerTest { ContinuationToken pirateContinuationToken = new ContinuationToken("user", DATE.plusMinutes(15), "fake"); assertThat(tokenManager.getValidity(pirateContinuationToken)).isEqualTo(TokenStatus.INVALID); } + + @Test + public void signedAttachmentAccessTokenShouldBeValidated() { + String blobId = "blobId"; + zonedDateTimeProvider.setFixedDateTime(DATE); + String serializedToken = tokenFactory.generateAttachmentAccessToken("user", blobId).serialize(); + + assertThat(tokenManager.isValid(AttachmentAccessToken.from(serializedToken, blobId))).isTrue(); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org