clearer/property variable naming and ordering

This commit is contained in:
2025-05-07 09:17:27 -04:00
parent 187e558177
commit 84d1b4ea2f
3 changed files with 48 additions and 48 deletions

View File

@@ -40,7 +40,7 @@ This extension requires the [`multiext-activiti-app-ext`](https://git.inteligr8.
| Activiti App Extension | Activiti App | | Activiti App Extension | Activiti App |
| --------------------------------------- | --------------- | | --------------------------------------- | --------------- |
| `keycloak-activiti-app-ext` v1.0 - v1.2 | v1.11.x | | `keycloak-activiti-app-ext` v1.0 - v1.2 | v1.11.x |
| `keycloak-activiti-app-ext` v1.3 | v1.11.x - v2.x | | `keycloak-activiti-app-ext` v1.3 - v1.4 | v1.11.x - v2.x |
| `auth-activiti-app-ext` v2.0+ | v24.x+ | | `auth-activiti-app-ext` v2.0+ | v24.x+ |
## Configuration ## Configuration
@@ -69,9 +69,9 @@ The following properties were added to increase the configurability of the built
The following properties provide the core functionality of this extension. That is role synchronization. The following properties provide the core functionality of this extension. That is role synchronization.
| Property | Default | Description | | Property | Default | Description |
| ---------------------------------------------- | --------- | ----------- | | --------------------------------------------- | ------------ | ----------- |
| `auth-ext.sync.user.createMissing` | `true` | If the user is authenticated, the user may be created in APS. | | `auth-ext.sync.user.createMissing` | `true` | If the user is authenticated, the user may be created in APS. |
| `auth-ext.sync.user.requireGroup` | | This is only applicable when `createMissing` is `true`. If this is unset or the OAuth Authorization Server gives the user the specified group/role, then the user record will be created in APS. | | `auth-ext.sync.user.requireOidcGroup` | | This is only applicable when `createMissing` is `true`. If this is unset or the OAuth Authorization Server gives the user the specified group/role, then the user record will be created in APS. |
| `auth-ext.sync.user.clearNewUserGroups` | `true` | This is only applicable when `createMissing` is `true`. All default APS groups will be deleted from the new user record. | | `auth-ext.sync.user.clearNewUserGroups` | `true` | This is only applicable when `createMissing` is `true`. All default APS groups will be deleted from the new user record. |
| `auth-ext.sync.group.createMissing` | `true` | If a filtered and translated OIDC group has no corresponding APS group, a group will be created in APS. See `auth-ext.sync.group.capabilities.patterns` for whether that group will be an APS Organization or APS Capability. | | `auth-ext.sync.group.createMissing` | `true` | If a filtered and translated OIDC group has no corresponding APS group, a group will be created in APS. See `auth-ext.sync.group.capabilities.patterns` for whether that group will be an APS Organization or APS Capability. |
| `auth-ext.sync.group.additions` | `true` | If the user isn't in an APS group but OAuth claims the OIDC group, then add them to it. | | `auth-ext.sync.group.additions` | `true` | If the user isn't in an APS group but OAuth claims the OIDC group, then add them to it. |
@@ -79,11 +79,11 @@ The following properties provide the core functionality of this extension. That
| `auth-ext.sync.group.internal` | `false` | When considering groups for creation or user membership, include internal groups. Internal groups are ones without an `externalId`. | | `auth-ext.sync.group.internal` | `false` | When considering groups for creation or user membership, include internal groups. Internal groups are ones without an `externalId`. |
| `auth-ext.sync.group.internal.externalize` | `false` | This is only applicable when `internal` is `true`. If an internal group is encountered during the operation of this extension, make it external with the current `externalId`. | | `auth-ext.sync.group.internal.externalize` | `false` | This is only applicable when `internal` is `true`. If an internal group is encountered during the operation of this extension, make it external with the current `externalId`. |
| `auth-ext.sync.group.tenantize` | `false` | If a group without a tenant is encountered during the operation of this extension, make it part of the selected tenant. | | `auth-ext.sync.group.tenantize` | `false` | If a group without a tenant is encountered during the operation of this extension, make it part of the selected tenant. |
| `auth-ext.sync.group.translate.patterns` | | A comma delimited set of regular expression patterns for the translation (reformatting) of authorities. | | `auth-ext.sync.group.include.patterns` | | A comma delimited set of regular expression patterns on what OIDC groups to include. This is processed before `translate` processing. A blank value matches everything. If anything is specified, then only matches could possibly be included. Any matches of the `exclude` property patterns always override though. |
| `auth-ext.sync.group.translate.replacements` | | A comma delimited set of regular expression replacement strings for the translation (reformatting) of authorities. | | `auth-ext.sync.group.exclude.patterns` | | A comma delimited set of regular expression patterns on what OIDC groups to exclude. This is processed before `translate` processing. A blank value matches nothing (includes all that pass the `include` constraint). If anything is specified and `include` is empty, then all non-matches are included. If both are specified, `exclude` matches override `include` matches. |
| `auth-ext.sync.group.include.patterns` | | A comma delimited set of regular expression patterns on what authorities to include. This is processed before `translate` processing. A blank value includes everything. If anything is specified, then only matches could possibly be included; but could still be excluded explicitly. | | `auth-ext.sync.group.translate.patterns` | | A comma delimited set of regular expression patterns for the translation (reformatting) of OIDC groups to APS groups. This list corresponds to the `replacements` property and must have the same number of commas. |
| `auth-ext.sync.group.exclude.patterns` | | A comma delimited set of regular expression patterns on what authorities to exclude. This is processed before `translate` processing. A blank value excludes nothing. If anything is specified and `include` is empty, then only matches will be excluded. If both are specified, `exclude` overrules `include` matches. | | `auth-ext.sync.group.translate.replacements` | | A comma delimited set of regular expression replacement strings for the translation (reformatting) of OIDC groups to APS groups. This list corresponds to the `patterns` property and must have the same number of commas. |
| `auth-ext.sync.group.capabilities.patterns` | `Superusers` | A comma delimited set of regular expression patterns on what authorities to associate with APS Capabilities instead of APS Organizations (default). | | `auth-ext.sync.group.capability.patterns` | `Superusers` | A comma delimited set of regular expression patterns on what translated OIDC groups to associate with APS Capability Groups instead of APS Organization Groups (default). This is processed after `translate` processing. |
### Authentication Data Fixers ### Authentication Data Fixers

View File

@@ -139,9 +139,9 @@ public class GroupSyncService {
this.logger.trace("Incoming OIDC groups: {}: {}", oidcUser.getEmail(), oidcGroups); this.logger.trace("Incoming OIDC groups: {}: {}", oidcUser.getEmail(), oidcGroups);
oidcGroups = this.filterGroups(oidcGroups); oidcGroups = this.filterGroups(oidcGroups);
oidcGroups = this.translateGroups(oidcGroups); Set<String> translatedGroups = this.translateGroups(oidcGroups);
this.logger.debug("Filtered/translated OIDC groups: {}: {}", oidcUser.getEmail(), oidcGroups); this.logger.debug("Filtered/translated OIDC groups: {}: {}", oidcUser.getEmail(), translatedGroups);
long tenantId = this.tenantFinderService.findTenantId(); long tenantId = this.tenantFinderService.findTenantId();
@@ -166,7 +166,7 @@ public class GroupSyncService {
this.logger.trace("Inspecting APS group: {} => {} ({})", group.getId(), group.getName(), group.getExternalId()); this.logger.trace("Inspecting APS group: {} => {} ({})", group.getId(), group.getName(), group.getExternalId());
if (group.getExternalId() != null) { if (group.getExternalId() != null) {
String oidcGroup = this.apsGroupExternalIdToOidcGroup(group.getExternalId()); String translatedGroup = this.apsGroupExternalIdToTranslatedOidcGroup(group.getExternalId());
if (this.retenantUntenantedGroups && group.getTenantId() == null) { if (this.retenantUntenantedGroups && group.getTenantId() == null) {
this.logger.warn("Moving tenant-less APS group to tenant: {} => {}", group.getName(), tenantId); this.logger.warn("Moving tenant-less APS group to tenant: {} => {}", group.getName(), tenantId);
@@ -175,20 +175,20 @@ public class GroupSyncService {
this.groupService.save(group); this.groupService.save(group);
} }
if (oidcGroups.remove(oidcGroup)) { if (translatedGroups.remove(translatedGroup)) {
this.logger.trace("User already belongs to APS group mapped to by OIDC group: {}: {} => {}", user.getExternalId(), oidcGroup, group.getName()); this.logger.trace("User already belongs to APS group mapped to by (translated) OIDC group: {}: {} => {}", user.getExternalId(), translatedGroup, group.getName());
continue; continue;
} }
} else { } else {
String oidcGroup = this.apsGroupNameToOidcGroup(group.getName()); String translatedGroup = this.apsGroupNameToTranslatedOidcGroup(group.getName());
if (oidcGroups.remove(oidcGroup)) { if (translatedGroups.remove(translatedGroup)) {
this.logger.trace("User already belongs to APS group mapped to by OIDC group: {}: {} => {}", user.getExternalId(), oidcGroup, group.getName()); this.logger.trace("User already belongs to APS group mapped to by (translated) OIDC group: {}: {} => {}", user.getExternalId(), translatedGroup, group.getName());
if (this.externalizeMatchingInternalGroups) { if (this.externalizeMatchingInternalGroups) {
this.logger.warn("Classifying internal APS group as external: {} => {}", group.getName(), this.externalIdmSource); this.logger.warn("Classifying internal APS group as external: {} => {}", group.getName(), this.externalIdmSource);
// register the group as external // register the group as external
group.setExternalId(this.oidcGroupToApsGroupExternalId(oidcGroup)); group.setExternalId(this.translatedOidcGroupToApsGroupExternalId(translatedGroup));
group.setLastUpdate(new Date()); group.setLastUpdate(new Date());
this.groupService.save(group); this.groupService.save(group);
// internal role already existed and the user is already a member // internal role already existed and the user is already a member
@@ -212,21 +212,21 @@ public class GroupSyncService {
} }
// the user needs to be added to the remaining authorities // the user needs to be added to the remaining authorities
for (String oidcGroup : oidcGroups) { for (String translatedGroup : translatedGroups) {
this.logger.trace("Inspecting unaccounted for OIDC group: {}", oidcGroup); this.logger.trace("Inspecting unaccounted for (translated) OIDC group: {}", translatedGroup);
Group group; Group group;
try { try {
group = this.groupService.getGroupByExternalIdAndTenantId(this.oidcGroupToApsGroupExternalId(oidcGroup), tenantId); group = this.groupService.getGroupByExternalIdAndTenantId(this.translatedOidcGroupToApsGroupExternalId(translatedGroup), tenantId);
} catch (NonUniqueResultException nure) { } catch (NonUniqueResultException nure) {
this.logger.warn("There are multiple groups matching the OIDC group for the external system: {} [{}]; skipping consideration of OIDC group", oidcGroup, this.externalIdmSource); this.logger.warn("There are multiple groups matching the (translated) OIDC group for the external system: {} [{}]; skipping consideration of OIDC group", translatedGroup, this.externalIdmSource);
continue; continue;
} }
if (group == null && this.syncInternalGroups) { if (group == null && this.syncInternalGroups) {
List<Group> groups = this.groupService.getGroupByNameAndTenantId(this.oidcGroupToApsGroupName(oidcGroup), tenantId); List<Group> groups = this.groupService.getGroupByNameAndTenantId(this.translatedOidcGroupToApsGroupName(translatedGroup), tenantId);
if (groups.size() > 1) { if (groups.size() > 1) {
this.logger.warn("There are multiple APS groups matching the OIDC group: {} [{}]; skipping consideration of OIDC group", oidcGroup, this.externalIdmSource); this.logger.warn("There are multiple APS groups matching the (translated) OIDC group: {} [{}]; skipping consideration of OIDC group", translatedGroup, this.externalIdmSource);
continue; continue;
} else if (groups.size() == 1) { } else if (groups.size() == 1) {
group = groups.iterator().next(); group = groups.iterator().next();
@@ -234,7 +234,7 @@ public class GroupSyncService {
if (this.externalizeMatchingInternalGroups) { if (this.externalizeMatchingInternalGroups) {
this.logger.debug("Found an internal APS group; registering as external: {}", group.getName()); this.logger.debug("Found an internal APS group; registering as external: {}", group.getName());
group.setExternalId(this.oidcGroupToApsGroupExternalId(oidcGroup)); group.setExternalId(this.translatedOidcGroupToApsGroupExternalId(translatedGroup));
group.setLastSyncTimeStamp(new Date()); group.setLastSyncTimeStamp(new Date());
group.setLastUpdate(new Date()); group.setLastUpdate(new Date());
this.groupService.save(group); this.groupService.save(group);
@@ -244,11 +244,11 @@ public class GroupSyncService {
if (group == null) { if (group == null) {
if (!this.createMissing) { if (!this.createMissing) {
this.logger.debug("APS Group does not exist for OIDC group; APS group creation is disabled; OIDC group will go unrecognized: {}", oidcGroup); this.logger.debug("APS Group does not exist for (translated) OIDC group; APS group creation is disabled; OIDC group will go unrecognized: {}", translatedGroup);
continue; continue;
} }
group = this.createApsGroup(oidcGroup, tenantId); group = this.createApsGroup(translatedGroup, tenantId);
} }
if (this.syncAdditions) { if (this.syncAdditions) {
@@ -261,13 +261,13 @@ public class GroupSyncService {
} }
} }
protected Group createApsGroup(String oidcGroup, long tenantId) { protected Group createApsGroup(String translatedGroup, long tenantId) {
this.logger.debug("APS Group does not exist for OIDC group; will attempt to create: {}", oidcGroup); this.logger.debug("APS Group does not exist for (translated) OIDC group; will attempt to create: {}", translatedGroup);
String name = this.oidcGroupToApsGroupName(oidcGroup); String name = this.translatedOidcGroupToApsGroupName(translatedGroup);
String externalId = this.oidcGroupToApsGroupExternalId(oidcGroup); String externalId = this.translatedOidcGroupToApsGroupExternalId(translatedGroup);
boolean syncAsOrg = this.isOidcGroupToBeOrganization(oidcGroup); boolean syncAsOrg = this.isTranslatedOidcGroupToBeOrganization(translatedGroup);
this.logger.trace("Creating new APS group as {}: {}", syncAsOrg ? "organization" : "capability", oidcGroup); this.logger.trace("Creating new APS group as {}: {}", syncAsOrg ? "organization" : "capability", translatedGroup);
int type = syncAsOrg ? Group.TYPE_FUNCTIONAL_GROUP : Group.TYPE_SYSTEM_GROUP; int type = syncAsOrg ? Group.TYPE_FUNCTIONAL_GROUP : Group.TYPE_SYSTEM_GROUP;
Group apsGroup = this.groupService.createGroupFromExternalStore(name, tenantId, type, null, externalId, new Date()); Group apsGroup = this.groupService.createGroupFromExternalStore(name, tenantId, type, null, externalId, new Date());
@@ -331,29 +331,29 @@ public class GroupSyncService {
return translatedGroups; return translatedGroups;
} }
private String oidcGroupToApsGroupExternalId(String group) { private String translatedOidcGroupToApsGroupExternalId(String group) {
return this.externalIdmSource + "_" + group; return this.externalIdmSource + "_" + group;
} }
private String apsGroupExternalIdToOidcGroup(String externalId) { private String apsGroupExternalIdToTranslatedOidcGroup(String externalId) {
int underscorePos = externalId.indexOf('_'); int underscorePos = externalId.indexOf('_');
return underscorePos < 0 ? externalId : externalId.substring(underscorePos + 1); return underscorePos < 0 ? externalId : externalId.substring(underscorePos + 1);
} }
private String oidcGroupToApsGroupName(String group) { private String translatedOidcGroupToApsGroupName(String group) {
return group; return group;
} }
private String apsGroupNameToOidcGroup(String externalId) { private String apsGroupNameToTranslatedOidcGroup(String externalId) {
return externalId; return externalId;
} }
private boolean isOidcGroupToBeOrganization(String role) { private boolean isTranslatedOidcGroupToBeOrganization(String translatedGroup) {
if (this.capabilities.isEmpty()) if (this.capabilities.isEmpty())
return true; return true;
for (Pattern regex : this.capabilities) { for (Pattern regex : this.capabilities) {
Matcher matcher = regex.matcher(role); Matcher matcher = regex.matcher(translatedGroup);
if (matcher.matches()) if (matcher.matches())
return false; return false;
} }

View File

@@ -42,7 +42,7 @@ public class UserSyncService {
@Value("${auth-ext.sync.user.createMissing:true}") @Value("${auth-ext.sync.user.createMissing:true}")
protected boolean createMissingUser; protected boolean createMissingUser;
@Value("${auth-ext.sync.user.requireGroup:#{null}}") @Value("${auth-ext.sync.user.requireOidcGroup:#{null}}")
protected String requiredGroup; protected String requiredGroup;
@Value("${auth-ext.sync.user.clearNewUserGroups:true}") @Value("${auth-ext.sync.user.clearNewUserGroups:true}")