openapi: 3.0.1
info:
  title: ForgeRock Identity Orchestration
  description:  This is the API specification for the Identity Orchestration (workflow) related endpoints and data model for ForgeRock Identity Cloud - Identity Governance (IGA).
  version: "1.0.0"
servers:
  - url: /orchestration
tags:
  - name: Orchestration
    description: Orchestration endpoints.
paths:
  /script:
    post:
      tags:
        - Orchestration
      description: Use this endpoint to validate the workflow script.
      summary: Validate script
      parameters:
        - name: _action
          in: query
          description: Only the value of "validate" is supported.
          required: true
          schema:
            type: string
          example: validate
      requestBody:
        content:
          application/json:
            schema:
              properties:
                script:
                  type: string
                  description: The script to validate.
                isExpression:
                  type: boolean
                  description: An expression that can be assigned to a variable. Defaults to false if you don't provide a value.
      responses:
        200:
          description: Validation response.
  /defaultScript:
    get:
      tags:
        - Orchestration
      description: This endpoint returns the default JavaScript that can be used in script node.
      summary: Get default script for script task
      responses:
        200:
          description: OK.
          content:
            text/plain:
              schema:
                type: string
              examples:
                default:
                  $ref: '#/components/examples/defaultScript'
  /definition:
    get:
      tags:
        - Orchestration
      description: Get a list of Orchestration Definitions that are saved to the backend. Orchestration definitions are either in status 'draft' of 'published'. Published orchestration definitions are tied to a request type by `id` and `name`. Published orchestration definitions are used by corresponding access request. Draft orchestration definitions can be worked on by end user and publish to backend. The draft orchestration `id` and  `name` corresponds to the published orchestration defintion `id` and `name`.
      summary: Get orchestration definitions
      parameters:
        - $ref: "#/components/parameters/_pageSize"
        - $ref: "#/components/parameters/_pagedResultsOffset"
        - $ref: "#/components/parameters/_searchAfter"
      responses:
        200:
          description: OK.
          content:
            application/json:
              schema:
                type: object
                properties:
                  result:
                    type: array
                    items:
                      status:
                        type: string
                      $ref: '#/components/schemas/OrchestrationResponse'

                  searchAfterKey:
                    type: string
                  totalHits:
                    type: integer
              examples:
                definitions:
                  $ref: '#/components/examples/multipleDefinitions'
    post:
      tags:
        - Orchestration
      description: Create or publish an an orchestration definition (workflow).
      summary: Create and/or Publish Orchestration Definition
      parameters:
        - $ref: "#/components/parameters/allRequestsAction"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Orchestration'
            examples:
              create:
                $ref: "#/components/examples/simpleOrchestration"
              publish:
                $ref: "#/components/examples/simpleOrchestration"
              validate:
                value:
                  - id: approvalTask-74cf85c35437
                    code: TYPE_REQUIRED
                    description: The type is required.

      responses:
        200:
          description: OK.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Orchestration'
              examples:
                default:
                  $ref: "#/components/examples/simpleOrchestration"
  /definition/{id}:
    put:
      tags:
        - Orchestration
      description: Update or publish the orchestration (worfklow) definition.
      summary: Update or publish the orchestration (worfklow) definition
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Orchestration'
            examples:
              default:
                $ref: "#/components/examples/simpleOrchestration"
      responses:
        200:
          description: OK.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Orchestration'
              examples:
                default:
                  $ref: "#/components/examples/simpleOrchestration"
  /definition/{id}/{status}:
    get:
      tags:
        - Orchestration
      description: Get Orchestration Definition.
      summary: Get Orchestration Definition
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: status
          in: path
          required: true
          schema:
            type: string
            enum:
              - draft
              - published
      responses:
        200:
          description: OK.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrchestrationResponse'
              examples:
                default:
                  $ref: '#/components/examples/simpleOrchestration'
    delete:
      tags:
        - Orchestration
      description: Delete Orchestration Definition.
      summary: Delete Orchestration Definition.  If the status is published, it will try to delete the workflow model and process defintion in IDM.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: status
          in: path
          required: true
          schema:
            type: string
            enum:
              - draft
              - published
      responses:
        200:
          description: OK.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Orchestration'
              examples:
                default:
                  $ref: "#/components/examples/simpleOrchestration"


components:
  schemas:
    Orchestration:
      type: object
      properties:
        id:
          type: string
          description: ID of the orchestration definition. It must to be one of the 6 seeded definitions.
        name:
          type: string
          description: Name of the orchestration definition. It must to be one of the 6 seeded definitions.
        displayName:
          type: string
          description: The name that displays for the orchestration definition.
        description:
          type: string
          description: The description of the orchestration definition.
        type:
          type: string
          description: Provisioning is the only available type.
          enum:
            - provisioning
        steps:
          description: The order of steps. The first element in the steps array is the first step of the workflow.
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/scriptTask'
              - $ref: '#/components/schemas/approvalTask'
              - $ref: '#/components/schemas/fulfillmentTask'
            discriminator:
              propertyName: type
    scriptTask:
      type: object
      description: Script task can be used to write any custom logic in workflow.
      properties:
        name:
          type: string
          description: Name of the step.
        displayName:
          type: string
          description: Display name of the step.
        type:
          type: string
          description: This must be 'scriptTask'.
          enum:
            - scriptTask
        scriptTask:
          type: object
          description: Body of script task.
          properties:
            language:
              type: string
              description: This must be `javascript`.
              enum:
                - javascript
            gatewayType:
              type: string
              description: This can either be ‘inclusive’ or ‘exclusive’.

                If the gatewayType is  ‘exclusive’ it follows the if/else pattern. Whichever step’s condition evaluates to true first is selected.
                
                If the gatewayType is ‘inclusive’ it follows the if/if/if pattern.
                All the steps with conditions evaluate to true runs in parallel (at the same time).
                
                When there are parallel flows that are initiated by an ‘inclusive’ gateway, they must be joined at the end by a script node with gatewayType as ‘inclusive’. This will make sure that the process will wait until every parallel path completes and reaches the join node.
              enum:
                - inclusive
                - exclusive
            script:
              type: string
              description: The javascript provided by the end user. The javascript has to be json string escaped.
              example: "logger.info(\"Auto-Deprovisioning\");\n\nvar content = execution.getVariables();\nvar requestId = content.get('id');\nvar failureReason = null;\n\ntry {\n var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});\n logger.info(\"requestObj: \" + requestObj);\n}\ncatch (e) {\n failureReason = \"Deprovisioning failed: Error reading request with id \" + requestId;\n}\n\nif(!failureReason) {\n try {\n var request = requestObj.request;\n var payload = {\n \"roleId\": request.common.roleId,\n \"startDate\": request.common.startDate,\n \"endDate\": request.common.endDate,\n \"auditContext\": {},\n \"grantType\": \"request\"\n };\n var queryParams = {\n \"_action\": \"remove\"\n }\n\n var result = openidm.action('iga/governance/user/' + request.common.userId + '/roles' , 'POST', payload,queryParams);\n }\n catch (e) {\n failureReason = \"Deprovisioning failed: Error deprovisioning role to user \" + request.common.userId + \" for role \" + request.common.roleId + \". Error message: \" + e.message;\n }\n \n var decision = {'status': 'complete'};\n if (failureReason) {\n decision.outcome = 'not provisioned';\n decision.comment = failureReason;\n decision.failure = true;\n }\n else {\n decision.outcome = 'provisioned';\n }\n\n var queryParams = { '_action': 'update'};\n openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);\n logger.info(\"Request \" + requestId + \" completed.\");\n}"
            nextStep:
              type: array
              description: What are the next steps after the approval task?
              items:
                properties:
                  condition:
                    type: string
                    description: Javascript expression that resolves to either true or false. If the expression returns true, the path is taken, else it isn't.
                  outcome:
                    type: string
                    description: Human-friendly name for th outcome.
                  step:
                    type: string
                    description: Name of the next step. To connect to the end step, set this value to `null`.
    approvalTask:
      type: object
      properties:
        name:
          type: string
          description: Name the step.
        displayName:
          type: string
          description: Display name the step.
        type:
          type: string
          description: The value must be 'approvalTask'.
          enum:
            - approvalTask
        nextStep:
          type: array
          description: What are the next steps after the approval task?
          items:
            properties:
              condition:
                type: string
                description: Javascript expression that resolves to either true or false. If the expression returns true, the path is taken, else it isn't.
              outcome:
                type: string
                description: Human-friendly name for th outcome.
              step:
                type: string
                description: Name of the next step. null if you want to connect to end step
        actors:
          type: array
          description: Who are the actors / approvers for this approval task?
            
            If there are multiple actors, one of them has to take an action to register a decision for the approval task and move the process forward.
          items:
            $ref: '#/components/schemas/Actor'
        events:
          $ref: '#/components/schemas/Events'
    fulfillmentTask:
      type: object
      properties:
        name:
          type: string
          description: Name of the step.
        displayName:
          type: string
          description: Display name of the step.
        type:
          type: string
          description: The value must be 'approvalTask'.
          enum:
            - approvalTask
        nextStep:
          type: array
          description: What are the next steps after the approval task?
          items:
            properties:
              condition:
                type: string
                description: Javascript expression that resolves to either true or false. If the expression returns true, path will be take, else it will not be taken
              outcome:
                type: string
                description: Human-friendly name for th outcome.
              step:
                type: string
                description: Name of the next step. null if you want to connect to end step.
        actors:
          type: array
          description: Who are the actors (approvers) for this approval task?
            
            If there are multiple approvers, one must take an action to register a decision for the approval task and to move the workflow forward.

          items:
            $ref: '#/components/schemas/Actor'
        events:
          $ref: '#/components/schemas/Events'
    Actor:
      type: object
      properties:
        id:
          type: object
          description: ID of the approver.
          properties:
            value:
              type: string
              description: Value of the id. It can be a string or an expression.
                
                An example of an expression is "\"managed/user/\" + requestIndex.applicationOwner[0].id".
                
                This assigns the approver to be the first application owner for the application grant access request type.
                
                An example of a string value is `managed/user/7174f301-dc29-4cbe-bf95-a1cba356fc6c`.
            isExpression:
              type: boolean
              description: Identifier to tell if the value is a plain string or an expression.
        permissions:
          type: object
          description: The permissions the approver can take on the access request.
          properties:
            approve:
              type: boolean
              description: Can the approver approve the access request?
            reject:
              type: boolean
              description: Can the approver reject the access request?
            reassign:
              type: boolean
              description: Can the approver reassign the access request to another user?
            modify:
              type: boolean
              description: Can the approver modify the access request?
            comment:
              type: boolean
              description: Can the approver comment on the access request?
    Events:
      type: object
      description: Notifications and frequency settings for this approval task.
      properties:
        assignment:
          type: object
          description: Assignment related settings
          properties:
            notification:
              type: string
              description: The email temmplate used on assignment of the access request.
        reassign:
          type: object
          description: Reassignment related settings
          properties:
            notification:
              type: string
              description: The email template to use when an access request is reassigned.
        reminder:
          type: object
          description: Reminder related settings
          properties:
            notification:
              type: string
              description: The email template to use when a reminder is sent to an approver to complete an access request task.
            frequency:
              type: number
              description: How frequently (in days) the reminder is sent.
            date:
              type: object
              description: When to start sending the email. This can be a javascript expression.
              properties:
                isExpression:
                  type: boolean
                  description: Whether date is an expression or a string.
                value:
                  type: string
                  description: Value of the expression or date string. For example,
                    "(new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()"
        escalation:
          type: object
          description: Escalation related settings.
          properties:
            notification:
              type: string
              description: The email template to use when an access request is escalated to another user.
            actors:
              type: array
              description: Who to send the escalation email to. You can define multiple approvers (actors).
              items:
                properties:
                  id:
                    type: object
                    description: ID related settings
                    properties:
                      value:
                        type: string
                        description: Value of the id. It can be a string or an expression.
                          
                          Example for expression.
                          
                          "\"managed/user/\" + requestIndex.applicationOwner[0].id"
                          
                          This dynamically populates the escalation point of contact as the application owner
                          However, you can easily change this to be the end user's manager.
                          
                          An example of a string value is `managed/user/7174f301-dc29-4cbe-bf95-a1cba356fc6c`.
                      isExpression:
                        type: boolean
                        description: Whether the id is an expression or a string.
            date:
              type: object
              description: Date when escalation happens. It can be javascript expression
              properties:
                isExpression:
                  description: Whether date is an expression or a string.
                  type: boolean
                value:
                  type: string
                  description: Value of the expression or date string.
                    "(new Date(new Date().getTime()+(7*1*24*60*60*1000))).toISOString()"

        expiration:
          type: object
          description: Expiration related settings.
          properties:
            notification:
              type: string
              description: The email template to use when the access request expires.
            actors:
              type: array
              description: The user to reassign the access request to if action is ‘reassign’.
              items:
                properties:
                  id:
                    type: object
                    description: Id related settings
                    properties:
                      value:
                        type: string
                        description: Value of the id. It can be a string or an expression.
                          
                          Example for expression.
                          
                          "\"managed/user/\" + requestIndex.applicationOwner[0].id"
                          
                          This dynamically populates the ID to be the application owner.
                          
                          Example of string value is `managed/user/7174f301-dc29-4cbe-bf95-a1cba356fc6c`.
                      isExpression:
                        type: boolean
                        description: Whether id is an expression or string.
                  permissions:
                    type: object
                    description: The permissions the approver can take on the access request.
                    properties:
                      approve:
                        type: boolean
                        description: Can the approver approve the access request?
                      reject:
                        type: boolean
                        description: Can the approver reject the access request?
                      reassign:
                        type: boolean
                        description: Can the approver reassign the access request?
                      modify:
                        type: boolean
                        description: Can the approver modify the access request?
                      comment:
                        type: boolean
                        description: Can the approver comment on the access request?
            date:
              type: object
              description: The date the access request expires. It can be javascript expression.
              properties:
                isExpression:
                  type: boolean
                  description: Whether date is an expression or a string.
                value:
                  type: string
                  description: Value of the expression or date string..
                    "(new Date(new Date().getTime()+(7*1*24*60*60*1000))).toISOString()"
            action:
              description: It can either be ‘reassign’ or ‘reject’.
                
                If you do not add the `action` key, the expiration takes no action when the task expires.

              type: string

    OrchestrationResponse:
      allOf:
        - $ref: '#/components/schemas/Orchestration'
        - type: object
          properties:
            status:
              type: string
              description: Values can be ‘draft’ or ‘published’.
  parameters:
    _pageSize:
      name: _pageSize
      in: query
      description: Number of results per page.
      example: 10
      schema:
        type: integer
    _pagedResultsOffset:
      name: _pagedResultsOffset
      in: query
      description: Page number of results to show.
      example: 1
      schema:
        type: integer
    _sortKeys:
      name: _sortKeys
      in: query
      description: The property to sort by.
      schema:
        type: string
    _sortDir:
      name: _sortDir
      in: query
      description: The direction of sort, asc or desc.
      schema:
        type: string
    _sortType:
      name: _sortType
      in: query
      description: The type of sort value, leave blank for normal sorting, or use 'date' or 'integer' for numeric.
      schema:
        type: string
    _searchAfter:
      name: _searchAfter
      in: query
      description: Page cursor token to be search after.  Get this from the response of pervious search response.
      example: CnoSdGoSc35mb3JnZXJvY2stYXV0b2lkcl4LEgZzdGF0dXMiCXB1Ymxpc2hlZAwLEi5maWVsZGluZy10ZXN0Ml9vcmNoZXN0cmF0aW9uX2RlZmluaXRpb25fbGF0ZXN0IhV0ZXN0UGFyYWxsZUFjY3RDcmVhdGUMGAAgAA==
      schema:
        type: string
    _queryFilter:
      name: _queryFilter
      in: query
      description: The filter condition to restrict the results.
      schema:
        type: string
    allRequestsAction:
      name: _action
      in: query
      required: true
      description: Action to be performed for requests endpoint.
      schema:
        type: string
        enum:
          - create
          - validate
          - publish
  examples:
    multipleDefinitions:
      value:
        result:
          - id: BasicApplicationGrant
            name: BasicApplicationGrant
            displayName: BasicApplicationGrant
            description: BasicApplicationGrant access request type.
            type: provisioning
            steps:
              - name: approvalTask-74cf85c35437
                displayName: Approval Task
                type: approvalTask
                approvalTask:
                  actors:
                    - id:
                        value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                      permissions:
                        approve: true
                        reject: true
                        reassign: true
                        modify: true
                        comment: true
                  events:
                    assignment:
                      notification: requestAssigned
                    reassign:
                      notification: requestReassigned
                    reminder:
                      notification: requestReminder
                      frequency: 3
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                    escalation:
                      notification: requestEscalated
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                      actors:
                        - id:
                            value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                            isExpression: true
                    expiration:
                      action: reject
                      notification: requestExpired
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
                  nextStep:
                    - condition: null
                      outcome: APPROVE
                      step: scriptTask-626899b6e99a
                    - condition: null
                      outcome: REJECT
                      step: scriptTask-c58309b8c470
                    - condition: null
                      outcome: EXPIRATION
                      step: null
              - name: scriptTask-626899b6e99a
                displayName: Application Grant Validation
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Running application grant request validation");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    var applicationId = null;
                    var app = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      applicationId = requestObj.application.id;
                    }
                    catch (e) {
                      failureReason = "Validation failed: Error reading request with id " + requestId;
                    }
                    
                    // Validation 1 - Check application exists
                    if (!failureReason) {
                      try {
                        app = openidm.read('managed/alpha_application/' + applicationId);
                        if (!app) {
                          failureReason = "Validation failed: Cannot find application with id " + applicationId;
                        }
                      }
                      catch (e) {
                        failureReason = "Validation failed: Error reading application with id " + applicationId + ". Error message: " + e.message;
                      }
                    }
                    
                    // Validation 2 - Check the user does not already have application granted
                    // Note: this is done at request submission time as well, the following is an example of how to check user's accounts
                    if (!failureReason) {
                      try {
                        var user = openidm.read('managed/alpha_user/' + requestObj.user.id, null, [ 'effectiveApplications' ]);
                        user.effectiveApplications.forEach(effectiveApp => {
                          if (effectiveApp._id === applicationId) {
                            failureReason = "Validation failed: User with id " + requestObj.user.id + " already has effective application " + applicationId;
                          }
                        })
                      }
                      catch (e) {
                        failureReason = "Validation failed: Unable to check effective applications of user with id " + requestObj.user.id + ". Error message: " + e.message;
                      }
                    }
                    
                    if (failureReason) {
                      logger.info("Validation failed: " + failureReason);
                    }
                    execution.setVariable("failureReason", failureReason);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: exclusiveGateway-5167870154a9
              - name: scriptTask-c58309b8c470
                displayName: Reject Request
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Rejecting request");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    
                    logger.info("Execution Content: " + content);
                    var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                    var decision = {'outcome': 'denied', 'status': 'complete'};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: exclusiveGateway-5167870154a9
                displayName: Validation Gateway
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: logger.info("This is exclusive gateway");
                  nextStep:
                    - condition: failureReason == null
                      outcome: validationSuccess
                      step: scriptTask-3a74557440fb
                    - condition: failureReason != null
                      outcome: validationFailure
                      step: scriptTask-744ef6a8b9a2
              - name: scriptTask-3a74557440fb
                displayName: Auto Provisioning
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Auto-Provisioning");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      logger.info("requestObj: " + requestObj);
                    }
                    catch (e) {
                      failureReason = "Provisioning failed: Error reading request with id " + requestId;
                    }
                    
                    if(!failureReason) {
                      try {
                        var request = requestObj.request;
                        var payload = {
                          "applicationId": request.common.applicationId,
                          "startDate": request.common.startDate,
                          "endDate": request.common.endDate,
                          "auditContext": {},
                          "grantType": "request"
                        };
                        var queryParams = {
                          "_action": "add"
                        }
                    
                        logger.info("Creating account: " + payload);
                        var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams);
                      }
                      catch (e) {
                        failureReason = "Provisioning failed: Error provisioning account to user " + request.common.userId + " for application " + request.common.applicationId + ". Error message: " + e.message;
                      }
                    
                      var decision = {'status': 'complete'};
                      if (failureReason) {
                        decision.outcome = 'not provisioned';
                        decision.comment = failureReason;
                        decision.failure = true;
                      }
                      else {
                        decision.outcome = 'provisioned';
                      }
                    
                      var queryParams = { '_action': 'update'};
                      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                      logger.info("Request " + requestId + " completed.");
                    }
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-744ef6a8b9a2
                displayName: Application Grant Validation Failure
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    var content = execution.getVariables();
                    var failureReason = content.get('failureReason');
                    
                    var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
            staticNodes:
              startNode:
                id: startNode
                x: 70
                'y': 140
                connections:
                  start: approvalTask-74cf85c35437
              endNode:
                id: endNode
                x: 1288
                'y': 521
                connections: null
              uiConfig:
                approvalTask-74cf85c35437:
                  actors:
                    - type: applicationOwner
                      id:
                        value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                  events:
                    escalationType: applicationOwner
                    escalationDate: 5
                    escalationTimeSpan: day(s)
                    reminderDate: 3
                    reminderTimeSpan: day(s)
                  x: 210
                  'y': 110
                scriptTask-626899b6e99a:
                  x: 440
                  'y': 80
                scriptTask-c58309b8c470:
                  x: 464
                  'y': 164
                exclusiveGateway-5167870154a9:
                  x: 740
                  'y': 78
                scriptTask-3a74557440fb:
                  x: 981
                  'y': 80.5
                scriptTask-744ef6a8b9a2:
                  x: 955
                  'y': 193.015625
            status: published
          - id: BasicApplicationRemove
            name: BasicApplicationRemove
            displayName: BasicApplicationRemove
            description: BasicApplicationRemove access request type.
            type: provisioning
            steps:
              - name: approvalTask-74cf85c35437
                displayName: Approval Task
                type: approvalTask
                approvalTask:
                  actors:
                    - id:
                        value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                      permissions:
                        approve: true
                        reject: true
                        reassign: true
                        modify: true
                        comment: true
                  events:
                    assignment:
                      notification: requestAssigned
                    reassign:
                      notification: requestReassigned
                    reminder:
                      notification: requestReminder
                      frequency: 3
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                    escalation:
                      notification: requestEscalated
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                      actors:
                        - id:
                            isExpression: true
                            value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                    expiration:
                      action: reject
                      notification: requestExpired
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
                  nextStep:
                    - condition: null
                      outcome: APPROVE
                      step: scriptTask-626899b6e99a
                    - condition: null
                      outcome: REJECT
                      step: scriptTask-c58309b8c470
                    - condition: null
                      outcome: EXPIRATION
                      step: null
              - name: scriptTask-626899b6e99a
                displayName: Auto Deprovisioning
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Auto-Deprovisioning");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      logger.info("requestObj: " + requestObj);
                    }
                    catch (e) {
                      failureReason = "Deprovisioning failed: Error reading request with id " + requestId;
                    }
                    
                    if(!failureReason) {
                      try {
                        var request = requestObj.request;
                        var payload = {
                          "applicationId": request.common.applicationId,
                          "startDate": request.common.startDate,
                          "endDate": request.common.endDate,
                          "auditContext": {},
                          "grantType": "request"
                        };
                        var queryParams = {
                          "_action": "remove"
                        }
                    
                        logger.info("Removing account: " + payload);
                        var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams);
                      }
                      catch (e) {
                        failureReason = "Deprovisioning failed: Error deprovisioning account to user " + request.common.userId + " for application " + request.common.applicationId + ". Error message: " + e.message;
                      }
                    
                      var decision = {'status': 'complete'};
                      if (failureReason) {
                        decision.outcome = 'not provisioned';
                        decision.comment = failureReason;
                        decision.failure = true;
                      }
                      else {
                        decision.outcome = 'provisioned';
                      }
                    
                      var queryParams = { '_action': 'update'};
                      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                      logger.info("Request " + requestId + " completed.");
                    }
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-c58309b8c470
                displayName: Reject Request
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Rejecting request");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    
                    logger.info("Execution Content: " + content);
                    var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                    var decision = {'outcome': 'denied', 'status': 'complete'};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
            staticNodes:
              startNode:
                id: startNode
                x: 70
                'y': 140
                connections:
                  start: approvalTask-74cf85c35437
              endNode:
                id: endNode
                x: 1014
                'y': 256
                connections: null
              uiConfig:
                approvalTask-74cf85c35437:
                  actors:
                    - type: applicationOwner
                      id:
                        value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                  events:
                    escalationType: applicationOwner
                    escalationDate: 5
                    escalationTimeSpan: day(s)
                    reminderDate: 3
                    reminderTimeSpan: day(s)
                  x: 210
                  'y': 110
                scriptTask-626899b6e99a:
                  x: 448
                  'y': 39
                scriptTask-c58309b8c470:
                  x: 456
                  'y': 120
            status: published
          - id: BasicEntitlementGrant
            name: BasicEntitlementGrant
            displayName: BasicEntitlementGrant
            description: BasicEntitlementGrant access request type.
            type: provisioning
            steps:
              - name: approvalTask-74cf85c35437
                displayName: Approval Task
                type: approvalTask
                approvalTask:
                  actors:
                    - id:
                        value: '"managed/user/" + requestIndex.entitlementOwner[0].id ? "managed/user/" + requestIndex.entitlementOwner[0].id : "managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                      permissions:
                        approve: true
                        reject: true
                        reassign: true
                        modify: true
                        comment: true
                  events:
                    assignment:
                      notification: requestAssigned
                    reassign:
                      notification: requestReassigned
                    reminder:
                      notification: requestReminder
                      frequency: 3
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                    escalation:
                      notification: requestEscalated
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                      actors:
                        - id:
                            isExpression: true
                            value: '"managed/user/" + requestIndex.entitlementOwner[0].id ? "managed/user/" + requestIndex.entitlementOwner[0].id : "managed/user/" + requestIndex.applicationOwner[0].id'
                    expiration:
                      action: reject
                      notification: requestExpired
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
                  nextStep:
                    - condition: null
                      outcome: EXPIRATION
                      step: null
                    - condition: null
                      outcome: APPROVE
                      step: scriptTask-3eab1948f1ec
                    - condition: null
                      outcome: REJECT
                      step: scriptTask-aec6c36b3a45
              - name: scriptTask-3eab1948f1ec
                displayName: Entitlement Grant Validation
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Running entitlement grant request validation");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    var applicationId = null;
                    var assignmentId = null;
                    var app = null;
                    var assignment = null;
                    var existingAccount = false;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      applicationId = requestObj.application.id;
                      assignmentId = requestObj.assignment.id;
                    }
                    catch (e) {
                      failureReason = "Validation failed: Error reading request with id " + requestId;
                    }
                    
                    // Validation 1 - Check application exists
                    if (!failureReason) {
                      try {
                        app = openidm.read('managed/alpha_application/' + applicationId);
                        if (!app) {
                          failureReason = "Validation failed: Cannot find application with id " + applicationId;
                        }
                      }
                      catch (e) {
                        failureReason = "Validation failed: Error reading application with id " + applicationId + ". Error message: " + e.message;
                      }
                    }
                    
                    // Validation 2 - Check entitlement exists
                    if (!failureReason) {
                      try {
                        assignment = openidm.read('managed/alpha_assignment/' + assignmentId);
                        if (!assignment) {
                          failureReason = "Validation failed: Cannot find assignment with id " + assignmentId;
                        }
                      }
                      catch (e) {
                        failureReason = "Validation failed: Error reading assignment with id " + assignmentId + ". Error message: " + e.message;
                      }
                    }
                    
                    // Validation 3 - Check the user has application granted
                    if (!failureReason) {
                      try {
                        var user = openidm.read('managed/alpha_user/' + requestObj.user.id, null, [ 'effectiveApplications' ]);
                        user.effectiveApplications.forEach(effectiveApp => {
                          if (effectiveApp._id === applicationId) {
                            existingAccount = true;
                          }
                        })
                      }
                      catch (e) {
                        failureReason = "Validation failed: Unable to check existing applications of user with id " + requestObj.user.id + ". Error message: " + e.message;
                      }
                    }
                    
                    // Validation 4 - If account does not exist, provision it
                    if (!failureReason) {
                      if (!existingAccount) {
                        try {
                          var request = requestObj.request;
                          var payload = {
                            "applicationId": applicationId,
                            "startDate": request.common.startDate,
                            "endDate": request.common.endDate,
                            "auditContext": {},
                            "grantType": "request"
                          };
                          var queryParams = {
                            "_action": "add"
                          }
                    
                          logger.info("Creating account: " + payload);
                          var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams);
                        }
                        catch (e) {
                          failureReason = "Validation failed: Error provisioning new account to user " + request.common.userId + " for application " + applicationId + ". Error message: " + e.message;
                        }
                      }
                    }
                    
                    if (failureReason) {
                      logger.info("Validation failed: " + failureReason);
                    }
                    execution.setVariable("failureReason", failureReason);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: exclusiveGateway-48e748c42994
              - name: exclusiveGateway-48e748c42994
                displayName: Validation Gateway
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: logger.info("This is exclusive gateway");
                  nextStep:
                    - condition: failureReason == null
                      outcome: validationFlowSuccess
                      step: scriptTask-0359a9d77ee2
                    - condition: failureReason != null
                      outcome: validationFlowFailure
                      step: scriptTask-0b56191887de
              - name: scriptTask-0b56191887de
                displayName: Entitlement Grant Validation Failure
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    var content = execution.getVariables();
                    var failureReason = content.get('failureReason');
                    
                    var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-0359a9d77ee2
                displayName: Auto Provisioning
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Auto-Provisioning");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      logger.info("requestObj: " + requestObj);
                    }
                    catch (e) {
                      failureReason = "Provisioning failed: Error reading request with id " + requestId;
                    }
                    
                    if(!failureReason) {
                      try {
                        var request = requestObj.request;
                        var payload = {
                          "entitlementId": request.common.entitlementId,
                          "startDate": request.common.startDate,
                          "endDate": request.common.endDate,
                          "auditContext": {},
                          "grantType": "request"
                        };
                        var queryParams = {
                          "_action": "add"
                        }
                    
                        var result = openidm.action('iga/governance/user/' + request.common.userId + '/entitlements' , 'POST', payload,queryParams);
                      }
                      catch (e) {
                        failureReason = "Provisioning failed: Error provisioning entitlement to user " + request.common.userId + " for entitlement " + request.common.entitlementId + ". Error message: " + e.message;
                      }
                    
                      var decision = {'status': 'complete'};
                      if (failureReason) {
                        decision.outcome = 'not provisioned';
                        decision.comment = failureReason;
                        decision.failure = true;
                      }
                      else {
                        decision.outcome = 'provisioned';
                      }
                    
                      var queryParams = { '_action': 'update'};
                      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                      logger.info("Request " + requestId + " completed.");
                    }
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-aec6c36b3a45
                displayName: Reject Request
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Rejecting request");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    
                    logger.info("Execution Content: " + content);
                    var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                    var decision = {'outcome': 'denied', 'status': 'complete'};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
            staticNodes:
              startNode:
                id: startNode
                x: 70
                'y': 140
                connections:
                  start: approvalTask-74cf85c35437
              endNode:
                id: endNode
                x: 1262
                'y': 513
                connections: null
              uiConfig:
                approvalTask-74cf85c35437:
                  actors:
                    - type: script
                      id:
                        value: '"managed/user/" + requestIndex.entitlementOwner[0].id ? "managed/user/" + requestIndex.entitlementOwner[0].id : "managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                  events:
                    escalationType: script
                    escalationDate: 5
                    escalationTimeSpan: day(s)
                    reminderDate: 3
                    reminderTimeSpan: day(s)
                  x: 210
                  'y': 110
                scriptTask-3eab1948f1ec:
                  x: 433
                  'y': 70.015625
                exclusiveGateway-48e748c42994:
                  x: 724
                  'y': 65.015625
                scriptTask-0b56191887de:
                  x: 978
                  'y': 165.015625
                scriptTask-0359a9d77ee2:
                  x: 957
                  'y': 72.015625
                scriptTask-aec6c36b3a45:
                  x: 430
                  'y': 165.015625
            status: published
          - id: BasicEntitlementRemove
            name: BasicEntitlementRemove
            displayName: BasicEntitlementRemove
            description: BasicEntitlementRemove access request type.
            type: provisioning
            steps:
              - name: approvalTask-74cf85c35437
                displayName: Approval Task
                type: approvalTask
                approvalTask:
                  actors:
                    - id:
                        value: '"managed/user/" + requestIndex.entitlementOwner[0].id ? "managed/user/" + requestIndex.entitlementOwner[0].id : "managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                      permissions:
                        approve: true
                        reject: true
                        reassign: true
                        modify: true
                        comment: true
                  events:
                    assignment:
                      notification: requestAssigned
                    reassign:
                      notification: requestReassigned
                    reminder:
                      notification: requestReminder
                      frequency: 3
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                    escalation:
                      notification: requestEscalated
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                      actors:
                        - id:
                            isExpression: true
                            value: '"managed/user/" + requestIndex.entitlementOwner[0].id ? "managed/user/" + requestIndex.entitlementOwner[0].id : "managed/user/" + requestIndex.applicationOwner[0].id'
                    expiration:
                      action: reject
                      notification: requestExpired
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
                  nextStep:
                    - condition: null
                      outcome: EXPIRATION
                      step: null
                    - condition: null
                      outcome: REJECT
                      step: scriptTask-aec6c36b3a45
                    - condition: null
                      outcome: APPROVE
                      step: scriptTask-0359a9d77ee2
              - name: scriptTask-0359a9d77ee2
                displayName: Auto Deprovisioning
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Auto-Deprovisioning");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      logger.info("requestObj: " + requestObj);
                    }
                    catch (e) {
                      failureReason = "Deprovisioning failed: Error reading request with id " + requestId;
                    }
                    
                    if(!failureReason) {
                      try {
                        var request = requestObj.request;
                        var payload = {
                          "entitlementId": request.common.entitlementId,
                          "startDate": request.common.startDate,
                          "endDate": request.common.endDate,
                          "auditContext": {},
                          "grantType": "request"
                        };
                        var queryParams = {
                          "_action": "remove"
                        }
                    
                        var result = openidm.action('iga/governance/user/' + request.common.userId + '/entitlements' , 'POST', payload,queryParams);
                      }
                      catch (e) {
                        failureReason = "Deprovisioning failed: Error deprovisioning entitlement to user " + request.common.userId + " for entitlement " + request.common.entitlementId + ". Error message: " + e.message;
                      }
                    
                      var decision = {'status': 'complete'};
                      if (failureReason) {
                        decision.outcome = 'not provisioned';
                        decision.comment = failureReason;
                        decision.failure = true;
                      }
                      else {
                        decision.outcome = 'provisioned';
                      }
                    
                      var queryParams = { '_action': 'update'};
                      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                      logger.info("Request " + requestId + " completed.");
                    }
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-aec6c36b3a45
                displayName: Reject Request
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Rejecting request");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    
                    logger.info("Execution Content: " + content);
                    var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                    var decision = {'outcome': 'denied', 'status': 'complete'};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
            staticNodes:
              startNode:
                id: startNode
                x: 70
                'y': 140
                connections:
                  start: approvalTask-74cf85c35437
              endNode:
                id: endNode
                x: 1037
                'y': 169
                connections: null
              uiConfig:
                approvalTask-74cf85c35437:
                  actors:
                    - type: script
                      id:
                        value: '"managed/user/" + requestIndex.entitlementOwner[0].id ? "managed/user/" + requestIndex.entitlementOwner[0].id : "managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                  events:
                    escalationType: script
                    escalationDate: 5
                    escalationTimeSpan: day(s)
                    reminderDate: 3
                    reminderTimeSpan: day(s)
                  x: 210
                  'y': 110
                scriptTask-0359a9d77ee2:
                  x: 438
                  'y': 42.015625
                scriptTask-aec6c36b3a45:
                  x: 432
                  'y': 127.015625
            status: published
          - id: BasicRoleGrant
            name: BasicRoleGrant
            displayName: BasicRoleGrant
            description: BasicRoleGrant access request type.
            type: provisioning
            steps:
              - name: approvalTask-74cf85c35437
                displayName: Approval Task
                type: approvalTask
                approvalTask:
                  actors:
                    - id:
                        value: |-
                          (function() {
                              var systemSettings = openidm.action('iga/commons/config/iga_access_request', 'GET', {}, {});
                              var approver = null;
                              if (requestIndex.roleOwner && requestIndex.roleOwner[0]) {
                                  approver = "managed/user/" + requestIndex.roleOwner[0].id;
                              } else if (systemSettings && systemSettings.defaultApprover) {
                                  approver = systemSettings.defaultApprover;
                              }
                          return approver;
                          })()
                        isExpression: true
                      permissions:
                        approve: true
                        reject: true
                        reassign: true
                        modify: true
                        comment: true
                  events:
                    assignment:
                      notification: requestAssigned
                    reassign:
                      notification: requestReassigned
                    reminder:
                      notification: requestReminder
                      frequency: 3
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                    escalation:
                      notification: requestEscalated
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                      actors:
                        - id:
                            value: |-
                              (function() {
                                  var systemSettings = openidm.action('iga/commons/config/iga_access_request', 'GET', {}, {});
                                  var approver = null;
                                  if (requestIndex.roleOwner && requestIndex.roleOwner[0]) {
                                      approver = "managed/user/" + requestIndex.roleOwner[0].id;
                                  } else if (systemSettings && systemSettings.defaultApprover) {
                                      approver = systemSettings.defaultApprover;
                                  }
                              return approver;
                              })()
                            isExpression: true
                    expiration:
                      action: reject
                      notification: requestExpired
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
                  nextStep:
                    - condition: null
                      outcome: EXPIRATION
                      step: null
                    - condition: null
                      outcome: APPROVE
                      step: scriptTask-3eab1948f1ec
                    - condition: null
                      outcome: REJECT
                      step: scriptTask-aec6c36b3a45
              - name: scriptTask-3eab1948f1ec
                displayName: Role Grant Validation
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Running role grant request validation");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    var roleId = null;
                    var role = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      roleId = requestObj.role.id;
                    }
                    catch (e) {
                      failureReason = "Validation failed: Error reading request with id " + requestId;
                    }
                    
                    // Validation 1 - Check role exists
                    if (!failureReason) {
                      try {
                        role = openidm.read('managed/alpha_role/' + roleId);
                        if (!role) {
                          failureReason = "Validation failed: Cannot find role with id " + roleId;
                        }
                      }
                      catch (e) {
                        failureReason = "Validation failed: Error reading role with id " + roleId + ". Error message: " + e.message;
                      }
                    }
                    
                    if (failureReason) {
                      logger.info("Validation failed: " + failureReason);
                    }
                    execution.setVariable("failureReason", failureReason);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: exclusiveGateway-48e748c42994
              - name: exclusiveGateway-48e748c42994
                displayName: Validation Gateway
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: logger.info("This is exclusive gateway");
                  nextStep:
                    - condition: failureReason == null
                      outcome: validationFlowSuccess
                      step: scriptTask-0359a9d77ee2
                    - condition: failureReason != null
                      outcome: validationFlowFailure
                      step: scriptTask-0b56191887de
              - name: scriptTask-0b56191887de
                displayName: Role Grant Validation Failure
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    var content = execution.getVariables();
                    var failureReason = content.get('failureReason');
                    
                    var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-0359a9d77ee2
                displayName: Auto Provisioning
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Auto-Provisioning");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      logger.info("requestObj: " + requestObj);
                    }
                    catch (e) {
                      failureReason = "Provisioning failed: Error reading request with id " + requestId;
                    }
                    
                    if(!failureReason) {
                      try {
                        var request = requestObj.request;
                        var payload = {
                          "roleId": request.common.roleId,
                          "startDate": request.common.startDate,
                          "endDate": request.common.endDate,
                          "auditContext": {},
                          "grantType": "request"
                        };
                        var queryParams = {
                          "_action": "add"
                        }
                    
                        var result = openidm.action('iga/governance/user/' + request.common.userId + '/roles' , 'POST', payload,queryParams);
                      }
                      catch (e) {
                        failureReason = "Provisioning failed: Error provisioning role to user " + request.common.userId + " for role " + request.common.roleId + ". Error message: " + e.message;
                      }
                    
                      var decision = {'status': 'complete'};
                      if (failureReason) {
                        decision.outcome = 'not provisioned';
                        decision.comment = failureReason;
                        decision.failure = true;
                      }
                      else {
                        decision.outcome = 'provisioned';
                      }
                    
                      var queryParams = { '_action': 'update'};
                      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                      logger.info("Request " + requestId + " completed.");
                    }
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-aec6c36b3a45
                displayName: Reject Request
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Rejecting request");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    
                    logger.info("Execution Content: " + content);
                    var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                    var decision = {'outcome': 'denied', 'status': 'complete'};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
            staticNodes:
              startNode:
                id: startNode
                x: 70
                'y': 140
                connections:
                  start: approvalTask-74cf85c35437
              endNode:
                id: endNode
                x: 1314
                'y': 456
                connections: null
              uiConfig:
                approvalTask-74cf85c35437:
                  actors:
                    - type: script
                      id:
                        value: |-
                          (function() {
                              var systemSettings = openidm.action('iga/commons/config/iga_access_request', 'GET', {}, {});
                              var approver = null;
                              if (requestIndex.roleOwner && requestIndex.roleOwner[0]) {
                                  approver = "managed/user/" + requestIndex.roleOwner[0].id;
                              } else if (systemSettings && systemSettings.defaultApprover) {
                                  approver = systemSettings.defaultApprover;
                              }
                          return approver;
                          })();
                        isExpression: true
                  events:
                    escalationType: script
                    escalationDate: 5
                    escalationTimeSpan: day(s)
                    reminderDate: 3
                    reminderTimeSpan: day(s)
                  x: 210
                  'y': 110
                scriptTask-3eab1948f1ec:
                  x: 433
                  'y': 70.015625
                exclusiveGateway-48e748c42994:
                  x: 724
                  'y': 65.015625
                scriptTask-0b56191887de:
                  x: 978
                  'y': 165.015625
                scriptTask-0359a9d77ee2:
                  x: 957
                  'y': 72.015625
                scriptTask-aec6c36b3a45:
                  x: 430
                  'y': 165.015625
            status: published
          - id: BasicRoleRemove
            name: BasicRoleRemove
            displayName: BasicRoleRemove
            description: BasicRoleRemove access request type.
            type: provisioning
            steps:
              - name: approvalTask-74cf85c35437
                displayName: Approval Task
                type: approvalTask
                approvalTask:
                  actors:
                    - id:
                        value: |-
                          (function() {
                              var systemSettings = openidm.action('iga/commons/config/iga_access_request', 'GET', {}, {});
                              var approver = null;
                              if (requestIndex.roleOwner && requestIndex.roleOwner[0]) {
                                  approver = "managed/user/" + requestIndex.roleOwner[0].id;
                              } else if (systemSettings && systemSettings.defaultApprover) {
                                  approver = systemSettings.defaultApprover;
                              }
                          return approver;
                          })()
                        isExpression: true
                      permissions:
                        approve: true
                        reject: true
                        reassign: true
                        modify: true
                        comment: true
                  events:
                    assignment:
                      notification: requestAssigned
                    reassign:
                      notification: requestReassigned
                    reminder:
                      notification: requestReminder
                      frequency: 3
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                    escalation:
                      notification: requestEscalated
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                      actors:
                        - id:
                            value: |-
                              (function() {
                                  var systemSettings = openidm.action('iga/commons/config/iga_access_request', 'GET', {}, {});
                                  var approver = null;
                                  if (requestIndex.roleOwner && requestIndex.roleOwner[0]) {
                                      approver = "managed/user/" + requestIndex.roleOwner[0].id;
                                  } else if (systemSettings && systemSettings.defaultApprover) {
                                      approver = systemSettings.defaultApprover;
                                  }
                              return approver;
                              })()
                            isExpression: true
                    expiration:
                      action: reject
                      notification: requestExpired
                      actors: []
                      date:
                        isExpression: true
                        value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
                  nextStep:
                    - condition: null
                      outcome: EXPIRATION
                      step: null
                    - condition: null
                      outcome: REJECT
                      step: scriptTask-aec6c36b3a45
                    - condition: null
                      outcome: APPROVE
                      step: scriptTask-0359a9d77ee2
              - name: scriptTask-0359a9d77ee2
                displayName: Auto Deprovisioning
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Auto-Deprovisioning");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    var failureReason = null;
                    
                    try {
                      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                      logger.info("requestObj: " + requestObj);
                    }
                    catch (e) {
                      failureReason = "Deprovisioning failed: Error reading request with id " + requestId;
                    }
                    
                    if(!failureReason) {
                      try {
                        var request = requestObj.request;
                        var payload = {
                          "roleId": request.common.roleId,
                          "startDate": request.common.startDate,
                          "endDate": request.common.endDate,
                          "auditContext": {},
                          "grantType": "request"
                        };
                        var queryParams = {
                          "_action": "remove"
                        }
                    
                        var result = openidm.action('iga/governance/user/' + request.common.userId + '/roles' , 'POST', payload,queryParams);
                      }
                      catch (e) {
                        failureReason = "Deprovisioning failed: Error deprovisioning role to user " + request.common.userId + " for role " + request.common.roleId + ". Error message: " + e.message;
                      }
                    
                      var decision = {'status': 'complete'};
                      if (failureReason) {
                        decision.outcome = 'not provisioned';
                        decision.comment = failureReason;
                        decision.failure = true;
                      }
                      else {
                        decision.outcome = 'provisioned';
                      }
                    
                      var queryParams = { '_action': 'update'};
                      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                      logger.info("Request " + requestId + " completed.");
                    }
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
              - name: scriptTask-aec6c36b3a45
                displayName: Reject Request
                type: scriptTask
                scriptTask:
                  language: javascript
                  script: |-
                    logger.info("Rejecting request");
                    
                    var content = execution.getVariables();
                    var requestId = content.get('id');
                    
                    logger.info("Execution Content: " + content);
                    var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                    var decision = {'outcome': 'denied', 'status': 'complete'};
                    var queryParams = { '_action': 'update'};
                    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  nextStep:
                    - condition: 'true'
                      outcome: done
                      step: null
            staticNodes:
              startNode:
                id: startNode
                x: 70
                'y': 140
                connections:
                  start: approvalTask-74cf85c35437
              endNode:
                id: endNode
                x: 1037
                'y': 169
                connections: null
              uiConfig:
                approvalTask-74cf85c35437:
                  actors:
                    - type: script
                      id:
                        value: |-
                          (function() {
                              var systemSettings = openidm.action('iga/commons/config/iga_access_request', 'GET', {}, {});
                              var approver = null;
                              if (requestIndex.roleOwner && requestIndex.roleOwner[0]) {
                                  approver = "managed/user/" + requestIndex.roleOwner[0].id;
                              } else if (systemSettings && systemSettings.defaultApprover) {
                                  approver = systemSettings.defaultApprover;
                              }
                          return approver;
                          })();
                        isExpression: true
                  events:
                    escalationType: script
                    escalationDate: 5
                    escalationTimeSpan: day(s)
                    reminderDate: 3
                    reminderTimeSpan: day(s)
                  x: 210
                  'y': 110
                scriptTask-0359a9d77ee2:
                  x: 438
                  'y': 42.015625
                scriptTask-aec6c36b3a45:
                  x: 432
                  'y': 127.015625
            status: published
        totalHits: 6
        searchAfterKey: CoQBEn5qInp1d35mci1zaGQ2OWt3OXU4eWxnYWs4ZWUyd2YxMnF4MTNyWAsSBnN0YXR1cyIJcHVibGlzaGVkDAsSLmF1dG9ub21vdXMtaWFtX29yY2hlc3RyYXRpb25fZGVmaW5pdGlvbl9sYXRlc3QiD0Jhc2ljUm9sZVJlbW92ZQwYACAA
    simpleOrchestration:
      value:
        id: BasicApplicationGrant
        name: BasicApplicationGrant
        displayName: BasicApplicationGrant
        description: BasicApplicationGrant access request type.
        type: provisioning
        steps:
          - name: approvalTask-74cf85c35437
            displayName: Approval Task
            type: approvalTask
            approvalTask:
              actors:
                - id:
                    value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                    isExpression: true
                  permissions:
                    approve: true
                    reject: true
                    reassign: true
                    modify: true
                    comment: true
              events:
                assignment:
                  notification: requestAssigned
                reassign:
                  notification: requestReassigned
                reminder:
                  notification: requestReminder
                  frequency: 3
                  actors: []
                  date:
                    isExpression: true
                    value: (new Date(new Date().getTime()+(3*1*24*60*60*1000))).toISOString()
                escalation:
                  notification: requestEscalated
                  date:
                    isExpression: true
                    value: (new Date(new Date().getTime()+(5*1*24*60*60*1000))).toISOString()
                  actors:
                    - id:
                        value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                        isExpression: true
                expiration:
                  action: reject
                  notification: requestExpired
                  actors: []
                  date:
                    isExpression: true
                    value: (new Date(new Date().getTime()+(7*24*60*60*1000))).toISOString()
              nextStep:
                - condition: null
                  outcome: APPROVE
                  step: scriptTask-626899b6e99a
                - condition: null
                  outcome: REJECT
                  step: scriptTask-c58309b8c470
                - condition: null
                  outcome: EXPIRATION
                  step: null
          - name: scriptTask-626899b6e99a
            displayName: Application Grant Validation
            type: scriptTask
            scriptTask:
              language: javascript
              script: |-
                logger.info("Running application grant request validation");
                
                var content = execution.getVariables();
                var requestId = content.get('id');
                var failureReason = null;
                var applicationId = null;
                var app = null;
                
                try {
                  var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                  applicationId = requestObj.application.id;
                }
                catch (e) {
                  failureReason = "Validation failed: Error reading request with id " + requestId;
                }
                
                // Validation 1 - Check application exists
                if (!failureReason) {
                  try {
                    app = openidm.read('managed/alpha_application/' + applicationId);
                    if (!app) {
                      failureReason = "Validation failed: Cannot find application with id " + applicationId;
                    }
                  }
                  catch (e) {
                    failureReason = "Validation failed: Error reading application with id " + applicationId + ". Error message: " + e.message;
                  }
                }
                
                // Validation 2 - Check the user does not already have application granted
                // Note: this is done at request submission time as well, the following is an example of how to check user's accounts
                if (!failureReason) {
                  try {
                    var user = openidm.read('managed/alpha_user/' + requestObj.user.id, null, [ 'effectiveApplications' ]);
                    user.effectiveApplications.forEach(effectiveApp => {
                      if (effectiveApp._id === applicationId) {
                        failureReason = "Validation failed: User with id " + requestObj.user.id + " already has effective application " + applicationId;
                      }
                    })
                  }
                  catch (e) {
                    failureReason = "Validation failed: Unable to check effective applications of user with id " + requestObj.user.id + ". Error message: " + e.message;
                  }
                }
                
                if (failureReason) {
                  logger.info("Validation failed: " + failureReason);
                }
                execution.setVariable("failureReason", failureReason);
              nextStep:
                - condition: 'true'
                  outcome: done
                  step: exclusiveGateway-5167870154a9
          - name: scriptTask-c58309b8c470
            displayName: Reject Request
            type: scriptTask
            scriptTask:
              language: javascript
              script: |-
                logger.info("Rejecting request");
                
                var content = execution.getVariables();
                var requestId = content.get('id');
                
                logger.info("Execution Content: " + content);
                var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                var decision = {'outcome': 'denied', 'status': 'complete'};
                var queryParams = { '_action': 'update'};
                openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
              nextStep:
                - condition: 'true'
                  outcome: done
                  step: null
          - name: exclusiveGateway-5167870154a9
            displayName: Validation Gateway
            type: scriptTask
            scriptTask:
              language: javascript
              script: logger.info("This is exclusive gateway");
              nextStep:
                - condition: failureReason == null
                  outcome: validationSuccess
                  step: scriptTask-3a74557440fb
                - condition: failureReason != null
                  outcome: validationFailure
                  step: scriptTask-744ef6a8b9a2
          - name: scriptTask-3a74557440fb
            displayName: Auto Provisioning
            type: scriptTask
            scriptTask:
              language: javascript
              script: |-
                logger.info("Auto-Provisioning");
                
                var content = execution.getVariables();
                var requestId = content.get('id');
                var failureReason = null;
                
                try {
                  var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
                  logger.info("requestObj: " + requestObj);
                }
                catch (e) {
                  failureReason = "Provisioning failed: Error reading request with id " + requestId;
                }
                
                if(!failureReason) {
                  try {
                    var request = requestObj.request;
                    var payload = {
                      "applicationId": request.common.applicationId,
                      "startDate": request.common.startDate,
                      "endDate": request.common.endDate,
                      "auditContext": {},
                      "grantType": "request"
                    };
                    var queryParams = {
                      "_action": "add"
                    }
                
                    logger.info("Creating account: " + payload);
                    var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams);
                  }
                  catch (e) {
                    failureReason = "Provisioning failed: Error provisioning account to user " + request.common.userId + " for application " + request.common.applicationId + ". Error message: " + e.message;
                  }
                
                  var decision = {'status': 'complete'};
                  if (failureReason) {
                    decision.outcome = 'not provisioned';
                    decision.comment = failureReason;
                    decision.failure = true;
                  }
                  else {
                    decision.outcome = 'provisioned';
                  }
                
                  var queryParams = { '_action': 'update'};
                  openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
                  logger.info("Request " + requestId + " completed.");
                }
              nextStep:
                - condition: 'true'
                  outcome: done
                  step: null
          - name: scriptTask-744ef6a8b9a2
            displayName: Application Grant Validation Failure
            type: scriptTask
            scriptTask:
              language: javascript
              script: |-
                var content = execution.getVariables();
                var failureReason = content.get('failureReason');
                
                var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true};
                var queryParams = { '_action': 'update'};
                openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
              nextStep:
                - condition: 'true'
                  outcome: done
                  step: null
        staticNodes:
          startNode:
            id: startNode
            x: 70
            'y': 140
            connections:
              start: approvalTask-74cf85c35437
          endNode:
            id: endNode
            x: 1288
            'y': 521
            connections: null
          uiConfig:
            approvalTask-74cf85c35437:
              actors:
                - type: applicationOwner
                  id:
                    value: '"managed/user/" + requestIndex.applicationOwner[0].id'
                    isExpression: true
              events:
                escalationType: applicationOwner
                escalationDate: 5
                escalationTimeSpan: day(s)
                reminderDate: 3
                reminderTimeSpan: day(s)
              x: 210
              'y': 110
            scriptTask-626899b6e99a:
              x: 440
              'y': 80
            scriptTask-c58309b8c470:
              x: 464
              'y': 164
            exclusiveGateway-5167870154a9:
              x: 740
              'y': 78
            scriptTask-3a74557440fb:
              x: 981
              'y': 80.5
            scriptTask-744ef6a8b9a2:
              x: 955
              'y': 193.015625
    defaultScript:
      value: |-
        logger.info(\"Creating User/Approval Task\");
        var execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        var content = execution.getVariables();
        var requestId = content.get(\"id\");
        var requestIndex = openidm.action(\"iga/governance/requests/\" + requestId, \"GET\", {}, {});"
    validate:
      value:
        - id: "Node1"
          code: "UNIQUE_NAME"
          description: "Node names must be unique."
        - id: "Node2"
          code: "JOIN_NODE"
          description: "Join Node must be inclusive."