From c523bda52b5ed91640bf1776562241ebda191fef Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Mon, 22 Apr 2024 10:00:04 +0300 Subject: [PATCH 1/5] fix tenant scope --- .../common/scope/tenant/TenantScope.java | 2 + .../TenantConfigurationController.java | 129 ++++++++++++++++++ .../common/scope/tenant/TenantScope.java | 5 +- .../data/tenant/TenantListener.java | 1 + 4 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java diff --git a/annotation-service/annotation/src/main/java/gr/cite/annotation/common/scope/tenant/TenantScope.java b/annotation-service/annotation/src/main/java/gr/cite/annotation/common/scope/tenant/TenantScope.java index e42eaebcf..ed39ac7a5 100644 --- a/annotation-service/annotation/src/main/java/gr/cite/annotation/common/scope/tenant/TenantScope.java +++ b/annotation-service/annotation/src/main/java/gr/cite/annotation/common/scope/tenant/TenantScope.java @@ -11,6 +11,8 @@ import javax.management.InvalidApplicationException; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; +@Component +@RequestScope public class TenantScope { public static final String TenantReplaceParameter = "::TenantCode::"; private final MultitenancyProperties multitenancy; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java new file mode 100644 index 000000000..156339675 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java @@ -0,0 +1,129 @@ +package eu.eudat.controllers; + +import eu.eudat.audit.AuditableAction; +import eu.eudat.authorization.AuthorizationFlags; +import gr.cite.tools.validation.ValidationFilterAnnotation; +import eu.eudat.data.EntityDoiEntity; +import eu.eudat.model.DescriptionTemplateType; +import eu.eudat.model.EntityDoi; +import eu.eudat.model.builder.EntityDoiBuilder; +import eu.eudat.model.censorship.EntityDoiCensor; +import eu.eudat.model.persist.EntityDoiPersist; +import eu.eudat.model.result.QueryResult; +import eu.eudat.query.EntityDoiQuery; +import eu.eudat.query.lookup.EntityDoiLookup; +import eu.eudat.service.deposit.DepositService; +import eu.eudat.service.entitydoi.EntityDoiService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.censor.CensorFactory; +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.fieldset.FieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.management.InvalidApplicationException; +import java.util.*; + +@RestController +@RequestMapping(path = "api/entity-doi") +public class EntityDoiController { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeController.class)); + + private final BuilderFactory builderFactory; + + private final AuditService auditService; + + private final EntityDoiService entityDoiService; + + private final CensorFactory censorFactory; + + private final QueryFactory queryFactory; + + private final MessageSource messageSource; + + public EntityDoiController( + BuilderFactory builderFactory, + AuditService auditService, + EntityDoiService entityDoiService, CensorFactory censorFactory, + QueryFactory queryFactory, + MessageSource messageSource) { + this.builderFactory = builderFactory; + this.auditService = auditService; + this.entityDoiService = entityDoiService; + this.censorFactory = censorFactory; + this.queryFactory = queryFactory; + this.messageSource = messageSource; + } + + @PostMapping("query") + public QueryResult Query(@RequestBody EntityDoiLookup lookup) throws MyApplicationException, MyForbiddenException { + logger.debug("querying {}", EntityDoi.class.getSimpleName()); + + this.censorFactory.censor(EntityDoiCensor.class).censor(lookup.getProject(), null); + + EntityDoiQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission); + + List data = query.collectAs(lookup.getProject()); + List models = this.builderFactory.builder(EntityDoiBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(lookup.getProject(), data); + long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); + + this.auditService.track(AuditableAction.EntityDoi_Query, "lookup", lookup); + + return new QueryResult<>(models, count); + } + + @GetMapping("{id}") + public EntityDoi Get(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("retrieving" + EntityDoi.class.getSimpleName()).And("id", id).And("fields", fieldSet)); + + this.censorFactory.censor(EntityDoiCensor.class).censor(fieldSet, null); + + EntityDoiQuery query = this.queryFactory.query(EntityDoiQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(id); + EntityDoi model = this.builderFactory.builder(EntityDoiBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(fieldSet, query.firstAs(fieldSet)); + if (model == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, EntityDoi.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.EntityDoi_Lookup, Map.ofEntries( + new AbstractMap.SimpleEntry("id", id), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return model; + } + + @PostMapping("persist") + @Transactional + @ValidationFilterAnnotation(validator = EntityDoiPersist.EntityDoiPersistValidator.ValidatorName, argumentName = "model") + public EntityDoi Persist(@RequestBody EntityDoiPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + logger.debug(new MapLogEntry("persisting" + DescriptionTemplateType.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); + EntityDoi persisted = this.entityDoiService.persist(model, fieldSet); + + this.auditService.track(AuditableAction.EntityDoi_Persist, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return persisted; + } + + @DeleteMapping("{id}") + @Transactional + public void Delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug(new MapLogEntry("retrieving" + EntityDoi.class.getSimpleName()).And("id", id)); + + this.entityDoiService.deleteAndSave(id); + + this.auditService.track(AuditableAction.EntityDoi_Delete, "id", id); + } + +} diff --git a/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java b/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java index 0a27d4cc6..349cf0707 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/common/scope/tenant/TenantScope.java @@ -11,6 +11,8 @@ import javax.management.InvalidApplicationException; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; +@Component +@RequestScope public class TenantScope { public static final String TenantReplaceParameter = "::TenantCode::"; private final MultitenancyProperties multitenancy; @@ -120,6 +122,3 @@ public class TenantScope { } } } - - - diff --git a/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java b/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java index 04b6ad2fb..40ef56aee 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/data/tenant/TenantListener.java @@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import javax.management.InvalidApplicationException; import java.util.UUID; + public class TenantListener { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantListener.class)); private final TenantScope tenantScope; From 378f3c957bcf4ab106fe7d60b8017374c052b8e4 Mon Sep 17 00:00:00 2001 From: Diamantis Tziotzios Date: Mon, 22 Apr 2024 10:32:24 +0300 Subject: [PATCH 2/5] mat-autocomplete change --- .../multiple-auto-complete-configuration.ts | 5 ++++- .../multiple-auto-complete.component.html | 4 ++-- .../multiple/multiple-auto-complete.component.ts | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts index 33ec75ee1..17898d24f 100644 --- a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete-configuration.ts @@ -30,6 +30,8 @@ export interface MultipleAutoCompleteConfiguration { valueAssign?: (selectedItem: any) => any; // Callback to provide equals function betwen the values uniqueAssign?: (selectedItem: any) => any; + // Get selected items. Used when valueAssign is used so the full object can be retrieved for presentation. + canRemoveItem?: (selectedItem: any) => { canRemove: boolean, message: string }; // Property formating template optionTemplate?: TemplateRef; // Property formatting component @@ -39,8 +41,9 @@ export interface MultipleAutoCompleteConfiguration { // Display icon that opens popup popupItemActionIcon?: string; + autoSelectFirstOptionOnBlur?: boolean; - appendClassToItem?: {class: string, applyFunc: (item:any) => boolean}[]; + appendClassToItem?: { class: string, applyFunc: (item: any) => boolean }[]; } diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html index b69c9919d..43f8b0746 100644 --- a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.html @@ -4,14 +4,14 @@
- + {{_displayFn(selectedItem)}} - diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts index 920d1d346..abad96f88 100644 --- a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts @@ -96,7 +96,6 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp _selectedItems: Map = new Map(); _groupedItems: Observable; selectable = false; - removable = true; selected: boolean = false; get empty() { @@ -434,6 +433,21 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp this._items = null; } + _canRemoveItem(item: any): boolean { + if(this.configuration.canRemoveItem != null) { + return this.configuration.canRemoveItem(item).canRemove; + } + return true; + } + + _canRemoveItemMessage(item: any): string { + if(this.configuration.canRemoveItem != null) { + const canRemoveResuslt = this.configuration.canRemoveItem(item); + if (canRemoveResuslt.canRemove) return canRemoveResuslt.message; + } + return null; + } + _removeSelectedItem(item: any, event: MouseEvent): void { if (event != null) { event.stopPropagation(); } const valueToDelete = this._valueToAssign(item); From e90e49b4f133d453a98f6b4c10f1e74e6cbcde8a Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Mon, 22 Apr 2024 11:42:07 +0300 Subject: [PATCH 3/5] tenant configuration changes --- .../java/eu/eudat/audit/AuditableAction.java | 5 + .../errorcode/ErrorThesaurusProperties.java | 10 + .../TenantConfigurationBuilder.java | 2 +- .../eu/eudat/model/deleter/TenantDeleter.java | 14 +- .../eudat/query/TenantConfigurationQuery.java | 43 +++- .../lookup/TenantConfigurationLookup.java | 4 + .../TenantConfigurationService.java | 21 ++ .../TenantConfigurationServiceImpl.java | 210 ++++++++++++++++++ .../controllers/EntityDoiController.java | 2 +- .../TenantConfigurationController.java | 76 +++---- .../web/src/main/resources/config/errors.yml | 4 + 11 files changed, 342 insertions(+), 49 deletions(-) create mode 100644 dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java create mode 100644 dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java diff --git a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java index d400b79c0..447a8da61 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java +++ b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java @@ -162,5 +162,10 @@ public class AuditableAction { public static final EventId PrefillingSource_Delete = new EventId(260003, "PrefillingSource_Delete"); public static final EventId PrefillingSource_Generate = new EventId(260004, "PrefillingSource_Generate"); + public static final EventId TenantConfiguration_Query = new EventId(270000, "TenantConfiguration_Query"); + public static final EventId TenantConfiguration_Lookup = new EventId(270001, "TenantConfiguration_Lookup"); + public static final EventId TenantConfiguration_Persist = new EventId(270002, "TenantConfiguration_Persist"); + public static final EventId TenantConfiguration_Delete = new EventId(270003, "TenantConfiguration_Delete"); + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java b/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java index 23cc87410..f3e518eff 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java +++ b/dmp-backend/core/src/main/java/eu/eudat/errorcode/ErrorThesaurusProperties.java @@ -174,4 +174,14 @@ public class ErrorThesaurusProperties { public void setTenantTampering(ErrorDescription tenantTampering) { this.tenantTampering = tenantTampering; } + + private ErrorDescription tenantConfigurationTypeCanNotChange; + + public ErrorDescription getTenantConfigurationTypeCanNotChange() { + return tenantConfigurationTypeCanNotChange; + } + + public void setTenantConfigurationTypeCanNotChange(ErrorDescription tenantConfigurationTypeCanNotChange) { + this.tenantConfigurationTypeCanNotChange = tenantConfigurationTypeCanNotChange; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/tenantconfiguration/TenantConfigurationBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/tenantconfiguration/TenantConfigurationBuilder.java index 50a636a9d..6d0c22672 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/builder/tenantconfiguration/TenantConfigurationBuilder.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/tenantconfiguration/TenantConfigurationBuilder.java @@ -36,7 +36,7 @@ public class TenantConfigurationBuilder extends BaseBuilder ids = data.stream().map(TenantEntity::getId).distinct().collect(Collectors.toList()); + { + logger.debug("checking related - {}", TenantConfigurationEntity.class.getSimpleName()); + List items = this.queryFactory.query(TenantConfigurationQuery.class).tenantIds(ids).collect(); + TenantConfigurationDeleter deleter = this.deleterFactory.deleter(TenantConfigurationDeleter.class); + deleter.delete(items); + } + Instant now = Instant.now(); for (TenantEntity item : data) { diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/TenantConfigurationQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/TenantConfigurationQuery.java index 2baed8d7d..8dce7d98e 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/TenantConfigurationQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/TenantConfigurationQuery.java @@ -6,7 +6,6 @@ import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.enums.TenantConfigurationType; import eu.eudat.data.TenantConfigurationEntity; import eu.eudat.model.tenantconfiguration.TenantConfiguration; -import eu.eudat.query.utils.QueryUtilsService; import gr.cite.tools.data.query.FieldResolver; import gr.cite.tools.data.query.QueryBase; import gr.cite.tools.data.query.QueryContext; @@ -25,16 +24,15 @@ import java.util.*; public class TenantConfigurationQuery extends QueryBase { private Collection ids; + private Collection tenantIds; + private Boolean tenantIsSet; private Collection isActives; private Collection types; private Collection excludedIds; private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); - private final QueryUtilsService queryUtilsService; - - public TenantConfigurationQuery(QueryUtilsService queryUtilsService) { - this.queryUtilsService = queryUtilsService; + public TenantConfigurationQuery() { } public TenantConfigurationQuery ids(UUID value) { @@ -52,6 +50,26 @@ public class TenantConfigurationQuery extends QueryBase values) { + this.tenantIds = values; + return this; + } + + public TenantConfigurationQuery tenantIsSet(Boolean values) { + this.tenantIsSet = values; + return this; + } + public TenantConfigurationQuery isActive(IsActive value) { this.isActives = List.of(value); return this; @@ -104,7 +122,7 @@ public class TenantConfigurationQuery extends QueryBase inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(TenantConfigurationEntity._tenantId)); + for (UUID item : this.tenantIds) inClause.value(item); + predicates.add(inClause); + } if (this.isActives != null) { CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(TenantConfigurationEntity._isActive)); @@ -128,6 +151,12 @@ public class TenantConfigurationQuery extends QueryBase inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(TenantConfigurationEntity._type)); diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java index 3ac81a423..b29d160a3 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java @@ -14,7 +14,9 @@ public class TenantConfigurationLookup extends Lookup { private List isActive; private List types; private List ids; + private List tenantIds; private List excludedIds; + private Boolean tenantIsSet; public List getIsActive() { @@ -55,6 +57,8 @@ public class TenantConfigurationLookup extends Lookup { if (this.isActive != null) query.isActive(this.isActive); if (this.ids != null) query.ids(this.ids); if (this.excludedIds != null) query.excludedIds(this.excludedIds); + if (this.tenantIds != null) query.tenantIds(this.tenantIds); + if (this.tenantIsSet != null) query.tenantIsSet(this.tenantIsSet); this.enrichCommon(query); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java new file mode 100644 index 000000000..686f6c6f0 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java @@ -0,0 +1,21 @@ +package eu.eudat.service.tenantconfiguration; + +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.eudat.model.persist.tenantconfiguration.TenantConfigurationPersist; +import eu.eudat.model.tenantconfiguration.TenantConfiguration; +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.FieldSet; + +import javax.management.InvalidApplicationException; +import java.util.UUID; + +public interface TenantConfigurationService { + + TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException; + + void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java new file mode 100644 index 000000000..680cf1f61 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java @@ -0,0 +1,210 @@ +package eu.eudat.service.tenantconfiguration; + +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.authorization.Permission; +import eu.eudat.commons.JsonHandlingService; +import eu.eudat.commons.enums.EntityType; +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.types.deposit.DepositSourceEntity; +import eu.eudat.commons.types.dmp.DmpPropertiesEntity; +import eu.eudat.commons.types.filetransformer.FileTransformerSourceEntity; +import eu.eudat.commons.types.tenantconfiguration.*; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.TenantConfigurationEntity; +import eu.eudat.data.TenantEntityManager; +import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.model.builder.tenantconfiguration.TenantConfigurationBuilder; +import eu.eudat.model.deleter.TenantConfigurationDeleter; +import eu.eudat.model.persist.deposit.DepositSourcePersist; +import eu.eudat.model.persist.dmpproperties.DmpBlueprintValuePersist; +import eu.eudat.model.persist.dmpproperties.DmpContactPersist; +import eu.eudat.model.persist.dmpproperties.DmpPropertiesPersist; +import eu.eudat.model.persist.filetransformer.FileTransformerSourcePersist; +import eu.eudat.model.persist.tenantconfiguration.*; +import eu.eudat.model.tenantconfiguration.TenantConfiguration; +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.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.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Service; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Service +public class TenantConfigurationServiceImpl implements TenantConfigurationService { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantConfigurationServiceImpl.class)); + + private final TenantEntityManager entityManager; + + private final AuthorizationService authorizationService; + + private final DeleterFactory deleterFactory; + + private final BuilderFactory builderFactory; + + private final ConventionService conventionService; + + private final ErrorThesaurusProperties errors; + + private final MessageSource messageSource; + + private final JsonHandlingService jsonHandlingService; + + + @Autowired + public TenantConfigurationServiceImpl( + TenantEntityManager entityManager, + AuthorizationService authorizationService, + DeleterFactory deleterFactory, + BuilderFactory builderFactory, + ConventionService conventionService, + ErrorThesaurusProperties errors, + MessageSource messageSource, JsonHandlingService jsonHandlingService) { + this.entityManager = entityManager; + this.authorizationService = authorizationService; + this.deleterFactory = deleterFactory; + this.builderFactory = builderFactory; + this.conventionService = conventionService; + this.errors = errors; + this.messageSource = messageSource; + this.jsonHandlingService = jsonHandlingService; + } + + public TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + logger.debug(new MapLogEntry("persisting data TenantConfiguration").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeForce(Permission.EditTenantConfiguration); + + Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); + + TenantConfigurationEntity data; + if (isUpdate) { + data = this.entityManager.find(TenantConfigurationEntity.class, model.getId()); + if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), TenantConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale())); + if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); + if (!data.getType().equals(model.getType())) throw new MyValidationException(this.errors.getTenantConfigurationTypeCanNotChange().getCode(), this.errors.getTenantConfigurationTypeCanNotChange().getMessage()); + } else { + data = new TenantConfigurationEntity(); + data.setId(UUID.randomUUID()); + data.setIsActive(IsActive.Active); + data.setCreatedAt(Instant.now()); + data.setType(model.getType()); + } + + switch (data.getType()){ + case CssColors -> data.setValue(this.jsonHandlingService.toJson(this.buildCssColorsTenantConfigurationEntity(model.getCssColors()))); + case DefaultUserLocale -> data.setValue(this.jsonHandlingService.toJson(this.buildDefaultUserLocaleTenantConfigurationEntity(model.getDefaultUserLocale()))); + case DepositPlugins -> data.setValue(this.jsonHandlingService.toJson(this.buildDepositTenantConfigurationEntity(model.getDepositPlugins()))); + case FileTransformerPlugins -> data.setValue(this.jsonHandlingService.toJson(this.buildFileTransformerTenantConfigurationEntity(model.getFileTransformerPlugins()))); + case Logo -> data.setValue(this.jsonHandlingService.toJson(this.buildLogoTenantConfigurationEntity(model.getLogo()))); + default -> throw new InternalError("unknown type: " + data.getType()); + } + data.setUpdatedAt(Instant.now()); + if (isUpdate) + this.entityManager.merge(data); + else + this.entityManager.persist(data); + + this.entityManager.flush(); + + return this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, TenantConfiguration._id), data); + } + + private @NotNull DepositTenantConfigurationEntity buildDepositTenantConfigurationEntity(DepositTenantConfigurationPersist persist){ + DepositTenantConfigurationEntity data = new DepositTenantConfigurationEntity(); + if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data; + data.setSources(new ArrayList<>()); + for (DepositSourcePersist depositSourcePersist : persist.getSources()) { + data.getSources().add(this.buildDepositSourceEntity(depositSourcePersist)); + } + return data; + } + + private DepositSourceEntity buildDepositSourceEntity(DepositSourcePersist depositSourcePersist) { + DepositSourceEntity depositSourceEntity = new DepositSourceEntity(); + depositSourceEntity.setClientId(depositSourcePersist.getClientId()); + depositSourceEntity.setClientSecret(depositSourcePersist.getClientSecret()); + depositSourceEntity.setRepositoryId(depositSourcePersist.getRepositoryId()); + depositSourceEntity.setUrl(depositSourcePersist.getUrl()); + depositSourceEntity.setIssuerUrl(depositSourcePersist.getIssuerUrl()); + depositSourceEntity.setScope(depositSourcePersist.getScope()); + depositSourceEntity.setPdfTransformerId(depositSourcePersist.getPdfTransformerId()); + depositSourceEntity.setRdaTransformerId(depositSourcePersist.getRdaTransformerId()); + return depositSourceEntity; + } + + private @NotNull FileTransformerTenantConfigurationEntity buildFileTransformerTenantConfigurationEntity(FileTransformerTenantConfigurationPersist persist){ + FileTransformerTenantConfigurationEntity data = new FileTransformerTenantConfigurationEntity(); + if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data; + data.setSources(new ArrayList<>()); + for (FileTransformerSourcePersist depositSourcePersist : persist.getSources()) { + data.getSources().add(this.buildFileTransformerSourceEntity(depositSourcePersist)); + } + return data; + } + + private FileTransformerSourceEntity buildFileTransformerSourceEntity(FileTransformerSourcePersist depositSourcePersist) { + FileTransformerSourceEntity depositSourceEntity = new FileTransformerSourceEntity(); + depositSourceEntity.setClientId(depositSourcePersist.getClientId()); + depositSourceEntity.setClientSecret(depositSourcePersist.getClientSecret()); + depositSourceEntity.setUrl(depositSourcePersist.getUrl()); + depositSourceEntity.setIssuerUrl(depositSourcePersist.getIssuerUrl()); + depositSourceEntity.setScope(depositSourcePersist.getScope()); + depositSourceEntity.setTransformerId(depositSourcePersist.getTransformerId()); + return depositSourceEntity; + } + + private @NotNull CssColorsTenantConfigurationEntity buildCssColorsTenantConfigurationEntity(CssColorsTenantConfigurationPersist persist){ + CssColorsTenantConfigurationEntity data = new CssColorsTenantConfigurationEntity(); + if (persist == null) return data; + data.setPrimaryColor(persist.getPrimaryColor()); + data.setPrimaryColor2(persist.getPrimaryColor2()); + data.setPrimaryColor3(persist.getPrimaryColor3()); + data.setSecondaryColor(persist.getSecondaryColor()); + return data; + } + + private @NotNull DefaultUserLocaleTenantConfigurationEntity buildDefaultUserLocaleTenantConfigurationEntity(DefaultUserLocaleTenantConfigurationPersist persist){ + DefaultUserLocaleTenantConfigurationEntity data = new DefaultUserLocaleTenantConfigurationEntity(); + if (persist == null) return data; + data.setCulture(persist.getCulture()); + data.setLanguage(persist.getLanguage()); + data.setTimezone(persist.getTimezone()); + return data; + } + + private @NotNull LogoTenantConfigurationEntity buildLogoTenantConfigurationEntity(LogoTenantConfigurationPersist persist){ + LogoTenantConfigurationEntity data = new LogoTenantConfigurationEntity(); + if (persist == null) return data; + data.setStorageFileId(persist.getStorageFileId()); + //TODO + return data; + } + + public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug("deleting dataset: {}", id); + + this.authorizationService.authorizeForce(Permission.DeleteTenantConfiguration); + + this.deleterFactory.deleter(TenantConfigurationDeleter.class).deleteAndSaveByIds(List.of(id)); + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/EntityDoiController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/EntityDoiController.java index 156339675..be56098f1 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/EntityDoiController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/EntityDoiController.java @@ -37,7 +37,7 @@ import java.util.*; @RequestMapping(path = "api/entity-doi") public class EntityDoiController { - private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeController.class)); + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(EntityDoiController.class)); private final BuilderFactory builderFactory; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java index 156339675..e7425cca0 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java @@ -1,19 +1,18 @@ package eu.eudat.controllers; +import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; -import gr.cite.tools.validation.ValidationFilterAnnotation; -import eu.eudat.data.EntityDoiEntity; +import eu.eudat.data.TenantConfigurationEntity; import eu.eudat.model.DescriptionTemplateType; -import eu.eudat.model.EntityDoi; -import eu.eudat.model.builder.EntityDoiBuilder; -import eu.eudat.model.censorship.EntityDoiCensor; -import eu.eudat.model.persist.EntityDoiPersist; +import eu.eudat.model.builder.tenantconfiguration.TenantConfigurationBuilder; +import eu.eudat.model.censorship.tenantconfiguration.TenantConfigurationCensor; +import eu.eudat.model.persist.tenantconfiguration.TenantConfigurationPersist; import eu.eudat.model.result.QueryResult; -import eu.eudat.query.EntityDoiQuery; -import eu.eudat.query.lookup.EntityDoiLookup; -import eu.eudat.service.deposit.DepositService; -import eu.eudat.service.entitydoi.EntityDoiService; +import eu.eudat.model.tenantconfiguration.TenantConfiguration; +import eu.eudat.query.TenantConfigurationQuery; +import eu.eudat.query.lookup.TenantConfigurationLookup; +import eu.eudat.service.tenantconfiguration.TenantConfigurationService; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.censor.CensorFactory; @@ -24,6 +23,7 @@ import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.MapLogEntry; +import gr.cite.tools.validation.ValidationFilterAnnotation; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; @@ -34,16 +34,16 @@ import javax.management.InvalidApplicationException; import java.util.*; @RestController -@RequestMapping(path = "api/entity-doi") -public class EntityDoiController { +@RequestMapping(path = "api/tenant-configuration") +public class TenantConfigurationController { - private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeController.class)); + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantConfigurationController.class)); private final BuilderFactory builderFactory; private final AuditService auditService; - private final EntityDoiService entityDoiService; + private final TenantConfigurationService tenantConfigurationService; private final CensorFactory censorFactory; @@ -51,49 +51,49 @@ public class EntityDoiController { private final MessageSource messageSource; - public EntityDoiController( + public TenantConfigurationController( BuilderFactory builderFactory, AuditService auditService, - EntityDoiService entityDoiService, CensorFactory censorFactory, + TenantConfigurationService tenantConfigurationService, CensorFactory censorFactory, QueryFactory queryFactory, MessageSource messageSource) { this.builderFactory = builderFactory; this.auditService = auditService; - this.entityDoiService = entityDoiService; + this.tenantConfigurationService = tenantConfigurationService; this.censorFactory = censorFactory; this.queryFactory = queryFactory; this.messageSource = messageSource; } @PostMapping("query") - public QueryResult Query(@RequestBody EntityDoiLookup lookup) throws MyApplicationException, MyForbiddenException { - logger.debug("querying {}", EntityDoi.class.getSimpleName()); + public QueryResult Query(@RequestBody TenantConfigurationLookup lookup) throws MyApplicationException, MyForbiddenException { + logger.debug("querying {}", TenantConfiguration.class.getSimpleName()); - this.censorFactory.censor(EntityDoiCensor.class).censor(lookup.getProject(), null); + this.censorFactory.censor(TenantConfigurationCensor.class).censor(lookup.getProject(), null); - EntityDoiQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission); + TenantConfigurationQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission); - List data = query.collectAs(lookup.getProject()); - List models = this.builderFactory.builder(EntityDoiBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(lookup.getProject(), data); + List data = query.collectAs(lookup.getProject()); + List models = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(lookup.getProject(), data); long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); - this.auditService.track(AuditableAction.EntityDoi_Query, "lookup", lookup); + this.auditService.track(AuditableAction.TenantConfiguration_Query, "lookup", lookup); return new QueryResult<>(models, count); } @GetMapping("{id}") - public EntityDoi Get(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { - logger.debug(new MapLogEntry("retrieving" + EntityDoi.class.getSimpleName()).And("id", id).And("fields", fieldSet)); + public TenantConfiguration Get(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("retrieving" + TenantConfiguration.class.getSimpleName()).And("id", id).And("fields", fieldSet)); - this.censorFactory.censor(EntityDoiCensor.class).censor(fieldSet, null); + this.censorFactory.censor(TenantConfigurationCensor.class).censor(fieldSet, null); - EntityDoiQuery query = this.queryFactory.query(EntityDoiQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(id); - EntityDoi model = this.builderFactory.builder(EntityDoiBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(fieldSet, query.firstAs(fieldSet)); + TenantConfigurationQuery query = this.queryFactory.query(TenantConfigurationQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(id); + TenantConfiguration model = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(fieldSet, query.firstAs(fieldSet)); if (model == null) - throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, EntityDoi.class.getSimpleName()}, LocaleContextHolder.getLocale())); + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, TenantConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale())); - this.auditService.track(AuditableAction.EntityDoi_Lookup, Map.ofEntries( + this.auditService.track(AuditableAction.TenantConfiguration_Lookup, Map.ofEntries( new AbstractMap.SimpleEntry("id", id), new AbstractMap.SimpleEntry("fields", fieldSet) )); @@ -103,12 +103,12 @@ public class EntityDoiController { @PostMapping("persist") @Transactional - @ValidationFilterAnnotation(validator = EntityDoiPersist.EntityDoiPersistValidator.ValidatorName, argumentName = "model") - public EntityDoi Persist(@RequestBody EntityDoiPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + @ValidationFilterAnnotation(validator = TenantConfigurationPersist.TenantConfigurationPersistValidator.ValidatorName, argumentName = "model") + public TenantConfiguration Persist(@RequestBody TenantConfigurationPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { logger.debug(new MapLogEntry("persisting" + DescriptionTemplateType.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); - EntityDoi persisted = this.entityDoiService.persist(model, fieldSet); + TenantConfiguration persisted = this.tenantConfigurationService.persist(model, fieldSet); - this.auditService.track(AuditableAction.EntityDoi_Persist, Map.ofEntries( + this.auditService.track(AuditableAction.TenantConfiguration_Persist, Map.ofEntries( new AbstractMap.SimpleEntry("model", model), new AbstractMap.SimpleEntry("fields", fieldSet) )); @@ -119,11 +119,11 @@ public class EntityDoiController { @DeleteMapping("{id}") @Transactional public void Delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { - logger.debug(new MapLogEntry("retrieving" + EntityDoi.class.getSimpleName()).And("id", id)); + logger.debug(new MapLogEntry("retrieving" + TenantConfiguration.class.getSimpleName()).And("id", id)); - this.entityDoiService.deleteAndSave(id); + this.tenantConfigurationService.deleteAndSave(id); - this.auditService.track(AuditableAction.EntityDoi_Delete, "id", id); + this.auditService.track(AuditableAction.TenantConfiguration_Delete, "id", id); } } diff --git a/dmp-backend/web/src/main/resources/config/errors.yml b/dmp-backend/web/src/main/resources/config/errors.yml index 6b3580195..7cdda0db9 100644 --- a/dmp-backend/web/src/main/resources/config/errors.yml +++ b/dmp-backend/web/src/main/resources/config/errors.yml @@ -59,3 +59,7 @@ error-thesaurus: tenant-tampering: code: 123 message: Tenant tampering + tenant-configuration-type-can-not-change: + code: 124 + message: Tenant configuration type can not change + From 1b78203d27cf366aad10fc90509a099894a28017 Mon Sep 17 00:00:00 2001 From: amentis Date: Mon, 22 Apr 2024 11:51:45 +0300 Subject: [PATCH 4/5] dmp, description autocomplete config changes --- .../services/description/description.service.ts | 16 ++++++++-------- .../src/app/core/services/dmp/dmp.service.ts | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dmp-frontend/src/app/core/services/description/description.service.ts b/dmp-frontend/src/app/core/services/description/description.service.ts index eb0f75948..305022023 100644 --- a/dmp-frontend/src/app/core/services/description/description.service.ts +++ b/dmp-frontend/src/app/core/services/description/description.service.ts @@ -126,9 +126,9 @@ export class DescriptionService { // // tslint:disable-next-line: member-ordering singleAutocompleteConfiguration: SingleAutoCompleteConfiguration = { - initialItems: (data?: any) => this.query(this.buildAutocompleteLookup()).pipe(map(x => x.items)), - filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteLookup(searchQuery)).pipe(map(x => x.items)), - getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), + initialItems: (data?: any) => this.query(this.buildAutocompleteLookup([IsActive.Active])).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteLookup([IsActive.Active], searchQuery)).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, [selectedItem])).pipe(map(x => x.items[0])), displayFn: (item: Description) => item.label, titleFn: (item: Description) => item.label, valueAssign: (item: Description) => item.id, @@ -136,20 +136,20 @@ export class DescriptionService { // tslint:disable-next-line: member-ordering multipleAutocompleteConfiguration: MultipleAutoCompleteConfiguration = { - initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup(null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), - filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup(searchQuery, excludedItems)).pipe(map(x => x.items)), - getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup(null, null, selectedItems)).pipe(map(x => x.items)), + initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup([IsActive.Active], null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), + filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup([IsActive.Active], searchQuery, excludedItems)).pipe(map(x => x.items)), + getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, selectedItems)).pipe(map(x => x.items)), displayFn: (item: Description) => item.label, titleFn: (item: Description) => item.label, valueAssign: (item: Description) => item.id, }; - public buildAutocompleteLookup(like?: string, excludedIds?: Guid[], ids?: Guid[]): DescriptionLookup { + public buildAutocompleteLookup(isActive: IsActive[], like?: string, excludedIds?: Guid[], ids?: Guid[]): DescriptionLookup { const lookup: DescriptionLookup = new DescriptionLookup(); lookup.page = { size: 100, offset: 0 }; if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } if (ids && ids.length > 0) { lookup.ids = ids; } - lookup.isActive = [IsActive.Active]; + lookup.isActive = isActive; lookup.project = { fields: [ nameof(x => x.id), diff --git a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts index 0f6a3c315..e195c7532 100644 --- a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts +++ b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts @@ -208,9 +208,9 @@ export class DmpService { // // tslint:disable-next-line: member-ordering singleAutocompleteConfiguration: SingleAutoCompleteConfiguration = { - initialItems: (data?: any) => this.query(this.buildAutocompleteLookup()).pipe(map(x => x.items)), - filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteLookup(searchQuery)).pipe(map(x => x.items)), - getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), + initialItems: (data?: any) => this.query(this.buildAutocompleteLookup([IsActive.Active])).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteLookup([IsActive.Active], searchQuery)).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, [selectedItem])).pipe(map(x => x.items[0])), displayFn: (item: Dmp) => item.label, titleFn: (item: Dmp) => item.label, valueAssign: (item: Dmp) => item.id, @@ -218,20 +218,20 @@ export class DmpService { // tslint:disable-next-line: member-ordering multipleAutocompleteConfiguration: MultipleAutoCompleteConfiguration = { - initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup(null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), - filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup(searchQuery, excludedItems)).pipe(map(x => x.items)), - getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup(null, null, selectedItems)).pipe(map(x => x.items)), + initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup([IsActive.Active], null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), + filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup([IsActive.Active],searchQuery, excludedItems)).pipe(map(x => x.items)), + getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup([IsActive.Active, IsActive.Inactive], null, null, selectedItems)).pipe(map(x => x.items)), displayFn: (item: Dmp) => item.label, titleFn: (item: Dmp) => item.label, valueAssign: (item: Dmp) => item.id, }; - public buildAutocompleteLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup { + public buildAutocompleteLookup(isActive: IsActive[], like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup { const lookup: DmpLookup = new DmpLookup(); lookup.page = { size: 100, offset: 0 }; if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } if (ids && ids.length > 0) { lookup.ids = ids; } - lookup.isActive = [IsActive.Active]; + lookup.isActive = isActive; lookup.statuses = statuses; lookup.project = { fields: [ From 4b38b990fc30d2da71bb56d5e483ab46d52482cf Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Mon, 22 Apr 2024 12:13:23 +0300 Subject: [PATCH 5/5] tenant configuration changes --- .../builder/deposit/DepositSourceBuilder.java | 30 ++++++-- .../FileTransformerSourceBuilder.java | 33 ++++++++- .../DepositTenantConfigurationBuilder.java | 2 +- ...TransformerTenantConfigurationBuilder.java | 2 +- .../eudat/query/lookup/EntityDoiLookup.java | 40 +++++++++++ .../lookup/TenantConfigurationLookup.java | 16 +++++ .../eudat/service/tenant/TenantService.java | 1 - .../service/tenant/TenantServiceImpl.java | 24 +------ .../TenantConfigurationService.java | 8 ++- .../TenantConfigurationServiceImpl.java | 70 ++++++++++++++----- .../TenantConfigurationController.java | 8 ++- .../eudat/controllers/TenantController.java | 5 -- 12 files changed, 181 insertions(+), 58 deletions(-) diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/deposit/DepositSourceBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/deposit/DepositSourceBuilder.java index 770923ee5..416df7c70 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/builder/deposit/DepositSourceBuilder.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/deposit/DepositSourceBuilder.java @@ -1,14 +1,12 @@ package eu.eudat.model.builder.deposit; import eu.eudat.authorization.AuthorizationFlags; -import eu.eudat.commons.XmlHandlingService; -import eu.eudat.commons.scope.tenant.TenantScope; import eu.eudat.commons.types.deposit.DepositSourceEntity; import eu.eudat.convention.ConventionService; import eu.eudat.model.builder.BaseBuilder; import eu.eudat.model.deposit.DepositSource; -import gr.cite.tools.data.builder.BuilderFactory; -import gr.cite.tools.data.query.QueryFactory; +import eu.eudat.service.encryption.EncryptionService; +import eu.eudat.service.tenant.TenantProperties; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.logging.DataLogEntry; @@ -25,11 +23,16 @@ import java.util.*; @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class DepositSourceBuilder extends BaseBuilder { private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + private boolean encrypted; + private final EncryptionService encryptionService; + private final TenantProperties tenantProperties; @Autowired public DepositSourceBuilder( - ConventionService conventionService) { + ConventionService conventionService, EncryptionService encryptionService, TenantProperties tenantProperties) { super(conventionService, new LoggerService(LoggerFactory.getLogger(DepositSourceBuilder.class))); + this.encryptionService = encryptionService; + this.tenantProperties = tenantProperties; } public DepositSourceBuilder authorize(EnumSet values) { @@ -37,6 +40,11 @@ public class DepositSourceBuilder extends BaseBuilder build(FieldSet fields, List data) throws MyApplicationException { this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); @@ -51,7 +59,17 @@ public class DepositSourceBuilder extends BaseBuilder { private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); - + private final EncryptionService encryptionService; + private final TenantProperties tenantProperties; + private boolean encrypted; @Autowired public FileTransformerSourceBuilder( - ConventionService conventionService) { + ConventionService conventionService, EncryptionService encryptionService, TenantProperties tenantProperties) { super(conventionService, new LoggerService(LoggerFactory.getLogger(FileTransformerSourceBuilder.class))); + this.encryptionService = encryptionService; + this.tenantProperties = tenantProperties; } public FileTransformerSourceBuilder authorize(EnumSet values) { @@ -33,6 +45,11 @@ public class FileTransformerSourceBuilder extends BaseBuilder build(FieldSet fields, List data) throws MyApplicationException { this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); @@ -47,7 +64,17 @@ public class FileTransformerSourceBuilder extends BaseBuilder dois; + public List getIsActive() { + return isActive; + } + + public void setIsActive(List isActive) { + this.isActive = isActive; + } + + public List getTypes() { + return types; + } + + public void setTypes(List types) { + this.types = types; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + public List getExcludedIds() { + return excludedIds; + } + + public void setExcludedIds(List excludedIds) { + this.excludedIds = excludedIds; + } + + public List getDois() { + return dois; + } + + public void setDois(List dois) { + this.dois = dois; + } + public EntityDoiQuery enrich(QueryFactory queryFactory) { EntityDoiQuery query = queryFactory.query(EntityDoiQuery.class); if (this.isActive != null) diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java index b29d160a3..d8f7a8091 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/TenantConfigurationLookup.java @@ -51,6 +51,22 @@ public class TenantConfigurationLookup extends Lookup { this.types = types; } + public List getTenantIds() { + return tenantIds; + } + + public void setTenantIds(List tenantIds) { + this.tenantIds = tenantIds; + } + + public Boolean getTenantIsSet() { + return tenantIsSet; + } + + public void setTenantIsSet(Boolean tenantIsSet) { + this.tenantIsSet = tenantIsSet; + } + public TenantConfigurationQuery enrich(QueryFactory queryFactory) { TenantConfigurationQuery query = queryFactory.query(TenantConfigurationQuery.class); if (this.types != null) query.types(this.types); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java index 311b91c15..aaf06e5ad 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantService.java @@ -25,6 +25,5 @@ public interface TenantService { Tenant persist(TenantPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException; - Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException; void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java index 7848f8dbb..a1f729271 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenant/TenantServiceImpl.java @@ -51,7 +51,6 @@ 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; @@ -190,28 +189,7 @@ public class TenantServiceImpl implements TenantService { } - @Override - public Tenant decryptTenant(Tenant model) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException { -// 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())); -// } -// } - - 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); - return model; - } + @Override public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java index 686f6c6f0..fbc587643 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationService.java @@ -9,12 +9,18 @@ import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.exception.MyValidationException; import gr.cite.tools.fieldset.FieldSet; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; import javax.management.InvalidApplicationException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.UUID; public interface TenantConfigurationService { - TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException; + TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException; void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java index 680cf1f61..d5f0f5ad4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/tenantconfiguration/TenantConfigurationServiceImpl.java @@ -4,25 +4,26 @@ import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.JsonHandlingService; -import eu.eudat.commons.enums.EntityType; import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.StorageType; +import eu.eudat.commons.enums.TenantConfigurationType; import eu.eudat.commons.types.deposit.DepositSourceEntity; -import eu.eudat.commons.types.dmp.DmpPropertiesEntity; import eu.eudat.commons.types.filetransformer.FileTransformerSourceEntity; import eu.eudat.commons.types.tenantconfiguration.*; import eu.eudat.convention.ConventionService; import eu.eudat.data.TenantConfigurationEntity; import eu.eudat.data.TenantEntityManager; import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.model.StorageFile; import eu.eudat.model.builder.tenantconfiguration.TenantConfigurationBuilder; import eu.eudat.model.deleter.TenantConfigurationDeleter; import eu.eudat.model.persist.deposit.DepositSourcePersist; -import eu.eudat.model.persist.dmpproperties.DmpBlueprintValuePersist; -import eu.eudat.model.persist.dmpproperties.DmpContactPersist; -import eu.eudat.model.persist.dmpproperties.DmpPropertiesPersist; import eu.eudat.model.persist.filetransformer.FileTransformerSourcePersist; import eu.eudat.model.persist.tenantconfiguration.*; import eu.eudat.model.tenantconfiguration.TenantConfiguration; +import eu.eudat.service.encryption.EncryptionService; +import eu.eudat.service.storage.StorageFileService; +import eu.eudat.service.tenant.TenantProperties; import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.deleter.DeleterFactory; @@ -41,7 +42,13 @@ import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Service; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; 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; @@ -68,7 +75,10 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic private final JsonHandlingService jsonHandlingService; + private final EncryptionService encryptionService; + private final TenantProperties tenantProperties; + private final StorageFileService storageFileService; @Autowired public TenantConfigurationServiceImpl( TenantEntityManager entityManager, @@ -77,7 +87,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic BuilderFactory builderFactory, ConventionService conventionService, ErrorThesaurusProperties errors, - MessageSource messageSource, JsonHandlingService jsonHandlingService) { + MessageSource messageSource, JsonHandlingService jsonHandlingService, EncryptionService encryptionService, TenantProperties tenantProperties, StorageFileService storageFileService) { this.entityManager = entityManager; this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; @@ -86,9 +96,12 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic this.errors = errors; this.messageSource = messageSource; this.jsonHandlingService = jsonHandlingService; + this.encryptionService = encryptionService; + this.tenantProperties = tenantProperties; + this.storageFileService = storageFileService; } - public TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public TenantConfiguration persist(TenantConfigurationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { logger.debug(new MapLogEntry("persisting data TenantConfiguration").And("model", model).And("fields", fields)); this.authorizationService.authorizeForce(Permission.EditTenantConfiguration); @@ -109,12 +122,16 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic data.setType(model.getType()); } + switch (data.getType()){ case CssColors -> data.setValue(this.jsonHandlingService.toJson(this.buildCssColorsTenantConfigurationEntity(model.getCssColors()))); case DefaultUserLocale -> data.setValue(this.jsonHandlingService.toJson(this.buildDefaultUserLocaleTenantConfigurationEntity(model.getDefaultUserLocale()))); case DepositPlugins -> data.setValue(this.jsonHandlingService.toJson(this.buildDepositTenantConfigurationEntity(model.getDepositPlugins()))); case FileTransformerPlugins -> data.setValue(this.jsonHandlingService.toJson(this.buildFileTransformerTenantConfigurationEntity(model.getFileTransformerPlugins()))); - case Logo -> data.setValue(this.jsonHandlingService.toJson(this.buildLogoTenantConfigurationEntity(model.getLogo()))); + case Logo -> { + LogoTenantConfigurationEntity oldValue = this.conventionService.isNullOrEmpty(data.getValue()) ? null : this.jsonHandlingService.fromJsonSafe(LogoTenantConfigurationEntity.class, data.getValue()); + data.setValue(this.jsonHandlingService.toJson(this.buildLogoTenantConfigurationEntity(model.getLogo(), oldValue))); + } default -> throw new InternalError("unknown type: " + data.getType()); } data.setUpdatedAt(Instant.now()); @@ -128,7 +145,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic return this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, TenantConfiguration._id), data); } - private @NotNull DepositTenantConfigurationEntity buildDepositTenantConfigurationEntity(DepositTenantConfigurationPersist persist){ + private @NotNull DepositTenantConfigurationEntity buildDepositTenantConfigurationEntity(DepositTenantConfigurationPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { DepositTenantConfigurationEntity data = new DepositTenantConfigurationEntity(); if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data; data.setSources(new ArrayList<>()); @@ -138,10 +155,10 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic return data; } - private DepositSourceEntity buildDepositSourceEntity(DepositSourcePersist depositSourcePersist) { + private DepositSourceEntity buildDepositSourceEntity(DepositSourcePersist depositSourcePersist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { DepositSourceEntity depositSourceEntity = new DepositSourceEntity(); depositSourceEntity.setClientId(depositSourcePersist.getClientId()); - depositSourceEntity.setClientSecret(depositSourcePersist.getClientSecret()); + if (!this.conventionService.isNullOrEmpty(depositSourcePersist.getClientSecret())) depositSourceEntity.setClientSecret(this.encryptionService.encryptAES(depositSourcePersist.getClientSecret(), this.tenantProperties.getConfigEncryptionAesKey(), this.tenantProperties.getConfigEncryptionAesIv())); depositSourceEntity.setRepositoryId(depositSourcePersist.getRepositoryId()); depositSourceEntity.setUrl(depositSourcePersist.getUrl()); depositSourceEntity.setIssuerUrl(depositSourcePersist.getIssuerUrl()); @@ -151,7 +168,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic return depositSourceEntity; } - private @NotNull FileTransformerTenantConfigurationEntity buildFileTransformerTenantConfigurationEntity(FileTransformerTenantConfigurationPersist persist){ + private @NotNull FileTransformerTenantConfigurationEntity buildFileTransformerTenantConfigurationEntity(FileTransformerTenantConfigurationPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { FileTransformerTenantConfigurationEntity data = new FileTransformerTenantConfigurationEntity(); if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data; data.setSources(new ArrayList<>()); @@ -161,10 +178,10 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic return data; } - private FileTransformerSourceEntity buildFileTransformerSourceEntity(FileTransformerSourcePersist depositSourcePersist) { + private FileTransformerSourceEntity buildFileTransformerSourceEntity(FileTransformerSourcePersist depositSourcePersist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { FileTransformerSourceEntity depositSourceEntity = new FileTransformerSourceEntity(); depositSourceEntity.setClientId(depositSourcePersist.getClientId()); - depositSourceEntity.setClientSecret(depositSourcePersist.getClientSecret()); + if (!this.conventionService.isNullOrEmpty(depositSourcePersist.getClientSecret())) depositSourceEntity.setClientSecret(this.encryptionService.encryptAES(depositSourcePersist.getClientSecret(), this.tenantProperties.getConfigEncryptionAesKey(), this.tenantProperties.getConfigEncryptionAesIv())); depositSourceEntity.setUrl(depositSourcePersist.getUrl()); depositSourceEntity.setIssuerUrl(depositSourcePersist.getIssuerUrl()); depositSourceEntity.setScope(depositSourcePersist.getScope()); @@ -191,11 +208,25 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic return data; } - private @NotNull LogoTenantConfigurationEntity buildLogoTenantConfigurationEntity(LogoTenantConfigurationPersist persist){ + private @NotNull LogoTenantConfigurationEntity buildLogoTenantConfigurationEntity(LogoTenantConfigurationPersist persist, LogoTenantConfigurationEntity oldValue) throws InvalidApplicationException { LogoTenantConfigurationEntity data = new LogoTenantConfigurationEntity(); if (persist == null) return data; data.setStorageFileId(persist.getStorageFileId()); - //TODO + + UUID existingFileId = oldValue != null ? oldValue.getStorageFileId() : null; + if (persist.getStorageFileId() != null){ + if (!persist.getStorageFileId().equals(existingFileId)) { + StorageFile storageFile = this.storageFileService.copyToStorage(persist.getStorageFileId(), StorageType.Main, true, new BaseFieldSet().ensure(StorageFile._id)); + this.storageFileService.updatePurgeAt(storageFile.getId(), null); + if (existingFileId != null) this.storageFileService.updatePurgeAt(existingFileId, Instant.now().minusSeconds(60)); + data.setStorageFileId(storageFile.getId()); + } else { + data.setStorageFileId(existingFileId); + } + } else { + if (existingFileId != null) this.storageFileService.updatePurgeAt(existingFileId, Instant.now().minusSeconds(60)); + data.setStorageFileId(null); + } return data; } @@ -204,6 +235,13 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic this.authorizationService.authorizeForce(Permission.DeleteTenantConfiguration); + TenantConfigurationEntity data = this.entityManager.find(TenantConfigurationEntity.class, id); + if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, TenantConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + if (data.getType().equals(TenantConfigurationType.Logo)){ + LogoTenantConfigurationEntity oldValue = this.conventionService.isNullOrEmpty(data.getValue()) ? null : this.jsonHandlingService.fromJsonSafe(LogoTenantConfigurationEntity.class, data.getValue()); + if (oldValue != null && oldValue.getStorageFileId() != null) this.storageFileService.updatePurgeAt(oldValue.getStorageFileId(), Instant.now().minusSeconds(60)); + } this.deleterFactory.deleter(TenantConfigurationDeleter.class).deleteAndSaveByIds(List.of(id)); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java index e7425cca0..2c8b5236d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantConfigurationController.java @@ -30,7 +30,13 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; import javax.management.InvalidApplicationException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.*; @RestController @@ -104,7 +110,7 @@ public class TenantConfigurationController { @PostMapping("persist") @Transactional @ValidationFilterAnnotation(validator = TenantConfigurationPersist.TenantConfigurationPersistValidator.ValidatorName, argumentName = "model") - public TenantConfiguration Persist(@RequestBody TenantConfigurationPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { + public TenantConfiguration Persist(@RequestBody TenantConfigurationPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { logger.debug(new MapLogEntry("persisting" + DescriptionTemplateType.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); TenantConfiguration persisted = this.tenantConfigurationService.persist(model, fieldSet); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java index feef64391..7533320b9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/TenantController.java @@ -86,9 +86,6 @@ public class TenantController { List data = query.collectAs(lookup.getProject()); List models = this.builderFactory.builder(TenantBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(lookup.getProject(), data); - for (Tenant model : models) { - models.set(models.indexOf(model), this.tenantService.decryptTenant(model)); - } long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); this.auditService.track(AuditableAction.Tenant_Query, "lookup", lookup); @@ -107,8 +104,6 @@ public class TenantController { if (model == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Tenant.class.getSimpleName()}, LocaleContextHolder.getLocale())); - model = this.tenantService.decryptTenant(model); - this.auditService.track(AuditableAction.Tenant_Lookup, Map.ofEntries( new AbstractMap.SimpleEntry("id", id), new AbstractMap.SimpleEntry("fields", fieldSet)