Loading pom.xml +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.inteligr8.activiti</groupId> <artifactId>keycloak-activiti-app-ext</artifactId> <version>1.1.4</version> <version>1.2.0</version> <name>Keycloak Authentication & Authorization for APS</name> <properties> Loading src/main/java/com/inteligr8/activiti/ActivitiAppAdminGroupFixer.java 0 → 100644 +128 −0 Original line number Diff line number Diff line package com.inteligr8.activiti; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.activiti.domain.idm.Group; import com.activiti.domain.idm.GroupCapability; import com.activiti.domain.idm.Tenant; import com.activiti.service.api.GroupService; /** * This class/bean overrides the APS security configuration with a collection * of implementations. The OOTB extension only provides one override. This * uses that extension point, but delegates it out to multiple possible * implementations. * * Order cannot be controlled, so it should not be assumed in any adapter * implementation. * * @author brian@inteligr8.com */ @Component public class ActivitiAppAdminGroupFixer implements DataFixer { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final List<String> adminCapabilities = Arrays.asList( "access-all-models-in-tenant", "access-editor", "access-reports", "publish-app-to-dashboard", "tenant-admin", "tenant-admin-api", "upload-license"); @Autowired(required = false) private GroupService groupService; @Autowired private TenantFinderService tenantFinderService; @Value("${keycloak-ext.group.admins.name:admins}") private String adminGroupName; @Value("${keycloak-ext.group.admins.externalId:#{null}}") private String adminGroupExternalId; @Value("${keycloak-ext.group.admins.validate:false}") private boolean validateAdministratorsGroup; @Override public void fix() { this.logger.trace("fix()"); if (this.logger.isTraceEnabled()) this.logGroups(); if (this.validateAdministratorsGroup) this.validateAdmins(); } private void logGroups() { if (this.groupService == null) return; Collection<Tenant> tenants = this.tenantFinderService.getTenants(); for (Tenant tenant : tenants) { this.logger.trace("Tenant: {} => {}", tenant.getId(), tenant.getName()); this.logger.trace("Functional groups: {}", this.toGroupNames(this.groupService.getFunctionalGroups(tenant.getId()))); this.logger.trace("System groups: {}", this.toGroupNames(this.groupService.getSystemGroups(tenant.getId()))); } this.logger.trace("Tenant: null"); this.logger.trace("Functional groups: {}", this.toGroupNames(this.groupService.getFunctionalGroups(null))); this.logger.trace("System groups: {}", this.toGroupNames(this.groupService.getSystemGroups(null))); } private void validateAdmins() { if (this.groupService == null) return; Long tenantId = this.tenantFinderService.findTenantId(); Group group = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group == null) { List<Group> groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); if (!groups.isEmpty()) group = groups.iterator().next(); } if (group == null) { this.logger.info("Creating group: {} ({})", this.adminGroupName, this.adminGroupExternalId); if (this.adminGroupExternalId != null) { group = this.groupService.createGroupFromExternalStore( this.adminGroupExternalId, tenantId, Group.TYPE_SYSTEM_GROUP, null, this.adminGroupName, new Date()); } else { group = this.groupService.createGroup(this.adminGroupName, tenantId, Group.TYPE_SYSTEM_GROUP, null); } } this.logger.debug("Checking group capabilities: {}", group.getName()); Group groupWithCaps = this.groupService.getGroup(group.getId(), false, true, false, false); Set<String> adminCaps = new HashSet<>(this.adminCapabilities); for (GroupCapability cap : groupWithCaps.getCapabilities()) adminCaps.remove(cap.getName()); if (!adminCaps.isEmpty()) { this.logger.info("Granting group '{}' capabilities: {}", group.getName(), adminCaps); this.groupService.addCapabilitiesToGroup(group.getId(), new ArrayList<>(adminCaps)); } } private Collection<String> toGroupNames(Collection<Group> groups) { List<String> groupNames = new ArrayList<>(groups.size()); for (Group group : groups) groupNames.add(group.getName() + " [" + group.getExternalId() + "]"); return groupNames; } } src/main/java/com/inteligr8/activiti/ActivitiAppAdminMembersFixer.java 0 → 100644 +86 −0 Original line number Diff line number Diff line package com.inteligr8.activiti; import java.util.Arrays; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.activiti.domain.idm.Group; import com.activiti.domain.idm.User; import com.activiti.service.api.GroupService; import com.activiti.service.api.UserService; /** * This class/bean overrides the APS security configuration with a collection * of implementations. The OOTB extension only provides one override. This * uses that extension point, but delegates it out to multiple possible * implementations. * * Order cannot be controlled, so it should not be assumed in any adapter * implementation. * * @author brian@inteligr8.com */ @Component public class ActivitiAppAdminMembersFixer implements DataFixer { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired(required = false) private UserService userService; @Autowired(required = false) private GroupService groupService; @Autowired private TenantFinderService tenantFinderService; @Value("${keycloak-ext.default.admins.users:#{null}}") private String adminUserStrs; @Value("${keycloak-ext.group.admins.name:admins}") private String adminGroupName; @Value("${keycloak-ext.group.admins.externalId:#{null}}") private String adminGroupExternalId; @Override public void fix() { this.logger.trace("fix()"); if (this.adminUserStrs != null && this.adminUserStrs.length() > 0) this.associateAdmins(); } private void associateAdmins() { if (this.userService == null || this.groupService == null) return; List<String> adminUsers = Arrays.asList(this.adminUserStrs.split(",")); if (adminUsers.isEmpty()) return; Long tenantId = this.tenantFinderService.findTenantId(); List<Group> groups; Group group1 = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group1 != null) { groups = Arrays.asList(group1); } else { groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); } this.logger.debug("Found {} admin group(s)", groups.size()); for (String email : adminUsers) { User user = this.userService.findUserByEmail(email); this.logger.debug("Adding {} to admin group(s)", user.getEmail()); for (Group group : groups) this.groupService.addUserToGroup(group, user); } } } src/main/java/com/inteligr8/activiti/DataFixer.java 0 → 100644 +7 −0 Original line number Diff line number Diff line package com.inteligr8.activiti; public interface DataFixer { void fix(); } src/main/java/com/inteligr8/activiti/Inteligr8SecurityConfigurationRegistry.java +5 −152 Original line number Diff line number Diff line package com.inteligr8.activiti; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import com.activiti.api.security.AlfrescoSecurityConfigOverride; import com.activiti.domain.idm.Group; import com.activiti.domain.idm.GroupCapability; import com.activiti.domain.idm.Tenant; import com.activiti.domain.idm.User; import com.activiti.service.api.GroupService; import com.activiti.service.api.UserService; import com.activiti.service.idm.TenantService; import com.activiti.service.license.LicenseService; /** * This class/bean overrides the APS security configuration with a collection Loading @@ -43,44 +28,11 @@ public class Inteligr8SecurityConfigurationRegistry implements AlfrescoSecurityC private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final List<String> adminCapabilities = Arrays.asList( "access-all-models-in-tenant", "access-editor", "access-reports", "publish-app-to-dashboard", "tenant-admin", "tenant-admin-api", "upload-license"); @Autowired private List<ActivitiSecurityConfigAdapter> adapters; @Autowired(required = false) private LicenseService licenseService; @Autowired(required = false) private TenantService tenantService; @Autowired(required = false) private UserService userService; @Autowired(required = false) private GroupService groupService; @Value("${keycloak-ext.tenant:#{null}}") private String tenant; @Value("${keycloak-ext.default.admins.users:#{null}}") private String adminUserStrs; @Value("${keycloak-ext.group.admins.name:admins}") private String adminGroupName; @Value("${keycloak-ext.group.admins.externalId:#{null}}") private String adminGroupExternalId; @Value("${keycloak-ext.group.admins.validate:false}") private boolean validateAdministratorsGroup; private List<DataFixer> fixers; @Override public void configureGlobal(AuthenticationManagerBuilder authmanBuilder, UserDetailsService userDetailsService) { Loading @@ -88,12 +40,10 @@ public class Inteligr8SecurityConfigurationRegistry implements AlfrescoSecurityC Collections.sort(this.adapters); if (this.logger.isTraceEnabled()) this.logGroups(); if (this.validateAdministratorsGroup) this.validateAdmins(); if (this.adminUserStrs != null && this.adminUserStrs.length() > 0) this.associateAdmins(); if (this.fixers != null) { for (DataFixer fixer : this.fixers) fixer.fix(); } for (ActivitiSecurityConfigAdapter adapter : this.adapters) { if (adapter.isEnabled()) { Loading @@ -106,101 +56,4 @@ public class Inteligr8SecurityConfigurationRegistry implements AlfrescoSecurityC } } private void logGroups() { if (this.groupService == null) return; List<Object[]> tenantObjs = this.tenantService.getAllTenants(); for (Object[] tenantObj : tenantObjs) { Long tenantId = (Long)tenantObj[0]; if (tenantId != null) { Tenant tenant = this.tenantService.getTenant(tenantId); this.logger.trace("Tenant: {} => {}", tenantId, tenant.getName()); this.logger.trace("Functional groups: {}", this.toGroupNames(this.groupService.getFunctionalGroups(tenantId))); this.logger.trace("System groups: {}", this.toGroupNames(this.groupService.getSystemGroups(tenantId))); } } } private void validateAdmins() { if (this.groupService == null) return; Long tenantId = this.findTenantId(); Group group = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group == null) { List<Group> groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); if (!groups.isEmpty()) group = groups.iterator().next(); } if (group == null) { this.logger.info("Creating group: {} ({})", this.adminGroupName, this.adminGroupExternalId); if (this.adminGroupExternalId != null) { group = this.groupService.createGroupFromExternalStore( this.adminGroupExternalId, tenantId, Group.TYPE_SYSTEM_GROUP, null, this.adminGroupName, new Date()); } else { group = this.groupService.createGroup(this.adminGroupName, tenantId, Group.TYPE_SYSTEM_GROUP, null); } } this.logger.debug("Checking group capabilities: {}", group.getName()); Group groupWithCaps = this.groupService.getGroup(group.getId(), false, true, false, false); Set<String> adminCaps = new HashSet<>(this.adminCapabilities); for (GroupCapability cap : groupWithCaps.getCapabilities()) adminCaps.remove(cap.getName()); if (!adminCaps.isEmpty()) { this.logger.info("Granting group '{}' capabilities: {}", group.getName(), adminCaps); this.groupService.addCapabilitiesToGroup(group.getId(), new ArrayList<>(adminCaps)); } } private void associateAdmins() { if (this.userService == null || this.groupService == null) return; List<String> adminUsers = Arrays.asList(this.adminUserStrs.split(",")); if (adminUsers.isEmpty()) return; Long tenantId = this.findTenantId(); List<Group> groups; Group group1 = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group1 != null) { groups = Arrays.asList(group1); } else { groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); } this.logger.debug("Found {} admin group(s)", groups.size()); for (String email : adminUsers) { User user = this.userService.findUserByEmail(email); this.logger.debug("Adding {} to admin group(s)", user.getEmail()); for (Group group : groups) this.groupService.addUserToGroup(group, user); } } private Long findTenantId() { String tenantName = this.tenant == null ? this.licenseService.getDefaultTenantName() : this.tenant; this.logger.trace("Using Tenant: {}", tenantName); List<Tenant> tenants = this.tenantService.findTenantsByName(tenantName); if (tenants == null || tenants.isEmpty()) { this.logger.warn("Default tenant not found"); return null; } Tenant tenant = tenants.iterator().next(); return tenant.getId(); } private Collection<String> toGroupNames(Collection<Group> groups) { List<String> groupNames = new ArrayList<>(groups.size()); for (Group group : groups) groupNames.add(group.getName() + " [" + group.getExternalId() + "]"); return groupNames; } } Loading
pom.xml +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.inteligr8.activiti</groupId> <artifactId>keycloak-activiti-app-ext</artifactId> <version>1.1.4</version> <version>1.2.0</version> <name>Keycloak Authentication & Authorization for APS</name> <properties> Loading
src/main/java/com/inteligr8/activiti/ActivitiAppAdminGroupFixer.java 0 → 100644 +128 −0 Original line number Diff line number Diff line package com.inteligr8.activiti; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.activiti.domain.idm.Group; import com.activiti.domain.idm.GroupCapability; import com.activiti.domain.idm.Tenant; import com.activiti.service.api.GroupService; /** * This class/bean overrides the APS security configuration with a collection * of implementations. The OOTB extension only provides one override. This * uses that extension point, but delegates it out to multiple possible * implementations. * * Order cannot be controlled, so it should not be assumed in any adapter * implementation. * * @author brian@inteligr8.com */ @Component public class ActivitiAppAdminGroupFixer implements DataFixer { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final List<String> adminCapabilities = Arrays.asList( "access-all-models-in-tenant", "access-editor", "access-reports", "publish-app-to-dashboard", "tenant-admin", "tenant-admin-api", "upload-license"); @Autowired(required = false) private GroupService groupService; @Autowired private TenantFinderService tenantFinderService; @Value("${keycloak-ext.group.admins.name:admins}") private String adminGroupName; @Value("${keycloak-ext.group.admins.externalId:#{null}}") private String adminGroupExternalId; @Value("${keycloak-ext.group.admins.validate:false}") private boolean validateAdministratorsGroup; @Override public void fix() { this.logger.trace("fix()"); if (this.logger.isTraceEnabled()) this.logGroups(); if (this.validateAdministratorsGroup) this.validateAdmins(); } private void logGroups() { if (this.groupService == null) return; Collection<Tenant> tenants = this.tenantFinderService.getTenants(); for (Tenant tenant : tenants) { this.logger.trace("Tenant: {} => {}", tenant.getId(), tenant.getName()); this.logger.trace("Functional groups: {}", this.toGroupNames(this.groupService.getFunctionalGroups(tenant.getId()))); this.logger.trace("System groups: {}", this.toGroupNames(this.groupService.getSystemGroups(tenant.getId()))); } this.logger.trace("Tenant: null"); this.logger.trace("Functional groups: {}", this.toGroupNames(this.groupService.getFunctionalGroups(null))); this.logger.trace("System groups: {}", this.toGroupNames(this.groupService.getSystemGroups(null))); } private void validateAdmins() { if (this.groupService == null) return; Long tenantId = this.tenantFinderService.findTenantId(); Group group = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group == null) { List<Group> groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); if (!groups.isEmpty()) group = groups.iterator().next(); } if (group == null) { this.logger.info("Creating group: {} ({})", this.adminGroupName, this.adminGroupExternalId); if (this.adminGroupExternalId != null) { group = this.groupService.createGroupFromExternalStore( this.adminGroupExternalId, tenantId, Group.TYPE_SYSTEM_GROUP, null, this.adminGroupName, new Date()); } else { group = this.groupService.createGroup(this.adminGroupName, tenantId, Group.TYPE_SYSTEM_GROUP, null); } } this.logger.debug("Checking group capabilities: {}", group.getName()); Group groupWithCaps = this.groupService.getGroup(group.getId(), false, true, false, false); Set<String> adminCaps = new HashSet<>(this.adminCapabilities); for (GroupCapability cap : groupWithCaps.getCapabilities()) adminCaps.remove(cap.getName()); if (!adminCaps.isEmpty()) { this.logger.info("Granting group '{}' capabilities: {}", group.getName(), adminCaps); this.groupService.addCapabilitiesToGroup(group.getId(), new ArrayList<>(adminCaps)); } } private Collection<String> toGroupNames(Collection<Group> groups) { List<String> groupNames = new ArrayList<>(groups.size()); for (Group group : groups) groupNames.add(group.getName() + " [" + group.getExternalId() + "]"); return groupNames; } }
src/main/java/com/inteligr8/activiti/ActivitiAppAdminMembersFixer.java 0 → 100644 +86 −0 Original line number Diff line number Diff line package com.inteligr8.activiti; import java.util.Arrays; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.activiti.domain.idm.Group; import com.activiti.domain.idm.User; import com.activiti.service.api.GroupService; import com.activiti.service.api.UserService; /** * This class/bean overrides the APS security configuration with a collection * of implementations. The OOTB extension only provides one override. This * uses that extension point, but delegates it out to multiple possible * implementations. * * Order cannot be controlled, so it should not be assumed in any adapter * implementation. * * @author brian@inteligr8.com */ @Component public class ActivitiAppAdminMembersFixer implements DataFixer { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired(required = false) private UserService userService; @Autowired(required = false) private GroupService groupService; @Autowired private TenantFinderService tenantFinderService; @Value("${keycloak-ext.default.admins.users:#{null}}") private String adminUserStrs; @Value("${keycloak-ext.group.admins.name:admins}") private String adminGroupName; @Value("${keycloak-ext.group.admins.externalId:#{null}}") private String adminGroupExternalId; @Override public void fix() { this.logger.trace("fix()"); if (this.adminUserStrs != null && this.adminUserStrs.length() > 0) this.associateAdmins(); } private void associateAdmins() { if (this.userService == null || this.groupService == null) return; List<String> adminUsers = Arrays.asList(this.adminUserStrs.split(",")); if (adminUsers.isEmpty()) return; Long tenantId = this.tenantFinderService.findTenantId(); List<Group> groups; Group group1 = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group1 != null) { groups = Arrays.asList(group1); } else { groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); } this.logger.debug("Found {} admin group(s)", groups.size()); for (String email : adminUsers) { User user = this.userService.findUserByEmail(email); this.logger.debug("Adding {} to admin group(s)", user.getEmail()); for (Group group : groups) this.groupService.addUserToGroup(group, user); } } }
src/main/java/com/inteligr8/activiti/DataFixer.java 0 → 100644 +7 −0 Original line number Diff line number Diff line package com.inteligr8.activiti; public interface DataFixer { void fix(); }
src/main/java/com/inteligr8/activiti/Inteligr8SecurityConfigurationRegistry.java +5 −152 Original line number Diff line number Diff line package com.inteligr8.activiti; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import com.activiti.api.security.AlfrescoSecurityConfigOverride; import com.activiti.domain.idm.Group; import com.activiti.domain.idm.GroupCapability; import com.activiti.domain.idm.Tenant; import com.activiti.domain.idm.User; import com.activiti.service.api.GroupService; import com.activiti.service.api.UserService; import com.activiti.service.idm.TenantService; import com.activiti.service.license.LicenseService; /** * This class/bean overrides the APS security configuration with a collection Loading @@ -43,44 +28,11 @@ public class Inteligr8SecurityConfigurationRegistry implements AlfrescoSecurityC private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final List<String> adminCapabilities = Arrays.asList( "access-all-models-in-tenant", "access-editor", "access-reports", "publish-app-to-dashboard", "tenant-admin", "tenant-admin-api", "upload-license"); @Autowired private List<ActivitiSecurityConfigAdapter> adapters; @Autowired(required = false) private LicenseService licenseService; @Autowired(required = false) private TenantService tenantService; @Autowired(required = false) private UserService userService; @Autowired(required = false) private GroupService groupService; @Value("${keycloak-ext.tenant:#{null}}") private String tenant; @Value("${keycloak-ext.default.admins.users:#{null}}") private String adminUserStrs; @Value("${keycloak-ext.group.admins.name:admins}") private String adminGroupName; @Value("${keycloak-ext.group.admins.externalId:#{null}}") private String adminGroupExternalId; @Value("${keycloak-ext.group.admins.validate:false}") private boolean validateAdministratorsGroup; private List<DataFixer> fixers; @Override public void configureGlobal(AuthenticationManagerBuilder authmanBuilder, UserDetailsService userDetailsService) { Loading @@ -88,12 +40,10 @@ public class Inteligr8SecurityConfigurationRegistry implements AlfrescoSecurityC Collections.sort(this.adapters); if (this.logger.isTraceEnabled()) this.logGroups(); if (this.validateAdministratorsGroup) this.validateAdmins(); if (this.adminUserStrs != null && this.adminUserStrs.length() > 0) this.associateAdmins(); if (this.fixers != null) { for (DataFixer fixer : this.fixers) fixer.fix(); } for (ActivitiSecurityConfigAdapter adapter : this.adapters) { if (adapter.isEnabled()) { Loading @@ -106,101 +56,4 @@ public class Inteligr8SecurityConfigurationRegistry implements AlfrescoSecurityC } } private void logGroups() { if (this.groupService == null) return; List<Object[]> tenantObjs = this.tenantService.getAllTenants(); for (Object[] tenantObj : tenantObjs) { Long tenantId = (Long)tenantObj[0]; if (tenantId != null) { Tenant tenant = this.tenantService.getTenant(tenantId); this.logger.trace("Tenant: {} => {}", tenantId, tenant.getName()); this.logger.trace("Functional groups: {}", this.toGroupNames(this.groupService.getFunctionalGroups(tenantId))); this.logger.trace("System groups: {}", this.toGroupNames(this.groupService.getSystemGroups(tenantId))); } } } private void validateAdmins() { if (this.groupService == null) return; Long tenantId = this.findTenantId(); Group group = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group == null) { List<Group> groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); if (!groups.isEmpty()) group = groups.iterator().next(); } if (group == null) { this.logger.info("Creating group: {} ({})", this.adminGroupName, this.adminGroupExternalId); if (this.adminGroupExternalId != null) { group = this.groupService.createGroupFromExternalStore( this.adminGroupExternalId, tenantId, Group.TYPE_SYSTEM_GROUP, null, this.adminGroupName, new Date()); } else { group = this.groupService.createGroup(this.adminGroupName, tenantId, Group.TYPE_SYSTEM_GROUP, null); } } this.logger.debug("Checking group capabilities: {}", group.getName()); Group groupWithCaps = this.groupService.getGroup(group.getId(), false, true, false, false); Set<String> adminCaps = new HashSet<>(this.adminCapabilities); for (GroupCapability cap : groupWithCaps.getCapabilities()) adminCaps.remove(cap.getName()); if (!adminCaps.isEmpty()) { this.logger.info("Granting group '{}' capabilities: {}", group.getName(), adminCaps); this.groupService.addCapabilitiesToGroup(group.getId(), new ArrayList<>(adminCaps)); } } private void associateAdmins() { if (this.userService == null || this.groupService == null) return; List<String> adminUsers = Arrays.asList(this.adminUserStrs.split(",")); if (adminUsers.isEmpty()) return; Long tenantId = this.findTenantId(); List<Group> groups; Group group1 = this.groupService.getGroupByExternalIdAndTenantId(this.adminGroupExternalId, tenantId); if (group1 != null) { groups = Arrays.asList(group1); } else { groups = this.groupService.getGroupByNameAndTenantId(this.adminGroupName, tenantId); } this.logger.debug("Found {} admin group(s)", groups.size()); for (String email : adminUsers) { User user = this.userService.findUserByEmail(email); this.logger.debug("Adding {} to admin group(s)", user.getEmail()); for (Group group : groups) this.groupService.addUserToGroup(group, user); } } private Long findTenantId() { String tenantName = this.tenant == null ? this.licenseService.getDefaultTenantName() : this.tenant; this.logger.trace("Using Tenant: {}", tenantName); List<Tenant> tenants = this.tenantService.findTenantsByName(tenantName); if (tenants == null || tenants.isEmpty()) { this.logger.warn("Default tenant not found"); return null; } Tenant tenant = tenants.iterator().next(); return tenant.getId(); } private Collection<String> toGroupNames(Collection<Group> groups) { List<String> groupNames = new ArrayList<>(groups.size()); for (Group group : groups) groupNames.add(group.getName() + " [" + group.getExternalId() + "]"); return groupNames; } }