| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| === Workflow |
| |
| Workflow manages the internal identity lifecycle by defining statuses and transitions that every user, group or any |
| object in Apache Syncope will traverse. A workflow instance is started once identities get created, and shut down when |
| they are removed. |
| |
| Workflow is triggered during the <<provisioning,provisioning>> process as the first step in creating, updating or deleting |
| identities into the internal storage. |
| |
| [[workflow-adapters]] |
| [NOTE] |
| .Workflow Adapters |
| ==== |
| The workflow features are defined by the workflow adapter interfaces: |
| |
| ifeval::["{snapshotOrRelease}" == "release"] |
| * https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java[UserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| * https://github.com/apache/syncope/blob/master/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java[UserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "release"] |
| * https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java[GroupWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| * https://github.com/apache/syncope/blob/master/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java[GroupWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "release"] |
| * https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java[AnyObjectWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| * https://github.com/apache/syncope/blob/master/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java[AnyObjectWorkflowAdapter^] |
| endif::[] |
| |
| Default implementations are available: |
| |
| ifeval::["{snapshotOrRelease}" == "release"] |
| * https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java[DefaultUserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| * https://github.com/apache/syncope/blob/master/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java[DefaultUserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "release"] |
| * https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java[DefaultGroupWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| * https://github.com/apache/syncope/blob/master/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java[DefaultGroupWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "release"] |
| * https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java[DefaultAnyObjectWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| * https://github.com/apache/syncope/blob/master/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java[DefaultAnyObjectWorkflowAdapter^] |
| endif::[] |
| |
| Custom adapters can be provided by implementing the related interfaces, also as bridges towards third-party tools as |
| https://camunda.org/[Camunda^] or http://jbpm.jboss.org/[jBPM^]. |
| ==== |
| |
| [[which-user-worflow-adapter]] |
| [TIP] |
| .Which workflow adapter for users? |
| ==== |
| . Do you need <<approval,approval>> management? <<flowable-user-workflow-adapter,Flowable>> |
| . If approval management is not needed, do you want to customize the internal user processing, or attach custom logic |
| to it? Provide a Java class with your customizations, extending |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java[DefaultUserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/tree/master/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java[DefaultUserWorkflowAdapter^] |
| endif::[] |
| . No approval nor customizations needed? Stick with |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java[DefaultUserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/tree/master/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java[DefaultUserWorkflowAdapter^] |
| endif::[] |
| ==== |
| |
| ==== Flowable User Workflow Adapter |
| |
| An advanced adapter is provided for Users, based on http://www.flowable.org/[Flowable^], one of reference open |
| source http://www.bpmn.org/[BPMN 2.0^] implementations. |
| |
| The |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserWorkflowAdapter.java[FlowableUserWorkflowAdapter^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/blob/master/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserWorkflowAdapter.java[FlowableUserWorkflowAdapter^] |
| endif::[] |
| is bootstrapped from |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/ext/flowable/flowable-bpmn/src/main/resources/userWorkflow.bpmn20.xml[userWorkflow.bpmn20.xml^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/blob/master/ext/flowable/flowable-bpmn/src/main/resources/userWorkflow.bpmn20.xml[userWorkflow.bpmn20.xml^] |
| endif::[] |
| and presents several advantages and more features, if compared to the default user adapter: |
| |
| . Besides mandatory statuses, which are modeled as BPMN `userTask` instances, more can be freely added |
| at runtime, provided that adequate transitions and conditions are also inserted; more details about available BPMN |
| constructs are available in the http://www.flowable.org/docs/userguide/index.html#bpmnConstructs[Flowable User Guide^]. + |
| Additional statuses and transitions allow the internal processes of Apache Syncope to better adapt to suit organizational flows. |
| . Custom logic can be injected into the workflow process by providing BPMN `serviceTask` instances. |
| . http://www.flowable.org/docs/userguide/index.html#forms[Flowable forms^] are used for implementing <<approval,approval>>. |
| . The http://www.flowable.org/docs/userguide/index.html#flowableModelerApp[Flowable Modeler^] is available with the |
| <<admin-console,admin console>>, thus allowing web-based graphical modeling of the workflow definition. |
| |
| [.text-center] |
| image::userWorkflow.png[title="Default Flowable user workflow",alt="Default Flowable user workflow"] |
| |
| ===== Approval |
| |
| Every transition in the Flowable user workflow definition can be subjected to approval. |
| |
| The underlying idea is that some kind of self-modifications (group memberships, external resource assignments, ...) |
| might not be allowed to 'plain' Users, as there could be conditions which require management approval. |
| Managers could also be asked to complete the information provided before the requested operation is finished. |
| |
| In order to define an approval form, a dedicated BPMN `userTask` needs to be defined, following the rules established |
| for http://www.flowable.org/docs/userguide/index.html#forms[Flowable forms^]. |
| |
| [NOTE] |
| .What is required for administrators to manage approval? |
| ==== |
| The following conditions must be met, for an User `U` to act as administrator for approval: |
| |
| . `U` must own the following <<entitlements,entitlements>>, for all the required realms: |
| .. `USER_REQUEST_FORM_CLAIM` |
| .. `USER_REQUEST_FORM_LIST` |
| .. `USER_REQUEST_FORM_SUBMIT` |
| .. `USER_READ` |
| . The BPMN `userTask` must either indicate `U` among `candidateUsers` or at least one of the groups assigned to `U` |
| among `candidateGroups`, as required by |
| http://www.flowable.org/docs/userguide/index.html#bpmnUserTaskUserAssignmentExtension[Flowable's task assignment rules^] |
| |
| The special super-user `admin` is entitled to manage all approvals, even those not specifying any |
| `candidateUsers` or `candidateGroups`. |
| ==== |
| |
| [[sample-selfreg-approval]] |
| .Approving self-registration |
| ==== |
| The snippet below shows how to define an approval form in XML; the same operation can be performed via the |
| http://www.flowable.org/docs/userguide/index.html#flowableModelerApp[Flowable Modeler^]. |
| |
| [source,xml] |
| ---- |
| <userTask id="createApproval" name="Create approval" |
| flowable:candidateGroups="managingDirector" flowable:formKey="createApproval"> // <1> |
| <extensionElements> |
| <flowable:formProperty id="username" name="Username" type="string" |
| expression="${userTO.username}" writable="false"/> // <2> |
| <flowable:formProperty id="approve" name="Approve?" type="boolean" |
| variable="approve" required="true"/> // <3> |
| <flowable:formProperty id="rejectReason" name="Reason for rejecting" type="string" |
| variable="rejectReason"/> |
| </extensionElements> |
| </userTask> |
| ---- |
| <1> `formKey` and `id` must be unique across the workflow definition, `name` is displayed by the admin console; |
| `candidateGroups` and `candidateUsers` might be defined, even both, to indicate which Groups or Users should be |
| managing these approvals; if none are specified, only `admin` is entitled to manage such approval |
| <2> `expression` will be evaluated against the current requesting `user` (as workflow variable) and related properties; |
| read-only form input can be defined by setting `writable="false"` |
| <3> exporting approval inputs into workflow variables is possible via the `variable` attribute; required form input can |
| be defined by setting `required="true"` |
| ==== |
| |
| Once the form is defined, any modification subject to that approval will be manageable via the admin console, according to |
| the following flow (the actual operations on the admin console for the sample above are reported <<console-approval,below>>): |
| |
| . administrator A sees the new approval notifications + |
| . administrator A claims the approval and is then allowed to manage it |
| . administrator A reviews the updated user, with ongoing modification applied (no actual modification performed yet) |
| . administrator A can approve or reject such modification |
| |
| ===== Request Management |
| |
| Request management is a key-feature of Identity Governance and allows to define and manage, in a structured way, |
| whatever process intended to update identity attributes, memberships and relationships. + |
| Request examples are "assign mobile phone", "grant groups on AD" or "consent access to application". |
| |
| Users can initiate whichever request among the ones defined; once initiated, such requests will follow their own path, |
| which might also include one or more <<approval,approval>> steps. |
| |
| [[sample-user-request]] |
| .Assigning printer to user |
| ==== |
| The BPMN process below shows how to define an user request in XML; the same operation can be performed via the |
| http://www.flowable.org/docs/userguide/index.html#flowableModelerApp[Flowable Modeler^]. |
| |
| In this user request definition: |
| |
| . user selects one of printers defined in the system, for self-assignment |
| . administrator approves user's selection |
| . a <<memberships-relationships,relationship>> between user and printer is established |
| |
| [source,xml] |
| ---- |
| <process id="assignPrinterRequest" name="Assign printer" isExecutable="true"> |
| <startEvent id="startevent1" name="Start"/> |
| <endEvent id="endevent1" name="End"/> |
| <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="selectPrinter"/> |
| <userTask id="selectPrinter" name="Select printer" flowable:formKey="selectPrinter" |
| flowable:assignee="${wfExecutor}"> // <1> |
| <extensionElements> |
| <flowable:formProperty id="printer" name="Printer" |
| variable="printer" type="dropdown" required="true"> // <2> |
| <flowable:value id="dropdownValueProvider" name="printersValueProvider"/> |
| </flowable:formProperty> |
| <flowable:formProperty id="printMode" name="Preferred print mode?" type="enum"> |
| <flowable:value id="bw" name="Black / White"/> |
| <flowable:value id="color" name="Color"/> |
| </flowable:formProperty> |
| </extensionElements> |
| </userTask> |
| <userTask id="approvePrinter" name="Approve printer" flowable:formKey="approvePrinter"> // <3> |
| <extensionElements> |
| <flowable:formProperty id="username" name="Username" type="string" |
| expression="${userTO.username}" writable="false"/> |
| <flowable:formProperty id="printer" name="Selected printer" type="string" |
| expression="${printer}" writable="false"/> |
| <flowable:formProperty id="approve" name="Approve?" type="boolean" |
| variable="approve" required="true"/> |
| </extensionElements> |
| </userTask> |
| <sequenceFlow id="sid-D7047714-8E57-46B8-B6D4-4844DE330329" |
| sourceRef="selectPrinter" targetRef="approvePrinter"/> |
| <serviceTask id="createARelationship" name="Create ARelationship" |
| flowable:delegateExpression="${createARelationship}"/> // <4> |
| <sequenceFlow id="sid-33880AE7-35C6-4A39-8E5B-12D8BA53F042" |
| sourceRef="approvePrinter" targetRef="createARelationship"/> |
| <sequenceFlow id="sid-831E1896-EDF9-4F7D-AA42-E86CC1F8C5D3" |
| sourceRef="createARelationship" targetRef="endevent1"/> |
| </process> |
| ---- |
| <1> the first form defined is self-assigned to the user which has started this request |
| <2> the `dropdown` type is a Syncope extension of the |
| https://www.flowable.org/docs/userguide/index.html#formProperties[form property types supported by Flowable^] |
| and allows to inject a list of elements via the `dropdownValueProvider` value (with name `printersValueProvider` in this |
| sample), which must be a Spring bean implementing the |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/DropdownValueProvider.java[DropdownValueProvider^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/blob/master/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/DropdownValueProvider.java[DropdownValueProvider^] |
| endif::[] |
| interface |
| <3> the second form is a traditional approval form, as seen <<sample-selfreg-approval,above>> |
| <4> this is a |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/task/FlowableServiceTask.java[FlowableServiceTask^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/blob/master/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/task/FlowableServiceTask.java[FlowableServiceTask^] |
| endif::[] |
| implementation which takes care of establishing the relationship |
| ==== |