...
This page describes algorithms that are used to assign capabilities to a user and role, capability sets to a user, and role.
Capability Relation Management
Role
Capability assignment process
safeCreate
flag is used only internally, for outside requests a user must always assign a set of new capability ids, if not - an update operation allows the creation and delete capabilities in a single request
Image Removed Expand |
---|
title | Role-Capability assignment PlantUML |
---|
|
Code Block |
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam Capabilities and capability sets are assigned individuallyExample:
There is a capability: foo.item.view [endpoints: GET /foo/item/{id}]
, foo.item.create [endpoints: POST /foo/item]
, foo.item.update [endpoints: PUT /foo/item/{id}]
and capability set foo.item.manage
uniting foo.item.view
, foo.item.create
and foo.item.update
.
Usage Scenarios
Scenario #1 (role-capability and role-capabilitySet management)
User assigned capability set foo.item.manage
to a role Foo management role (sampleRoleId)
. The following resources will be created:
Entities in mod-roles-keycloak
database:
policy: [policyId, 'Policy for role: sampleRoleId']
roleCapabilitySet: [policyId, fooItemManageCapabilitySetId]
Entities in Keycloak:
Policy: [policyId, 'Policy for role: sampleRoleId']
Permission: [name: 'GET access for role: sampleRoleId to /foo/item/{id}', scope: 'GET', resource: '/foo/item/{id}', policy: policyId]
Permission: [name: 'POST access for role: sampleRoleId to /foo/item', scope: 'POST', resource: '/foo/item', policy: policyId]
Permission: [PUT access for role: sampleRoleId to /foo/item/{id}, scope: 'GET', resource: '/foo/item/{id}', policy: policyId]
Then a user assigns explicitly foo.item.view
capability to a role with a sampleRoleId
. The following resources will be created:
Entities in mod-roles-keycloak
database:
Info |
---|
Note that keycloak entities are not affected, because permission: Permission: [name: 'GET access for role: sampleRoleId to /foo/item/{id}', scope: 'GET', resource: '/foo/item/{id}', policy: policyId] already exists |
Then a user removes assignment foo.item.manage
from a role with a sampleRoleId
. The following resources will be deleted:
Entities in mod-roles-keycloak
database:
Entities in Keycloak:
Permission: [name: 'POST access for role: sampleRoleId to /foo/item', scope: 'POST', resource: '/foo/item', policy: policyId]
Permission: [PUT access for role: sampleRoleId to /foo/item/{id}, scope: 'GET', resource: '/foo/item/{id}', policy: policyId]
Info |
---|
Not that Permission: [name: 'GET access for role: sampleRoleId to /foo/item/{id}', scope: 'GET', resource: '/foo/item/{id}', policy: policyId] is not deleted, because it was explicitly assigned to a role via relation roleCapability: [policyId, fooItemViewCapabilityId] |
Info |
---|
The same process works for user-capability, user-capabilitySet link management |
Capability Relation Management
Role
Capability assignment process
safeCreate
flag is used only internally, for outside requests a user must always assign a set of new capability ids, if not - an update operation allows the creation and delete capabilities in a single request
Image Added
Expand |
---|
title | Role-Capability assignment PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group RoleCapabilityServiceImpl {
:get role by id;<<input>>
:get ""roleCapabilities"" by ""roleId"";<<task>>
:extract existing ""capabilityIds"" from ""roleCapabilities"";<<task>>
if (not ""safeCreate"" AND ""capabilityIds"" not empty)) then (yes)
:throw EntityExistsException;<<output>>
end
else (no)
:get difference between new and existing ""capabilityIds"" sets as ""newCapabilityIds"";<<input>>
end if
group assignCapabilities {
:get assigned capabilities through capability sets as ""assignedCapabilityIds"";<<input>>
:store union of ""assignedCapabilityIds"" and ""newCapabilityIds"" as ""assignedCapabilityIds"";<<input>>
group #LightSteelBlue CapabilityEndpointService.getByCapabilityIds {
:get difference with ""newCapabilityIds"" and ""assignedCapabilityIds"" as ""changedIdentifiers"";<<input>>
:get changed capability endpoints by querying capabilities by ""changedIdentifiers""
and extracting distinct list of assigned endpoints and store it as ""changedCapabilityEndpoints"";<<task>>
:get assigned capability endpoints by querying capabilities by ""assignedIds""
and extracting distinct list of assigned endpoints and store it as ""assignedCapabilityEndpoints"";<<task>>
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:rolePermissionsService.createPermissions for ""roleId"" and ""endpoints"";<<task>>
group #LightSteelBlue CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
else (no)
:get role by ""roleId"";<<input>>
:generate policy name for ""role"";<<input>>
:getOrCreate role policy by name
//Policy name template:// ""Policy for role: {{roleId}}"";<<task>>
:create permissions in Keycloak with role policy, list of endpoint and using permissionNameGenerator
//Permission name template:// ""{{httpMethod}} access for role '{{roleId}}' to '{{path}}'"";
end if
}
:generate RoleCapabilityEntity for ""newIds"" and store them as ""entities"";<<task>>
:upsert entities to table ""role_capability"" in database;<<output>>
:convert ""RoleCapabilityEntity"" to ""RoleCapability"" and return them as ""PageResult"";<<output>>
}
}
@enduml |
|
Capability remove process
...
Expand |
---|
title | Role-Capability removal process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group RoleCapabilityServiceImpl {
:get existing ""roleCapabilities"" by ""roleId"";<<task>>
:extract existing ""capabilityIds"" from ""roleCapabilities"";<<task>>
if (""capabilityIds"" is empty) then (yes)
:do nothing;<<output>>
end
else (no)
:get intersection between ""capabilityIds"" and existing ""capabilityIds"" sets as ""deprecatedIds"";<<input>>
:get subtraction between ""assignedCapabilityIds"" and existing ""deprecatedIds"" sets as ""assignedIds"";<<input>>
end if
group removeCapabilities {
:get assigned capabilities through capability sets as ""assignedCapabilityIds"";<<input>>
:store union of ""assignedCapabilityIds"" and ""assignedIds"" as ""assignedCapabilityIds"";<<task>>
group #LightSteelBlue CapabilityEndpointService.getByCapabilityIds {
:get difference with ""deprecatedIds"" and ""assignedIds"" as ""changedIdentifiers"";<<input>>
:get changed capability endpoints by querying capabilities by ""changedIdentifiers""
and extracting distinct list of assigned endpoints and store it as ""changedCapabilityEndpoints"";<<task>>
:get assigned capability endpoints by querying capabilities by ""assignedIds""
and extracting distinct list of assigned endpoints and store it as ""assignedCapabilityEndpoints"";<<task>>
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:rolePermissionsService.deletePermissions for ""roleId"" and ""endpoints"";<<task>>
group #LightSteelBlue CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
else (no)
:get role by ""roleId"";<<input>>
:generate policy name for ""role"";<<input>>
:get policy by ""name"" and type == ""ROLE"";<<task>>
:delete permissions in Keycloak with role policy, list of endpoint and using permissionNameGenerator
//Permission name template:// ""{{httpMethod}} access for role '{{roleId}}' to '{{path}}'"";
end if
}
:delete entities from table ""role_capability"" in database by ""roleId"" and ""deprecatedIds"";<<output>>
}
}
@enduml |
|
Capability update process
A capability update process combines capability assignment and capability remove processes, where unmodified capabilities and corresponding keycloak permissions remain intact.
CapabilitySet assignment process
...
Expand |
---|
title | Capability Set assignment process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group RoleCapabilityServiceImpl {
:get role by id;<<input>>
:get ""roleCapabilitySets"" by ""roleId"";<<task>>
:extract existing ""capabilitySetIds"" from ""roleCapabilitySets"";<<task>>
if (not ""safeCreate"" AND ""capabilitySetIds"" not empty)) then (yes)
:throw EntityExistsException;<<output>>
end
else (no)
:get difference between new and existing ""capabilitySetIds"" sets as ""newSetIds"";<<input>>
end if
group #LightSteelBlue assignCapabilitySets {
group getChangedEndpoints {
:retrieve ""Capability"" entities by ""roleId"" as ""directlyAssignedCapabilities"";<<input>>
:extract endpoints from ""directlyAssignedCapabilities"" and store them as ""excludedEndpoints"";<<task>>
group capabilityEndpointService.getByCapabilitySetIds {
:retrieve ""Capability"" entities by ""newSetIds"" as ""changedCapabilities"";<<input>>
:retrieve ""Capability"" entities by ""assignedSetIds"" as ""assignedCapabilities"";<<input>>
:extract endpoints from ""changedCapabilities"" and store them as ""changedCapabilitySetEndpoints"";<<task>>
:extract endpoints from ""assignedCapabilities"" and store them as ""assignedCapabilitySetEndpoints"";<<task>>
:return subtraction ""assignedCapabilitySetEndpoints"" and ""excludedEndpoints"" from ""changedCapabilitySetEndpoints"" as ""List<Endpoint"";<<output>>
}
}
:create keycloak permissions in ""RolePermissionsService"" for ""roleId"" and ""endpoints"";<<task>>
:generate ""RoleCapabilitySetEntity"" for ""newSetIds"" and store them as ""entities"";<<task>>
:upsert entities to table ""role_capability_set"" in database;<<output>>
:convert ""RoleCapabilitySetEntity"" to ""RoleCapabilitySet"" and return them as ""PageResult"";<<output>>
}
}
@enduml |
|
CapabilitySet removal process
Image Added
Expand |
---|
title | Capability Set removal process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group RoleCapabilityServiceImpl {
:get role by id;<<input>>
:get ""roleCapabilities"" by ""roleId"";<<task>>
:extract existing ""capabilityIds"" from ""roleCapabilities"";<<task>>
if (not ""safeCreate"" AND ""capabilityIds"" not empty)) then (yes)
:throw EntityExistsException;<<output>>
end
else (no)
:get difference between new and existing ""capabilityIds"" sets as ""newCapabilityIds"";<<input>>
end if
group assignCapabilities {
:get assigned capabilities through capability sets as ""assignedCapabilityIds"";<<input>>
:store union of ""assignedCapabilityIds"" and ""newCapabilityIds"" as ""assignedCapabilityIds"";<<input>>
group #LightSteelBlue CapabilityEndpointService.getByCapabilityIds { MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group RoleCapabilityServiceImpl {
:get role by id;<<input>>
:get ""roleCapabilitySets"" by ""roleId"" as ""assignedRoleCapabilitySetEntities"";<<task>>
:extract existing ""assignedCapabilitySetIds"" from ""assignedRoleCapabilitySetEntities"";<<task>>
if (""assignedCapabilitySetIds"" is empty) then (yes)
:do nothing;<<output>>
end
else (no)
:get intersection between ""assignedCapabilitySetIds"" and given ""capabilitySetIds"" sets as ""deprecatedSetIds"";<<input>>
:get subtraction between ""assignedCapabilityIds"" and existing ""deprecatedSetIds"" sets as ""assignedSetIds"";<<input>>
end if
group removeCapabilitySets {
group #LightSteelBlue getChangedEndpoints {
:retrieve "Capability" entities by ""roleId"" as ""directlyAssignedCapabilities"";<<input>>
:extract endpoints from ""directlyAssignedCapabilities"" and store them as ""excludedEndpoints"";<<task>>
group capabilityEndpointService.getByCapabilitySetIds {
:retrieve "Capability" entities by ""deprecatedSetIds"" as ""changedCapabilities"";<<input>>
:extract endpoints from ""changedCapabilities"" and store them as ""changedCapabilitySetEndpoints"";<<task>>
:getretrieve difference with "Capability"newCapabilityIds"" and entities by ""assignedCapabilityIdsassignedSetIds"" as ""changedIdentifiersassignedCapabilities"";<<input>>
:getextract changedendpoints capability endpoints by querying capabilities byfrom ""assignedCapabilities"" and store them as ""changedIdentifiersassignedCapabilitySetEndpoints"";<<task>>
and extracting distinct:return list of assigned endpoints and store it subtraction ""assignedCapabilitySetEndpoints"" and ""excludedEndpoints"" from ""changedCapabilitySetEndpoints"" as ""changedCapabilityEndpointsList<Endpoint"";<<task>><<output>>
}
:getremove assignedkeycloak capabilitypermissions endpoints by querying capabilities byusing ""RolePermissionsService"" for ""roleId"" and ""assignedIdsendpoints"";<<task>>
and:delete extractingentities distinctfrom list of assigned endpoints and store it astable ""user_capability"" by ""roleId"" and ""assignedCapabilityEndpointsdeprecatedIds"";<<task>><<output>>
}
}
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:rolePermissionsService.createPermissions for ""roleId"" and ""endpoints"";<<task>>
group #LightSteelBlue CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
else (no)
:get role by ""roleId"";<<input>>
:generate policy name for ""role"";<<input>>
:getOrCreate role policy by name
//Policy name template:// ""Policy for role: {{roleId}}"";<<task>>
:create permissions in Keycloak with role policy, list of endpoint and using permissionNameGenerator
//Permission name template:// ""{{httpMethod}} access for role '{{roleId}}' to '{{path}}'"";
end if
}
:generate RoleCapabilityEntity for ""newIds"" and store them as ""entities"";<<task>>
:upsert entities to table ""role_capability"" in database;<<output>>
:convert ""RoleCapabilityEntity"" to ""RoleCapability"" and return them as ""PageResult"";<<output>>
}
}
@enduml |
|
Capability remove process
...
title | Role-Capability removal process PlantUML |
---|
...
User
Capability assignment process
safeCreate
flag is used only internally, for outside requests a user must always assign a set of new capability ids, if not - an update operation allows the creation and delete capabilities in a single request
...
Expand |
---|
title | User-Capability assignment PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group UserCapabilityServiceImpl {
:create keycloakUser If not exists by calling ""mod-users-keycloak"" API;<<task>>
:extract existing ""capabilityIds"" from ""userCapabilities"";<<task>>
if (not ""safeCreate"" AND ""capabilityIds"" not empty)) then (yes)
:throw EntityExistsException;<<output>>
end
else (no)
:get difference between new and existing ""capabilityIds"" sets as ""newCapabilityIds"";<<input>>
end if
group assignCapabilities {
:get assigned capabilities through capability sets as ""assignedCapabilityIds"";<<input>>
:store union of ""assignedCapabilityIds"" and ""newCapabilityIds"" as ""assignedCapabilityIds"";<<input>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
:get difference with ""newCapabilityIds"" and ""assignedCapabilityIds"" as ""changedIdentifiers"";<<input>>
:get changed capability endpoints by querying capabilities by ""changedIdentifiers""
and extracting distinct list of assigned endpoints and store it as ""changedCapabilityEndpoints"";<<task>>
:get assigned capability endpoints by querying capabilities by ""assignedIds""
and extracting distinct list of assigned endpoints and store it as ""assignedCapabilityEndpoints"";<<task>>
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:userPermissionsService.createPermissions for ""userId"" and ""endpoints"";<<task>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
end else (no)
:get intersection between ""capabilityIds"" and existing ""capabilityIds"" sets as :get keycloak user by Folio ""deprecatedIdsuserId"";<<input>>
:get subtraction between ""assignedCapabilityIds"" and existing ""deprecatedIds"" sets as ""assignedIds :generate policy name for ""user"";<<input>>
end if :getOrCreate groupuser policy removeCapabilitiesby {name
:get assigned capabilities through capability//Policy sets asname template:// ""assignedCapabilityIdsPolicy for user: {{userId}}"";<<input>><<task>>
:store union of ""assignedCapabilityIds"" and ""assignedIds"" as ""assignedCapabilityIds"";<<task>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
:create permissions in Keycloak with user policy, list of endpoint and using permissionNameGenerator
:get difference with ""deprecatedIds"" and ""assignedIds"" as ""changedIdentifiers"";<<input>>
:get changed capability endpoints by querying capabilities by ""changedIdentifiers""
and extracting distinct list of assigned endpoints //Permission name template:// ""{{httpMethod}} access for user '{{userId}}' to '{{path}}'"";
end if
}
:generate UserCapabilityEntity for ""newIds"" and store itthem as ""changedCapabilityEndpointsentities"";<<task>>
:get assigned capability endpoints by querying capabilities by ""assignedIds :upsert entities to table ""user_capability"" in database;<<output>>
and extracting distinct list of assigned endpoints and store it:convert ""UserCapabilityEntity"" to ""UserCapability"" and return them as ""assignedCapabilityEndpointsPageResult"";<<task>>
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:userPermissionsService.deletePermissions for ""userId"" and ""endpoints"";<<task>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
else (no)
:get keycloak user by ""userId"";<<input>>
:generate policy name for ""user"";<<input>>
:get policy by ""name"" and type == ""USER<<output>>
}
}
@enduml |
|
Capability removal process
...
Expand |
---|
title | Capability removal process from a user process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group UserCapabilityServiceImpl {
:get existing ""userCapabilities"" by ""userId"";<<task>>
:extract existing ""capabilityIds"" from ""userCapabilities"";<<task>>
if (""capabilityIds"" is empty) then (yes)
:delete permissions in Keycloak with user policy, list of endpoint and using permissionNameGenerator
:do nothing;<<output>>
end
else (no)
:get intersection //Permission name template:// ""{{httpMethod}} access for user '{{userId}}' to '{{path}}'"";between ""capabilityIds"" and existing ""capabilityIds"" sets as ""deprecatedIds"";<<input>>
:get subtraction end if
}
between ""assignedCapabilityIds"" and existing ""deprecatedIds"" sets as ""assignedIds"";<<input>>
end if
:delete
entities from table ""user_capability"" in database by ""userId"" and ""deprecatedIds"";<<output>>
}
}
@enduml |
|
Capability update process
A capability update process is a combination of capability assignment and capability remove processes, where unmodified capabilities and corresponding keycloak permissions remain intact.
User
Capability assignment process
safeCreate
flag is used only internally, for outside requests a user must always assign a set of new capability ids, if not - an update operation allows the creation and delete capabilities in a single request
...
Expand |
---|
title | User-Capability assignment PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group UserCapabilityServiceImpl {
:create keycloakUser If not exists by calling ""mod-users-keycloak"" API;<<task>>
:extract existing ""capabilityIds"" from ""userCapabilities"";<<task>>
if (not ""safeCreate"" AND ""capabilityIds"" not empty)) then (yes)
:throw EntityExistsException;<<output>>
end
group removeCapabilities {
:get assigned capabilities through capability sets as ""assignedCapabilityIds"";<<input>>
:store union of ""assignedCapabilityIds"" and ""assignedIds"" as ""assignedCapabilityIds"";<<task>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
:get difference with ""deprecatedIds"" and ""assignedIds"" as ""changedIdentifiers"";<<input>>
:get changed capability endpoints by querying capabilities by ""changedIdentifiers""
and extracting distinct list of assigned endpoints and store it as ""changedCapabilityEndpoints"";<<task>>
:get assigned capability endpoints by querying capabilities by ""assignedIds""
and extracting distinct list of assigned endpoints and store it as ""assignedCapabilityEndpoints"";<<task>>
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:userPermissionsService.deletePermissions for ""userId"" and ""endpoints"";<<task>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
else (no)
:get difference between new and:get existing ""capabilityIds"" sets as ""newCapabilityIdskeycloak user by ""userId"";<<input>>
end if
group assignCapabilities { :generate policy name for ""user"";<<input>>
:get assignedpolicy capabilities through capability sets asby ""name"" and type == ""assignedCapabilityIdsUSER"";<<input>><<task>>
:storedelete permissions unionin of ""assignedCapabilityIds"" and ""newCapabilityIds"" as ""assignedCapabilityIds"";<<input>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {Keycloak with user policy, list of endpoint and using permissionNameGenerator
//Permission name template:get difference with ""newCapabilityIds"" and ""assignedCapabilityIds"" as ""changedIdentifiers"";<<input>>// ""{{httpMethod}} access for user '{{userId}}' to '{{path}}'"";
end :getif
changed capability endpoints by querying}
capabilities
by
""changedIdentifiers"" :delete entities from and extracting distinct list of assigned endpoints and store it as ""changedCapabilityEndpoints"";<<task>>
:get assigned capability endpoints by querying capabilities by ""assignedIds""
and extracting distinct list of assigned endpoints and store it as ""assignedCapabilityEndpoints"";<<task>>
:return subtraction ""assignedCapabilityEndpoints"" from ""changedCapabilityEndpoints"";<<output>>
}
:userPermissionsService.createPermissions for ""userId"" and ""endpoints"";<<task>>
group #PaleGreen CapabilityEndpointService.getByCapabilityIds {
if (""endpoints"" are empty) then (yes)
:do nothing;<<output>>
else (no)
:get keycloak user by Folio ""userId"";<<input>>
:generate policy name for ""user"";<<input>>
:getOrCreate user policy by name
//Policy name template:// ""Policy for user: {{userId}}"";<<task>>
:create permissions in Keycloak with user policy, list of endpoint and using permissionNameGenerator
//Permission name template:// ""{{httpMethod}} access for user '{{userId}}' to '{{path}}'"";
end if
}
:generate UserCapabilityEntity for ""newIdstable ""user_capability"" in database by ""userId"" and ""deprecatedIds"";<<output>>
}
}
@enduml |
|
Capability update process
A capability update process combines capability assignment and capability remove processes, where unmodified capabilities and corresponding keycloak permissions remain intact.
CapabilitySet assignment process
...
Expand |
---|
title | Capability Set assignment process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center
}
group {
LineColor LightGrey
FontSize 10
}
}
</style>
group UserCapabilityServiceImpl {
:create keycloakUser If not exists by calling ""mod-users-keycloak"" API;<<task>>
:get ""userCapabilitySets"" by ""userId"";<<task>>
:extract existing ""capabilitySetIds"" from ""userCapabilitySets"";<<task>>
if (not ""safeCreate"" AND ""capabilitySetIds"" not empty)) then (yes)
:throw EntityExistsException;<<output>>
end
else (no)
:get difference between new and existing ""capabilitySetIds"" sets as ""newSetIds"";<<input>>
end if
group #PaleGreen assignCapabilitySets {
group getChangedEndpoints {
:retrieve ""Capability"" entities by ""userId"" as ""directlyAssignedCapabilities"";<<input>>
:extract endpoints from ""directlyAssignedCapabilities"" and store them as ""entitiesexcludedEndpoints"";<<task>>
group capabilityEndpointService.getByCapabilitySetIds {
:upsert entities to table:retrieve ""user_capabilityCapability"" inentities database;<<output>>
:convert by ""UserCapabilityEntitynewSetIds"" toas ""UserCapabilitychangedCapabilities"" and return them as;<<input>>
:retrieve ""PageResultCapability"";<<output>> entities by }
}
@enduml |
|
Capability removal process
...
Expand |
---|
title | Capability removal process from a user process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
HorizontalAlignment center""assignedSetIds"" as ""assignedCapabilities"";<<input>>
:extract endpoints from ""changedCapabilities"" and store them as ""changedCapabilitySetEndpoints"";<<task>>
:extract endpoints from ""assignedCapabilities"" and store them as ""assignedCapabilitySetEndpoints"";<<task>>
:return subtraction ""assignedCapabilitySetEndpoints"" and ""excludedEndpoints"" from ""changedCapabilitySetEndpoints"" as ""List<Endpoint"";<<output>>
}
group {}
LineColor LightGrey:create keycloak permissions in ""UserPermissionsService"" FontSize 10
}
}
</style>
group UserCapabilityServiceImpl {for ""userId"" and ""endpoints"";<<task>>
:get existinggenerate ""UserCapabilitySetEntity"" for ""userCapabilitiesnewSetIds"" byand store them as ""userIdentities"";<<task>>
:extract existing :upsert entities to table ""capabilityIdsuser_capability_set"" from ""userCapabilities"";<<task>>in database;<<output>>
if (not:convert ""UserCapabilitySetEntity"" to ""safeCreateUserCapabilitySet"" ANDand return them as ""capabilityIdsPageResult"";<<output>>
not empty)) then}
(yes)
:do nothing;<<output>>
end
else (no)
:get intersection between ""capabilityIds"" and existing ""capabilityIds"" sets as ""deprecatedIds"";<<input>>
:get subtraction between ""assignedCapabilityIds"" and existing ""deprecatedIds"" sets as ""assignedIds"";<<input>>
end if
group removeCapabilities}
@enduml |
|
CapabilitySet removal process
Image Added
Expand |
---|
title | CapabilitySet removal process PlantUML |
---|
|
Code Block |
---|
@startuml
!theme mono
!pragma useVerticalIf on
skinparam conditionStyle inside
skinparam defaultTextAlignment center
skinparam defaultFontSize 12
<style>
activityDiagram {
activity {
MaximumWidth 600
backgroundColor #f0f0f0
LineColor DimGrey
}
diamond {
|
|
...
HorizontalAlignment center
}
group {
LineColor |
|
...
...
...
...
...
...
FontSize 10
}
}
</style>
group |
|
...
UserCapabilityServiceImpl {
:get keycloak user by Folio ""userId"";<<input>>
:get |
|
...
...
...
...
...
assignedUserCapabilitySetEntities""; |
|
...
<<task>>
:extract existing ""assignedCapabilitySetIds"" from ""assignedUserCapabilitySetEntities"";<<task>>
if (""assignedCapabilitySetIds"" is empty) then (yes)
:do nothing;<<output>>
end
else (no)
:get |
|
...
...
between ""assignedCapabilitySetIds"" and given "" |
|
...
capabilitySetIds"" sets as ""deprecatedSetIds"";<<input>>
|
|
...
...
...
...
between ""assignedCapabilityIds"" and existing ""deprecatedSetIds"" sets as "" |
|
...
...
<<input>>
end if
group removeCapabilitySets {
|
|
...
...
...
...
group #PaleGreen getChangedEndpoints {
|
|
...
...
"Capability" entities by ""userId"" |
|
...
...
directlyAssignedCapabilities""; |
|
...
...
...
:extract endpoints from ""directlyAssignedCapabilities"" and store them as ""excludedEndpoints"";<<task>>
|
|
...
group capabilityEndpointService.getByCapabilitySetIds {
: |
|
...
...
...
entities by ""deprecatedSetIds"" as "" |
|
...
changedCapabilities"";<<input>>
: |
|
...
extract endpoints from ""changedCapabilities"" and store them as "" |
|
...
changedCapabilitySetEndpoints""; |
|
...
...
retrieve "Capability" entities by "" |
|
...
...
...
...
...
...
from ""assignedCapabilities"" and store them as ""assignedCapabilitySetEndpoints"";<<task>>
:return subtraction ""assignedCapabilitySetEndpoints"" and |
|
...
""excludedEndpoints"" from ""changedCapabilitySetEndpoints"" as ""List<Endpoint"";<<output>>
}
|
|
...
...
:remove keycloak permissions using |
|
...
""UserPermissionsService"" for ""userId"" and ""endpoints"";<<task>>
:delete entities from table ""user_capability"" |
|
...
...
by ""userId"" and ""deprecatedIds"";<<output>>
}
}
}
@enduml |
|
...
Capability update process
A capability update process is a combination of capability assignment and capability remove processes, where unmodified capabilities and corresponding keycloak permissions remain intact.