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 c1d00d110362c3991d3c5655f8dd31e612f4b6f8 Author: Benoit Tellier <btell...@linagora.com> AuthorDate: Wed Dec 18 10:05:32 2019 +0700 JAMES-2993 Expose projecting fixing endpoint over memory --- .../org/apache/james/CassandraJamesServerMain.java | 2 - .../java/org/apache/james/JPAJamesServerMain.java | 2 - .../org/apache/james/MemoryJamesServerMain.java | 2 +- .../james/modules/server/MailboxRoutesModule.java | 8 + .../james/modules/server/ReIndexingModule.java | 16 + .../RabbitMQWebAdminServerIntegrationTest.java | 1 - .../integration/WebAdminServerIntegrationTest.java | 3 +- .../james/webadmin/routes/MailboxesRoutes.java | 422 +++++++++++---------- .../routes/MailboxesRoutesNoTasksTest.java | 102 +++++ .../james/webadmin/routes/MailboxesRoutesTest.java | 18 +- 10 files changed, 369 insertions(+), 207 deletions(-) diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java index f62e1bd..05e07ea 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java @@ -63,7 +63,6 @@ import org.apache.james.modules.server.JmapTasksModule; import org.apache.james.modules.server.MailQueueRoutesModule; import org.apache.james.modules.server.MailRepositoriesRoutesModule; import org.apache.james.modules.server.MailboxRoutesModule; -import org.apache.james.modules.server.MailboxesRoutesModule; import org.apache.james.modules.server.MessagesRoutesModule; import org.apache.james.modules.server.ReIndexingModule; import org.apache.james.modules.server.SieveRoutesModule; @@ -89,7 +88,6 @@ public class CassandraJamesServerMain { new DeletedMessageVaultRoutesModule(), new DLPRoutesModule(), new JmapTasksModule(), - new MailboxesRoutesModule(), new MailboxRoutesModule(), new MailQueueRoutesModule(), new MailRepositoriesRoutesModule(), diff --git a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java index b4f2b64..d03f0cf 100644 --- a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java +++ b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java @@ -41,7 +41,6 @@ import org.apache.james.modules.server.JMXServerModule; import org.apache.james.modules.server.MailQueueRoutesModule; import org.apache.james.modules.server.MailRepositoriesRoutesModule; import org.apache.james.modules.server.MailboxRoutesModule; -import org.apache.james.modules.server.MailboxesRoutesModule; import org.apache.james.modules.server.NoJwtModule; import org.apache.james.modules.server.RawPostDequeueDecoratorModule; import org.apache.james.modules.server.ReIndexingModule; @@ -61,7 +60,6 @@ public class JPAJamesServerMain { new WebAdminServerModule(), new DataRoutesModules(), new MailboxRoutesModule(), - new MailboxesRoutesModule(), new MailQueueRoutesModule(), new MailRepositoriesRoutesModule(), new ReIndexingModule(), diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java index 489b055..21f65f3 100644 --- a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java +++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java @@ -70,7 +70,6 @@ public class MemoryJamesServerMain { new DataRoutesModules(), new DeletedMessageVaultRoutesModule(), new DLPRoutesModule(), - new JmapTasksModule(), new MailboxRoutesModule(), new MailQueueRoutesModule(), new MailRepositoriesRoutesModule(), @@ -97,6 +96,7 @@ public class MemoryJamesServerMain { new SpamAssassinListenerModule()); public static final Module JMAP = Modules.combine( + new JmapTasksModule(), new MemoryDataJmapModule(), new JMAPDraftServerModule()); diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java index 9b05566..42a7c88 100644 --- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java +++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java @@ -19,6 +19,9 @@ package org.apache.james.modules.server; +import static org.apache.james.webadmin.routes.MailboxesRoutes.ALL_MAILBOXES_TASKS; +import static org.apache.james.webadmin.routes.MailboxesRoutes.ONE_MAILBOX_TASKS; +import static org.apache.james.webadmin.routes.MailboxesRoutes.ONE_MAIL_TASKS; import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USER_MAILBOXES_OPERATIONS_INJECTION_KEY; import org.apache.james.webadmin.Routes; @@ -26,6 +29,7 @@ import org.apache.james.webadmin.jackson.QuotaModule; import org.apache.james.webadmin.routes.DomainQuotaRoutes; import org.apache.james.webadmin.routes.EventDeadLettersRoutes; import org.apache.james.webadmin.routes.GlobalQuotaRoutes; +import org.apache.james.webadmin.routes.MailboxesRoutes; import org.apache.james.webadmin.routes.UserMailboxesRoutes; import org.apache.james.webadmin.routes.UserQuotaRoutes; import org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration; @@ -45,10 +49,14 @@ public class MailboxRoutesModule extends AbstractModule { routesMultibinder.addBinding().to(GlobalQuotaRoutes.class); routesMultibinder.addBinding().to(UserQuotaRoutes.class); routesMultibinder.addBinding().to(UserMailboxesRoutes.class); + routesMultibinder.addBinding().to(MailboxesRoutes.class); Multibinder<JsonTransformerModule> jsonTransformerModuleMultibinder = Multibinder.newSetBinder(binder(), JsonTransformerModule.class); jsonTransformerModuleMultibinder.addBinding().to(QuotaModule.class); Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(USER_MAILBOXES_OPERATIONS_INJECTION_KEY)); + Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(ALL_MAILBOXES_TASKS)); + Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(ONE_MAILBOX_TASKS)); + Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(ONE_MAIL_TASKS)); } } diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java index 8825cf6..c6de10e 100644 --- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java +++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/ReIndexingModule.java @@ -19,8 +19,12 @@ package org.apache.james.modules.server; +import static org.apache.james.webadmin.routes.MailboxesRoutes.ALL_MAILBOXES_TASKS; +import static org.apache.james.webadmin.routes.MailboxesRoutes.ONE_MAILBOX_TASKS; +import static org.apache.james.webadmin.routes.MailboxesRoutes.ONE_MAIL_TASKS; import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USER_MAILBOXES_OPERATIONS_INJECTION_KEY; +import org.apache.james.webadmin.routes.MailboxesRoutes; import org.apache.james.webadmin.routes.UserMailboxesRoutes.UserReIndexingTaskRegistration; import org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration; @@ -34,5 +38,17 @@ public class ReIndexingModule extends AbstractModule { Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(USER_MAILBOXES_OPERATIONS_INJECTION_KEY)) .addBinding() .to(UserReIndexingTaskRegistration.class); + + Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(ALL_MAILBOXES_TASKS)) + .addBinding() + .to(MailboxesRoutes.ReIndexAllMailboxesTaskRegistration.class); + + Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(ONE_MAILBOX_TASKS)) + .addBinding() + .to(MailboxesRoutes.ReIndexOneMailboxTaskRegistration.class); + + Multibinder.newSetBinder(binder(), TaskRegistration.class, Names.named(ONE_MAIL_TASKS)) + .addBinding() + .to(MailboxesRoutes.ReIndexOneMailTaskRegistration.class); } } diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java index 05228e1..65c1423 100644 --- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java +++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java @@ -165,7 +165,6 @@ public class RabbitMQWebAdminServerIntegrationTest extends WebAdminServerIntegra .then() .statusCode(HttpStatus.OK_200) .body(containsString("\"tags\":[\"Cassandra Mappings Operations\"]")) - .body(containsString("{\"name\":\"ReIndexing (mailboxes)\"}")) .body(containsString("{\"name\":\"MessageIdReIndexing\"}")); } } \ No newline at end of file diff --git a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java index 7ab11e8..4e83ebe 100644 --- a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java +++ b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/WebAdminServerIntegrationTest.java @@ -298,7 +298,8 @@ public abstract class WebAdminServerIntegrationTest { .body(containsString("\"tags\":[\"MailQueues\"]")) .body(containsString("\"tags\":[\"Address Forwards\"]")) .body(containsString("\"tags\":[\"Address Aliases\"]")) - .body(containsString("\"tags\":[\"Address Groups\"]")); + .body(containsString("\"tags\":[\"Address Groups\"]")) + .body(containsString("{\"name\":\"Mailboxes\"}")); } @Test diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java index f48f090..a26450e 100644 --- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MailboxesRoutes.java @@ -19,6 +19,7 @@ package org.apache.james.webadmin.routes; +import java.util.Optional; import java.util.Set; import javax.inject.Inject; @@ -60,204 +61,185 @@ import spark.Request; import spark.Route; import spark.Service; -@Api(tags = "ReIndexing (mailboxes)") +@Api(tags = "Mailboxes") @Path("/mailboxes") @Produces("application/json") public class MailboxesRoutes implements Routes { - private static final String BASE_PATH = "/mailboxes"; - private static final String RE_INDEX_FAILED_MESSAGES_QUERY_PARAM = "reIndexFailedMessagesOf"; - private static final String MAILBOX_PARAM = ":mailbox"; - private static final String UID_PARAM = ":uid"; - private static final String MAILBOX_PATH = BASE_PATH + "/" + MAILBOX_PARAM; - private static final String MESSAGE_PATH = MAILBOX_PATH + "/mails/" + UID_PARAM; - static final TaskRegistrationKey RE_INDEX = TaskRegistrationKey.of("reIndex"); - static final String TASK_PARAMETER = "task"; - public static final String ALL_MAILBOXES_TASKS = "allMailboxesTasks"; - - private final TaskManager taskManager; - private final PreviousReIndexingService previousReIndexingService; - private final MailboxId.Factory mailboxIdFactory; - private final ReIndexer reIndexer; - private final JsonTransformer jsonTransformer; - private final Set<TaskRegistration> allMailboxesTaskRegistration; - - @Inject - MailboxesRoutes(TaskManager taskManager, PreviousReIndexingService previousReIndexingService, - MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer, JsonTransformer jsonTransformer, - @Named(ALL_MAILBOXES_TASKS) Set<TaskRegistration> allMailboxesTaskRegistration) { - this.taskManager = taskManager; - this.previousReIndexingService = previousReIndexingService; - this.mailboxIdFactory = mailboxIdFactory; - this.reIndexer = reIndexer; - this.jsonTransformer = jsonTransformer; - this.allMailboxesTaskRegistration = allMailboxesTaskRegistration; - } + public static class ReIndexAllMailboxesTaskRegistration extends TaskRegistration { + @Inject + public ReIndexAllMailboxesTaskRegistration(ReIndexer reIndexer, PreviousReIndexingService previousReIndexingService, MailboxId.Factory mailboxIdFactory) { + super(RE_INDEX, wrap(request -> reIndexAll(previousReIndexingService, reIndexer, request))); + } - @Override - public String getBasePath() { - return BASE_PATH; - } + @POST + @Path("/") + @ApiOperation(value = "Re-indexes all the mails on this server") + @ApiImplicitParams({ + @ApiImplicitParam( + required = true, + name = "task", + paramType = "query parameter", + dataType = "String", + defaultValue = "none", + example = "?task=reIndex", + value = "Compulsory. Only supported value is `reIndex`"), + @ApiImplicitParam( + name = "reIndexFailedMessagesOf", + paramType = "query parameter", + dataType = "String", + defaultValue = "none", + example = "?reIndexFailedMessagesOf=3294a976-ce63-491e-bd52-1b6f465ed7a2", + value = "optional. References a previously run reIndexing task. if present, the messages that this previous " + + "task failed to index will be reIndexed.") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message") + }) + private static Task reIndexAll(PreviousReIndexingService previousReIndexingService, ReIndexer reIndexer, Request request) throws MailboxException { + boolean indexingCorrection = !Strings.isNullOrEmpty(request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM)); + if (indexingCorrection) { + IndexingDetailInformation indexingDetailInformation = retrieveIndexingExecutionDetails(previousReIndexingService, request); + return reIndexer.reIndex(indexingDetailInformation.failures()); + } + return reIndexer.reIndex(); + } - @Override - public void define(Service service) { - service.post(BASE_PATH, reIndexAll(), jsonTransformer); - service.post(MAILBOX_PATH, reIndexMailbox(), jsonTransformer); - service.post(MESSAGE_PATH, reIndexMessage(), jsonTransformer); - } + private static IndexingDetailInformation retrieveIndexingExecutionDetails(PreviousReIndexingService previousReIndexingService, Request request) { + TaskId taskId = getTaskId(request); + try { + return previousReIndexingService.retrieveIndexingExecutionDetails(taskId); + } catch (PreviousReIndexingService.NotAnIndexingRetriableTask | PreviousReIndexingService.TaskNotYetFinishedException e) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message("Invalid task id") + .cause(e) + .haltError(); + } catch (TaskNotFoundException e) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message("TaskId " + taskId.asString() + " does not exist") + .cause(e) + .haltError(); + } + } - @POST - @Path("/") - @ApiOperation(value = "Re-indexes all the mails on this server") - @ApiImplicitParams({ - @ApiImplicitParam( - required = true, - name = "task", - paramType = "query parameter", - dataType = "String", - defaultValue = "none", - example = "?task=reIndex", - value = "Compulsory. Only supported value is `reIndex`"), - @ApiImplicitParam( - name = "reIndexFailedMessagesOf", - paramType = "query parameter", - dataType = "String", - defaultValue = "none", - example = "?reIndexFailedMessagesOf=3294a976-ce63-491e-bd52-1b6f465ed7a2", - value = "optional. References a previously run reIndexing task. if present, the messages that this previous " + - "task failed to index will be reIndexed.") - }) - @ApiResponses(value = { - @ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class), - @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), - @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message") - }) - private Route reIndexAll() { - return TaskFromRequestRegistry.builder() - .parameterName(TASK_PARAMETER) - .registrations(allMailboxesTaskRegistration) - .register(RE_INDEX, wrap(this::reIndexAll)) - .buildAsRoute(taskManager); + private static TaskId getTaskId(Request request) { + try { + String id = request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM); + return TaskId.fromString(id); + } catch (Exception e) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .cause(e) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message("Invalid task id") + .haltError(); + } + } } - private Task reIndexAll(Request request) throws MailboxException { - boolean indexingCorrection = !Strings.isNullOrEmpty(request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM)); - if (indexingCorrection) { - IndexingDetailInformation indexingDetailInformation = retrieveIndexingExecutionDetails(request); - return reIndexer.reIndex(indexingDetailInformation.failures()); + public static class ReIndexOneMailboxTaskRegistration extends TaskRegistration { + @Inject + public ReIndexOneMailboxTaskRegistration(ReIndexer reIndexer, MailboxId.Factory mailboxIdFactory) { + super(RE_INDEX, toTask(reIndexer, mailboxIdFactory)); } - return reIndexer.reIndex(); - } - private IndexingDetailInformation retrieveIndexingExecutionDetails(Request request) { - TaskId taskId = getTaskId(request); - try { - return previousReIndexingService.retrieveIndexingExecutionDetails(taskId); - } catch (PreviousReIndexingService.NotAnIndexingRetriableTask | PreviousReIndexingService.TaskNotYetFinishedException e) { - throw ErrorResponder.builder() - .statusCode(HttpStatus.BAD_REQUEST_400) - .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) - .message("Invalid task id") - .cause(e) - .haltError(); - } catch (TaskNotFoundException e) { - throw ErrorResponder.builder() - .statusCode(HttpStatus.BAD_REQUEST_400) - .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) - .message("TaskId " + taskId.asString() + " does not exist") - .cause(e) - .haltError(); + @POST + @Path("/{mailboxId}") + @ApiOperation(value = "Re-indexes all the mails in a mailbox") + @ApiImplicitParams({ + @ApiImplicitParam( + required = true, + name = "task", + paramType = "query parameter", + dataType = "String", + defaultValue = "none", + example = "?task=reIndex", + value = "Compulsory. Only supported value is `reIndex`"), + @ApiImplicitParam( + required = true, + name = "mailboxId", + paramType = "path parameter", + dataType = "String", + defaultValue = "none", + value = "Compulsory. Needs to be a valid mailbox ID") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message") + }) + private static TaskFromRequest toTask(ReIndexer reIndexer, MailboxId.Factory mailboxIdFactory) { + return wrap(request -> reIndexer.reIndex(extractMailboxId(mailboxIdFactory, request))); } } - private TaskId getTaskId(Request request) { - try { - String id = request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM); - return TaskId.fromString(id); - } catch (Exception e) { - throw ErrorResponder.builder() - .statusCode(HttpStatus.BAD_REQUEST_400) - .cause(e) - .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) - .message("Invalid task id") - .haltError(); + public static class ReIndexOneMailTaskRegistration extends TaskRegistration { + @Inject + public ReIndexOneMailTaskRegistration(ReIndexer reIndexer, MailboxId.Factory mailboxIdFactory) { + super(RE_INDEX, toTask(reIndexer, mailboxIdFactory)); } - } - @POST - @Path("/{mailboxId}") - @ApiOperation(value = "Re-indexes all the mails in a mailbox") - @ApiImplicitParams({ - @ApiImplicitParam( - required = true, - name = "task", - paramType = "query parameter", - dataType = "String", - defaultValue = "none", - example = "?task=reIndex", - value = "Compulsory. Only supported value is `reIndex`"), - @ApiImplicitParam( - required = true, - name = "mailboxId", - paramType = "path parameter", - dataType = "String", - defaultValue = "none", - value = "Compulsory. Needs to be a valid mailbox ID") - }) - @ApiResponses(value = { - @ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class), - @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."), - @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message") - }) - private Route reIndexMailbox() { - return TaskFromRequestRegistry.builder() - .parameterName(TASK_PARAMETER) - .register(RE_INDEX, wrap(request -> reIndexer.reIndex(extractMailboxId(request)))) - .buildAsRoute(taskManager); - } + @POST + @Path("/{mailboxId}/mails/{uid}") + @ApiOperation(value = "Re-indexes a single email") + @ApiImplicitParams({ + @ApiImplicitParam( + required = true, + name = "task", + paramType = "query parameter", + dataType = "String", + defaultValue = "none", + example = "?task=reIndex", + value = "Compulsory. Only supported value is `reIndex`"), + @ApiImplicitParam( + required = true, + name = "user", + paramType = "path parameter", + dataType = "String", + defaultValue = "none", + example = "ben...@apache.org", + value = "Compulsory. Needs to be a valid username"), + @ApiImplicitParam( + required = true, + name = "mailboxId", + paramType = "path parameter", + dataType = "String", + defaultValue = "none", + value = "Compulsory. Needs to be a valid mailbox ID"), + @ApiImplicitParam( + required = true, + name = "uid", + paramType = "path parameter", + dataType = "Integer", + defaultValue = "none", + value = "Compulsory. Needs to be a valid UID") + }) + public static TaskFromRequest toTask(ReIndexer reIndexer, MailboxId.Factory mailboxIdFactory) { + return wrap(request -> reIndexer.reIndex( + extractMailboxId(mailboxIdFactory, request), + extractUid(request))); + } - @POST - @Path("/{mailboxId}/mails/{uid}") - @ApiOperation(value = "Re-indexes a single email") - @ApiImplicitParams({ - @ApiImplicitParam( - required = true, - name = "task", - paramType = "query parameter", - dataType = "String", - defaultValue = "none", - example = "?task=reIndex", - value = "Compulsory. Only supported value is `reIndex`"), - @ApiImplicitParam( - required = true, - name = "user", - paramType = "path parameter", - dataType = "String", - defaultValue = "none", - example = "ben...@apache.org", - value = "Compulsory. Needs to be a valid username"), - @ApiImplicitParam( - required = true, - name = "mailboxId", - paramType = "path parameter", - dataType = "String", - defaultValue = "none", - value = "Compulsory. Needs to be a valid mailbox ID"), - @ApiImplicitParam( - required = true, - name = "uid", - paramType = "path parameter", - dataType = "Integer", - defaultValue = "none", - value = "Compulsory. Needs to be a valid UID") - }) - private Route reIndexMessage() { - return TaskFromRequestRegistry.builder() - .parameterName(TASK_PARAMETER) - .register(RE_INDEX, wrap(request -> reIndexer.reIndex(extractMailboxId(request), extractUid(request)))) - .buildAsRoute(taskManager); + private static MessageUid extractUid(Request request) { + try { + return MessageUid.of(Long.parseLong(request.params(UID_PARAM))); + } catch (NumberFormatException e) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message("'uid' needs to be a parsable long") + .cause(e) + .haltError(); + } + } } - private TaskFromRequest wrap(TaskFromRequest toBeWrapped) { + private static TaskFromRequest wrap(TaskFromRequest toBeWrapped) { return request -> { try { return toBeWrapped.fromRequest(request); @@ -272,7 +254,7 @@ public class MailboxesRoutes implements Routes { }; } - private MailboxId extractMailboxId(Request request) { + private static MailboxId extractMailboxId(MailboxId.Factory mailboxIdFactory, Request request) { try { return mailboxIdFactory.fromString(request.params(MAILBOX_PARAM)); } catch (Exception e) { @@ -285,16 +267,72 @@ public class MailboxesRoutes implements Routes { } } - private MessageUid extractUid(Request request) { - try { - return MessageUid.of(Long.parseLong(request.params(UID_PARAM))); - } catch (NumberFormatException e) { - throw ErrorResponder.builder() - .statusCode(HttpStatus.BAD_REQUEST_400) - .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) - .message("'uid' needs to be a parsable long") - .cause(e) - .haltError(); - } + private static final String BASE_PATH = "/mailboxes"; + private static final String RE_INDEX_FAILED_MESSAGES_QUERY_PARAM = "reIndexFailedMessagesOf"; + private static final String MAILBOX_PARAM = ":mailbox"; + private static final String UID_PARAM = ":uid"; + private static final String MAILBOX_PATH = BASE_PATH + "/" + MAILBOX_PARAM; + private static final String MESSAGE_PATH = MAILBOX_PATH + "/mails/" + UID_PARAM; + static final TaskRegistrationKey RE_INDEX = TaskRegistrationKey.of("reIndex"); + static final String TASK_PARAMETER = "task"; + public static final String ALL_MAILBOXES_TASKS = "allMailboxesTasks"; + public static final String ONE_MAILBOX_TASKS = "oneMailboxTasks"; + public static final String ONE_MAIL_TASKS = "oneMailTasks"; + + private final TaskManager taskManager; + private final JsonTransformer jsonTransformer; + private final Set<TaskRegistration> allMailboxesTaskRegistration; + private final Set<TaskRegistration> oneMailboxTaskRegistration; + private final Set<TaskRegistration> oneMailTaskRegistration; + + @Inject + MailboxesRoutes(TaskManager taskManager, + JsonTransformer jsonTransformer, + @Named(ALL_MAILBOXES_TASKS) Set<TaskRegistration> allMailboxesTaskRegistration, + @Named(ONE_MAILBOX_TASKS) Set<TaskRegistration> oneMailboxTaskRegistration, + @Named(ONE_MAIL_TASKS) Set<TaskRegistration> oneMailTaskRegistration) { + this.taskManager = taskManager; + this.jsonTransformer = jsonTransformer; + this.allMailboxesTaskRegistration = allMailboxesTaskRegistration; + this.oneMailboxTaskRegistration = oneMailboxTaskRegistration; + this.oneMailTaskRegistration = oneMailTaskRegistration; + } + + @Override + public String getBasePath() { + return BASE_PATH; + } + + @Override + public void define(Service service) { + allMailboxesOperations() + .ifPresent(route -> service.post(BASE_PATH, route, jsonTransformer)); + + oneMailboxOperations() + .ifPresent(route -> service.post(MAILBOX_PATH, route, jsonTransformer)); + + oneMail() + .ifPresent(route -> service.post(MESSAGE_PATH, route, jsonTransformer)); + } + + private Optional<Route> allMailboxesOperations() { + return TaskFromRequestRegistry.builder() + .parameterName(TASK_PARAMETER) + .registrations(allMailboxesTaskRegistration) + .buildAsRouteOptional(taskManager); + } + + private Optional<Route> oneMailboxOperations() { + return TaskFromRequestRegistry.builder() + .parameterName(TASK_PARAMETER) + .registrations(oneMailboxTaskRegistration) + .buildAsRouteOptional(taskManager); + } + + private Optional<Route> oneMail() { + return TaskFromRequestRegistry.builder() + .parameterName(TASK_PARAMETER) + .registrations(oneMailTaskRegistration) + .buildAsRouteOptional(taskManager); } } diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesNoTasksTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesNoTasksTest.java new file mode 100644 index 0000000..2a3b1d1 --- /dev/null +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesNoTasksTest.java @@ -0,0 +1,102 @@ +/**************************************************************** + * 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 io.restassured.RestAssured.when; + +import org.apache.james.task.Hostname; +import org.apache.james.task.MemoryTaskManager; +import org.apache.james.webadmin.WebAdminServer; +import org.apache.james.webadmin.WebAdminUtils; +import org.apache.james.webadmin.tasks.TaskFromRequestRegistry; +import org.apache.james.webadmin.utils.ErrorResponder; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.eclipse.jetty.http.HttpStatus; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.testcontainers.shaded.com.google.common.collect.ImmutableSet; + +import io.restassured.RestAssured; + +class MailboxesRoutesNoTasksTest { + private static final ImmutableSet<TaskFromRequestRegistry.TaskRegistration> NO_ADDITIONAL_REGISTRATION = ImmutableSet.of(); + + private WebAdminServer webAdminServer; + private MemoryTaskManager taskManager; + + @BeforeEach + void beforeEach() { + taskManager = new MemoryTaskManager(new Hostname("foo")); + JsonTransformer jsonTransformer = new JsonTransformer(); + + webAdminServer = WebAdminUtils.createWebAdminServer( + new TasksRoutes(taskManager, jsonTransformer), + new MailboxesRoutes(taskManager, + jsonTransformer, + NO_ADDITIONAL_REGISTRATION, + NO_ADDITIONAL_REGISTRATION, + NO_ADDITIONAL_REGISTRATION)) + .start(); + + RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer).build(); + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + } + + @AfterEach + void tearDown() { + webAdminServer.destroy(); + taskManager.stop(); + } + + @Test + void allMailboxesEndpointShouldNotBeExposedWhenNoTasks() { + when() + .post("/mailboxes") + .then() + .statusCode(HttpStatus.NOT_FOUND_404) + .body("statusCode", Matchers.is(404)) + .body("type", Matchers.is(ErrorResponder.ErrorType.NOT_FOUND.getType())) + .body("message", Matchers.is("POST /mailboxes can not be found")); + } + + @Test + void oneMailboxEndpointShouldNotBeExposedWhenNoTasks() { + when() + .post("/mailboxes/36") + .then() + .statusCode(HttpStatus.NOT_FOUND_404) + .body("statusCode", Matchers.is(404)) + .body("type", Matchers.is(ErrorResponder.ErrorType.NOT_FOUND.getType())) + .body("message", Matchers.is("POST /mailboxes/36 can not be found")); + } + + @Test + void oneMailEndpointShouldNotBeExposedWhenNoTasks() { + when() + .post("/mailboxes/36/mails/7") + .then() + .statusCode(HttpStatus.NOT_FOUND_404) + .body("statusCode", Matchers.is(404)) + .body("type", Matchers.is(ErrorResponder.ErrorType.NOT_FOUND.getType())) + .body("message", Matchers.is("POST /mailboxes/36/mails/7 can not be found")); + } +} \ No newline at end of file diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java index 552356a..50da3b0 100644 --- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java @@ -51,7 +51,6 @@ import org.apache.james.task.MemoryTaskManager; import org.apache.james.webadmin.WebAdminServer; import org.apache.james.webadmin.WebAdminUtils; import org.apache.james.webadmin.service.PreviousReIndexingService; -import org.apache.james.webadmin.tasks.TaskFromRequestRegistry; import org.apache.james.webadmin.utils.ErrorResponder; import org.apache.james.webadmin.utils.JsonTransformer; import org.apache.mailbox.tools.indexer.FullReindexingTask; @@ -72,7 +71,6 @@ import io.restassured.RestAssured; class MailboxesRoutesTest { private static final Username USERNAME = Username.of("be...@apache.org"); private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME); - private static final ImmutableSet<TaskFromRequestRegistry.TaskRegistration> NO_ADDITIONAL_REGISTRATION = ImmutableSet.of(); private WebAdminServer webAdminServer; private ListeningMessageSearchIndex searchIndex; @@ -97,13 +95,17 @@ class MailboxesRoutesTest { webAdminServer = WebAdminUtils.createWebAdminServer( new TasksRoutes(taskManager, jsonTransformer), - new MailboxesRoutes( - taskManager, - new PreviousReIndexingService(taskManager), - mailboxIdFactory, - reIndexer, + new MailboxesRoutes(taskManager, jsonTransformer, - NO_ADDITIONAL_REGISTRATION)) + ImmutableSet.of( + new MailboxesRoutes.ReIndexAllMailboxesTaskRegistration( + reIndexer, new PreviousReIndexingService(taskManager), mailboxIdFactory)), + ImmutableSet.of( + new MailboxesRoutes.ReIndexOneMailboxTaskRegistration( + reIndexer, mailboxIdFactory)), + ImmutableSet.of( + new MailboxesRoutes.ReIndexOneMailTaskRegistration( + reIndexer, mailboxIdFactory)))) .start(); RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer).build(); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org