argos/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java

231 lines
12 KiB
Java
Raw Normal View History

2023-11-22 17:01:58 +01:00
package eu.eudat.service.tenant;
import eu.eudat.authorization.AuthorizationFlags;
2024-04-16 12:17:58 +02:00
import eu.eudat.authorization.AuthorizationProperties;
2023-11-22 17:01:58 +01:00
import eu.eudat.authorization.Permission;
import eu.eudat.commons.XmlHandlingService;
import eu.eudat.commons.enums.IsActive;
2024-04-16 12:17:58 +02:00
import eu.eudat.commons.scope.tenant.TenantScope;
2023-11-22 17:01:58 +01:00
import eu.eudat.convention.ConventionService;
import eu.eudat.data.TenantEntity;
2024-04-01 17:36:03 +02:00
import eu.eudat.data.TenantEntityManager;
2024-04-16 12:17:58 +02:00
import eu.eudat.data.UserCredentialEntity;
import eu.eudat.data.UserRoleEntity;
2023-11-22 17:01:58 +01:00
import eu.eudat.errorcode.ErrorThesaurusProperties;
2024-04-04 11:21:12 +02:00
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;
2023-11-22 17:01:58 +01:00
import eu.eudat.model.Tenant;
import eu.eudat.model.builder.TenantBuilder;
import eu.eudat.model.deleter.TenantDeleter;
import eu.eudat.model.persist.TenantPersist;
2024-04-16 12:17:58 +02:00
import eu.eudat.query.UserCredentialQuery;
import eu.eudat.query.UserRoleQuery;
2023-11-24 14:12:02 +01:00
import eu.eudat.service.encryption.EncryptionService;
2024-04-16 12:17:58 +02:00
import eu.eudat.service.keycloak.KeycloakService;
2023-11-22 17:01:58 +01:00
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;
2023-11-24 14:12:02 +01:00
import org.jetbrains.annotations.NotNull;
2023-11-22 17:01:58 +01:00
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
2024-04-19 17:39:51 +02:00
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
2023-11-22 17:01:58 +01:00
import javax.management.InvalidApplicationException;
2023-11-24 14:12:02 +01:00
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
2023-11-22 17:01:58 +01:00
import java.time.Instant;
2023-11-24 14:12:02 +01:00
import java.util.ArrayList;
2023-11-22 17:01:58 +01:00
import java.util.List;
import java.util.UUID;
@Service
public class TenantServiceImpl implements TenantService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantServiceImpl.class));
2024-04-01 17:36:03 +02:00
private final TenantEntityManager entityManager;
2023-11-22 17:01:58 +01:00
private final AuthorizationService authorizationService;
private final DeleterFactory deleterFactory;
private final BuilderFactory builderFactory;
private final ConventionService conventionService;
private final MessageSource messageSource;
private final XmlHandlingService xmlHandlingService;
private final ErrorThesaurusProperties errors;
2023-11-24 14:12:02 +01:00
private final EncryptionService encryptionService;
private final TenantProperties properties;
2024-04-04 11:21:12 +02:00
private final TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler;
private final TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler;
2024-04-16 12:17:58 +02:00
private final KeycloakService keycloakService;
private final AuthorizationProperties authorizationProperties;
private final TenantScope tenantScope;
private final QueryFactory queryFactory;
2024-04-04 11:21:12 +02:00
2023-11-22 17:01:58 +01:00
@Autowired
public TenantServiceImpl(
2024-04-04 11:21:12 +02:00
TenantEntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
MessageSource messageSource,
XmlHandlingService xmlHandlingService,
ErrorThesaurusProperties errors,
2024-04-16 12:17:58 +02:00
EncryptionService encryptionService, TenantProperties properties, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory) {
2023-11-22 17:01:58 +01:00
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.builderFactory = builderFactory;
this.conventionService = conventionService;
this.messageSource = messageSource;
this.xmlHandlingService = xmlHandlingService;
this.errors = errors;
2023-11-24 14:12:02 +01:00
this.encryptionService = encryptionService;
this.properties = properties;
2024-04-04 11:21:12 +02:00
this.tenantTouchedIntegrationEventHandler = tenantTouchedIntegrationEventHandler;
this.tenantRemovalIntegrationEventHandler = tenantRemovalIntegrationEventHandler;
2024-04-16 12:17:58 +02:00
this.keycloakService = keycloakService;
this.authorizationProperties = authorizationProperties;
this.tenantScope = tenantScope;
this.queryFactory = queryFactory;
2023-11-22 17:01:58 +01:00
}
@Override
2023-11-24 14:12:02 +01:00
public Tenant persist(TenantPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
2023-11-22 17:01:58 +01:00
logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.EditTenant);
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
TenantEntity data;
if (isUpdate) {
data = this.entityManager.find(TenantEntity.class, model.getId());
2023-11-24 14:12:02 +01:00
if (data == null)
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash()))
throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
2023-11-22 17:01:58 +01:00
} else {
data = new TenantEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
}
data.setCode(model.getCode());
data.setName(model.getName());
data.setDescription(model.getDescription());
data.setUpdatedAt(Instant.now());
2023-11-24 14:12:02 +01:00
2023-11-22 17:01:58 +01:00
if (isUpdate) this.entityManager.merge(data);
2023-11-24 14:12:02 +01:00
else this.entityManager.persist(data);
2023-11-22 17:01:58 +01:00
this.entityManager.flush();
2024-04-16 12:17:58 +02:00
if (!isUpdate) {
this.keycloakService.createTenantGroups(data.getCode());
this.autoAssignGlobalAdminsToNewTenant(data);
}
2023-11-22 17:01:58 +01:00
2024-04-04 11:21:12 +02:00
TenantTouchedIntegrationEvent tenantTouchedIntegrationEvent = new TenantTouchedIntegrationEvent();
tenantTouchedIntegrationEvent.setId(data.getId());
tenantTouchedIntegrationEvent.setCode(data.getCode());
this.tenantTouchedIntegrationEventHandler.handle(tenantTouchedIntegrationEvent);
2024-03-12 17:27:16 +01:00
return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data);
2023-11-22 17:01:58 +01:00
}
2024-04-16 12:17:58 +02:00
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();
}
2023-11-24 14:12:02 +01:00
@Override
2024-04-04 11:21:12 +02:00
public Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException {
2024-04-19 17:39:51 +02:00
// if (model.getConfig() != null && model.getConfig().getDeposit() != null && model.getConfig().getDeposit().getSources() != null) {
// for (TenantSource source : model.getConfig().getDeposit().getSources().stream().toList()) {
// source.setClientSecret(this.encryptionService.decryptAES(source.getClientSecret(), properties.getConfigEncryptionAesKey(), properties.getConfigEncryptionAesIv()));
// }
// }
// if (model.getConfig() != null && model.getConfig().getFileTransformers() != null && model.getConfig().getFileTransformers().getSources() != null) {
// for (TenantSource source : model.getConfig().getFileTransformers().getSources().stream().toList()) {
// source.setClientSecret(this.encryptionService.decryptAES(source.getClientSecret(), properties.getConfigEncryptionAesKey(), properties.getConfigEncryptionAesIv()));
// }
// }
2024-04-04 11:21:12 +02:00
TenantEntity data = this.entityManager.find(TenantEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale()));
TenantTouchedIntegrationEvent tenantTouchedIntegrationEvent = new TenantTouchedIntegrationEvent();
tenantTouchedIntegrationEvent.setId(data.getId());
tenantTouchedIntegrationEvent.setCode(data.getCode());
this.tenantTouchedIntegrationEventHandler.handle(tenantTouchedIntegrationEvent);
2023-11-24 14:12:02 +01:00
return model;
}
2023-11-22 17:01:58 +01:00
@Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting : {}", id);
this.authorizationService.authorizeForce(Permission.DeleteTenant);
this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id));
2024-04-04 11:21:12 +02:00
TenantRemovalIntegrationEvent tenantRemovalIntegrationEvent = new TenantRemovalIntegrationEvent();
tenantRemovalIntegrationEvent.setId(id);
this.tenantRemovalIntegrationEventHandler.handle(tenantRemovalIntegrationEvent);
2023-11-22 17:01:58 +01:00
}
}