Commit 28a6f4d1 authored by Brian Long's avatar Brian Long
Browse files

allowing for more dynamic organization/capability sync control

parent 07a5ed95
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -42,8 +42,8 @@ The library is highly configurable. You configure it with properties specified
### For Activiti App Only

| 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. |

### Rare
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.inteligr8.activiti</groupId>
	<artifactId>keycloak-activiti-app-ext</artifactId>
	<version>1.2-SNAPSHOT</version>
	<version>1.3-SNAPSHOT</version>
	<name>Keycloak Authentication &amp; Authorization for APS</name>

	<properties>
+3 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.OverridingMethodsMustInvokeSuper;

import org.apache.commons.lang3.StringUtils;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
@@ -71,6 +73,7 @@ public abstract class AbstractKeycloakActivitiAuthenticator implements Authentic
    protected final Set<Pattern> groupExcludes = new HashSet<>();
    
    @Override
    @OverridingMethodsMustInvokeSuper
    public void afterPropertiesSet() {
    	if (this.regexPatterns != null) {
    		String[] regexPatternStrs = StringUtils.split(this.regexPatterns, ',');
+33 −11
Original line number Diff line number Diff line
package com.inteligr8.activiti.keycloak;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.persistence.NonUniqueResultException;

import org.apache.commons.lang3.StringUtils;
@@ -59,15 +62,21 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
    @Value("${keycloak-ext.external.id:ais}")
    protected String externalIdmSource;

    @Value("${keycloak-ext.syncGroupAs:organization}")
    protected String syncGroupAs;
    @Value("${keycloak-ext.group.organization.regex.patterns:.*}")
    protected String regexOrgIncludes;

    protected boolean syncGroupAsOrganization() {
    	return !this.syncGroupAsCapability();
    }
    protected final Set<Pattern> orgIncludes = new HashSet<>();
    
    protected boolean syncGroupAsCapability() {
    	return this.syncGroupAs != null && this.syncGroupAs.toLowerCase().startsWith("cap");
    @Override
    @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]));
    	}
	}
    
    /**
@@ -163,8 +172,6 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
    		return;
    	}
    	
    	boolean syncAsOrg = this.syncGroupAsOrganization();
    	
		// check Activiti groups
		User userWithGroups = this.userService.getUser(user.getId(), true);
		for (Group group : userWithGroups.getGroups()) {
@@ -228,6 +235,8 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
			if (group == null) {
				if (this.createMissingGroup) {
					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 externalId = this.keycloakRoleToApsGroupExternalId(role.getKey());
					int type = syncAsOrg ? Group.TYPE_FUNCTIONAL_GROUP : Group.TYPE_SYSTEM_GROUP;
@@ -264,4 +273,17 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
    	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;
    }
    
}