allowing for more dynamic organization/capability sync control
This commit is contained in:
@@ -41,10 +41,10 @@ The library is highly configurable. You configure it with properties specified
|
|||||||
|
|
||||||
### For Activiti App Only
|
### For Activiti App Only
|
||||||
|
|
||||||
| Property | Default | Description |
|
| Property | Default | Description |
|
||||||
| ----------------------------------------- | -------------- | ----------- |
|
| ------------------------------------------------ | ------- | ----------- |
|
||||||
| `keycloak-ext.syncGroupAs` | `organization` | When creating a new group, should it be a functional (`organization`) group or a system (`capability`) group? |
|
| `keycloak-ext.group.organization.regex.patterns` | `.*` | When creating a new group, sync as APS Organization (functional group) when the role matches the specified regular expression. If it doesn't, add as APS Capability (system group). |
|
||||||
| `keycloak-ext.external.id` | `ais` | When creating a new group or registering an internal group as external, use this ID as a prefix to the external group ID. |
|
| `keycloak-ext.external.id` | `ais` | When creating a new group or registering an internal group as external, use this ID as a prefix to the external group ID. |
|
||||||
|
|
||||||
### Rare
|
### Rare
|
||||||
|
|
||||||
|
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.inteligr8.activiti</groupId>
|
<groupId>com.inteligr8.activiti</groupId>
|
||||||
<artifactId>keycloak-activiti-app-ext</artifactId>
|
<artifactId>keycloak-activiti-app-ext</artifactId>
|
||||||
<version>1.2-SNAPSHOT</version>
|
<version>1.3-SNAPSHOT</version>
|
||||||
<name>Keycloak Authentication & Authorization for APS</name>
|
<name>Keycloak Authentication & Authorization for APS</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -12,6 +12,8 @@ import java.util.Set;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.keycloak.KeycloakPrincipal;
|
import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
@@ -71,6 +73,7 @@ public abstract class AbstractKeycloakActivitiAuthenticator implements Authentic
|
|||||||
protected final Set<Pattern> groupExcludes = new HashSet<>();
|
protected final Set<Pattern> groupExcludes = new HashSet<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@OverridingMethodsMustInvokeSuper
|
||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
if (this.regexPatterns != null) {
|
if (this.regexPatterns != null) {
|
||||||
String[] regexPatternStrs = StringUtils.split(this.regexPatterns, ',');
|
String[] regexPatternStrs = StringUtils.split(this.regexPatterns, ',');
|
||||||
|
@@ -1,12 +1,15 @@
|
|||||||
package com.inteligr8.activiti.keycloak;
|
package com.inteligr8.activiti.keycloak;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||||
import javax.persistence.NonUniqueResultException;
|
import javax.persistence.NonUniqueResultException;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -59,16 +62,22 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
|
|||||||
@Value("${keycloak-ext.external.id:ais}")
|
@Value("${keycloak-ext.external.id:ais}")
|
||||||
protected String externalIdmSource;
|
protected String externalIdmSource;
|
||||||
|
|
||||||
@Value("${keycloak-ext.syncGroupAs:organization}")
|
@Value("${keycloak-ext.group.organization.regex.patterns:.*}")
|
||||||
protected String syncGroupAs;
|
protected String regexOrgIncludes;
|
||||||
|
|
||||||
protected boolean syncGroupAsOrganization() {
|
protected final Set<Pattern> orgIncludes = new HashSet<>();
|
||||||
return !this.syncGroupAsCapability();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean syncGroupAsCapability() {
|
@Override
|
||||||
return this.syncGroupAs != null && this.syncGroupAs.toLowerCase().startsWith("cap");
|
@OverridingMethodsMustInvokeSuper
|
||||||
}
|
public void afterPropertiesSet() {
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
|
||||||
|
if (this.regexOrgIncludes != null) {
|
||||||
|
String[] regexPatternStrs = StringUtils.split(this.regexOrgIncludes, ',');
|
||||||
|
for (int i = 0; i < regexPatternStrs.length; i++)
|
||||||
|
this.orgIncludes.add(Pattern.compile(regexPatternStrs[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method validates that the user exists, if not, it creates the
|
* This method validates that the user exists, if not, it creates the
|
||||||
@@ -163,8 +172,6 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean syncAsOrg = this.syncGroupAsOrganization();
|
|
||||||
|
|
||||||
// check Activiti groups
|
// check Activiti groups
|
||||||
User userWithGroups = this.userService.getUser(user.getId(), true);
|
User userWithGroups = this.userService.getUser(user.getId(), true);
|
||||||
for (Group group : userWithGroups.getGroups()) {
|
for (Group group : userWithGroups.getGroups()) {
|
||||||
@@ -228,6 +235,8 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
|
|||||||
if (group == null) {
|
if (group == null) {
|
||||||
if (this.createMissingGroup) {
|
if (this.createMissingGroup) {
|
||||||
this.logger.trace("Creating new group for role: {}", role);
|
this.logger.trace("Creating new group for role: {}", role);
|
||||||
|
boolean syncAsOrg = this.isRoleToBeOrganization(role.getKey());
|
||||||
|
this.logger.trace("Creating new group as {}: {}", syncAsOrg ? "organization" : "capability", role);
|
||||||
String name = this.keycloakRoleToApsGroupName(role.getValue());
|
String name = this.keycloakRoleToApsGroupName(role.getValue());
|
||||||
String externalId = this.keycloakRoleToApsGroupExternalId(role.getKey());
|
String externalId = this.keycloakRoleToApsGroupExternalId(role.getKey());
|
||||||
int type = syncAsOrg ? Group.TYPE_FUNCTIONAL_GROUP : Group.TYPE_SYSTEM_GROUP;
|
int type = syncAsOrg ? Group.TYPE_FUNCTIONAL_GROUP : Group.TYPE_SYSTEM_GROUP;
|
||||||
@@ -264,4 +273,17 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
|
|||||||
return externalId;
|
return externalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRoleToBeOrganization(String role) {
|
||||||
|
if (this.orgIncludes.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (Pattern regex : this.orgIncludes) {
|
||||||
|
Matcher matcher = regex.matcher(role);
|
||||||
|
if (matcher.matches())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user