package eu.eudat.service.tenant; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.types.tenant.*; import eu.eudat.convention.ConventionService; import eu.eudat.data.TenantEntity; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.Tenant; import eu.eudat.model.builder.TenantBuilder; import eu.eudat.model.deleter.TenantDeleter; import eu.eudat.model.persist.TenantPersist; import eu.eudat.model.persist.tenantconfig.*; import eu.eudat.model.tenantconfig.TenantSource; import eu.eudat.service.encryption.EncryptionService; import eu.eudat.service.responseutils.ResponseUtilsService; 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 jakarta.persistence.EntityManager; import org.jetbrains.annotations.NotNull; 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; import javax.crypto.*; import javax.management.InvalidApplicationException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @Service public class TenantServiceImpl implements TenantService { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantServiceImpl.class)); private final EntityManager entityManager; private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; private final ConventionService conventionService; private final MessageSource messageSource; private final QueryFactory queryFactory; private final ResponseUtilsService responseUtilsService; private final XmlHandlingService xmlHandlingService; private final ErrorThesaurusProperties errors; private final EncryptionService encryptionService; private final TenantProperties properties; @Autowired public TenantServiceImpl( EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, ConventionService conventionService, MessageSource messageSource, QueryFactory queryFactory, ResponseUtilsService responseUtilsService, XmlHandlingService xmlHandlingService, ErrorThesaurusProperties errors, EncryptionService encryptionService, TenantProperties properties) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; this.builderFactory = builderFactory; this.conventionService = conventionService; this.messageSource = messageSource; this.queryFactory = queryFactory; this.responseUtilsService = responseUtilsService; this.xmlHandlingService = xmlHandlingService; this.errors = errors; this.encryptionService = encryptionService; this.properties = properties; } @Override public Tenant persist(TenantPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { 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()); 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()); } 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()); data.setConfig(this.xmlHandlingService.toXmlSafe(this.buildConfigEntity(model.getConfig()))); if (isUpdate) this.entityManager.merge(data); else this.entityManager.persist(data); this.entityManager.flush(); return this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Tenant._id), data); } private @NotNull TenantConfigEntity buildConfigEntity(TenantConfigPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { TenantConfigEntity data = new TenantConfigEntity(); if (persist == null) return data; if (persist.getDeposit() != null) { data.setDeposit(this.buildDepositConfigEntity(persist.getDeposit())); } if (persist.getFileTransformers() != null) { data.setFileTransformers(this.buildFileConfigEntity(persist.getFileTransformers())); } return data; } private @NotNull TenantDepositConfigEntity buildDepositConfigEntity(TenantDepositConfigPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { TenantDepositConfigEntity data = new TenantDepositConfigEntity(); if (persist == null) return data; if (!this.conventionService.isListNullOrEmpty(persist.getSources())) { data.setSources(new ArrayList<>()); for (TenantSourcePersist sourcePersist : persist.getSources()) { data.getSources().add(this.buildSourceEntity(sourcePersist)); } } return data; } private @NotNull TenantFileTransformersConfigEntity buildFileConfigEntity(TenantFileTransformersConfigPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { TenantFileTransformersConfigEntity data = new TenantFileTransformersConfigEntity(); if (persist == null) return data; if (!this.conventionService.isListNullOrEmpty(persist.getSources())) { data.setSources(new ArrayList<>()); for (TenantSourcePersist sourcePersist : persist.getSources()) { data.getSources().add(this.buildSourceEntity(sourcePersist)); } } return data; } private @NotNull TenantSourceEntity buildSourceEntity(TenantSourcePersist persist) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { TenantSourceEntity data = new TenantSourceEntity(); if (persist == null) return data; data.setUrl(persist.getUrl()); data.setCodes(persist.getCodes()); data.setIssuerUrl(persist.getIssuerUrl()); data.setClientId(persist.getClientId()); data.setClientSecret(this.encryptionService.encryptAES(persist.getClientSecret(), properties.getConfigEncryptionAesKey(), properties.getConfigEncryptionAesIv())); //data.setClientSecret(persist.getClientSecret()); data.setScope(persist.getScope()); return data; } @Override public Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { if (model.getConfig() != null && model.getConfig().getDeposit() != null && model.getConfig().getDeposit().getSources() != null) { for (TenantSource source : model.getConfig().getDeposit().getSources().stream().collect(Collectors.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().collect(Collectors.toList())) { source.setClientSecret(this.encryptionService.decryptAES(source.getClientSecret(), properties.getConfigEncryptionAesKey(), properties.getConfigEncryptionAesIv())); } } return model; } @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)); } }