blob: 3c740020edad0d397d5d796ae2f34e8df058ffb2 [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
package org.apache.james.jmap.methods.integration;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import java.io.ByteArrayInputStream;
import java.util.Date;
import javax.mail.Flags;
import org.apache.james.GuiceJamesServer;
import org.apache.james.jmap.JmapAuthentication;
import org.apache.james.jmap.api.access.AccessToken;
import org.apache.james.mailbox.model.MailboxConstants;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.base.Charsets;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.http.ContentType;
public abstract class GetMailboxesMethodTest {
private static final String NAME = "[0][0]";
private static final String ARGUMENTS = "[0][1]";
protected abstract GuiceJamesServer createJmapServer();
private AccessToken accessToken;
private String username;
private GuiceJamesServer jmapServer;
@Before
public void setup() throws Throwable {
jmapServer = createJmapServer();
jmapServer.start();
RestAssured.requestSpecification = new RequestSpecBuilder()
.setContentType(ContentType.JSON)
.setAccept(ContentType.JSON)
.setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
.setPort(jmapServer.getJmapPort())
.build();
String domain = "domain.tld";
username = "username@" + domain;
String password = "password";
jmapServer.serverProbe().addDomain(domain);
jmapServer.serverProbe().addUser(username, password);
accessToken = JmapAuthentication.authenticateJamesUser(username, password);
}
@After
public void teardown() {
jmapServer.stop();
}
@Test
public void getMailboxesShouldErrorNotSupportedWhenRequestContainsNonNullAccountId() throws Exception {
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"accountId\": \"1\"}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("error"))
.body(ARGUMENTS + ".type", equalTo("Not yet implemented"));
}
@Test
public void getMailboxesShouldReturnEmptyWhenIdsDoesntMatch() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "name");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"ids\": [\"notAMailboxId\"]}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(0));
}
@Test
public void getMailboxesShouldReturnMailboxesWhenIdsMatch() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "myMailbox");
Mailbox mailbox = jmapServer.serverProbe().getMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
Mailbox mailbox2 = jmapServer.serverProbe().getMailbox(MailboxConstants.USER_NAMESPACE, username, "myMailbox");
String mailboxId = mailbox.getMailboxId().serialize();
String mailboxId2 = mailbox2.getMailboxId().serialize();
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\", \"" + mailboxId2 + "\"]}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(2))
.body(ARGUMENTS + ".list[0].id", equalTo(mailboxId))
.body(ARGUMENTS + ".list[1].id", equalTo(mailboxId2));
}
@Test
public void getMailboxesShouldReturnOnlyMatchingMailboxesWhenIdsGiven() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "myMailbox");
Mailbox mailbox = jmapServer.serverProbe().getMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
String mailboxId = mailbox.getMailboxId().serialize();
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"ids\": [\"" + mailboxId + "\"]}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(1))
.body(ARGUMENTS + ".list[0].id", equalTo(mailboxId));
}
@Test
public void getMailboxesShouldReturnEmptyWhenIdsIsEmpty() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"ids\": []}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", empty());
}
@Test
public void getMailboxesShouldReturnAllMailboxesWhenIdsIsNull() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "myMailbox");
Mailbox mailbox = jmapServer.serverProbe().getMailbox(MailboxConstants.USER_NAMESPACE, username, "INBOX");
Mailbox mailbox2 = jmapServer.serverProbe().getMailbox(MailboxConstants.USER_NAMESPACE, username, "myMailbox");
String mailboxId = mailbox.getMailboxId().serialize();
String mailboxId2 = mailbox2.getMailboxId().serialize();
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"ids\": null}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(2))
.body(ARGUMENTS + ".list[0].id", equalTo(mailboxId))
.body(ARGUMENTS + ".list[1].id", equalTo(mailboxId2));
}
@Test
public void getMailboxesShouldErrorInvalidArgumentsWhenRequestIsInvalid() throws Exception {
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"ids\": true}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("error"))
.body(ARGUMENTS + ".type", equalTo("invalidArguments"))
.body(ARGUMENTS + ".description", equalTo("Can not deserialize instance of java.util.ArrayList out of VALUE_TRUE token\n"
+ " at [Source: {\"ids\":true}; line: 1, column: 2] (through reference chain: org.apache.james.jmap.model.Builder[\"ids\"])"));
}
@Test
public void getMailboxesShouldReturnEmptyListWhenNoMailboxes() throws Exception {
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", empty());
}
@Test
public void getMailboxesShouldReturnDefaultMailboxesWhenAuthenticatedUserDoesntHaveAnAccountYet() throws Exception {
String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMzM3QGRvbWFpbi50bGQiLCJuYW1lIjoiTmV3IFVzZXIif"
+ "Q.fxNWNzksXyCij2ooVi-QfGe9vTicF2N9FDtWSJdjWTjhwoQ_i0dgiT8clp4dtOJzy78hB2UkAW-iq7z3PR_Gz0qFah7EbYoEs"
+ "5lQs1UlhNGCRTvIsyR8qHUXtA6emw9x0nuMnswtyXhzoA-cEHCArrMxMeWhTYi2l4od3G8Irrvu1Yc5hKLwLgPdnImbKyB5a89T"
+ "vzuZE8-FVyMmhlaJA2T1GpbsaUnfE1ki_bBzqMHTD_Ob7oSVzz2UOiOeL-ombn1X9GbYQ2I-Ob4V84WHONYxw0VjPHlj9saZ2n7"
+ "2RJTBsIo6flJT-MchaEvTYBvuV_wlCCQYjI1g7mdeD6aXfw";
given()
.header("Authorization", "Bearer " + token)
.body("[[\"getMailboxes\", {}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(3))
.body(ARGUMENTS + ".list.name", hasItems("INBOX", "Outbox", "Sent"));
}
@Test
public void getMailboxesShouldErrorWithBadJWTToken() {
String badAuthToken = "BADTOKENOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
"LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZ" +
"DN_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf" +
"49t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2" +
"qNOR8Q31ydinyqzXvCSzVJOf6T60-w";
given()
.header("Authorization", "Bearer " + badAuthToken)
.body("[[\"getMailboxes\", {}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(401);
}
@Test
public void getMailboxesShouldReturnMailboxesWhenAvailable() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "name");
jmapServer.serverProbe().appendMessage(username, new MailboxPath(MailboxConstants.USER_NAMESPACE, username, "name"),
new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list[0].name", equalTo("name"))
.body(ARGUMENTS + ".list[0].parentId", nullValue())
.body(ARGUMENTS + ".list[0].role", nullValue())
.body(ARGUMENTS + ".list[0].sortOrder", equalTo(1000))
.body(ARGUMENTS + ".list[0].mustBeOnlyMailbox", equalTo(false))
.body(ARGUMENTS + ".list[0].mayReadItems", equalTo(false))
.body(ARGUMENTS + ".list[0].mayAddItems", equalTo(false))
.body(ARGUMENTS + ".list[0].mayRemoveItems", equalTo(false))
.body(ARGUMENTS + ".list[0].mayCreateChild", equalTo(false))
.body(ARGUMENTS + ".list[0].mayRename", equalTo(false))
.body(ARGUMENTS + ".list[0].mayDelete", equalTo(false))
.body(ARGUMENTS + ".list[0].totalMessages", equalTo(1))
.body(ARGUMENTS + ".list[0].unreadMessages", equalTo(1))
.body(ARGUMENTS + ".list[0].unreadThreads", equalTo(0));
}
@Test
public void getMailboxesShouldReturnFilteredMailboxesPropertiesWhenRequestContainsFilterProperties() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "name");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"properties\" : [\"unreadMessages\", \"sortOrder\"]}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list[0].id", not(isEmptyOrNullString()))
.body(ARGUMENTS + ".list[0].name", nullValue())
.body(ARGUMENTS + ".list[0].parentId", nullValue())
.body(ARGUMENTS + ".list[0].role", nullValue())
.body(ARGUMENTS + ".list[0].sortOrder", equalTo(1000))
.body(ARGUMENTS + ".list[0].mustBeOnlyMailbox", nullValue())
.body(ARGUMENTS + ".list[0].mayReadItems", nullValue())
.body(ARGUMENTS + ".list[0].mayAddItems", nullValue())
.body(ARGUMENTS + ".list[0].mayRemoveItems", nullValue())
.body(ARGUMENTS + ".list[0].mayCreateChild", nullValue())
.body(ARGUMENTS + ".list[0].mayRename", nullValue())
.body(ARGUMENTS + ".list[0].mayDelete", nullValue())
.body(ARGUMENTS + ".list[0].totalMessages", nullValue())
.body(ARGUMENTS + ".list[0].unreadMessages", equalTo(0))
.body(ARGUMENTS + ".list[0].unreadThreads", nullValue());
}
@Test
public void getMailboxesShouldReturnIdWhenRequestContainsEmptyPropertyListFilter() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "name");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"properties\" : []}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list[0].id", not(isEmptyOrNullString()))
.body(ARGUMENTS + ".list[0].name", nullValue());
}
@Test
public void getMailboxesShouldIgnoreUnknownPropertiesWhenRequestContainsUnknownPropertyListFilter() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "name");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {\"properties\" : [\"unknown\"]}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list[0].id", not(isEmptyOrNullString()))
.body(ARGUMENTS + ".list[0].name", nullValue());
}
@Test
public void getMailboxesShouldReturnMailboxesWithSortOrder() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "inbox");
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "trash");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(2))
.body(ARGUMENTS + ".list[0].name", equalTo("inbox"))
.body(ARGUMENTS + ".list[0].sortOrder", equalTo(10))
.body(ARGUMENTS + ".list[1].name", equalTo("trash"))
.body(ARGUMENTS + ".list[1].sortOrder", equalTo(60));
}
@Test
public void getMailboxesShouldReturnMailboxesWithRolesInLowerCase() throws Exception {
jmapServer.serverProbe().createMailbox(MailboxConstants.USER_NAMESPACE, username, "outbox");
given()
.header("Authorization", accessToken.serialize())
.body("[[\"getMailboxes\", {}, \"#0\"]]")
.when()
.post("/jmap")
.then()
.statusCode(200)
.body(NAME, equalTo("mailboxes"))
.body(ARGUMENTS + ".list", hasSize(1))
.body(ARGUMENTS + ".list[0].role", equalTo("outbox"));
}
}