auto create keycloak tenant groups
This commit is contained in:
parent
3e4316a627
commit
2e083df185
|
@ -9,6 +9,25 @@ import java.util.List;
|
|||
@ConfigurationProperties(prefix = "authorization")
|
||||
public class AuthorizationProperties {
|
||||
|
||||
private String globalAdminRole;
|
||||
|
||||
public String getGlobalAdminRole() {
|
||||
return globalAdminRole;
|
||||
}
|
||||
|
||||
public void setGlobalAdminRole(String globalAdminRole) {
|
||||
this.globalAdminRole = globalAdminRole;
|
||||
}
|
||||
private Boolean autoAssignGlobalAdminToNewTenants;
|
||||
|
||||
public Boolean getAutoAssignGlobalAdminToNewTenants() {
|
||||
return autoAssignGlobalAdminToNewTenants;
|
||||
}
|
||||
|
||||
public void setAutoAssignGlobalAdminToNewTenants(Boolean autoAssignGlobalAdminToNewTenants) {
|
||||
this.autoAssignGlobalAdminToNewTenants = autoAssignGlobalAdminToNewTenants;
|
||||
}
|
||||
|
||||
private List<String> allowedTenantRoles;
|
||||
|
||||
public List<String> getAllowedTenantRoles() {
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
package eu.eudat.service.keycloak;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding;
|
||||
|
||||
public class KeycloakAuthorityProperties {
|
||||
|
||||
private final String groupId, groupTitle;
|
||||
private String groupId;
|
||||
|
||||
@ConstructorBinding
|
||||
public KeycloakAuthorityProperties(String groupId, String groupTitle) {
|
||||
this.groupId = groupId;
|
||||
this.groupTitle = groupTitle;
|
||||
public KeycloakAuthorityProperties() {
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public String getGroupTitle() {
|
||||
return groupTitle;
|
||||
public void setGroupId(String groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,4 +19,14 @@ public class KeycloakResourcesConfiguration {
|
|||
return properties;
|
||||
}
|
||||
|
||||
public String getTenantGroupName(String tenantCode) {
|
||||
return properties.getTenantGroupsNamingStrategy()
|
||||
.replace("{tenantCode}", tenantCode);
|
||||
}
|
||||
|
||||
public String getTenantRoleAttributeValue(String tenantCode, String key) {
|
||||
return properties.getTenantAuthorities().get(key).getRoleAttributeValueStrategy()
|
||||
.replace("{tenantCode}", tenantCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,15 +10,41 @@ import java.util.HashMap;
|
|||
@ConditionalOnProperty(prefix = "keycloak-resources", name = "enabled", havingValue = "true")
|
||||
public class KeycloakResourcesProperties {
|
||||
|
||||
private final HashMap<String, KeycloakAuthorityProperties> authorities;
|
||||
private HashMap<String, KeycloakAuthorityProperties> authorities;
|
||||
private HashMap<String, KeycloakTenantAuthorityProperties> tenantAuthorities;
|
||||
|
||||
@ConstructorBinding
|
||||
public KeycloakResourcesProperties(HashMap<String, KeycloakAuthorityProperties> authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
private String tenantGroupsNamingStrategy;
|
||||
private String tenantRoleAttributeName;
|
||||
|
||||
public HashMap<String, KeycloakAuthorityProperties> getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
public void setAuthorities(HashMap<String, KeycloakAuthorityProperties> authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
|
||||
public HashMap<String, KeycloakTenantAuthorityProperties> getTenantAuthorities() {
|
||||
return tenantAuthorities;
|
||||
}
|
||||
|
||||
public void setTenantAuthorities(HashMap<String, KeycloakTenantAuthorityProperties> tenantAuthorities) {
|
||||
this.tenantAuthorities = tenantAuthorities;
|
||||
}
|
||||
|
||||
public String getTenantGroupsNamingStrategy() {
|
||||
return tenantGroupsNamingStrategy;
|
||||
}
|
||||
|
||||
public void setTenantGroupsNamingStrategy(String tenantGroupsNamingStrategy) {
|
||||
this.tenantGroupsNamingStrategy = tenantGroupsNamingStrategy;
|
||||
}
|
||||
|
||||
public String getTenantRoleAttributeName() {
|
||||
return tenantRoleAttributeName;
|
||||
}
|
||||
|
||||
public void setTenantRoleAttributeName(String tenantRoleAttributeName) {
|
||||
this.tenantRoleAttributeName = tenantRoleAttributeName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
package eu.eudat.service.keycloak;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface KeycloakService {
|
||||
|
||||
void addUserToGroup(UUID subjectId, String groupId);
|
||||
void removeUserFromGroup(@NotNull UUID subjectId, String groupId);
|
||||
void addUserToGroup(UUID subjectId, KeycloakRole role);
|
||||
void removeUserFromGroup(@NotNull UUID subjectId, KeycloakRole role);
|
||||
void assignClientRoleToUser(UUID subjectId, String clientId, KeycloakRole role);
|
||||
void removeClientRoleFromUser(UUID subjectId, String clientId, KeycloakRole role);
|
||||
void addUserToGroup(@NotNull String subjectId, String groupId);
|
||||
|
||||
void removeUserFromGroup(@NotNull String subjectId, String groupId);
|
||||
|
||||
void addUserToGlobalRoleGroup(String subjectId, String role);
|
||||
void removeUserGlobalRoleGroup(@NotNull String subjectId, String role);
|
||||
|
||||
void addUserToTenantRoleGroup(String subjectId, String tenantCode, String tenantRole);
|
||||
|
||||
void removeUserTenantRoleGroup(String subjectId, String tenantCode, String tenantRole);
|
||||
|
||||
void createTenantGroups(String tenantCode);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import gr.cite.commons.web.keycloak.api.configuration.KeycloakClientConfiguratio
|
|||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -27,56 +26,83 @@ public class KeycloakServiceImpl implements KeycloakService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addUserToGroup(@NotNull UUID subjectId, String groupId) {
|
||||
api.users().addUserToGroup(subjectId.toString(), groupId);
|
||||
public void addUserToGroup(@NotNull String subjectId, String groupId) {
|
||||
api.users().addUserToGroup(subjectId, groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUserFromGroup(@NotNull UUID subjectId, String groupId) {
|
||||
api.users().removeUserFromGroup(subjectId.toString(), groupId);
|
||||
public void removeUserFromGroup(@NotNull String subjectId, String groupId) {
|
||||
api.users().removeUserFromGroup(subjectId, groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addUserToGroup(UUID subjectId, KeycloakRole role) {
|
||||
KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().get(role.name());
|
||||
if (properties != null)
|
||||
addUserToGroup(subjectId, properties.getGroupId());
|
||||
public void addUserToGlobalRoleGroup(String subjectId, String role) {
|
||||
KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().get(role);
|
||||
if (properties != null) addUserToGroup(subjectId, properties.getGroupId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUserFromGroup(@NotNull UUID subjectId, KeycloakRole role) {
|
||||
KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().get(role.name());
|
||||
public void removeUserGlobalRoleGroup(@NotNull String subjectId, String role) {
|
||||
KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().get(role);
|
||||
if (properties != null)
|
||||
removeUserFromGroup(subjectId, properties.getGroupId());
|
||||
}
|
||||
//
|
||||
// @Override
|
||||
// public void assignClientRoleToUser(UUID subjectId, String clientId, KeycloakRole role) {
|
||||
// if (clientId == null)
|
||||
// clientId = clientConfiguration.getProperties().getClientId();
|
||||
// UserRepresentation user = api.users().findUserById(subjectId.toString());
|
||||
// user.getClientRoles().computeIfAbsent(clientId, k -> new ArrayList<>());
|
||||
// Set<String> clientRoles = new HashSet<>(Set.copyOf(user.getClientRoles().get(clientId)));
|
||||
// clientRoles.add(role.name());
|
||||
// user.getClientRoles().get(clientId).clear();
|
||||
// user.getClientRoles().get(clientId).addAll(clientRoles);
|
||||
// api.users().updateUser(subjectId.toString(), user);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void removeClientRoleFromUser(UUID subjectId, String clientId, KeycloakRole role) {
|
||||
// if (clientId == null) clientId = clientConfiguration.getProperties().getClientId();
|
||||
// UserRepresentation user = api.users().findUserById(subjectId.toString());
|
||||
// user.getClientRoles().computeIfAbsent(clientId, k -> new ArrayList<>());
|
||||
// Set<String> clientRoles = new HashSet<>(Set.copyOf(user.getClientRoles().get(clientId)));
|
||||
// clientRoles.remove(role.name());
|
||||
// user.getClientRoles().get(clientId).clear();
|
||||
// user.getClientRoles().get(clientId).addAll(clientRoles);
|
||||
// api.users().updateUser(subjectId.toString(), user);
|
||||
// }
|
||||
//
|
||||
// public List<GroupRepresentation> getUserGroups(UUID subjectId) {
|
||||
// return api.users().getGroups(subjectId.toString());
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void assignClientRoleToUser(UUID subjectId, String clientId, KeycloakRole role) {
|
||||
if (clientId == null)
|
||||
clientId = clientConfiguration.getProperties().getClientId();
|
||||
UserRepresentation user = api.users().findUserById(subjectId.toString());
|
||||
user.getClientRoles().computeIfAbsent(clientId, k -> new ArrayList<>());
|
||||
Set<String> clientRoles = new HashSet<>(Set.copyOf(user.getClientRoles().get(clientId)));
|
||||
clientRoles.add(role.name());
|
||||
user.getClientRoles().get(clientId).clear();
|
||||
user.getClientRoles().get(clientId).addAll(clientRoles);
|
||||
api.users().updateUser(subjectId.toString(), user);
|
||||
public void addUserToTenantRoleGroup(String subjectId, String tenantCode, String tenantRole) {
|
||||
GroupRepresentation group = api.groups().findGroupByPath(getTenantAuthorityParentPath(tenantRole) + "/" + configuration.getTenantGroupName(tenantCode));
|
||||
addUserToGroup(subjectId, group.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeClientRoleFromUser(UUID subjectId, String clientId, KeycloakRole role) {
|
||||
if (clientId == null) clientId = clientConfiguration.getProperties().getClientId();
|
||||
UserRepresentation user = api.users().findUserById(subjectId.toString());
|
||||
user.getClientRoles().computeIfAbsent(clientId, k -> new ArrayList<>());
|
||||
Set<String> clientRoles = new HashSet<>(Set.copyOf(user.getClientRoles().get(clientId)));
|
||||
clientRoles.remove(role.name());
|
||||
user.getClientRoles().get(clientId).clear();
|
||||
user.getClientRoles().get(clientId).addAll(clientRoles);
|
||||
api.users().updateUser(subjectId.toString(), user);
|
||||
public void removeUserTenantRoleGroup(String subjectId, String tenantCode, String tenantRole) {
|
||||
GroupRepresentation group = api.groups().findGroupByPath(getTenantAuthorityParentPath(tenantRole) + "/" + configuration.getTenantGroupName(tenantCode));
|
||||
removeUserFromGroup(subjectId, group.getId());
|
||||
}
|
||||
|
||||
public List<GroupRepresentation> getUserGroups(UUID subjectId) {
|
||||
return api.users().getGroups(subjectId.toString());
|
||||
private String getTenantAuthorityParentPath(String tenantRole) {
|
||||
GroupRepresentation parent = api.groups().findGroupById(configuration.getProperties().getTenantAuthorities().get(tenantRole).getParent());
|
||||
return parent.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTenantGroups(String tenantCode) {
|
||||
for (Map.Entry<String,KeycloakTenantAuthorityProperties> entry :configuration.getProperties().getTenantAuthorities().entrySet()){
|
||||
GroupRepresentation group = new GroupRepresentation();
|
||||
group.setName(configuration.getTenantGroupName(tenantCode));
|
||||
HashMap<String, List<String>> user_attributes = new HashMap<>();
|
||||
user_attributes.put(this.configuration.getProperties().getTenantRoleAttributeName(), List.of(configuration.getTenantRoleAttributeValue(tenantCode, entry.getKey())));
|
||||
group.setAttributes(user_attributes);
|
||||
api.groups().addGroupWithParent(group, configuration.getProperties().getTenantAuthorities().get(entry.getKey()).getParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package eu.eudat.service.keycloak;
|
||||
|
||||
public class KeycloakTenantAuthorityProperties {
|
||||
|
||||
private String parent;
|
||||
private String roleAttributeValueStrategy;
|
||||
|
||||
public KeycloakTenantAuthorityProperties() {
|
||||
}
|
||||
|
||||
public String getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(String parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getRoleAttributeValueStrategy() {
|
||||
return roleAttributeValueStrategy;
|
||||
}
|
||||
|
||||
public void setRoleAttributeValueStrategy(String roleAttributeValueStrategy) {
|
||||
this.roleAttributeValueStrategy = roleAttributeValueStrategy;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,34 @@
|
|||
package eu.eudat.service.tenant;
|
||||
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.authorization.AuthorizationProperties;
|
||||
import eu.eudat.authorization.Permission;
|
||||
import eu.eudat.commons.XmlHandlingService;
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.scope.tenant.TenantScope;
|
||||
import eu.eudat.commons.types.tenant.*;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.data.TenantEntity;
|
||||
import eu.eudat.data.TenantEntityManager;
|
||||
import eu.eudat.data.UserCredentialEntity;
|
||||
import eu.eudat.data.UserRoleEntity;
|
||||
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
||||
import eu.eudat.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEvent;
|
||||
import eu.eudat.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEvent;
|
||||
import eu.eudat.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEventHandler;
|
||||
import eu.eudat.model.Tenant;
|
||||
import eu.eudat.model.UserCredential;
|
||||
import eu.eudat.model.builder.TenantBuilder;
|
||||
import eu.eudat.model.deleter.TenantDeleter;
|
||||
import eu.eudat.model.deleter.UserRoleDeleter;
|
||||
import eu.eudat.model.persist.TenantPersist;
|
||||
import eu.eudat.model.persist.tenantconfig.*;
|
||||
import eu.eudat.model.tenantconfig.TenantSource;
|
||||
import eu.eudat.query.UserCredentialQuery;
|
||||
import eu.eudat.query.UserRoleQuery;
|
||||
import eu.eudat.service.encryption.EncryptionService;
|
||||
import eu.eudat.service.keycloak.KeycloakService;
|
||||
import eu.eudat.service.responseutils.ResponseUtilsService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
|
@ -73,6 +82,11 @@ public class TenantServiceImpl implements TenantService {
|
|||
private final TenantProperties properties;
|
||||
private final TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler;
|
||||
private final TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler;
|
||||
private final KeycloakService keycloakService;
|
||||
private final AuthorizationProperties authorizationProperties;
|
||||
private final TenantScope tenantScope;
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
|
||||
@Autowired
|
||||
public TenantServiceImpl(
|
||||
|
@ -84,7 +98,7 @@ public class TenantServiceImpl implements TenantService {
|
|||
MessageSource messageSource,
|
||||
XmlHandlingService xmlHandlingService,
|
||||
ErrorThesaurusProperties errors,
|
||||
EncryptionService encryptionService, TenantProperties properties, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler) {
|
||||
EncryptionService encryptionService, TenantProperties properties, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -97,6 +111,10 @@ public class TenantServiceImpl implements TenantService {
|
|||
this.properties = properties;
|
||||
this.tenantTouchedIntegrationEventHandler = tenantTouchedIntegrationEventHandler;
|
||||
this.tenantRemovalIntegrationEventHandler = tenantRemovalIntegrationEventHandler;
|
||||
this.keycloakService = keycloakService;
|
||||
this.authorizationProperties = authorizationProperties;
|
||||
this.tenantScope = tenantScope;
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -132,6 +150,11 @@ public class TenantServiceImpl implements TenantService {
|
|||
|
||||
this.entityManager.flush();
|
||||
|
||||
if (!isUpdate) {
|
||||
this.keycloakService.createTenantGroups(data.getCode());
|
||||
this.autoAssignGlobalAdminsToNewTenant(data);
|
||||
}
|
||||
|
||||
TenantTouchedIntegrationEvent tenantTouchedIntegrationEvent = new TenantTouchedIntegrationEvent();
|
||||
tenantTouchedIntegrationEvent.setId(data.getId());
|
||||
tenantTouchedIntegrationEvent.setCode(data.getCode());
|
||||
|
@ -140,6 +163,39 @@ public class TenantServiceImpl implements TenantService {
|
|||
return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data);
|
||||
}
|
||||
|
||||
private void autoAssignGlobalAdminsToNewTenant(TenantEntity tenant){
|
||||
if (!this.authorizationProperties.getAutoAssignGlobalAdminToNewTenants()) return;
|
||||
List<UserRoleEntity> existingItems;
|
||||
List<UserCredentialEntity> userCredentialEntities;
|
||||
try {
|
||||
this.tenantScope.setTempTenant(this.entityManager.getEntityManager(), null, this.tenantScope.getDefaultTenantCode());
|
||||
|
||||
existingItems = this.queryFactory.query(UserRoleQuery.class).tenantIsSet(false).roles(this.authorizationProperties.getGlobalAdminRole()).collect();
|
||||
userCredentialEntities = this.queryFactory.query(UserCredentialQuery.class).userIds(existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()).collect();
|
||||
} finally {
|
||||
this.tenantScope.removeTempTenant(this.entityManager.getEntityManager());
|
||||
}
|
||||
try {
|
||||
this.tenantScope.setTempTenant(this.entityManager.getEntityManager(), tenant.getId(), tenant.getCode());
|
||||
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
|
||||
UserCredentialEntity userCredential = userCredentialEntities.stream().filter(x-> !this.conventionService.isNullOrEmpty(x.getExternalId()) && x.getUserId().equals(userId)).findFirst().orElse(null);
|
||||
if (userCredential == null) continue;
|
||||
UserRoleEntity item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(userId);
|
||||
item.setRole(this.authorizationProperties.getGlobalAdminRole());
|
||||
item.setCreatedAt(Instant.now());
|
||||
this.entityManager.persist(item);
|
||||
this.keycloakService.addUserToGlobalRoleGroup(userCredential.getExternalId(), this.authorizationProperties.getGlobalAdminRole());
|
||||
}
|
||||
} finally {
|
||||
this.tenantScope.removeTempTenant(this.entityManager.getEntityManager());
|
||||
}
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
}
|
||||
|
||||
private @NotNull TenantConfigEntity buildConfigEntity(TenantConfigPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
TenantConfigEntity data = new TenantConfigEntity();
|
||||
if (persist == null) return data;
|
||||
|
|
|
@ -29,7 +29,6 @@ import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
|||
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.userremoval.UserRemovalIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.usertouched.UserTouchedIntegrationEventHandler;
|
||||
import eu.eudat.model.Tenant;
|
||||
import eu.eudat.model.User;
|
||||
import eu.eudat.model.UserContactInfo;
|
||||
import eu.eudat.model.UserCredential;
|
||||
|
@ -41,7 +40,6 @@ import eu.eudat.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
|
|||
import eu.eudat.query.*;
|
||||
import eu.eudat.service.actionconfirmation.ActionConfirmationService;
|
||||
import eu.eudat.service.elastic.ElasticService;
|
||||
import eu.eudat.service.keycloak.KeycloakRole;
|
||||
import eu.eudat.service.keycloak.KeycloakService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
|
@ -252,7 +250,7 @@ public class UserServiceImpl implements UserService {
|
|||
throw new MyApplicationException("Currently cannot update roles for this user");
|
||||
if (userCredentials.getFirst().getExternalId() == null)
|
||||
throw new MyApplicationException("Currently cannot update roles for this user");
|
||||
UUID subjectId = UUID.fromString(userCredentials.getFirst().getExternalId());
|
||||
String subjectId = userCredentials.getFirst().getExternalId();
|
||||
|
||||
this.applyGlobalRoles(data.getId(), subjectId, model);
|
||||
|
||||
|
@ -266,33 +264,39 @@ public class UserServiceImpl implements UserService {
|
|||
return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, User._id), data);
|
||||
}
|
||||
|
||||
private void applyGlobalRoles(UUID userId, UUID subjectId, UserRolePatchPersist model) throws InvalidApplicationException {
|
||||
List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(userId).tenantIsSet(false).roles(this.authorizationProperties.getAllowedGlobalRoles()).collect();
|
||||
List<UUID> foundIds = new ArrayList<>();
|
||||
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank() && this.authorizationProperties.getAllowedGlobalRoles().contains(x)).distinct().toList()) {
|
||||
UserRoleEntity item = existingItems.stream().filter(x-> x.getRole().equals(roleName)).findFirst().orElse(null);
|
||||
if (item == null) {
|
||||
item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(userId);
|
||||
item.setRole(roleName);
|
||||
item.setCreatedAt(Instant.now());
|
||||
this.entityManager.persist(item);
|
||||
this.keycloakService.addUserToGroup(subjectId, KeycloakRole.valueOf(roleName));
|
||||
private void applyGlobalRoles(UUID userId, String subjectId, UserRolePatchPersist model) throws InvalidApplicationException {
|
||||
try {
|
||||
this.tenantScope.setTempTenant(this.entityManager.getEntityManager(), null, this.tenantScope.getDefaultTenantCode());
|
||||
|
||||
List<UserRoleEntity> existingItems = this.queryFactory.query(UserRoleQuery.class).userIds(userId).tenantIsSet(false).roles(this.authorizationProperties.getAllowedGlobalRoles()).collect();
|
||||
List<UUID> foundIds = new ArrayList<>();
|
||||
for (String roleName : model.getRoles().stream().filter(x -> x != null && !x.isBlank() && this.authorizationProperties.getAllowedGlobalRoles().contains(x)).distinct().toList()) {
|
||||
UserRoleEntity item = existingItems.stream().filter(x -> x.getRole().equals(roleName)).findFirst().orElse(null);
|
||||
if (item == null) {
|
||||
item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(userId);
|
||||
item.setRole(roleName);
|
||||
item.setCreatedAt(Instant.now());
|
||||
this.entityManager.persist(item);
|
||||
this.keycloakService.addUserToGlobalRoleGroup(subjectId, roleName);
|
||||
}
|
||||
foundIds.add(item.getId());
|
||||
}
|
||||
foundIds.add(item.getId());
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
List<UserRoleEntity> toDelete = existingItems.stream().filter(x -> foundIds.stream().noneMatch(y -> y.equals(x.getId()))).collect(Collectors.toList());
|
||||
toDelete.forEach(x -> this.keycloakService.removeUserGlobalRoleGroup(subjectId, x.getRole()));
|
||||
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
|
||||
|
||||
this.entityManager.flush();
|
||||
} finally {
|
||||
this.tenantScope.removeTempTenant(this.entityManager.getEntityManager());
|
||||
}
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
|
||||
toDelete.forEach(x -> this.keycloakService.removeUserFromGroup(subjectId, KeycloakRole.valueOf(x.getRole())));
|
||||
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
|
||||
|
||||
this.entityManager.flush();
|
||||
}
|
||||
|
||||
private void applyTenantRoles(UUID userId, UUID subjectId, UserRolePatchPersist model) throws InvalidApplicationException {
|
||||
private void applyTenantRoles(UUID userId, String subjectId, UserRolePatchPersist model) throws InvalidApplicationException {
|
||||
if (!tenantScope.isSet()) throw new MyForbiddenException("tenant scope required");
|
||||
|
||||
UserRoleQuery userRoleQuery = this.queryFactory.query(UserRoleQuery.class).userIds(userId).roles(this.authorizationProperties.getAllowedTenantRoles());
|
||||
|
@ -311,7 +315,7 @@ public class UserServiceImpl implements UserService {
|
|||
item.setCreatedAt(Instant.now());
|
||||
item.setTenantId(this.tenantScope.getTenant());
|
||||
this.entityManager.persist(item);
|
||||
this.keycloakService.addUserToGroup(subjectId, KeycloakRole.valueOf(roleName));
|
||||
this.keycloakService.addUserToTenantRoleGroup(subjectId, this.tenantScope.getTenantCode(), roleName);
|
||||
}
|
||||
foundIds.add(item.getId());
|
||||
}
|
||||
|
@ -319,7 +323,13 @@ public class UserServiceImpl implements UserService {
|
|||
this.entityManager.flush();
|
||||
|
||||
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
|
||||
toDelete.forEach(x -> this.keycloakService.removeUserFromGroup(subjectId, KeycloakRole.valueOf(x.getRole())));
|
||||
toDelete.forEach(x -> {
|
||||
try {
|
||||
this.keycloakService.removeUserTenantRoleGroup(subjectId, this.tenantScope.getTenantCode(), x.getRole());
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
|
||||
|
||||
this.entityManager.flush();
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
authorization:
|
||||
globalAdminRole: Admin
|
||||
autoAssignGlobalAdminToNewTenants: true
|
||||
allowedTenantRoles:
|
||||
- TenantAdmin
|
||||
- TenantUser
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
keycloak-resources:
|
||||
tenantGroupsNamingStrategy: 'tenant-{tenantCode}'
|
||||
tenantRoleAttributeName: 'tenant_role'
|
||||
authorities:
|
||||
User:
|
||||
groupId: a04fd333-f127-449e-8fc2-0626570a3899
|
||||
groupTitle: role-user
|
||||
Admin:
|
||||
groupId: 299f18fe-e271-4625-a4c1-9c3eb313b2ea
|
||||
groupTitle: role-admin
|
||||
Manager:
|
||||
groupId: 1753f7a7-cedb-4ad4-ae5f-96fe9bdabe3e
|
||||
groupTitle: role-manager
|
||||
DescriptionTemplateEditor:
|
||||
groupId: b0ea3cf3-21b0-4c6b-9c42-fb09f0e09dbb
|
||||
groupTitle: role-description-template-editor
|
||||
tenantAuthorities:
|
||||
TenantAdmin:
|
||||
parent: 1e650f57-8b7c-4f32-bf5b-e1a9147c597b
|
||||
roleAttributeValueStrategy: 'TenantAdmin:{tenantCode}'
|
||||
TenantUser:
|
||||
parent: c7057c4d-e7dc-49ef-aa5d-02ad3a22bff8
|
||||
roleAttributeValueStrategy: 'TenantUser:{tenantCode}'
|
||||
TenantManager:
|
||||
parent: d111bb2f-b4a6-4de7-ad22-5151ee1a508b
|
||||
roleAttributeValueStrategy: 'TenantManager:{tenantCode}'
|
||||
TenantDescriptionTemplateEditor:
|
||||
parent: 55cf7b17-c025-4065-8906-49f9f430f038
|
||||
roleAttributeValueStrategy: 'TenantDescriptionTemplateEditor:{tenantCode}'
|
|
@ -1,10 +1,10 @@
|
|||
keycloak-client:
|
||||
serverUrl: ${KEYCLOAK_API_SERVER_URL:}
|
||||
realm: ${KEYCLOAK_API_REALM:}
|
||||
username: ${KEYCLOAK_API_USERNAME:}
|
||||
password: ${KEYCLOAK_API_PASSWORD:}
|
||||
clientId: ${KEYCLOAK_API_CLIENT_ID:}
|
||||
clientSecret: ${KEYCLOAK_API_CLIENT_SECRET:}
|
||||
serverUrl: ${KEYCLOAK_API_SERVER_URL}
|
||||
realm: ${KEYCLOAK_API_REALM}
|
||||
username: ${KEYCLOAK_API_USERNAME}
|
||||
password: ${KEYCLOAK_API_PASSWORD}
|
||||
clientId: ${KEYCLOAK_API_CLIENT_ID}
|
||||
clientSecret: ${KEYCLOAK_API_CLIENT_SECRET}
|
||||
|
||||
keycloak-resources:
|
||||
authorities: null
|
Loading…
Reference in New Issue