Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#30629 adding the first step + postmans #30631

Merged
merged 4 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.dotmarketing.portlets.workflows.model.WorkflowAction;
import com.dotmarketing.portlets.workflows.model.WorkflowScheme;
import com.dotmarketing.portlets.workflows.model.WorkflowStep;

/**
* View just to encapsulate a scheme and an action for the default workflow actions
Expand All @@ -11,11 +12,13 @@ public class WorkflowDefaultActionView {

private final WorkflowScheme scheme;
private final WorkflowAction action;
private final WorkflowStep firstStep;

public WorkflowDefaultActionView(WorkflowScheme scheme, WorkflowAction action) {
public WorkflowDefaultActionView(final WorkflowScheme scheme, final WorkflowAction action, final WorkflowStep step) {

this.scheme = scheme;
this.action = action;
this.firstStep = step;
}

public WorkflowScheme getScheme() {
Expand All @@ -25,4 +28,8 @@ public WorkflowScheme getScheme() {
public WorkflowAction getAction() {
return action;
}

public WorkflowStep getFirstStep() {
return firstStep;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5209,7 +5209,7 @@ public final Response copyScheme(@Context final HttpServletRequest httpServletRe
@ApiResponse(responseCode = "500", description = "Internal Server Error")
}
)
public final Response findAvailableDefaultActionsByContentType(@Context final HttpServletRequest request,
public final ResponseEntityDefaultWorkflowActionsView findAvailableDefaultActionsByContentType(@Context final HttpServletRequest request,
@Context final HttpServletResponse response,
@PathParam("contentTypeId") @Parameter(
required = true,
Expand All @@ -5220,18 +5220,11 @@ public final Response findAvailableDefaultActionsByContentType(@Context final Ht
) final String contentTypeId) {
final InitDataObject initDataObject = this.webResource.init
(null, request, response, true, null);
try {
Logger.debug(this,
() -> "Getting the available workflow schemes default action for the ContentType: "
+ contentTypeId );
final List<WorkflowDefaultActionView> actions = this.workflowHelper.findAvailableDefaultActionsByContentType(contentTypeId, initDataObject.getUser());
return Response.ok(new ResponseEntityView<>(actions)).build(); // 200
} catch (Exception e) {
Logger.error(this.getClass(),
"Exception on find Available Default Actions exception message: " + e.getMessage(), e);
return ResponseUtil.mapExceptionResponse(e);
}

return new ResponseEntityDefaultWorkflowActionsView(actions);
} // findAvailableDefaultActionsByContentType.

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import com.liferay.portal.language.LanguageUtil;
import com.liferay.portal.model.User;
import com.liferay.util.StringPool;
import io.vavr.control.Try;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.velocity.context.Context;
Expand Down Expand Up @@ -1775,14 +1776,16 @@ public WorkflowAction getAction() {
public List<WorkflowDefaultActionView> findAvailableDefaultActionsByContentType(final String contentTypeId, final User user) {
final ContentTypeAPI contentTypeAPI = APILocator.getContentTypeAPI(user);
final ImmutableList.Builder<WorkflowDefaultActionView> results = new ImmutableList.Builder<>();
final Map<String, WorkflowStep> steps = new HashMap<>();
try {

Logger.debug(this, () -> "Getting the available default workflows actions by content type: " + contentTypeId);
//When no license is available. This should get the system workflow.
final List<WorkflowAction> actions = this.workflowAPI.findAvailableDefaultActionsByContentType(contentTypeAPI.find(contentTypeId), user);
for (final WorkflowAction action : actions){
final WorkflowScheme scheme = this.workflowAPI.findScheme(action.getSchemeId());
final WorkflowDefaultActionView value = new WorkflowDefaultActionView(scheme, action);
steps.computeIfAbsent(scheme.getId(), k -> Try.of(()->this.workflowAPI.findFirstStep(scheme.getId()).orElse(null)).get());
final WorkflowDefaultActionView value = new WorkflowDefaultActionView(scheme, action, steps.get(scheme.getId()));
results.add(value);
}

Expand Down Expand Up @@ -1888,9 +1891,11 @@ public List<WorkflowDefaultActionView> findInitialAvailableActionsByContentType(
*/
private List<WorkflowDefaultActionView> buildDefaultActionsViewObj(final List<WorkflowAction> actions) throws DotDataException, DotSecurityException {
final ImmutableList.Builder<WorkflowDefaultActionView> results = new ImmutableList.Builder<>();
final Map<String, WorkflowStep> steps = new HashMap<>();
for (final WorkflowAction action : actions) {
final WorkflowScheme scheme = this.workflowAPI.findScheme(action.getSchemeId());
final WorkflowDefaultActionView value = new WorkflowDefaultActionView(scheme, action);
steps.computeIfAbsent(scheme.getId(), k -> Try.of(()->this.workflowAPI.findFirstStep(scheme.getId()).orElse(null)).get());
final WorkflowDefaultActionView value = new WorkflowDefaultActionView(scheme, action, steps.get(scheme.getId()));
results.add(value);
}
return results.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.dotmarketing.business.Role;
import com.dotmarketing.business.RoleAPI;
import com.dotmarketing.db.LocalTransaction;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.contentlet.business.ContentletAPI;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.dotmarketing.portlets.workflows.business.WorkflowAPI;
Expand Down Expand Up @@ -614,17 +615,16 @@ public void Find_Available_Actions_Invalid_License() throws Exception {
public void Find_Available_Default_Actions_Invalid_License() throws Exception {
final HttpServletRequest request = mock(HttpServletRequest.class);
final ContentType contentType = new ContentTypeDataGen().nextPersisted();// Uses the System Workflow by default
final Response response = nonLicenseWorkflowResource.findAvailableDefaultActionsByContentType(request, new EmptyHttpResponse(), contentType.id());
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
ResponseEntityView ev = ResponseEntityView.class.cast(response.getEntity());
List<WorkflowDefaultActionView> actions = List.class.cast(ev.getEntity());
final ResponseEntityDefaultWorkflowActionsView response = nonLicenseWorkflowResource.findAvailableDefaultActionsByContentType(request, new EmptyHttpResponse(), contentType.id());
assertNotNull(response);
List<WorkflowDefaultActionView> actions = response.getEntity();
for(WorkflowDefaultActionView av:actions){
assertTrue(av.getScheme().isSystem());
}
}

@SuppressWarnings("unchecked")
@Test
@Test(expected = DotSecurityException.class)
public void Find_Available_Default_Actions_No_Read_Permission_Invalid_License()
throws Exception {

Expand All @@ -637,10 +637,8 @@ public void Find_Available_Default_Actions_No_Read_Permission_Invalid_License()
BaseContentType.CONTENT, editPermission, role.getId());

final HttpServletRequest request = mock(HttpServletRequest.class);
final Response findResponse = nonLicenseWorkflowResource
final ResponseEntityDefaultWorkflowActionsView findResponse = nonLicenseWorkflowResource
.findAvailableDefaultActionsByContentType(request, new EmptyHttpResponse(), contentType.id());
assertEquals(Status.FORBIDDEN.getStatusCode(), findResponse.getStatus());
assertEquals(ACCESS_CONTROL_HEADER_PERMISSION_VIOLATION, findResponse.getHeaderString("access-control"));
} finally {
if(contentType != null){
APILocator.getContentTypeAPI(APILocator.systemUser()).delete(contentType);
Expand Down
136 changes: 113 additions & 23 deletions dotcms-postman/src/main/resources/postman/Workflow_Resource_Tests.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info": {
"_postman_id": "551fc73a-c338-498a-9aeb-b4f19b1708f9",
"_postman_id": "679e6657-065b-41a2-b666-672f59b9e95c",
"name": "Workflow Resource Tests [/api/v1/workflows]",
"description": "Test the necesary validations to every end point of the worlflow resource ",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
Expand Down Expand Up @@ -4109,34 +4109,29 @@
"",
"pm.test(\"Valid response\", function () {",
" pm.expect(pm.response.text()).to.include(\"Save\");",
"});",
"",
"",
"pm.test(\"Response has expected properties\", function () {",
" const jsonData = pm.response.json();",
" pm.expect(jsonData.entity[0]).to.have.property(\"action\");",
" pm.expect(jsonData.entity[0]).to.have.property(\"firstStep\");",
" pm.expect(jsonData.entity[0]).to.have.property(\"scheme\");",
"});"
],
"type": "text/javascript"
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "password",
"value": "admin",
"type": "string"
},
"type": "bearer",
"bearer": [
{
"key": "username",
"value": "[email protected]",
"key": "token",
"value": "{{jwt}}",
"type": "string"
},
{
"key": "saveHelperData",
"type": "any"
},
{
"key": "showPassword",
"value": false,
"type": "boolean"
}
]
},
Expand Down Expand Up @@ -17773,6 +17768,96 @@
}
},
"response": []
},
{
"name": "CreateComment",
"event": [
{
"listen": "test",
"script": {
"exec": [
"",
"// Test to check that the response has a 200 OK status",
"pm.test(\"Status code is 200\", function () {",
" pm.response.to.have.status(200);",
"});",
"",
"// Test to check that the JSON response has the main properties",
"pm.test(\"Response has expected properties\", function () {",
" const jsonData = pm.response.json();",
" pm.expect(jsonData).to.have.property(\"entity\");",
" pm.expect(jsonData).to.have.property(\"errors\");",
" pm.expect(jsonData).to.have.property(\"i18nMessagesMap\");",
" pm.expect(jsonData).to.have.property(\"messages\");",
" pm.expect(jsonData).to.have.property(\"pagination\");",
" pm.expect(jsonData).to.have.property(\"permissions\");",
"});",
"",
"// Test to check that \"entity\" has the expected properties",
"pm.test(\"Entity has expected properties\", function () {",
" const entity = pm.response.json().entity;",
" pm.expect(entity).to.have.property(\"commentDescription\").that.is.a(\"string\");",
" pm.expect(entity).to.have.property(\"createdDate\").that.is.a(\"number\");",
" pm.expect(entity).to.have.property(\"postedBy\").that.is.a(\"string\");",
" pm.expect(entity).to.have.property(\"roleId\").that.is.a(\"string\");",
" pm.expect(entity).to.have.property(\"taskId\").that.is.a(\"string\");",
" pm.expect(entity).to.have.property(\"type\").that.is.a(\"string\");",
"",
" // Check specific values",
" pm.expect(entity.type).to.equal(\"WorkflowComment\");",
" pm.expect(entity.postedBy).to.equal(\"Admin User\");",
"});",
"",
"// Test to check that \"errors\" is an empty array",
"pm.test(\"Errors array is empty\", function () {",
" const errors = pm.response.json().errors;",
" pm.expect(errors).to.be.an(\"array\").that.is.empty;",
"});",
"",
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{jwt}}",
"type": "string"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"comment\":\"This is a postman test\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{serverURL}}/api/v1/workflow/{{identifier}}/comments",
"host": [
"{{serverURL}}"
],
"path": [
"api",
"v1",
"workflow",
"{{identifier}}",
"comments"
]
}
},
"response": []
}
]
},
Expand Down Expand Up @@ -17857,10 +17942,12 @@
"listen": "test",
"script": {
"exec": [
"// Test para verificar que la respuesta tiene el estado 200 OK",
"pm.test(\"Status code is 200\", function () {",
" pm.response.to.have.status(200);",
"});",
"",
"// Test para verificar que el JSON de respuesta tiene las propiedades principales",
"pm.test(\"Response has expected properties\", function () {",
" const jsonData = pm.response.json();",
" pm.expect(jsonData).to.have.property(\"entity\");",
Expand All @@ -17871,11 +17958,13 @@
" pm.expect(jsonData).to.have.property(\"permissions\");",
"});",
"",
"// Test para verificar que \"entity\" es un array y tiene al menos un elemento",
"pm.test(\"Entity is an array and contains items\", function () {",
" const entity = pm.response.json().entity;",
" pm.expect(entity).to.be.an(\"array\").that.is.not.empty;",
"});",
"",
"// Test para verificar las propiedades de los objetos dentro de \"entity\"",
"pm.test(\"Each entity item has expected properties\", function () {",
" const entity = pm.response.json().entity;",
" entity.forEach(item => {",
Expand Down Expand Up @@ -17907,13 +17996,15 @@
" pm.expect(item).to.have.property(\"schemeId\").that.is.a(\"string\");",
" pm.expect(item).to.have.property(\"showOn\").that.is.an(\"array\");",
" ",
" // Verificación adicional: que \"showOn\" contiene valores específicos esperados",
" const allowedShowOnValues = [\"NEW\", \"LISTING\", \"PUBLISHED\", \"UNLOCKED\", \"ARCHIVED\", \"UNPUBLISHED\", \"EDITING\", \"LOCKED\"];",
" item.showOn.forEach(status => {",
" pm.expect(allowedShowOnValues).to.include(status);",
" });",
" });",
"});",
"",
"// Test para verificar que \"errors\" es un array vacío",
"pm.test(\"Errors array is empty\", function () {",
" const errors = pm.response.json().errors;",
" pm.expect(errors).to.be.an(\"array\").that.is.empty;",
Expand Down Expand Up @@ -17964,7 +18055,7 @@
]
},
{
"name": "Commentable",
"name": "Resetable",
"item": [
{
"name": "CreateContentPreconditions",
Expand Down Expand Up @@ -18038,7 +18129,7 @@
"response": []
},
{
"name": "CheckCommentable",
"name": "CheckResetable",
"event": [
{
"listen": "test",
Expand Down Expand Up @@ -18081,7 +18172,6 @@
" pm.expect(item).to.have.property(\"hasSaveActionlet\").that.is.a(\"boolean\");",
" pm.expect(item).to.have.property(\"hasUnarchiveActionlet\").that.is.a(\"boolean\");",
" pm.expect(item).to.have.property(\"hasUnpublishActionlet\").that.is.a(\"boolean\");",
" pm.expect(item).to.have.property(\"hasCommentActionlet\").that.is.a(\"boolean\");",
" pm.expect(item).to.have.property(\"icon\").that.is.a(\"string\");",
" pm.expect(item).to.have.property(\"id\").that.is.a(\"string\");",
" pm.expect(item).to.have.property(\"name\").that.is.a(\"string\");",
Expand Down
Loading