tenant fixes

This commit is contained in:
Efstratios Giannopoulos 2024-05-01 14:57:49 +03:00
parent f6ea1e2b04
commit 1888711fe9
5 changed files with 49 additions and 45 deletions

View File

@ -3,16 +3,16 @@ package org.opencdmp.authorization;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.HashSet;
import java.util.List; import java.util.List;
@ConfigurationProperties(prefix = "authorization") @ConfigurationProperties(prefix = "authorization")
public class AuthorizationProperties { public class AuthorizationProperties {
private String globalAdminRole; private String globalAdminRole;
private String tenantAdminRole;
public String getGlobalAdminRole() { public String getGlobalAdminRole() {
return globalAdminRole; return this.globalAdminRole;
} }
public void setGlobalAdminRole(String globalAdminRole) { public void setGlobalAdminRole(String globalAdminRole) {
@ -21,7 +21,7 @@ public class AuthorizationProperties {
private Boolean autoAssignGlobalAdminToNewTenants; private Boolean autoAssignGlobalAdminToNewTenants;
public Boolean getAutoAssignGlobalAdminToNewTenants() { public Boolean getAutoAssignGlobalAdminToNewTenants() {
return autoAssignGlobalAdminToNewTenants; return this.autoAssignGlobalAdminToNewTenants;
} }
public void setAutoAssignGlobalAdminToNewTenants(Boolean autoAssignGlobalAdminToNewTenants) { public void setAutoAssignGlobalAdminToNewTenants(Boolean autoAssignGlobalAdminToNewTenants) {
@ -31,7 +31,7 @@ public class AuthorizationProperties {
private List<String> allowedTenantRoles; private List<String> allowedTenantRoles;
public List<String> getAllowedTenantRoles() { public List<String> getAllowedTenantRoles() {
return allowedTenantRoles; return this.allowedTenantRoles;
} }
public void setAllowedTenantRoles(List<String> allowedTenantRoles) { public void setAllowedTenantRoles(List<String> allowedTenantRoles) {
@ -41,10 +41,18 @@ public class AuthorizationProperties {
private List<String> allowedGlobalRoles; private List<String> allowedGlobalRoles;
public List<String> getAllowedGlobalRoles() { public List<String> getAllowedGlobalRoles() {
return allowedGlobalRoles; return this.allowedGlobalRoles;
} }
public void setAllowedGlobalRoles(List<String> allowedGlobalRoles) { public void setAllowedGlobalRoles(List<String> allowedGlobalRoles) {
this.allowedGlobalRoles = allowedGlobalRoles; this.allowedGlobalRoles = allowedGlobalRoles;
} }
public String getTenantAdminRole() {
return this.tenantAdminRole;
}
public void setTenantAdminRole(String tenantAdminRole) {
this.tenantAdminRole = tenantAdminRole;
}
} }

View File

@ -16,11 +16,11 @@ public class KeycloakResourcesConfiguration {
} }
public KeycloakResourcesProperties getProperties() { public KeycloakResourcesProperties getProperties() {
return properties; return this.properties;
} }
public String getTenantGroupName(String tenantCode) { public String getTenantGroupName(String tenantCode) {
return properties.getTenantGroupsNamingStrategy() return this.properties.getTenantGroupsNamingStrategy()
.replace("{tenantCode}", tenantCode); .replace("{tenantCode}", tenantCode);
} }

View File

@ -1,20 +1,18 @@
package org.opencdmp.service.keycloak; package org.opencdmp.service.keycloak;
import org.opencdmp.convention.ConventionService;
import gr.cite.commons.web.keycloak.api.configuration.KeycloakClientConfiguration;
import gr.cite.tools.logging.LoggerService;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.keycloak.representations.idm.GroupRepresentation; import org.keycloak.representations.idm.GroupRepresentation;
import org.slf4j.LoggerFactory; import org.opencdmp.convention.ConventionService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service @Service
public class KeycloakServiceImpl implements KeycloakService { public class KeycloakServiceImpl implements KeycloakService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(KeycloakServiceImpl.class));
private final MyKeycloakAdminRestApi api; private final MyKeycloakAdminRestApi api;
private final KeycloakResourcesConfiguration configuration; private final KeycloakResourcesConfiguration configuration;
private final ConventionService conventionService; private final ConventionService conventionService;
@ -28,26 +26,26 @@ public class KeycloakServiceImpl implements KeycloakService {
@Override @Override
public void addUserToGroup(@NotNull String subjectId, String groupId) { public void addUserToGroup(@NotNull String subjectId, String groupId) {
api.users().addUserToGroup(subjectId, groupId); this.api.users().addUserToGroup(subjectId, groupId);
} }
@Override @Override
public void removeUserFromGroup(@NotNull String subjectId, String groupId) { public void removeUserFromGroup(@NotNull String subjectId, String groupId) {
api.users().removeUserFromGroup(subjectId, groupId); this.api.users().removeUserFromGroup(subjectId, groupId);
} }
@Override @Override
public void addUserToGlobalRoleGroup(String subjectId, String role) { public void addUserToGlobalRoleGroup(String subjectId, String role) {
if (this.configuration.getProperties().getAuthorities() == null) return; if (this.configuration.getProperties().getAuthorities() == null) return;
KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().getOrDefault(role, null); KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().getOrDefault(role, null);
if (properties != null) addUserToGroup(subjectId, properties.getGroupId()); if (properties != null) this.addUserToGroup(subjectId, properties.getGroupId());
} }
@Override @Override
public void removeUserGlobalRoleGroup(@NotNull String subjectId, String role) { public void removeUserGlobalRoleGroup(@NotNull String subjectId, String role) {
if (this.configuration.getProperties().getAuthorities() == null) return; if (this.configuration.getProperties().getAuthorities() == null) return;
KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().getOrDefault(role, null); KeycloakAuthorityProperties properties = this.configuration.getProperties().getAuthorities().getOrDefault(role, null);
if (properties != null) removeUserFromGroup(subjectId, properties.getGroupId()); if (properties != null) this.removeUserFromGroup(subjectId, properties.getGroupId());
} }
@Override @Override
@ -55,33 +53,33 @@ public class KeycloakServiceImpl implements KeycloakService {
if (this.configuration.getProperties().getAuthorities() == null) return; if (this.configuration.getProperties().getAuthorities() == null) return;
KeycloakTenantAuthorityProperties properties = this.configuration.getProperties().getTenantAuthorities().getOrDefault(tenantRole, null); KeycloakTenantAuthorityProperties properties = this.configuration.getProperties().getTenantAuthorities().getOrDefault(tenantRole, null);
if (properties == null) return; if (properties == null) return;
GroupRepresentation group = api.groups().findGroupByPath(getTenantAuthorityParentPath(properties) + "/" + configuration.getTenantGroupName(tenantCode)); GroupRepresentation group = this.api.groups().findGroupByPath(this.getTenantAuthorityParentPath(properties) + "/" + this.configuration.getTenantGroupName(tenantCode));
if (group != null) addUserToGroup(subjectId, group.getId()); if (group != null) this.addUserToGroup(subjectId, group.getId());
} }
@Override @Override
public void removeUserTenantRoleGroup(String subjectId, String tenantCode, String tenantRole) { public void removeUserTenantRoleGroup(String subjectId, String tenantCode, String tenantRole) {
KeycloakTenantAuthorityProperties properties = this.configuration.getProperties().getTenantAuthorities().getOrDefault(tenantRole, null); KeycloakTenantAuthorityProperties properties = this.configuration.getProperties().getTenantAuthorities().getOrDefault(tenantRole, null);
if (properties == null) return; if (properties == null) return;
GroupRepresentation group = api.groups().findGroupByPath(getTenantAuthorityParentPath(properties) + "/" + configuration.getTenantGroupName(tenantCode)); GroupRepresentation group = this.api.groups().findGroupByPath(this.getTenantAuthorityParentPath(properties) + "/" + this.configuration.getTenantGroupName(tenantCode));
if (group != null) removeUserFromGroup(subjectId, group.getId()); if (group != null) this.removeUserFromGroup(subjectId, group.getId());
} }
private String getTenantAuthorityParentPath(KeycloakTenantAuthorityProperties keycloakTenantAuthorityProperties) { private String getTenantAuthorityParentPath(KeycloakTenantAuthorityProperties keycloakTenantAuthorityProperties) {
GroupRepresentation parent = api.groups().findGroupById(keycloakTenantAuthorityProperties.getParent()); GroupRepresentation parent = this.api.groups().findGroupById(keycloakTenantAuthorityProperties.getParent());
return parent.getPath(); return parent.getPath();
} }
@Override @Override
public void createTenantGroups(String tenantCode) { public void createTenantGroups(String tenantCode) {
if (this.configuration.getProperties().getTenantAuthorities() == null) return; if (this.configuration.getProperties().getTenantAuthorities() == null) return;
for (Map.Entry<String,KeycloakTenantAuthorityProperties> entry :configuration.getProperties().getTenantAuthorities().entrySet()){ for (Map.Entry<String,KeycloakTenantAuthorityProperties> entry : this.configuration.getProperties().getTenantAuthorities().entrySet()){
GroupRepresentation group = new GroupRepresentation(); GroupRepresentation group = new GroupRepresentation();
group.setName(configuration.getTenantGroupName(tenantCode)); group.setName(this.configuration.getTenantGroupName(tenantCode));
HashMap<String, List<String>> user_attributes = new HashMap<>(); HashMap<String, List<String>> user_attributes = new HashMap<>();
if (!this.conventionService.isNullOrEmpty(this.configuration.getProperties().getTenantRoleAttributeName())) user_attributes.put(this.configuration.getProperties().getTenantRoleAttributeName(), List.of(configuration.getTenantRoleAttributeValue(tenantCode, entry.getValue()))); if (!this.conventionService.isNullOrEmpty(this.configuration.getProperties().getTenantRoleAttributeName())) user_attributes.put(this.configuration.getProperties().getTenantRoleAttributeName(), List.of(this.configuration.getTenantRoleAttributeValue(tenantCode, entry.getValue())));
group.setAttributes(user_attributes); group.setAttributes(user_attributes);
api.groups().addGroupWithParent(group, entry.getValue().getParent()); this.api.groups().addGroupWithParent(group, entry.getValue().getParent());
} }
} }
} }

View File

@ -1,9 +1,20 @@
package org.opencdmp.service.tenant; package org.opencdmp.service.tenant;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.authorization.AuthorizationFlags; import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.AuthorizationProperties; import org.opencdmp.authorization.AuthorizationProperties;
import org.opencdmp.authorization.Permission; import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope; import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
@ -22,21 +33,7 @@ import org.opencdmp.model.deleter.TenantDeleter;
import org.opencdmp.model.persist.TenantPersist; import org.opencdmp.model.persist.TenantPersist;
import org.opencdmp.query.UserCredentialQuery; import org.opencdmp.query.UserCredentialQuery;
import org.opencdmp.query.UserRoleQuery; import org.opencdmp.query.UserRoleQuery;
import org.opencdmp.service.encryption.EncryptionService;
import org.opencdmp.service.keycloak.KeycloakService; import org.opencdmp.service.keycloak.KeycloakService;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.jetbrains.annotations.NotNull;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
@ -114,7 +111,7 @@ public class TenantServiceImpl implements TenantService {
if (isUpdate) { if (isUpdate) {
data = this.entityManager.find(TenantEntity.class, model.getId()); data = this.entityManager.find(TenantEntity.class, model.getId());
if (data == null) if (data == null)
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale())); throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash()))
throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
} else { } else {
@ -147,7 +144,7 @@ public class TenantServiceImpl implements TenantService {
return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data); return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data);
} }
private void autoAssignGlobalAdminsToNewTenant(TenantEntity tenant){ private void autoAssignGlobalAdminsToNewTenant(TenantEntity tenant) throws InvalidApplicationException {
if (!this.authorizationProperties.getAutoAssignGlobalAdminToNewTenants()) return; if (!this.authorizationProperties.getAutoAssignGlobalAdminToNewTenants()) return;
List<UserRoleEntity> existingItems; List<UserRoleEntity> existingItems;
List<UserCredentialEntity> userCredentialEntities; List<UserCredentialEntity> userCredentialEntities;
@ -167,10 +164,10 @@ public class TenantServiceImpl implements TenantService {
UserRoleEntity item = new UserRoleEntity(); UserRoleEntity item = new UserRoleEntity();
item.setId(UUID.randomUUID()); item.setId(UUID.randomUUID());
item.setUserId(userId); item.setUserId(userId);
item.setRole(this.authorizationProperties.getGlobalAdminRole()); item.setRole(this.authorizationProperties.getTenantAdminRole());
item.setCreatedAt(Instant.now()); item.setCreatedAt(Instant.now());
this.entityManager.persist(item); this.entityManager.persist(item);
this.keycloakService.addUserToGlobalRoleGroup(userCredential.getExternalId(), this.authorizationProperties.getGlobalAdminRole()); this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), this.tenantScope.getTenantCode(), this.authorizationProperties.getTenantAdminRole());
} }
} finally { } finally {
this.tenantScope.removeTempTenant(this.entityManager.getEntityManager()); this.tenantScope.removeTempTenant(this.entityManager.getEntityManager());

View File

@ -1,5 +1,6 @@
authorization: authorization:
globalAdminRole: Admin globalAdminRole: Admin
tenantAdminRole: TenantAdmin
autoAssignGlobalAdminToNewTenants: true autoAssignGlobalAdminToNewTenants: true
allowedTenantRoles: allowedTenantRoles:
- TenantAdmin - TenantAdmin