diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityBulkActionView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityBulkActionView.java new file mode 100644 index 000000000000..cbbfa4b3ae92 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityBulkActionView.java @@ -0,0 +1,9 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; + +public class ResponseEntityBulkActionView extends ResponseEntityView { + public ResponseEntityBulkActionView(BulkActionView entity) { + super(entity); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityBulkActionsResultView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityBulkActionsResultView.java new file mode 100644 index 000000000000..c9cce3ec03ea --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityBulkActionsResultView.java @@ -0,0 +1,9 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; + +public class ResponseEntityBulkActionsResultView extends ResponseEntityView { + public ResponseEntityBulkActionsResultView(BulkActionsResultView entity) { + super(entity); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntitySystemActionWorkflowActionMapping.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntitySystemActionWorkflowActionMapping.java new file mode 100644 index 000000000000..1773819d898c --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntitySystemActionWorkflowActionMapping.java @@ -0,0 +1,10 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.workflows.model.SystemActionWorkflowActionMapping; + +public class ResponseEntitySystemActionWorkflowActionMapping extends ResponseEntityView { + public ResponseEntitySystemActionWorkflowActionMapping(SystemActionWorkflowActionMapping entity) { + super(entity); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionClassesView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionClassesView.java new file mode 100644 index 000000000000..447522798c6d --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionClassesView.java @@ -0,0 +1,12 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.workflows.model.WorkflowActionClass; + +import java.util.List; + +public class ResponseEntityWorkflowActionClassesView extends ResponseEntityView> { + public ResponseEntityWorkflowActionClassesView(List actionClasses) { + super(actionClasses); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionView.java new file mode 100644 index 000000000000..899ecb6d9334 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionView.java @@ -0,0 +1,9 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; + +public class ResponseEntityWorkflowActionView extends ResponseEntityView { + public ResponseEntityWorkflowActionView(WorkflowActionView entity) { + super(entity); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionletsView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionletsView.java new file mode 100644 index 000000000000..c428388155b9 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionletsView.java @@ -0,0 +1,12 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.workflows.actionlet.WorkFlowActionlet; + +import java.util.List; + +public class ResponseEntityWorkflowActionletsView extends ResponseEntityView> { + public ResponseEntityWorkflowActionletsView(List actionlets) { + super(actionlets); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionsView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionsView.java new file mode 100644 index 000000000000..e1e2119a851d --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowActionsView.java @@ -0,0 +1,11 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; + +import java.util.List; + +public class ResponseEntityWorkflowActionsView extends ResponseEntityView> { + public ResponseEntityWorkflowActionsView(List entity) { + super(entity); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowSchemesView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowSchemesView.java new file mode 100644 index 000000000000..86e336545049 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowSchemesView.java @@ -0,0 +1,12 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.workflows.model.WorkflowScheme; + +import java.util.List; + +public class ResponseEntityWorkflowSchemesView extends ResponseEntityView> { + public ResponseEntityWorkflowSchemesView(List schemes) { + super(schemes); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowStepsView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowStepsView.java new file mode 100644 index 000000000000..27affcbfad69 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/ResponseEntityWorkflowStepsView.java @@ -0,0 +1,12 @@ +package com.dotcms.rest.api.v1.workflow; + +import com.dotcms.rest.ResponseEntityView; +import com.dotmarketing.portlets.workflows.model.WorkflowStep; + +import java.util.List; + +public class ResponseEntityWorkflowStepsView extends ResponseEntityView> { + public ResponseEntityWorkflowStepsView(List steps) { + super(steps); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java index ed5ede250671..482d54e45f15 100644 --- a/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java @@ -14,14 +14,7 @@ import com.dotcms.mock.response.MockHttpResponse; import com.dotcms.repackage.com.google.common.annotations.VisibleForTesting; import com.dotcms.repackage.javax.validation.constraints.NotNull; -import com.dotcms.rest.AnonymousAccess; -import com.dotcms.rest.ContentHelper; -import com.dotcms.rest.EmptyHttpResponse; -import com.dotcms.rest.InitDataObject; -import com.dotcms.rest.MapToContentletPopulator; -import com.dotcms.rest.PATCH; -import com.dotcms.rest.ResponseEntityView; -import com.dotcms.rest.WebResource; +import com.dotcms.rest.*; import com.dotcms.rest.annotation.IncludePermissions; import com.dotcms.rest.annotation.NoCache; import com.dotcms.rest.api.MultiPartUtils; @@ -99,12 +92,13 @@ import com.rainerhahnekamp.sneakythrow.Sneaky; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.ExternalDocumentation; -import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.vavr.Tuple2; import io.vavr.control.Try; import org.apache.commons.beanutils.BeanUtils; @@ -181,7 +175,11 @@ * @since Dec 6th, 2017 */ @Path("/v1/workflow") -@Tag(name = "Workflow") +@Tag(name = "Workflow", + description = "Endpoints that perform operations related to workflows.", + externalDocs = @ExternalDocumentation(description = "Additional Workflow API information", + url = "https://www.dotcms.com/docs/latest/workflow-rest-api") +) public class WorkflowResource { public final static String VERSION = "1.0"; @@ -271,32 +269,36 @@ public WorkflowResource() { @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) - @Operation(operationId = "getSchemes", summary = "Find Workflow schemes", - description = "Fetches Workflow schemes. Can be filtered by Content Type and/or live status " + - "through optional query parameters.", - externalDocs = @ExternalDocumentation(url = "https://www.dotcms.com/docs/latest/workflow-rest-api"), + @Operation(operationId = "getWorkflowSchemes", summary = "Find workflow schemes", + description = "Returns workflow schemes. Can be filtered by content type and/or live status " + + "through optional query parameters.", + tags = {"Workflow"}, responses = { - @ApiResponse(responseCode = "200", description = "Success", + @ApiResponse(responseCode = "200", description = "Scheme(s) returned successfully", content = @Content(mediaType = "application/json", - schema = @Schema(implementation = ResponseEntityView.class) + schema = @Schema(implementation = ResponseEntityWorkflowSchemesView.class) ) ), - @ApiResponse(responseCode = "401", description = "Insufficient Permissions") + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Content type not found"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") } ) public final Response findSchemes(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @Parameter(in = ParameterIn.QUERY, name = "contentTypeId", - description = "Identifier of Content Type examined for schemes; leave blank to show all workflow schemes." + - "\n\nExample: `c541abb1-69b3-4bc5-8430-5e09e5239cc8` (Page Content Type)", - schema = @Schema(type = "string", format = "uuid", - accessMode = Schema.AccessMode.READ_ONLY) - ) @QueryParam("contentTypeId") final String contentTypeId, - @Parameter(in = ParameterIn.QUERY, name = "showArchived", - description = "If true, includes archived schemes in response.", - schema = @Schema(type = "boolean", defaultValue = "true", - accessMode = Schema.AccessMode.READ_ONLY) - ) @DefaultValue("true") @QueryParam("showArchived") final boolean showArchived) { + @QueryParam("contentTypeId") @Parameter( + description = "Optional filter parameter that takes a content type identifier and returns " + + "all workflow schemes associated with that type.\n\n" + + "Leave blank to return all workflow schemes.\n\n" + + "Example value: `c541abb1-69b3-4bc5-8430-5e09e5239cc8` " + + "(Default page content type)", + schema = @Schema(type = "string", format = "uuid") + ) final String contentTypeId, + @DefaultValue("true") @QueryParam("showArchived") @Parameter( + description = "If `true`, includes archived schemes in response.", + schema = @Schema(type = "boolean", defaultValue = "true") + ) final boolean showArchived) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -327,6 +329,21 @@ public final Response findSchemes(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionlets", summary = "Find all workflow actionlets", + description = "Returns a list of all workflow actionlets, a.k.a. workflow sub-actions. " + + "The returned list is complete and does not use pagination.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Workflow actionlets returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionletsView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findActionlets(@Context final HttpServletRequest request) { this.webResource.init @@ -356,8 +373,31 @@ public final Response findActionlets(@Context final HttpServletRequest request) @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionletsByActionId", summary = "Find workflow actionlets by workflow action", + description = "Returns a list of the workflow actionlets, a.k.a. workflow sub-actions, associated with " + + "a specified workflow action.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Workflow actionlets returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionClassesView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow action not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findActionletsByAction(@Context final HttpServletRequest request, - @PathParam("actionId") final String actionId) { + @PathParam("actionId") @Parameter( + required = true, + description = "Identifier of workflow action to examine for " + + "actionlets.\n\n" + + "Example value: `b9d89c80-3d88-4311-8365-187323c96436` " + + "(Default system workflow \"Publish\" action)", + schema = @Schema(type = "string", format = "uuid") + ) final String actionId) { final InitDataObject initDataObject = this.webResource.init (null, true, request, true, null); @@ -387,10 +427,35 @@ public final Response findActionletsByAction(@Context final HttpServletRequest r @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowSchemesByContentTypeId", summary = "Find workflow schemes by content type id", + description = "Fetches workflow schemes associated with a content type by its identifier. Returns an entity " + + "containing two properties:\n\n" + + "| Property | Description |\n" + + "|----------|-------------|\n" + + "| `contentTypeSchemes` | A list of schemes associated with the specified content type. |\n" + + "| `schemes` | A list of non-archived schemes, irrespective of relation to the content type. |", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Scheme(s) returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = SchemesAndSchemesContentTypeView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Content type ID not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findAllSchemesAndSchemesByContentType( @Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("contentTypeId") final String contentTypeId) { + @PathParam("contentTypeId") @Parameter( + required = true, + description = "Identifier of content type to examine for workflow schemes.\n\n" + + "Example value: `c541abb1-69b3-4bc5-8430-5e09e5239cc8` (Default page content type)", + schema = @Schema(type = "string", format = "uuid") + ) final String contentTypeId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -427,9 +492,30 @@ public final Response findAllSchemesAndSchemesByContentType( @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowStepsBySchemeId", summary = "Find steps by workflow scheme ID", + description = "Returns a list of steps associated with a workflow scheme.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Scheme(s) returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowStepsView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow scheme not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findStepsByScheme(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("schemeId") final String schemeId) { + @PathParam("schemeId") @Parameter( + required = true, + description = "Identifier of workflow scheme.\n\n" + + "Example value: `d61a59e1-a49c-46f2-a929-db2b4bfa88b2` " + + "(Default system workflow)", + schema = @Schema(type = "string", format = "uuid") + ) final String schemeId) { this.webResource.init (null, request, response, true, null); @@ -466,10 +552,40 @@ public final Response findStepsByScheme(@Context final HttpServletRequest reques @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionsByContentletInode", summary = "Finds workflow actions by content inode", + description = "Returns a list of workflow actions associated with a contentlet specified by inode.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Scheme(s) returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionsView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Contentlet not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findAvailableActions(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("inode") final String inode, - @QueryParam("renderMode") final String renderMode) { + @PathParam("inode") @Parameter( + required = true, + description = "Inode of contentlet to examine for workflow actions.\n\n", + schema = @Schema(type = "string", format = "uuid") + ) final String inode, + @QueryParam("renderMode") @Parameter( + description = "*Optional.* Case-insensitive parameter indicating " + + "how results are to be displayed.\n\n" + + "In listing mode, all associated actions are returned; " + + "in editing mode (the default), it returns only the actions " + + "accessible to the contentlet's current workflow step.", + schema = @Schema( + type = "string", + allowableValues = {"EDITING", "LISTING"}, + defaultValue = "EDITING" + ) + ) final String renderMode) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -575,9 +691,50 @@ private static List createActionInputViews (final WorkflowActio @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) + @Operation(operationId = "postBulkActions", summary = "Finds available bulk workflow actions for content", + description = "Returns a list of bulk actions available for contentlets specified either by identifiers " + + "or by query, as specified in the POST body.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Zero or more bulk actions returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityBulkActionView.class) + ) + ), + @ApiResponse(responseCode = "400", description = "Bad request"), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response getBulkActions(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - final BulkActionForm bulkActionForm) { + @RequestBody( + description = "POST body consists of a JSON object with either of the following properties:\n\n" + + "| Property | Type | Description |\n" + + "|-|-|-|\n" + + "| `contentletIds` | List of Strings | A list of individual contentlet identifiers. |\n" + + "| `query` | String | [Lucene query](https://www.dotcms.com/docs/latest/content-search-syntax#Lucene); " + + "uses all matching contentlets. |\n\n" + + "If both properties are present, the operation will use the list of identifiers and disregard " + + "the query.", + required = true, + content = @Content( + schema = @Schema(implementation = BulkActionForm.class), + examples = { + @ExampleObject( + value = "{\n" + + " \"contentletIds\": [\n" + + " \"651a4dc8-2124-45d8-8bd2-d8e68ad358a8\",\n" + + " \"f8d60f79-e006-42e0-894f-5d3488b796f6\"\n" + + " ],\n" + + " \"query\": \"+contentType:*\"\n" + + "}" + ) + } + ) + ) final BulkActionForm bulkActionForm) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -601,9 +758,46 @@ public final Response getBulkActions(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) + @Operation(operationId = "putBulkActionsFire", summary = "Perform workflow actions on bulk content", + description = "This operation allows you to specify a multiple content items (either by query or a list of " + + "identifiers), a workflow action to perform on them, and additional parameters as needed by " + + "the selected action.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Success", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityBulkActionsResultView.class) + ) + ), + @ApiResponse(responseCode = "400", description = "Bad request"), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final void fireBulkActions(@Context final HttpServletRequest request, @Suspended final AsyncResponse asyncResponse, - final FireBulkActionsForm fireBulkActionsForm) { + @RequestBody( + description = "PUT body consists of a JSON object with the following possible properties:\n\n" + + "| Property | Type | Description |\n" + + "|-|-|-|\n" + + "| `contentletIds` | List of Strings | A list of individual contentlet identifiers. |\n" + + "| `query` | String | [Lucene query](https://www.dotcms.com/docs/latest/content-search-syntax#Lucene); " + + "uses all matching contentlets. |\n" + + "| `workflowActionId` | String | The identifier of the workflow action to be performed on the " + + "selected content. |\n" + + "| `additionalParams` | Object | Further parameters and properties are conveyed here, depending " + + "on the particulars of the selected action. For example, an " + + "action using the Send Form Email actionlet would require " + + "parameters like `fromEmail` or `emailSubject`.

For a " + + "complete list of possible parameters, refer to the various " + + "keys listed in the `/actionlets` GET method. |\n\n" + + "If both `contentletIds` and `query` properties are present, the operation will use the query and " + + "disregard the identifier list.", + required = true, + content = @Content(schema = @Schema(implementation = FireBulkActionsForm.class)) + ) final FireBulkActionsForm fireBulkActionsForm) { final InitDataObject initDataObject = this.webResource.init(null, request, new EmptyHttpResponse(), true, null); Logger.debug(this, ()-> "Fire bulk actions: " + fireBulkActionsForm); @@ -631,8 +825,46 @@ public final void fireBulkActions(@Context final HttpServletRequest request, @Path("/contentlet/actions/_bulkfire") @JSONP @Produces(SseFeature.SERVER_SENT_EVENTS) + @Consumes({MediaType.APPLICATION_JSON}) + @Operation(operationId = "postBulkActionsFire", summary = "Perform workflow actions on bulk content", + description = "This operation allows you to specify a multiple content items (either by query or a list of " + + "identifiers), a workflow action to perform on them, and additional parameters as needed by " + + "the selected action.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Success", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = EventOutput.class) + ) + ), + @ApiResponse(responseCode = "400", description = "Bad request"), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public EventOutput fireBulkActions(@Context final HttpServletRequest request, - final FireBulkActionsForm fireBulkActionsForm) + @RequestBody( + description = "POST body consists of a JSON object with the following possible properties:\n\n" + + "| Property | Type | Description |\n" + + "|-|-|-|\n" + + "| `contentletIds` | List of Strings | A list of individual contentlet identifiers. |\n" + + "| `query` | String | [Lucene query](https://www.dotcms.com/docs/latest/content-search-syntax#Lucene); " + + "uses all matching contentlets. |\n" + + "| `workflowActionId` | String | The identifier of the workflow action to be performed on the " + + "selected content. |\n" + + "| `additionalParams` | Object | Further parameters and properties are conveyed here, depending " + + "on the particulars of the selected action. For example, an " + + "action using the Send Form Email actionlet would require " + + "parameters like `fromEmail` or `emailSubject`.

For a " + + "complete list of possible parameters, refer to the various " + + "keys listed in the `/actionlets` GET method. |\n\n" + + "If both `contentletIds` and `query` properties are present, the operation will perform the " + + "selected action on all contentlets indicated in both. Note that this will lead to the workflow " + + "action being performed on the same contentlet twice, if it appears in both.", + required = true, + content = @Content(schema = @Schema(implementation = FireBulkActionsForm.class)) + ) final FireBulkActionsForm fireBulkActionsForm) throws DotDataException, DotSecurityException { final InitDataObject initDataObject = this.webResource .init(null, request, new EmptyHttpResponse(), true, null); @@ -696,9 +928,30 @@ public EventOutput fireBulkActions(@Context final HttpServletRequest request, @NoCache @IncludePermissions @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionByActionId", summary = "Find action by ID", + description = "Returns a workflow action object.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Action returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow action not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findAction(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("actionId") final String actionId) { + @PathParam("actionId") @Parameter( + required = true, + description = "Identifier of the workflow action to return.\n\n" + + "Example value: `b9d89c80-3d88-4311-8365-187323c96436` " + + "(Default system workflow \"Publish\" action)", + schema = @Schema(type = "string", format = "uuid") + ) final String actionId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -727,10 +980,33 @@ public final Response findAction(@Context final HttpServletRequest request, @NoCache @IncludePermissions @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowConditionByActionId", summary = "Find condition by action ID", + description = "Returns a string representing the \"condition\" on the selected action.\n\n" + + "More specifically: if the workflow action has anything in its Custom Code field, " + + "the result is evaluated as Velocity, and the output is returned.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Condition returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityStringView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow action not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response evaluateActionCondition( @Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("actionId") final String actionId) { + @PathParam("actionId") @Parameter( + required = true, + description = "Identifier of a workflow action to check for condition.\n\n" + + "Example value: `b9d89c80-3d88-4311-8365-187323c96436` " + + "(Default system workflow \"Publish\" action)", + schema = @Schema(type = "string", format = "uuid") + ) final String actionId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -759,10 +1035,37 @@ public final Response evaluateActionCondition( @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionByStepActionId", summary = "Find a workflow action within a step", + description = "Returns a workflow action if it exists within a specific step.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Action returned successfully from step", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow action not found within specified step."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findActionByStep(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("stepId") final String stepId, - @PathParam("actionId") final String actionId) { + @PathParam("stepId") @Parameter( + required = true, + description = "Identifier of a workflow step.\n\n" + + "Example value: `ee24a4cb-2d15-4c98-b1bd-6327126451f3` " + + "(Default system workflow \"Draft\" step)", + schema = @Schema(type = "string", format = "uuid") + ) final String stepId, + @PathParam("actionId") @Parameter( + required = true, + description = "Identifier of a workflow action.\n\n" + + "Example value: `b9d89c80-3d88-4311-8365-187323c96436` " + + "(Default system workflow \"Publish\" action)", + schema = @Schema(type = "string", format = "uuid") + ) final String actionId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -791,9 +1094,30 @@ public final Response findActionByStep(@Context final HttpServletRequest request @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionsByStepId", summary = "Find all actions in a workflow step", + description = "Returns a list of workflow actions associated with a specified workflow step.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Actions returned successfully from step", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionsView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow step not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findActionsByStep(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("stepId") final String stepId) { + @PathParam("stepId") @Parameter( + required = true, + description = "Identifier of a workflow step.\n\n" + + "Example value: `ee24a4cb-2d15-4c98-b1bd-6327126451f3` " + + "(Default system workflow \"Draft\" step)", + schema = @Schema(type = "string", format = "uuid") + ) final String stepId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -821,9 +1145,30 @@ public final Response findActionsByStep(@Context final HttpServletRequest reques @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getWorkflowActionsBySchemeId", summary = "Find all actions in a workflow scheme", + description = "Returns a list of workflow actions associated with a specified workflow scheme.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Actions returned successfully from workflow scheme", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionsView.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow scheme not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findActionsByScheme(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("schemeId") final String schemeId) { + @PathParam("schemeId") @Parameter( + required = true, + description = "Identifier of workflow scheme.\n\n" + + "Example value: `d61a59e1-a49c-46f2-a929-db2b4bfa88b2` " + + "(Default system workflow)", + schema = @Schema(type = "string", format = "uuid") + ) final String schemeId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -851,10 +1196,45 @@ public final Response findActionsByScheme(@Context final HttpServletRequest requ @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) + @Operation(operationId = "postFindActionsBySchemesAndSystemAction", summary = "Finds workflow actions by schemes and system action", + description = "Returns a list of workflow actions associated with workflow schemes, further filtered " + + "by [default system workflow actions](https://www.dotcms.com/docs/latest/managing-workflows#DefaultActions).", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Workflow action(s) returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityWorkflowActionsView.class) + ) + ), + @ApiResponse(responseCode = "400", description = "Bad request"), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findActionsBySchemesAndSystemAction(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("systemAction") final WorkflowAPI.SystemAction systemAction, - final WorkflowSchemesForm workflowSchemesForm) { + @PathParam("systemAction") @Parameter( + required = true, + description = "Default workflow action." + ) final WorkflowAPI.SystemAction systemAction, + @RequestBody( + description = "POST body consists of a JSON object containing " + + "a single property called `schemes`, which contains a " + + "list of workflow scheme identifier strings.", + required = true, + content = @Content( + schema = @Schema(implementation = WorkflowSchemesForm.class), + examples = @ExampleObject( + value = "{\n" + + " \"schemes\": [\n" + + " \"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"\n" + + " ]\n" + + "}" + ) + ) + ) final WorkflowSchemesForm workflowSchemesForm) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -888,9 +1268,31 @@ public final Response findActionsBySchemesAndSystemAction(@Context final HttpSer @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getSystemActionMappingsBySchemeId", summary = "Find default actions mapped to a workflow scheme", + description = "Returns a list of [default system workflow actions](https://www.dotcms.com/docs/latest/managing-" + + "workflows#DefaultActions) associated with a specified workflow scheme.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Actions returned successfully from workflow scheme", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntitySystemActionWorkflowActionMapping.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow scheme not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findSystemActionsByScheme(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("schemeId") final String schemeId) { + @PathParam("schemeId") @Parameter( + required = true, + description = "Identifier of workflow scheme.\n\n" + + "Example value: `d61a59e1-a49c-46f2-a929-db2b4bfa88b2` " + + "(Default system workflow)", + schema = @Schema(type = "string", format = "uuid") + ) final String schemeId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -919,9 +1321,30 @@ public final Response findSystemActionsByScheme(@Context final HttpServletReques @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getSystemActionMappingsByContentType", summary = "Find default actions mapped to a workflow scheme", + description = "Returns a list of [default system workflow actions](https://www.dotcms.com/docs/latest/managing-" + + "workflows#DefaultActions) associated with a specified workflow scheme.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Action(s) returned successfully from workflow scheme", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntitySystemActionWorkflowActionMapping.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Content Type not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response findSystemActionsByContentType(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("contentTypeVarOrId") final String contentTypeVarOrId) { + @PathParam("contentTypeVarOrId") @Parameter( + required = true, + description = "The ID or Velocity variable of the content type to update.\n\n" + + "Example value: `htmlpageasset` (Default page content type)", + schema = @Schema(type = "string") + ) final String contentTypeVarOrId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -952,9 +1375,32 @@ public final Response findSystemActionsByContentType(@Context final HttpServletR @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Operation(operationId = "getSystemActionsByActionId", summary = "Find default actions by workflow action id", + description = "Returns a list of " + + "[default system workflow actions](https://www.dotcms.com/docs/latest/managing-workflows#DefaultActions) " + + "associated with a specified workflow action.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Action(s) returned successfully", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntitySystemActionWorkflowActionMapping.class) + ) + ), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "404", description = "Workflow action not found."), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response getSystemActionsReferredByWorkflowAction(@Context final HttpServletRequest request, @Context final HttpServletResponse response, - @PathParam("workflowActionId") final String workflowActionId) { + @PathParam("workflowActionId") @Parameter( + required = true, + description = "Identifier of the workflow action to return.\n\n" + + "Example value: `b9d89c80-3d88-4311-8365-187323c96436` " + + "(Default system workflow \"Publish\" action)", + schema = @Schema(type = "string", format = "uuid") + ) final String workflowActionId) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -988,9 +1434,45 @@ public final Response getSystemActionsReferredByWorkflowAction(@Context final Ht @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) + @Operation(operationId = "putSystemActions", summary = "Save a default workflow action mapping", + description = "This operation allows you to save a [default system workflow action]" + + "(https://www.dotcms.com/docs/latest/managing-workflows#DefaultActions) mapping. This requires:\n\n" + + "1. Selecting the default workflow action to be mapped;\n" + + "2. Specifying a workflow action to be performed when that default action is called;\n" + + "3. Associating this mapping with either a workflow scheme or a content type.\n\n" + + "See the request body below for further details.", + tags = {"Workflow"}, + responses = { + @ApiResponse(responseCode = "200", description = "Success", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = ResponseEntityBulkActionsResultView.class) + ) + ), + @ApiResponse(responseCode = "400", description = "Bad request"), + @ApiResponse(responseCode = "401", description = "Insufficient Permissions"), + @ApiResponse(responseCode = "403", description = "Forbidden"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + } + ) public final Response saveSystemAction(@Context final HttpServletRequest request, - @Context final HttpServletResponse response, - final WorkflowSystemActionForm workflowSystemActionForm) { + @Context final HttpServletResponse response, + @RequestBody( + description = "PUT body consists of a JSON object with the following properties:\n\n" + + "| Property | Type | Description |\n" + + "|-|-|-|\n" + + "| `systemAction` | String | A default workflow action, such as `NEW` or `PUBLISH`. |\n" + + "| `actionId` | String | The identifier of an action that will be performed " + + "by the specified default action. |\n" + + "| `schemeId` | String | The identifier of a workflow scheme to be associated " + + "with the default action. |\n" + + "| `contentTypeVariable` | String | The variable of a content type to be " + + "associated with the default action.|\n\n" + + "If both the `schemeId` and `contentTypeVariable` are specified, the scheme " + + "identifier takes precedence, and the content type variable is disregarded.", + required = true, + content = @Content(schema = @Schema(implementation = WorkflowSystemActionForm.class)) + )final WorkflowSystemActionForm workflowSystemActionForm) { final InitDataObject initDataObject = this.webResource.init (null, request, response, true, null); @@ -1101,6 +1583,7 @@ public final Response saveAction(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) public final Response updateAction(@Context final HttpServletRequest request, @Context final HttpServletResponse response, @PathParam("actionId") final String actionId, @@ -1132,6 +1615,7 @@ public final Response updateAction(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) public final Response saveActionToStep(@Context final HttpServletRequest request, @Context final HttpServletResponse response, @PathParam("stepId") final String stepId, @@ -1166,6 +1650,7 @@ public final Response saveActionToStep(@Context final HttpServletRequest request @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) public final Response saveActionletToAction(@Context final HttpServletRequest request, @PathParam("actionId") final String actionId, final WorkflowActionletActionForm workflowActionletActionForm) { @@ -1340,6 +1825,7 @@ public final Response deleteActionlet(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) public final Response reorderStep(@Context final HttpServletRequest request, @Context final HttpServletResponse response, @PathParam("stepId") final String stepId, @@ -1373,6 +1859,7 @@ public final Response reorderStep(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) public final Response updateStep(@Context final HttpServletRequest request, @Context final HttpServletResponse response, @NotNull @PathParam("stepId") final String stepId, @@ -1402,6 +1889,7 @@ public final Response updateStep(@Context final HttpServletRequest request, @JSONP @NoCache @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) + @Consumes({MediaType.APPLICATION_JSON}) public final Response addStep(@Context final HttpServletRequest request, @Context final HttpServletResponse response, final WorkflowStepAddForm newStepForm) { @@ -1955,6 +2443,7 @@ private void saveMultipleContentletsByDefaultAction(final List