diff --git a/.gitignore b/.gitignore index f509b359e..deaccb3a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ pyrightconfig.json -.idea/ \ No newline at end of file +.idea/ +t diff --git a/bin/run_pyl b/bin/run_pyl index af82c6a6a..d3abd7fc6 100755 --- a/bin/run_pyl +++ b/bin/run_pyl @@ -20,6 +20,12 @@ function get_python_dirs() { (git ls-tree -r HEAD --name-only | grep -E '\.py$' | awk -F '/' '{print $1}' | sort | uniq | grep -v '\.' | grep -Ev '^(bin|migrations)$') || echo '' } +function run_fix_docstrings() { + if command -v fix_python_docstrings >/dev/null ; then + fix_python_docstrings $(get_top_level_directories_containing_python_files) + fi +} + function run_autoflake() { if ! command -v autoflake8 >/dev/null ; then pip install autoflake8 @@ -51,6 +57,7 @@ done for python_project in "${python_projects[@]}" ; do pushd "$python_project" + run_fix_docstrings || run_fix_docstrings run_autoflake || run_autoflake popd done diff --git a/spiffworkflow-backend/bin/import_tickets_for_command_line.py b/spiffworkflow-backend/bin/import_tickets_for_command_line.py index 8b145dc4a..e193b5990 100644 --- a/spiffworkflow-backend/bin/import_tickets_for_command_line.py +++ b/spiffworkflow-backend/bin/import_tickets_for_command_line.py @@ -74,7 +74,7 @@ def main(): print(f"ticket_identifier: {ticket_identifier}") print(f"priority: {priority}") - process_instance = ProcessInstanceService.create_process_instance( + process_instance = ProcessInstanceService.create_process_instance_from_process_model_identifier( process_model_identifier_ticket, user, process_group_identifier="sartography-admin", diff --git a/spiffworkflow-backend/bin/import_tickets_for_script_task.py b/spiffworkflow-backend/bin/import_tickets_for_script_task.py index f89779788..6b12699be 100644 --- a/spiffworkflow-backend/bin/import_tickets_for_script_task.py +++ b/spiffworkflow-backend/bin/import_tickets_for_script_task.py @@ -68,7 +68,7 @@ def main(): print(f"priority: {priority}") # if there is no month, who cares about it. if month: - process_instance = ProcessInstanceService.create_process_instance( + process_instance = ProcessInstanceService.create_process_instance_from_process_model_identifier( process_model_identifier=process_model_identifier_ticket, user=user, process_group_identifier="sartography-admin", diff --git a/spiffworkflow-backend/bin/spiffworkflow-realm.json b/spiffworkflow-backend/bin/spiffworkflow-realm.json index 4b37f289b..e0b7ee3f7 100644 --- a/spiffworkflow-backend/bin/spiffworkflow-realm.json +++ b/spiffworkflow-backend/bin/spiffworkflow-realm.json @@ -1,3182 +1,2866 @@ { - "id": "spiffworkflow", - "realm": "spiffworkflow", - "notBefore": 0, - "defaultSignatureAlgorithm": "RS256", - "revokeRefreshToken": false, - "refreshTokenMaxReuse": 0, - "accessTokenLifespan": 1800, - "accessTokenLifespanForImplicitFlow": 900, - "ssoSessionIdleTimeout": 86400, - "ssoSessionMaxLifespan": 864000, - "ssoSessionIdleTimeoutRememberMe": 0, - "ssoSessionMaxLifespanRememberMe": 0, - "offlineSessionIdleTimeout": 2592000, - "offlineSessionMaxLifespanEnabled": false, - "offlineSessionMaxLifespan": 5184000, - "clientSessionIdleTimeout": 0, - "clientSessionMaxLifespan": 0, - "clientOfflineSessionIdleTimeout": 0, - "clientOfflineSessionMaxLifespan": 0, - "accessCodeLifespan": 60, - "accessCodeLifespanUserAction": 300, - "accessCodeLifespanLogin": 1800, - "actionTokenGeneratedByAdminLifespan": 43200, - "actionTokenGeneratedByUserLifespan": 300, - "oauth2DeviceCodeLifespan": 600, - "oauth2DevicePollingInterval": 5, - "enabled": true, - "sslRequired": "external", - "registrationAllowed": false, - "registrationEmailAsUsername": false, - "rememberMe": false, - "verifyEmail": false, - "loginWithEmailAllowed": true, - "duplicateEmailsAllowed": false, - "resetPasswordAllowed": false, - "editUsernameAllowed": false, - "bruteForceProtected": false, - "permanentLockout": false, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 60, - "quickLoginCheckMilliSeconds": 1000, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 30, - "roles": { - "realm": [ - { - "id": "c9f0ff93-642d-402b-965a-04d70719886b", - "name": "default-roles-spiffworkflow", - "description": "${role_default-roles}", - "composite": true, - "composites": { - "realm": ["offline_access", "uma_authorization"], - "client": { - "account": ["view-profile", "manage-account"] + "id" : "spiffworkflow", + "realm" : "spiffworkflow", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 1800, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 86400, + "ssoSessionMaxLifespan" : 864000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "c9f0ff93-642d-402b-965a-04d70719886b", + "name" : "default-roles-spiffworkflow", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "view-profile", "manage-account" ] + } + }, + "clientRole" : false, + "containerId" : "spiffworkflow", + "attributes" : { } + }, { + "id" : "9f474167-5707-4c10-8f9e-bb54ec715cd3", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "spiffworkflow", + "attributes" : { } + }, { + "id" : "6738d143-2d1d-4458-8a98-01ea003fde14", + "name" : "admin", + "composite" : false, + "clientRole" : false, + "containerId" : "spiffworkflow", + "attributes" : { } + }, { + "id" : "6cbcdea5-0083-469d-9576-1d245fb3cdfd", + "name" : "repeat-form-role-realm", + "composite" : false, + "clientRole" : false, + "containerId" : "spiffworkflow", + "attributes" : { } + }, { + "id" : "b5a92aee-82d2-4687-8282-365df4df21a9", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "spiffworkflow", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "257c348c-4b9e-4fea-be39-5fdd28e8bb93", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "1d224265-63a8-40ea-9316-47627d0aed8c", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "535d7ca0-0f06-42d8-938b-e6e7aabffb42", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "9ff52ab5-2558-4cb0-901f-6e6f1469d075", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "manage-authorization", "view-authorization", "query-groups", "view-clients", "view-realm", "manage-users", "query-users", "impersonation", "manage-clients", "view-identity-providers", "create-client", "query-realms", "view-users", "view-events", "manage-identity-providers", "manage-events", "query-clients", "manage-realm" ] } }, - "clientRole": false, - "containerId": "spiffworkflow", - "attributes": {} - }, - { - "id": "9f474167-5707-4c10-8f9e-bb54ec715cd3", - "name": "uma_authorization", - "description": "${role_uma_authorization}", - "composite": false, - "clientRole": false, - "containerId": "spiffworkflow", - "attributes": {} - }, - { - "id": "6738d143-2d1d-4458-8a98-01ea003fde14", - "name": "admin", - "composite": false, - "clientRole": false, - "containerId": "spiffworkflow", - "attributes": {} - }, - { - "id": "6cbcdea5-0083-469d-9576-1d245fb3cdfd", - "name": "repeat-form-role-realm", - "composite": false, - "clientRole": false, - "containerId": "spiffworkflow", - "attributes": {} - }, - { - "id": "b5a92aee-82d2-4687-8282-365df4df21a9", - "name": "offline_access", - "description": "${role_offline-access}", - "composite": false, - "clientRole": false, - "containerId": "spiffworkflow", - "attributes": {} - } - ], - "client": { - "realm-management": [ - { - "id": "257c348c-4b9e-4fea-be39-5fdd28e8bb93", - "name": "manage-authorization", - "description": "${role_manage-authorization}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "1d224265-63a8-40ea-9316-47627d0aed8c", - "name": "view-authorization", - "description": "${role_view-authorization}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "535d7ca0-0f06-42d8-938b-e6e7aabffb42", - "name": "query-groups", - "description": "${role_query-groups}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "9ff52ab5-2558-4cb0-901f-6e6f1469d075", - "name": "realm-admin", - "description": "${role_realm-admin}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "manage-authorization", - "view-authorization", - "query-groups", - "view-clients", - "view-realm", - "manage-users", - "query-users", - "impersonation", - "manage-clients", - "view-identity-providers", - "create-client", - "query-realms", - "view-users", - "view-events", - "manage-identity-providers", - "manage-events", - "query-clients", - "manage-realm" - ] - } - }, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "98db35e3-833f-4b61-83af-fc50484fda57", - "name": "view-clients", - "description": "${role_view-clients}", - "composite": true, - "composites": { - "client": { - "realm-management": ["query-clients"] - } - }, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "e0dc0e0c-eba4-4de7-b2eb-2ba095c4c6d4", - "name": "manage-users", - "description": "${role_manage-users}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "69ce3805-1897-4291-842b-b8e8e9f29bd7", - "name": "view-realm", - "description": "${role_view-realm}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "3e803641-96b1-44d8-9de5-7dee83a0a75b", - "name": "impersonation", - "description": "${role_impersonation}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "2c92c3e5-1a0a-4318-9b63-617c5dca0b66", - "name": "query-users", - "description": "${role_query-users}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "326a3718-390d-4e41-af00-2197d3ef6858", - "name": "manage-clients", - "description": "${role_manage-clients}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "e4c69181-5e0d-484e-ac31-be6beef57c28", - "name": "create-client", - "description": "${role_create-client}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "f4ac66cc-97b4-4590-beae-5ff23c9935b3", - "name": "query-realms", - "description": "${role_query-realms}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "a24704fe-13fd-40e6-bf2d-29014f63c069", - "name": "view-identity-providers", - "description": "${role_view-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "7deec87c-2716-40c1-a115-2a0fe840b119", - "name": "view-users", - "description": "${role_view-users}", - "composite": true, - "composites": { - "client": { - "realm-management": ["query-groups", "query-users"] - } - }, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "827c40ae-b4c2-4574-9f34-db33925cd19c", - "name": "view-events", - "description": "${role_view-events}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "cbe05c62-2b07-4ac7-a33a-ffca7c176252", - "name": "manage-events", - "description": "${role_manage-events}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "8ca56814-a817-4849-a515-45399eb1dcc1", - "name": "manage-identity-providers", - "description": "${role_manage-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "1134c6df-d0ff-498d-9dc4-ad989f7cfe93", - "name": "query-clients", - "description": "${role_query-clients}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - }, - { - "id": "3bb14549-60f6-4078-8f4e-47a1162412f2", - "name": "manage-realm", - "description": "${role_manage-realm}", - "composite": false, - "clientRole": true, - "containerId": "4ce68130-aced-4e67-936a-8082dc843cc2", - "attributes": {} - } - ], - "spiffworkflow-frontend": [], - "security-admin-console": [], - "admin-cli": [], - "spiffworkflow-backend": [ - { - "id": "4d71d1bb-d627-43c8-bc07-d542f816e04b", - "name": "spiffworkflow-admin", - "composite": false, - "clientRole": true, - "containerId": "f44558af-3601-4e54-b854-08396a247544", - "attributes": {} - }, - { - "id": "2341ca1c-24c8-4ddf-874c-7153c9408068", - "name": "uma_protection", - "composite": false, - "clientRole": true, - "containerId": "f44558af-3601-4e54-b854-08396a247544", - "attributes": {} - }, - { - "id": "cf88054e-4bdc-491c-bf93-c660cdaad72d", - "name": "repeat-form-role-2", - "composite": false, - "clientRole": true, - "containerId": "f44558af-3601-4e54-b854-08396a247544", - "attributes": { - "repeat-form-role-2-att-key": ["repeat-form-role-2-att-value"] + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "98db35e3-833f-4b61-83af-fc50484fda57", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] } + }, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "e0dc0e0c-eba4-4de7-b2eb-2ba095c4c6d4", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "69ce3805-1897-4291-842b-b8e8e9f29bd7", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "3e803641-96b1-44d8-9de5-7dee83a0a75b", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "2c92c3e5-1a0a-4318-9b63-617c5dca0b66", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "326a3718-390d-4e41-af00-2197d3ef6858", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "e4c69181-5e0d-484e-ac31-be6beef57c28", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "f4ac66cc-97b4-4590-beae-5ff23c9935b3", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "a24704fe-13fd-40e6-bf2d-29014f63c069", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "7deec87c-2716-40c1-a115-2a0fe840b119", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-groups", "query-users" ] + } + }, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "827c40ae-b4c2-4574-9f34-db33925cd19c", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "cbe05c62-2b07-4ac7-a33a-ffca7c176252", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "8ca56814-a817-4849-a515-45399eb1dcc1", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "1134c6df-d0ff-498d-9dc4-ad989f7cfe93", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + }, { + "id" : "3bb14549-60f6-4078-8f4e-47a1162412f2", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "attributes" : { } + } ], + "spiffworkflow-frontend" : [ ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "spiffworkflow-backend" : [ { + "id" : "4d71d1bb-d627-43c8-bc07-d542f816e04b", + "name" : "spiffworkflow-admin", + "composite" : false, + "clientRole" : true, + "containerId" : "f44558af-3601-4e54-b854-08396a247544", + "attributes" : { } + }, { + "id" : "2341ca1c-24c8-4ddf-874c-7153c9408068", + "name" : "uma_protection", + "composite" : false, + "clientRole" : true, + "containerId" : "f44558af-3601-4e54-b854-08396a247544", + "attributes" : { } + }, { + "id" : "cf88054e-4bdc-491c-bf93-c660cdaad72d", + "name" : "repeat-form-role-2", + "composite" : false, + "clientRole" : true, + "containerId" : "f44558af-3601-4e54-b854-08396a247544", + "attributes" : { + "repeat-form-role-2-att-key" : [ "repeat-form-role-2-att-value" ] } - ], - "withAuth": [ - { - "id": "87673823-6a5a-4cb2-baa7-6c8b5da5d402", - "name": "uma_protection", - "composite": false, - "clientRole": true, - "containerId": "5d94a8c3-f56b-4eff-ac39-8580053a7fbe", - "attributes": {} - } - ], - "broker": [ - { - "id": "6d688d72-cf5b-4450-a902-cb2d41f0e04c", - "name": "read-token", - "description": "${role_read-token}", - "composite": false, - "clientRole": true, - "containerId": "55d75754-cf1b-4875-bf3e-15add4be8c99", - "attributes": {} - } - ], - "account": [ - { - "id": "9c51c3e1-028d-4a0d-96dc-6619196b49f0", - "name": "delete-account", - "description": "${role_delete-account}", - "composite": false, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} + } ], + "withAuth" : [ { + "id" : "87673823-6a5a-4cb2-baa7-6c8b5da5d402", + "name" : "uma_protection", + "composite" : false, + "clientRole" : true, + "containerId" : "5d94a8c3-f56b-4eff-ac39-8580053a7fbe", + "attributes" : { } + } ], + "broker" : [ { + "id" : "6d688d72-cf5b-4450-a902-cb2d41f0e04c", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "55d75754-cf1b-4875-bf3e-15add4be8c99", + "attributes" : { } + } ], + "account" : [ { + "id" : "9c51c3e1-028d-4a0d-96dc-6619196b49f0", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "f395d221-7f80-4fcf-90ac-0a89c8b15a9b", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } }, - { - "id": "f395d221-7f80-4fcf-90ac-0a89c8b15a9b", - "name": "manage-consent", - "description": "${role_manage-consent}", - "composite": true, - "composites": { - "client": { - "account": ["view-consent"] - } - }, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "7abb4169-1960-4b4d-b5ae-6ea45cf91ee4", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "4d3c24ed-cc61-4a6e-ac78-47af4545b415", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "a4954091-9be9-4b7c-a196-1af934917ff7", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "0810773c-a57d-449e-a31f-1344e1eb4b9b", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } }, - { - "id": "7abb4169-1960-4b4d-b5ae-6ea45cf91ee4", - "name": "view-consent", - "description": "${role_view-consent}", - "composite": false, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} - }, - { - "id": "4d3c24ed-cc61-4a6e-ac78-47af4545b415", - "name": "manage-account-links", - "description": "${role_manage-account-links}", - "composite": false, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} - }, - { - "id": "a4954091-9be9-4b7c-a196-1af934917ff7", - "name": "view-profile", - "description": "${role_view-profile}", - "composite": false, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} - }, - { - "id": "0810773c-a57d-449e-a31f-1344e1eb4b9b", - "name": "manage-account", - "description": "${role_manage-account}", - "composite": true, - "composites": { - "client": { - "account": ["manage-account-links"] - } - }, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} - }, - { - "id": "ae774a41-a274-4f99-9d7f-f4a0d5dbc085", - "name": "view-applications", - "description": "${role_view-applications}", - "composite": false, - "clientRole": true, - "containerId": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "attributes": {} - } - ] + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "f75e4973-b9b6-4ff0-a691-5f900199b17a", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + }, { + "id" : "ae774a41-a274-4f99-9d7f-f4a0d5dbc085", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "attributes" : { } + } ] } }, - "groups": [], - "defaultRole": { - "id": "c9f0ff93-642d-402b-965a-04d70719886b", - "name": "default-roles-spiffworkflow", - "description": "${role_default-roles}", - "composite": true, - "clientRole": false, - "containerId": "spiffworkflow" + "groups" : [ ], + "defaultRole" : { + "id" : "c9f0ff93-642d-402b-965a-04d70719886b", + "name" : "default-roles-spiffworkflow", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "spiffworkflow" }, - "requiredCredentials": ["password"], - "otpPolicyType": "totp", - "otpPolicyAlgorithm": "HmacSHA1", - "otpPolicyInitialCounter": 0, - "otpPolicyDigits": 6, - "otpPolicyLookAheadWindow": 1, - "otpPolicyPeriod": 30, - "otpSupportedApplications": ["FreeOTP", "Google Authenticator"], - "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": ["ES256"], - "webAuthnPolicyRpId": "", - "webAuthnPolicyAttestationConveyancePreference": "not specified", - "webAuthnPolicyAuthenticatorAttachment": "not specified", - "webAuthnPolicyRequireResidentKey": "not specified", - "webAuthnPolicyUserVerificationRequirement": "not specified", - "webAuthnPolicyCreateTimeout": 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyAcceptableAaguids": [], - "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], - "webAuthnPolicyPasswordlessRpId": "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", - "webAuthnPolicyPasswordlessCreateTimeout": 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "users": [ - { - "id": "4048e9a7-8afa-4e69-9904-389657221abe", - "createdTimestamp": 1665517741516, - "username": "alex", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "81a61a3b-228d-42b3-b39a-f62d8e7f57ca", - "type": "password", - "createdDate": 1665517748308, - "secretData": "{\"value\":\"13OdXlB1S1EqHL+3/0y4LYp/LGCn0UW8/Wh9ykgpUbRrwdX6dY3iiMlKePfTy5nXoH/ISmPlxNKOe5z7FWXsgg==\",\"salt\":\"pv0SEb7Ctk5tpu2y32L2kw==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppFreeOTPName" ], + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "users" : [ { + "id" : "5a97144d-4f59-4a8c-b365-463d0577a740", + "createdTimestamp" : 1669600821350, + "username" : "admin", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "ef435043-ef0c-407a-af5b-ced13182a408", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669600831704, + "secretData" : "{\"value\":\"4D4JRvE7kR5nfGiIdrwzK+0drmy3kX++TlT1BTvYix8N83c9FGTPWvxR1Hl4ggEKuCCAEYZnTzVJZY0DcUcN+A==\",\"salt\":\"yI7UkD+mCuq0H35AnNV/KA==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "4048e9a7-8afa-4e69-9904-389657221abe", + "createdTimestamp" : 1665517741516, + "username" : "alex", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "81a61a3b-228d-42b3-b39a-f62d8e7f57ca", + "type" : "password", + "createdDate" : 1665517748308, + "secretData" : "{\"value\":\"13OdXlB1S1EqHL+3/0y4LYp/LGCn0UW8/Wh9ykgpUbRrwdX6dY3iiMlKePfTy5nXoH/ISmPlxNKOe5z7FWXsgg==\",\"salt\":\"pv0SEb7Ctk5tpu2y32L2kw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "b4dc5a30-4bd7-44fc-88b5-839fbb8567ea", + "createdTimestamp" : 1665518311550, + "username" : "amir", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "e589f3ad-bf7b-4756-89f7-7894c03c2831", + "type" : "password", + "createdDate" : 1665518319210, + "secretData" : "{\"value\":\"mamd7Hi6nV5suylSrUgwWon3Gw3WeOIvAJu9g39Mq1iYoXWj2rI870bGHiSITLaFBpdjLOEmlu9feKkULOXNpQ==\",\"salt\":\"wG7tkMQfPKRW9ymu4ekujQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "4c436296-8471-4105-b551-80eee96b43bb", + "createdTimestamp" : 1657139858075, + "username" : "ciadmin1", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "111b5ea1-c2ab-470a-a16b-2373bc94de7a", + "type" : "password", + "createdDate" : 1657139904275, + "secretData" : "{\"value\":\"e5MjWAk7RPspQIh9gEOKyv3AV/DHNoWk8w1tf+MRLh2oxrKmnnizOj0eFtIadT/q/i5JRfUq5IYBPLL/4nEJDw==\",\"salt\":\"5inqMqqTR6+PBYriy3RPjA==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow", "admin" ], + "clientRoles" : { + "spiffworkflow-backend" : [ "spiffworkflow-admin", "uma_protection" ] }, - { - "id": "b4dc5a30-4bd7-44fc-88b5-839fbb8567ea", - "createdTimestamp": 1665518311550, - "username": "amir", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "e589f3ad-bf7b-4756-89f7-7894c03c2831", - "type": "password", - "createdDate": 1665518319210, - "secretData": "{\"value\":\"mamd7Hi6nV5suylSrUgwWon3Gw3WeOIvAJu9g39Mq1iYoXWj2rI870bGHiSITLaFBpdjLOEmlu9feKkULOXNpQ==\",\"salt\":\"wG7tkMQfPKRW9ymu4ekujQ==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "56457e8f-47c6-4f9f-a72b-473dea5edfeb", + "createdTimestamp" : 1657139955336, + "username" : "ciuser1", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "762f36e9-47af-44da-8520-cf09d752497a", + "type" : "password", + "createdDate" : 1657139966468, + "secretData" : "{\"value\":\"Dpn9QBJSxvl54b0Fu+OKrKRwmDJbk28FQ3xhlOdJPvZVJU/SpdrcsH7ktYAIkVLkRC5qILSZuNPQ3vDGzE2r1Q==\",\"salt\":\"yXd7N8XIQBkJ7swHDeRzXw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "clientRoles" : { + "spiffworkflow-backend" : [ "uma_protection" ] }, - { - "id": "4c436296-8471-4105-b551-80eee96b43bb", - "createdTimestamp": 1657139858075, - "username": "ciadmin1", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "111b5ea1-c2ab-470a-a16b-2373bc94de7a", - "type": "password", - "createdDate": 1657139904275, - "secretData": "{\"value\":\"e5MjWAk7RPspQIh9gEOKyv3AV/DHNoWk8w1tf+MRLh2oxrKmnnizOj0eFtIadT/q/i5JRfUq5IYBPLL/4nEJDw==\",\"salt\":\"5inqMqqTR6+PBYriy3RPjA==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow", "admin"], - "clientRoles": { - "spiffworkflow-backend": ["spiffworkflow-admin", "uma_protection"] - }, - "notBefore": 0, - "groups": [] + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "d58b61cc-a77e-488f-a427-05f4e0572e20", + "createdTimestamp" : 1669132945413, + "username" : "core", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "ee80092b-8ee6-4699-8492-566e088b48f5", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669132955862, + "secretData" : "{\"value\":\"x0f/IvOAsMmbQzgc1LXJ9O7dDepeFURi7lD4Wy0NZBrFRyQ3pMXM6FHNNjhVDeZMsTr2tesYYQ2BK3z9xIPPrA==\",\"salt\":\"vx4/Z41MiUnLqaVt+vMmOQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "99e7e4ea-d4ae-4944-bd31-873dac7b004c", + "createdTimestamp" : 1665517024483, + "username" : "dan", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "d517c520-f500-4542-80e5-7144daef1e32", + "type" : "password", + "createdDate" : 1665517033429, + "secretData" : "{\"value\":\"rgWPI1YobMfDaaT3di2+af3gHU8bkreRElAHgYFA+dXHw0skiGVd1t57kNLEP49M6zKYjZzlOKr0qvAxQF0oSg==\",\"salt\":\"usMZebZnPYXhD6ID95bizg==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "1834a79d-917f-4e4c-ab38-8ec376179fe9", + "createdTimestamp" : 1665517805115, + "username" : "daniel", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "f240495c-265b-42fc-99db-46928580d07d", + "type" : "password", + "createdDate" : 1665517812636, + "secretData" : "{\"value\":\"sRCF3tFOZrUbEW220cVHhQ7e89iKqjgAMyO0BaYCPZZw1tEjZ+drGj+bfwRbuuK0Nps3t//YGVELsejRogWkcw==\",\"salt\":\"XQtLR9oZctkyRTi2Be+Z0g==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "72d32cba-e2e2-489d-9141-4d94e3bb2cda", + "createdTimestamp" : 1665517787787, + "username" : "elizabeth", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "ae951ec8-9fc9-4f1b-b340-bbbe463ae5c2", + "type" : "password", + "createdDate" : 1665517794484, + "secretData" : "{\"value\":\"oudGUsbh8utUavZ8OmoUvggCYxr+RHCgwcqpub5AgbITsK4DgY01X0SlDGRTdNGOIqoHse8zGBNmcyBNPWjC0w==\",\"salt\":\"auHilaAS2Lo7oa0UaA7L6A==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "faf29027-dc54-4804-a408-4989a8c9c243", + "createdTimestamp" : 1669132994561, + "username" : "fin", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "2379940c-98b4-481a-b629-0bd1a4e91acf", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669133003955, + "secretData" : "{\"value\":\"Wb9XtkrxJ9YdW7faHcWgQ+WK3JqBYCQ5wTn9rJa7Uo47I2TrniH+7/CBODIaiF3ipYAEZBkiCJDnPqg2qbZ+aA==\",\"salt\":\"bY1gRb+5sjbmrYWvxfl9CQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "13e009b2-e96f-43b7-a227-465675ece81d", + "createdTimestamp" : 1669303701625, + "username" : "fin1", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "96216746-ff72-454e-8288-232428d10b42", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669303725352, + "secretData" : "{\"value\":\"ukPIO1rlfpzbxb+FXHAwCdNQ4cq3yX+Ke11uFPpGy7xBNT5UgLzO3oIK34Cw1Ma3+gFqK6/OsT4Q5fZd/AsVJQ==\",\"salt\":\"iSIY1gAdz7wkAwnGer95Lw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "9b46f3be-a81d-4b76-92e6-2ac8462f5ec8", + "createdTimestamp" : 1665688255982, + "username" : "finance_user1", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "f14722ec-13a7-4d35-a4ec-0475d405ae58", + "type" : "password", + "createdDate" : 1665688275943, + "secretData" : "{\"value\":\"PlNhf8ShIvaSP3CUwCwAJ2tkqcTCVmCWUy4rbuLSXxEIiuGMu4XeZdsrE82R8PWuDQhlWn/YOUOk38xKZS2ySQ==\",\"salt\":\"m7JGY2cWgFBXMYQSSP2JQQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "087bdc16-e362-4340-aa60-1ff71a45f844", + "createdTimestamp" : 1665516884829, + "username" : "harmeet", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "89c26090-9bd3-46ac-b038-883d02e3f125", + "type" : "password", + "createdDate" : 1665516905862, + "secretData" : "{\"value\":\"vDzTFQhjg8l8XgQ/YFYZSMLxQovFc/wflVBiRtAk/UWRKhJwuz3XInFbQ64wbYppBlXDYSmYis3luKv6YyUWjQ==\",\"salt\":\"58OQLETS0sM9VpXWoNa6rQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "1561518b-c327-491e-9db3-23c2b5394104", + "createdTimestamp" : 1669303773974, + "username" : "j", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "e71ec785-9133-4b7d-8015-1978379af0bb", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669303786522, + "secretData" : "{\"value\":\"g/nsCceqGWoU7thzq21RFSNUB8WP6l9/x2ghKFAKC1Xrqcf2At+u0r8GglqM6WmLthOTtrwICs98tS4ZPLmsbA==\",\"salt\":\"Na/OfJ9itENgaLPsIntzUQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "13f5481e-c6b5-450d-8aaf-e13c1c1f5914", + "createdTimestamp" : 1665518332327, + "username" : "jakub", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "ce141fa5-b8d5-4bbe-93e7-22e7119f97c2", + "type" : "password", + "createdDate" : 1665518338651, + "secretData" : "{\"value\":\"+L4TmIGURzFtyRMFyKbPmQ8iYSC639K0GLNHXM+T/cLiMGxVr/wvWj5j435c1V9P+kwO2CnGtd09IsSN8cXuXg==\",\"salt\":\"a2eNeYyoci5fpkPJJy735g==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "3965a6c8-31df-474f-9a45-c268ed98e3fd", + "createdTimestamp" : 1665518284693, + "username" : "jarrad", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "113e0343-1069-476d-83f9-21d98edb9cfa", + "type" : "password", + "createdDate" : 1665518292234, + "secretData" : "{\"value\":\"1CeBMYC3yiJ/cmIxHs/bSea3kxItLNnaIkPNRk2HefZiCdfUKcJ/QLI0O9QO108G2Lzg9McR33EB72zbFAfYUw==\",\"salt\":\"2kWgItvYvzJkgJU9ICWMAw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "58bcce19-41ec-4ae7-b930-b37be7ad4ba3", + "createdTimestamp" : 1665516949583, + "username" : "jason", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "40abf32e-f0cc-4a17-8231-1a69a02c1b0b", + "type" : "password", + "createdDate" : 1665516957192, + "secretData" : "{\"value\":\"nCnRYH5rLRMu1E7C260SowAdvJfQCSdf4LigcIzSkoPwT+qfLT5ut5m99zakNLeHLoCtGhO2lSVGUQWhdCUYJw==\",\"salt\":\"mW5QN/RSr55I04VI6FTERA==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "29c11638-3b32-4024-8594-91c8b09e713c", + "createdTimestamp" : 1665518366585, + "username" : "jon", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "8b520e01-5b9b-44ab-9ee8-505bd0831a45", + "type" : "password", + "createdDate" : 1665518373016, + "secretData" : "{\"value\":\"lZBDnz49zW6EkT2t7JSQjOzBlYhjhkw3hHefcOC4tmet+h/dAuxSGRuLibJHBap2j6G9Z2SoRqtyS8bwGbR42g==\",\"salt\":\"MI90jmxbLAno0g5O4BCeHw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "af15c167-d0e7-4a41-ac2c-109188dd7166", + "createdTimestamp" : 1665516966482, + "username" : "kb", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "2c0be363-038f-48f1-86d6-91fdd28657cf", + "type" : "password", + "createdDate" : 1665516982394, + "secretData" : "{\"value\":\"yvliX8Mn+lgpxfMpkjfsV8CASgghEgPA2P1/DR1GP5LSFoGwGCEwj0SmeQAo+MQjBsn3nfvtL9asQvmIYdNZwQ==\",\"salt\":\"kFr1K94QCEx9eGD25rZR9g==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "23c464ea-6a98-462c-a8b9-e8e561804361", + "createdTimestamp" : 1669132970114, + "username" : "lead", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "96e836a4-1a84-45c5-a9ed-651b0c90195e", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669132979516, + "secretData" : "{\"value\":\"DsOkyXBHcwY0HAGta+m+E5jXDZwxGl/fgROCR7ph23oJ3j9833UVH5VLHfYcZ3YZixUIfskYMlcwW91uqO0oxQ==\",\"salt\":\"zOLZMvNnOIEB0t32DghWiQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "fef2c863-be05-49f2-94d0-702238505a4d", + "createdTimestamp" : 1669303745591, + "username" : "lead1", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "firstName" : "", + "lastName" : "", + "credentials" : [ { + "id" : "4e17388b-6c44-44e1-b20a-a873c0feb9a8", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1669303762736, + "secretData" : "{\"value\":\"NNPFZcVk47adUPH1q3L27uPkULy9OocZkOzi4qUVvO+tvZJVH5sMrSUYqM8S71AqdHNZD1a8ge6amF6k6dDIkQ==\",\"salt\":\"7e48fZJBAeVferVYA4gNVw==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "6f5bfa09-7494-4a2f-b871-cf327048cac7", + "createdTimestamp" : 1665517010600, + "username" : "manuchehr", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "07dabf55-b5d3-4f98-abba-3334086ecf5e", + "type" : "password", + "createdDate" : 1665517017682, + "secretData" : "{\"value\":\"1btDXHraz9l0Gp4g1xxdcuZffLsuKsW0tHwQGzoEtTlI/iZdrKPG9WFlCEFd84qtpdYPJD/tvzn6ZK6zU4/GlQ==\",\"salt\":\"jHtMiO+4jMv9GqLhC9wg4w==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "d1c46b47-67c4-4d07-9cf4-6b1ceac88fc1", + "createdTimestamp" : 1665517760255, + "username" : "mike", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "1ed375fb-0f1a-4c2a-9243-2477242cf7bd", + "type" : "password", + "createdDate" : 1665517768715, + "secretData" : "{\"value\":\"S1cxZ3dgNB+A6yfMchDWEGP8OyZaaAOU/IUKn+QWFt255yoFqs28pfmwCsevdzuh0YfygO9GBgBv7qZQ2pknNQ==\",\"salt\":\"i+Q9zEHNxfi8TAHw17Dv6w==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "cecacfd3-2f59-4ce2-87d9-bea91ef13c5b", + "createdTimestamp" : 1666102618518, + "username" : "natalia", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "b6aa9936-39cc-4931-bfeb-60e6753de5ba", + "type" : "password", + "createdDate" : 1666102626704, + "secretData" : "{\"value\":\"kGyQIqZM6n9rjGZkNScJbkFjLvRJ2I+ZzCtjQ80e+zX7QaXtIF3CEeSY6KTXVjE8Z74oyVBWTIibpiTblm5Ztw==\",\"salt\":\"0k+Y+QJiW0YhxuxxYigasg==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "f3852a7d-8adf-494f-b39d-96ad4c899ee5", + "createdTimestamp" : 1665516926300, + "username" : "sasha", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "4a170af4-6f0c-4e7b-b70c-e674edf619df", + "type" : "password", + "createdDate" : 1665516934662, + "secretData" : "{\"value\":\"/cimS+PL6p+YnOCF9ZSA6UuwmmLZ7aVUZUthiFDqp/sn0c8GTpWmAdDIbJy2Ut+D4Rx605kRFQaekzRgSYPxcg==\",\"salt\":\"0dmUnLfqK745YHVSz6HOZg==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "487d3a85-89dd-4839-957a-c3f6d70551f6", + "createdTimestamp" : 1657115173081, + "username" : "service-account-spiffworkflow-backend", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "serviceAccountClientId" : "spiffworkflow-backend", + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "clientRoles" : { + "spiffworkflow-backend" : [ "uma_protection" ] }, - { - "id": "56457e8f-47c6-4f9f-a72b-473dea5edfeb", - "createdTimestamp": 1657139955336, - "username": "ciuser1", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "762f36e9-47af-44da-8520-cf09d752497a", - "type": "password", - "createdDate": 1657139966468, - "secretData": "{\"value\":\"Dpn9QBJSxvl54b0Fu+OKrKRwmDJbk28FQ3xhlOdJPvZVJU/SpdrcsH7ktYAIkVLkRC5qILSZuNPQ3vDGzE2r1Q==\",\"salt\":\"yXd7N8XIQBkJ7swHDeRzXw==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "clientRoles": { - "spiffworkflow-backend": ["uma_protection"] - }, - "notBefore": 0, - "groups": [] + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "22de68b1-4b06-4bc2-8da6-0c577e7e62ad", + "createdTimestamp" : 1657055472800, + "username" : "service-account-withauth", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "serviceAccountClientId" : "withAuth", + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-spiffworkflow" ], + "clientRoles" : { + "withAuth" : [ "uma_protection" ] }, - { - "id": "99e7e4ea-d4ae-4944-bd31-873dac7b004c", - "createdTimestamp": 1665517024483, - "username": "dan", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "d517c520-f500-4542-80e5-7144daef1e32", - "type": "password", - "createdDate": 1665517033429, - "secretData": "{\"value\":\"rgWPI1YobMfDaaT3di2+af3gHU8bkreRElAHgYFA+dXHw0skiGVd1t57kNLEP49M6zKYjZzlOKr0qvAxQF0oSg==\",\"salt\":\"usMZebZnPYXhD6ID95bizg==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "notBefore" : 0, + "groups" : [ ] + } ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clients" : [ { + "id" : "e39b3c85-bb9d-4c73-8250-be087c82ae48", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/spiffworkflow/account/", + "surrogateAuthRequired" : false, + "enabled" : false, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/spiffworkflow/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "false", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" }, - { - "id": "1834a79d-917f-4e4c-ab38-8ec376179fe9", - "createdTimestamp": 1665517805115, - "username": "daniel", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "f240495c-265b-42fc-99db-46928580d07d", - "type": "password", - "createdDate": 1665517812636, - "secretData": "{\"value\":\"sRCF3tFOZrUbEW220cVHhQ7e89iKqjgAMyO0BaYCPZZw1tEjZ+drGj+bfwRbuuK0Nps3t//YGVELsejRogWkcw==\",\"salt\":\"XQtLR9oZctkyRTi2Be+Z0g==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "02fa6179-9399-4bb1-970f-c4d8e8b5f99f", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : false, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "false", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" }, - { - "id": "72d32cba-e2e2-489d-9141-4d94e3bb2cda", - "createdTimestamp": 1665517787787, - "username": "elizabeth", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "ae951ec8-9fc9-4f1b-b340-bbbe463ae5c2", - "type": "password", - "createdDate": 1665517794484, - "secretData": "{\"value\":\"oudGUsbh8utUavZ8OmoUvggCYxr+RHCgwcqpub5AgbITsK4DgY01X0SlDGRTdNGOIqoHse8zGBNmcyBNPWjC0w==\",\"salt\":\"auHilaAS2Lo7oa0UaA7L6A==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "55d75754-cf1b-4875-bf3e-15add4be8c99", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : false, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "false", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" }, - { - "id": "9b46f3be-a81d-4b76-92e6-2ac8462f5ec8", - "createdTimestamp": 1665688255982, - "username": "finance_user1", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "f14722ec-13a7-4d35-a4ec-0475d405ae58", - "type": "password", - "createdDate": 1665688275943, - "secretData": "{\"value\":\"PlNhf8ShIvaSP3CUwCwAJ2tkqcTCVmCWUy4rbuLSXxEIiuGMu4XeZdsrE82R8PWuDQhlWn/YOUOk38xKZS2ySQ==\",\"salt\":\"m7JGY2cWgFBXMYQSSP2JQQ==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "4ce68130-aced-4e67-936a-8082dc843cc2", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : false, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "false", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" }, - { - "id": "087bdc16-e362-4340-aa60-1ff71a45f844", - "createdTimestamp": 1665516884829, - "username": "harmeet", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "89c26090-9bd3-46ac-b038-883d02e3f125", - "type": "password", - "createdDate": 1665516905862, - "secretData": "{\"value\":\"vDzTFQhjg8l8XgQ/YFYZSMLxQovFc/wflVBiRtAk/UWRKhJwuz3XInFbQ64wbYppBlXDYSmYis3luKv6YyUWjQ==\",\"salt\":\"58OQLETS0sM9VpXWoNa6rQ==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "7c82344d-d4ae-4599-bbce-583cc8848199", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/spiffworkflow/console/", + "surrogateAuthRequired" : false, + "enabled" : false, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/spiffworkflow/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "false", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "pkce.code.challenge.method" : "S256", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" }, - { - "id": "13f5481e-c6b5-450d-8aaf-e13c1c1f5914", - "createdTimestamp": 1665518332327, - "username": "jakub", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "ce141fa5-b8d5-4bbe-93e7-22e7119f97c2", - "type": "password", - "createdDate": 1665518338651, - "secretData": "{\"value\":\"+L4TmIGURzFtyRMFyKbPmQ8iYSC639K0GLNHXM+T/cLiMGxVr/wvWj5j435c1V9P+kwO2CnGtd09IsSN8cXuXg==\",\"salt\":\"a2eNeYyoci5fpkPJJy735g==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "3965a6c8-31df-474f-9a45-c268ed98e3fd", - "createdTimestamp": 1665518284693, - "username": "jarrad", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "113e0343-1069-476d-83f9-21d98edb9cfa", - "type": "password", - "createdDate": 1665518292234, - "secretData": "{\"value\":\"1CeBMYC3yiJ/cmIxHs/bSea3kxItLNnaIkPNRk2HefZiCdfUKcJ/QLI0O9QO108G2Lzg9McR33EB72zbFAfYUw==\",\"salt\":\"2kWgItvYvzJkgJU9ICWMAw==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "58bcce19-41ec-4ae7-b930-b37be7ad4ba3", - "createdTimestamp": 1665516949583, - "username": "jason", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "40abf32e-f0cc-4a17-8231-1a69a02c1b0b", - "type": "password", - "createdDate": 1665516957192, - "secretData": "{\"value\":\"nCnRYH5rLRMu1E7C260SowAdvJfQCSdf4LigcIzSkoPwT+qfLT5ut5m99zakNLeHLoCtGhO2lSVGUQWhdCUYJw==\",\"salt\":\"mW5QN/RSr55I04VI6FTERA==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "29c11638-3b32-4024-8594-91c8b09e713c", - "createdTimestamp": 1665518366585, - "username": "jon", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "8b520e01-5b9b-44ab-9ee8-505bd0831a45", - "type": "password", - "createdDate": 1665518373016, - "secretData": "{\"value\":\"lZBDnz49zW6EkT2t7JSQjOzBlYhjhkw3hHefcOC4tmet+h/dAuxSGRuLibJHBap2j6G9Z2SoRqtyS8bwGbR42g==\",\"salt\":\"MI90jmxbLAno0g5O4BCeHw==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "af15c167-d0e7-4a41-ac2c-109188dd7166", - "createdTimestamp": 1665516966482, - "username": "kb", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "2c0be363-038f-48f1-86d6-91fdd28657cf", - "type": "password", - "createdDate": 1665516982394, - "secretData": "{\"value\":\"yvliX8Mn+lgpxfMpkjfsV8CASgghEgPA2P1/DR1GP5LSFoGwGCEwj0SmeQAo+MQjBsn3nfvtL9asQvmIYdNZwQ==\",\"salt\":\"kFr1K94QCEx9eGD25rZR9g==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "6f5bfa09-7494-4a2f-b871-cf327048cac7", - "createdTimestamp": 1665517010600, - "username": "manuchehr", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "07dabf55-b5d3-4f98-abba-3334086ecf5e", - "type": "password", - "createdDate": 1665517017682, - "secretData": "{\"value\":\"1btDXHraz9l0Gp4g1xxdcuZffLsuKsW0tHwQGzoEtTlI/iZdrKPG9WFlCEFd84qtpdYPJD/tvzn6ZK6zU4/GlQ==\",\"salt\":\"jHtMiO+4jMv9GqLhC9wg4w==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "d1c46b47-67c4-4d07-9cf4-6b1ceac88fc1", - "createdTimestamp": 1665517760255, - "username": "mike", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "1ed375fb-0f1a-4c2a-9243-2477242cf7bd", - "type": "password", - "createdDate": 1665517768715, - "secretData": "{\"value\":\"S1cxZ3dgNB+A6yfMchDWEGP8OyZaaAOU/IUKn+QWFt255yoFqs28pfmwCsevdzuh0YfygO9GBgBv7qZQ2pknNQ==\",\"salt\":\"i+Q9zEHNxfi8TAHw17Dv6w==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "cecacfd3-2f59-4ce2-87d9-bea91ef13c5b", - "createdTimestamp": 1666102618518, - "username": "natalia", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "b6aa9936-39cc-4931-bfeb-60e6753de5ba", - "type": "password", - "createdDate": 1666102626704, - "secretData": "{\"value\":\"kGyQIqZM6n9rjGZkNScJbkFjLvRJ2I+ZzCtjQ80e+zX7QaXtIF3CEeSY6KTXVjE8Z74oyVBWTIibpiTblm5Ztw==\",\"salt\":\"0k+Y+QJiW0YhxuxxYigasg==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "f3852a7d-8adf-494f-b39d-96ad4c899ee5", - "createdTimestamp": 1665516926300, - "username": "sasha", - "enabled": true, - "totp": false, - "emailVerified": false, - "credentials": [ - { - "id": "4a170af4-6f0c-4e7b-b70c-e674edf619df", - "type": "password", - "createdDate": 1665516934662, - "secretData": "{\"value\":\"/cimS+PL6p+YnOCF9ZSA6UuwmmLZ7aVUZUthiFDqp/sn0c8GTpWmAdDIbJy2Ut+D4Rx605kRFQaekzRgSYPxcg==\",\"salt\":\"0dmUnLfqK745YHVSz6HOZg==\",\"additionalParameters\":{}}", - "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" - } - ], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "notBefore": 0, - "groups": [] - }, - { - "id": "487d3a85-89dd-4839-957a-c3f6d70551f6", - "createdTimestamp": 1657115173081, - "username": "service-account-spiffworkflow-backend", - "enabled": true, - "totp": false, - "emailVerified": false, - "serviceAccountClientId": "spiffworkflow-backend", - "credentials": [], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "clientRoles": { - "spiffworkflow-backend": ["uma_protection"] - }, - "notBefore": 0, - "groups": [] - }, - { - "id": "22de68b1-4b06-4bc2-8da6-0c577e7e62ad", - "createdTimestamp": 1657055472800, - "username": "service-account-withauth", - "enabled": true, - "totp": false, - "emailVerified": false, - "serviceAccountClientId": "withAuth", - "credentials": [], - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["default-roles-spiffworkflow"], - "clientRoles": { - "withAuth": ["uma_protection"] - }, - "notBefore": 0, - "groups": [] - } - ], - "scopeMappings": [ - { - "clientScope": "offline_access", - "roles": ["offline_access"] - } - ], - "clients": [ - { - "id": "e39b3c85-bb9d-4c73-8250-be087c82ae48", - "clientId": "account", - "name": "${client_account}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/spiffworkflow/account/", - "surrogateAuthRequired": false, - "enabled": false, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": ["/realms/spiffworkflow/account/*"], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "false", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "02fa6179-9399-4bb1-970f-c4d8e8b5f99f", - "clientId": "admin-cli", - "name": "${client_admin-cli}", - "surrogateAuthRequired": false, - "enabled": false, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "false", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "55d75754-cf1b-4875-bf3e-15add4be8c99", - "clientId": "broker", - "name": "${client_broker}", - "surrogateAuthRequired": false, - "enabled": false, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "false", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "4ce68130-aced-4e67-936a-8082dc843cc2", - "clientId": "realm-management", - "name": "${client_realm-management}", - "surrogateAuthRequired": false, - "enabled": false, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "false", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "7c82344d-d4ae-4599-bbce-583cc8848199", - "clientId": "security-admin-console", - "name": "${client_security-admin-console}", - "rootUrl": "${authAdminUrl}", - "baseUrl": "/admin/spiffworkflow/console/", - "surrogateAuthRequired": false, - "enabled": false, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": ["/admin/spiffworkflow/console/*"], - "webOrigins": ["+"], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "false", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "pkce.code.challenge.method": "S256", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "949c8afa-a06e-4a86-9260-6f477fc9ad9d", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "f44558af-3601-4e54-b854-08396a247544", - "clientId": "spiffworkflow-backend", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q", - "redirectUris": [ - "http://localhost:7000/*", - "http://67.205.133.116:7000/*", - "http://167.172.242.138:7000/*", - "https://api.{{SPIFF_SUBDOMAIN}}.spiffworkflow.org/*", - "https://api.demo.spiffworkflow.org/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "client.secret.creation.time": "1657115173", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "af3598ab-74a9-48ba-956f-431b14acd896", - "name": "Client IP Address", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientAddress", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientAddress", - "jsonType.label": "String" - } - }, - { - "id": "87369cf7-2a77-40fd-a926-a26d689831a0", - "name": "Client Host", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientHost", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientHost", - "jsonType.label": "String" - } - }, - { - "id": "2c78d7e8-0a99-43bd-bc29-0ba062ed8750", - "name": "Client ID", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientId", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientId", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ], - "authorizationSettings": { - "allowRemoteResourceManagement": true, - "policyEnforcementMode": "ENFORCING", - "resources": [ - { - "name": "everything", - "ownerManagedAccess": false, - "attributes": {}, - "_id": "446bdcf4-a3bd-41c7-a0f8-67a225ba6b57", - "uris": ["/*"], - "scopes": [ - { - "name": "read" - }, - { - "name": "update" - }, - { - "name": "delete" - }, - { - "name": "instantiate" - } - ] - }, - { - "name": "Default Resource", - "type": "urn:spiffworkflow-backend:resources:default", - "ownerManagedAccess": false, - "attributes": {}, - "_id": "8e00e4a3-3fff-4521-b7f0-95f66c2f79d2", - "uris": ["/*"] - }, - { - "name": "process-model-with-repeating-form-crud", - "type": "process-model", - "ownerManagedAccess": false, - "displayName": "process-model-with-repeating-form-crud", - "attributes": { - "test_resource_att1": ["this_is_the_value"] - }, - "_id": "e294304c-796e-4c56-bdf2-8c854f65db59", - "uris": [ - "/process-models/category_number_one/process-model-with-repeating-form" - ], - "scopes": [ - { - "name": "read" - }, - { - "name": "update" - }, - { - "name": "delete" - }, - { - "name": "instantiate" - } - ] - } - ], - "policies": [ - { - "id": "048d043e-d98c-44d8-8c85-656ba117053e", - "name": "repeat-form-role-policy", - "type": "role", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "roles": "[{\"id\":\"spiffworkflow-backend/repeat-form-role-2\",\"required\":false}]" - } - }, - { - "id": "ac55237b-6ec9-4f66-bb8e-bee94a5bb5e9", - "name": "admins have everything", - "type": "role", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "roles": "[{\"id\":\"spiffworkflow-backend/spiffworkflow-admin\",\"required\":false}]" - } - }, - { - "id": "7dac9bea-d415-4bc4-8817-7a71c2b3ce32", - "name": "Default Policy", - "description": "A policy that grants access only for users within this realm", - "type": "role", - "logic": "POSITIVE", - "decisionStrategy": "AFFIRMATIVE", - "config": { - "roles": "[{\"id\":\"spiffworkflow-backend/repeat-form-role-2\",\"required\":false}]" - } - }, - { - "id": "5133ae0b-5e90-48a6-bdd9-3f323e10c44d", - "name": "repeat-form-read", - "type": "scope", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "resources": "[\"process-model-with-repeating-form-crud\"]", - "scopes": "[\"read\"]", - "applyPolicies": "[\"repeat-form-role-policy\"]" - } - }, - { - "id": "0a86ae38-7460-4bc2-b1f9-f933531303ac", - "name": "all_permissions", - "type": "resource", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "resources": "[\"everything\"]", - "applyPolicies": "[\"admins have everything\"]" - } - }, - { - "id": "4b634627-51d9-4257-91d9-29503490e4fb", - "name": "Default Permission", - "description": "A permission that applies to the default resource type", - "type": "resource", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "defaultResourceType": "urn:spiffworkflow-backend:resources:default", - "applyPolicies": "[\"Default Policy\"]" - } - } - ], - "scopes": [ - { - "id": "c03b5c4e-f1bb-4066-8666-3c8a6f44ddb3", - "name": "read", - "displayName": "read" - }, - { - "id": "f55c3e81-9257-4618-9acb-32c57fc561a6", - "name": "update", - "displayName": "update" - }, - { - "id": "c8628417-7ffa-4675-9cda-955df62ea1db", - "name": "delete", - "displayName": "delete" - }, - { - "id": "50ef4129-aa88-4ecd-9afe-c7e5a1b66142", - "name": "instantiate", - "displayName": "instantiate" - } - ], - "decisionStrategy": "UNANIMOUS" + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "949c8afa-a06e-4a86-9260-6f477fc9ad9d", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "f44558af-3601-4e54-b854-08396a247544", + "clientId" : "spiffworkflow-backend", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "JXeQExm0JhQPLumgHtIIqf52bDalHz0q", + "redirectUris" : [ "http://localhost:7000/*", "https://api.unused-for-local-dev.spiffworkflow.org/*", "http://67.205.133.116:7000/*", "http://167.172.242.138:7000/*", "https://api.demo.spiffworkflow.org/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : true, + "authorizationServicesEnabled" : true, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "true", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "client.secret.creation.time" : "1657115173", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" }, - { - "id": "9f340eba-2b84-43d0-a976-010e270e3981", - "clientId": "spiffworkflow-frontend", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "http://localhost:7001/*", - "http://67.205.133.116:7000/*", - "http://167.172.242.138:7001/*", - "https://api.{{SPIFF_SUBDOMAIN}}.spiffworkflow.org/*", - "https://api.demo.spiffworkflow.org/*" - ], - "webOrigins": ["*"], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "5d94a8c3-f56b-4eff-ac39-8580053a7fbe", - "clientId": "withAuth", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "6o8kIKQznQtejHOdRhWeKorBJclMGcgA", - "redirectUris": [ - "http://localhost:7001/*", - "http://67.205.133.116:7000/*", - "http://167.172.242.138:7001/*", - "https://api.{{SPIFF_SUBDOMAIN}}.spiffworkflow.org/*", - "https://api.demo.spiffworkflow.org/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "saml.force.post.binding": "false", - "saml.multivalued.roles": "false", - "frontchannel.logout.session.required": "false", - "post.logout.redirect.uris": "+", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false", - "saml.server.signature.keyinfo.ext": "false", - "use.refresh.tokens": "true", - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "client_credentials.use_refresh_token": "false", - "require.pushed.authorization.requests": "false", - "saml.client.signature": "false", - "saml.allow.ecp.flow": "false", - "id.token.as.detached.signature": "false", - "saml.assertion.signature": "false", - "client.secret.creation.time": "1657055472", - "saml.encrypt": "false", - "saml.server.signature": "false", - "exclude.session.state.from.auth.response": "false", - "saml.artifact.binding": "false", - "saml_force_name_id_format": "false", - "acr.loa.map": "{}", - "tls.client.certificate.bound.access.tokens": "false", - "saml.authnstatement": "false", - "display.on.consent.screen": "false", - "token.response.type.bearer.lower-case": "false", - "saml.onetimeuse.condition": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "abfc756f-fc57-45b4-8a40-0cd0f8081f0c", - "name": "Client ID", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientId", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientId", - "jsonType.label": "String" - } - }, - { - "id": "c05d38b7-9b4d-4286-b40c-f48b3cca42e3", - "name": "Client Host", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientHost", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientHost", - "jsonType.label": "String" - } - }, - { - "id": "b27d0bd8-b8d9-43cb-a07a-3ec4bdc818dc", - "name": "Client IP Address", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientAddress", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientAddress", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ], - "authorizationSettings": { - "allowRemoteResourceManagement": true, - "policyEnforcementMode": "ENFORCING", - "resources": [ - { - "name": "Default Resource", - "type": "urn:withAuth:resources:default", - "ownerManagedAccess": false, - "attributes": {}, - "_id": "c882ad40-c15d-4f88-ad60-c2ea2f486ce2", - "uris": ["/*"] - } - ], - "policies": [ - { - "id": "b8b338bc-884d-43cf-96d8-3776f2b220f3", - "name": "Default Policy", - "description": "A policy that grants access only for users within this realm", - "type": "role", - "logic": "POSITIVE", - "decisionStrategy": "AFFIRMATIVE", - "config": { - "roles": "[{\"id\":\"spiffworkflow-backend/repeat-form-role-2\",\"required\":false}]" - } - }, - { - "id": "4f5afa22-0fdf-4ed7-97b9-35400591bf6f", - "name": "Default Permission", - "description": "A permission that applies to the default resource type", - "type": "resource", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "defaultResourceType": "urn:withAuth:resources:default", - "applyPolicies": "[\"Default Policy\"]" - } - } - ], - "scopes": [], - "decisionStrategy": "UNANIMOUS" + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "af3598ab-74a9-48ba-956f-431b14acd896", + "name" : "Client IP Address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientAddress", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientAddress", + "jsonType.label" : "String" } - } - ], - "clientScopes": [ - { - "id": "fa3d9944-cf66-4af9-b931-1f3b02943e5b", - "name": "acr", - "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "12ad0a69-d414-4b5b-9f5f-b647db5f8959", - "name": "acr loa level", - "protocol": "openid-connect", - "protocolMapper": "oidc-acr-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - } - ] - }, - { - "id": "4e69d058-1229-4704-9411-decf25da0a49", - "name": "profile", - "description": "OpenID Connect built-in scope: profile", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "d0d7334e-3f11-45d2-9670-46dbc1977cb2", - "name": "full name", - "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "4efcf169-4df2-4cdb-b331-005aff1cee28", - "name": "website", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "website", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" - } - }, - { - "id": "3f639f2f-cf0e-4651-ab93-15a77023b5a0", - "name": "given name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "firstName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "given_name", - "jsonType.label": "String" - } - }, - { - "id": "16e93663-bf6a-4f6d-b5ab-8e68bf118f72", - "name": "nickname", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "nickname", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "nickname", - "jsonType.label": "String" - } - }, - { - "id": "b9c97283-8153-4c4d-b8d8-dd1bde17823b", - "name": "username", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "preferred_username", - "jsonType.label": "String" - } - }, - { - "id": "eeead6c7-1dae-4be1-9eca-988ffb38aaf4", - "name": "zoneinfo", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "zoneinfo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "zoneinfo", - "jsonType.label": "String" - } - }, - { - "id": "d62991bc-2583-42be-bb08-8d1527c4f162", - "name": "family name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "lastName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "family_name", - "jsonType.label": "String" - } - }, - { - "id": "9f761222-f84d-4a25-a53f-13e196d38a46", - "name": "profile", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" - } - }, - { - "id": "ec866e3c-582f-4c99-920f-d57cf03d772d", - "name": "gender", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" - } - }, - { - "id": "b05e679c-e00e-427e-8e47-0a4fd411c7a6", - "name": "updated at", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "updatedAt", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "updated_at", - "jsonType.label": "long" - } - }, - { - "id": "505ff402-5533-48ea-91f9-ab4804c3826b", - "name": "middle name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "middleName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "middle_name", - "jsonType.label": "String" - } - }, - { - "id": "d546af31-b669-442b-9a9d-8a6478364002", - "name": "picture", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "picture", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "picture", - "jsonType.label": "String" - } - }, - { - "id": "5a75c993-290f-4bfb-9044-5d7d269378b2", - "name": "birthdate", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "birthdate", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" - } - }, - { - "id": "2d387240-0f2f-4f30-8464-0e7c57946743", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "2efee39d-723c-44af-9eb1-4dde9635b249", - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "5bf7db0f-a915-43c2-bff4-475ee5c3259b", - "name": "email", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "email", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email", - "jsonType.label": "String" - } - }, - { - "id": "687a8c7d-c93f-47d9-a176-78b0954429c7", - "name": "email verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "emailVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "4a7737cf-83e3-40e1-b36d-9566b34e4148", - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "14bd2816-a2f3-4fde-9ac2-452dea2e9e58", - "name": "phone number", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number", - "jsonType.label": "String" - } - }, - { - "id": "6172e315-8999-4df8-89fa-75ffd1981793", - "name": "phone number verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "5ad0c621-d3ec-4018-98c8-d6fb630d661f", - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "252fdd9f-cc91-4ca3-aaab-cdf053360e94", - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "user.attribute": "foo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" - } - }, - { - "id": "8e9b880e-6dd8-4e2f-ade2-77fc8fd0bc6d", - "name": "upn", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "upn", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "77ca4f26-3777-451b-a907-e258f46f7b95", - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "e7ebb9c0-5ed3-4c6f-bb69-22e01d26b49f", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - }, - { - "id": "66fd470f-419e-44cd-822e-43df8ee5fe1b", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "id": "f3c313bc-7da7-4cf6-a0df-b62e77209b7c", - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String", - "multivalued": "true" - } - } - ] - }, - { - "id": "3e9849f5-15ff-43c6-b929-40f26fda2c05", - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" + }, { + "id" : "87369cf7-2a77-40fd-a926-a26d689831a0", + "name" : "Client Host", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientHost", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientHost", + "jsonType.label" : "String" } - }, - { - "id": "ffda6ea6-8add-4c7e-9754-66d00c6735a1", - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "05635d42-8bb3-440b-b871-b64c97f524da", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": {} + }, { + "id" : "2c78d7e8-0a99-43bd-bc29-0ba062ed8750", + "name" : "Client ID", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientId", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientId", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], + "authorizationSettings" : { + "allowRemoteResourceManagement" : true, + "policyEnforcementMode" : "ENFORCING", + "resources" : [ { + "name" : "everything", + "ownerManagedAccess" : false, + "attributes" : { }, + "_id" : "446bdcf4-a3bd-41c7-a0f8-67a225ba6b57", + "uris" : [ "/*" ], + "scopes" : [ { + "name" : "read" + }, { + "name" : "update" + }, { + "name" : "delete" + }, { + "name" : "instantiate" + } ] + }, { + "name" : "Default Resource", + "type" : "urn:spiffworkflow-backend:resources:default", + "ownerManagedAccess" : false, + "attributes" : { }, + "_id" : "8e00e4a3-3fff-4521-b7f0-95f66c2f79d2", + "uris" : [ "/*" ] + }, { + "name" : "process-model-with-repeating-form-crud", + "type" : "process-model", + "ownerManagedAccess" : false, + "displayName" : "process-model-with-repeating-form-crud", + "attributes" : { + "test_resource_att1" : [ "this_is_the_value" ] + }, + "_id" : "e294304c-796e-4c56-bdf2-8c854f65db59", + "uris" : [ "/process-models/category_number_one/process-model-with-repeating-form" ], + "scopes" : [ { + "name" : "read" + }, { + "name" : "update" + }, { + "name" : "delete" + }, { + "name" : "instantiate" + } ] + } ], + "policies" : [ { + "id" : "048d043e-d98c-44d8-8c85-656ba117053e", + "name" : "repeat-form-role-policy", + "type" : "role", + "logic" : "POSITIVE", + "decisionStrategy" : "UNANIMOUS", + "config" : { + "roles" : "[{\"id\":\"spiffworkflow-backend/repeat-form-role-2\",\"required\":false}]" } - ] - }, - { - "id": "6f56ae2b-253f-40f7-ba99-e8c5bbc71423", - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", - "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "id": "7036c17a-9306-4481-82a1-d8d9d77077e5", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" - } + }, { + "id" : "ac55237b-6ec9-4f66-bb8e-bee94a5bb5e9", + "name" : "admins have everything", + "type" : "role", + "logic" : "POSITIVE", + "decisionStrategy" : "UNANIMOUS", + "config" : { + "roles" : "[{\"id\":\"spiffworkflow-backend/spiffworkflow-admin\",\"required\":false}]" } - ] - }, - { - "id": "ce4493c0-ccb4-45f9-a46e-a40cc3f6d4b2", - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "8a0d3248-d231-40b2-9b8e-3d63bd5a5d12", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } + }, { + "id" : "7dac9bea-d415-4bc4-8817-7a71c2b3ce32", + "name" : "Default Policy", + "description" : "A policy that grants access only for users within this realm", + "type" : "role", + "logic" : "POSITIVE", + "decisionStrategy" : "AFFIRMATIVE", + "config" : { + "roles" : "[{\"id\":\"spiffworkflow-backend/repeat-form-role-2\",\"required\":false}]" } - ] + }, { + "id" : "5133ae0b-5e90-48a6-bdd9-3f323e10c44d", + "name" : "repeat-form-read", + "type" : "scope", + "logic" : "POSITIVE", + "decisionStrategy" : "UNANIMOUS", + "config" : { + "resources" : "[\"process-model-with-repeating-form-crud\"]", + "scopes" : "[\"read\"]", + "applyPolicies" : "[\"repeat-form-role-policy\"]" + } + }, { + "id" : "0a86ae38-7460-4bc2-b1f9-f933531303ac", + "name" : "all_permissions", + "type" : "resource", + "logic" : "POSITIVE", + "decisionStrategy" : "UNANIMOUS", + "config" : { + "resources" : "[\"everything\"]", + "applyPolicies" : "[\"admins have everything\"]" + } + }, { + "id" : "4b634627-51d9-4257-91d9-29503490e4fb", + "name" : "Default Permission", + "description" : "A permission that applies to the default resource type", + "type" : "resource", + "logic" : "POSITIVE", + "decisionStrategy" : "UNANIMOUS", + "config" : { + "defaultResourceType" : "urn:spiffworkflow-backend:resources:default", + "applyPolicies" : "[\"Default Policy\"]" + } + } ], + "scopes" : [ { + "id" : "c03b5c4e-f1bb-4066-8666-3c8a6f44ddb3", + "name" : "read", + "displayName" : "read" + }, { + "id" : "f55c3e81-9257-4618-9acb-32c57fc561a6", + "name" : "update", + "displayName" : "update" + }, { + "id" : "c8628417-7ffa-4675-9cda-955df62ea1db", + "name" : "delete", + "displayName" : "delete" + }, { + "id" : "50ef4129-aa88-4ecd-9afe-c7e5a1b66142", + "name" : "instantiate", + "displayName" : "instantiate" + } ], + "decisionStrategy" : "UNANIMOUS" } - ], - "defaultDefaultClientScopes": [ - "email", - "profile", - "role_list", - "roles", - "acr", - "web-origins" - ], - "defaultOptionalClientScopes": [ - "offline_access", - "phone", - "microprofile-jwt", - "address" - ], - "browserSecurityHeaders": { - "contentSecurityPolicyReportOnly": "", - "xContentTypeOptions": "nosniff", - "xRobotsTag": "none", - "xFrameOptions": "SAMEORIGIN", - "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection": "1; mode=block", - "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, { + "id" : "9f340eba-2b84-43d0-a976-010e270e3981", + "clientId" : "spiffworkflow-frontend", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "https://api.unused-for-local-dev.spiffworkflow.org/*", "http://localhost:7001/*", "http://67.205.133.116:7000/*", "http://167.172.242.138:7001/*", "https://api.demo.spiffworkflow.org/*" ], + "webOrigins" : [ "*" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "true", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "5d94a8c3-f56b-4eff-ac39-8580053a7fbe", + "clientId" : "withAuth", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "6o8kIKQznQtejHOdRhWeKorBJclMGcgA", + "redirectUris" : [ "https://api.unused-for-local-dev.spiffworkflow.org/*", "http://localhost:7001/*", "http://67.205.133.116:7000/*", "http://167.172.242.138:7001/*", "https://api.demo.spiffworkflow.org/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : true, + "authorizationServicesEnabled" : true, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "saml.force.post.binding" : "false", + "saml.multivalued.roles" : "false", + "frontchannel.logout.session.required" : "false", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "saml.server.signature.keyinfo.ext" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "true", + "client_credentials.use_refresh_token" : "false", + "require.pushed.authorization.requests" : "false", + "saml.client.signature" : "false", + "saml.allow.ecp.flow" : "false", + "id.token.as.detached.signature" : "false", + "saml.assertion.signature" : "false", + "client.secret.creation.time" : "1657055472", + "saml.encrypt" : "false", + "saml.server.signature" : "false", + "exclude.session.state.from.auth.response" : "false", + "saml.artifact.binding" : "false", + "saml_force_name_id_format" : "false", + "acr.loa.map" : "{}", + "tls.client.certificate.bound.access.tokens" : "false", + "saml.authnstatement" : "false", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false", + "saml.onetimeuse.condition" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "abfc756f-fc57-45b4-8a40-0cd0f8081f0c", + "name" : "Client ID", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientId", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientId", + "jsonType.label" : "String" + } + }, { + "id" : "c05d38b7-9b4d-4286-b40c-f48b3cca42e3", + "name" : "Client Host", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientHost", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientHost", + "jsonType.label" : "String" + } + }, { + "id" : "b27d0bd8-b8d9-43cb-a07a-3ec4bdc818dc", + "name" : "Client IP Address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientAddress", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientAddress", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], + "authorizationSettings" : { + "allowRemoteResourceManagement" : true, + "policyEnforcementMode" : "ENFORCING", + "resources" : [ { + "name" : "Default Resource", + "type" : "urn:withAuth:resources:default", + "ownerManagedAccess" : false, + "attributes" : { }, + "_id" : "c882ad40-c15d-4f88-ad60-c2ea2f486ce2", + "uris" : [ "/*" ] + } ], + "policies" : [ { + "id" : "b8b338bc-884d-43cf-96d8-3776f2b220f3", + "name" : "Default Policy", + "description" : "A policy that grants access only for users within this realm", + "type" : "role", + "logic" : "POSITIVE", + "decisionStrategy" : "AFFIRMATIVE", + "config" : { + "roles" : "[{\"id\":\"spiffworkflow-backend/repeat-form-role-2\",\"required\":false}]" + } + }, { + "id" : "4f5afa22-0fdf-4ed7-97b9-35400591bf6f", + "name" : "Default Permission", + "description" : "A permission that applies to the default resource type", + "type" : "resource", + "logic" : "POSITIVE", + "decisionStrategy" : "UNANIMOUS", + "config" : { + "defaultResourceType" : "urn:withAuth:resources:default", + "applyPolicies" : "[\"Default Policy\"]" + } + } ], + "scopes" : [ ], + "decisionStrategy" : "UNANIMOUS" + } + } ], + "clientScopes" : [ { + "id" : "fa3d9944-cf66-4af9-b931-1f3b02943e5b", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "12ad0a69-d414-4b5b-9f5f-b647db5f8959", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + }, { + "id" : "4e69d058-1229-4704-9411-decf25da0a49", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "d0d7334e-3f11-45d2-9670-46dbc1977cb2", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "4efcf169-4df2-4cdb-b331-005aff1cee28", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "3f639f2f-cf0e-4651-ab93-15a77023b5a0", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "16e93663-bf6a-4f6d-b5ab-8e68bf118f72", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "b9c97283-8153-4c4d-b8d8-dd1bde17823b", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "eeead6c7-1dae-4be1-9eca-988ffb38aaf4", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "d62991bc-2583-42be-bb08-8d1527c4f162", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "9f761222-f84d-4a25-a53f-13e196d38a46", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "ec866e3c-582f-4c99-920f-d57cf03d772d", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "b05e679c-e00e-427e-8e47-0a4fd411c7a6", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "505ff402-5533-48ea-91f9-ab4804c3826b", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "d546af31-b669-442b-9a9d-8a6478364002", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "5a75c993-290f-4bfb-9044-5d7d269378b2", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "2d387240-0f2f-4f30-8464-0e7c57946743", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "2efee39d-723c-44af-9eb1-4dde9635b249", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "5bf7db0f-a915-43c2-bff4-475ee5c3259b", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + }, { + "id" : "687a8c7d-c93f-47d9-a176-78b0954429c7", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "4a7737cf-83e3-40e1-b36d-9566b34e4148", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "14bd2816-a2f3-4fde-9ac2-452dea2e9e58", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "6172e315-8999-4df8-89fa-75ffd1981793", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "5ad0c621-d3ec-4018-98c8-d6fb630d661f", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "252fdd9f-cc91-4ca3-aaab-cdf053360e94", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "multivalued" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "8e9b880e-6dd8-4e2f-ade2-77fc8fd0bc6d", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "77ca4f26-3777-451b-a907-e258f46f7b95", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "e7ebb9c0-5ed3-4c6f-bb69-22e01d26b49f", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + }, { + "id" : "66fd470f-419e-44cd-822e-43df8ee5fe1b", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "f3c313bc-7da7-4cf6-a0df-b62e77209b7c", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + }, { + "id" : "3e9849f5-15ff-43c6-b929-40f26fda2c05", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "ffda6ea6-8add-4c7e-9754-66d00c6735a1", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "05635d42-8bb3-440b-b871-b64c97f524da", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { } + } ] + }, { + "id" : "6f56ae2b-253f-40f7-ba99-e8c5bbc71423", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "7036c17a-9306-4481-82a1-d8d9d77077e5", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "ce4493c0-ccb4-45f9-a46e-a40cc3f6d4b2", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "8a0d3248-d231-40b2-9b8e-3d63bd5a5d12", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "email", "profile", "role_list", "roles", "acr", "web-origins" ], + "defaultOptionalClientScopes" : [ "offline_access", "phone", "microprofile-jwt", "address" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" }, - "smtpServer": {}, - "eventsEnabled": false, - "eventsListeners": ["jboss-logging"], - "enabledEventTypes": [], - "adminEventsEnabled": false, - "adminEventsDetailsEnabled": false, - "identityProviders": [], - "identityProviderMappers": [], - "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ - { - "id": "b8617465-1c84-4a5f-a16f-a6f10f0f66b1", - "name": "Trusted Hosts", - "providerId": "trusted-hosts", - "subType": "anonymous", - "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": ["true"], - "client-uris-must-match": ["true"] - } - }, - { - "id": "6061713a-c1f5-46e1-adfb-762b8768976a", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-full-name-mapper", - "oidc-usermodel-property-mapper", - "oidc-sha256-pairwise-sub-mapper", - "saml-user-property-mapper", - "oidc-usermodel-attribute-mapper", - "oidc-address-mapper", - "saml-role-list-mapper", - "saml-user-attribute-mapper" - ] - } - }, - { - "id": "d68e938d-dde6-47d9-bdc8-8e8523eb08cd", - "name": "Max Clients Limit", - "providerId": "max-clients", - "subType": "anonymous", - "subComponents": {}, - "config": { - "max-clients": ["200"] - } - }, - { - "id": "1209fa5d-37df-4f9a-b4fa-4a3cd94e21fe", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-full-name-mapper", - "saml-user-property-mapper", - "oidc-usermodel-attribute-mapper", - "saml-role-list-mapper", - "oidc-sha256-pairwise-sub-mapper", - "oidc-usermodel-property-mapper", - "saml-user-attribute-mapper", - "oidc-address-mapper" - ] - } - }, - { - "id": "3854361d-3fe5-47fb-9417-a99592e3dc5c", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allow-default-scopes": ["true"] - } - }, - { - "id": "4c4076ec-68ed-46c1-b0a5-3c8ed08dd4f6", - "name": "Consent Required", - "providerId": "consent-required", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "bbbe2ea2-2a36-494b-b57f-8b202740ebf4", - "name": "Full Scope Disabled", - "providerId": "scope", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "41eef3e1-bf71-4e8a-b729-fea8eb16b5d8", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allow-default-scopes": ["true"] - } + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "b8617465-1c84-4a5f-a16f-a6f10f0f66b1", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] } - ], - "org.keycloak.userprofile.UserProfileProvider": [ - { - "id": "576f8c6a-00e6-45dd-a63d-614100fb2cc4", - "providerId": "declarative-user-profile", - "subComponents": {}, - "config": {} + }, { + "id" : "6061713a-c1f5-46e1-adfb-762b8768976a", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-address-mapper", "saml-user-attribute-mapper" ] } - ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "1f9958a4-b3ac-4a1b-af95-fd8e6053864a", - "name": "hmac-generated", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "kid": ["4e99c641-0494-49d5-979f-45cb5126f6f1"], - "secret": [ - "4wV4voiQmFajEegv83Ugd8DxFoy3JpN4YzO5qMx4XfB7Abq8NKU4Az5AkSpxYBSdb5GJEQypA4aLmnaDyCWLIw" - ], - "priority": ["100"], - "algorithm": ["HS256"] - } - }, - { - "id": "70fe0720-f3b7-47b4-a625-ae8fb6635da1", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "kid": ["76118b54-fc74-4149-9028-fab1fdc07860"], - "secret": ["DvxTn0KA4TEUPqSFBw8qAw"], - "priority": ["100"] - } - }, - { - "id": "a12fdd97-1d72-4d9e-9e6a-f9e0b5d4e5f0", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "privateKey": [ - "MIIEpAIBAAKCAQEAimbfmG2pL3qesWhUrQayRyYBbRFE0Ul5Ii/AW8Kq6Kad9R2n2sT2BvXWnsWBH6KuINUFJz3Tb+gWy235Jy0Idmekwx63JR20//ZJ7dyQ+b1iadmYPpqyixGL7NrVxQYT0AEGLcD/Fwsh869F3jgfQt7N15q2arRnOrW5NMwi+IvtHxZRZ3UluxShut2577ef8cakwCv4zoTV29y+Z3XhtlKZ4WOCuqIHL3SRHwNkb+k8cY0Gwc88FHl/ihFR0fX/lc7W2AHRd98ex8il4kBFfShBZur8ZLE7QWQdXRY2EYYr3D/W6/5wf/R2fAvbVmGzcYGZ2qm6d+K1XH8VU3X84wIDAQABAoIBABXXrHwa+nOCz57CD3MLNoGiDuGOsySwisyJartQmraC7TTtDDurkASDMe72zq0WeJK368tIp6DmqQpL/eFf6xD8xHUC2PajnJg033AJuluftvNroupmcb0e9M1ZsBkbH29Zagc4iUmyuRYDWGx8wPpFvYjEYvuuIwiR+3vIp9A/0ZbcBwdtml3Of5gYTXChPj28PrA4K7oFib2Zu1aYCBEdF8h9bKRF/UlvyWeSajjddexSQ6gkEjzAEMpliCDbOGSFGwNu1pY7FF4EpyJbalzdpn44m5v9bqfS9/CDrIOOUus88Nn5wCD2OAmAQnWn0Hnh7at4A5fw3VBUmEt70ckCgYEAx0Fg8Gp3SuMaytrf9HJHJcltyDRsdSxysF1ZvDV9cDUsD28QOa/wFJRVsABxqElU+W6QEc20NMgOHVyPFed5UhQA6WfmydzGIcF5C6T5IbE/5Uk3ptGuPdI0aR7rlRfefQOnUBr28dz5UDBTb93t9+Klxcss+nLGRbugnFBAtTUCgYEAsdD+92nuF/GfET97vbHxtJ6+epHddttWlsa5PVeVOZBE/LUsOZRxmxm4afvZGOkhUrvmA1+U0arcp9crS5+Ol2LUGh/9efqLvoBImBxLwB37VcIYLJi0EVPrhVPh+9r3vah1YMBhtapS0VtuEZOr47Yz7asBg1s1Z06l+bD1JLcCgYA+3YS9NYn/qZl5aQcBs9B4vo2RfeC+M1DYDgvS0rmJ3mzRTcQ7vyOrCoXiarFxW/mgXN69jz4M7RVu9BX83jQrzj3fZjWteKdWXRlYsCseEzNKnwgc7MjhnmGEzQmc15QNs0plfqxs8MAEKcsZX1bGP873kbvWJMIjnCf3SWaxBQKBgQCh9zt2w19jIewA+vFMbXw7SGk6Hgk6zTlG50YtkMxU/YtJIAFjhUohu8DVkNhDr35x7MLribF1dYu9ueku3ew1CokmLsNkywllAVaebw+0s9qOV9hLLuC989HQxQJPtTj54SrhcPrPTZBYME7G5dqo9PrB3oTnUDoJmoLmOABjawKBgQCeyd12ShpKYHZS4ZvE87OfXanuNfpVxhcXOqYHpQz2W0a+oUu9e78MlwTVooR4O52W/Ohch2FPEzq/1DBjJrK6PrMY8DS018BIVpQ9DS35/Ga9NtSi8DX7jTXacYPwL9n/+//U3vw0mjaoMXgCv44nYu4ro62J6wvVM98hjQmLJw==" - ], - "keyUse": ["SIG"], - "certificate": [ - "MIICqTCCAZECBgGBz6+bXzANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1zcGlmZndvcmtmbG93MB4XDTIyMDcwNTE4NDUwMVoXDTMyMDcwNTE4NDY0MVowGDEWMBQGA1UEAwwNc3BpZmZ3b3JrZmxvdzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIpm35htqS96nrFoVK0GskcmAW0RRNFJeSIvwFvCquimnfUdp9rE9gb11p7FgR+iriDVBSc902/oFstt+SctCHZnpMMetyUdtP/2Se3ckPm9YmnZmD6asosRi+za1cUGE9ABBi3A/xcLIfOvRd44H0Lezdeatmq0Zzq1uTTMIviL7R8WUWd1JbsUobrdue+3n/HGpMAr+M6E1dvcvmd14bZSmeFjgrqiBy90kR8DZG/pPHGNBsHPPBR5f4oRUdH1/5XO1tgB0XffHsfIpeJARX0oQWbq/GSxO0FkHV0WNhGGK9w/1uv+cH/0dnwL21Zhs3GBmdqpunfitVx/FVN1/OMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAaI7BEPZpf4MU7bMWmNgyfRTRDy5wtpyfuLPGHZ9EqtnvwwzsmlmXXsC55SLXx3wJETm+rFqeRFbo/hamlRajzzD317AUpE7nhnONTukmh6UuB8hXoWiQTD+YDYMy8kneSP4zvfm27F+TgUC4cvJSYuWVaCxFx52kxqW1hZkBzYUcfi21Qb1jRrbTbso37BxuVX+GdN015If3DPD6QnAhLPAYEFA9jiL16YeMdWHdvlXXmvriDegMUYQjFYPRh6iPzUEdG6KGHItF4AkOYBQAcoaYhfxpxofVlDdOqMZ/1c7AAbe4lR6/jYQ0CbHwdUu4dzJQe3vxr7GdxcB1ypvXPA==" - ], - "priority": ["100"] - } - }, - { - "id": "e16c740d-3ae2-4cc5-a68d-49d99e079672", - "name": "rsa-enc-generated", - "providerId": "rsa-enc-generated", - "subComponents": {}, - "config": { - "privateKey": [ - "MIIEowIBAAKCAQEAsqGsclDQDFSTn8HS1LiiNAnTwn3CS8HXPLDYMHr/jUQ8r5eD+vQY5ICh5V5c8l8J6ydbpzffFEKam54Ypp4yzaWJZ4huYBMf4vL7xrAZ4VXBreu16BIxOrThzrJe9WmI8+Annzo62mNYZbjf4WNpZDURmxZSo7v6Czprd5O6T4N5bxr8sjRRptZR8hxtrRvJnuC0jF+dLHIO5SKR1hUVG/gbpIBqGcsLkNC9nnS6M/N5YFzUIV5JhXo3+mrR/yvw7m+oS5yRsN0raCSXVenNP05Dhsd4FOYqoXBBcdgXXbiDxed0HWB/g5dASqyMydHriddGr8FU0W8/uZmF79wxPwIDAQABAoIBAFsWCaL5Bj1jWytZYDJMO5mhcTN5gPu0ShaObo66CVl1dCRtdEUg9xh9ZxBYf7ivMZWRKjEoUj44gDHd+d/sRyeJw3jhnraqydWl5TC5V1kJq4sN6GH/9M5kscf+OGGXgNgqcsnEnYICqm6kSLTbRkBstx+H0HfhQG09StNcpuIn4MsoMZT8XmZbXRLb3FhfpuTSX3t2nbSDRfUf7LI1EDnFQen/AJAA5lOHthLCdz4Gj1vfalOFjCMYOUWmL/mCDEb38F6QJZxkyhmS/r2kM09PFLOio6z3J8C8mVeq7uao0s5xAKj5SJqx4r+TTvL5aOF8JBWm8Hz1Vcip9/MjsQECgYEA/8Hpb4RggNyn+YzTxqxtPtbLFL0YywtNT+gutmJH1gyTjfx7p3dmA/NsdIeuJmBpZfA7oDXIqfj2M9QLfC5bdKnggQzrIO3BgClI88zOIWd229Bt6D1yx92k4+9eaRwOKBPn8+u0mCk8TBv32ecMLQ9o8AKNIHeCZQjByvOrIMECgYEAss0J3TzrRuEOpnxJ9fNOeB3rNpIFrpNua+oEQI4gDbBvyT7osBKkGqfXJpUQMftr8a6uBHLHV7/Wq6/aRkRhk+aER8h01DUIWGLmbCUdkFSJZ8iObMZQvURtckhzxxhYu0Ybwn0RJg/zzR4onTRO+eL1fTnb5Id55PyPt3Pp0f8CgYEAovDOoP6MYOyzk5h1/7gwrX04ytCicBGWQtdgk0/QBn3ir+3wdcPq2Y+HREKA3/BClfBUfIBnhGqZqHFqk8YQ/CWSY4Vwc30l71neIX0UwlFhdy+2JeSoMM9z0sfYtUxrdHsiJtO/LcXvpWmYIVpC9p4/s9FcShf5mhbXKE7PcsECgYBN7qqvAH94LF4rWJ8QEZWRK1E7Ptg1KFOHu79Qt+HmtZFzwPTA0c8vQxq22V/uuSxqcf2tOK4EZDxYJtTXrbRuN5pOg2PQnrDdfXX7iw3gu8gMMVFKvgGxDSM7HbNBAy6hqcQtuD+CPI/CRrPjGUqXBkKD63UZnacWlLK7fk1a1wKBgExUaqOBKmr0vldVn66E1XzZj4F4+fV5Ggka9289pBNBRlJFD4VmIYkDkOrLimyy2cYeCkocrOvF6HMJqTcOzD50pj44OWkYFRbs6vK0S7iLSX0eR158XOR9C+uZzp1vIA4sYwW3504HVdVoIU5M8ItSgDsFjGnvHopTGu3MBWPT" - ], - "keyUse": ["ENC"], - "certificate": [ - "MIICqTCCAZECBgGBz6+byzANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1zcGlmZndvcmtmbG93MB4XDTIyMDcwNTE4NDUwMVoXDTMyMDcwNTE4NDY0MVowGDEWMBQGA1UEAwwNc3BpZmZ3b3JrZmxvdzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALKhrHJQ0AxUk5/B0tS4ojQJ08J9wkvB1zyw2DB6/41EPK+Xg/r0GOSAoeVeXPJfCesnW6c33xRCmpueGKaeMs2liWeIbmATH+Ly+8awGeFVwa3rtegSMTq04c6yXvVpiPPgJ586OtpjWGW43+FjaWQ1EZsWUqO7+gs6a3eTuk+DeW8a/LI0UabWUfIcba0byZ7gtIxfnSxyDuUikdYVFRv4G6SAahnLC5DQvZ50ujPzeWBc1CFeSYV6N/pq0f8r8O5vqEuckbDdK2gkl1XpzT9OQ4bHeBTmKqFwQXHYF124g8XndB1gf4OXQEqsjMnR64nXRq/BVNFvP7mZhe/cMT8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEArDDC7bYbuBg33PbUQi7P77lV7PuE9uQU1F3HqulhkARQeM/xmBdJRj9CHjj62shkI3An70tJtGBJkVAHltmvjC+A6IDO5I8IbnPkvWJFu9HwphdP/C1HXYmGPPe7yGdKpy6mdCZ+LMZP7BENhOlx9yXLDFYtcGvqZ4u3XvfsLqUsRGqZHNlhVJD13dUbI6pvbwMsb3gIxozgTIa2ySHMbHafln2UQk5jD0eOIVkaNAdlHqMHiBpPjkoVxnhAmJ/dUIAqKBvuIbCOu9N0kOQSl82LqC7CZ21JCyT86Ll3n1RTkxY5G3JzGW4dyJMOGSyVnWaQ9Z+C92ZMFcOt611M2A==" - ], - "priority": ["100"], - "algorithm": ["RSA-OAEP"] - } + }, { + "id" : "d68e938d-dde6-47d9-bdc8-8e8523eb08cd", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] } - ] + }, { + "id" : "1209fa5d-37df-4f9a-b4fa-4a3cd94e21fe", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper" ] + } + }, { + "id" : "3854361d-3fe5-47fb-9417-a99592e3dc5c", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "4c4076ec-68ed-46c1-b0a5-3c8ed08dd4f6", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "bbbe2ea2-2a36-494b-b57f-8b202740ebf4", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "41eef3e1-bf71-4e8a-b729-fea8eb16b5d8", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + } ], + "org.keycloak.userprofile.UserProfileProvider" : [ { + "id" : "576f8c6a-00e6-45dd-a63d-614100fb2cc4", + "providerId" : "declarative-user-profile", + "subComponents" : { }, + "config" : { } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "1f9958a4-b3ac-4a1b-af95-fd8e6053864a", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "4e99c641-0494-49d5-979f-45cb5126f6f1" ], + "secret" : [ "4wV4voiQmFajEegv83Ugd8DxFoy3JpN4YzO5qMx4XfB7Abq8NKU4Az5AkSpxYBSdb5GJEQypA4aLmnaDyCWLIw" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + }, { + "id" : "70fe0720-f3b7-47b4-a625-ae8fb6635da1", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "76118b54-fc74-4149-9028-fab1fdc07860" ], + "secret" : [ "DvxTn0KA4TEUPqSFBw8qAw" ], + "priority" : [ "100" ] + } + }, { + "id" : "a12fdd97-1d72-4d9e-9e6a-f9e0b5d4e5f0", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEAimbfmG2pL3qesWhUrQayRyYBbRFE0Ul5Ii/AW8Kq6Kad9R2n2sT2BvXWnsWBH6KuINUFJz3Tb+gWy235Jy0Idmekwx63JR20//ZJ7dyQ+b1iadmYPpqyixGL7NrVxQYT0AEGLcD/Fwsh869F3jgfQt7N15q2arRnOrW5NMwi+IvtHxZRZ3UluxShut2577ef8cakwCv4zoTV29y+Z3XhtlKZ4WOCuqIHL3SRHwNkb+k8cY0Gwc88FHl/ihFR0fX/lc7W2AHRd98ex8il4kBFfShBZur8ZLE7QWQdXRY2EYYr3D/W6/5wf/R2fAvbVmGzcYGZ2qm6d+K1XH8VU3X84wIDAQABAoIBABXXrHwa+nOCz57CD3MLNoGiDuGOsySwisyJartQmraC7TTtDDurkASDMe72zq0WeJK368tIp6DmqQpL/eFf6xD8xHUC2PajnJg033AJuluftvNroupmcb0e9M1ZsBkbH29Zagc4iUmyuRYDWGx8wPpFvYjEYvuuIwiR+3vIp9A/0ZbcBwdtml3Of5gYTXChPj28PrA4K7oFib2Zu1aYCBEdF8h9bKRF/UlvyWeSajjddexSQ6gkEjzAEMpliCDbOGSFGwNu1pY7FF4EpyJbalzdpn44m5v9bqfS9/CDrIOOUus88Nn5wCD2OAmAQnWn0Hnh7at4A5fw3VBUmEt70ckCgYEAx0Fg8Gp3SuMaytrf9HJHJcltyDRsdSxysF1ZvDV9cDUsD28QOa/wFJRVsABxqElU+W6QEc20NMgOHVyPFed5UhQA6WfmydzGIcF5C6T5IbE/5Uk3ptGuPdI0aR7rlRfefQOnUBr28dz5UDBTb93t9+Klxcss+nLGRbugnFBAtTUCgYEAsdD+92nuF/GfET97vbHxtJ6+epHddttWlsa5PVeVOZBE/LUsOZRxmxm4afvZGOkhUrvmA1+U0arcp9crS5+Ol2LUGh/9efqLvoBImBxLwB37VcIYLJi0EVPrhVPh+9r3vah1YMBhtapS0VtuEZOr47Yz7asBg1s1Z06l+bD1JLcCgYA+3YS9NYn/qZl5aQcBs9B4vo2RfeC+M1DYDgvS0rmJ3mzRTcQ7vyOrCoXiarFxW/mgXN69jz4M7RVu9BX83jQrzj3fZjWteKdWXRlYsCseEzNKnwgc7MjhnmGEzQmc15QNs0plfqxs8MAEKcsZX1bGP873kbvWJMIjnCf3SWaxBQKBgQCh9zt2w19jIewA+vFMbXw7SGk6Hgk6zTlG50YtkMxU/YtJIAFjhUohu8DVkNhDr35x7MLribF1dYu9ueku3ew1CokmLsNkywllAVaebw+0s9qOV9hLLuC989HQxQJPtTj54SrhcPrPTZBYME7G5dqo9PrB3oTnUDoJmoLmOABjawKBgQCeyd12ShpKYHZS4ZvE87OfXanuNfpVxhcXOqYHpQz2W0a+oUu9e78MlwTVooR4O52W/Ohch2FPEzq/1DBjJrK6PrMY8DS018BIVpQ9DS35/Ga9NtSi8DX7jTXacYPwL9n/+//U3vw0mjaoMXgCv44nYu4ro62J6wvVM98hjQmLJw==" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIICqTCCAZECBgGBz6+bXzANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1zcGlmZndvcmtmbG93MB4XDTIyMDcwNTE4NDUwMVoXDTMyMDcwNTE4NDY0MVowGDEWMBQGA1UEAwwNc3BpZmZ3b3JrZmxvdzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIpm35htqS96nrFoVK0GskcmAW0RRNFJeSIvwFvCquimnfUdp9rE9gb11p7FgR+iriDVBSc902/oFstt+SctCHZnpMMetyUdtP/2Se3ckPm9YmnZmD6asosRi+za1cUGE9ABBi3A/xcLIfOvRd44H0Lezdeatmq0Zzq1uTTMIviL7R8WUWd1JbsUobrdue+3n/HGpMAr+M6E1dvcvmd14bZSmeFjgrqiBy90kR8DZG/pPHGNBsHPPBR5f4oRUdH1/5XO1tgB0XffHsfIpeJARX0oQWbq/GSxO0FkHV0WNhGGK9w/1uv+cH/0dnwL21Zhs3GBmdqpunfitVx/FVN1/OMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAaI7BEPZpf4MU7bMWmNgyfRTRDy5wtpyfuLPGHZ9EqtnvwwzsmlmXXsC55SLXx3wJETm+rFqeRFbo/hamlRajzzD317AUpE7nhnONTukmh6UuB8hXoWiQTD+YDYMy8kneSP4zvfm27F+TgUC4cvJSYuWVaCxFx52kxqW1hZkBzYUcfi21Qb1jRrbTbso37BxuVX+GdN015If3DPD6QnAhLPAYEFA9jiL16YeMdWHdvlXXmvriDegMUYQjFYPRh6iPzUEdG6KGHItF4AkOYBQAcoaYhfxpxofVlDdOqMZ/1c7AAbe4lR6/jYQ0CbHwdUu4dzJQe3vxr7GdxcB1ypvXPA==" ], + "priority" : [ "100" ] + } + }, { + "id" : "e16c740d-3ae2-4cc5-a68d-49d99e079672", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEAsqGsclDQDFSTn8HS1LiiNAnTwn3CS8HXPLDYMHr/jUQ8r5eD+vQY5ICh5V5c8l8J6ydbpzffFEKam54Ypp4yzaWJZ4huYBMf4vL7xrAZ4VXBreu16BIxOrThzrJe9WmI8+Annzo62mNYZbjf4WNpZDURmxZSo7v6Czprd5O6T4N5bxr8sjRRptZR8hxtrRvJnuC0jF+dLHIO5SKR1hUVG/gbpIBqGcsLkNC9nnS6M/N5YFzUIV5JhXo3+mrR/yvw7m+oS5yRsN0raCSXVenNP05Dhsd4FOYqoXBBcdgXXbiDxed0HWB/g5dASqyMydHriddGr8FU0W8/uZmF79wxPwIDAQABAoIBAFsWCaL5Bj1jWytZYDJMO5mhcTN5gPu0ShaObo66CVl1dCRtdEUg9xh9ZxBYf7ivMZWRKjEoUj44gDHd+d/sRyeJw3jhnraqydWl5TC5V1kJq4sN6GH/9M5kscf+OGGXgNgqcsnEnYICqm6kSLTbRkBstx+H0HfhQG09StNcpuIn4MsoMZT8XmZbXRLb3FhfpuTSX3t2nbSDRfUf7LI1EDnFQen/AJAA5lOHthLCdz4Gj1vfalOFjCMYOUWmL/mCDEb38F6QJZxkyhmS/r2kM09PFLOio6z3J8C8mVeq7uao0s5xAKj5SJqx4r+TTvL5aOF8JBWm8Hz1Vcip9/MjsQECgYEA/8Hpb4RggNyn+YzTxqxtPtbLFL0YywtNT+gutmJH1gyTjfx7p3dmA/NsdIeuJmBpZfA7oDXIqfj2M9QLfC5bdKnggQzrIO3BgClI88zOIWd229Bt6D1yx92k4+9eaRwOKBPn8+u0mCk8TBv32ecMLQ9o8AKNIHeCZQjByvOrIMECgYEAss0J3TzrRuEOpnxJ9fNOeB3rNpIFrpNua+oEQI4gDbBvyT7osBKkGqfXJpUQMftr8a6uBHLHV7/Wq6/aRkRhk+aER8h01DUIWGLmbCUdkFSJZ8iObMZQvURtckhzxxhYu0Ybwn0RJg/zzR4onTRO+eL1fTnb5Id55PyPt3Pp0f8CgYEAovDOoP6MYOyzk5h1/7gwrX04ytCicBGWQtdgk0/QBn3ir+3wdcPq2Y+HREKA3/BClfBUfIBnhGqZqHFqk8YQ/CWSY4Vwc30l71neIX0UwlFhdy+2JeSoMM9z0sfYtUxrdHsiJtO/LcXvpWmYIVpC9p4/s9FcShf5mhbXKE7PcsECgYBN7qqvAH94LF4rWJ8QEZWRK1E7Ptg1KFOHu79Qt+HmtZFzwPTA0c8vQxq22V/uuSxqcf2tOK4EZDxYJtTXrbRuN5pOg2PQnrDdfXX7iw3gu8gMMVFKvgGxDSM7HbNBAy6hqcQtuD+CPI/CRrPjGUqXBkKD63UZnacWlLK7fk1a1wKBgExUaqOBKmr0vldVn66E1XzZj4F4+fV5Ggka9289pBNBRlJFD4VmIYkDkOrLimyy2cYeCkocrOvF6HMJqTcOzD50pj44OWkYFRbs6vK0S7iLSX0eR158XOR9C+uZzp1vIA4sYwW3504HVdVoIU5M8ItSgDsFjGnvHopTGu3MBWPT" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICqTCCAZECBgGBz6+byzANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1zcGlmZndvcmtmbG93MB4XDTIyMDcwNTE4NDUwMVoXDTMyMDcwNTE4NDY0MVowGDEWMBQGA1UEAwwNc3BpZmZ3b3JrZmxvdzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALKhrHJQ0AxUk5/B0tS4ojQJ08J9wkvB1zyw2DB6/41EPK+Xg/r0GOSAoeVeXPJfCesnW6c33xRCmpueGKaeMs2liWeIbmATH+Ly+8awGeFVwa3rtegSMTq04c6yXvVpiPPgJ586OtpjWGW43+FjaWQ1EZsWUqO7+gs6a3eTuk+DeW8a/LI0UabWUfIcba0byZ7gtIxfnSxyDuUikdYVFRv4G6SAahnLC5DQvZ50ujPzeWBc1CFeSYV6N/pq0f8r8O5vqEuckbDdK2gkl1XpzT9OQ4bHeBTmKqFwQXHYF124g8XndB1gf4OXQEqsjMnR64nXRq/BVNFvP7mZhe/cMT8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEArDDC7bYbuBg33PbUQi7P77lV7PuE9uQU1F3HqulhkARQeM/xmBdJRj9CHjj62shkI3An70tJtGBJkVAHltmvjC+A6IDO5I8IbnPkvWJFu9HwphdP/C1HXYmGPPe7yGdKpy6mdCZ+LMZP7BENhOlx9yXLDFYtcGvqZ4u3XvfsLqUsRGqZHNlhVJD13dUbI6pvbwMsb3gIxozgTIa2ySHMbHafln2UQk5jD0eOIVkaNAdlHqMHiBpPjkoVxnhAmJ/dUIAqKBvuIbCOu9N0kOQSl82LqC7CZ21JCyT86Ll3n1RTkxY5G3JzGW4dyJMOGSyVnWaQ9Z+C92ZMFcOt611M2A==" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + } ] }, - "internationalizationEnabled": false, - "supportedLocales": [], - "authenticationFlows": [ - { - "id": "ff21c216-5ea8-4d26-95ca-2b467a9d5059", - "alias": "Account verification options", - "description": "Method with which to verity the existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-email-verification", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false - } - ] - }, - { - "id": "256108f7-b791-4e54-b4cb-a551afdf870a", - "alias": "Authentication Options", - "description": "Authentication options.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "basic-auth", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "basic-auth-otp", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "fa9b2739-d814-4f83-805f-2ab0f5692cc8", - "alias": "Browser - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "76819f1b-04b8-412e-933c-3e30b48f350b", - "alias": "Direct Grant - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "54f89ad2-b2b2-4554-8528-04a8b4e73e68", - "alias": "First broker login - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "08664454-8aa7-4f07-990b-9b59ddd19a26", - "alias": "Handle Existing Account", - "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-confirm-link", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Account verification options", - "userSetupAllowed": false - } - ] - }, - { - "id": "29af9cfb-11d1-4781-aee3-844b436d4c08", - "alias": "Reset - Conditional OTP", - "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "2c2d44f6-115e-420e-bc86-1d58914b16ac", - "alias": "User creation or linking", - "description": "Flow for the existing/non-existing user alternatives", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "create unique user config", - "authenticator": "idp-create-user-if-unique", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Handle Existing Account", - "userSetupAllowed": false - } - ] - }, - { - "id": "050e3be8-d313-49ec-a891-fa84592c6cc4", - "alias": "Verify Existing Account by Re-authentication", - "description": "Reauthentication of existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "First broker login - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "d04138a1-dfa4-4854-a59e-b7f4693b56e6", - "alias": "browser", - "description": "browser based authentication", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-cookie", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "identity-provider-redirector", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 25, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "forms", - "userSetupAllowed": false - } - ] - }, - { - "id": "998cd89f-b1da-4101-9c75-658998ad3503", - "alias": "clients", - "description": "Base authentication for clients", - "providerId": "client-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "client-secret", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-secret-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-x509", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "e75753f0-6cd8-4fe5-88d5-55affdbbc5d1", - "alias": "direct grant", - "description": "OpenID Connect Resource Owner Grant", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "direct-grant-validate-username", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "Direct Grant - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "3854b6cc-eb08-473b-95f8-71eaab9219de", - "alias": "docker auth", - "description": "Used by Docker clients to authenticate against the IDP", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "docker-http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "a52f25a7-8509-468c-925c-4bb02e8ccd8e", - "alias": "first broker login", - "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "review profile config", - "authenticator": "idp-review-profile", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "User creation or linking", - "userSetupAllowed": false - } - ] - }, - { - "id": "cc9b12fa-7f7d-44ef-aa11-d7e374b2ec0d", - "alias": "forms", - "description": "Username, password, otp and other auth forms.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Browser - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "289ec9b7-c2b8-4222-922a-81be4450ac2e", - "alias": "http challenge", - "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "no-cookie-redirect", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Authentication Options", - "userSetupAllowed": false - } - ] - }, - { - "id": "295c9bc2-0252-4fd3-b7da-47d4d2f0a09b", - "alias": "registration", - "description": "registration flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-page-form", - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": true, - "flowAlias": "registration form", - "userSetupAllowed": false - } - ] - }, - { - "id": "260f9fad-5f32-4507-9e39-6e46bc26e74e", - "alias": "registration form", - "description": "registration form", - "providerId": "form-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-user-creation", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-profile-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-password-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 50, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-recaptcha-action", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 60, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "39ef84e4-b7a0-434d-ba2a-5869b78e7aa0", - "alias": "reset credentials", - "description": "Reset credentials for a user if they forgot their password or something", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "reset-credentials-choose-user", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-credential-email", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 40, - "autheticatorFlow": true, - "flowAlias": "Reset - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "e47473b7-22e0-4bd0-a253-60300aadd9b9", - "alias": "saml ecp", - "description": "SAML ECP Profile Authentication Flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "b30ab201-b13a-405f-bc57-cb5cd934bdc3", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "7d22faa2-1da8-49ae-a2cc-74e9c9f6ed51", + "alias" : "Authentication Options", + "description" : "Authentication options.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "basic-auth", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "basic-auth-otp", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "ae089cf3-3179-4e12-a683-7969a31be566", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "27a21643-2167-4847-a6b4-b07007671d9a", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "0ee33ef7-da6b-4248-81c6-9f4f11b58195", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "e1d02af3-2886-42bb-95f4-bfa6f1299edc", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "35cfc75f-70e3-487c-acd7-0627ab1dbdf1", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "cc2f7206-8d15-46db-b974-71e67d4d1077", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "d8314533-eacb-40ef-8f44-7c06321e9793", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "d58a5ff1-9a9c-45a9-9f97-1324565e9679", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "3ea2aed9-12d9-4999-a104-67f5c5f7841a", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "c605af3c-bede-4f8f-a5c5-94176171c82c", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "901b4d6c-9c27-4d3d-981a-1b5281c1ea2b", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "9d1de1bf-b170-4235-92f1-5dfd3ec31c45", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "8ee6b54f-4d31-4847-9ddc-36cb4c01b92b", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "76d3380b-218b-443d-a3ea-bea712f4a1f4", + "alias" : "http challenge", + "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "no-cookie-redirect", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Authentication Options", + "userSetupAllowed" : false + } ] + }, { + "id" : "cd756473-4606-4150-9ba5-5b96e6f39c3a", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "574fcee6-e152-4069-b328-a7fe33aded3a", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-profile-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "e5a890ee-140a-4ab3-8d79-87e3499385b0", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "6243167c-7e2e-4cc7-b35d-bad7862dc9ef", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "ae605746-d169-4a81-8348-b5f52e07ae14", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" } - ], - "authenticatorConfig": [ - { - "id": "a85a0c1d-f3a2-4183-862e-394a22f12c28", - "alias": "create unique user config", - "config": { - "require.password.update.after.registration": "false" - } - }, - { - "id": "9167b412-f119-4f29-8b38-211437556f63", - "alias": "review profile config", - "config": { - "update.profile.on.first.login": "missing" - } + }, { + "id" : "c5feb20c-eea5-4556-b9f8-797be4d67e26", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" } - ], - "requiredActions": [ - { - "alias": "CONFIGURE_TOTP", - "name": "Configure OTP", - "providerId": "CONFIGURE_TOTP", - "enabled": true, - "defaultAction": false, - "priority": 10, - "config": {} - }, - { - "alias": "terms_and_conditions", - "name": "Terms and Conditions", - "providerId": "terms_and_conditions", - "enabled": false, - "defaultAction": false, - "priority": 20, - "config": {} - }, - { - "alias": "UPDATE_PASSWORD", - "name": "Update Password", - "providerId": "UPDATE_PASSWORD", - "enabled": true, - "defaultAction": false, - "priority": 30, - "config": {} - }, - { - "alias": "UPDATE_PROFILE", - "name": "Update Profile", - "providerId": "UPDATE_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 40, - "config": {} - }, - { - "alias": "VERIFY_EMAIL", - "name": "Verify Email", - "providerId": "VERIFY_EMAIL", - "enabled": true, - "defaultAction": false, - "priority": 50, - "config": {} - }, - { - "alias": "delete_account", - "name": "Delete Account", - "providerId": "delete_account", - "enabled": false, - "defaultAction": false, - "priority": 60, - "config": {} - }, - { - "alias": "update_user_locale", - "name": "Update User Locale", - "providerId": "update_user_locale", - "enabled": true, - "defaultAction": false, - "priority": 1000, - "config": {} - } - ], - "browserFlow": "browser", - "registrationFlow": "registration", - "directGrantFlow": "direct grant", - "resetCredentialsFlow": "reset credentials", - "clientAuthenticationFlow": "clients", - "dockerAuthenticationFlow": "docker auth", - "attributes": { - "cibaBackchannelTokenDeliveryMode": "poll", - "cibaAuthRequestedUserHint": "login_hint", - "clientOfflineSessionMaxLifespan": "0", - "oauth2DevicePollingInterval": "5", - "clientSessionIdleTimeout": "0", - "actionTokenGeneratedByUserLifespan-execute-actions": "", - "actionTokenGeneratedByUserLifespan-verify-email": "", - "clientOfflineSessionIdleTimeout": "0", - "actionTokenGeneratedByUserLifespan-reset-credentials": "", - "cibaInterval": "5", - "cibaExpiresIn": "120", - "oauth2DeviceCodeLifespan": "600", - "actionTokenGeneratedByUserLifespan-idp-verify-account-via-email": "", - "parRequestUriLifespan": "60", - "clientSessionMaxLifespan": "0" + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "terms_and_conditions", + "name" : "Terms and Conditions", + "providerId" : "terms_and_conditions", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaAuthRequestedUserHint" : "login_hint", + "clientOfflineSessionMaxLifespan" : "0", + "oauth2DevicePollingInterval" : "5", + "clientSessionIdleTimeout" : "0", + "actionTokenGeneratedByUserLifespan-execute-actions" : "", + "actionTokenGeneratedByUserLifespan-verify-email" : "", + "clientOfflineSessionIdleTimeout" : "0", + "actionTokenGeneratedByUserLifespan-reset-credentials" : "", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false", + "cibaExpiresIn" : "120", + "oauth2DeviceCodeLifespan" : "600", + "actionTokenGeneratedByUserLifespan-idp-verify-account-via-email" : "", + "parRequestUriLifespan" : "60", + "clientSessionMaxLifespan" : "0" }, - "keycloakVersion": "19.0.3", - "userManagedAccessAllowed": false, - "clientProfiles": { - "profiles": [] + "keycloakVersion" : "20.0.1", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] }, - "clientPolicies": { - "policies": [] + "clientPolicies" : { + "policies" : [ ] } } diff --git a/spiffworkflow-backend/bin/start_keycloak b/spiffworkflow-backend/bin/start_keycloak index 002c2668a..32b502ca0 100755 --- a/spiffworkflow-backend/bin/start_keycloak +++ b/spiffworkflow-backend/bin/start_keycloak @@ -27,7 +27,7 @@ docker run \ -e KEYCLOAK_LOGLEVEL=ALL \ -e ROOT_LOGLEVEL=ALL \ -e KEYCLOAK_ADMIN=admin \ - -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:19.0.3 start-dev \ + -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:20.0.1 start-dev \ -Dkeycloak.profile.feature.token_exchange=enabled \ -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled diff --git a/spiffworkflow-backend/conftest.py b/spiffworkflow-backend/conftest.py index 4751b8588..c3af94332 100644 --- a/spiffworkflow-backend/conftest.py +++ b/spiffworkflow-backend/conftest.py @@ -96,7 +96,7 @@ def setup_process_instances_for_reports( # ) process_instances = [] for data in [kay(), ray(), jay()]: - process_instance = ProcessInstanceService.create_process_instance( + process_instance = ProcessInstanceService.create_process_instance_from_process_model_identifier( # process_group_identifier=process_group_id, process_model_identifier=process_model_identifier, user=user, diff --git a/spiffworkflow-backend/keycloak/Dockerfile b/spiffworkflow-backend/keycloak/Dockerfile index 14c472060..60837bb6e 100644 --- a/spiffworkflow-backend/keycloak/Dockerfile +++ b/spiffworkflow-backend/keycloak/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/keycloak/keycloak:19.0.3 as builder +FROM quay.io/keycloak/keycloak:20.0.1 as builder ENV KEYCLOAK_LOGLEVEL="ALL" ENV ROOT_LOGLEVEL="ALL" diff --git a/spiffworkflow-backend/migrations/versions/70223f5c7b98_.py b/spiffworkflow-backend/migrations/versions/ff1c1628337c_.py similarity index 93% rename from spiffworkflow-backend/migrations/versions/70223f5c7b98_.py rename to spiffworkflow-backend/migrations/versions/ff1c1628337c_.py index 0d9209448..d8da6d3c4 100644 --- a/spiffworkflow-backend/migrations/versions/70223f5c7b98_.py +++ b/spiffworkflow-backend/migrations/versions/ff1c1628337c_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 70223f5c7b98 +Revision ID: ff1c1628337c Revises: -Create Date: 2022-11-20 19:54:45.061376 +Create Date: 2022-11-28 15:08:52.014254 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '70223f5c7b98' +revision = 'ff1c1628337c' down_revision = None branch_labels = None depends_on = None @@ -97,14 +97,12 @@ def upgrade(): sa.Column('id', sa.Integer(), nullable=False), sa.Column('message_model_id', sa.Integer(), nullable=False), sa.Column('process_model_identifier', sa.String(length=50), nullable=False), - sa.Column('process_group_identifier', sa.String(length=50), nullable=False), sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('message_model_id') ) - op.create_index(op.f('ix_message_triggerable_process_model_process_group_identifier'), 'message_triggerable_process_model', ['process_group_identifier'], unique=False) op.create_index(op.f('ix_message_triggerable_process_model_process_model_identifier'), 'message_triggerable_process_model', ['process_model_identifier'], unique=False) op.create_table('principal', sa.Column('id', sa.Integer(), nullable=False), @@ -120,7 +118,7 @@ def upgrade(): op.create_table('process_instance', sa.Column('id', sa.Integer(), nullable=False), sa.Column('process_model_identifier', sa.String(length=255), nullable=False), - sa.Column('process_group_identifier', sa.String(length=50), nullable=False), + sa.Column('process_model_display_name', sa.String(length=255), nullable=False), sa.Column('process_initiator_id', sa.Integer(), nullable=False), sa.Column('bpmn_json', sa.JSON(), nullable=True), sa.Column('start_in_seconds', sa.Integer(), nullable=True), @@ -134,7 +132,7 @@ def upgrade(): sa.ForeignKeyConstraint(['process_initiator_id'], ['user.id'], ), sa.PrimaryKeyConstraint('id') ) - op.create_index(op.f('ix_process_instance_process_group_identifier'), 'process_instance', ['process_group_identifier'], unique=False) + op.create_index(op.f('ix_process_instance_process_model_display_name'), 'process_instance', ['process_model_display_name'], unique=False) op.create_index(op.f('ix_process_instance_process_model_identifier'), 'process_instance', ['process_model_identifier'], unique=False) op.create_table('process_instance_report', sa.Column('id', sa.Integer(), nullable=False), @@ -168,17 +166,6 @@ def upgrade(): sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('key') ) - op.create_table('spiff_step_details', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('spiff_step', sa.Integer(), nullable=False), - sa.Column('task_json', sa.JSON(), nullable=False), - sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False), - sa.Column('completed_by_user_id', sa.Integer(), nullable=True), - sa.Column('lane_assignment_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ), - sa.PrimaryKeyConstraint('id') - ) op.create_table('user_group_assignment', sa.Column('id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=False), @@ -251,6 +238,29 @@ def upgrade(): sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('principal_id', 'permission_target_id', 'permission', name='permission_assignment_uniq') ) + op.create_table('process_instance_metadata', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('process_instance_id', sa.Integer(), nullable=False), + sa.Column('key', sa.String(length=255), nullable=False), + sa.Column('value', sa.String(length=255), nullable=False), + sa.Column('updated_at_in_seconds', sa.Integer(), nullable=False), + sa.Column('created_at_in_seconds', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('process_instance_id', 'key', name='process_instance_metadata_unique') + ) + op.create_table('spiff_step_details', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('process_instance_id', sa.Integer(), nullable=False), + sa.Column('spiff_step', sa.Integer(), nullable=False), + sa.Column('task_json', sa.JSON(), nullable=False), + sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False), + sa.Column('completed_by_user_id', sa.Integer(), nullable=True), + sa.Column('lane_assignment_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ), + sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), + sa.PrimaryKeyConstraint('id') + ) op.create_table('active_task_user', sa.Column('id', sa.Integer(), nullable=False), sa.Column('active_task_id', sa.Integer(), nullable=False), @@ -284,6 +294,8 @@ def downgrade(): op.drop_index(op.f('ix_active_task_user_user_id'), table_name='active_task_user') op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user') op.drop_table('active_task_user') + op.drop_table('spiff_step_details') + op.drop_table('process_instance_metadata') op.drop_table('permission_assignment') op.drop_table('message_instance') op.drop_index(op.f('ix_message_correlation_value'), table_name='message_correlation') @@ -293,18 +305,16 @@ def downgrade(): op.drop_table('message_correlation') op.drop_table('active_task') op.drop_table('user_group_assignment') - op.drop_table('spiff_step_details') op.drop_table('secret') op.drop_table('refresh_token') op.drop_index(op.f('ix_process_instance_report_identifier'), table_name='process_instance_report') op.drop_index(op.f('ix_process_instance_report_created_by_id'), table_name='process_instance_report') op.drop_table('process_instance_report') op.drop_index(op.f('ix_process_instance_process_model_identifier'), table_name='process_instance') - op.drop_index(op.f('ix_process_instance_process_group_identifier'), table_name='process_instance') + op.drop_index(op.f('ix_process_instance_process_model_display_name'), table_name='process_instance') op.drop_table('process_instance') op.drop_table('principal') op.drop_index(op.f('ix_message_triggerable_process_model_process_model_identifier'), table_name='message_triggerable_process_model') - op.drop_index(op.f('ix_message_triggerable_process_model_process_group_identifier'), table_name='message_triggerable_process_model') op.drop_table('message_triggerable_process_model') op.drop_index(op.f('ix_message_correlation_property_identifier'), table_name='message_correlation_property') op.drop_table('message_correlation_property') diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index 1a683ec53..e7dc00fe2 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -160,7 +160,7 @@ paths: schema: type: integer get: - operationId: spiffworkflow_backend.routes.process_api_blueprint.process_groups_list + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_group_list summary: get list tags: - Process Groups @@ -278,7 +278,13 @@ paths: required: false description: Get all sub process models recursively if true schema: - type: string + type: boolean + - name: filter_runnable_by_user + in: query + required: false + description: Get only the process models that the user can run + schema: + type: boolean - name: page in: query required: false @@ -508,6 +514,24 @@ paths: description: For filtering - not_started, user_input_required, waiting, complete, error, or suspended schema: type: string + - name: initiated_by_me + in: query + required: false + description: For filtering - show instances initiated by me + schema: + type: boolean + - name: with_tasks_completed_by_me + in: query + required: false + description: For filtering - show instances with tasks completed by me + schema: + type: boolean + - name: with_tasks_completed_by_my_group + in: query + required: false + description: For filtering - show instances with tasks completed by my group + schema: + type: boolean - name: user_filter in: query required: false @@ -686,7 +710,7 @@ paths: schema: $ref: "#/components/schemas/Workflow" - /process-instances/{process_instance_id}/run: + /process-instances/{modified_process_model_identifier}/{process_instance_id}/run: parameters: - name: process_instance_id in: path @@ -700,7 +724,6 @@ paths: description: Defaults to true, can be set to false if you are just looking at the workflow not completeing it. schema: type: boolean - # process_instance_run post: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_run summary: Run a process instance @@ -1642,10 +1665,6 @@ components: type: integer x-nullable: true example: 12 - study_id: - type: integer - x-nullable: true - example: 42 user_id: type: string x-nullable: true @@ -1770,8 +1789,6 @@ components: type: integer num_tasks_incomplete: type: integer - study_id: - type: integer example: id: 291234 @@ -1906,9 +1923,6 @@ components: workflow_id: example: 42 type: integer - study_id: - example: 187 - type: integer user_uid: example: "dhf8r" type: string diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml index 618a9719f..e17e3f110 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml @@ -4,26 +4,22 @@ groups: admin: users: [ + admin, jakub, kb, alex, dan, mike, jason, + j, amir, jarrad, elizabeth, jon, - harmeet, - sasha, - manuchehr, natalia, ] Finance Team: - users: [finance_user1, jason] - - Project Lead: users: [ jakub, @@ -31,18 +27,42 @@ groups: dan, mike, jason, + j, + amir, jarrad, elizabeth, jon, natalia, + sasha, + fin, + fin1, + ] + + demo: + users: + [ + core, + fin, + fin1, + harmeet, + sasha, manuchehr, + lead, + lead1 + ] + + core-contributor: + users: + [ + core, + harmeet, ] permissions: admin: groups: [admin] users: [] - allowed_permissions: [create, read, update, delete, list, instantiate] + allowed_permissions: [create, read, update, delete] uri: /* tasks-crud: @@ -51,45 +71,116 @@ permissions: allowed_permissions: [create, read, update, delete] uri: /v1.0/tasks/* - process-model-read-all: - groups: [everybody] - users: [] - allowed_permissions: [read] - uri: /v1.0/process-models/* - - process-group-read-all: + # read all for everybody + read-all-process-groups: groups: [everybody] users: [] allowed_permissions: [read] uri: /v1.0/process-groups/* - - process-instance-list: + read-all-process-models: groups: [everybody] users: [] allowed_permissions: [read] - uri: /v1.0/process-instances + uri: /v1.0/process-models/* + read-all-process-instance: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/process-instances/* + read-process-instance-reports: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/process-instances/reports/* + processes-read: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/processes - # TODO: all uris should really have the same structure - finance-admin-group: + + manage-procurement-admin: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-groups/manage-procurement:* + manage-procurement-admin-slash: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-groups/manage-procurement/* + manage-procurement-admin-models: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-models/manage-procurement:* + manage-procurement-admin-models-slash: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-models/manage-procurement/* + manage-procurement-admin-instances: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-instances/manage-procurement:* + manage-procurement-admin-instances-slash: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-instances/manage-procurement/* + + finance-admin: groups: ["Finance Team"] users: [] allowed_permissions: [create, read, update, delete] - uri: /v1.0/process-groups/finance/* + uri: /v1.0/process-groups/manage-procurement:procurement:* - finance-admin-model: - groups: ["Finance Team"] + manage-revenue-streams-instantiate: + groups: ["core-contributor", "demo"] users: [] - allowed_permissions: [create, read, update, delete] - uri: /v1.0/process-models/finance/* + allowed_permissions: [create] + uri: /v1.0/process-models/manage-revenue-streams:product-revenue-streams:customer-contracts-trade-terms/* + manage-revenue-streams-instances: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/manage-revenue-streams:product-revenue-streams:customer-contracts-trade-terms/* - read-all: - groups: [admin, "Project Lead"] + manage-procurement-invoice-instantiate: + groups: ["core-contributor", "demo"] users: [] - allowed_permissions: [read] - uri: /* + allowed_permissions: [create] + uri: /v1.0/process-models/manage-procurement:procurement:core-contributor-invoice-management:* + manage-procurement-invoice-instances: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/manage-procurement:procurement:core-contributor-invoice-management:* - invoice-approval-tasks-read: - groups: ["Finance Team"] + manage-procurement-instantiate: + groups: ["core-contributor", "demo"] users: [] - allowed_permissions: [read] - uri: /v1.0/process-instances/category_number_one:lanes/* + allowed_permissions: [create] + uri: /v1.0/process-models/manage-procurement:vendor-lifecycle-management:* + manage-procurement-instances: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/manage-procurement:vendor-lifecycle-management:* + + core1-admin-models-instantiate: + groups: ["core-contributor"] + users: [] + allowed_permissions: [create] + uri: /v1.0/process-models/misc:category_number_one:process-model-with-form/process-instances + core1-admin-instances: + groups: ["core-contributor"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/misc:category_number_one:process-model-with-form:* + core1-admin-instances-slash: + groups: ["core-contributor"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/misc:category_number_one:process-model-with-form/* diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml index 96a5c1c52..e60946b3c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml @@ -4,20 +4,19 @@ groups: admin: users: [ + admin, jakub, kb, alex, dan, mike, jason, + j, amir, jarrad, elizabeth, jon, natalia, - harmeet, - sasha, - manuchehr, ] Finance Team: @@ -28,60 +27,144 @@ groups: dan, mike, jason, + j, amir, jarrad, elizabeth, jon, natalia, sasha, + fin, + fin1, ] - Project Lead: + demo: users: [ - jakub, - alex, - dan, - mike, - jason, - jarrad, - elizabeth, - jon, - natalia, + core, + fin, + fin1, + harmeet, + sasha, manuchehr, + lead, + lead1 ] - hr: - users: [manuchehr] + core-contributor: + users: + [ + core, + harmeet, + ] permissions: + admin: + groups: [admin] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /* + tasks-crud: groups: [everybody] users: [] allowed_permissions: [create, read, update, delete] uri: /v1.0/tasks/* - admin: - groups: [admin] + # read all for everybody + read-all-process-groups: + groups: [everybody] users: [] - allowed_permissions: [create, read, update, delete, list, instantiate] - uri: /* + allowed_permissions: [read] + uri: /v1.0/process-groups/* + read-all-process-models: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/process-models/* + read-all-process-instance: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/process-instances/* + read-process-instance-reports: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/process-instances/reports/* + processes-read: + groups: [everybody] + users: [] + allowed_permissions: [read] + uri: /v1.0/processes - # TODO: all uris should really have the same structure - finance-admin-group: - groups: ["Finance Team"] + + manage-procurement-admin: + groups: ["Project Lead"] users: [] allowed_permissions: [create, read, update, delete] - uri: /v1.0/process-groups/finance/* + uri: /v1.0/process-groups/manage-procurement:* + manage-procurement-admin-slash: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-groups/manage-procurement/* + manage-procurement-admin-models: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-models/manage-procurement:* + manage-procurement-admin-models-slash: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-models/manage-procurement/* + manage-procurement-admin-instances: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-instances/manage-procurement:* + manage-procurement-admin-instances-slash: + groups: ["Project Lead"] + users: [] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-instances/manage-procurement/* finance-admin: groups: ["Finance Team"] users: [] allowed_permissions: [create, read, update, delete] - uri: /v1.0/process-groups/finance/* + uri: /v1.0/process-groups/manage-procurement:procurement:* - read-all: - groups: ["Finance Team", "Project Lead", hr, admin] + manage-revenue-streams-instantiate: + groups: ["core-contributor", "demo"] users: [] - allowed_permissions: [read] - uri: /* + allowed_permissions: [create] + uri: /v1.0/process-models/manage-revenue-streams:product-revenue-streams:customer-contracts-trade-terms/* + manage-revenue-streams-instances: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/manage-revenue-streams:product-revenue-streams:customer-contracts-trade-terms/* + + manage-procurement-invoice-instantiate: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create] + uri: /v1.0/process-models/manage-procurement:procurement:core-contributor-invoice-management:* + manage-procurement-invoice-instances: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/manage-procurement:procurement:core-contributor-invoice-management:* + + manage-procurement-instantiate: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create] + uri: /v1.0/process-models/manage-procurement:vendor-lifecycle-management:* + manage-procurement-instances: + groups: ["core-contributor", "demo"] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/process-instances/manage-procurement:vendor-lifecycle-management:* diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py b/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py index 97c990004..71adb57c6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py @@ -51,5 +51,8 @@ from spiffworkflow_backend.models.spiff_step_details import ( ) # noqa: F401 from spiffworkflow_backend.models.user import UserModel # noqa: F401 from spiffworkflow_backend.models.group import GroupModel # noqa: F401 +from spiffworkflow_backend.models.process_instance_metadata import ( + ProcessInstanceMetadataModel, +) # noqa: F401 add_listeners() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py index 9e4c3928e..cc8834654 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py @@ -16,8 +16,6 @@ class MessageTriggerableProcessModel(SpiffworkflowBaseDBModel): ForeignKey(MessageModel.id), nullable=False, unique=True ) process_model_identifier: str = db.Column(db.String(50), nullable=False, index=True) - # fixme: Maybe we don't need this anymore? - process_group_identifier: str = db.Column(db.String(50), nullable=False, index=True) updated_at_in_seconds: int = db.Column(db.Integer) created_at_in_seconds: int = db.Column(db.Integer) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py index 14ab3c74c..1439b0459 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py @@ -29,6 +29,7 @@ class ProcessGroup: default_factory=list[ProcessModelInfo] ) process_groups: list[ProcessGroup] = field(default_factory=list["ProcessGroup"]) + parent_groups: list[dict] | None = None def __post_init__(self) -> None: """__post_init__.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 2e94e9949..e6a5f6849 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -1,7 +1,6 @@ """Process_instance.""" from __future__ import annotations -from dataclasses import dataclass from typing import Any from typing import cast @@ -18,12 +17,15 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import validates from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum -from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import TaskSchema from spiffworkflow_backend.models.user import UserModel +class ProcessInstanceNotFoundError(Exception): + """ProcessInstanceNotFoundError.""" + + class NavigationItemSchema(Schema): """NavigationItemSchema.""" @@ -74,7 +76,9 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): process_model_identifier: str = db.Column( db.String(255), nullable=False, index=True ) - process_group_identifier: str = db.Column(db.String(50), nullable=False, index=True) + process_model_display_name: str = db.Column( + db.String(255), nullable=False, index=True + ) process_initiator_id: int = db.Column(ForeignKey(UserModel.id), nullable=False) process_initiator = relationship("UserModel") @@ -103,7 +107,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): return { "id": self.id, "process_model_identifier": self.process_model_identifier, - "process_group_identifier": self.process_group_identifier, + "process_model_display_name": self.process_model_display_name, "status": self.status, "start_in_seconds": self.start_in_seconds, "end_in_seconds": self.end_in_seconds, @@ -112,6 +116,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): "bpmn_version_control_identifier": self.bpmn_version_control_identifier, "bpmn_version_control_type": self.bpmn_version_control_type, "spiff_step": self.spiff_step, + "username": self.process_initiator.username, } @property @@ -140,7 +145,7 @@ class ProcessInstanceModelSchema(Schema): fields = [ "id", "process_model_identifier", - "process_group_identifier", + "process_model_display_name", "process_initiator_id", "start_in_seconds", "end_in_seconds", @@ -166,23 +171,18 @@ class ProcessInstanceApi: status: ProcessInstanceStatus, next_task: Task | None, process_model_identifier: str, - process_group_identifier: str, + process_model_display_name: str, completed_tasks: int, updated_at_in_seconds: int, - is_review: bool, - title: str, ) -> None: """__init__.""" self.id = id self.status = status self.next_task = next_task # The next task that requires user input. - # self.navigation = navigation fixme: would be a hotness. self.process_model_identifier = process_model_identifier - self.process_group_identifier = process_group_identifier + self.process_model_display_name = process_model_display_name self.completed_tasks = completed_tasks self.updated_at_in_seconds = updated_at_in_seconds - self.title = title - self.is_review = is_review class ProcessInstanceApiSchema(Schema): @@ -196,24 +196,15 @@ class ProcessInstanceApiSchema(Schema): "id", "status", "next_task", - "navigation", "process_model_identifier", - "process_group_identifier", + "process_model_display_name", "completed_tasks", "updated_at_in_seconds", - "is_review", - "title", - "study_id", - "state", ] unknown = INCLUDE status = EnumField(ProcessInstanceStatus) next_task = marshmallow.fields.Nested(TaskSchema, dump_only=True, required=False) - navigation = marshmallow.fields.List( - marshmallow.fields.Nested(NavigationItemSchema, dump_only=True) - ) - state = marshmallow.fields.String(allow_none=True) @marshmallow.post_load def make_process_instance( @@ -224,73 +215,11 @@ class ProcessInstanceApiSchema(Schema): "id", "status", "next_task", - "navigation", "process_model_identifier", - "process_group_identifier", + "process_model_display_name", "completed_tasks", "updated_at_in_seconds", - "is_review", - "title", - "study_id", - "state", ] filtered_fields = {key: data[key] for key in keys} filtered_fields["next_task"] = TaskSchema().make_task(data["next_task"]) return ProcessInstanceApi(**filtered_fields) - - -@dataclass -class ProcessInstanceMetadata: - """ProcessInstanceMetadata.""" - - id: int - display_name: str | None = None - description: str | None = None - spec_version: str | None = None - state: str | None = None - status: str | None = None - completed_tasks: int | None = None - is_review: bool | None = None - state_message: str | None = None - process_model_identifier: str | None = None - process_group_id: str | None = None - - @classmethod - def from_process_instance( - cls, process_instance: ProcessInstanceModel, process_model: ProcessModelInfo - ) -> ProcessInstanceMetadata: - """From_process_instance.""" - instance = cls( - id=process_instance.id, - display_name=process_model.display_name, - description=process_model.description, - process_group_id=process_model.process_group, - state_message=process_instance.state_message, - status=process_instance.status, - completed_tasks=process_instance.completed_tasks, - is_review=process_model.is_review, - process_model_identifier=process_instance.process_model_identifier, - ) - return instance - - -class ProcessInstanceMetadataSchema(Schema): - """ProcessInstanceMetadataSchema.""" - - status = EnumField(ProcessInstanceStatus) - - class Meta: - """Meta.""" - - model = ProcessInstanceMetadata - additional = [ - "id", - "display_name", - "description", - "state", - "completed_tasks", - "process_group_id", - "is_review", - "state_message", - ] - unknown = INCLUDE diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py new file mode 100644 index 000000000..5a4d4ca5b --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py @@ -0,0 +1,30 @@ +"""Spiff_step_details.""" +from dataclasses import dataclass + +from flask_bpmn.models.db import db +from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from sqlalchemy import ForeignKey + +from spiffworkflow_backend.models.process_instance import ProcessInstanceModel + + +@dataclass +class ProcessInstanceMetadataModel(SpiffworkflowBaseDBModel): + """ProcessInstanceMetadataModel.""" + + __tablename__ = "process_instance_metadata" + __table_args__ = ( + db.UniqueConstraint( + "process_instance_id", "key", name="process_instance_metadata_unique" + ), + ) + + id: int = db.Column(db.Integer, primary_key=True) + process_instance_id: int = db.Column( + ForeignKey(ProcessInstanceModel.id), nullable=False # type: ignore + ) + key: str = db.Column(db.String(255), nullable=False) + value: str = db.Column(db.String(255), nullable=False) + + updated_at_in_seconds: int = db.Column(db.Integer, nullable=False) + created_at_in_seconds: int = db.Column(db.Integer, nullable=False) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py index 97f4c49c8..5cccf4a59 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py @@ -75,7 +75,7 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel): def add_fixtures(cls) -> None: """Add_fixtures.""" try: - # process_model = ProcessModelService().get_process_model( + # process_model = ProcessModelService.get_process_model( # process_model_id="sartography-admin/ticket" # ) user = UserModel.query.first() @@ -205,7 +205,7 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel): ) -> ProcessInstanceReportModel: """Create_with_attributes.""" # <<<<<<< HEAD - # process_model = ProcessModelService().get_process_model( + # process_model = ProcessModelService.get_process_model( # process_model_id=f"{process_model_identifier}" # ) # process_instance_report = cls( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py index 3ab55d07c..4f5ee2ada 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py @@ -34,10 +34,10 @@ class ProcessModelInfo: primary_file_name: str | None = None primary_process_id: str | None = None display_order: int | None = 0 - is_review: bool = False files: list[File] | None = field(default_factory=list[File]) fault_or_suspend_on_exception: str = NotificationType.fault.value exception_notification_addresses: list[str] = field(default_factory=list) + parent_groups: list[dict] | None = None def __post_init__(self) -> None: """__post_init__.""" @@ -71,7 +71,6 @@ class ProcessModelInfoSchema(Schema): display_order = marshmallow.fields.Integer(allow_none=True) primary_file_name = marshmallow.fields.String(allow_none=True) primary_process_id = marshmallow.fields.String(allow_none=True) - is_review = marshmallow.fields.Boolean(allow_none=True) files = marshmallow.fields.List(marshmallow.fields.Nested("FileSchema")) fault_or_suspend_on_exception = marshmallow.fields.String() exception_notification_addresses = marshmallow.fields.List( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py index e00e7cacf..91d70116a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py @@ -8,6 +8,7 @@ from sqlalchemy import ForeignKey from sqlalchemy.orm import deferred from spiffworkflow_backend.models.group import GroupModel +from spiffworkflow_backend.models.process_instance import ProcessInstanceModel @dataclass @@ -16,7 +17,9 @@ class SpiffStepDetailsModel(SpiffworkflowBaseDBModel): __tablename__ = "spiff_step_details" id: int = db.Column(db.Integer, primary_key=True) - process_instance_id: int = db.Column(db.Integer, nullable=False) + process_instance_id: int = db.Column( + ForeignKey(ProcessInstanceModel.id), nullable=False # type: ignore + ) spiff_step: int = db.Column(db.Integer, nullable=False) task_json: str = deferred(db.Column(db.JSON, nullable=False)) # type: ignore timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py index 2e480f2a4..f1223ae0d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py @@ -27,28 +27,28 @@ ALLOWED_BPMN_EXTENSIONS = {"bpmn", "dmn"} @admin_blueprint.route("/process-groups", methods=["GET"]) -def process_groups_list() -> str: - """Process_groups_list.""" - process_groups = ProcessModelService().get_process_groups() - return render_template("process_groups_list.html", process_groups=process_groups) +def process_group_list() -> str: + """Process_group_list.""" + process_groups = ProcessModelService.get_process_groups() + return render_template("process_group_list.html", process_groups=process_groups) @admin_blueprint.route("/process-groups/", methods=["GET"]) def process_group_show(process_group_id: str) -> str: """Show_process_group.""" - process_group = ProcessModelService().get_process_group(process_group_id) + process_group = ProcessModelService.get_process_group(process_group_id) return render_template("process_group_show.html", process_group=process_group) @admin_blueprint.route("/process-models/", methods=["GET"]) def process_model_show(process_model_id: str) -> Union[str, Response]: """Show_process_model.""" - process_model = ProcessModelService().get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) files = SpecFileService.get_files(process_model, extension_filter="bpmn") current_file_name = process_model.primary_file_name if current_file_name is None: flash("No primary_file_name", "error") - return redirect(url_for("admin.process_groups_list")) + return redirect(url_for("admin.process_group_list")) bpmn_xml = SpecFileService.get_data(process_model, current_file_name) return render_template( "process_model_show.html", @@ -64,7 +64,7 @@ def process_model_show(process_model_id: str) -> Union[str, Response]: ) def process_model_show_file(process_model_id: str, file_name: str) -> str: """Process_model_show_file.""" - process_model = ProcessModelService().get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) bpmn_xml = SpecFileService.get_data(process_model, file_name) files = SpecFileService.get_files(process_model, extension_filter="bpmn") return render_template( @@ -81,8 +81,7 @@ def process_model_show_file(process_model_id: str, file_name: str) -> str: ) def process_model_upload_file(process_model_id: str) -> Response: """Process_model_upload_file.""" - process_model_service = ProcessModelService() - process_model = process_model_service.get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) if "file" not in request.files: flash("No file part", "error") @@ -97,7 +96,7 @@ def process_model_upload_file(process_model_id: str) -> Response: SpecFileService.add_file( process_model, request_file.filename, request_file.stream.read() ) - process_model_service.save_process_model(process_model) + ProcessModelService.save_process_model(process_model) return redirect( url_for("admin.process_model_show", process_model_id=process_model.id) @@ -109,7 +108,7 @@ def process_model_upload_file(process_model_id: str) -> Response: ) def process_model_edit(process_model_id: str, file_name: str) -> str: """Edit_bpmn.""" - process_model = ProcessModelService().get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) bpmn_xml = SpecFileService.get_data(process_model, file_name) return render_template( @@ -125,11 +124,11 @@ def process_model_edit(process_model_id: str, file_name: str) -> str: ) def process_model_save(process_model_id: str, file_name: str) -> Union[str, Response]: """Process_model_save.""" - process_model = ProcessModelService().get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) SpecFileService.update_file(process_model, file_name, request.get_data()) if process_model.primary_file_name is None: flash("No primary_file_name", "error") - return redirect(url_for("admin.process_groups_list")) + return redirect(url_for("admin.process_group_list")) bpmn_xml = SpecFileService.get_data(process_model, process_model.primary_file_name) return render_template( "process_model_edit.html", @@ -143,19 +142,21 @@ def process_model_save(process_model_id: str, file_name: str) -> Union[str, Resp def process_model_run(process_model_id: str) -> Union[str, Response]: """Process_model_run.""" user = UserService.create_user("internal", "Mr. Test", username="Mr. Test") - process_instance = ProcessInstanceService.create_process_instance( - process_model_id, user + process_instance = ( + ProcessInstanceService.create_process_instance_from_process_model_identifier( + process_model_id, user + ) ) processor = ProcessInstanceProcessor(process_instance) processor.do_engine_steps() result = processor.get_data() - process_model = ProcessModelService().get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) files = SpecFileService.get_files(process_model, extension_filter="bpmn") current_file_name = process_model.primary_file_name if current_file_name is None: flash("No primary_file_name", "error") - return redirect(url_for("admin.process_groups_list")) + return redirect(url_for("admin.process_group_list")) bpmn_xml = SpecFileService.get_data(process_model, current_file_name) return render_template( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_groups_list.html b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_group_list.html similarity index 100% rename from spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_groups_list.html rename to spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_group_list.html diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_group_show.html b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_group_show.html index a5fbab887..2a41abe91 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_group_show.html +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/templates/process_group_show.html @@ -3,7 +3,7 @@ {% block content %} diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index 1488b43fe..739e689d2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -30,6 +30,7 @@ from SpiffWorkflow.task import TaskState from sqlalchemy import and_ from sqlalchemy import asc from sqlalchemy import desc +from sqlalchemy.orm import joinedload from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, @@ -63,6 +64,7 @@ from spiffworkflow_backend.models.spec_reference import SpecReferenceSchema from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from spiffworkflow_backend.models.spiff_step_details import SpiffStepDetailsModel from spiffworkflow_backend.models.user import UserModel +from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel from spiffworkflow_backend.routes.user import verify_token from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.error_handling_service import ErrorHandlingService @@ -157,9 +159,8 @@ def un_modify_modified_process_model_id(modified_process_model_id: str) -> str: def process_group_add(body: dict) -> flask.wrappers.Response: """Add_process_group.""" - process_model_service = ProcessModelService() process_group = ProcessGroup(**body) - process_model_service.add_process_group(process_group) + ProcessModelService.add_process_group(process_group) return make_response(jsonify(process_group), 201) @@ -183,20 +184,20 @@ def process_group_update( process_group_id = un_modify_modified_process_model_id(modified_process_group_id) process_group = ProcessGroup(id=process_group_id, **body_filtered) - ProcessModelService().update_process_group(process_group) + ProcessModelService.update_process_group(process_group) return make_response(jsonify(process_group), 200) -def process_groups_list( +def process_group_list( process_group_identifier: Optional[str] = None, page: int = 1, per_page: int = 100 ) -> flask.wrappers.Response: - """Process_groups_list.""" + """Process_group_list.""" if process_group_identifier is not None: - process_groups = ProcessModelService().get_process_groups( + process_groups = ProcessModelService.get_process_groups( process_group_identifier ) else: - process_groups = ProcessModelService().get_process_groups() + process_groups = ProcessModelService.get_process_groups() batch = ProcessModelService().get_batch( items=process_groups, page=page, per_page=per_page ) @@ -222,7 +223,7 @@ def process_group_show( """Process_group_show.""" process_group_id = un_modify_modified_process_model_id(modified_process_group_id) try: - process_group = ProcessModelService().get_process_group(process_group_id) + process_group = ProcessModelService.get_process_group(process_group_id) except ProcessEntityNotFoundError as exception: raise ( ApiError( @@ -231,13 +232,17 @@ def process_group_show( status_code=400, ) ) from exception + + process_group.parent_groups = ProcessModelService.get_parent_group_array( + process_group.id + ) return make_response(jsonify(process_group), 200) def process_group_move( modified_process_group_identifier: str, new_location: str ) -> flask.wrappers.Response: - """process_group_move.""" + """Process_group_move.""" original_process_group_id = un_modify_modified_process_model_id( modified_process_group_identifier ) @@ -268,8 +273,7 @@ def process_model_create( unmodified_process_group_id = un_modify_modified_process_model_id( modified_process_group_id ) - process_model_service = ProcessModelService() - process_group = process_model_service.get_process_group(unmodified_process_group_id) + process_group = ProcessModelService.get_process_group(unmodified_process_group_id) if process_group is None: raise ApiError( error_code="process_model_could_not_be_created", @@ -277,7 +281,7 @@ def process_model_create( status_code=400, ) - process_model_service.add_process_model(process_model_info) + ProcessModelService.add_process_model(process_model_info) return Response( json.dumps(ProcessModelInfoSchema().dump(process_model_info)), status=201, @@ -314,7 +318,7 @@ def process_model_update( # process_model_identifier = f"{process_group_id}/{process_model_id}" process_model = get_process_model(process_model_identifier) - ProcessModelService().update_process_model(process_model, body_filtered) + ProcessModelService.update_process_model(process_model, body_filtered) return ProcessModelInfoSchema().dump(process_model) @@ -329,14 +333,17 @@ def process_model_show(modified_process_model_identifier: str) -> Any: process_model.files = files for file in process_model.files: file.references = SpecFileService.get_references_for_file(file, process_model) - process_model_json = ProcessModelInfoSchema().dump(process_model) - return process_model_json + + process_model.parent_groups = ProcessModelService.get_parent_group_array( + process_model.id + ) + return make_response(jsonify(process_model), 200) def process_model_move( modified_process_model_identifier: str, new_location: str ) -> flask.wrappers.Response: - """process_model_move.""" + """Process_model_move.""" original_process_model_id = un_modify_modified_process_model_id( modified_process_model_identifier ) @@ -349,12 +356,15 @@ def process_model_move( def process_model_list( process_group_identifier: Optional[str] = None, recursive: Optional[bool] = False, + filter_runnable_by_user: Optional[bool] = False, page: int = 1, per_page: int = 100, ) -> flask.wrappers.Response: """Process model list!""" - process_models = ProcessModelService().get_process_models( - process_group_id=process_group_identifier, recursive=recursive + process_models = ProcessModelService.get_process_models( + process_group_id=process_group_identifier, + recursive=recursive, + filter_runnable_by_user=filter_runnable_by_user, ) batch = ProcessModelService().get_batch( process_models, page=page, per_page=per_page @@ -483,8 +493,10 @@ def process_instance_create(modified_process_model_id: str) -> flask.wrappers.Re process_model_identifier = un_modify_modified_process_model_id( modified_process_model_id ) - process_instance = ProcessInstanceService.create_process_instance( - process_model_identifier, g.user + process_instance = ( + ProcessInstanceService.create_process_instance_from_process_model_identifier( + process_model_identifier, g.user + ) ) return Response( json.dumps(ProcessInstanceModelSchema().dump(process_instance)), @@ -494,6 +506,7 @@ def process_instance_create(modified_process_model_id: str) -> flask.wrappers.Re def process_instance_run( + modified_process_model_identifier: str, process_instance_id: int, do_engine_steps: bool = True, ) -> flask.wrappers.Response: @@ -758,6 +771,9 @@ def process_instance_list( end_from: Optional[int] = None, end_to: Optional[int] = None, process_status: Optional[str] = None, + initiated_by_me: Optional[bool] = None, + with_tasks_completed_by_me: Optional[bool] = None, + with_tasks_completed_by_my_group: Optional[bool] = None, user_filter: Optional[bool] = False, report_identifier: Optional[str] = None, ) -> flask.wrappers.Response: @@ -774,6 +790,9 @@ def process_instance_list( end_from, end_to, process_status.split(",") if process_status else None, + initiated_by_me, + with_tasks_completed_by_me, + with_tasks_completed_by_my_group, ) else: report_filter = ( @@ -785,11 +804,19 @@ def process_instance_list( end_from, end_to, process_status, + initiated_by_me, + with_tasks_completed_by_me, + with_tasks_completed_by_my_group, ) ) # process_model_identifier = un_modify_modified_process_model_id(modified_process_model_identifier) process_instance_query = ProcessInstanceModel.query + # Always join that hot user table for good performance at serialization time. + process_instance_query = process_instance_query.options( + joinedload(ProcessInstanceModel.process_initiator) + ) + if report_filter.process_model_identifier is not None: process_model = get_process_model( f"{report_filter.process_model_identifier}", @@ -833,9 +860,81 @@ def process_instance_list( ProcessInstanceModel.status.in_(report_filter.process_status) # type: ignore ) - process_instances = process_instance_query.order_by( - ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore - ).paginate(page=page, per_page=per_page, error_out=False) + if report_filter.initiated_by_me is True: + process_instance_query = process_instance_query.filter( + ProcessInstanceModel.status.in_(["complete", "error", "terminated"]) # type: ignore + ) + process_instance_query = process_instance_query.filter_by( + process_initiator=g.user + ) + + # TODO: not sure if this is exactly what is wanted + if report_filter.with_tasks_completed_by_me is True: + process_instance_query = process_instance_query.filter( + ProcessInstanceModel.status.in_(["complete", "error", "terminated"]) # type: ignore + ) + # process_instance_query = process_instance_query.join(UserModel, UserModel.id == ProcessInstanceModel.process_initiator_id) + # process_instance_query = process_instance_query.add_columns(UserModel.username) + # search for process_instance.UserModel.username in this file for more details about why adding columns is annoying. + + process_instance_query = process_instance_query.filter( + ProcessInstanceModel.process_initiator_id != g.user.id + ) + process_instance_query = process_instance_query.join( + SpiffStepDetailsModel, + ProcessInstanceModel.id == SpiffStepDetailsModel.process_instance_id, + ) + process_instance_query = process_instance_query.join( + SpiffLoggingModel, + ProcessInstanceModel.id == SpiffLoggingModel.process_instance_id, + ) + process_instance_query = process_instance_query.filter( + SpiffLoggingModel.message.contains("COMPLETED") # type: ignore + ) + process_instance_query = process_instance_query.filter( + SpiffLoggingModel.spiff_step == SpiffStepDetailsModel.spiff_step + ) + process_instance_query = process_instance_query.filter( + SpiffStepDetailsModel.completed_by_user_id == g.user.id + ) + + if report_filter.with_tasks_completed_by_my_group is True: + process_instance_query = process_instance_query.filter( + ProcessInstanceModel.status.in_(["complete", "error", "terminated"]) # type: ignore + ) + process_instance_query = process_instance_query.join( + SpiffStepDetailsModel, + ProcessInstanceModel.id == SpiffStepDetailsModel.process_instance_id, + ) + process_instance_query = process_instance_query.join( + SpiffLoggingModel, + ProcessInstanceModel.id == SpiffLoggingModel.process_instance_id, + ) + process_instance_query = process_instance_query.filter( + SpiffLoggingModel.message.contains("COMPLETED") # type: ignore + ) + process_instance_query = process_instance_query.filter( + SpiffLoggingModel.spiff_step == SpiffStepDetailsModel.spiff_step + ) + process_instance_query = process_instance_query.join( + GroupModel, + GroupModel.id == SpiffStepDetailsModel.lane_assignment_id, + ) + process_instance_query = process_instance_query.join( + UserGroupAssignmentModel, + UserGroupAssignmentModel.group_id == GroupModel.id, + ) + process_instance_query = process_instance_query.filter( + UserGroupAssignmentModel.user_id == g.user.id + ) + + process_instances = ( + process_instance_query.group_by(ProcessInstanceModel.id) + .order_by( + ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore + ) + .paginate(page=page, per_page=per_page, error_out=False) + ) results = list( map( @@ -1001,7 +1100,7 @@ def authentication_callback( f"{service}/{auth_method}", response, g.user.id, create_if_not_exists=True ) return redirect( - f"{current_app.config['SPIFFWORKFLOW_FRONTEND_URL']}/admin/authentications" + f"{current_app.config['SPIFFWORKFLOW_FRONTEND_URL']}/admin/configuration" ) @@ -1056,7 +1155,7 @@ def task_list_my_tasks(page: int = 1, per_page: int = 100) -> flask.wrappers.Res # just need this add_columns to add the process_model_identifier. Then add everything back that was removed. .add_columns( ProcessInstanceModel.process_model_identifier, - ProcessInstanceModel.process_group_identifier, + ProcessInstanceModel.process_model_display_name, ProcessInstanceModel.status, ActiveTaskModel.task_name, ActiveTaskModel.task_title, @@ -1197,8 +1296,10 @@ def process_instance_task_list( ) .first() ) - if step_detail is not None: - process_instance.bpmn_json = json.dumps(step_detail.task_json) + if step_detail is not None and process_instance.bpmn_json is not None: + bpmn_json = json.loads(process_instance.bpmn_json) + bpmn_json["tasks"] = step_detail.task_json + process_instance.bpmn_json = json.dumps(bpmn_json) processor = ProcessInstanceProcessor(process_instance) @@ -1318,7 +1419,7 @@ def task_submit( task_id, process_instance, processor=processor ) AuthorizationService.assert_user_can_complete_spiff_task( - processor, spiff_task, principal.user + process_instance.id, spiff_task, principal.user ) if spiff_task.state != TaskState.READY: @@ -1503,7 +1604,7 @@ def get_process_model(process_model_id: str) -> ProcessModelInfo: """Get_process_model.""" process_model = None try: - process_model = ProcessModelService().get_process_model(process_model_id) + process_model = ProcessModelService.get_process_model(process_model_id) except ProcessEntityNotFoundError as exception: raise ( ApiError( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py new file mode 100644 index 000000000..ae5fe00ef --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py @@ -0,0 +1,42 @@ +"""Get_env.""" +from typing import Any + +from flask_bpmn.models.db import db + +from spiffworkflow_backend.models.process_instance_metadata import ( + ProcessInstanceMetadataModel, +) +from spiffworkflow_backend.models.script_attributes_context import ( + ScriptAttributesContext, +) +from spiffworkflow_backend.scripts.script import Script + + +class SaveProcessInstanceMetadata(Script): + """SaveProcessInstanceMetadata.""" + + def get_description(self) -> str: + """Get_description.""" + return """Save a given dict as process instance metadata (useful for creating reports).""" + + def run( + self, + script_attributes_context: ScriptAttributesContext, + *args: Any, + **kwargs: Any, + ) -> Any: + """Run.""" + metadata_dict = args[0] + for key, value in metadata_dict.items(): + pim = ProcessInstanceMetadataModel.query.filter_by( + process_instance_id=script_attributes_context.process_instance_id, + key=key, + ).first() + if pim is None: + pim = ProcessInstanceMetadataModel( + process_instance_id=script_attributes_context.process_instance_id, + key=key, + ) + pim.value = value + db.session.add(pim) + db.session.commit() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index dff7be8c6..81488910e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -30,7 +30,7 @@ def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]: process_instances = [] for i in range(len(statuses)): - process_instance = ProcessInstanceService.create_process_instance( + process_instance = ProcessInstanceService.create_process_instance_from_process_model_identifier( test_process_model_id, user ) process_instance.status = statuses[i] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py index 29ee78845..ea488f7a9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py @@ -24,9 +24,6 @@ from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserNotFoundError from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel from spiffworkflow_backend.services.group_service import GroupService -from spiffworkflow_backend.services.process_instance_processor import ( - ProcessInstanceProcessor, -) from spiffworkflow_backend.services.user_service import UserService @@ -393,25 +390,25 @@ class AuthorizationService: @staticmethod def assert_user_can_complete_spiff_task( - processor: ProcessInstanceProcessor, + process_instance_id: int, spiff_task: SpiffTask, user: UserModel, ) -> bool: """Assert_user_can_complete_spiff_task.""" active_task = ActiveTaskModel.query.filter_by( task_name=spiff_task.task_spec.name, - process_instance_id=processor.process_instance_model.id, + process_instance_id=process_instance_id, ).first() if active_task is None: raise ActiveTaskNotFoundError( f"Could find an active task with task name '{spiff_task.task_spec.name}'" - f" for process instance '{processor.process_instance_model.id}'" + f" for process instance '{process_instance_id}'" ) if user not in active_task.potential_owners: raise UserDoesNotHaveAccessToTaskError( f"User {user.username} does not have access to update task'{spiff_task.task_spec.name}'" - f" for process instance '{processor.process_instance_model.id}'" + f" for process instance '{process_instance_id}'" ) return True diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py index 412c4b82a..c9c0647ed 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py @@ -26,7 +26,7 @@ class DataSetupService: current_app.logger.debug("DataSetupService.save_all_process_models() start") failing_process_models = [] - process_models = ProcessModelService().get_process_models() + process_models = ProcessModelService.get_process_models(recursive=True) SpecFileService.clear_caches() for process_model in process_models: current_app.logger.debug(f"Process Model: {process_model.display_name}") diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py index 99e4fbe8c..1e8b38f2d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py @@ -34,7 +34,7 @@ class ErrorHandlingService: self, _processor: ProcessInstanceProcessor, _error: Union[ApiError, Exception] ) -> None: """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception.""" - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( _processor.process_model_identifier ) if process_model.fault_or_suspend_on_exception == "suspend": diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py index 216a66a58..cfb42c836 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py @@ -117,7 +117,7 @@ class MessageService: user: UserModel, ) -> ProcessInstanceModel: """Process_message_triggerable_process_model.""" - process_instance_receive = ProcessInstanceService.create_process_instance( + process_instance_receive = ProcessInstanceService.create_process_instance_from_process_model_identifier( message_triggerable_process_model.process_model_identifier, user, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index 80887a6eb..9b6ed01b9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -349,7 +349,9 @@ class ProcessInstanceProcessor: check_sub_specs(test_spec, 5) self.process_model_identifier = process_instance_model.process_model_identifier - # self.process_group_identifier = process_instance_model.process_group_identifier + self.process_model_display_name = ( + process_instance_model.process_model_display_name + ) try: self.bpmn_process_instance = self.__get_bpmn_process_instance( @@ -374,7 +376,7 @@ class ProcessInstanceProcessor: cls, process_model_identifier: str ) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]: """Get_process_model_and_subprocesses.""" - process_model_info = ProcessModelService().get_process_model( + process_model_info = ProcessModelService.get_process_model( process_model_identifier ) if process_model_info is None: @@ -540,13 +542,8 @@ class ProcessInstanceProcessor: """SaveSpiffStepDetails.""" bpmn_json = self.serialize() wf_json = json.loads(bpmn_json) - task_json = "{}" - if "tasks" in wf_json: - task_json = json.dumps(wf_json["tasks"]) + task_json = wf_json["tasks"] - # TODO want to just save the tasks, something wasn't immediately working - # so after the flow works with the full wf_json revisit this - task_json = wf_json return { "process_instance_id": self.process_instance_model.id, "spiff_step": self.process_instance_model.spiff_step or 1, @@ -593,16 +590,12 @@ class ProcessInstanceProcessor: if self.bpmn_process_instance.is_completed(): self.process_instance_model.end_in_seconds = round(time.time()) - active_tasks = ActiveTaskModel.query.filter_by( - process_instance_id=self.process_instance_model.id - ).all() - if len(active_tasks) > 0: - for at in active_tasks: - db.session.delete(at) - db.session.add(self.process_instance_model) db.session.commit() + active_tasks = ActiveTaskModel.query.filter_by( + process_instance_id=self.process_instance_model.id + ).all() ready_or_waiting_tasks = self.get_all_ready_or_waiting_tasks() for ready_or_waiting_task in ready_or_waiting_tasks: # filter out non-usertasks @@ -629,27 +622,41 @@ class ProcessInstanceProcessor: if process_model_info is not None: process_model_display_name = process_model_info.display_name - active_task = ActiveTaskModel( - process_instance_id=self.process_instance_model.id, - process_model_display_name=process_model_display_name, - form_file_name=form_file_name, - ui_form_file_name=ui_form_file_name, - task_id=str(ready_or_waiting_task.id), - task_name=ready_or_waiting_task.task_spec.name, - task_title=ready_or_waiting_task.task_spec.description, - task_type=ready_or_waiting_task.task_spec.__class__.__name__, - task_status=ready_or_waiting_task.get_state_name(), - lane_assignment_id=potential_owner_hash["lane_assignment_id"], - ) - db.session.add(active_task) - db.session.commit() + active_task = None + for at in active_tasks: + if at.task_id == str(ready_or_waiting_task.id): + active_task = at + active_tasks.remove(at) - for potential_owner_id in potential_owner_hash["potential_owner_ids"]: - active_task_user = ActiveTaskUserModel( - user_id=potential_owner_id, active_task_id=active_task.id + if active_task is None: + active_task = ActiveTaskModel( + process_instance_id=self.process_instance_model.id, + process_model_display_name=process_model_display_name, + form_file_name=form_file_name, + ui_form_file_name=ui_form_file_name, + task_id=str(ready_or_waiting_task.id), + task_name=ready_or_waiting_task.task_spec.name, + task_title=ready_or_waiting_task.task_spec.description, + task_type=ready_or_waiting_task.task_spec.__class__.__name__, + task_status=ready_or_waiting_task.get_state_name(), + lane_assignment_id=potential_owner_hash["lane_assignment_id"], ) - db.session.add(active_task_user) - db.session.commit() + db.session.add(active_task) + db.session.commit() + + for potential_owner_id in potential_owner_hash[ + "potential_owner_ids" + ]: + active_task_user = ActiveTaskUserModel( + user_id=potential_owner_id, active_task_id=active_task.id + ) + db.session.add(active_task_user) + db.session.commit() + + if len(active_tasks) > 0: + for at in active_tasks: + db.session.delete(at) + db.session.commit() @staticmethod def get_parser() -> MyCustomParser: @@ -662,7 +669,7 @@ class ProcessInstanceProcessor: bpmn_process_identifier: str, ) -> Optional[str]: """Backfill_missing_spec_reference_records.""" - process_models = ProcessModelService().get_process_models(recursive=True) + process_models = ProcessModelService.get_process_models(recursive=True) for process_model in process_models: try: refs = SpecFileService.reference_map( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index 9c398514b..fc5a93da4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -18,6 +18,9 @@ class ProcessInstanceReportFilter: end_from: Optional[int] = None end_to: Optional[int] = None process_status: Optional[list[str]] = None + initiated_by_me: Optional[bool] = None + with_tasks_completed_by_me: Optional[bool] = None + with_tasks_completed_by_my_group: Optional[bool] = None def to_dict(self) -> dict[str, str]: """To_dict.""" @@ -35,6 +38,16 @@ class ProcessInstanceReportFilter: d["end_to"] = str(self.end_to) if self.process_status is not None: d["process_status"] = ",".join(self.process_status) + if self.initiated_by_me is not None: + d["initiated_by_me"] = str(self.initiated_by_me).lower() + if self.with_tasks_completed_by_me is not None: + d["with_tasks_completed_by_me"] = str( + self.with_tasks_completed_by_me + ).lower() + if self.with_tasks_completed_by_my_group is not None: + d["with_tasks_completed_by_my_group"] = str( + self.with_tasks_completed_by_my_group + ).lower() return d @@ -63,48 +76,61 @@ class ProcessInstanceReportService: "columns": [ {"Header": "id", "accessor": "id"}, { - "Header": "process_model_identifier", - "accessor": "process_model_identifier", + "Header": "process_model_display_name", + "accessor": "process_model_display_name", }, {"Header": "start_in_seconds", "accessor": "start_in_seconds"}, {"Header": "end_in_seconds", "accessor": "end_in_seconds"}, + {"Header": "username", "accessor": "username"}, {"Header": "status", "accessor": "status"}, ], }, "system_report_instances_initiated_by_me": { "columns": [ + {"Header": "id", "accessor": "id"}, { - "Header": "process_model_identifier", - "accessor": "process_model_identifier", + "Header": "process_model_display_name", + "accessor": "process_model_display_name", }, {"Header": "start_in_seconds", "accessor": "start_in_seconds"}, - {"Header": "id", "accessor": "id"}, {"Header": "end_in_seconds", "accessor": "end_in_seconds"}, {"Header": "status", "accessor": "status"}, ], + "filter_by": [{"field_name": "initiated_by_me", "field_value": True}], }, "system_report_instances_with_tasks_completed_by_me": { "columns": [ - {"Header": "start_in_seconds", "accessor": "start_in_seconds"}, - {"Header": "end_in_seconds", "accessor": "end_in_seconds"}, - {"Header": "status", "accessor": "status"}, {"Header": "id", "accessor": "id"}, { - "Header": "process_model_identifier", - "accessor": "process_model_identifier", + "Header": "process_model_display_name", + "accessor": "process_model_display_name", }, + {"Header": "start_in_seconds", "accessor": "start_in_seconds"}, + {"Header": "end_in_seconds", "accessor": "end_in_seconds"}, + {"Header": "username", "accessor": "username"}, + {"Header": "status", "accessor": "status"}, + ], + "filter_by": [ + {"field_name": "with_tasks_completed_by_me", "field_value": True} ], }, "system_report_instances_with_tasks_completed_by_my_groups": { "columns": [ + {"Header": "id", "accessor": "id"}, { - "Header": "process_model_identifier", - "accessor": "process_model_identifier", + "Header": "process_model_display_name", + "accessor": "process_model_display_name", }, {"Header": "start_in_seconds", "accessor": "start_in_seconds"}, {"Header": "end_in_seconds", "accessor": "end_in_seconds"}, + {"Header": "username", "accessor": "username"}, {"Header": "status", "accessor": "status"}, - {"Header": "id", "accessor": "id"}, + ], + "filter_by": [ + { + "field_name": "with_tasks_completed_by_my_group", + "field_value": True, + } ], }, } @@ -112,7 +138,7 @@ class ProcessInstanceReportService: process_instance_report = ProcessInstanceReportModel( identifier=report_identifier, created_by_id=user.id, - report_metadata=temp_system_metadata_map[report_identifier], + report_metadata=temp_system_metadata_map[report_identifier], # type: ignore ) return process_instance_report # type: ignore @@ -138,6 +164,10 @@ class ProcessInstanceReportService: """Filter_from_metadata.""" filters = cls.filter_by_to_dict(process_instance_report) + def bool_value(key: str) -> Optional[bool]: + """Bool_value.""" + return bool(filters[key]) if key in filters else None + def int_value(key: str) -> Optional[int]: """Int_value.""" return int(filters[key]) if key in filters else None @@ -152,6 +182,11 @@ class ProcessInstanceReportService: end_from = int_value("end_from") end_to = int_value("end_to") process_status = list_value("process_status") + initiated_by_me = bool_value("initiated_by_me") + with_tasks_completed_by_me = bool_value("with_tasks_completed_by_me") + with_tasks_completed_by_my_group = bool_value( + "with_tasks_completed_by_my_group" + ) report_filter = ProcessInstanceReportFilter( process_model_identifier, @@ -160,6 +195,9 @@ class ProcessInstanceReportService: end_from, end_to, process_status, + initiated_by_me, + with_tasks_completed_by_me, + with_tasks_completed_by_my_group, ) return report_filter @@ -174,6 +212,9 @@ class ProcessInstanceReportService: end_from: Optional[int] = None, end_to: Optional[int] = None, process_status: Optional[str] = None, + initiated_by_me: Optional[bool] = None, + with_tasks_completed_by_me: Optional[bool] = None, + with_tasks_completed_by_my_group: Optional[bool] = None, ) -> ProcessInstanceReportFilter: """Filter_from_metadata_with_overrides.""" report_filter = cls.filter_from_metadata(process_instance_report) @@ -190,5 +231,13 @@ class ProcessInstanceReportService: report_filter.end_to = end_to if process_status is not None: report_filter.process_status = process_status.split(",") + if initiated_by_me is not None: + report_filter.initiated_by_me = initiated_by_me + if with_tasks_completed_by_me is not None: + report_filter.with_tasks_completed_by_me = with_tasks_completed_by_me + if with_tasks_completed_by_my_group is not None: + report_filter.with_tasks_completed_by_my_group = ( + with_tasks_completed_by_my_group + ) return report_filter diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index 3c81e1b12..f98eaae18 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -12,6 +12,7 @@ from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus +from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.task import MultiInstanceType from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.user import UserModel @@ -28,9 +29,10 @@ class ProcessInstanceService: TASK_STATE_LOCKED = "locked" - @staticmethod + @classmethod def create_process_instance( - process_model_identifier: str, + cls, + process_model: ProcessModelInfo, user: UserModel, ) -> ProcessInstanceModel: """Get_process_instance_from_spec.""" @@ -38,8 +40,8 @@ class ProcessInstanceService: process_instance_model = ProcessInstanceModel( status=ProcessInstanceStatus.not_started.value, process_initiator=user, - process_model_identifier=process_model_identifier, - process_group_identifier="", + process_model_identifier=process_model.id, + process_model_display_name=process_model.display_name, start_in_seconds=round(time.time()), bpmn_version_control_type="git", bpmn_version_control_identifier=current_git_revision, @@ -48,6 +50,16 @@ class ProcessInstanceService: db.session.commit() return process_instance_model + @classmethod + def create_process_instance_from_process_model_identifier( + cls, + process_model_identifier: str, + user: UserModel, + ) -> ProcessInstanceModel: + """Create_process_instance_from_process_model_identifier.""" + process_model = ProcessModelService.get_process_model(process_model_identifier) + return cls.create_process_instance(process_model, user) + @staticmethod def do_waiting() -> None: """Do_waiting.""" @@ -88,20 +100,15 @@ class ProcessInstanceService: process_model = process_model_service.get_process_model( processor.process_model_identifier ) - is_review_value = process_model.is_review if process_model else False - title_value = process_model.display_name if process_model else "" + process_model.display_name if process_model else "" process_instance_api = ProcessInstanceApi( id=processor.get_process_instance_id(), status=processor.get_status(), next_task=None, - # navigation=navigation, process_model_identifier=processor.process_model_identifier, - process_group_identifier="", - # total_tasks=len(navigation), + process_model_display_name=processor.process_model_display_name, completed_tasks=processor.process_instance_model.completed_tasks, updated_at_in_seconds=processor.process_instance_model.updated_at_in_seconds, - is_review=is_review_value, - title=title_value, ) next_task_trying_again = next_task @@ -197,7 +204,7 @@ class ProcessInstanceService: a multi-instance task. """ AuthorizationService.assert_user_can_complete_spiff_task( - processor, spiff_task, user + processor.process_instance_model.id, spiff_task, user ) dot_dct = ProcessInstanceService.create_dot_dict(data) @@ -320,12 +327,13 @@ class ProcessInstanceService: def serialize_flat_with_task_data( process_instance: ProcessInstanceModel, ) -> dict[str, Any]: + """NOTE: This is crazy slow. Put the latest task data in the database.""" """Serialize_flat_with_task_data.""" - results = {} - try: - processor = ProcessInstanceProcessor(process_instance) - process_instance.data = processor.get_current_data() - results = process_instance.serialized_flat - except ApiError: - results = process_instance.serialized + # results = {} + # try: + # processor = ProcessInstanceProcessor(process_instance) + # process_instance.data = processor.get_current_data() + # results = process_instance.serialized_flat + # except ApiError: + results = process_instance.serialized return results diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py index f9788658f..f009af688 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py @@ -18,7 +18,9 @@ from spiffworkflow_backend.models.process_group import ProcessGroupSchema from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema +from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.file_system_service import FileSystemService +from spiffworkflow_backend.services.user_service import UserService T = TypeVar("T") @@ -35,20 +37,54 @@ class ProcessModelService(FileSystemService): GROUP_SCHEMA = ProcessGroupSchema() PROCESS_MODEL_SCHEMA = ProcessModelInfoSchema() - def is_group(self, path: str) -> bool: + @classmethod + def is_group(cls, path: str) -> bool: """Is_group.""" - group_json_path = os.path.join(path, self.PROCESS_GROUP_JSON_FILE) + group_json_path = os.path.join(path, cls.PROCESS_GROUP_JSON_FILE) if os.path.exists(group_json_path): return True return False - def is_model(self, path: str) -> bool: + @classmethod + def is_group_identifier(cls, process_group_identifier: str) -> bool: + """Is_group_identifier.""" + if os.path.exists(FileSystemService.root_path()): + process_group_path = os.path.abspath( + os.path.join( + FileSystemService.root_path(), + FileSystemService.id_string_to_relative_path( + process_group_identifier + ), + ) + ) + return cls.is_group(process_group_path) + + return False + + @classmethod + def is_model(cls, path: str) -> bool: """Is_model.""" - model_json_path = os.path.join(path, self.PROCESS_MODEL_JSON_FILE) + model_json_path = os.path.join(path, cls.PROCESS_MODEL_JSON_FILE) if os.path.exists(model_json_path): return True return False + @classmethod + def is_model_identifier(cls, process_model_identifier: str) -> bool: + """Is_model_identifier.""" + if os.path.exists(FileSystemService.root_path()): + process_model_path = os.path.abspath( + os.path.join( + FileSystemService.root_path(), + FileSystemService.id_string_to_relative_path( + process_model_identifier + ), + ) + ) + return cls.is_model(process_model_path) + + return False + @staticmethod def write_json_file( file_path: str, json_data: dict, indent: int = 4, sort_keys: bool = True @@ -68,37 +104,38 @@ class ProcessModelService(FileSystemService): end = start + per_page return items[start:end] - def add_process_model(self, process_model: ProcessModelInfo) -> None: + @classmethod + def add_process_model(cls, process_model: ProcessModelInfo) -> None: """Add_spec.""" - display_order = self.next_display_order(process_model) - process_model.display_order = display_order - self.save_process_model(process_model) + cls.save_process_model(process_model) + @classmethod def update_process_model( - self, process_model: ProcessModelInfo, attributes_to_update: dict + cls, process_model: ProcessModelInfo, attributes_to_update: dict ) -> None: """Update_spec.""" for atu_key, atu_value in attributes_to_update.items(): if hasattr(process_model, atu_key): setattr(process_model, atu_key, atu_value) - self.save_process_model(process_model) + cls.save_process_model(process_model) - def save_process_model(self, process_model: ProcessModelInfo) -> None: + @classmethod + def save_process_model(cls, process_model: ProcessModelInfo) -> None: """Save_process_model.""" process_model_path = os.path.abspath( os.path.join(FileSystemService.root_path(), process_model.id) ) os.makedirs(process_model_path, exist_ok=True) json_path = os.path.abspath( - os.path.join(process_model_path, self.PROCESS_MODEL_JSON_FILE) + os.path.join(process_model_path, cls.PROCESS_MODEL_JSON_FILE) ) process_model_id = process_model.id # we don't save id in the json file # this allows us to move models around on the filesystem # the id is determined by its location on the filesystem delattr(process_model, "id") - json_data = self.PROCESS_MODEL_SCHEMA.dump(process_model) - self.write_json_file(json_path, json_data) + json_data = cls.PROCESS_MODEL_SCHEMA.dump(process_model) + cls.write_json_file(json_path, json_data) process_model.id = process_model_id def process_model_delete(self, process_model_id: str) -> None: @@ -119,7 +156,7 @@ class ProcessModelService(FileSystemService): def process_model_move( self, original_process_model_id: str, new_location: str ) -> ProcessModelInfo: - """process_model_move.""" + """Process_model_move.""" original_model_path = os.path.abspath( os.path.join(FileSystemService.root_path(), original_process_model_id) ) @@ -138,11 +175,11 @@ class ProcessModelService(FileSystemService): ) -> ProcessModelInfo: """Get_process_model_from_relative_path.""" process_group_identifier, _ = os.path.split(relative_path) - process_group = cls().get_process_group(process_group_identifier) path = os.path.join(FileSystemService.root_path(), relative_path) - return cls().__scan_process_model(path, process_group=process_group) + return cls.__scan_process_model(path) - def get_process_model(self, process_model_id: str) -> ProcessModelInfo: + @classmethod + def get_process_model(cls, process_model_id: str) -> ProcessModelInfo: """Get a process model from a model and group id. process_model_id is the full path to the model--including groups. @@ -153,33 +190,16 @@ class ProcessModelService(FileSystemService): model_path = os.path.abspath( os.path.join(FileSystemService.root_path(), process_model_id) ) - if self.is_model(model_path): - process_model = self.get_process_model_from_relative_path(process_model_id) - return process_model - - # group_path, model_id = os.path.split(process_model_id) - # if group_path is not None: - # process_group = self.get_process_group(group_path) - # if process_group is not None: - # for process_model in process_group.process_models: - # if process_model_id == process_model.id: - # return process_model - # with os.scandir(FileSystemService.root_path()) as process_group_dirs: - # for item in process_group_dirs: - # process_group_dir = item - # if item.is_dir(): - # with os.scandir(item.path) as spec_dirs: - # for sd in spec_dirs: - # if sd.name == process_model_id: - # # Now we have the process_group directory, and spec directory - # process_group = self.__scan_process_group( - # process_group_dir - # ) - # return self.__scan_process_model(sd.path, sd.name, process_group) + if cls.is_model(model_path): + return cls.get_process_model_from_relative_path(process_model_id) raise ProcessEntityNotFoundError("process_model_not_found") + @classmethod def get_process_models( - self, process_group_id: Optional[str] = None, recursive: Optional[bool] = False + cls, + process_group_id: Optional[str] = None, + recursive: Optional[bool] = False, + filter_runnable_by_user: Optional[bool] = False, ) -> List[ProcessModelInfo]: """Get process models.""" process_models = [] @@ -196,22 +216,56 @@ class ProcessModelService(FileSystemService): process_model_relative_path = os.path.relpath( file, start=FileSystemService.root_path() ) - process_model = self.get_process_model_from_relative_path( + process_model = cls.get_process_model_from_relative_path( os.path.dirname(process_model_relative_path) ) process_models.append(process_model) process_models.sort() + + if filter_runnable_by_user: + user = UserService.current_user() + new_process_model_list = [] + for process_model in process_models: + uri = f"/v1.0/process-models/{process_model.id.replace('/', ':')}/process-instances" + result = AuthorizationService.user_has_permission( + user=user, permission="create", target_uri=uri + ) + if result: + new_process_model_list.append(process_model) + return new_process_model_list + return process_models + @classmethod + def get_parent_group_array(cls, process_identifier: str) -> list[dict]: + """Get_parent_group_array.""" + full_group_id_path = None + parent_group_array = [] + for process_group_id_segment in process_identifier.split("/")[0:-1]: + if full_group_id_path is None: + full_group_id_path = process_group_id_segment + else: + full_group_id_path = f"{full_group_id_path}/{process_group_id_segment}" # type: ignore + parent_group = ProcessModelService.get_process_group(full_group_id_path) + if parent_group: + parent_group_array.append( + {"id": parent_group.id, "display_name": parent_group.display_name} + ) + return parent_group_array + + @classmethod def get_process_groups( - self, process_group_id: Optional[str] = None + cls, process_group_id: Optional[str] = None ) -> list[ProcessGroup]: - """Returns the process_groups as a list in display order.""" - process_groups = self.__scan_process_groups(process_group_id) + """Returns the process_groups.""" + process_groups = cls.__scan_process_groups(process_group_id) process_groups.sort() return process_groups - def get_process_group(self, process_group_id: str) -> ProcessGroup: + @classmethod + def get_process_group( + cls, process_group_id: str, find_direct_nested_items: bool = True + ) -> ProcessGroup: """Look for a given process_group, and return it.""" if os.path.exists(FileSystemService.root_path()): process_group_path = os.path.abspath( @@ -220,48 +274,38 @@ class ProcessModelService(FileSystemService): FileSystemService.id_string_to_relative_path(process_group_id), ) ) - if self.is_group(process_group_path): - return self.__scan_process_group(process_group_path) - # nested_groups = [] - # process_group_dir = os.scandir(process_group_path) - # for item in process_group_dir: - # if self.is_group(item.path): - # nested_group = self.get_process_group(os.path.join(process_group_path, item.path)) - # nested_groups.append(nested_group) - # elif self.is_model(item.path): - # print("get_process_group: ") - # return self.__scan_process_group(process_group_path) - # with os.scandir(FileSystemService.root_path()) as directory_items: - # for item in directory_items: - # if item.is_dir() and item.name == process_group_id: - # return self.__scan_process_group(item) + if cls.is_group(process_group_path): + return cls.find_or_create_process_group( + process_group_path, + find_direct_nested_items=find_direct_nested_items, + ) raise ProcessEntityNotFoundError( "process_group_not_found", f"Process Group Id: {process_group_id}" ) - def add_process_group(self, process_group: ProcessGroup) -> ProcessGroup: + @classmethod + def add_process_group(cls, process_group: ProcessGroup) -> ProcessGroup: """Add_process_group.""" - display_order = len(self.get_process_groups()) - process_group.display_order = display_order - return self.update_process_group(process_group) + return cls.update_process_group(process_group) - def update_process_group(self, process_group: ProcessGroup) -> ProcessGroup: + @classmethod + def update_process_group(cls, process_group: ProcessGroup) -> ProcessGroup: """Update_process_group.""" - cat_path = self.process_group_path(process_group.id) + cat_path = cls.process_group_path(process_group.id) os.makedirs(cat_path, exist_ok=True) - json_path = os.path.join(cat_path, self.PROCESS_GROUP_JSON_FILE) + json_path = os.path.join(cat_path, cls.PROCESS_GROUP_JSON_FILE) serialized_process_group = process_group.serialized # we don't store `id` in the json files # this allows us to move groups around on the filesystem del serialized_process_group["id"] - self.write_json_file(json_path, serialized_process_group) + cls.write_json_file(json_path, serialized_process_group) return process_group def process_group_move( self, original_process_group_id: str, new_location: str ) -> ProcessGroup: - """process_group_move.""" + """Process_group_move.""" original_group_path = self.process_group_path(original_process_group_id) original_root, original_group_id = os.path.split(original_group_path) new_root = f"{FileSystemService.root_path()}/{new_location}" @@ -278,7 +322,7 @@ class ProcessModelService(FileSystemService): for _root, dirs, _files in os.walk(group_path): for dir in dirs: model_dir = os.path.join(group_path, dir) - if ProcessModelService().is_model(model_dir): + if ProcessModelService.is_model(model_dir): process_model = self.get_process_model(model_dir) all_nested_models.append(process_model) return all_nested_models @@ -314,8 +358,9 @@ class ProcessModelService(FileSystemService): index += 1 return process_groups + @classmethod def __scan_process_groups( - self, process_group_id: Optional[str] = None + cls, process_group_id: Optional[str] = None ) -> list[ProcessGroup]: """__scan_process_groups.""" if not os.path.exists(FileSystemService.root_path()): @@ -329,14 +374,17 @@ class ProcessModelService(FileSystemService): process_groups = [] for item in directory_items: # if item.is_dir() and not item.name[0] == ".": - if item.is_dir() and self.is_group(item): # type: ignore - scanned_process_group = self.__scan_process_group(item.path) + if item.is_dir() and cls.is_group(item): # type: ignore + scanned_process_group = cls.find_or_create_process_group(item.path) process_groups.append(scanned_process_group) return process_groups - def __scan_process_group(self, dir_path: str) -> ProcessGroup: + @classmethod + def find_or_create_process_group( + cls, dir_path: str, find_direct_nested_items: bool = True + ) -> ProcessGroup: """Reads the process_group.json file, and any nested directories.""" - cat_path = os.path.join(dir_path, self.PROCESS_GROUP_JSON_FILE) + cat_path = os.path.join(dir_path, cls.PROCESS_GROUP_JSON_FILE) if os.path.exists(cat_path): with open(cat_path) as cat_json: data = json.load(cat_json) @@ -357,40 +405,41 @@ class ProcessModelService(FileSystemService): display_order=10000, admin=False, ) - self.write_json_file(cat_path, self.GROUP_SCHEMA.dump(process_group)) + cls.write_json_file(cat_path, cls.GROUP_SCHEMA.dump(process_group)) # we don't store `id` in the json files, so we add it in here process_group.id = process_group_id - with os.scandir(dir_path) as nested_items: - process_group.process_models = [] - process_group.process_groups = [] - for nested_item in nested_items: - if nested_item.is_dir(): - # TODO: check whether this is a group or model - if self.is_group(nested_item.path): - # This is a nested group - process_group.process_groups.append( - self.__scan_process_group(nested_item.path) - ) - elif self.is_model(nested_item.path): - process_group.process_models.append( - self.__scan_process_model( - nested_item.path, - nested_item.name, - process_group=process_group, + + if find_direct_nested_items: + with os.scandir(dir_path) as nested_items: + process_group.process_models = [] + process_group.process_groups = [] + for nested_item in nested_items: + if nested_item.is_dir(): + # TODO: check whether this is a group or model + if cls.is_group(nested_item.path): + # This is a nested group + process_group.process_groups.append( + cls.find_or_create_process_group(nested_item.path) ) - ) - process_group.process_models.sort() - # process_group.process_groups.sort() + elif ProcessModelService.is_model(nested_item.path): + process_group.process_models.append( + cls.__scan_process_model( + nested_item.path, + nested_item.name, + ) + ) + process_group.process_models.sort() + # process_group.process_groups.sort() return process_group + @classmethod def __scan_process_model( - self, + cls, path: str, name: Optional[str] = None, - process_group: Optional[ProcessGroup] = None, ) -> ProcessModelInfo: """__scan_process_model.""" - json_file_path = os.path.join(path, self.PROCESS_MODEL_JSON_FILE) + json_file_path = os.path.join(path, cls.PROCESS_MODEL_JSON_FILE) if os.path.exists(json_file_path): with open(json_file_path) as wf_json: @@ -418,13 +467,10 @@ class ProcessModelService(FileSystemService): display_name=name, description="", display_order=0, - is_review=False, ) - self.write_json_file( - json_file_path, self.PROCESS_MODEL_SCHEMA.dump(process_model_info) + cls.write_json_file( + json_file_path, cls.PROCESS_MODEL_SCHEMA.dump(process_model_info) ) # we don't store `id` in the json files, so we add it in here process_model_info.id = name - if process_group: - process_model_info.process_group = process_group.id return process_model_info diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py index 41ee22b2d..e4dee4913 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py @@ -65,7 +65,7 @@ class SecretService: def update_secret( key: str, value: str, - user_id: int, + user_id: Optional[int] = None, create_if_not_exists: Optional[bool] = False, ) -> None: """Does this pass pre commit?""" @@ -79,6 +79,12 @@ class SecretService: db.session.rollback() raise e elif create_if_not_exists: + if user_id is None: + raise ApiError( + error_code="update_secret_error_no_user_id", + message=f"Cannot update secret with key: {key}. Missing user id.", + status_code=404, + ) SecretService.add_secret(key=key, value=value, user_id=user_id) else: raise ApiError( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py index 97ce1495a..15e25a759 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py @@ -8,6 +8,7 @@ from flask import g from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.secret_service import SecretService +from spiffworkflow_backend.services.user_service import UserService class ConnectorProxyError(Exception): @@ -65,7 +66,8 @@ class ServiceTaskDelegate: secret_key = parsed_response["auth"] refreshed_token_set = json.dumps(parsed_response["refreshed_token_set"]) - SecretService().update_secret(secret_key, refreshed_token_set, g.user.id) + user_id = g.user.id if UserService.has_user() else None + SecretService().update_secret(secret_key, refreshed_token_set, user_id) return json.dumps(parsed_response["api_response"]) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py index f02e3a6f1..c69f41c30 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -171,12 +171,11 @@ class SpecFileService(FileSystemService): ref.is_primary = True if ref.is_primary: - ProcessModelService().update_process_model( + ProcessModelService.update_process_model( process_model_info, { "primary_process_id": ref.identifier, "primary_file_name": file_name, - "is_review": ref.has_lanes, }, ) SpecFileService.update_caches(ref) @@ -322,7 +321,6 @@ class SpecFileService(FileSystemService): message_triggerable_process_model = MessageTriggerableProcessModel( message_model_id=message_model.id, process_model_identifier=ref.process_model_id, - process_group_identifier="process_group_identifier", ) db.session.add(message_triggerable_process_model) db.session.commit() @@ -330,8 +328,6 @@ class SpecFileService(FileSystemService): if ( message_triggerable_process_model.process_model_identifier != ref.process_model_id - # or message_triggerable_process_model.process_group_identifier - # != process_model_info.process_group_id ): raise ValidationException( f"Message model is already used to start process model {ref.process_model_id}" diff --git a/spiffworkflow-backend/tests/data/save_process_instance_metadata/save_process_instance_metadata.bpmn b/spiffworkflow-backend/tests/data/save_process_instance_metadata/save_process_instance_metadata.bpmn new file mode 100644 index 000000000..2c72b08d1 --- /dev/null +++ b/spiffworkflow-backend/tests/data/save_process_instance_metadata/save_process_instance_metadata.bpmn @@ -0,0 +1,52 @@ + + + + + Flow_1j4jzft + + + + Flow_01xr2ac + + + Flow_1j4jzft + Flow_10xyk22 + save_process_instance_metadata({"key1": "value1"}) + + + + Flow_10xyk22 + Flow_01xr2ac + save_process_instance_metadata({"key2": "value2", "key3": "value3"}) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py index 44c99908c..8d56853b4 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py @@ -140,7 +140,7 @@ class BaseTest: process_group_path = os.path.abspath( os.path.join(FileSystemService.root_path(), process_group_id) ) - if ProcessModelService().is_group(process_group_path): + if ProcessModelService.is_group(process_group_path): if exception_notification_addresses is None: exception_notification_addresses = [] @@ -149,7 +149,6 @@ class BaseTest: id=process_model_id, display_name=process_model_display_name, description=process_model_description, - is_review=False, primary_process_id=primary_process_id, primary_file_name=primary_file_name, fault_or_suspend_on_exception=fault_or_suspend_on_exception, @@ -253,6 +252,17 @@ class BaseTest: There must be an existing process model to instantiate. """ + if not ProcessModelService.is_model_identifier(test_process_model_id): + dirname = os.path.dirname(test_process_model_id) + if not ProcessModelService.is_group_identifier(dirname): + process_group = ProcessGroup(id=dirname, display_name=dirname) + ProcessModelService.add_process_group(process_group) + basename = os.path.basename(test_process_model_id) + load_test_spec( + process_model_id=test_process_model_id, + process_model_source_directory=basename, + bpmn_file_name=basename, + ) modified_process_model_id = test_process_model_id.replace("/", ":") response = client.post( f"/v1.0/process-models/{modified_process_model_id}/process-instances", @@ -284,7 +294,7 @@ class BaseTest: status=status, process_initiator=user, process_model_identifier=process_model.id, - process_group_identifier="", + process_model_display_name=process_model.display_name, updated_at_in_seconds=round(time.time()), start_in_seconds=current_time - (3600 * 1), end_in_seconds=current_time - (3600 * 1 - 20), @@ -347,3 +357,16 @@ class BaseTest: target_uri=target_uri, ) assert has_permission is expected_result + + def modify_process_identifier_for_path_param(self, identifier: str) -> str: + """Identifier.""" + if "\\" in identifier: + raise Exception(f"Found backslash in identifier: {identifier}") + + return identifier.replace("/", ":") + + def un_modify_modified_process_identifier_for_path_param( + self, modified_identifier: str + ) -> str: + """Un_modify_modified_process_model_id.""" + return modified_identifier.replace(":", "/") diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py index befd2602a..4b0ee5fca 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py @@ -36,10 +36,8 @@ class ExampleDataLoader: display_name=display_name, description=description, display_order=display_order, - is_review=False, ) - workflow_spec_service = ProcessModelService() - workflow_spec_service.add_process_model(spec) + ProcessModelService.add_process_model(spec) bpmn_file_name_with_extension = bpmn_file_name if not bpmn_file_name_with_extension: @@ -88,7 +86,7 @@ class ExampleDataLoader: ) spec.primary_process_id = references[0].identifier spec.primary_file_name = filename - ProcessModelService().save_process_model(spec) + ProcessModelService.save_process_model(spec) finally: if file: file.close() diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py index 97dafaf3f..2f56d1d6c 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py @@ -51,7 +51,7 @@ class TestLoggingService(BaseTest): assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=headers, ) assert response.status_code == 200 diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py index 3a12acf6d..3983f9be8 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py @@ -46,7 +46,7 @@ class TestNestedGroups(BaseTest): process_instance_id = response.json["id"] client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) process_instance = ProcessInstanceService().get_process_instance( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py index ef65dfbe3..5ee5ae9f2 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -133,12 +133,12 @@ class TestProcessApi(BaseTest): process_model_description=model_description, user=with_super_admin_user, ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_identifier, ) assert model_display_name == process_model.display_name assert 0 == process_model.display_order - assert 1 == len(ProcessModelService().get_process_groups()) + assert 1 == len(ProcessModelService.get_process_groups()) # add bpmn file to the model bpmn_file_name = "sample.bpmn" @@ -155,9 +155,7 @@ class TestProcessApi(BaseTest): user=with_super_admin_user, ) # get the model, assert that primary is set - process_model = ProcessModelService().get_process_model( - process_model_identifier - ) + process_model = ProcessModelService.get_process_model(process_model_identifier) assert process_model.primary_file_name == bpmn_file_name assert process_model.primary_process_id == "sample" @@ -208,9 +206,7 @@ class TestProcessApi(BaseTest): headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 - process_model = ProcessModelService().get_process_model( - process_model_identifier - ) + process_model = ProcessModelService.get_process_model(process_model_identifier) assert process_model.primary_file_name == bpmn_file_name assert process_model.primary_process_id == terminal_primary_process_id @@ -236,9 +232,7 @@ class TestProcessApi(BaseTest): ) # assert we have a model - process_model = ProcessModelService().get_process_model( - process_model_identifier - ) + process_model = ProcessModelService.get_process_model(process_model_identifier) assert process_model is not None assert process_model.id == process_model_identifier @@ -254,7 +248,7 @@ class TestProcessApi(BaseTest): # assert we no longer have a model with pytest.raises(ProcessEntityNotFoundError): - ProcessModelService().get_process_model(process_model_identifier) + ProcessModelService.get_process_model(process_model_identifier) def test_process_model_delete_with_instances( self, @@ -327,19 +321,15 @@ class TestProcessApi(BaseTest): process_model_id=process_model_identifier, user=with_super_admin_user, ) - process_model = ProcessModelService().get_process_model( - process_model_identifier - ) + process_model = ProcessModelService.get_process_model(process_model_identifier) assert process_model.id == process_model_identifier assert process_model.display_name == "Cooooookies" - assert process_model.is_review is False assert process_model.primary_file_name is None assert process_model.primary_process_id is None process_model.display_name = "Updated Display Name" process_model.primary_file_name = "superduper.bpmn" process_model.primary_process_id = "superduper" - process_model.is_review = True # not in the include list, so get ignored modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.put( @@ -353,7 +343,6 @@ class TestProcessApi(BaseTest): assert response.json["display_name"] == "Updated Display Name" assert response.json["primary_file_name"] == "superduper.bpmn" assert response.json["primary_process_id"] == "superduper" - assert response.json["is_review"] is False def test_process_model_list_all( self, @@ -550,7 +539,7 @@ class TestProcessApi(BaseTest): assert result.description == "Test Description" # Check what is persisted - persisted = ProcessModelService().get_process_group("test") + persisted = ProcessModelService.get_process_group("test") assert persisted.display_name == "Another Test Category" assert persisted.id == "test" assert persisted.description == "Test Description" @@ -572,7 +561,7 @@ class TestProcessApi(BaseTest): process_group_id, display_name=process_group_display_name, ) - persisted = ProcessModelService().get_process_group(process_group_id) + persisted = ProcessModelService.get_process_group(process_group_id) assert persisted is not None assert persisted.id == process_group_id @@ -582,7 +571,7 @@ class TestProcessApi(BaseTest): ) with pytest.raises(ProcessEntityNotFoundError): - ProcessModelService().get_process_group(process_group_id) + ProcessModelService.get_process_group(process_group_id) def test_process_group_update( self, @@ -598,7 +587,7 @@ class TestProcessApi(BaseTest): self.create_process_group( client, with_super_admin_user, group_id, display_name=group_display_name ) - process_group = ProcessModelService().get_process_group(group_id) + process_group = ProcessModelService.get_process_group(group_id) assert process_group.display_name == group_display_name @@ -612,7 +601,7 @@ class TestProcessApi(BaseTest): ) assert response.status_code == 200 - process_group = ProcessModelService().get_process_group(group_id) + process_group = ProcessModelService.get_process_group(group_id) assert process_group.display_name == "Modified Display Name" def test_process_group_list( @@ -979,6 +968,43 @@ class TestProcessApi(BaseTest): assert response.json is not None assert response.json["id"] == process_group_id assert response.json["process_models"][0]["id"] == process_model_identifier + assert response.json["parent_groups"] == [] + + def test_get_process_group_show_when_nested( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_get_process_group_show_when_nested.""" + self.create_group_and_model_with_bpmn( + client=client, + user=with_super_admin_user, + process_group_id="test_group_one", + process_model_id="simple_form", + bpmn_file_location="simple_form", + ) + + self.create_group_and_model_with_bpmn( + client=client, + user=with_super_admin_user, + process_group_id="test_group_one/test_group_two", + process_model_id="call_activity_nested", + bpmn_file_location="call_activity_nested", + ) + + response = client.get( + "/v1.0/process-groups/test_group_one:test_group_two", + headers=self.logged_in_headers(with_super_admin_user), + ) + + assert response.status_code == 200 + assert response.json is not None + assert response.json["id"] == "test_group_one/test_group_two" + assert response.json["parent_groups"] == [ + {"display_name": "test_group_one", "id": "test_group_one"} + ] def test_get_process_model_when_found( self, @@ -997,11 +1023,15 @@ class TestProcessApi(BaseTest): f"/v1.0/process-models/{modified_process_model_identifier}", headers=self.logged_in_headers(with_super_admin_user), ) + assert response.status_code == 200 assert response.json is not None assert response.json["id"] == process_model_identifier assert len(response.json["files"]) == 1 assert response.json["files"][0]["name"] == "random_fact.bpmn" + assert response.json["parent_groups"] == [ + {"display_name": "test_group", "id": "test_group"} + ] def test_get_process_model_when_not_found( self, @@ -1069,7 +1099,7 @@ class TestProcessApi(BaseTest): assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1101,7 +1131,9 @@ class TestProcessApi(BaseTest): process_group_id=process_group_id, process_model_id=process_model_id, ) - modified_process_model_identifier = process_model_identifier.replace("/", ":") + modified_process_model_identifier = ( + self.modify_process_identifier_for_path_param(process_model_identifier) + ) headers = self.logged_in_headers(with_super_admin_user) create_response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers @@ -1109,7 +1141,7 @@ class TestProcessApi(BaseTest): assert create_response.json is not None process_instance_id = create_response.json["id"] client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{modified_process_model_identifier}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) show_response = client.get( @@ -1212,7 +1244,7 @@ class TestProcessApi(BaseTest): process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1272,7 +1304,7 @@ class TestProcessApi(BaseTest): process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -1320,7 +1352,7 @@ class TestProcessApi(BaseTest): process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None @@ -1359,7 +1391,7 @@ class TestProcessApi(BaseTest): process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1516,7 +1548,7 @@ class TestProcessApi(BaseTest): status=ProcessInstanceStatus[statuses[i]].value, process_initiator=with_super_admin_user, process_model_identifier=process_model_identifier, - process_group_identifier="test_process_group_id", + process_model_display_name=process_model_identifier, updated_at_in_seconds=round(time.time()), start_in_seconds=(1000 * i) + 1000, end_in_seconds=(1000 * i) + 2000, @@ -1818,7 +1850,7 @@ class TestProcessApi(BaseTest): assert process.status == "not_started" response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 400 @@ -1862,10 +1894,8 @@ class TestProcessApi(BaseTest): process_instance_id = self.setup_testing_instance( client, process_model_identifier, with_super_admin_user ) - process_model = ProcessModelService().get_process_model( - process_model_identifier - ) - ProcessModelService().update_process_model( + process_model = ProcessModelService.get_process_model(process_model_identifier) + ProcessModelService.update_process_model( process_model, {"fault_or_suspend_on_exception": NotificationType.suspend.value}, ) @@ -1879,7 +1909,7 @@ class TestProcessApi(BaseTest): assert process.status == "not_started" response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 400 @@ -1917,10 +1947,8 @@ class TestProcessApi(BaseTest): client, process_model_identifier, with_super_admin_user ) - process_model = ProcessModelService().get_process_model( - process_model_identifier - ) - ProcessModelService().update_process_model( + process_model = ProcessModelService.get_process_model(process_model_identifier) + ProcessModelService.update_process_model( process_model, {"exception_notification_addresses": ["with_super_admin_user@example.com"]}, ) @@ -1929,7 +1957,7 @@ class TestProcessApi(BaseTest): with mail.record_messages() as outbox: response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 400 @@ -2114,7 +2142,7 @@ class TestProcessApi(BaseTest): assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(initiator_user), ) assert response.status_code == 200 @@ -2319,7 +2347,7 @@ class TestProcessApi(BaseTest): process_instance_id = response.json["id"] client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -2339,7 +2367,7 @@ class TestProcessApi(BaseTest): # TODO: Why can I run a suspended process instance? response = client.post( - f"/v1.0/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -2408,7 +2436,7 @@ class TestProcessApi(BaseTest): def setup_initial_groups_for_move_tests( self, client: FlaskClient, with_super_admin_user: UserModel ) -> None: - """setup_initial_groups_for_move_tests.""" + """Setup_initial_groups_for_move_tests.""" groups = ["group_a", "group_b", "group_b/group_bb"] # setup initial groups for group in groups: @@ -2417,7 +2445,7 @@ class TestProcessApi(BaseTest): ) # make sure initial groups exist for group in groups: - persisted = ProcessModelService().get_process_group(group) + persisted = ProcessModelService.get_process_group(group) assert persisted is not None assert persisted.id == group @@ -2428,7 +2456,7 @@ class TestProcessApi(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """test_move_model.""" + """Test_move_model.""" self.setup_initial_groups_for_move_tests(client, with_super_admin_user) process_model_id = "test_model" @@ -2443,7 +2471,7 @@ class TestProcessApi(BaseTest): process_model_display_name=process_model_id, process_model_description=process_model_id, ) - persisted = ProcessModelService().get_process_model(original_process_model_path) + persisted = ProcessModelService.get_process_model(original_process_model_path) assert persisted is not None assert persisted.id == original_process_model_path @@ -2463,11 +2491,11 @@ class TestProcessApi(BaseTest): # make sure the original model does not exist with pytest.raises(ProcessEntityNotFoundError) as e: - ProcessModelService().get_process_model(original_process_model_path) + ProcessModelService.get_process_model(original_process_model_path) assert e.value.args[0] == "process_model_not_found" # make sure the new model does exist - new_process_model = ProcessModelService().get_process_model( + new_process_model = ProcessModelService.get_process_model( new_process_model_path ) assert new_process_model is not None @@ -2480,7 +2508,7 @@ class TestProcessApi(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """test_move_group.""" + """Test_move_group.""" self.setup_initial_groups_for_move_tests(client, with_super_admin_user) # add sub group to `group_a` @@ -2491,7 +2519,7 @@ class TestProcessApi(BaseTest): client, with_super_admin_user, original_sub_path, display_name=sub_group_id ) # make sure original subgroup exists - persisted = ProcessModelService().get_process_group(original_sub_path) + persisted = ProcessModelService.get_process_group(original_sub_path) assert persisted is not None assert persisted.id == original_sub_path @@ -2508,11 +2536,11 @@ class TestProcessApi(BaseTest): # make sure the original subgroup does not exist with pytest.raises(ProcessEntityNotFoundError) as e: - ProcessModelService().get_process_group(original_sub_path) + ProcessModelService.get_process_group(original_sub_path) assert e.value.args[0] == "process_group_not_found" assert e.value.args[1] == f"Process Group Id: {original_sub_path}" # make sure the new subgroup does exist - new_process_group = ProcessModelService().get_process_group(new_sub_path) + new_process_group = ProcessModelService.get_process_group(new_sub_path) assert new_process_group.id == new_sub_path diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py index 071ef6ccd..c71f67f23 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -52,7 +52,7 @@ class SecretServiceTestHelpers(BaseTest): process_model_description=self.test_process_model_description, user=user, ) - process_model_info = ProcessModelService().get_process_model( + process_model_info = ProcessModelService.get_process_model( process_model_identifier ) return process_model_info diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_save_process_instance_metadata.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_save_process_instance_metadata.py new file mode 100644 index 000000000..96eb62970 --- /dev/null +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_save_process_instance_metadata.py @@ -0,0 +1,45 @@ +"""Test_get_localtime.""" +from flask.app import Flask +from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + +from spiffworkflow_backend.models.process_instance_metadata import ( + ProcessInstanceMetadataModel, +) +from spiffworkflow_backend.models.user import UserModel +from spiffworkflow_backend.services.process_instance_processor import ( + ProcessInstanceProcessor, +) + + +class TestSaveProcessInstanceMetadata(BaseTest): + """TestSaveProcessInstanceMetadata.""" + + def test_can_save_process_instance_metadata( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_can_save_process_instance_metadata.""" + initiator_user = self.find_or_create_user("initiator_user") + self.create_process_group( + client, with_super_admin_user, "test_group", "test_group" + ) + process_model = load_test_spec( + process_model_id="save_process_instance_metadata/save_process_instance_metadata", + bpmn_file_name="save_process_instance_metadata.bpmn", + process_model_source_directory="save_process_instance_metadata", + ) + process_instance = self.create_process_instance_from_process_model( + process_model=process_model, user=initiator_user + ) + processor = ProcessInstanceProcessor(process_instance) + processor.do_engine_steps(save=True) + + process_instance_metadata = ProcessInstanceMetadataModel.query.filter_by( + process_instance_id=process_instance.id + ).all() + assert len(process_instance_metadata) == 3 diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py index 1d5157123..c738c7f69 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py @@ -1,13 +1,38 @@ """Test_acceptance_test_fixtures.""" +import os + from flask.app import Flask +from spiffworkflow_backend.models.process_group import ProcessGroup +from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.acceptance_test_fixtures import ( load_acceptance_test_fixtures, ) +from spiffworkflow_backend.services.process_model_service import ProcessModelService def test_start_dates_are_one_hour_apart(app: Flask) -> None: """Test_start_dates_are_one_hour_apart.""" + process_model_identifier = ( + "misc/acceptance-tests-group-one/acceptance-tests-model-1" + ) + group_identifier = os.path.dirname(process_model_identifier) + parent_group_identifier = os.path.dirname(group_identifier) + if not ProcessModelService.is_group(parent_group_identifier): + process_group = ProcessGroup( + id=parent_group_identifier, display_name=parent_group_identifier + ) + ProcessModelService.add_process_group(process_group) + if not ProcessModelService.is_group(group_identifier): + process_group = ProcessGroup(id=group_identifier, display_name=group_identifier) + ProcessModelService.add_process_group(process_group) + if not ProcessModelService.is_model(process_model_identifier): + process_model = ProcessModelInfo( + id=process_model_identifier, + display_name=process_model_identifier, + description="hey", + ) + ProcessModelService.add_process_model(process_model) process_instances = load_acceptance_test_fixtures() assert len(process_instances) > 2 diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py index 36f077435..00622a1f7 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py @@ -113,7 +113,7 @@ class TestAuthorizationService(BaseTest): bpmn_file_location="model_with_lanes", ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py index 0292032ee..2c091eeb1 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -44,7 +44,7 @@ class TestMessageInstance(BaseTest): client, with_super_admin_user ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model( @@ -81,7 +81,7 @@ class TestMessageInstance(BaseTest): client, with_super_admin_user ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model( @@ -127,7 +127,7 @@ class TestMessageInstance(BaseTest): client, with_super_admin_user ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model( @@ -174,7 +174,7 @@ class TestMessageInstance(BaseTest): client, with_super_admin_user ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py index aa1f28053..c012e287a 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py @@ -47,7 +47,7 @@ class TestMessageService(BaseTest): bpmn_file_name="message_sender.bpmn", ) - process_instance_sender = ProcessInstanceService.create_process_instance( + process_instance_sender = ProcessInstanceService.create_process_instance_from_process_model_identifier( process_model_sender.id, with_super_admin_user, ) @@ -154,7 +154,7 @@ class TestMessageService(BaseTest): user = self.find_or_create_user() - process_instance_sender = ProcessInstanceService.create_process_instance( + process_instance_sender = ProcessInstanceService.create_process_instance_from_process_model_identifier( process_model_sender.id, user, # process_group_identifier=process_model_sender.process_group_id, diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py index 6c3ad0ade..5cf8945f2 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py @@ -9,8 +9,7 @@ def test_there_is_at_least_one_group_after_we_create_one( app: Flask, with_db_and_bpmn_file_cleanup: None ) -> None: """Test_there_is_at_least_one_group_after_we_create_one.""" - process_model_service = ProcessModelService() process_group = ProcessGroup(id="hey", display_name="sure") - process_model_service.add_process_group(process_group) - process_groups = ProcessModelService().get_process_groups() + ProcessModelService.add_process_group(process_group) + process_groups = ProcessModelService.get_process_groups() assert len(process_groups) > 0 diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py index f0de77aa7..3e0107957 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py @@ -161,6 +161,7 @@ class TestProcessInstanceProcessor(BaseTest): ) processor = ProcessInstanceProcessor(process_instance) processor.do_engine_steps(save=True) + processor.save() assert len(process_instance.active_tasks) == 1 active_task = process_instance.active_tasks[0] @@ -241,3 +242,42 @@ class TestProcessInstanceProcessor(BaseTest): ) assert process_instance.status == ProcessInstanceStatus.complete.value + + def test_does_not_recreate_active_tasks_on_multiple_saves( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_sets_permission_correctly_on_active_task_when_using_dict.""" + self.create_process_group( + client, with_super_admin_user, "test_group", "test_group" + ) + initiator_user = self.find_or_create_user("initiator_user") + finance_user_three = self.find_or_create_user("testuser3") + assert initiator_user.principal is not None + assert finance_user_three.principal is not None + AuthorizationService.import_permissions_from_yaml_file() + + finance_group = GroupModel.query.filter_by(identifier="Finance Team").first() + assert finance_group is not None + + process_model = load_test_spec( + process_model_id="test_group/model_with_lanes", + bpmn_file_name="lanes_with_owner_dict.bpmn", + process_model_source_directory="model_with_lanes", + ) + process_instance = self.create_process_instance_from_process_model( + process_model=process_model, user=initiator_user + ) + processor = ProcessInstanceProcessor(process_instance) + processor.do_engine_steps(save=True) + assert len(process_instance.active_tasks) == 1 + initial_active_task_id = process_instance.active_tasks[0].id + + # save again to ensure we go attempt to process the active tasks again + processor.save() + + assert len(process_instance.active_tasks) == 1 + assert initial_active_task_id == process_instance.active_tasks[0].id diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py index 7127eb415..7392bdfdd 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py @@ -32,7 +32,7 @@ class TestProcessModelService(BaseTest): primary_process_id = process_model.primary_process_id assert primary_process_id == "Process_HelloWorld" - ProcessModelService().update_process_model( + ProcessModelService.update_process_model( process_model, {"display_name": "new_name"} ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py index 9f5c5f8a9..3cc353b52 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -188,7 +188,7 @@ class TestSpecFileService(BaseTest): # , # process_model_source_directory="call_activity_nested", # ) - process_model_info = ProcessModelService().get_process_model( + process_model_info = ProcessModelService.get_process_model( process_model_identifier ) files = SpecFileService.get_files(process_model_info) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py index aa91fcfd3..26656143a 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py @@ -28,7 +28,7 @@ class TestVariousBpmnConstructs(BaseTest): "timer_intermediate_catch_event", ) - process_model = ProcessModelService().get_process_model( + process_model = ProcessModelService.get_process_model( process_model_id=process_model_identifier ) diff --git a/spiffworkflow-frontend/cypress/e2e/process_groups.cy.js b/spiffworkflow-frontend/cypress/e2e/process_groups.cy.js index 85ab9b824..bef0e5603 100644 --- a/spiffworkflow-frontend/cypress/e2e/process_groups.cy.js +++ b/spiffworkflow-frontend/cypress/e2e/process_groups.cy.js @@ -19,18 +19,12 @@ describe('process-groups', () => { cy.url().should('include', `process-groups/${groupId}`); cy.contains(`Process Group: ${groupDisplayName}`); - cy.contains('Edit process group').click(); + cy.getBySel('edit-process-group-button').click(); cy.get('input[name=display_name]').clear().type(newGroupDisplayName); cy.contains('Submit').click(); cy.contains(`Process Group: ${newGroupDisplayName}`); - cy.contains('Edit process group').click(); - cy.get('input[name=display_name]').should( - 'have.value', - newGroupDisplayName - ); - - cy.contains('Delete').click(); + cy.getBySel('delete-process-group-button').click(); cy.contains('Are you sure'); cy.getBySel('delete-process-group-button-modal-confirmation-dialog') .find('.cds--btn--danger') diff --git a/spiffworkflow-frontend/cypress/e2e/process_models.cy.js b/spiffworkflow-frontend/cypress/e2e/process_models.cy.js index 4bc75ead7..4fd1b4810 100644 --- a/spiffworkflow-frontend/cypress/e2e/process_models.cy.js +++ b/spiffworkflow-frontend/cypress/e2e/process_models.cy.js @@ -1,4 +1,4 @@ -import { modifyProcessModelPath } from '../../src/helpers'; +import { modifyProcessIdentifierForPathParam } from '../../src/helpers'; describe('process-models', () => { beforeEach(() => { @@ -16,25 +16,22 @@ describe('process-models', () => { const modelDisplayName = `Test Model 2 ${id}`; const modelId = `test-model-2-${id}`; const newModelDisplayName = `${modelDisplayName} edited`; - cy.contains('Misc').click(); + cy.contains('99-Shared Resources').click(); cy.wait(500); cy.contains(groupDisplayName).click(); cy.createModel(groupId, modelId, modelDisplayName); cy.url().should( 'include', - `process-models/${modifyProcessModelPath(groupId)}:${modelId}` + `process-models/${modifyProcessIdentifierForPathParam( + groupId + )}:${modelId}` ); cy.contains(`Process Model: ${modelDisplayName}`); - cy.contains('Edit process model').click(); + cy.getBySel('edit-process-model-button').click(); cy.get('input[name=display_name]').clear().type(newModelDisplayName); cy.contains('Submit').click(); - cy.contains(`Process Model: ${groupId}/${modelId}`); - cy.contains('Submit').click(); - cy.get('input[name=display_name]').should( - 'have.value', - newModelDisplayName - ); + cy.contains(`Process Model: ${newModelDisplayName}`); // go back to process model show by clicking on the breadcrumb cy.contains(modelId).click(); @@ -46,7 +43,7 @@ describe('process-models', () => { .click(); cy.url().should( 'include', - `process-groups/${modifyProcessModelPath(groupId)}` + `process-groups/${modifyProcessIdentifierForPathParam(groupId)}` ); cy.contains(modelId).should('not.exist'); }); @@ -64,15 +61,17 @@ describe('process-models', () => { const dmnFileName = `dmn_test_file_${id}`; const jsonFileName = `json_test_file_${id}`; - cy.contains('Misc').click(); + cy.contains('99-Shared Resources').click(); cy.wait(500); cy.contains(groupDisplayName).click(); cy.createModel(groupId, modelId, modelDisplayName); cy.contains(directParentGroupId).click(); - cy.contains(modelId).click(); + cy.contains(modelDisplayName).click(); cy.url().should( 'include', - `process-models/${modifyProcessModelPath(groupId)}:${modelId}` + `process-models/${modifyProcessIdentifierForPathParam( + groupId + )}:${modelId}` ); cy.contains(`Process Model: ${modelDisplayName}`); cy.contains(`${bpmnFileName}.bpmn`).should('not.exist'); @@ -135,8 +134,12 @@ describe('process-models', () => { cy.getBySel('delete-process-model-button-modal-confirmation-dialog') .find('.cds--btn--danger') .click(); - cy.url().should('include', `process-groups/${modifyProcessModelPath(groupId)}`); + cy.url().should( + 'include', + `process-groups/${modifyProcessIdentifierForPathParam(groupId)}` + ); cy.contains(modelId).should('not.exist'); + cy.contains(modelDisplayName).should('not.exist'); }); it('can upload and run a bpmn file', () => { @@ -148,17 +151,19 @@ describe('process-models', () => { const modelDisplayName = `Test Model 2 ${id}`; const modelId = `test-model-2-${id}`; cy.contains('Add a process group'); - cy.contains('Misc').click(); + cy.contains('99-Shared Resources').click(); cy.wait(500); cy.contains(groupDisplayName).click(); cy.createModel(groupId, modelId, modelDisplayName); cy.contains(`${directParentGroupId}`).click(); cy.contains('Add a process model'); - cy.contains(modelId).click(); + cy.contains(modelDisplayName).click(); cy.url().should( 'include', - `process-models/${modifyProcessModelPath(groupId)}:${modelId}` + `process-models/${modifyProcessIdentifierForPathParam( + groupId + )}:${modelId}` ); cy.contains(`Process Model: ${modelDisplayName}`); @@ -190,17 +195,19 @@ describe('process-models', () => { .click(); cy.url().should( 'include', - `process-groups/${modifyProcessModelPath(groupId)}` + `process-groups/${modifyProcessIdentifierForPathParam(groupId)}` ); cy.contains(modelId).should('not.exist'); + cy.contains(modelDisplayName).should('not.exist'); }); - it('can paginate items', () => { - cy.contains('Misc').click(); - cy.wait(500); - cy.contains('Acceptance Tests Group One').click(); - cy.basicPaginationTest(); - }); + // process models no longer has pagination post-tiles + // it.only('can paginate items', () => { + // cy.contains('99-Shared Resources').click(); + // cy.wait(500); + // cy.contains('Acceptance Tests Group One').click(); + // cy.basicPaginationTest(); + // }); it('can allow searching for model', () => { cy.getBySel('process-model-selection').click().type('model-3'); diff --git a/spiffworkflow-frontend/cypress/support/commands.js b/spiffworkflow-frontend/cypress/support/commands.js index 60ffd7913..f0034168c 100644 --- a/spiffworkflow-frontend/cypress/support/commands.js +++ b/spiffworkflow-frontend/cypress/support/commands.js @@ -1,5 +1,5 @@ import { string } from 'prop-types'; -import { modifyProcessModelPath } from '../../src/helpers'; +import { modifyProcessIdentifierForPathParam } from '../../src/helpers'; // *********************************************** // This example commands.js shows you how to @@ -78,8 +78,7 @@ Cypress.Commands.add('createModel', (groupId, modelId, modelDisplayName) => { cy.url().should( 'include', - `process-models/${modifyProcessModelPath(groupId)}:${modelId}` - // `process-models/${groupId}:${modelId}` + `process-models/${modifyProcessIdentifierForPathParam(groupId)}:${modelId}` ); cy.contains(`Process Model: ${modelDisplayName}`); }); @@ -104,12 +103,12 @@ Cypress.Commands.add( 'navigateToProcessModel', (groupDisplayName, modelDisplayName, modelIdentifier) => { cy.navigateToAdmin(); - cy.contains('Misc').click(); - cy.contains(`Process Group: 99-Misc`, { timeout: 10000 }); + cy.contains('99-Shared Resources').click(); + cy.contains(`Process Group: 99-Shared Resources`, { timeout: 10000 }); cy.contains(groupDisplayName).click(); cy.contains(`Process Group: ${groupDisplayName}`); // https://stackoverflow.com/q/51254946/6090676 - cy.getBySel('process-model-show-link').contains(modelIdentifier).click(); + cy.getBySel('process-model-show-link').contains(modelDisplayName).click(); cy.contains(`Process Model: ${modelDisplayName}`); } ); @@ -133,8 +132,3 @@ Cypress.Commands.add('assertAtLeastOneItemInPaginatedResults', () => { Cypress.Commands.add('assertNoItemInPaginatedResults', () => { cy.contains(/\b0–0 of 0 items/); }); - -Cypress.Commands.add('modifyProcessModelPath', (path) => { - path.replace('/', ':'); - return path; -}); diff --git a/spiffworkflow-frontend/package-lock.json b/spiffworkflow-frontend/package-lock.json index f31017c8c..ba2339983 100644 --- a/spiffworkflow-frontend/package-lock.json +++ b/spiffworkflow-frontend/package-lock.json @@ -7980,7 +7980,7 @@ }, "node_modules/bpmn-js-spiffworkflow": { "version": "0.0.8", - "resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#e92f48da7cb4416310af71bb1699caaca87324cd", + "resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#aca23dc56e5d37aa1ed0a3cf11acb55f76a36da7", "license": "MIT", "dependencies": { "inherits": "^2.0.4", @@ -37138,7 +37138,7 @@ } }, "bpmn-js-spiffworkflow": { - "version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#e92f48da7cb4416310af71bb1699caaca87324cd", + "version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#aca23dc56e5d37aa1ed0a3cf11acb55f76a36da7", "from": "bpmn-js-spiffworkflow@sartography/bpmn-js-spiffworkflow#main", "requires": { "inherits": "^2.0.4", diff --git a/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx b/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx index fe6652951..2d0fe26a7 100644 --- a/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx +++ b/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx @@ -8,6 +8,8 @@ export default function MyCompletedInstances() { filtersEnabled={false} paginationQueryParamPrefix={paginationQueryParamPrefix} perPageOptions={[2, 5, 25]} + reportIdentifier="system_report_instances_initiated_by_me" + showReports={false} /> ); } diff --git a/spiffworkflow-frontend/src/components/NavigationBar.tsx b/spiffworkflow-frontend/src/components/NavigationBar.tsx index 5c5ee9665..47e0de998 100644 --- a/spiffworkflow-frontend/src/components/NavigationBar.tsx +++ b/spiffworkflow-frontend/src/components/NavigationBar.tsx @@ -163,6 +163,7 @@ export default function NavigationBar() { {configurationElement()}