Repository: james-project Updated Branches: refs/heads/master 6a8b56bf0 -> 5d3bedee1
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java new file mode 100644 index 0000000..79a6915 --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java @@ -0,0 +1,129 @@ +/**************************************************************** + * 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.webadmin.routes; + +import javax.inject.Inject; + +import org.apache.james.webadmin.Constants; +import org.apache.james.webadmin.Routes; +import org.apache.james.webadmin.service.UserMailboxesService; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.apache.james.webadmin.utils.MailboxHaveChildrenException; +import org.apache.james.webadmin.validation.MailboxName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import spark.Service; + +public class UserMailboxesRoutes implements Routes { + + private static final Logger LOGGER = LoggerFactory.getLogger(UserMailboxesRoutes.class); + + public static final String MAILBOX_NAME = ":mailboxName"; + public static final String MAILBOXES = "mailboxes"; + private static final String USER_NAME = ":userName"; + public static final String USERS_BASE = "/users"; + public static final String USER_MAILBOXES_BASE = USERS_BASE + Constants.SEPARATOR + USER_NAME + Constants.SEPARATOR + MAILBOXES; + public static final String SPECIFIC_MAILBOX = USER_MAILBOXES_BASE + Constants.SEPARATOR + MAILBOX_NAME; + + private final UserMailboxesService userMailboxesService; + private final JsonTransformer jsonTransformer; + + @Inject + public UserMailboxesRoutes(UserMailboxesService userMailboxesService, JsonTransformer jsonTransformer) { + this.userMailboxesService = userMailboxesService; + this.jsonTransformer = jsonTransformer; + } + + @Override + public void define(Service service) { + + service.put(SPECIFIC_MAILBOX, (request, response) -> { + try { + userMailboxesService.createMailbox(request.params(USER_NAME), new MailboxName(request.params(MAILBOX_NAME))); + response.status(204); + } catch (IllegalStateException e) { + LOGGER.info("Invalid put on user mailbox", e); + response.status(404); + } catch (IllegalArgumentException e) { + LOGGER.info("Attempt to create an invalid mailbox"); + response.status(400); + } + return Constants.EMPTY_BODY; + }); + + service.delete(SPECIFIC_MAILBOX, (request, response) -> { + try { + userMailboxesService.deleteMailbox(request.params(USER_NAME), new MailboxName(request.params(MAILBOX_NAME))); + response.status(204); + } catch (IllegalStateException e) { + LOGGER.info("Invalid delete on user mailbox", e); + response.status(404); + } catch (MailboxHaveChildrenException e) { + LOGGER.info("Attempt to delete a mailbox with children"); + response.status(409); + } catch (IllegalArgumentException e) { + LOGGER.info("Attempt to create an invalid mailbox"); + response.status(400); + } + return Constants.EMPTY_BODY; + }); + + service.delete(USER_MAILBOXES_BASE, (request, response) -> { + try { + userMailboxesService.deleteMailboxes(request.params(USER_NAME)); + response.status(204); + } catch (IllegalStateException e) { + LOGGER.info("Invalid delete on user mailboxes", e); + response.status(404); + } + return Constants.EMPTY_BODY; + }); + + service.get(SPECIFIC_MAILBOX, (request, response) -> { + try { + if (userMailboxesService.testMailboxExists(request.params(USER_NAME), new MailboxName(request.params(MAILBOX_NAME)))) { + response.status(204); + } else { + response.status(404); + } + } catch (IllegalStateException e) { + LOGGER.info("Invalid get on user mailbox", e); + response.status(404); + } catch (IllegalArgumentException e) { + LOGGER.info("Attempt to create an invalid mailbox"); + response.status(400); + } + return Constants.EMPTY_BODY; + }); + + service.get(USER_MAILBOXES_BASE, (request, response) -> { + response.status(200); + try { + return userMailboxesService.listMailboxes(request.params(USER_NAME)); + } catch (IllegalStateException e) { + LOGGER.info("Invalid get on user mailboxes", e); + response.status(404); + return Constants.EMPTY_BODY; + } + }, jsonTransformer); + + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java new file mode 100644 index 0000000..469bdfb --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java @@ -0,0 +1,143 @@ +/**************************************************************** + * 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.webadmin.service; + +import java.util.List; +import java.util.stream.Stream; + +import javax.inject.Inject; + +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.exception.MailboxExistsException; +import org.apache.james.mailbox.exception.MailboxNotFoundException; +import org.apache.james.mailbox.model.MailboxMetaData; +import org.apache.james.mailbox.model.MailboxPath; +import org.apache.james.mailbox.model.MailboxQuery; +import org.apache.james.user.api.UsersRepository; +import org.apache.james.user.api.UsersRepositoryException; +import org.apache.james.webadmin.dto.MailboxResponse; +import org.apache.james.webadmin.utils.MailboxHaveChildrenException; +import org.apache.james.webadmin.validation.MailboxName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.fge.lambdas.Throwing; +import com.github.steveash.guavate.Guavate; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; + + +public class UserMailboxesService { + + private static final Logger LOGGER = LoggerFactory.getLogger(UserMailboxesService.class); + private static final String USER_NAME = "webAdmin"; + + private final MailboxManager mailboxManager; + private final UsersRepository usersRepository; + + @Inject + public UserMailboxesService(MailboxManager mailboxManager, UsersRepository usersRepository) { + this.mailboxManager = mailboxManager; + this.usersRepository = usersRepository; + } + + public void createMailbox(String username, MailboxName mailboxName) throws MailboxException, UsersRepositoryException { + usernamePreconditions(username); + MailboxSession mailboxSession = mailboxManager.createSystemSession(USER_NAME, LOGGER); + try { + mailboxManager.createMailbox( + convertToMailboxPath(username, mailboxName.asString(), mailboxSession), + mailboxSession); + } catch (MailboxExistsException e) { + LOGGER.info("Attempt to create mailbox {} for user {} that already exists", mailboxName, username); + } + } + + public void deleteMailboxes(String username) throws MailboxException, UsersRepositoryException { + usernamePreconditions(username); + MailboxSession mailboxSession = mailboxManager.createSystemSession(USER_NAME, LOGGER); + listUserMailboxes(username, mailboxSession) + .map(MailboxMetaData::getPath) + .forEach(Throwing.consumer(mailboxPath -> deleteMailbox(mailboxSession, mailboxPath))); + } + + public List<MailboxResponse> listMailboxes(String username) throws MailboxException, UsersRepositoryException { + usernamePreconditions(username); + MailboxSession mailboxSession = mailboxManager.createSystemSession(USER_NAME, LOGGER); + return listUserMailboxes(username, mailboxSession) + .map(mailboxMetaData -> new MailboxResponse(mailboxMetaData.getPath().getName())) + .collect(Guavate.toImmutableList()); + } + + public boolean testMailboxExists(String username, MailboxName mailboxName) throws MailboxException, UsersRepositoryException { + usernamePreconditions(username); + MailboxSession mailboxSession = mailboxManager.createSystemSession(USER_NAME, LOGGER); + return mailboxManager.mailboxExists( + convertToMailboxPath(username, mailboxName.asString(), mailboxSession), + mailboxSession); + } + + public void deleteMailbox(String username, MailboxName mailboxName) throws MailboxException, UsersRepositoryException, MailboxHaveChildrenException { + usernamePreconditions(username); + MailboxSession mailboxSession = mailboxManager.createSystemSession(USER_NAME, LOGGER); + MailboxPath mailboxPath = convertToMailboxPath(username, mailboxName.asString(), mailboxSession); + listChildren(mailboxPath, mailboxSession) + .forEach(Throwing.consumer(path -> deleteMailbox(mailboxSession, path))); + } + + private Stream<MailboxPath> listChildren(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException { + return mailboxManager.search(createUserMailboxesQuery(mailboxPath.getUser()), mailboxSession) + .stream() + .map(MailboxMetaData::getPath) + .filter(path -> path.getHierarchyLevels(mailboxSession.getPathDelimiter()).contains(mailboxPath)); + } + + private void deleteMailbox(MailboxSession mailboxSession, MailboxPath mailboxPath) throws MailboxException { + try { + mailboxManager.deleteMailbox(mailboxPath, mailboxSession); + } catch (MailboxNotFoundException e) { + LOGGER.info("Attempt to delete mailbox {} for user {} that does not exists", mailboxPath.getName(), mailboxPath.getUser()); + } + } + + private void usernamePreconditions(String username) throws UsersRepositoryException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(username)); + Preconditions.checkState(usersRepository.contains(username)); + } + + private MailboxPath convertToMailboxPath(String username, String mailboxName, MailboxSession mailboxSession) { + return new MailboxPath(mailboxSession.getPersonalSpace(), username, mailboxName); + } + + private Stream<MailboxMetaData> listUserMailboxes(String username, MailboxSession mailboxSession) throws MailboxException { + return mailboxManager.search(createUserMailboxesQuery(username), mailboxSession) + .stream(); + } + + private MailboxQuery createUserMailboxesQuery(String username) { + return MailboxQuery.builder() + .username(username) + .privateUserMailboxes() + .build(); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/utils/MailboxHaveChildrenException.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/utils/MailboxHaveChildrenException.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/utils/MailboxHaveChildrenException.java new file mode 100644 index 0000000..ae8213e --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/utils/MailboxHaveChildrenException.java @@ -0,0 +1,27 @@ +/**************************************************************** + * 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.webadmin.utils; + +public class MailboxHaveChildrenException extends Exception { + + public MailboxHaveChildrenException(String mailboxName) { + super(mailboxName + "have children"); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/MailboxName.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/MailboxName.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/MailboxName.java new file mode 100644 index 0000000..fdd079d --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/MailboxName.java @@ -0,0 +1,40 @@ +/**************************************************************** + * 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.webadmin.validation; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; + +public class MailboxName { + + public static final CharMatcher INVALID_CHARS_MATCHER = CharMatcher.anyOf("%*&#"); + private final String mailboxName; + + public MailboxName(String mailboxName) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(mailboxName)); + Preconditions.checkArgument(INVALID_CHARS_MATCHER.matchesNoneOf(mailboxName)); + this.mailboxName = mailboxName; + } + + public String asString() { + return mailboxName; + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java new file mode 100644 index 0000000..34df209 --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java @@ -0,0 +1,59 @@ +/**************************************************************** + * 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.webadmin.dto; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class QuotaRequestTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void parseShouldThrowWhenNotANumber() { + expectedException.expect(NumberFormatException.class); + + QuotaRequest.parse("invalid"); + } + + @Test + public void parseShouldThrowOnNegativeNumber() { + expectedException.expect(IllegalArgumentException.class); + + QuotaRequest.parse("-1"); + } + + @Test + public void parseShouldParseZero() { + assertThat(QuotaRequest.parse("0").getValue()) + .isEqualTo(0); + } + + @Test + public void parseShouldParsePositiveValue() { + assertThat(QuotaRequest.parse("42").getValue()) + .isEqualTo(42); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java new file mode 100644 index 0000000..89f9fc0 --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java @@ -0,0 +1,261 @@ +/**************************************************************** + * 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.webadmin.routes; + +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.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.is; + +import org.apache.james.mailbox.inmemory.quota.InMemoryPerUserMaxQuotaManager; +import org.apache.james.mailbox.model.Quota; +import org.apache.james.metrics.logger.DefaultMetricFactory; +import org.apache.james.webadmin.WebAdminServer; +import org.apache.james.webadmin.utils.JsonTransformer; +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 class GlobalQuotaRoutesTest { + + private WebAdminServer webAdminServer; + private InMemoryPerUserMaxQuotaManager maxQuotaManager; + + @Before + public void setUp() throws Exception { + maxQuotaManager = new InMemoryPerUserMaxQuotaManager(); + webAdminServer = new WebAdminServer( + new DefaultMetricFactory(), + new GlobalQuotaRoutes(maxQuotaManager, new JsonTransformer())); + webAdminServer.configure(NO_CONFIGURATION); + webAdminServer.await(); + + RestAssured.requestSpecification = new RequestSpecBuilder() + .setContentType(ContentType.JSON) + .setAccept(ContentType.JSON) + .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8))) + .setPort(webAdminServer.getPort().toInt()) + .build(); + } + + @After + public void stop() { + webAdminServer.destroy(); + } + + @Test + public void getCountQuotaCountShouldReturnUnlimitedByDefault() { + given() + .get(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(200) + .body(is(String.valueOf(Quota.UNLIMITED))); + } + + @Test + public void getCountShouldReturnStoredValue() throws Exception{ + int value = 42; + maxQuotaManager.setDefaultMaxMessage(value); + + given() + .get(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(200) + .body(is(String.valueOf(value))); + } + + @Test + public void putCountShouldRejectInvalid() throws Exception { + given() + .body("invalid") + .put(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(400); + } + + @Test + public void putCountShouldRejectNegative() throws Exception { + given() + .body("-1") + .put(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(400); + } + + @Test + public void putCountShouldAcceptValidValue() throws Exception { + given() + .body("42") + .put(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(204); + + assertThat(maxQuotaManager.getDefaultMaxMessage()).isEqualTo(42); + } + + @Test + public void deleteCountShouldSetQuotaToUnlimited() throws Exception { + maxQuotaManager.setDefaultMaxMessage(42); + + given() + .delete(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(204); + + assertThat(maxQuotaManager.getDefaultMaxMessage()).isEqualTo(Quota.UNLIMITED); + } + + @Test + public void getSizeQuotaCountShouldReturnUnlimitedByDefault() { + given() + .get(GlobalQuotaRoutes.SIZE_ENDPOINT) + .then() + .statusCode(200) + .body(is(String.valueOf(Quota.UNLIMITED))); + } + + @Test + public void getSizeShouldReturnStoredValue() throws Exception{ + int value = 42; + maxQuotaManager.setDefaultMaxStorage(value); + + given() + .get(GlobalQuotaRoutes.SIZE_ENDPOINT) + .then() + .statusCode(200) + .body(is(String.valueOf(value))); + } + + @Test + public void putSizeShouldRejectInvalid() throws Exception { + given() + .body("invalid") + .put(GlobalQuotaRoutes.SIZE_ENDPOINT) + .then() + .statusCode(400); + } + + @Test + public void putSizeShouldRejectNegative() throws Exception { + given() + .body("-1") + .put(GlobalQuotaRoutes.SIZE_ENDPOINT) + .then() + .statusCode(400); + } + + @Test + public void putSizeShouldAcceptValidValue() throws Exception { + given() + .body("42") + .put(GlobalQuotaRoutes.SIZE_ENDPOINT) + .then() + .statusCode(204); + + assertThat(maxQuotaManager.getDefaultMaxStorage()).isEqualTo(42); + } + + @Test + public void deleteSizeShouldSetQuotaToUnlimited() throws Exception { + maxQuotaManager.setDefaultMaxStorage(42); + + given() + .delete(GlobalQuotaRoutes.COUNT_ENDPOINT) + .then() + .statusCode(204); + + assertThat(maxQuotaManager.getDefaultMaxMessage()).isEqualTo(Quota.UNLIMITED); + } + + @Test + public void getQuotaShouldReturnBothWhenValueSpecified() throws Exception { + maxQuotaManager.setDefaultMaxStorage(42); + maxQuotaManager.setDefaultMaxMessage(52); + + given() + .get(GlobalQuotaRoutes.QUOTA_ENDPOINT) + .then() + .statusCode(200) + .body(is("{\"count\":52,\"size\":42}")); + } + + @Test + public void getQuotaShouldReturnBothDefaultValues() throws Exception { + given() + .get(GlobalQuotaRoutes.QUOTA_ENDPOINT) + .then() + .statusCode(200) + .body(is("{\"count\":-1,\"size\":-1}")); + } + + @Test + public void getQuotaShouldReturnBothWhenNoCount() throws Exception { + maxQuotaManager.setDefaultMaxStorage(42); + + given() + .get(GlobalQuotaRoutes.QUOTA_ENDPOINT) + .then() + .statusCode(200) + .body(is("{\"count\":-1,\"size\":42}")); + } + + @Test + public void getQuotaShouldReturnBothWhenNoSize() throws Exception { + maxQuotaManager.setDefaultMaxMessage(42); + + given() + .get(GlobalQuotaRoutes.QUOTA_ENDPOINT) + .then() + .statusCode(200) + .body(is("{\"count\":42,\"size\":-1}")); + } + + @Test + public void putQuotaShouldUpdateBothQuota() throws Exception { + given() + .body("{\"count\":52,\"size\":42}") + .put(GlobalQuotaRoutes.QUOTA_ENDPOINT) + .then() + .statusCode(204); + + assertThat(maxQuotaManager.getDefaultMaxMessage()).isEqualTo(52); + assertThat(maxQuotaManager.getDefaultMaxStorage()).isEqualTo(42); + } + + @Test + public void putQuotaShouldBeAbleToRemoveBothQuota() throws Exception { + given() + .body("{\"count\":-1,\"size\":-1}") + .put(GlobalQuotaRoutes.QUOTA_ENDPOINT) + .then() + .statusCode(204); + + assertThat(maxQuotaManager.getDefaultMaxMessage()).isEqualTo(Quota.UNLIMITED); + assertThat(maxQuotaManager.getDefaultMaxStorage()).isEqualTo(Quota.UNLIMITED); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java new file mode 100644 index 0000000..d19542f --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java @@ -0,0 +1,780 @@ +/**************************************************************** + * 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.webadmin.routes; + +import static com.jayway.restassured.RestAssured.when; +import static com.jayway.restassured.RestAssured.with; +import static com.jayway.restassured.config.EncoderConfig.encoderConfig; +import static com.jayway.restassured.config.RestAssuredConfig.newConfig; +import static org.apache.james.webadmin.Constants.SEPARATOR; +import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION; +import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USERS_BASE; +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; +import org.apache.james.mailbox.acl.UnionMailboxACLResolver; +import org.apache.james.mailbox.exception.MailboxException; +import org.apache.james.mailbox.exception.MailboxExistsException; +import org.apache.james.mailbox.exception.MailboxNotFoundException; +import org.apache.james.mailbox.inmemory.InMemoryId; +import org.apache.james.mailbox.inmemory.InMemoryMailboxManager; +import org.apache.james.mailbox.inmemory.InMemoryMailboxSessionMapperFactory; +import org.apache.james.mailbox.model.MailboxId; +import org.apache.james.mailbox.model.MailboxPath; +import org.apache.james.mailbox.model.MailboxQuery; +import org.apache.james.mailbox.model.MessageId; +import org.apache.james.mailbox.store.FakeAuthorizator; +import org.apache.james.mailbox.store.JVMMailboxPathLocker; +import org.apache.james.mailbox.store.SimpleMailboxMetaData; +import org.apache.james.mailbox.store.mail.model.DefaultMessageId; +import org.apache.james.mailbox.store.mail.model.impl.MessageParser; +import org.apache.james.metrics.logger.DefaultMetricFactory; +import org.apache.james.user.api.UsersRepository; +import org.apache.james.webadmin.WebAdminServer; +import org.apache.james.webadmin.service.UserMailboxesService; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableList; +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.builder.RequestSpecBuilder; +import com.jayway.restassured.http.ContentType; + +import de.bechte.junit.runners.context.HierarchicalContextRunner; + +@RunWith(HierarchicalContextRunner.class) +public class UserMailboxesRoutesTest { + + public static final String USERNAME = "username"; + public static final String MAILBOX_NAME = "myMailboxName"; + private WebAdminServer webAdminServer; + private UsersRepository usersRepository; + + private void createServer(MailboxManager mailboxManager) throws Exception { + usersRepository = mock(UsersRepository.class); + when(usersRepository.contains(USERNAME)).thenReturn(true); + + webAdminServer = new WebAdminServer( + new DefaultMetricFactory(), + new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer())); + webAdminServer.configure(NO_CONFIGURATION); + webAdminServer.await(); + + RestAssured.requestSpecification = new RequestSpecBuilder() + .setContentType(ContentType.JSON) + .setAccept(ContentType.JSON) + .setBasePath(USERS_BASE + SEPARATOR + USERNAME + SEPARATOR + UserMailboxesRoutes.MAILBOXES) + .setPort(webAdminServer.getPort().toInt()) + .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8))) + .build(); + } + + @After + public void tearDown() { + webAdminServer.destroy(); + } + + public class NormalBehaviour { + + @Before + public void setUp() throws Exception { + MessageId.Factory messageIdFactory = new DefaultMessageId.Factory(); + InMemoryMailboxManager mailboxManager = new InMemoryMailboxManager(new InMemoryMailboxSessionMapperFactory(), + (userid, passwd) -> true, + FakeAuthorizator.defaultReject(), + new JVMMailboxPathLocker(), + new UnionMailboxACLResolver(), + new SimpleGroupMembershipResolver(), + new MessageParser(), + messageIdFactory); + mailboxManager.init(); + + createServer(mailboxManager); + } + + @Test + public void getMailboxesShouldUserErrorFoundWithNonExistingUser() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .get() + .then() + .statusCode(404); + } + + @Test + public void getShouldReturnNotFoundWithNonExistingUser() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .get(MAILBOX_NAME) + .then() + .statusCode(404); + } + + @Test + public void putShouldReturnNotFoundWithNonExistingUser() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(404); + } + + @Test + public void deleteShouldReturnNotFoundWithNonExistingUser() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(404); + } + + @Test + public void getShouldReturnUserErrorWithInvalidWildcardMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .get(MAILBOX_NAME + "*") + .then() + .statusCode(400); + } + + @Test + public void putShouldReturnUserErrorWithInvalidWildcardMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME+ "*") + .then() + .statusCode(400); + } + + @Test + public void deleteShouldReturnUserErrorWithInvalidWildcardMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME + "*") + .then() + .statusCode(400); + } + + @Test + public void getShouldReturnUserErrorWithInvalidPercentMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .get(MAILBOX_NAME + "%") + .then() + .statusCode(400); + } + + @Test + public void putShouldReturnUserErrorWithInvalidPercentMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME+ "%") + .then() + .statusCode(400); + } + + @Test + public void deleteShouldReturnUserErrorWithInvalidPercentMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME + "%") + .then() + .statusCode(400); + } + + @Test + public void getShouldReturnUserErrorWithInvalidSharpMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .get(MAILBOX_NAME + "#") + .then() + .statusCode(400); + } + + @Test + public void putShouldReturnUserErrorWithInvalidSharpMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME+ "#") + .then() + .statusCode(400); + } + + @Test + public void deleteShouldReturnUserErrorWithInvalidSharpMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME + "#") + .then() + .statusCode(400); + } + + @Test + public void getShouldReturnUserErrorWithInvalidAndMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .get(MAILBOX_NAME + "&") + .then() + .statusCode(400); + } + + @Test + public void putShouldReturnUserErrorWithInvalidAndMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME+ "&") + .then() + .statusCode(400); + } + + @Test + public void deleteShouldReturnUserErrorWithInvalidAndMailboxName() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .put(MAILBOX_NAME + "&") + .then() + .statusCode(400); + } + + @Test + public void deleteMailboxesShouldReturnUserErrorWithNonExistingUser() throws Exception { + when(usersRepository.contains(USERNAME)).thenReturn(false); + + when() + .delete() + .then() + .statusCode(404); + } + + @Test + public void getMailboxesShouldReturnEmptyListByDefault() { + when() + .get() + .then() + .statusCode(200) + .body(is("[]")); + } + + @Test + public void putShouldReturnNotFoundWhenNoMailboxName() { + when() + .put() + .then() + .statusCode(404); + } + + @Test + public void putShouldReturnNotFoundWhenJustSeparator() { + when() + .put(SEPARATOR) + .then() + .statusCode(404); + } + + @Test + public void putShouldReturnOk() { + when() + .put(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void putShouldReturnOkWhenIssuedTwoTimes() { + with() + .put(MAILBOX_NAME); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void putShouldAddAMailbox() { + with() + .put(MAILBOX_NAME); + + when() + .get() + .then() + .statusCode(200) + .body(is("[{\"mailboxName\":\"myMailboxName\"}]")); + } + + @Test + public void getShouldReturnNotFoundWhenMailboxDoesNotExist() { + when() + .get(MAILBOX_NAME) + .then() + .statusCode(404); + } + + @Test + public void getShouldReturnOkWhenMailboxExists() { + with() + .put(MAILBOX_NAME); + + when() + .get(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void deleteShouldReturnOkWhenMailboxDoesNotExist() { + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void deleteShouldReturnOkWhenMailboxExists() { + with() + .put(MAILBOX_NAME); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void deleteShouldRemoveMailbox() { + with() + .put(MAILBOX_NAME); + + with() + .delete(MAILBOX_NAME); + + when() + .get(MAILBOX_NAME) + .then() + .statusCode(404); + } + + @Test + public void deleteMailboxesShouldReturnOkWhenNoMailboxes() { + when() + .delete() + .then() + .statusCode(204); + } + + @Test + public void deleteMailboxesShouldReturnOkWhenMailboxes() { + with() + .put(MAILBOX_NAME); + + when() + .delete() + .then() + .statusCode(204); + } + + @Test + public void deleteMailboxesShouldRemoveAllUserMailboxes() { + with() + .put(MAILBOX_NAME); + + with() + .put("otherMailbox"); + + with() + .delete(); + + when() + .get() + .then() + .statusCode(200) + .body(is("[]")); + } + + @Test + public void deleteShouldReturnOkWhenMailboxHasChildren() { + with() + .put(MAILBOX_NAME); + + with() + .put(MAILBOX_NAME + ".child"); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void deleteShouldDeleteAMailboxAndItsChildren() { + with() + .put(MAILBOX_NAME); + + with() + .put(MAILBOX_NAME + ".child"); + + with() + .delete(MAILBOX_NAME); + + when() + .get() + .then() + .statusCode(200) + .body(is("[]")); + } + + @Test + public void deleteShouldNotDeleteUnrelatedMailbox() { + String mailboxName = MAILBOX_NAME + "!child"; + with() + .put(MAILBOX_NAME); + + with() + .put(mailboxName); + + with() + .delete(MAILBOX_NAME); + + when() + .get() + .then() + .statusCode(200) + .body(is("[{\"mailboxName\":\"" + mailboxName + "\"}]")); + } + + @Test + public void deleteShouldReturnOkWhenDeletingChildMailboxes() { + with() + .put(MAILBOX_NAME); + + with() + .put(MAILBOX_NAME + ".child"); + + when() + .delete(MAILBOX_NAME + ".child") + .then() + .statusCode(204); + } + + @Test + public void deleteShouldBeAbleToRemoveChildMailboxes() { + with() + .put(MAILBOX_NAME); + + with() + .put(MAILBOX_NAME + ".child"); + + with() + .delete(MAILBOX_NAME + ".child"); + + when() + .get() + .then() + .statusCode(200) + .body(is("[{\"mailboxName\":\"myMailboxName\"}]")); + } + } + + public class ExceptionHandling { + + private MailboxManager mailboxManager; + + @Before + public void setUp() throws Exception { + mailboxManager = mock(MailboxManager.class); + when(mailboxManager.createSystemSession(any(), any())).thenReturn(mock(MailboxSession.class)); + + createServer(mailboxManager); + } + + @Test + public void putShouldGenerateInternalErrorOnUnknownException() throws Exception { + doThrow(new RuntimeException()).when(mailboxManager).createMailbox(any(), any()); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void putShouldGenerateInternalErrorOnUnknownMailboxException() throws Exception { + doThrow(new MailboxException()).when(mailboxManager).createMailbox(any(), any()); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void putShouldReturnOkOnMailboxExists() throws Exception { + doThrow(new MailboxExistsException(MAILBOX_NAME)).when(mailboxManager).createMailbox(any(), any()); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void deleteShouldGenerateInternalErrorOnUnknownExceptionOnDelete() throws Exception { + MailboxId mailboxId = InMemoryId.of(12); + when(mailboxManager.search(any(MailboxQuery.class), any())) + .thenReturn( + ImmutableList.of( + new SimpleMailboxMetaData( + new MailboxPath("#private", USERNAME, MAILBOX_NAME), mailboxId, '.'))); + doThrow(new RuntimeException()).when(mailboxManager).deleteMailbox(any(), any()); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void deleteShouldGenerateInternalErrorOnUnknownExceptionOnSearch() throws Exception { + when(mailboxManager.search(any(MailboxQuery.class), any())).thenThrow(new RuntimeException()); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void deleteShouldGenerateInternalErrorOnUnknownMailboxExceptionOnDelete() throws Exception { + MailboxId mailboxId = InMemoryId.of(12); + when(mailboxManager.search(any(MailboxQuery.class), any())) + .thenReturn( + ImmutableList.of( + new SimpleMailboxMetaData(new MailboxPath("#private", USERNAME, MAILBOX_NAME), mailboxId, '.'))); + doThrow(new MailboxException()).when(mailboxManager).deleteMailbox(any(), any()); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void deleteShouldGenerateInternalErrorOnUnknownMailboxExceptionOnSearch() throws Exception { + when(mailboxManager.search(any(MailboxQuery.class), any())).thenThrow(new MailboxException()); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void deleteShouldReturnOkOnMailboxDoesNotExists() throws Exception { + doThrow(new MailboxNotFoundException(MAILBOX_NAME)).when(mailboxManager).deleteMailbox(any(), any()); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(204); + } + + @Test + public void deleteShouldGenerateInternalErrorOnUnknownExceptionWhenListingMailboxes() throws Exception { + doThrow(new RuntimeException()).when(mailboxManager).search(any(MailboxQuery.class), any()); + + when() + .delete() + .then() + .statusCode(500); + } + + @Test + public void deleteShouldGenerateInternalErrorOnMailboxExceptionWhenListingMailboxes() throws Exception { + doThrow(new MailboxException()).when(mailboxManager).search(any(MailboxQuery.class), any()); + + when() + .delete() + .then() + .statusCode(500); + } + + + @Test + public void deleteShouldGenerateInternalErrorOnUnknownExceptionWhenRemovingMailboxes() throws Exception { + MailboxId mailboxId = InMemoryId.of(12); + when(mailboxManager.search(any(MailboxQuery.class), any())) + .thenReturn( + ImmutableList.of( + new SimpleMailboxMetaData(new MailboxPath("#private", USERNAME, "any"), mailboxId, '.'))); + doThrow(new RuntimeException()).when(mailboxManager).deleteMailbox(any(), any()); + + when() + .delete() + .then() + .statusCode(500); + } + + @Test + public void deleteShouldReturnOkOnMailboxNotFoundExceptionWhenRemovingMailboxes() throws Exception { + MailboxId mailboxId = InMemoryId.of(12); + when(mailboxManager.search(any(MailboxQuery.class), any())) + .thenReturn( + ImmutableList.of(new SimpleMailboxMetaData(new MailboxPath("#private", USERNAME, "any"), mailboxId, '.'))); + doThrow(new MailboxNotFoundException("any")).when(mailboxManager).deleteMailbox(any(), any()); + + when() + .delete() + .then() + .statusCode(204); + } + + @Test + public void deleteShouldReturnInternalErrorOnMailboxExceptionWhenRemovingMailboxes() throws Exception { + MailboxId mailboxId = InMemoryId.of(12); + when(mailboxManager.search(any(MailboxQuery.class), any())) + .thenReturn( + ImmutableList.of(new SimpleMailboxMetaData(new MailboxPath("#private", USERNAME, "any"), mailboxId, '.'))); + doThrow(new MailboxException()).when(mailboxManager).deleteMailbox(any(), any()); + + when() + .delete() + .then() + .statusCode(500); + } + + @Test + public void getShouldGenerateInternalErrorOnUnknownException() throws Exception { + doThrow(new RuntimeException()).when(mailboxManager).mailboxExists(any(), any()); + + when() + .get(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void getShouldGenerateInternalErrorOnUnknownMailboxException() throws Exception { + doThrow(new MailboxException()).when(mailboxManager).mailboxExists(any(), any()); + + when() + .get(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void getMailboxesShouldGenerateInternalErrorOnUnknownException() throws Exception { + doThrow(new RuntimeException()).when(mailboxManager).search(any(MailboxQuery.class), any()); + + when() + .get() + .then() + .statusCode(500); + } + + @Test + public void getMailboxesShouldGenerateInternalErrorOnUnknownMailboxException() throws Exception { + doThrow(new MailboxException()).when(mailboxManager).search(any(MailboxQuery.class), any()); + + when() + .get() + .then() + .statusCode(500); + } + + @Test + public void getMailboxesShouldGenerateInternalErrorOnRepositoryException() throws Exception { + doThrow(new RuntimeException()).when(usersRepository).contains(USERNAME); + + when() + .get() + .then() + .statusCode(500); + } + + @Test + public void getShouldGenerateInternalErrorOnRepositoryException() throws Exception { + doThrow(new RuntimeException()).when(usersRepository).contains(USERNAME); + + when() + .get(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void putShouldGenerateInternalErrorOnRepositoryException() throws Exception { + doThrow(new RuntimeException()).when(usersRepository).contains(USERNAME); + + when() + .put(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void deleteShouldGenerateInternalErrorOnRepositoryException() throws Exception { + doThrow(new RuntimeException()).when(usersRepository).contains(USERNAME); + + when() + .delete(MAILBOX_NAME) + .then() + .statusCode(500); + } + + @Test + public void deleteMailboxesShouldGenerateInternalErrorOnRepositoryException() throws Exception { + doThrow(new RuntimeException()).when(usersRepository).contains(USERNAME); + + when() + .delete() + .then() + .statusCode(500); + } + + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org