This is an automated email from the ASF dual-hosted git repository. skylark17 pushed a commit to branch 2_1_X in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/2_1_X by this push: new 83bc0ec [SYNCOPE-1394] Added unclaim capability for user requests 83bc0ec is described below commit 83bc0ec2428e91f36d6d261e6369bcf5ddd92604 Author: skylark17 <matteo.alessandr...@tirasa.net> AuthorDate: Fri Nov 30 10:15:16 2018 +0100 [SYNCOPE-1394] Added unclaim capability for user requests --- .../wicket/markup/html/form/ActionLink.java | 1 + .../wicket/markup/html/form/ActionPanel.properties | 4 ++ .../panels/UserRequestFormDirectoryPanel.java | 36 +++++++++++- .../client/console/rest/UserRequestRestClient.java | 4 ++ .../client/console/pages/UserRequests.properties | 3 +- .../console/pages/UserRequests_it.properties | 3 +- .../console/pages/UserRequests_ja.properties | 3 +- .../console/pages/UserRequests_pt_BR.properties | 3 +- .../console/pages/UserRequests_ru.properties | 3 +- .../widgets/UserRequestFormsWidget.properties | 2 +- .../widgets/UserRequestFormsWidget_it.properties | 2 +- .../widgets/UserRequestFormsWidget_ja.properties | 2 +- .../UserRequestFormsWidget_pt_BR.properties | 2 +- .../widgets/UserRequestFormsWidget_ru.properties | 2 +- .../syncope/common/lib/to/UserRequestForm.java | 10 ++-- .../common/lib/types/FlowableEntitlement.java | 2 + .../core/flowable/api/UserRequestHandler.java | 8 +++ .../flowable/impl/FlowableUserRequestHandler.java | 42 +++++++++++--- .../syncope/core/logic/UserRequestLogic.java | 9 +++ .../rest/api/service/UserRequestService.java | 14 ++++- .../rest/cxf/service/UserRequestServiceImpl.java | 5 ++ .../apache/syncope/fit/core/UserSelfITCase.java | 66 +++++++++++++++++++--- 22 files changed, 192 insertions(+), 34 deletions(-) diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java index 7f8ade0..dd53e21 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java @@ -68,6 +68,7 @@ public abstract class ActionLink<T extends Serializable> implements Serializable REQUEST_PASSWORD_RESET("update"), DRYRUN("execute"), CLAIM("claim"), + UNCLAIM("unclaim"), SELECT("read"), CLOSE("read"), EXPORT("read"), diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.properties index af1d580..698e4cc 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.properties +++ b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionPanel.properties @@ -142,6 +142,10 @@ claim.class=fa fa-ticket claim.title=claim claim.alt=claim icon +unclaim.class=fa fa-undo +unclaim.title=unclaim +unclaim.alt=unclaim icon + select.class=glyphicon glyphicon-ok select.title=select select.alt=select icon diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/UserRequestFormDirectoryPanel.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/UserRequestFormDirectoryPanel.java index bf82896..c6b254b 100644 --- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/UserRequestFormDirectoryPanel.java +++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/panels/UserRequestFormDirectoryPanel.java @@ -132,7 +132,7 @@ public class UserRequestFormDirectoryPanel columns.add(new DatePropertyColumn<>( new ResourceModel("dueDate"), "dueDate", "dueDate")); columns.add(new PropertyColumn<>( - new ResourceModel("owner"), "owner", "owner")); + new ResourceModel("assignee"), "assignee", "assignee")); return columns; } @@ -152,10 +152,32 @@ public class UserRequestFormDirectoryPanel ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); target.add(container); } + }, ActionLink.ActionType.CLAIM, FlowableEntitlement.USER_REQUEST_FORM_CLAIM); panel.add(new ActionLink<UserRequestForm>() { + private static final long serialVersionUID = -4496313424398213416L; + + @Override + public void onClick(final AjaxRequestTarget target, final UserRequestForm ignore) { + unclaimForm(model.getObject().getTaskId()); + SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED)); + UserRequestFormDirectoryPanel.this.getTogglePanel().close(target); + target.add(container); + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + + @Override + protected boolean statusCondition(final UserRequestForm modelObject) { + return SyncopeConsoleSession.get().getSelfTO().getUsername(). + equals(model.getObject().getAssignee()); + } + + }, ActionLink.ActionType.UNCLAIM, FlowableEntitlement.USER_REQUEST_FORM_UNCLAIM); + + panel.add(new ActionLink<UserRequestForm>() { + private static final long serialVersionUID = -3722207913631435501L; @Override @@ -188,7 +210,7 @@ public class UserRequestFormDirectoryPanel @Override protected boolean statusCondition(final UserRequestForm modelObject) { return SyncopeConsoleSession.get().getSelfTO().getUsername(). - equals(model.getObject().getOwner()); + equals(model.getObject().getAssignee()); } }, ActionLink.ActionType.MANAGE_APPROVAL, FlowableEntitlement.USER_REQUEST_FORM_SUBMIT); @@ -237,7 +259,7 @@ public class UserRequestFormDirectoryPanel @Override protected boolean statusCondition(final UserRequestForm modelObject) { return SyncopeConsoleSession.get().getSelfTO().getUsername(). - equals(model.getObject().getOwner()); + equals(model.getObject().getAssignee()); } }, ActionLink.ActionType.EDIT_APPROVAL, FlowableEntitlement.USER_REQUEST_FORM_SUBMIT); @@ -305,6 +327,14 @@ public class UserRequestFormDirectoryPanel } } + private void unclaimForm(final String taskId) { + try { + restClient.unclaimForm(taskId); + } catch (SyncopeClientException scee) { + SyncopeConsoleSession.get().error(getString(Constants.ERROR) + ": " + scee.getMessage()); + } + } + private class FormUserWizardBuilder extends UserWizardBuilder { private static final long serialVersionUID = 1854981134836384069L; diff --git a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java index 8d3b03b..7921249 100644 --- a/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java +++ b/ext/flowable/client-console/src/main/java/org/apache/syncope/client/console/rest/UserRequestRestClient.java @@ -73,6 +73,10 @@ public class UserRequestRestClient extends BaseRestClient { return getService(UserRequestService.class).claimForm(taskKey); } + public UserRequestForm unclaimForm(final String taskKey) { + return getService(UserRequestService.class).unclaimForm(taskKey); + } + public void submitForm(final UserRequestForm form) { getService(UserRequestService.class).submitForm(form); } diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests.properties index 9f30811..41ac106 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests.properties @@ -19,8 +19,9 @@ key=Key description=Description createTime=Create Time dueDate=Due Date -owner=Owner +assignee=Assignee claim=Claim +unclaim=Unclaim manage=Manage userRequests=User Requests delete=Delete diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_it.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_it.properties index 04f5462..e355780 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_it.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_it.properties @@ -19,8 +19,9 @@ key=Chiave description=Descrizione createTime=Data di creazione dueDate=Scadenza -owner=Esecutore +assignee=Esecutore claim=Richiedi +unclaim=Annulla richiesta manage=Gestisci userRequests=Richieste utente delete=Rimuovi diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ja.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ja.properties index 61fef13..51ae26a 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ja.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ja.properties @@ -19,8 +19,9 @@ key=\u30ad\u30fc description=\u8aac\u660e createTime=\u4f5c\u6210\u6642\u523b dueDate=\u671f\u9650 -owner=\u30aa\u30fc\u30ca\u30fc +assignee=\u30aa\u30fc\u30ca\u30fc claim=\u7533\u8acb +unclaim=\u7533\u3057\u7acb\u3066\u3092\u53d6\u308a\u6d88\u3059 manage=\u7ba1\u7406 userRequests=User Requests delete=\u524a\u9664 diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_pt_BR.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_pt_BR.properties index 65c43f4..e9c3e92 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_pt_BR.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_pt_BR.properties @@ -19,8 +19,9 @@ key=Chave description=Descri\u00e7\u00e3o createTime=Tempo de Cria\u00e7\u00e3o dueDate=Data acordada -owner=Propriet\u00e1rio +assignee=Propriet\u00e1rio claim=Requerimento +unclaim=Cancelar requerimento manage=Ger\u00eancia userRequests=User Requests delete=Excluir diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ru.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ru.properties index 52b454b..f97c4ef 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ru.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/pages/UserRequests_ru.properties @@ -26,9 +26,10 @@ createTime=\u0414\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u # dueDate=\u00d0\u00a1\u00d1\u0080\u00d0\u00be\u00d0\u00ba dueDate=\u0421\u0440\u043e\u043a # owner=\u00d0\u0092\u00d0\u00bb\u00d0\u00b0\u00d0\u00b4\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d1\u0086 -owner=\u0412\u043b\u0430\u0434\u0435\u043b\u0435\u0446 +assignee=\u0412\u043b\u0430\u0434\u0435\u043b\u0435\u0446 # claim=\u00d0\u0092\u00d1\u008b\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d1\u0081\u00d0\u00be\u00d0\u00b3\u00d0\u00bb\u00d0\u00b0\u00d1\u0081\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 claim=\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0435 +unclaim=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 # manage=\u00d0\u00a3\u00d0\u00bf\u00d1\u0080\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 manage=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 # approvals=\u00d0\u0097\u00d0\u00b0\u00d1\u008f\u00d0\u00b2\u00d0\u00ba\u00d0\u00b8 diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget.properties index 36e1e2e..753a2d8 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget.properties @@ -16,5 +16,5 @@ # under the License. alerts.view.all=View all forms duedate=Due date -owner=Owner +assignee=Assignee summary=${number} pending form(s) diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_it.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_it.properties index bf3e9ad..796636e 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_it.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_it.properties @@ -16,5 +16,5 @@ # under the License. alerts.view.all=Tutte le form duedate=Scadenza -owner=Assegnato +assignee=Assegnato summary=${number} form pendenti diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ja.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ja.properties index 0d938e3..ef5d77f 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ja.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ja.properties @@ -16,5 +16,5 @@ # under the License. alerts.view.all=View all forms duedate=\u671f\u9650 -owner=\u30aa\u30fc\u30ca\u30fc +assignee=\u30aa\u30fc\u30ca\u30fc summary=${number} pending form(s) diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_pt_BR.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_pt_BR.properties index 36e1e2e..753a2d8 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_pt_BR.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_pt_BR.properties @@ -16,5 +16,5 @@ # under the License. alerts.view.all=View all forms duedate=Due date -owner=Owner +assignee=Assignee summary=${number} pending form(s) diff --git a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ru.properties b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ru.properties index e713681..bb1fa45 100644 --- a/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ru.properties +++ b/ext/flowable/client-console/src/main/resources/org/apache/syncope/client/console/widgets/UserRequestFormsWidget_ru.properties @@ -17,5 +17,5 @@ # alerts.view.all=View all forms duedate=\u0421\u0440\u043e\u043a -owner=\u0412\u043b\u0430\u0434\u0435\u043b\u0435\u0446 +assignee=\u0412\u043b\u0430\u0434\u0435\u043b\u0435\u0446 summary=${number} pending form(s) diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java index 8508c2c..a073a0b 100644 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequestForm.java @@ -51,7 +51,7 @@ public class UserRequestForm extends BaseBean { private Date dueDate; - private String owner; + private String assignee; private UserTO userTO; @@ -129,12 +129,12 @@ public class UserRequestForm extends BaseBean { } } - public String getOwner() { - return owner; + public String getAssignee() { + return assignee; } - public void setOwner(final String owner) { - this.owner = owner; + public void setAssignee(final String assignee) { + this.assignee = assignee; } public UserTO getUserTO() { diff --git a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java index fbf5b02..0c41c99 100644 --- a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java +++ b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/types/FlowableEntitlement.java @@ -42,6 +42,8 @@ public final class FlowableEntitlement { public static final String USER_REQUEST_FORM_CLAIM = "USER_REQUEST_FORM_CLAIM"; + public static final String USER_REQUEST_FORM_UNCLAIM = "USER_REQUEST_FORM_UNCLAIM"; + public static final String USER_REQUEST_FORM_SUBMIT = "USER_REQUEST_FORM_SUBMIT"; public static final String USER_REQUEST_START = "USER_REQUEST_START"; diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java index c3c6f0d..f7d7a35 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java @@ -103,6 +103,14 @@ public interface UserRequestHandler { * @return updated form */ UserRequestForm claimForm(String taskId); + + /** + * Unclaim a form for a given object. + * + * @param taskId Workflow task to which the form is associated + * @return updated form + */ + UserRequestForm unclaimForm(String taskId); /** * Submit a form. diff --git a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java index ac28126..1f539fb 100644 --- a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java +++ b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java @@ -62,6 +62,7 @@ import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.impl.persistence.entity.HistoricFormPropertyEntity; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.identitylink.api.IdentityLinkType; import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; @@ -310,7 +311,7 @@ public class FlowableUserRequestHandler implements UserRequestHandler { formTO.setDueDate(task.getDueDate()); formTO.setExecutionId(task.getExecutionId()); formTO.setFormKey(task.getFormKey()); - formTO.setOwner(task.getOwner()); + formTO.setAssignee(task.getAssignee()); return formTO; } @@ -328,7 +329,7 @@ public class FlowableUserRequestHandler implements UserRequestHandler { formTO.setDueDate(task.getDueDate()); formTO.setExecutionId(task.getExecutionId()); formTO.setFormKey(task.getFormKey()); - formTO.setOwner(task.getOwner()); + formTO.setAssignee(task.getAssignee()); HistoricActivityInstance historicActivityInstance = engine.getHistoryService(). createHistoricActivityInstanceQuery(). @@ -509,8 +510,8 @@ public class FlowableUserRequestHandler implements UserRequestHandler { query.orderByTaskDueDate(); break; - case "owner": - query.orderByTaskOwner(); + case "assignee": + query.orderByTaskAssignee(); break; default: @@ -570,9 +571,21 @@ public class FlowableUserRequestHandler implements UserRequestHandler { } } + boolean hasAssignees = + engine.getTaskService().getIdentityLinksForTask(taskId).stream().anyMatch(identityLink -> { + return IdentityLinkType.ASSIGNEE.equals(identityLink.getType()); + }); + if (hasAssignees) { + try { + engine.getTaskService().unclaim(taskId); + } catch (FlowableException e) { + throw new WorkflowException("While unclaiming task " + taskId, e); + } + } + Task task; try { - engine.getTaskService().setOwner(taskId, authUser); + engine.getTaskService().claim(taskId, authUser); task = FlowableRuntimeUtils.createTaskQuery(engine, true).taskId(taskId).singleResult(); } catch (FlowableException e) { throw new WorkflowException("While reading task " + taskId, e); @@ -581,6 +594,21 @@ public class FlowableUserRequestHandler implements UserRequestHandler { return FlowableUserRequestHandler.this.getForm(task, parsed.getRight()); } + @Override + public UserRequestForm unclaimForm(final String taskId) { + Pair<Task, TaskFormData> parsed = parseTask(taskId); + + Task task; + try { + engine.getTaskService().unclaim(taskId); + task = FlowableRuntimeUtils.createTaskQuery(engine, true).taskId(taskId).singleResult(); + } catch (FlowableException e) { + throw new WorkflowException("While unclaiming task " + taskId, e); + } + + return FlowableUserRequestHandler.this.getForm(task, parsed.getRight()); + } + private Map<String, String> getPropertiesForSubmit(final UserRequestForm form) { Map<String, String> props = new HashMap<>(); form.getProperties().stream(). @@ -596,9 +624,9 @@ public class FlowableUserRequestHandler implements UserRequestHandler { Pair<Task, TaskFormData> parsed = parseTask(form.getTaskId()); String authUser = AuthContextUtils.getUsername(); - if (!parsed.getLeft().getOwner().equals(authUser)) { + if (!parsed.getLeft().getAssignee().equals(authUser)) { throw new WorkflowException(new IllegalArgumentException("Task " + form.getTaskId() + " assigned to " - + parsed.getLeft().getOwner() + " but submitted by " + authUser)); + + parsed.getLeft().getAssignee() + " but submitted by " + authUser)); } String procInstId = parsed.getLeft().getProcessInstanceId(); diff --git a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java index edff188..d3851cd 100644 --- a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java +++ b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java @@ -144,6 +144,15 @@ public class UserRequestLogic extends AbstractTransactionalLogic<EntityTO> { } @PreAuthorize("isAuthenticated()") + public UserRequestForm unclaimForm(final String taskId) { + UserRequestForm form = userRequestHandler.unclaimForm(taskId); + securityChecks(form.getUsername(), + FlowableEntitlement.USER_REQUEST_FORM_UNCLAIM, + "Unclaiming form " + taskId + " not allowed"); + return form; + } + + @PreAuthorize("isAuthenticated()") @Transactional(readOnly = true) public Pair<Integer, List<UserRequestForm>> getForms( final String userKey, diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java index 11aac50..c58020a 100644 --- a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java +++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java @@ -47,7 +47,8 @@ import org.apache.syncope.common.rest.api.beans.UserRequestQuery; */ @Tag(name = "Flowable") @SecurityRequirements({ - @SecurityRequirement(name = "BasicAuthentication"), + @SecurityRequirement(name = "BasicAuthentication") + , @SecurityRequirement(name = "Bearer") }) @Path("flowable/userRequests") public interface UserRequestService extends JAXRSService { @@ -114,6 +115,17 @@ public interface UserRequestService extends JAXRSService { UserRequestForm claimForm(@NotNull @PathParam("taskId") String taskId); /** + * Cancels request to manage the form for the given task id. + * + * @param taskId workflow task id + * @return the workflow form for the given task id + */ + @POST + @Path("forms/{taskId}/unclaim") + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + UserRequestForm unclaimForm(@NotNull @PathParam("taskId") String taskId); + + /** * Submits a user request form. * * @param form user request form. diff --git a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java index 188d22e..580ca76 100644 --- a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java +++ b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java @@ -68,6 +68,11 @@ public class UserRequestServiceImpl extends AbstractServiceImpl implements UserR public UserRequestForm claimForm(final String taskId) { return logic.claimForm(taskId); } + + @Override + public UserRequestForm unclaimForm(final String taskId) { + return logic.unclaimForm(taskId); + } @Override public PagedResult<UserRequestForm> getForms(final UserRequestFormQuery query) { diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java index 162cb88..63e1672 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java @@ -106,7 +106,7 @@ public class UserSelfITCase extends AbstractITCase { public void createAndApprove() { assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); - // self-create user with membership: goes 'createApproval' with resources and membership but no propagation + // 1. self-create user with membership: goes 'createApproval' with resources and membership but no propagation UserTO userTO = UserITCase.getUniqueSampleTO("anonym...@syncope.apache.org"); userTO.getMemberships().add( new MembershipTO.Builder().group("29f96485-729e-4d31-88a1-6fc60e4677f3").build()); @@ -129,7 +129,7 @@ public class UserSelfITCase extends AbstractITCase { assertEquals(ClientExceptionType.NotFound, e.getType()); } - // now approve and verify that propagation has happened + // 2. now approve and verify that propagation has happened UserRequestForm form = userRequestService.getForms( new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); @@ -141,6 +141,56 @@ public class UserSelfITCase extends AbstractITCase { } @Test + public void createAndUnclaim() { + assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); + + // 1. self-create user with membership: goes 'createApproval' with resources and membership but no propagation + UserTO userTO = UserITCase.getUniqueSampleTO("anonym...@syncope.apache.org"); + userTO.getMemberships().add( + new MembershipTO.Builder().group("29f96485-729e-4d31-88a1-6fc60e4677f3").build()); + userTO.getResources().add(RESOURCE_NAME_TESTDB); + SyncopeClient anonClient = clientFactory.create(); + userTO = anonClient.getService(UserSelfService.class). + create(userTO, true). + readEntity(new GenericType<ProvisioningResult<UserTO>>() { + }).getEntity(); + assertNotNull(userTO); + assertEquals("createApproval", userTO.getStatus()); + assertFalse(userTO.getMemberships().isEmpty()); + assertFalse(userTO.getResources().isEmpty()); + try { + resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userTO.getKey()); + fail(); + } catch (SyncopeClientException e) { + assertEquals(ClientExceptionType.NotFound, e.getType()); + } + + // 2. unclaim and verify that propagation has NOT happened + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); + form = userRequestService.unclaimForm(form.getTaskId()); + assertNull(form.getAssignee()); + assertNotNull(userTO); + assertNotEquals("active", userTO.getStatus()); + try { + resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userTO.getKey()); + fail(); + } catch (Exception e) { + assertNotNull(e); + } + + // 3. approve and verify that propagation has happened + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); + form = userRequestService.claimForm(form.getTaskId()); + form.getProperty("approveCreate").get().setValue(Boolean.TRUE.toString()); + userTO = userRequestService.submitForm(form); + assertNotNull(userTO); + assertEquals("active", userTO.getStatus()); + assertNotNull(resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userTO.getKey())); + } + + @Test public void read() { UserTO user = createUser(UserITCase.getUniqueSampleTO("selfr...@syncope.apache.org")).getEntity(); UserService us2 = clientFactory.create(user.getUsername(), "password123").getService(UserService.class); @@ -428,7 +478,7 @@ public class UserSelfITCase extends AbstractITCase { assertNotNull(form.getUsername()); assertEquals(userTO.getUsername(), form.getUsername()); assertNotNull(form.getTaskId()); - assertNull(form.getOwner()); + assertNull(form.getAssignee()); // 3. claim task as rossini, with role "User manager" granting entitlement to claim forms but not in // groupForWorkflowApproval, designated for approval in workflow definition: fail @@ -457,7 +507,7 @@ public class UserSelfITCase extends AbstractITCase { form = userService3.claimForm(form.getTaskId()); assertNotNull(form); assertNotNull(form.getTaskId()); - assertNotNull(form.getOwner()); + assertNotNull(form.getAssignee()); // 5. reject user form.getProperty("approveCreate").get().setValue(Boolean.FALSE.toString()); @@ -533,7 +583,7 @@ public class UserSelfITCase extends AbstractITCase { assertNotNull(form.getUserTO()); assertEquals(updatedUsername, form.getUserTO().getUsername()); assertNull(form.getUserPatch()); - assertNull(form.getOwner()); + assertNull(form.getAssignee()); // 4. claim task (as admin) form = userRequestService.claimForm(form.getTaskId()); @@ -542,7 +592,7 @@ public class UserSelfITCase extends AbstractITCase { assertNotNull(form.getUserTO()); assertEquals(updatedUsername, form.getUserTO().getUsername()); assertNull(form.getUserPatch()); - assertNotNull(form.getOwner()); + assertNotNull(form.getAssignee()); // 5. approve user (and verify that propagation occurred) form.getProperty("approveCreate").get().setValue(Boolean.TRUE.toString()); @@ -595,7 +645,7 @@ public class UserSelfITCase extends AbstractITCase { new UserRequestFormQuery.Builder().user(created.getKey()).build()).getResult().get(0); assertNotNull(form); assertNotNull(form.getTaskId()); - assertNull(form.getOwner()); + assertNull(form.getAssignee()); assertNotNull(form.getUserTO()); assertNotNull(form.getUserPatch()); assertEquals(patch, form.getUserPatch()); @@ -684,7 +734,7 @@ public class UserSelfITCase extends AbstractITCase { form = userService3.claimForm(form.getTaskId()); assertNotNull(form); assertNotNull(form.getTaskId()); - assertNotNull(form.getOwner()); + assertNotNull(form.getAssignee()); // 4. second claim task by admin form = userRequestService.claimForm(form.getTaskId());