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 f4d1cebb3..f662b21a7 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 @@ -51,4 +51,9 @@ public class AuditableAction { public static final EventId DescriptionTemplate_GetXml = new EventId(8006, "DescriptionTemplate_GetXml"); public static final EventId DescriptionTemplate_Import = new EventId(8007, "DescriptionTemplate_Import"); + public static final EventId SupportiveMaterial_Query = new EventId(9000, "SupportiveMaterial_Query"); + public static final EventId SupportiveMaterial_Lookup = new EventId(9001, "SupportiveMaterial_Lookup"); + public static final EventId SupportiveMaterial_Persist = new EventId(9002, "SupportiveMaterial_Persist"); + public static final EventId SupportiveMaterial_Delete = new EventId(9003, "SupportiveMaterial_Delete"); + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java index c2b37d20d..53dc19998 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java @@ -86,5 +86,10 @@ public final class Permission { public static String EditDescriptionReference = "EditDescriptionReference"; public static String DeleteDescriptionReference = "DeleteDescriptionReference"; + //SupportiveMaterial + public static String BrowseSupportiveMaterial = "BrowseSupportiveMaterial"; + public static String EditSupportiveMaterial= "EditSupportiveMaterial"; + public static String DeleteSupportiveMaterial = "DeleteSupportiveMaterial"; + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java new file mode 100644 index 000000000..6131a7868 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/data/SupportiveMaterialEntity.java @@ -0,0 +1,102 @@ +package eu.eudat.data; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.SupportiveMaterialFieldType; +import eu.eudat.data.converters.enums.IsActiveConverter; +import eu.eudat.data.converters.enums.SupportiveMaterialFieldTypeConverter; +import jakarta.persistence.*; + +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "\"SupportiveMaterial\"") +public class SupportiveMaterialEntity { + + @Id + @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) + private UUID id; + public static final String _id = "id"; + + @Column(name = "type", nullable = false) + @Convert(converter = SupportiveMaterialFieldTypeConverter.class) + private SupportiveMaterialFieldType type; + public static final String _type = "type"; + + @Column(name = "language_code", length = 20, nullable = false) + private String languageCode; + public static final String _languageCode = "languageCode"; + + @Column(name = "payload", nullable = false) + private String payload; + public static final String _payload = "payload"; + + @Column(name = "\"created_at\"", nullable = false) + private Instant createdAt; + public static final String _createdAt = "createdAt"; + + @Column(name = "\"updated_at\"", nullable = false) + private Instant updatedAt; + public static final String _updatedAt = "updatedAt"; + + @Column(name = "is_active", nullable = false) + @Convert(converter = IsActiveConverter.class) + private IsActive isActive; + public static final String _isActive = "isActive"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public SupportiveMaterialFieldType getType() { + return type; + } + + public void setType(SupportiveMaterialFieldType type) { + this.type = type; + } + + public String getLanguageCode() { + return languageCode; + } + + public void setLanguageCode(String languageCode) { + this.languageCode = languageCode; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + + public Instant getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Instant updatedAt) { + this.updatedAt = updatedAt; + } + + public IsActive getIsActive() { + return isActive; + } + + public void setIsActive(IsActive isActive) { + this.isActive = isActive; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/converters/enums/SupportiveMaterialFieldTypeConverter.java b/dmp-backend/core/src/main/java/eu/eudat/data/converters/enums/SupportiveMaterialFieldTypeConverter.java new file mode 100644 index 000000000..b308b5ae8 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/data/converters/enums/SupportiveMaterialFieldTypeConverter.java @@ -0,0 +1,11 @@ +package eu.eudat.data.converters.enums; + +import eu.eudat.commons.enums.SupportiveMaterialFieldType; +import jakarta.persistence.Converter; + +@Converter +public class SupportiveMaterialFieldTypeConverter extends DatabaseEnumConverter { + public SupportiveMaterialFieldType of(Short i) { + return SupportiveMaterialFieldType.of(i); + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/SupportiveMaterial.java b/dmp-backend/core/src/main/java/eu/eudat/model/SupportiveMaterial.java new file mode 100644 index 000000000..ca552da3b --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/SupportiveMaterial.java @@ -0,0 +1,88 @@ +package eu.eudat.model; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.SupportiveMaterialFieldType; + +import java.time.Instant; +import java.util.UUID; + + +public class SupportiveMaterial { + + private UUID id; + public static final String _id = "id"; + + private SupportiveMaterialFieldType type; + public static final String _type = "type"; + + private String languageCode; + public static final String _languageCode = "languageCode"; + + private String payload; + public static final String _payload = "payload"; + + private Instant createdAt; + public static final String _createdAt = "createdAt"; + + private Instant updatedAt; + public static final String _updatedAt = "updatedAt"; + + private IsActive isActive; + public static final String _isActive = "isActive"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public SupportiveMaterialFieldType getType() { + return type; + } + + public void setType(SupportiveMaterialFieldType type) { + this.type = type; + } + + public String getLanguageCode() { + return languageCode; + } + + public void setLanguageCode(String languageCode) { + this.languageCode = languageCode; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + + public Instant getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Instant updatedAt) { + this.updatedAt = updatedAt; + } + + public IsActive getIsActive() { + return isActive; + } + + public void setIsActive(IsActive isActive) { + this.isActive = isActive; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/SupportiveMaterialBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/SupportiveMaterialBuilder.java new file mode 100644 index 000000000..c465cd702 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/SupportiveMaterialBuilder.java @@ -0,0 +1,74 @@ +package eu.eudat.model.builder; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.DmpReferenceEntity; +import eu.eudat.data.SupportiveMaterialEntity; +import eu.eudat.model.Dmp; +import eu.eudat.model.DmpReference; +import eu.eudat.model.Reference; +import eu.eudat.model.SupportiveMaterial; +import eu.eudat.query.DmpQuery; +import eu.eudat.query.ReferenceQuery; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class SupportiveMaterialBuilder extends BaseBuilder{ + + private final BuilderFactory builderFactory; + private final QueryFactory queryFactory; + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public SupportiveMaterialBuilder( + ConventionService conventionService, + BuilderFactory builderFactory, QueryFactory queryFactory) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(SupportiveMaterialBuilder.class))); + this.builderFactory = builderFactory; + this.queryFactory = queryFactory; + } + + public SupportiveMaterialBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List 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)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + List models = new ArrayList<>(); + for (SupportiveMaterialEntity d : data) { + SupportiveMaterial m = new SupportiveMaterial(); + if (fields.hasField(this.asIndexer(SupportiveMaterial._id))) m.setId(d.getId()); + if (fields.hasField(this.asIndexer(SupportiveMaterial._type))) m.setType(d.getType()); + if (fields.hasField(this.asIndexer(SupportiveMaterial._languageCode))) m.setLanguageCode(d.getLanguageCode()); + if (fields.hasField(this.asIndexer(SupportiveMaterial._payload))) m.setPayload(d.getPayload()); + if (fields.hasField(this.asIndexer(SupportiveMaterial._createdAt))) m.setCreatedAt(d.getCreatedAt()); + if (fields.hasField(this.asIndexer(SupportiveMaterial._updatedAt))) m.setUpdatedAt(d.getUpdatedAt()); + if (fields.hasField(this.asIndexer(SupportiveMaterial._isActive))) m.setIsActive(d.getIsActive()); + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/SupportiveMaterialCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/SupportiveMaterialCensor.java new file mode 100644 index 000000000..72d4dcefe --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/SupportiveMaterialCensor.java @@ -0,0 +1,44 @@ +package eu.eudat.model.censorship; + +import eu.eudat.authorization.Permission; +import eu.eudat.convention.ConventionService; +import eu.eudat.model.DmpBlueprint; +import eu.eudat.model.censorship.dmpblueprintdefinition.DefinitionCensor; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class SupportiveMaterialCensor extends BaseCensor { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(SupportiveMaterialCensor.class)); + + protected final AuthorizationService authService; + protected final CensorFactory censorFactory; + + public SupportiveMaterialCensor(ConventionService conventionService, + AuthorizationService authService, + CensorFactory censorFactory) { + super(conventionService); + this.authService = authService; + this.censorFactory = censorFactory; + } + + public void censor(FieldSet fields, UUID userId) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (fields == null || fields.isEmpty()) + return; + + this.authService.authorizeForce(Permission.BrowseDmpBlueprint); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java new file mode 100644 index 000000000..f5a548e64 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/SupportiveMaterialDeleter.java @@ -0,0 +1,79 @@ +package eu.eudat.model.deleter; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.data.SupportiveMaterialEntity; +import eu.eudat.query.SupportiveMaterialQuery; +import gr.cite.tools.data.deleter.Deleter; +import gr.cite.tools.data.deleter.DeleterFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import jakarta.persistence.EntityManager; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class SupportiveMaterialDeleter implements Deleter { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(SupportiveMaterialDeleter.class)); + + private final EntityManager entityManager; + + protected final QueryFactory queryFactory; + + protected final DeleterFactory deleterFactory; + + @Autowired + public SupportiveMaterialDeleter( + EntityManager entityManager, + QueryFactory queryFactory, + DeleterFactory deleterFactory + ) { + this.entityManager = entityManager; + this.queryFactory = queryFactory; + this.deleterFactory = deleterFactory; + } + + public void deleteAndSaveByIds(List ids) throws InvalidApplicationException { + logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids)); + List data = this.queryFactory.query(SupportiveMaterialQuery.class).ids(ids).collect(); + logger.trace("retrieved {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + this.deleteAndSave(data); + } + + public void deleteAndSave(List data) throws InvalidApplicationException { + logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + this.delete(data); + logger.trace("saving changes"); + this.entityManager.flush(); + logger.trace("changes saved"); + } + + public void delete(List data) throws InvalidApplicationException { + logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + if (data == null || data.isEmpty()) + return; + + Instant now = Instant.now(); + + for (SupportiveMaterialEntity item : data) { + logger.trace("deleting item {}", item.getId()); + item.setIsActive(IsActive.Inactive); + item.setUpdatedAt(now); + logger.trace("updating item"); + this.entityManager.merge(item); + logger.trace("updated item"); + } + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/SupportiveMaterialPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/SupportiveMaterialPersist.java index cd4d6b948..8c14508bc 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/SupportiveMaterialPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/SupportiveMaterialPersist.java @@ -2,28 +2,36 @@ package eu.eudat.model.persist; import eu.eudat.commons.enums.SupportiveMaterialFieldType; import eu.eudat.commons.validation.ValidEnum; +import eu.eudat.commons.validation.ValidId; +import eu.eudat.data.DmpBlueprintEntity; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; -public class SupportiveMaterialPersist { +import java.util.UUID; - @NotNull(message = "{validation.empty}") - @NotEmpty(message = "{validation.empty}") - private String name; +public class SupportiveMaterialPersist { + @ValidId(message = "{validation.invalidid}") + private UUID id; @ValidEnum(message = "{validation.empty}") private SupportiveMaterialFieldType type; @NotNull(message = "{validation.empty}") @NotEmpty(message = "{validation.empty}") - private String html; + @Size(max = 20, message = "{validation.largerthanmax}") + private String languageCode; - public String getName() { - return name; + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + private String payload; + + public UUID getId() { + return id; } - public void setName(String name) { - this.name = name; + public void setId(UUID id) { + this.id = id; } public SupportiveMaterialFieldType getType() { @@ -34,11 +42,19 @@ public class SupportiveMaterialPersist { this.type = type; } - public String getHtml() { - return html; + public String getLanguageCode() { + return languageCode; } - public void setHtml(String html) { - this.html = html; + public void setLanguageCode(String languageCode) { + this.languageCode = languageCode; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/SupportiveMaterialQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/SupportiveMaterialQuery.java new file mode 100644 index 000000000..e818f2fed --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/query/SupportiveMaterialQuery.java @@ -0,0 +1,219 @@ +package eu.eudat.query; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.SupportiveMaterialFieldType; +import eu.eudat.commons.scope.user.UserScope; +import eu.eudat.data.SupportiveMaterialEntity; +import eu.eudat.model.SupportiveMaterial; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.data.query.FieldResolver; +import gr.cite.tools.data.query.QueryBase; +import gr.cite.tools.data.query.QueryContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class SupportiveMaterialQuery extends QueryBase { + + private String like; + + private Collection ids; + + private Collection isActives; + + private Collection types; + + private Collection languageCodes; + + private Collection excludedIds; + + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + public SupportiveMaterialQuery like(String value) { + this.like = value; + return this; + } + + public SupportiveMaterialQuery ids(UUID value) { + this.ids = List.of(value); + return this; + } + + public SupportiveMaterialQuery ids(UUID... value) { + this.ids = Arrays.asList(value); + return this; + } + + public SupportiveMaterialQuery ids(Collection values) { + this.ids = values; + return this; + } + + public SupportiveMaterialQuery isActive(IsActive value) { + this.isActives = List.of(value); + return this; + } + + public SupportiveMaterialQuery isActive(IsActive... value) { + this.isActives = Arrays.asList(value); + return this; + } + + public SupportiveMaterialQuery isActive(Collection values) { + this.isActives = values; + return this; + } + + public SupportiveMaterialQuery types(SupportiveMaterialFieldType value) { + this.types = List.of(value); + return this; + } + + public SupportiveMaterialQuery types(SupportiveMaterialFieldType... value) { + this.types = Arrays.asList(value); + return this; + } + + public SupportiveMaterialQuery types(Collection values) { + this.types = values; + return this; + } + + public SupportiveMaterialQuery languageCodes(String value) { + this.languageCodes = List.of(value); + return this; + } + + public SupportiveMaterialQuery languageCodes(String... value) { + this.languageCodes = Arrays.asList(value); + return this; + } + + public SupportiveMaterialQuery languageCodes(Collection values) { + this.languageCodes = values; + return this; + } + + public SupportiveMaterialQuery excludedIds(Collection values) { + this.excludedIds = values; + return this; + } + + public SupportiveMaterialQuery excludedIds(UUID value) { + this.excludedIds = List.of(value); + return this; + } + + public SupportiveMaterialQuery excludedIds(UUID... value) { + this.excludedIds = Arrays.asList(value); + return this; + } + + public SupportiveMaterialQuery authorize(EnumSet values) { + this.authorize = values; + return this; + } + + private final UserScope userScope; + + private final AuthorizationService authService; + + public SupportiveMaterialQuery( + UserScope userScope, + AuthorizationService authService + ) { + this.userScope = userScope; + this.authService = authService; + } + + @Override + protected Class entityClass() { + return SupportiveMaterialEntity.class; + } + + @Override + protected Boolean isFalseQuery() { + return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.excludedIds) || this.isEmpty(this.types) || this.isEmpty(this.languageCodes); + } + + @Override + protected Predicate applyFilters(QueryContext queryContext) { + List predicates = new ArrayList<>(); + if (this.ids != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(SupportiveMaterialEntity._id)); + for (UUID item : this.ids) + inClause.value(item); + predicates.add(inClause); + } + if (this.like != null && !this.like.isEmpty()) { + predicates.add(queryContext.CriteriaBuilder.or(queryContext.CriteriaBuilder.like(queryContext.Root.get(SupportiveMaterialEntity._languageCode), this.like), + queryContext.CriteriaBuilder.like(queryContext.Root.get(SupportiveMaterialEntity._payload), this.like) + )); + } + if (this.isActives != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(SupportiveMaterialEntity._isActive)); + for (IsActive item : this.isActives) + inClause.value(item); + predicates.add(inClause); + } + + if (this.types != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(SupportiveMaterialEntity._type)); + for (SupportiveMaterialFieldType item : this.types) + inClause.value(item); + predicates.add(inClause); + } + if (this.languageCodes != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(SupportiveMaterialEntity._languageCode)); + for (String item : this.languageCodes) + inClause.value(item); + predicates.add(inClause); + } + if (this.excludedIds != null) { + CriteriaBuilder.In notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(SupportiveMaterialEntity._id)); + for (UUID item : this.excludedIds) + notInClause.value(item); + predicates.add(notInClause.not()); + } + if (!predicates.isEmpty()) { + Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); + return queryContext.CriteriaBuilder.and(predicatesArray); + } else { + return null; + } + } + + @Override + protected SupportiveMaterialEntity convert(Tuple tuple, Set columns) { + SupportiveMaterialEntity item = new SupportiveMaterialEntity(); + item.setId(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._id, UUID.class)); + item.setType(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._type, SupportiveMaterialFieldType.class)); + item.setLanguageCode(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._languageCode, String.class)); + item.setPayload(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._payload, String.class)); + item.setCreatedAt(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._createdAt, Instant.class)); + item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._updatedAt, Instant.class)); + item.setIsActive(QueryBase.convertSafe(tuple, columns, SupportiveMaterialEntity._isActive, IsActive.class)); + return item; + } + + @Override + protected String fieldNameOf(FieldResolver item) { + if (item.match(SupportiveMaterial._id)) return SupportiveMaterialEntity._id; + else if (item.match(SupportiveMaterial._type)) return SupportiveMaterialEntity._type; + else if (item.match(SupportiveMaterial._languageCode)) return SupportiveMaterialEntity._languageCode; + else if (item.match(SupportiveMaterial._createdAt)) return SupportiveMaterialEntity._createdAt; + else if (item.match(SupportiveMaterial._updatedAt)) return SupportiveMaterialEntity._updatedAt; + else if (item.match(SupportiveMaterial._isActive)) return SupportiveMaterialEntity._isActive; + else return null; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/lookup/SupportiveMaterialLookup.java b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/SupportiveMaterialLookup.java new file mode 100644 index 000000000..8e0160dc5 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/SupportiveMaterialLookup.java @@ -0,0 +1,89 @@ +package eu.eudat.query.lookup; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.SupportiveMaterialFieldType; +import eu.eudat.query.SupportiveMaterialQuery; +import gr.cite.tools.data.query.Lookup; +import gr.cite.tools.data.query.QueryFactory; + +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +public class SupportiveMaterialLookup extends Lookup { + + private String like; + + private List isActive; + + private Collection types; + + private List languageCodes; + + private List ids; + + private List excludedIds; + + public String getLike() { + return like; + } + + public void setLike(String like) { + this.like = like; + } + + public List getIsActive() { + return isActive; + } + + public void setIsActive(List isActive) { + this.isActive = isActive; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + public List getExcludedIds() { + return excludedIds; + } + + public void setExcludedIds(List excludeIds) { + this.excludedIds = excludeIds; + } + + public Collection getTypes() { + return types; + } + + public void setTypes(Collection types) { + this.types = types; + } + + public List getLanguageCodes() { + return languageCodes; + } + + public void setLanguageCodes(List languageCodes) { + this.languageCodes = languageCodes; + } + + public SupportiveMaterialQuery enrich(QueryFactory queryFactory) { + SupportiveMaterialQuery query = queryFactory.query(SupportiveMaterialQuery.class); + if (this.like != null) query.like(this.like); + if (this.isActive != null) query.isActive(this.isActive); + if (this.types != null) query.types(this.types); + if (this.languageCodes != null) query.languageCodes(this.languageCodes); + if (this.ids != null) query.ids(this.ids); + if (this.excludedIds != null) query.excludedIds(this.excludedIds); + + this.enrichCommon(query); + + return query; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java index 3a1bafc79..57396f1ae 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java @@ -1,70 +1,27 @@ package eu.eudat.service.supportivematerial; +import eu.eudat.model.SupportiveMaterial; import eu.eudat.model.persist.SupportiveMaterialPersist; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; +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 java.io.*; -import java.nio.file.Files; +import javax.management.InvalidApplicationException; +import java.io.IOException; import java.nio.file.Path; -import java.util.List; -import java.util.stream.Collectors; +import java.util.UUID; import java.util.stream.Stream; +import jakarta.xml.bind.JAXBException; +import org.springframework.http.ResponseEntity; -@Service -public class SupportiveMaterialService { +public interface SupportiveMaterialService { - private final SupportiveMaterialCacheService supportiveMaterialCacheService; + ResponseEntity getResponseEntity(String lang, Stream paths) throws IOException; - public SupportiveMaterialService( - SupportiveMaterialCacheService supportiveMaterialCacheService - ) { - this.supportiveMaterialCacheService = supportiveMaterialCacheService; - } + SupportiveMaterial persist(SupportiveMaterialPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException; - public ResponseEntity getResponseEntity(String lang, Stream paths) throws IOException { - List result = paths.filter(Files::isRegularFile) - .map(Path::toString).collect(Collectors.toList()); - - String fileName = result.stream().filter(about -> about.contains("_" + lang)).findFirst().orElse(null); - - if (fileName == null) { - fileName = result.stream().filter(about -> about.contains("_en")).findFirst().get(); - } - - SupportiveMaterialCacheService.SupportiveMaterialCacheValue supportiveMaterialCacheItem = this.supportiveMaterialCacheService.lookup(this.supportiveMaterialCacheService.buildKey(fileName)); - - if(supportiveMaterialCacheItem == null){ - InputStream is = new FileInputStream(fileName); - - // Path path = Paths.get(fileName); - - byte[] content = new byte[is.available()]; - is.read(content); - is.close(); - - supportiveMaterialCacheItem = new SupportiveMaterialCacheService.SupportiveMaterialCacheValue(fileName, content); - this.supportiveMaterialCacheService.put(supportiveMaterialCacheItem); - } - - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.setContentLength(supportiveMaterialCacheItem.getContent().length); - responseHeaders.setContentType(MediaType.TEXT_HTML); - responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName); - responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); - responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); - - return new ResponseEntity<>(supportiveMaterialCacheItem.getContent(), responseHeaders, HttpStatus.OK); - } - - public void persist(SupportiveMaterialPersist model) throws IOException { - this.supportiveMaterialCacheService.evict(model.getName()); - OutputStream os = new FileOutputStream(model.getName()); - os.write(model.getHtml().getBytes()); - os.close(); - } + void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialServiceImpl.java new file mode 100644 index 000000000..24aa4481c --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialServiceImpl.java @@ -0,0 +1,166 @@ +package eu.eudat.service.supportivematerial; + +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.authorization.Permission; +import eu.eudat.commons.enums.IsActive; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.SupportiveMaterialEntity; +import eu.eudat.model.SupportiveMaterial; +import eu.eudat.model.builder.SupportiveMaterialBuilder; +import eu.eudat.model.deleter.SupportiveMaterialDeleter; +import eu.eudat.model.persist.SupportiveMaterialPersist; +import eu.eudat.query.SupportiveMaterialQuery; +import eu.eudat.service.dmpblueprint.DmpBlueprintServiceImpl; +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 jakarta.xml.bind.JAXBException; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import javax.management.InvalidApplicationException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +@Service +public class SupportiveMaterialServiceImpl implements SupportiveMaterialService{ + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintServiceImpl.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 SupportiveMaterialCacheService supportiveMaterialCacheService; + + public SupportiveMaterialServiceImpl( + EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + ConventionService conventionService, MessageSource messageSource, QueryFactory queryFactory, + SupportiveMaterialCacheService supportiveMaterialCacheService + ) { + this.entityManager = entityManager; + this.authorizationService = authorizationService; + this.deleterFactory = deleterFactory; + this.builderFactory = builderFactory; + this.conventionService = conventionService; + this.messageSource = messageSource; + this.queryFactory = queryFactory; + this.supportiveMaterialCacheService = supportiveMaterialCacheService; + } + + public ResponseEntity getResponseEntity(String lang, Stream paths) throws IOException { + List result = paths.filter(Files::isRegularFile) + .map(Path::toString).collect(Collectors.toList()); + + String fileName = result.stream().filter(about -> about.contains("_" + lang)).findFirst().orElse(null); + + if (fileName == null) { + fileName = result.stream().filter(about -> about.contains("_en")).findFirst().get(); + } + + SupportiveMaterialCacheService.SupportiveMaterialCacheValue supportiveMaterialCacheItem = this.supportiveMaterialCacheService.lookup(this.supportiveMaterialCacheService.buildKey(fileName)); + + if(supportiveMaterialCacheItem == null){ + InputStream is = new FileInputStream(fileName); + + // Path path = Paths.get(fileName); + + byte[] content = new byte[is.available()]; + is.read(content); + is.close(); + + supportiveMaterialCacheItem = new SupportiveMaterialCacheService.SupportiveMaterialCacheValue(fileName, content); + this.supportiveMaterialCacheService.put(supportiveMaterialCacheItem); + } + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentLength(supportiveMaterialCacheItem.getContent().length); + responseHeaders.setContentType(MediaType.TEXT_HTML); + responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName); + responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); + responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); + + return new ResponseEntity<>(supportiveMaterialCacheItem.getContent(), responseHeaders, HttpStatus.OK); + } + +// public void persist(SupportiveMaterialPersist model) throws IOException { +// this.supportiveMaterialCacheService.evict(model.getName()); +// OutputStream os = new FileOutputStream(model.getName()); +// os.write(model.getHtml().getBytes()); +// os.close(); +// } + + public SupportiveMaterial persist(SupportiveMaterialPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException{ + logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeForce(Permission.EditSupportiveMaterial); + + Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); + + SupportiveMaterialEntity data; + if (isUpdate) { + data = this.entityManager.find(SupportiveMaterialEntity.class, model.getId()); + if (data == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), SupportiveMaterial.class.getSimpleName()}, LocaleContextHolder.getLocale())); + } else { + List datas = this.queryFactory.query(SupportiveMaterialQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).languageCodes(model.getLanguageCode()).types(model.getType()).collect(); + + if(datas != null){ + throw new MyApplicationException("Could not create a new Data with same type and lang code !"); + } + + data = new SupportiveMaterialEntity(); + data.setId(UUID.randomUUID()); + data.setIsActive(IsActive.Active); + data.setCreatedAt(Instant.now()); + } + + data.setType(model.getType()); + data.setLanguageCode(model.getLanguageCode()); + data.setPayload(model.getPayload()); + data.setUpdatedAt(Instant.now()); + + if (isUpdate) this.entityManager.merge(data); + else this.entityManager.persist(data); + + this.entityManager.flush(); + + return this.builderFactory.builder(SupportiveMaterialBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(BaseFieldSet.build(fields, SupportiveMaterial._id), data); + } + + public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug("deleting : {}", id); + + this.authorizationService.authorizeForce(Permission.DeleteSupportiveMaterial); + + this.deleterFactory.deleter(SupportiveMaterialDeleter.class).deleteAndSaveByIds(List.of(id)); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java index f2d323e53..21fa1d814 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DmpController.java @@ -1,5 +1,6 @@ package eu.eudat.controllers.v2; +import com.fasterxml.jackson.core.JsonProcessingException; import eu.eudat.audit.AuditableAction; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.data.DmpEntity; @@ -102,7 +103,7 @@ public class DmpController { @PostMapping("persist") @Transactional - public Dmp Persist(@MyValidate @RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException { + public Dmp Persist(@MyValidate @RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JsonProcessingException { logger.debug(new MapLogEntry("persisting" + Dmp.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); Dmp persisted = this.dmpService.persist(model, fieldSet); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java index c8c992066..564a18b0f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java @@ -1,44 +1,118 @@ package eu.eudat.controllers.v2; -import eu.eudat.authorization.Permission; +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.eudat.audit.AuditableAction; +import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.commons.enums.SupportiveMaterialFieldType; -import eu.eudat.logic.managers.MetricsManager; +import eu.eudat.data.SupportiveMaterialEntity; +import eu.eudat.model.SupportiveMaterial; +import eu.eudat.model.builder.SupportiveMaterialBuilder; +import eu.eudat.model.censorship.SupportiveMaterialCensor; import eu.eudat.model.persist.SupportiveMaterialPersist; -import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.model.result.QueryResult; +import eu.eudat.query.SupportiveMaterialQuery; +import eu.eudat.query.lookup.SupportiveMaterialLookup; import eu.eudat.service.supportivematerial.SupportiveMaterialService; -import eu.eudat.types.ApiMessageCode; +import eu.eudat.service.supportivematerial.SupportiveMaterialServiceImpl; import gr.cite.commons.web.authz.service.AuthorizationService; +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 gr.cite.tools.validation.MyValidate; +import jakarta.transaction.Transactional; +import jakarta.xml.bind.JAXBException; import org.apache.commons.lang3.EnumUtils; +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.core.env.Environment; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import javax.management.InvalidApplicationException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Locale; -import java.util.Objects; +import java.util.*; import java.util.stream.Stream; @RestController -@RequestMapping(path = {"/api/material"}) +@RequestMapping(path = {"/api/supportive-material"}) public class SupportiveMaterialController { + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(SupportiveMaterialController.class)); private Environment environment; - private SupportiveMaterialService supportiveMaterialService; + private final BuilderFactory builderFactory; + private final AuditService auditService; + + private final CensorFactory censorFactory; + private final QueryFactory queryFactory; + private final MessageSource messageSource; + private final SupportiveMaterialService supportiveMaterialService; private final AuthorizationService authorizationService; @Autowired - public SupportiveMaterialController(Environment environment, SupportiveMaterialService supportiveMaterialService, MetricsManager metricsManager, AuthorizationService authorizationService) { + public SupportiveMaterialController(Environment environment, SupportiveMaterialService supportiveMaterialService, BuilderFactory builderFactory, + AuditService auditService, CensorFactory censorFactory, QueryFactory queryFactory, MessageSource messageSource, + AuthorizationService authorizationService) { this.environment = environment; this.supportiveMaterialService = supportiveMaterialService; + this.builderFactory = builderFactory; + this.auditService = auditService; + this.censorFactory = censorFactory; + this.queryFactory = queryFactory; + this.messageSource = messageSource; this.authorizationService = authorizationService; } - @GetMapping("{lang}") + @PostMapping("query") + public QueryResult query(@RequestBody SupportiveMaterialLookup lookup) throws MyApplicationException, MyForbiddenException { + logger.debug("querying {}", SupportiveMaterial.class.getSimpleName()); + + this.censorFactory.censor(SupportiveMaterialCensor.class).censor(lookup.getProject(), null); + + SupportiveMaterialQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermission); + List datas = query.collectAs(lookup.getProject()); + List models = this.builderFactory.builder(SupportiveMaterialBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(lookup.getProject(), datas); + long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); + + this.auditService.track(AuditableAction.SupportiveMaterial_Query, "lookup", lookup); + + return new QueryResult(models, count); + } + + @GetMapping("{id}") + public SupportiveMaterial get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("retrieving " + SupportiveMaterial.class.getSimpleName()).And("id", id).And("fields", fieldSet)); + + this.censorFactory.censor(SupportiveMaterialCensor.class).censor(fieldSet, null); + + SupportiveMaterialQuery query = this.queryFactory.query(SupportiveMaterialQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).ids(id); + SupportiveMaterial model = this.builderFactory.builder(SupportiveMaterialBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet)); + if (model == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, SupportiveMaterial.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.SupportiveMaterial_Lookup, Map.ofEntries( + new AbstractMap.SimpleEntry("id", id), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return model; + } + + @GetMapping("get/{lang}") public ResponseEntity getMaterial(@PathVariable(name = "lang") String lang, int field) throws IOException { if( !EnumUtils.isValidEnum(SupportiveMaterialFieldType.class, SupportiveMaterialFieldType.of((short) field).name())){ return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -49,14 +123,39 @@ public class SupportiveMaterialController { } } - @PostMapping("persist") - public @ResponseBody - ResponseEntity> persist(@RequestBody SupportiveMaterialPersist model) throws IOException { - this.authorizationService.authorizeForce(Permission.AdminRole); +// @PostMapping("persist") +// public @ResponseBody +// ResponseEntity> persist(@RequestBody SupportiveMaterialPersist model) throws IOException { +// this.authorizationService.authorizeForce(Permission.AdminRole); +// +// //String fileName = this.environment.getProperty(model.getName()+ ".path"); +// this.supportiveMaterialService.persist(model); +// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); +// } - //String fileName = this.environment.getProperty(model.getName()+ ".path"); - this.supportiveMaterialService.persist(model); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); + @PostMapping("persist") + @Transactional + public SupportiveMaterial persist(@MyValidate @RequestBody SupportiveMaterialPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException { + logger.debug(new MapLogEntry("persisting" + SupportiveMaterial.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); + this.censorFactory.censor(SupportiveMaterialCensor.class).censor(fieldSet, null); + + SupportiveMaterial persisted = this.supportiveMaterialService.persist(model, fieldSet); + + this.auditService.track(AuditableAction.SupportiveMaterial_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" + SupportiveMaterial.class.getSimpleName()).And("id", id)); + + this.supportiveMaterialService.deleteAndSave(id); + + this.auditService.track(AuditableAction.SupportiveMaterial_Delete, "id", id); } diff --git a/dmp-frontend/src/app/core/model/supportive-material/supportive-material.ts b/dmp-frontend/src/app/core/model/supportive-material/supportive-material.ts index e3501146f..8af5d0892 100644 --- a/dmp-frontend/src/app/core/model/supportive-material/supportive-material.ts +++ b/dmp-frontend/src/app/core/model/supportive-material/supportive-material.ts @@ -1,7 +1,21 @@ +import { IsActive } from "@app/core/common/enum/is-active.enum"; import { SupportiveMaterialFieldType } from "@app/core/common/enum/supportive-material-field-type"; +import { Guid } from "@common/types/guid"; + +export interface SupportiveMaterial{ + id: Guid; + type: SupportiveMaterialFieldType; + languageCode: string; + payload: string; + createdAt: Date; + updatedAt: Date; + isActive: IsActive; +} + export interface SupportiveMaterialPersist{ - name: string; + id: Guid; type: SupportiveMaterialFieldType; - html: string; + languageCode: string; + payload: string; } \ No newline at end of file diff --git a/dmp-frontend/src/app/core/query/supportive-material.lookup.ts b/dmp-frontend/src/app/core/query/supportive-material.lookup.ts new file mode 100644 index 000000000..43537e1a4 --- /dev/null +++ b/dmp-frontend/src/app/core/query/supportive-material.lookup.ts @@ -0,0 +1,26 @@ +import { Lookup } from '@common/model/lookup'; +import { Guid } from '@common/types/guid'; +import { IsActive } from '../common/enum/is-active.enum'; +import { SupportiveMaterialFieldType } from '../common/enum/supportive-material-field-type'; + +export class SupportiveMaterialLookup extends Lookup implements SupportiveMaterialFilter { + ids: Guid[]; + excludedIds: Guid[]; + like: string; + isActive: IsActive[]; + types: SupportiveMaterialFieldType[]; + languageCodes: string[]; + + constructor() { + super(); + } +} + +export interface SupportiveMaterialFilter { + ids: Guid[]; + excludedIds: Guid[]; + like: string; + isActive: IsActive[]; + types: SupportiveMaterialFieldType[]; + languageCodes: string[]; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts b/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts index 9defff094..454b20514 100644 --- a/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts +++ b/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts @@ -1,10 +1,15 @@ import { Injectable } from "@angular/core"; import { ConfigurationService } from "../configuration/configuration.service"; import { HttpClient, HttpResponse } from "@angular/common/http"; -import { Observable } from "rxjs"; -import { SupportiveMaterialFieldType } from "@app/core/common/enum/supportive-material-field-type"; -import { SupportiveMaterialPersist } from "@app/core/model/supportive-material/supportive-material"; +import { Observable, throwError } from "rxjs"; +import { SupportiveMaterial, SupportiveMaterialPersist } from "@app/core/model/supportive-material/supportive-material"; import { BaseHttpV2Service } from "../http/base-http-v2.service"; +import { SupportiveMaterialLookup } from "@app/core/query/supportive-material.lookup"; +import { QueryResult } from "@common/model/query-result"; +import { catchError } from "rxjs/operators"; +import { Guid } from "@common/types/guid"; +import { nameof } from "ts-simple-nameof"; +import { IsActive } from "@app/core/common/enum/is-active.enum"; @Injectable() export class SupportiveMaterialService{ @@ -15,13 +20,67 @@ export class SupportiveMaterialService{ ) { } - private get apiBase(): string { return `${this.configurationService.server}material`; } + private get apiBase(): string { return `${this.configurationService.server}supportive-material`; } public getMaterial(lang: string, field: number): Observable> { - return this.http.get(`${this.apiBase}/${lang}`, {params: {field}, responseType: 'blob', observe: 'response' }); + return this.http.get(`${this.apiBase}/get/${lang}`, {params: {field}, responseType: 'blob', observe: 'response' }); } - public persist(item :SupportiveMaterialPersist): Observable { - return this.http.post(`${this.apiBase}/persist`, item); + // public persist(item :SupportiveMaterialPersist): Observable { + // return this.http.post(`${this.apiBase}/persist`, item); + // } + + query(q: SupportiveMaterialLookup): Observable> { + const url = `${this.apiBase}/query`; + return this.http.post>(url, q).pipe(catchError((error: any) => throwError(error))); } + + getSingle(id: Guid, reqFields: string[] = []): Observable { + const url = `${this.apiBase}/${id}`; + const options = { params: { f: reqFields } }; + + return this.http + .get(url, options).pipe( + catchError((error: any) => throwError(error))); + } + + persist(item: SupportiveMaterialPersist): Observable { + const url = `${this.apiBase}/persist`; + + return this.http + .post(url, item).pipe( + catchError((error: any) => throwError(error))); + } + + delete(id: Guid): Observable { + const url = `${this.apiBase}/${id}`; + + return this.http + .delete(url).pipe( + catchError((error: any) => throwError(error))); + } + + + // LOOKUP + + public static DefaultSupportiveMaterialLookup(params?: {}): SupportiveMaterialLookup{ + const lookup = new SupportiveMaterialLookup(); + + lookup.project = { + fields: [ + nameof(x => x.id), + nameof(x => x.type), + nameof(x => x.languageCode), + nameof(x => x.payload), + nameof(x => x.createdAt), + nameof(x => x.updatedAt), + nameof(x => x.isActive) + ] + }; + lookup.order = { items: [nameof(x => x.type)] }; + lookup.page = { offset: 0, size: 10 }; + lookup.isActive = [IsActive.Active]; + return lookup; + } + } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.ts b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.ts index 8c4901bdb..808a9dfc9 100644 --- a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.ts +++ b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.ts @@ -132,15 +132,20 @@ export class SupportiveMaterialEditorComponent extends BaseComponent implements let result = this.parseText(this.formGroup.get('html').value); //result = result.replace(/href="#/g, 'class="href" path="'); this.formGroup.get('html').patchValue(result); - const item = {name: this.formGroup.value['name'], type: this.selectedMaterial.type ,html: this.formGroup.value['html']} as SupportiveMaterialPersist - if(item.name.endsWith("_en.html") && this.selectedLang.type != "en" ){ - item.name = item.name.replace("_en.html", `_${this.selectedLang.type}.html`); - } + //const item = {name: this.formGroup.value['name'], type: this.selectedMaterial.type ,html: this.formGroup.value['html']} as SupportiveMaterialPersist + const item = {id: null, + type: this.selectedMaterial.type, + languageCode: this.selectedLang.type, + payload: this.formGroup.value['html']} as SupportiveMaterialPersist; + + // if(item.name.endsWith("_en.html") && this.selectedLang.type != "en" ){ + // item.name = item.name.replace("_en.html", `_${this.selectedLang.type}.html`); + // } this.supportiveMaterialService.persist(item).pipe(takeUntil(this._destroyed)) .subscribe( complete => { - this.onCallbackSuccess(complete); + this.onCallbackSuccess(); }, error => { this.onCallbackError(error); @@ -149,9 +154,9 @@ export class SupportiveMaterialEditorComponent extends BaseComponent implements } -onCallbackSuccess(id?: String): void { +onCallbackSuccess(): void { this.uiNotificationService.snackBarNotification( this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); - this.router.navigate(['/reload']).then(() => this.router.navigate(['/user-guide-editor'])); + this.router.navigate(['/reload']).then(() => this.router.navigate(['/supportive-material'])); } onCallbackError(error: any) {