In a patch in Grouper 2.4, Grouper will have a electronic forms workflow / approvals capability.  This will start simple and we can add more features later.  There will be the capability to have an interface so external workflow services can satisfy the request.  Fixed in patches: grouper_v2_4_0_api_patch_70 and grouper_v2_4_0_ui_patch_42

High level description

Think of this like a paper form, but electronic.  It is simple and if you need something more complicated likely you might need a BPM or workflow system and integrate with it.

  • Grouper admins (or members of etc:workflowEditors group) can configure a workflow on a group
    • Specify which groups need to approve the request
    • Configure the workflow and form fields with JSON
    • Configure the form itself with HTML
  • Workflow daemon will run to send out notifications
    • There will be two daemons
      1. Runs every 5 minutes, looks for state changes, sends out individual email
      2. Runs nightly, looks for instances that need another reminder, sends out digest email
  • Screens to view and manage the requests
  • Automatic provisioning into group(s)
  • A copy of the form being submitted will be stored at every state of the form to the database, AWS S3, or the file system.  That includes the history of the form and who approved it when

  • There is not a lightweight open source workflow library to add to grouper core, so we will create our own
    • The first part of this task is to confirm this statement
  • Note: the workflow should be able to be kicked off by the daemon when the status is "initiate".  So that workflow can be kicked off by web service.  Daemon should check every 5 minutes.  If this is the UI it should be immediate, send the email, and go to the next state.   

Changes to group drop down

Under groups, in the more actions, should be "Electronic forms", which goes to View forms screen.  

"Join" a group could kick off a workflow too

Notifications

Emails should be sent out to approvers when they need to approve forms.  Emails should be sent out when the state changes, or daily (in a digest per user)

Hooks on workflow

Workflow should have hooks at various place so it can be customized

View electronic forms screen

This is the default screen.   Drop down with the following options:

  1. View forms
  2. Edit forms

Miscellaneous → Forms

  1. My forms - see forms the current user submitted
  2. Forms waiting for my approval - see forms that need approvals

Screenshots

On each group, there's a new action available in the More actions dropdown.


Clicking on the Electronic forms shows all the workflows configured on the selected group.


When a subject wants to join the group and click on the Join group button in the More actions, they are shown a form configured as per the workflow.


Under Miscellaneous, there is a new link called Forms


Clicking on Miscellaneous → Forms → My forms shows a list of all the forms the logged in subject has initiated.


Clicking on Miscellaneous → Forms → Forms waiting for my approval shows a list of all the forms logged in subject has in its pending queue.


To Do later

  • Enable kicking off workflows from other events (e.g. folder create, group create, membership add , membership remove , attribute values add/change/remove, etc…)
  • Form search - for form admins, can search for forms, see status, search by submitter, able to approve forms for approvers

Configuration

The configuration will follow the same attribute structure as other Grouper modules like reporting

Attribute definitions for config

Definition

Assigned To

Purpose

Value

Cardinality

workflowConfigDef

groupidentify a workflow configmarkerMulti assign

workflowConfigValueDef

group assignmentname/value pairsstringSingle assign, single valued


Instance values at different states in workflow

When user submits form

AttributeValue
workflowInstanceStateinitiate
workflowInstanceLastUpdatedMillisSince1970lastUpdated

workflowInstanceConfigMarkerAssignmentId

assign id
workflowInstanceInitiatedMillisSince1970timestamp
workflowInstanceUuiduuid
workflowInstanceEncryptionKeygenerated an encrypted encryption key
workflowInstanceFileInfo

value is:

{ fileNamesAndPointers: [
{state: "initiate", fileName: "/something.html", filePointer: "something/something"}
]
}


File contents have:

HTML

show form just like they saw it

has values in there.

has some auditing at the bottom in div.  append to that at each state

subjectsource: subjectID, name clicked approve for state dataOwner on timestamp: 2019/03/05 12:35:47 (standard timestamp format)



workflowInstanceLog
{
logEntries: [
  {subjectSourceId: "jdbc", subjectId: "jsmith", action: "initiate", state: "initiate", millisSince1970: 12345678}
]
}
workflowInstanceParamValue0

params should be in order that they are configured

{paramName: "notesForApprovers", paramValue: "He will be collaborating with such and such which is why he needs access", 
lastUpdatedMillis: 12324345432434234, editedByMemberId: "abc123", editedInState: "initiate"}
workflowInstanceParamValue1if there is more than one param, put second one here

Daemon runs, sees the state initiate, and progresses workflow:

AttributeValue
workflowInstanceStatesupervisor
workflowInstanceLastUpdatedMillisSince1970lastUpdated

workflowInstanceLastEmailedDate

now
workflowInstanceLastEmailedStatesupervisor
workflowInstanceLog
{
logEntries: [
  {subjectSourceId: "jdbc", subjectId: "jsmith", action: "initiate", state: "initiate", millisSince1970: 12345678},
  {action: "workflowStateChange", state: "supervisor", millisSince1970: 12345679}
]
}

Attribute names for config

Note: for non-grouper workflows configured in grouper.properties, only the marker and type will be set.  For Grouper workflows, all the attributes will be available

Name

Definition

Required?

Value

workflowConfigMarker

workflowConfigDef
<none>
workflowConfigTypeworkflowConfigValueDefrequiredif grouper is the only implementation in grouper.properties, auto populate with "grouper", otherwise list other implementations
workflowConfigApprovalsworkflowConfigValueDefrequired

This is a JSON config of the workflow approvals.  must have "initiate" and "complete"

{
  states: [
    {
      stateName: "initiate", 
      allowedGroupId: "abc123def456"     
    },
    
    {
      stateName: "supervisor",
      approverSubjectId: "${initiatorSubject.attribute['supervisorSubjectId']}",
      approverSubjectSourceId: "mypeople"
    },
    
    {
      stateName: "dataOwner",
      //who can approve
      approverGroupId: "sdgf76gdf87",  
      //who is notified, if blank, then use approverGroupId
      approverNotifyGroupId: "dfkjh234kjb"
    },
    
    {
      stateName: "complete",
      //if blank use the selected groups from form or just the group
      //the workflow is assigned to
      actions: [
           {
              actionName: "assignToGroup",
              actionArg0: "sgk234kh234" 
            }
        ]
    }
  ]
}

This is the default and should pre-populate:

{
  states: [
    {
      stateName: "initiate", 
    },
    {
      stateName: "groupManager",
      //who can approve
      approverManagersOfGroupId: "sdgf76gdf87" <-- groupId of current group
                                               <-- updater/admins of group
    },
    {
      stateName: "complete",
      //if blank use the selected groups from form or just the group
      //the workflow is assigned to
      actions: [
           {
              actionName: "assignToGroup",
              actionArg0: "sgk234kh234"   <-- groupId of current group
            }
        ]
    }
  ]
}

workflowConfigName

workflowConfigValueDefrequired

Name of workflow. No two workflows in the same owner should have the same name

Default to groupName_managerApproval   (e.g. wikiUsers_managerApproval)

workflowConfigIdworkflowConfigValueDefrequired

Camel-case alphanumeric id of workflow.  No two workflows in all of Grouper can have the same ID

Default to groupName_managerApproval   (e.g. wikiUsers_managerApproval)

workflowConfigDescriptionworkflowConfigValueDefrequired

Textarea which describes the information in the workflow. Must be less than 4k

Default to: Group: $groupDisplayPath% approval for membership.  The group's managers will be notified about requests and can approve them.

workflowConfigParams

workflowConfigValueDefrequired

Note: max 10 params, checkbox is true/false

{
  params: [
    { 
      paramName: "agreeToTerms",
      label: "Agree to terms",
      type: "checkbox",
      editableInStates: "initiate",
      required: "true"
    },
    {
      paramName: "notes",
      label: "Notes",
      type: "textarea",
      editableInStates: "initiate"
    },
    {
      paramName: "notesForApprovers",
      label: "Notes for approvers",
      type: "textarea",
      editableInStates: "supervisor, dataOwner"
    },
    {
      paramName: "reason",
      label: "Reason",
      type: "text",
      editableInStates: "initiate"
    }
  ]
}

Default pre-populated:

{
  params: [
    {
      paramName: "notes",
      label: "Notes",
      type: "textarea",
      editableInStates: "initiate"
    },
    {
      paramName: "notesForApprovers",
      label: "Notes for approvers",
      type: "textarea",
      editableInStates: "supervisor, dataOwner"
    }
  ]
}
workflowConfigFormworkflowConfigValueDefoptional

Note: Grouper with javascript will enable or disable these form fields, or fill in values, as needed.  The form field names need to match the names in the params.  The id must match with "Id" appended to the end.  If a name or id doesnt exist in the HTML there will be an error

Fill out this form to be added to this group.<br /><br />
Several approvals will take place which usually take less than 2 business days<br /><br />
State the reason you would like this access: <input type="text" name="reason" id="reasonId" /><br /><br >
<input type="checkbox" name="agreeToTerms" id="agreeToTermsId" /> I agree this this institutions' <a href="https://whatever.whatever/whatever">terms and conditions</a><br /><br />
Notes: <textarea rows="4" cols="50" name="notes" id="notesId"></textarea><br /><br />
Notes for approvers: <textarea rows="4" cols="50" name="notesForApprovers" id="notesForApproversId"></textarea><br /><br />


This is the default:

Submit this form to be added to this group.<br /><br />
The managers of the group will be notified to approve this request.<br /><br />
Notes (optional): <textarea rows="4" cols="50" name="notes" id="notesId"></textarea><br /><br />
Notes for approvers: <textarea rows="4" cols="50" name="notesForApprovers" id="notesForApproversId"></textarea><br /><br />
workflowConfigViewersGroupIdworkflowConfigValueDefoptionalGroupId of people who can view this workflow and instances of this workflow. Grouper admins can view any workflow (blank means admin only).  Anyone in an approver group can view the workflow.

workflowConfigSendEmail

workflowConfigValueDefrequired (default to true, no blank option available)true/false if email should be sent

workflowConfigEnabled

workflowConfigValueDefdefault to true (required, no blank option)Could by "true", "false", or "noNewSubmissions", i.e. let current forms go through


Attribute definitions for instance (a workflow that was run)

This attribute is assigned to the same owner as the config attribute (e.g. the same group/folder)

Definition

Assigned To

Purpose

Value

Cardinality

workflowInstanceDefgroupidentify a workflow that was runmarkerMulti assign
workflowInstanceValueDeffolder assignment, group assignmentname/value pairsstringSingle assign, single valued


Attribute names for instance

Note: the ID is the attribute assign id of the marker (this is passed in URLs/emails etc)

Name

Definition

Value

workflowInstanceMarker

workflowInstanceDef<none>
workflowInstanceStateworkflowInstanceValueDefAny of the states, plus "exception" if there is a problem, workflows must have "initiate", and "complete", plus "rejected" if someone rejects it.
workflowInstanceLastUpdatedMillisSince1970workflowInstanceValueDefnumber of millis since 1970 when this instance was last updated

workflowInstanceConfigMarkerAssignmentId

workflowInstanceValueDefAttribute assign ID of the marker attribute of the config (same owner as this attribute, but there could be many workflows configured on one owner)
workflowInstanceInitiatedMillisSince1970workflowInstanceValueDefmillis since 1970 that this workflow was submitted
workflowInstanceUuidworkflowInstanceValueDefuuid assigned to this workflow instance
workflowInstanceFileInfoworkflowInstanceValueDef

value is:

pointer: depending on storage type, this is a pointer to the workflow in storage, e.g. the S3 address. note the S3 address is .csv suffix, but change to __metadata.json for instance metadata

{ fileNamesAndPointers: [
{state: "initiate", fileName: "/something.html", filePointer: "something/something"}
]
}


File contents have:

HTML

show form just like they saw it

has values in there.

has some auditing at the bottom in div.  append to that at each state

subjectsource: subjectID, name clicked approve for state dataOwner on timestamp: 2019/03/05 12:35:47 (standard timestamp format)



workflowInstanceEncryptionKeyworkflowInstanceValueDefrandomly generated 16 char alphanumeric encryption key (never allow display or edit of this)

workflowInstanceLastEmailedDate

workflowInstanceValueDefyyyy/mm/dd date that this was last emailed so multiple emails dont go out on same day
workflowInstanceLastEmailedStateworkflowInstanceValueDefthe state of the workflow instance when it was last emailed
workflowInstanceLogworkflowInstanceValueDefhas brief info about who did what when on this instance
workflowInstanceErrorworkflowInstanceValueDeferror message including stack of why this instance is in "exception" state
workflowInstanceParamValue0workflowInstanceValueDef
{paramName: "agreeToTerms", paramValue: "true", lastUpdatedMillis: 12324345432434234, editedByMemberId: "abc123", editedInState: "initiate"}
workflowInstanceParamValue1workflowInstanceValueDef
{paramName: "notes", paramValue: "Im traveling abroad and need access to such and such", lastUpdatedMillis: 12324345432434234, editedByMemberId: "abc123", editedInState: "initiate"}
workflowInstanceParamValue2workflowInstanceValueDef
{paramName: "notesForApprovers", paramValue: "He will be collaborating with such and such which is why he needs access", lastUpdatedMillis: 12324345432434234, editedByMemberId: "abc123", editedInState: "initiate"}
workflowInstanceParamValue3workflowInstanceValueDef
{paramName: "reason", paramValue: "Need access to whatever system", lastUpdatedMillis: 12324345432434234, editedByMemberId: "abc123", editedInState: "initiate"}
workflowInstanceParamValue4workflowInstanceValueDef
workflowInstanceParamValue5workflowInstanceValueDef
workflowInstanceParamValue6workflowInstanceValueDef
workflowInstanceParamValue7workflowInstanceValueDef
workflowInstanceParamValue8workflowInstanceValueDef
workflowInstanceParamValue9workflowInstanceValueDef
  • No labels