From 1a76942b5f46e5427522db5400477e33d448e0c0 Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Mon, 4 Dec 2023 18:38:23 +0200 Subject: [PATCH] add Description PersistStatus --- .../java/eu/eudat/audit/AuditableAction.java | 1 + .../errorcode/ErrorThesaurusProperties.java | 16 ++++-- .../persist/DescriptionStatusPersist.java | 54 +++++++++++++++++++ .../description/DescriptionService.java | 2 + .../description/DescriptionServiceImpl.java | 29 ++++++++++ .../controllers/v2/DescriptionController.java | 15 ++++++ .../web/src/main/resources/config/errors.yml | 3 ++ 7 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionStatusPersist.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 f164c03d4..b6c83a378 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 @@ -42,6 +42,7 @@ public class AuditableAction { public static final EventId Description_Delete = new EventId(6003, "Description_Delete"); public static final EventId Description_PublicQuery = new EventId(6004, "Description_PublicQuery"); public static final EventId Description_PublicLookup = new EventId(6005, "Description_PublicLookup"); + public static final EventId Description_PersistStatus = new EventId(6006, "Description_PersistStatus"); public static final EventId Reference_Query = new EventId(7000, "Reference_Query"); public static final EventId Reference_Lookup = new EventId(7001, "Reference_Lookup"); 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 53b6cd926..525e3014f 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 @@ -45,14 +45,14 @@ public class ErrorThesaurusProperties { this.modelValidation = modelValidation; } - private ErrorDescription DescriptionTemplateNewVersionConflict; + private ErrorDescription descriptionTemplateNewVersionConflict; public ErrorDescription getDescriptionTemplateNewVersionConflict() { - return DescriptionTemplateNewVersionConflict; + return descriptionTemplateNewVersionConflict; } public void setDescriptionTemplateNewVersionConflict(ErrorDescription descriptionTemplateNewVersionConflict) { - DescriptionTemplateNewVersionConflict = descriptionTemplateNewVersionConflict; + this.descriptionTemplateNewVersionConflict = descriptionTemplateNewVersionConflict; } private ErrorDescription dmpNewVersionConflict; @@ -64,4 +64,14 @@ public class ErrorThesaurusProperties { public void setDmpNewVersionConflict(ErrorDescription dmpNewVersionConflict) { this.dmpNewVersionConflict = dmpNewVersionConflict; } + + private ErrorDescription dmpIsFinalized; + + public ErrorDescription getDmpIsFinalized() { + return dmpIsFinalized; + } + + public void setDmpIsFinalized(ErrorDescription dmpIsFinalized) { + this.dmpIsFinalized = dmpIsFinalized; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionStatusPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionStatusPersist.java new file mode 100644 index 000000000..7c092f29f --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionStatusPersist.java @@ -0,0 +1,54 @@ +package eu.eudat.model.persist; + +import eu.eudat.commons.enums.DescriptionStatus; +import eu.eudat.commons.validation.FieldNotNullIfOtherSet; +import eu.eudat.commons.validation.ValidEnum; +import eu.eudat.commons.validation.ValidId; +import eu.eudat.data.DescriptionEntity; +import eu.eudat.model.persist.descriptionproperties.PropertyDefinitionPersist; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +import java.util.List; +import java.util.UUID; + +@FieldNotNullIfOtherSet(message = "{validation.hashempty}") +public class DescriptionStatusPersist { + + @NotNull(message = "{validation.empty}") + @ValidId(message = "{validation.invalidid}") + private UUID id; + + @ValidEnum(message = "{validation.empty}") + private DescriptionStatus status; + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + private String hash; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public DescriptionStatus getStatus() { + return status; + } + + public void setStatus(DescriptionStatus status) { + this.status = status; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java index 79ea829e2..e7c6df3fe 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionService.java @@ -3,6 +3,7 @@ package eu.eudat.service.description; import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.model.Description; import eu.eudat.model.persist.DescriptionPersist; +import eu.eudat.model.persist.DescriptionStatusPersist; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyForbiddenException; import gr.cite.tools.exception.MyNotFoundException; @@ -16,6 +17,7 @@ import java.util.UUID; public interface DescriptionService { Description persist(DescriptionPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException; + Description persistStatus(DescriptionStatusPersist model, FieldSet fields); void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java index ee75cdeea..7d01d14ea 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java @@ -6,6 +6,7 @@ import eu.eudat.authorization.Permission; import eu.eudat.commons.JsonHandlingService; import eu.eudat.commons.XmlHandlingService; import eu.eudat.commons.enums.DescriptionStatus; +import eu.eudat.commons.enums.DmpStatus; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.commons.types.description.FieldEntity; @@ -24,6 +25,7 @@ import eu.eudat.model.deleter.DescriptionReferenceDeleter; import eu.eudat.model.deleter.DescriptionTagDeleter; import eu.eudat.model.persist.DescriptionPersist; import eu.eudat.model.persist.DescriptionReferencePersist; +import eu.eudat.model.persist.DescriptionStatusPersist; import eu.eudat.model.persist.ReferencePersist; import eu.eudat.model.persist.descriptionproperties.FieldPersist; import eu.eudat.model.persist.descriptionproperties.PropertyDefinitionPersist; @@ -154,6 +156,33 @@ public class DescriptionServiceImpl implements DescriptionService { return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Description._id), data); } + @Override + public Description persistStatus(DescriptionStatusPersist model, FieldSet fields) { + logger.debug(new MapLogEntry("persisting data dmp").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeForce(Permission.EditDescription); + + DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId()); + if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.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.getStatus().equals(model.getStatus())){ + if (data.getStatus() == DescriptionStatus.Finalized){ + DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, data.getDmpId()); + if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{data.getDmpId(), DmpEntity.class.getSimpleName()}, LocaleContextHolder.getLocale())); + if(dmpEntity.getStatus() .equals(DmpStatus.Finalized)) throw new MyValidationException(this.errors.getDmpIsFinalized().getCode(), this.errors.getDmpIsFinalized().getMessage()); + } + + data.setStatus(model.getStatus()); + data.setUpdatedAt(Instant.now()); + this.entityManager.merge(data); + + this.entityManager.flush(); + + this.eventBroker.emit(new DescriptionTouchedEvent(data.getId())); + } + return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Description._id), data); + } + private @NotNull PropertyDefinitionEntity buildPropertyDefinitionEntity(PropertyDefinitionPersist persist){ PropertyDefinitionEntity data = new PropertyDefinitionEntity(); if (persist == null) return data; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java index 44d48f4fa..fbedf9fb9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionController.java @@ -13,6 +13,7 @@ import eu.eudat.model.builder.DescriptionBuilder; import eu.eudat.model.censorship.DescriptionCensor; import eu.eudat.model.censorship.PublicDescriptionCensor; import eu.eudat.model.persist.DescriptionPersist; +import eu.eudat.model.persist.DescriptionStatusPersist; import eu.eudat.model.result.QueryResult; import eu.eudat.query.DescriptionQuery; import eu.eudat.query.DmpQuery; @@ -157,6 +158,20 @@ public class DescriptionController { return persisted; } + @PostMapping("persist-status") + @Transactional + public Description persistStatus(@MyValidate @RequestBody DescriptionStatusPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); + Description persisted = this.descriptionService.persistStatus(model, fieldSet); + + this.auditService.track(AuditableAction.Description_PersistStatus, 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, IOException { diff --git a/dmp-backend/web/src/main/resources/config/errors.yml b/dmp-backend/web/src/main/resources/config/errors.yml index 4e7d42118..dc198536b 100644 --- a/dmp-backend/web/src/main/resources/config/errors.yml +++ b/dmp-backend/web/src/main/resources/config/errors.yml @@ -32,3 +32,6 @@ error-thesaurus: dmp-new-version-conflict: code: 115 message: version to update not the latest + dmp-is-finalized: + code: 116 + message: To perform this action you will need to revert DMP's finalisation