PingOne Advanced Identity Cloud

Workflow to create an Organization custom request type and form

In this example, an administrator wants to create a custom request type called Create Organization to add new organizations to the system. Administrators and form creators need to carry out the following tasks:

After these tasks, the approver receives the request and can start reviewing it.

Assumptions

  • You have designated an end user who can function as an approver and review the request.

  • You have configured notification emails to alert the approver of incoming requests.

Example

Task 1: Create an organization request type

The initial task is to create a custom request type, Create Organization that lets an administrator easily add a new organization to the system.

Currently, the only way to create a custom request type is through the API. The UI will support this functionality in a future release.

  • Create a custom request type called Create Organization using the API. Enter the following command using curl to create your custom request type:

    Details
    curl --location 'http://<hostname>/iga/governance/requestTypes' \
    --header 'Authorization: Bearer token' \
    --header 'Content-Type: application/json' \
    --data '{
        "id": "createOrganization",
        "schemas": {
            "common": [
                {
                    "_meta": {
                        "type": "system",
                        "displayName": "commonRequest",
                        "properties": {
                            "justification": {
                                "isRequired": false,
                                "isInternal": true,
                                "display": {
                                    "name": "Justification",
                                    "isVisible": true,
                                    "order": 3,
                                    "description": "The reason for the request"
                                }
                            },
                            "externalRequestId": {
                                "isRequired": false,
                                "isInternal": true,
                                "isChangable": false,
                                "display": {
                                    "name": "External Request ID",
                                    "isVisible": true,
                                    "order": 4,
                                    "description": "The external ID for the request"
                                }
                            },
                            "requestIdPrefix": {
                                "isRequired": false,
                                "isInternal": true,
                                "display": {
                                    "name": "Request ID prefix",
                                    "isVisible": true,
                                    "order": 5,
                                    "description": "Prefix for the request ID"
                                }
                            },
                            "isDraft": {
                                "isRequired": false,
                                "isInternal": true
                            },
                            "priority": {
                                "isRequired": false,
                                "display": {
                                    "name": "Priority",
                                    "isVisible": true,
                                    "order": 6,
                                    "description": "The priority of the reqeust"
                                },
                                "text": {
                                    "defaultValue": "low"
                                }
                            },
                            "expiryDate": {
                                "isRequired": false,
                                "isInternal": true,
                                "display": {
                                    "name": "Request expiration date",
                                    "isVisible": true,
                                    "order": 7,
                                    "description": "User provided date on which the request will cancel"
                                }
                            },
                            "context": {
                                "isRequired": false,
                                "isInternal": true,
                                "isMultiValue": false,
                                "display": {
                                    "name": "Context",
                                    "isVisible": true,
                                    "order": 1,
                                    "description": "The context of the request"
                                }
                            },
                            "workflowId": {
                                "isRequired": false,
                                "isInternal": true,
                                "isChangable": false,
                                "display": {
                                    "name": "BPMN workflow ID",
                                    "isVisible": true,
                                    "order": 7,
                                    "description": "The ID key of the BPMN workflow"
                                }
                            },
                            "blob": {
                                "isRequired": false,
                                "isInternal": true
                            }
                        }
                    },
                    "properties": {
                        "justification": {
                            "type": "text"
                        },
                        "externalRequestId": {
                            "type": "text"
                        },
                        "requestIdPrefix": {
                            "type": "text"
                        },
                        "isDraft": {
                            "type": "boolean"
                        },
                        "priority": {
                            "type": "text"
                        },
                        "expiryDate": {
                            "type": "text"
                        },
                        "context": {
                            "type": "object"
                        },
                        "workflowId": {
                            "type": "text"
                        },
                        "blob": {
                            "type": "object"
                        }
                    }
                }
            ],
            "custom": [
                {
                    "_meta": {
                        "type": "system",
                        "displayName": "Create Organization",
                        "properties": {
                            "name": {
                                "isRequired": true,
                                "isInternal": false,
                                "isMultiValue": false,
                                "display": {
                                    "name": "Name",
                                    "isVisible": true,
                                    "order": 1,
                                    "description": "The name of the organization"
                                }
                            },
                            "description": {
                                "isRequired": false,
                                "isInternal": false,
                                "isMultiValue": false,
                                "display": {
                                    "name": "Description",
                                    "isVisible": true,
                                    "order": 2,
                                    "description": "The description of the organization being created"
                                }
                            },
                            "parent": {
                                "isRequired": false,
                                "isInternal": false,
                                "isMultiValue": false,
                                "display": {
                                    "name": "Parent Organization",
                                    "isVisible": true,
                                    "order": 3,
                                    "description": "The ID of the parent organization for this organization"
                                }
                            },
                            "admins": {
                                "isRequired": false,
                                "isInternal": false,
                                "isMultiValue": true,
                                "display": {
                                    "name": "Organization Administrators",
                                    "isVisible": true,
                                    "order": 4,
                                    "description": "The IDs of the users who will be this organization's admins"
                                }
                            },
                            "includeSelfAdmin": {
                                "isRequired": false,
                                "isInternal": false,
                                "isMultiValue": false,
                                "display": {
                                    "name": "Include Self as Admin",
                                    "isVisible": true,
                                    "order": 4,
                                    "description": "If selected, include requester as an organization admin"
                                }
                            }
                        }
                    },
                    "properties": {
                        "name": {
                            "type": "text"
                        },
                        "description": {
                            "type": "text"
                        },
                        "parent": {
                            "type": "text"
                        },
                        "admins": {
                            "type": "text"
                        },
                        "includeSelfAdmin": {
                            "type": "boolean"
                        }
                    }
                }
            ]
        },
        "workflow": {
            "id": "createOrganization",
            "type": "bpmn"
        },
        "validation": {
            "source": "var validation = {\"errors\" : [], \"comments\" : []}; if (request.custom.name == undefined) { validation.errors.push(\"Must include all name field.\");} validation;"
        },
        "custom": true,
        "displayName": "Create Organization",
        "uniqueKeys": [
            "custom.name"
        ],
        "notModifiableProperties": []
    }'

Task 2: Create a form for the organization request type

  1. In the Advanced Identity Cloud admin UI, click Governance > Forms.

  2. On the New Form modal, click Custom request form, and then click Next.

  3. On the Custom request form modal, enter the following:

    Field Description

    Form

    Enter a descriptive name for your form. In this example, enter: Create Organization.

    Description (optional)

    Enter a general description for your form. In this example, enter: Form used to create a new organization.

    Request Type (optional)

    Click and select a request type for the form. In this example, enter: Create Organization.

    You can only assign one form to each request type.

    Once you create your form, you can go back and make edits to any of the previous form settings by clicking the ellipsis() in the top right, and then click Settings.

  4. Use the Forms editor to create a form for your custom request type. For example, drag-and-drop five form fields onto the canvas for the fields and label them:

    1. On the Forms editor canvas, drag-and-drop the Text node to the canvas, and fill in the properties in the right pane for the Organization Name field:

      Organization name text field properties
      Field Description

      Key

      Enter the key for the text string. You can retrieve this key from the example in Task 1 under the schemas entry. For example, enter custom.name as the key.

      Label

      Enter a general label for this text field. For example, enter User Name.

      Description

      Enter help text for the text field. The description appears below your text field. Enter Name of the organization.

      Required

      Click if this text field is required. In this example, click Required.

      Read Only

      Click to make the field non-editable. In this example, skip this step.

      Provide Default Value

      Click Provide Default Value to assign a default value for this text field. In this example, skip this step.

      Columns

      Enter the number of columns for this text field. Values are from 1 to 12. For this example, use the default (12 columns).

      Offset

      Enter the number of columns to offset from the left for this text field. Values are from 0 to 11. For this example, use the default (0).

      Use validation

      Click if you want to validate the text field using a regular expression. In this example, skip this step.

    2. On the Forms editor canvas, drag-and-drop the Textarea node to the canvas, and fill in the properties in the right pane for the Description field:

      Description textarea field properties
      Field Description

      Key

      Enter the key for the text string. You can retrieve this key from the example in Task 1 under the schemas entry. For example, enter custom.description as the key.

      Label

      Enter a general label for this text field. For example, enter Description.

      Description

      Enter help text for the text field. The description appears below your text field.

      Required

      Click if this text field is required. In this example, skip this step.

      Read Only

      Click to make the field non-editable. In this example, skip this step.

      Provide Default Value

      Click Provide Default Value to assign a default value for this text field. In this example, skip this step.

      Columns

      Enter the number of columns for this text field. Values are from 1 to 12. For this example, use the default (12 columns).

      Offset

      Enter the number of columns to offset from the left for this text field. Values are from 0 to 11. For this example, use the default (0).

      Use Validation

      Click if you want to validate the text field using a regular expression. In this example, skip this step.

    3. On the Forms editor canvas, drag-and-drop the Select node to the canvas, and fill in the properties in the right pane for the Parent Organization field:

      Parent Organization Select field properties
      Field Description

      Key

      Enter the key for the text string. You can retrieve this key from the example in Task 1 under the schemas entry. For example, enter custom.parent as the key.

      Label

      Enter a general label for this text field. For example, enter Parent Organization (optional).

      Description

      Enter help text for the text field. The description appears below your text field.

      Required

      Click if this text field is required. In this example, skip this step.

      Read Only

      Click to make the field non-editable. In this example, skip this step.

      Options

      Click to manually add enumerated values for your Select menu options:

      1. Click .

      2. On the Add Option modal, do the following:

        1. Value: enter a value for the option field. For example, in the Advanced Identity Cloud end-user UI, click Identities > Manage > <realm> realm - Organizations and search for an organization, such as the Engineering organization, you can view the ID as a27172ad-8adf-425e-a93f-ebd7c7aaa776. Enter this managed organization ID in the Value field.

        2. Label: enter a label for the option field. In this example, enter: Engineering.

        3. Click Selected by default to make the option a default enumerated value for the field.

      3. Click Add.

        1. Repeat the steps 1–3 again to add more Select menu options.

      Provide Default Value

      Click Provide Default Value to assign a default value for this text field. In this example, skip this step.

      Columns

      Enter the number of columns for this text field. Values are from 1 to 12. In this example, use the default (12).

      Offset

      Enter the number of columns to offset from the left for this text field. Values are from 0 to 11. For this example, enter 0.

      Use validation

      Click if you want to validate the text field using a regular expression. In this example, skip this step.

      Regex

      Enter a regular expression to validate the text field.

      Error message

      Enter an error message when the regular expression fails.

    4. On the Forms editor canvas, drag-and-drop the Select node to the canvas, and fill in the properties in the right pane for the Organization Admins field:

      Organization Admins Select field properties
      Field Description

      Key

      Enter the key for the text string. You can retrieve this key from the example in Task 1 under the schemas entry. For example, enter custom.admins as the key.

      Label

      Enter a general label for this text field. For example, enter Organization Admins (optional).

      Description

      Enter help text for the text field. The description appears below your text field.

      Required

      Click if this text field is required. In this example, skip this step.

      Read Only

      Click to make the field non-editable. In this example, skip this step.

      Options

      Click to manually add enumerated values for your Select menu options:

      1. Click .

      2. On the Add Option modal, do the following:

        1. Value: enter a value for the option field. For example, in the Advanced Identity Cloud end-user UI, click Identities > Manage > <realm> realm - Users and search for a user, such as Frank York. You can view the ID as c51d9ee1-43b3-49d1-8742-cbb33842a5cc. Enter this managed user ID in the Value field.

        2. Label: enter a label for the option field. In this example, enter an admin user, such as Frank York.

        3. Click Selected by default to make the option a default enumerated value for the field. In this example, skip this step.

      3. Click Add.

        1. Repeat the steps 1–3 again to add more options.

      Provide Default Value

      Click Provide Default Value to assign a default value for this text field. In this example, skip this step.

      Columns

      Enter the number of columns for this text field. Values are from 1 to 12. In this example, use the default (12).

      Offset

      Enter the number of columns to offset from the left for this text field. Values are from 0 to 11. In this example, use the default (0).

      Use validation

      Click if you want to validate the text field using a regular expression. In this example, skip this step.

    5. On the Forms editor canvas, drag-and-drop the Checkbox node to the canvas, and fill in the properties in the right pane for the Include yourself as administrator field:

      Include yourself as administrator Checkbox field properties
      Field Description

      Key

      Enter the key for the text string. You can retrieve this key from the example in Task 1 under the schemas entry. For example, enter custom.includeSelfAdmin as the key.

      Label

      Enter a general label for this text field. For example, enter Include yourself as administrator.

      Description

      Enter help text for the text field. The description appears below your text field.

      Read Only

      Click to make the field non-editable. In this example, skip this step.

      Provide Default Value

      Click Provide Default Value to assign a default value for this text field. In this example, skip this step.

      Columns

      Enter the number of columns for this text field. Values are from 1 to 12. In this example, use the default (12).

      Offset

      Enter the number of columns to offset from the left for this text field. Values are from 0 to 11. In this example, use the default (0).

      Use validation

      Click if you want to validate the text field using a regular expression. In this example, skip this step.

  5. Click Preview to review your form.

  6. Click Save.

    An example of a form for the `Create Organization` custom request type.

Task 3: Create a workflow to use the organization request type and form

An example of a workflow using the organization request type and form.
  • 1 Use a Script node to do a context check for the request.

    Click to display the Request Context Check script
    var content = execution.getVariables();
    var requestId = content.get('id');
    var context = null;
    var skipApproval = false;
    try {
      var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
      if (requestObj.request.common.context) {
        context = requestObj.request.common.context.type;
        if (context == 'admin') {
          skipApproval = true;
        }
      }
    }
    catch (e) {
      logger.info("Request Context Check failed "+e.message);
    }
    
    logger.info("Context: " + context);
    execution.setVariable("context", context);
    execution.setVariable("skipApproval", skipApproval);
  • 2 Use an IF/ELSE node and name it Context Gateway. If skipApproval==true, route it to the Auto Approval node. If skipApproval==false, route it to the Approval Task node.

  • 3 Use a Script node for the Auto Approval task.

    Click to display the Auto Approval script
    var content = execution.getVariables();
    var requestId = content.get('id');
    var context = content.get('context');
    var queryParams = {
      "_action": "update"
    }
    try {
      var decision = {
          "decision": "approved",
          "comment": "Request auto-approved due to request context: " + context
      }
      openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
    }
    catch (e) {
      var failureReason = "Failure updating decision on request. Error message: " + e.message;
      var update = {'comment': failureReason, 'failure': true};
      openidm.action('iga/governance/requests/' + requestId, 'POST', update, queryParams);
    
    }
  • 4 Use a Script node to create a new organization using the custom request type.

    Click to display the Create Organization script node
    logger.info("Creating Organization");
    
    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 = {
          "name": request.custom.name,
          "description": request.custom.description,
          "admins": []
        };
    
        if (request.custom.parent) {
          payload.parent = {
            "_ref": "managed/alpha_organization/" + request.custom.parent,
            "_refProperties": {}
          }
        }
    
        if (request.custom.admins) {
          request.custom.admins.forEach(function(admin) {
            payload.admins.push({ "_ref": "managed/alpha_user/" + admin, "_refProperties": {}});
          });
        }
    
        if (request.custom.includeSelfAdmin) {
          payload.admins.push({ "_ref": "managed/alpha_user/" + requestObj.requester.id.split('/')[2], "_refProperties": {}});
        }
    
        /** Create new org **/
        var result = openidm.create('managed/alpha_organization', null, payload);
    
        /** Send new org admins email **/
    
        payload.admins.forEach(function(admin) {
          var id = admin._ref
          var adminUser = openidm.read(id);
          var body = {
            subject: "Welcome " + adminUser.givenName + " " + adminUser.sn + "!",
            to: adminUser.mail,
            body: "You have been added as an administrator for a new organization.\nOrganization: " + payload.name + "",
            object: {}
          };
          openidm.action("external/email", "send", body);
        });
      }
      catch (e) {
        failureReason = "Creating org failed: Error during creation of organization " + request.custom.name + ". Error: " + e.message;
      }
    
      var decision = {'status': 'complete', 'decision': 'approved'};
      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.");
    }
  • 5 The Approval node assigns an approval task to users and roles. The node chains tasks in conjunction with a Switch node to implement serial or parallel flows.

    Click to display the Approval Task properties
    Item Description

    Name

    Approval Task

    Approvers

    Two options are available:

    • Add users who can approve the request, such as fyork, and define the Approver type. For this example, click . In the Approver Type field, select User, and then select a user. Give the approver all permissions below. Click Add.

      • Approve

      • Reject

      • Reassign

      • Modify

      • Comment

    • Define users using a script:

    Form

    Select a form to present to the reviewer.

    • Dynamic form selection. Skip this step

    • Click Choose a form and select Create Organization.

    Expiration Settings

    Options are:

    • Reject request. For this example, you can select this option.

    • Reassign request

    • Do nothing

    Notification Settings

    Options are:

    • Assignment notification and email templates, such as requestAssigned.

    • Reassignment notification and email templates, such as requestReassigned.

    • Assignee reminders and email templates, such as requestReminder.

      • Sends every number of time periods, such as 3 day(s).

    • Escalation notifications and email templates, such as requestEscalated.

      • Send every number of day(s), such as 5 day(s).

      • Send to Send escalation to to User and select User.

      • Send escalation to: Select User and select a user to handle the escalation.

    • Expiration notification and email templates, such as requestExpired.

      • Send a configured number of days before expiration.

  • 6 Use the Script node to process any request rejections.

    Click to display the Reject Request 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', 'decision': 'rejected'};
    var queryParams = { '_action': 'update'};
    openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);

Download the JSON file for this workflow here.

Learn more about how to import or export workflows in workflow editor canvas.

Task 4: Submit the organization request

You can enter a curl command to submit a Create Organization request.

curl --location 'https://<hostname>/iga/governance/requests/createOrganization?_action=publish' \
--header 'Authorization: Bearer token' \
--header 'Content-Type: application/json' \
--data '{
    "custom": {
        "name": "IGA Organization",
        "description": "Organization for all IGA members.",
        "parent": "a27172ad-8adf-425e-a93f-ebd7c7aaa776",
        "admins": [
            "c51d9ee1-43b3-49d1-8742-cbb33842a5cc",
            "e140e883-8ec7-4201-889d-f77ea118fcf3",
            "adeb08c0-f3b7-44eb-a31a-a31fba305a40"
        ],
        "includeSelfAdmin": false
    },
    "common": {

    }
}'

Currently, you must include the common key either unpopulated or to provide additional information, such as justification.

Approver Task: Process the organization request

Once the administrator submits the request, the approver (for example, "Frank York") can review the request.

Organization request