Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-05-30 17:18:31 +03:00
commit 82e7075667
13 changed files with 159 additions and 89 deletions

View File

@ -22,9 +22,12 @@ public class TenantEntityManager {
private final TenantScope tenantScope;
private final ErrorThesaurusProperties errors;
boolean tenantFiltersDisabled;
public TenantEntityManager(TenantScope tenantScope, ErrorThesaurusProperties errors) {
this.tenantScope = tenantScope;
this.errors = errors;
this.tenantFiltersDisabled = false;
}
@ -33,7 +36,7 @@ public class TenantEntityManager {
}
public <T> T merge(T entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantScope.isDefaultTenant()) {
if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
} else if (tenantScopedEntity.getTenantId() != null) {
@ -44,7 +47,7 @@ public class TenantEntityManager {
}
public void remove(Object entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantScope.isDefaultTenant()) {
if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
} else if (tenantScopedEntity.getTenantId() != null) {
@ -57,7 +60,7 @@ public class TenantEntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey) throws InvalidApplicationException {
T entity = this.entityManager.find(entityClass, primaryKey);
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
}
return entity;
@ -66,7 +69,7 @@ public class TenantEntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey, boolean disableTracking) throws InvalidApplicationException {
T entity = this.entityManager.find(entityClass, primaryKey);
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
}
if (disableTracking) this.entityManager.detach(entity);
@ -106,6 +109,7 @@ public class TenantEntityManager {
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
}
this.tenantFiltersDisabled = false;
}
public void loadExplictTenantFilters() throws InvalidApplicationException {
@ -123,6 +127,7 @@ public class TenantEntityManager {
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
}
this.tenantFiltersDisabled = false;
}
public void disableTenantFilters() {
@ -137,6 +142,11 @@ public class TenantEntityManager {
this.entityManager
.unwrap(Session.class)
.disableFilter(TenantScopedBaseEntity.TENANT_FILTER_EXPLICT);
this.tenantFiltersDisabled = true;
}
public boolean isTenantFiltersDisabled() {
return tenantFiltersDisabled;
}
public EntityManager getEntityManager() {

View File

@ -2,6 +2,7 @@ package gr.cite.annotation.data.tenant;
import gr.cite.annotation.common.scope.tenant.TenantScope;
import gr.cite.annotation.common.scope.tenant.TenantScoped;
import gr.cite.annotation.data.TenantEntityManager;
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.logging.LoggerService;
@ -19,18 +20,21 @@ public class TenantListener {
private final TenantScope tenantScope;
private final ErrorThesaurusProperties errors;
private final TenantEntityManager tenantEntityManager;
@Autowired
public TenantListener(
TenantScope tenantScope, ErrorThesaurusProperties errors
TenantScope tenantScope, ErrorThesaurusProperties errors, TenantEntityManager tenantEntityManager
) {
this.tenantScope = tenantScope;
this.errors = errors;
this.tenantEntityManager = tenantEntityManager;
}
@PrePersist
public void setTenantOnCreate(TenantScoped entity) throws InvalidApplicationException {
if (this.tenantEntityManager.isTenantFiltersDisabled()) return;
if (tenantScope.isMultitenant()) {
if (entity.getTenantId() != null && (this.tenantScope.isDefaultTenant() || entity.getTenantId().compareTo(tenantScope.getTenant()) != 0)) {
logger.error("somebody tried to set not login tenant");
@ -48,6 +52,7 @@ public class TenantListener {
@PreUpdate
@PreRemove
public void setTenantOnUpdate(TenantScoped entity) throws InvalidApplicationException {
if (this.tenantEntityManager.isTenantFiltersDisabled()) return;
if (tenantScope.isMultitenant()) {
if (!tenantScope.isDefaultTenant()) {
if (entity.getTenantId() == null) {

View File

@ -74,24 +74,11 @@ public class AnnotationEntitiesRemovalIntegrationEventHandlerImpl implements Ann
EventProcessingStatus status = EventProcessingStatus.Success;
try {
if (this.tenantScope.isMultitenant() && properties.getTenantId() != null) {
TenantEntity tenant = queryFactory.query(TenantQuery.class).disableTracking().ids(properties.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
if (tenant == null) {
logger.error("missing tenant from event message");
return EventProcessingStatus.Error;
}
this.tenantScope.setTempTenant(tenantEntityManager, properties.getTenantId(), tenant.getCode());
} else if (this.tenantScope.isMultitenant()) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
this.tenantScope.setTempTenant(tenantEntityManager, null, this.tenantScope.getDefaultTenantCode());
}
tenantEntityManager.disableTenantFilters();
currentPrincipalResolver.push(InboxPrincipal.build(properties, claimExtractorProperties));
tenantEntityManager.disableTenantFilters();
EntityUserQuery entityUserQuery = this.queryFactory.query(EntityUserQuery.class);
List<EntityUserEntity> items = entityUserQuery
.entityIds(event.getEntityIds())
@ -101,6 +88,7 @@ public class AnnotationEntitiesRemovalIntegrationEventHandlerImpl implements Ann
deleterFactory.deleter(gr.cite.EntityUser.model.deleter.EntityUserDeleter.class).delete(items);
tenantEntityManager.flush();
auditService.track(AuditableAction.User_Persist, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", event)
@ -113,9 +101,9 @@ public class AnnotationEntitiesRemovalIntegrationEventHandlerImpl implements Ann
} finally {
currentPrincipalResolver.pop();
try {
tenantScope.removeTempTenant(this.tenantEntityManager);
this.tenantEntityManager.reloadTenantFilters();
} catch (InvalidApplicationException e) {
tenantEntityManager.reloadTenantFilters();
} catch (InvalidApplicationException ex) {
logger.error(ex.getMessage(), ex);
}
}
return status;

View File

@ -32,8 +32,6 @@ public class UserTouchedIntegrationEventHandlerImpl implements UserTouchedIntegr
private final JsonHandlingService jsonHandlingService;
private final ValidatorFactory validatorFactory;
private final QueryFactory queryFactory;
private final TenantScope tenantScope;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final ClaimExtractorProperties claimExtractorProperties;
private final UserService userService;
@ -42,11 +40,9 @@ public class UserTouchedIntegrationEventHandlerImpl implements UserTouchedIntegr
public UserTouchedIntegrationEventHandlerImpl(
JsonHandlingService jsonHandlingService,
ValidatorFactory validatorFactory, QueryFactory queryFactory, TenantScope tenantScope, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractorProperties claimExtractorProperties, UserService userService, AuditService auditService, TenantEntityManager tenantEntityManager) {
ValidatorFactory validatorFactory, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractorProperties claimExtractorProperties, UserService userService, AuditService auditService, TenantEntityManager tenantEntityManager) {
this.jsonHandlingService = jsonHandlingService;
this.validatorFactory = validatorFactory;
this.queryFactory = queryFactory;
this.tenantScope = tenantScope;
this.currentPrincipalResolver = currentPrincipalResolver;
this.claimExtractorProperties = claimExtractorProperties;
this.userService = userService;

View File

@ -22,9 +22,12 @@ public class TenantEntityManager {
private final TenantScope tenantScope;
private final ErrorThesaurusProperties errors;
boolean tenantFiltersDisabled;
public TenantEntityManager(TenantScope tenantScope, ErrorThesaurusProperties errors) {
this.tenantScope = tenantScope;
this.errors = errors;
this.tenantFiltersDisabled = false;
}
@ -33,7 +36,7 @@ public class TenantEntityManager {
}
public <T> T merge(T entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantScope.isDefaultTenant()) {
if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
} else if (tenantScopedEntity.getTenantId() != null) {
@ -44,7 +47,7 @@ public class TenantEntityManager {
}
public void remove(Object entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantScope.isDefaultTenant()) {
if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
} else if (tenantScopedEntity.getTenantId() != null) {
@ -57,7 +60,7 @@ public class TenantEntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey) throws InvalidApplicationException {
T entity = this.entityManager.find(entityClass, primaryKey);
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
}
return entity;
@ -66,7 +69,7 @@ public class TenantEntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey, boolean disableTracking) throws InvalidApplicationException {
T entity = this.entityManager.find(entityClass, primaryKey);
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
}
if (disableTracking) this.entityManager.detach(entity);
@ -96,7 +99,7 @@ public class TenantEntityManager {
if (!this.tenantScope.isSet()) return;
if(!this.tenantScope.isDefaultTenant()) {
if (!this.tenantScope.isDefaultTenant()) {
this.entityManager
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
@ -106,6 +109,7 @@ public class TenantEntityManager {
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
}
this.tenantFiltersDisabled = false;
}
public void loadExplictTenantFilters() throws InvalidApplicationException {
@ -113,7 +117,7 @@ public class TenantEntityManager {
if (!this.tenantScope.isSet()) return;
if(!this.tenantScope.isDefaultTenant()) {
if (!this.tenantScope.isDefaultTenant()) {
this.entityManager
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER_EXPLICT)
@ -123,9 +127,10 @@ public class TenantEntityManager {
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
}
this.tenantFiltersDisabled = false;
}
public void disableTenantFilters(){
public void disableTenantFilters() {
this.entityManager
.unwrap(Session.class)
.disableFilter(TenantScopedBaseEntity.TENANT_FILTER);
@ -137,6 +142,11 @@ public class TenantEntityManager {
this.entityManager
.unwrap(Session.class)
.disableFilter(TenantScopedBaseEntity.TENANT_FILTER_EXPLICT);
this.tenantFiltersDisabled = true;
}
public boolean isTenantFiltersDisabled() {
return this.tenantFiltersDisabled;
}
public EntityManager getEntityManager() {
@ -146,5 +156,5 @@ public class TenantEntityManager {
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}

View File

@ -1,9 +1,10 @@
package org.opencdmp.data;
import jakarta.persistence.*;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.converters.enums.IsActiveConverter;
import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import jakarta.persistence.*;
import java.time.Instant;
import java.util.UUID;
@ -37,7 +38,7 @@ public class TenantUserEntity extends TenantScopedBaseEntity {
public final static String _updatedAt = "updatedAt";
public UUID getId() {
return id;
return this.id;
}
public void setId(UUID id) {
@ -45,7 +46,7 @@ public class TenantUserEntity extends TenantScopedBaseEntity {
}
public UUID getUserId() {
return userId;
return this.userId;
}
public void setUserId(UUID userId) {
@ -53,7 +54,7 @@ public class TenantUserEntity extends TenantScopedBaseEntity {
}
public UUID getTenantId() {
return tenantId;
return this.tenantId;
}
public void setTenantId(UUID tenantId) {
@ -61,7 +62,7 @@ public class TenantUserEntity extends TenantScopedBaseEntity {
}
public IsActive getIsActive() {
return isActive;
return this.isActive;
}
public void setIsActive(IsActive isActive) {
@ -69,7 +70,7 @@ public class TenantUserEntity extends TenantScopedBaseEntity {
}
public Instant getCreatedAt() {
return createdAt;
return this.createdAt;
}
public void setCreatedAt(Instant createdAt) {
@ -77,7 +78,7 @@ public class TenantUserEntity extends TenantScopedBaseEntity {
}
public Instant getUpdatedAt() {
return updatedAt;
return this.updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {

View File

@ -8,6 +8,7 @@ import jakarta.persistence.PreRemove;
import jakarta.persistence.PreUpdate;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.scope.tenant.TenantScoped;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -20,18 +21,21 @@ public class TenantListener {
private final TenantScope tenantScope;
private final ErrorThesaurusProperties errors;
private final TenantEntityManager tenantEntityManager;
@Autowired
public TenantListener(
TenantScope tenantScope, ErrorThesaurusProperties errors
TenantScope tenantScope, ErrorThesaurusProperties errors, TenantEntityManager tenantEntityManager
) {
this.tenantScope = tenantScope;
this.errors = errors;
this.tenantEntityManager = tenantEntityManager;
}
@PrePersist
public void setTenantOnCreate(TenantScoped entity) throws InvalidApplicationException {
if (this.tenantEntityManager.isTenantFiltersDisabled()) return;
if (this.tenantScope.isMultitenant()) {
if (entity.getTenantId() != null && (this.tenantScope.isDefaultTenant() || entity.getTenantId().compareTo(this.tenantScope.getTenant()) != 0)) {
logger.error("somebody tried to set not login tenant");
@ -49,6 +53,7 @@ public class TenantListener {
@PreUpdate
@PreRemove
public void setTenantOnUpdate(TenantScoped entity) throws InvalidApplicationException {
if (this.tenantEntityManager.isTenantFiltersDisabled()) return;
if (this.tenantScope.isMultitenant()) {
if (!this.tenantScope.isDefaultTenant()) {
if (entity.getTenantId() == null) {
@ -77,3 +82,4 @@ public class TenantListener {
}
}

View File

@ -15,6 +15,7 @@ import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
public class TenantPersist {
@ -115,6 +116,10 @@ public class TenantPersist {
.iff(() -> !this.isEmpty(item.getCode()))
.must(() -> this.lessEqualLength(item.getCode(), TenantEntity._codeLength))
.failOn(TenantPersist._code).failWith(messageSource.getMessage("Validation_MaxLength", new Object[]{TenantPersist._code}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getCode()))
.must(() -> this.validateCodePattern(item.getCode()))
.failOn(TenantPersist._code).failWith(messageSource.getMessage("Validation_UnexpectedValue", new Object[]{TenantPersist._code}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getName()))
.failOn(TenantPersist._name).failWith(messageSource.getMessage("Validation_Required", new Object[]{TenantPersist._name}, LocaleContextHolder.getLocale())),
@ -128,6 +133,13 @@ public class TenantPersist {
);
}
private boolean validateCodePattern(String code){
if (this.isEmpty(code)) return false;
Pattern pattern = Pattern.compile("^[a-z0-9_]*$");
return pattern.matcher(code).matches();
}
}
}

View File

@ -1,7 +1,7 @@
package org.opencdmp.model.persist;
import org.opencdmp.commons.validation.BaseValidator;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -27,7 +27,7 @@ public class UserRolePatchPersist {
public static final String _hash = "hash";
public UUID getId() {
return id;
return this.id;
}
public void setId(UUID id) {
@ -35,7 +35,7 @@ public class UserRolePatchPersist {
}
public List<String> getRoles() {
return roles;
return this.roles;
}
public void setRoles(List<String> roles) {
@ -43,7 +43,7 @@ public class UserRolePatchPersist {
}
public String getHash() {
return hash;
return this.hash;
}
public void setHash(String hash) {
@ -74,14 +74,14 @@ public class UserRolePatchPersist {
this.spec()
.iff(() -> this.isValidGuid(item.getId()))
.must(() -> this.isValidHash(item.getHash()))
.failOn(UserRolePatchPersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserRolePatchPersist._hash}, LocaleContextHolder.getLocale())),
.failOn(UserRolePatchPersist._hash).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{UserRolePatchPersist._hash}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isValidGuid(item.getId()))
.must(() -> !this.isValidHash(item.getHash()))
.failOn(UserRolePatchPersist._hash).failWith(messageSource.getMessage("Validation_OverPosting", new Object[]{}, LocaleContextHolder.getLocale())),
.failOn(UserRolePatchPersist._hash).failWith(this.messageSource.getMessage("Validation_OverPosting", new Object[]{}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isListNullOrEmpty(item.getRoles()))
.failOn(UserRolePatchPersist._roles).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserRolePatchPersist._roles}, LocaleContextHolder.getLocale()))
.failOn(UserRolePatchPersist._roles).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{UserRolePatchPersist._roles}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -23,15 +23,13 @@ import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.TenantEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserCredentialEntity;
import org.opencdmp.data.UserRoleEntity;
import org.opencdmp.data.*;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEvent;
import org.opencdmp.integrationevent.outbox.tenantremoval.TenantRemovalIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEvent;
import org.opencdmp.integrationevent.outbox.tenanttouched.TenantTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.usertouched.UserTouchedIntegrationEventHandler;
import org.opencdmp.model.Tenant;
import org.opencdmp.model.builder.TenantBuilder;
import org.opencdmp.model.deleter.TenantDeleter;
@ -76,6 +74,7 @@ public class TenantServiceImpl implements TenantService {
private final ErrorThesaurusProperties errors;
private final TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler;
private final TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler;
private final UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler;
private final KeycloakService keycloakService;
private final AuthorizationProperties authorizationProperties;
private final TenantScope tenantScope;
@ -92,7 +91,7 @@ public class TenantServiceImpl implements TenantService {
BuilderFactory builderFactory,
ConventionService conventionService,
MessageSource messageSource,
ErrorThesaurusProperties errors, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractor claimExtractor) {
ErrorThesaurusProperties errors, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractor claimExtractor) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -102,6 +101,7 @@ public class TenantServiceImpl implements TenantService {
this.errors = errors;
this.tenantTouchedIntegrationEventHandler = tenantTouchedIntegrationEventHandler;
this.tenantRemovalIntegrationEventHandler = tenantRemovalIntegrationEventHandler;
this.userTouchedIntegrationEventHandler = userTouchedIntegrationEventHandler;
this.keycloakService = keycloakService;
this.authorizationProperties = authorizationProperties;
this.tenantScope = tenantScope;
@ -145,16 +145,16 @@ public class TenantServiceImpl implements TenantService {
Long tenantsWithThisCode = this.queryFactory.query(TenantQuery.class).codes(data.getCode()).count();
if (tenantsWithThisCode > 1) throw new MyValidationException(this.errors.getTenantCodeExists().getCode(), this.errors.getTenantCodeExists().getMessage());
if (!isUpdate) {
this.keycloakService.createTenantGroups(data.getCode());
this.autoAssignGlobalAdminsToNewTenant(data);
}
TenantTouchedIntegrationEvent tenantTouchedIntegrationEvent = new TenantTouchedIntegrationEvent();
tenantTouchedIntegrationEvent.setId(data.getId());
tenantTouchedIntegrationEvent.setCode(data.getCode());
this.tenantTouchedIntegrationEventHandler.handle(tenantTouchedIntegrationEvent);
if (!isUpdate) {
this.keycloakService.createTenantGroups(data.getCode());
this.autoAssignGlobalAdminsToNewTenant(data);
}
return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data);
}
@ -170,6 +170,15 @@ public class TenantServiceImpl implements TenantService {
List<String> keycloakIdsToAddToTenantGroup = new ArrayList<>();
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
TenantUserEntity tenantUserEntity = new TenantUserEntity();
tenantUserEntity.setId(UUID.randomUUID());
tenantUserEntity.setUserId(userId);
tenantUserEntity.setIsActive(IsActive.Active);
tenantUserEntity.setTenantId(tenant.getId());
tenantUserEntity.setCreatedAt(Instant.now());
tenantUserEntity.setUpdatedAt(Instant.now());
this.entityManager.persist(tenantUserEntity);
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();
@ -180,13 +189,18 @@ public class TenantServiceImpl implements TenantService {
item.setCreatedAt(Instant.now());
this.entityManager.persist(item);
keycloakIdsToAddToTenantGroup.add(userCredential.getExternalId());
this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), this.tenantScope.getTenantCode(), this.authorizationProperties.getTenantAdminRole());
}
this.entityManager.flush();
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
this.userTouchedIntegrationEventHandler.handle(userId);
}
this.entityManager.flush();
for (String externalId : keycloakIdsToAddToTenantGroup) {
this.keycloakService.addUserToTenantRoleGroup(externalId, this.tenantScope.getTenantCode(), this.authorizationProperties.getTenantAdminRole());
this.keycloakService.addUserToTenantRoleGroup(externalId, tenant.getCode(), this.authorizationProperties.getTenantAdminRole());
}
} finally {
this.entityManager.reloadTenantFilters();

View File

@ -380,6 +380,8 @@ public class UserServiceImpl implements UserService {
if (this.tenantScope.isDefaultTenant()) userRoleQuery.tenantIsSet(false);
else userRoleQuery.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
boolean hasTenantUser = this.queryFactory.query(TenantUserQuery.class).isActive(IsActive.Active).userIds(userId).count() > 0;
List<UserRoleEntity> existingItems = userRoleQuery.collect();
List<UUID> foundIds = new ArrayList<>();
for (String roleName : model.getRoles().stream().filter(x-> x != null && !x.isBlank() && this.authorizationProperties.getAllowedTenantRoles().contains(x)).distinct().toList()) {
@ -396,6 +398,17 @@ public class UserServiceImpl implements UserService {
foundIds.add(item.getId());
}
if (!hasTenantUser && !model.getRoles().isEmpty() && !this.tenantScope.isDefaultTenant()){
TenantUserEntity tenantUserEntity = new TenantUserEntity();
tenantUserEntity.setId(UUID.randomUUID());
tenantUserEntity.setUserId(userId);
tenantUserEntity.setIsActive(IsActive.Active);
tenantUserEntity.setTenantId(this.tenantScope.getTenant());
tenantUserEntity.setCreatedAt(Instant.now());
tenantUserEntity.setUpdatedAt(Instant.now());
this.entityManager.persist(tenantUserEntity);
}
this.entityManager.flush();
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());

View File

@ -22,9 +22,12 @@ public class TenantEntityManager {
private final TenantScope tenantScope;
private final ErrorThesaurusProperties errors;
boolean tenantFiltersDisabled;
public TenantEntityManager(TenantScope tenantScope, ErrorThesaurusProperties errors) {
this.tenantScope = tenantScope;
this.errors = errors;
this.tenantFiltersDisabled = false;
}
@ -33,7 +36,7 @@ public class TenantEntityManager {
}
public <T> T merge(T entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantScope.isDefaultTenant()) {
if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
} else if (tenantScopedEntity.getTenantId() != null) {
@ -44,7 +47,7 @@ public class TenantEntityManager {
}
public void remove(Object entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantScope.isDefaultTenant()) {
if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
} else if (tenantScopedEntity.getTenantId() != null) {
@ -57,7 +60,7 @@ public class TenantEntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey) throws InvalidApplicationException {
T entity = this.entityManager.find(entityClass, primaryKey);
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
}
return entity;
@ -66,7 +69,7 @@ public class TenantEntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey, boolean disableTracking) throws InvalidApplicationException {
T entity = this.entityManager.find(entityClass, primaryKey);
if (this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
}
if (disableTracking) this.entityManager.detach(entity);
@ -96,7 +99,7 @@ public class TenantEntityManager {
if (!this.tenantScope.isSet()) return;
if(!this.tenantScope.isDefaultTenant()) {
if (!this.tenantScope.isDefaultTenant()) {
this.entityManager
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
@ -106,6 +109,7 @@ public class TenantEntityManager {
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
}
this.tenantFiltersDisabled = false;
}
public void loadExplictTenantFilters() throws InvalidApplicationException {
@ -113,7 +117,7 @@ public class TenantEntityManager {
if (!this.tenantScope.isSet()) return;
if(!this.tenantScope.isDefaultTenant()) {
if (!this.tenantScope.isDefaultTenant()) {
this.entityManager
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER_EXPLICT)
@ -123,9 +127,10 @@ public class TenantEntityManager {
.unwrap(Session.class)
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
}
this.tenantFiltersDisabled = false;
}
public void disableTenantFilters(){
public void disableTenantFilters() {
this.entityManager
.unwrap(Session.class)
.disableFilter(TenantScopedBaseEntity.TENANT_FILTER);
@ -137,6 +142,11 @@ public class TenantEntityManager {
this.entityManager
.unwrap(Session.class)
.disableFilter(TenantScopedBaseEntity.TENANT_FILTER_EXPLICT);
this.tenantFiltersDisabled = true;
}
public boolean isTenantFiltersDisabled() {
return tenantFiltersDisabled;
}
public EntityManager getEntityManager() {
@ -146,5 +156,4 @@ public class TenantEntityManager {
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}

View File

@ -2,6 +2,7 @@ package gr.cite.notification.data.tenant;
import gr.cite.notification.common.scope.tenant.TenantScope;
import gr.cite.notification.common.scope.tenant.TenantScoped;
import gr.cite.notification.data.TenantEntityManager;
import gr.cite.notification.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.logging.LoggerService;
@ -20,25 +21,28 @@ public class TenantListener {
private final TenantScope tenantScope;
private final ErrorThesaurusProperties errors;
private final TenantEntityManager tenantEntityManager;
@Autowired
public TenantListener(
TenantScope tenantScope, ErrorThesaurusProperties errors
TenantScope tenantScope, ErrorThesaurusProperties errors, TenantEntityManager tenantEntityManager
) {
this.tenantScope = tenantScope;
this.errors = errors;
this.tenantEntityManager = tenantEntityManager;
}
@PrePersist
public void setTenantOnCreate(TenantScoped entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant()) {
if (entity.getTenantId() != null && (this.tenantScope.isDefaultTenant() || entity.getTenantId().compareTo(this.tenantScope.getTenant()) != 0)) {
if (this.tenantEntityManager.isTenantFiltersDisabled()) return;
if (tenantScope.isMultitenant()) {
if (entity.getTenantId() != null && (this.tenantScope.isDefaultTenant() || entity.getTenantId().compareTo(tenantScope.getTenant()) != 0)) {
logger.error("somebody tried to set not login tenant");
throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
}
if (!this.tenantScope.isDefaultTenant()) {
final UUID tenantId = this.tenantScope.getTenant();
if (!tenantScope.isDefaultTenant()) {
final UUID tenantId = tenantScope.getTenant();
entity.setTenantId(tenantId);
}
} else {
@ -49,18 +53,19 @@ public class TenantListener {
@PreUpdate
@PreRemove
public void setTenantOnUpdate(TenantScoped entity) throws InvalidApplicationException {
if (this.tenantScope.isMultitenant()) {
if (!this.tenantScope.isDefaultTenant()) {
if (this.tenantEntityManager.isTenantFiltersDisabled()) return;
if (tenantScope.isMultitenant()) {
if (!tenantScope.isDefaultTenant()) {
if (entity.getTenantId() == null) {
logger.error("somebody tried to set null tenant");
throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
}
if (entity.getTenantId().compareTo(this.tenantScope.getTenant()) != 0) {
if (entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) {
logger.error("somebody tried to change an entries tenant");
throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
}
final UUID tenantId = this.tenantScope.getTenant();
final UUID tenantId = tenantScope.getTenant();
entity.setTenantId(tenantId);
} else {
if (entity.getTenantId() != null) {
@ -69,7 +74,7 @@ public class TenantListener {
}
}
} else {
if (entity.getTenantId() != null && (!this.tenantScope.isDefaultTenant() ||entity.getTenantId().compareTo(this.tenantScope.getTenant()) != 0)) {
if (entity.getTenantId() != null && (!this.tenantScope.isDefaultTenant() ||entity.getTenantId().compareTo(tenantScope.getTenant()) != 0)) {
logger.error("somebody tried to change an entries tenant");
throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
}
@ -77,3 +82,4 @@ public class TenantListener {
}
}