From c480e8e508af1303331b17ba41a2bc5d8d6aeede Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Tue, 19 Mar 2024 17:21:50 +0200 Subject: [PATCH] authz changes --- .../java/eu/eudat/audit/AuditableAction.java | 3 +- .../eu/eudat/authorization/Permission.java | 1 - .../AuthorizationContentResolver.java | 4 + .../AuthorizationContentResolverImpl.java | 51 ++++++++++- .../censorship/DmpAssociatedUserCensor.java | 2 +- .../model/dmpblueprintdefinition/Section.java | 12 +++ .../DescriptionSectionPermissionResolver.java | 89 +++++++++++++++++++ .../eu/eudat/model/persist/LockPersist.java | 1 + .../query/DescriptionReferenceQuery.java | 10 +-- .../eu/eudat/query/DescriptionTagQuery.java | 31 ------- .../java/eu/eudat/query/DmpUserQuery.java | 10 +++ .../main/java/eu/eudat/query/UserQuery.java | 2 +- .../query/utils/QueryUtilsServiceImpl.java | 8 +- .../description/DescriptionService.java | 6 +- .../description/DescriptionServiceImpl.java | 34 +++++-- .../java/eu/eudat/service/dmp/DmpService.java | 2 +- .../eu/eudat/service/dmp/DmpServiceImpl.java | 6 +- .../eudat/service/lock/LockServiceImpl.java | 9 +- .../controllers/DescriptionController.java | 14 +++ .../eu/eudat/controllers/DmpController.java | 2 +- .../eu/eudat/controllers/LockController.java | 8 +- .../src/main/resources/config/permissions.yml | 60 ++----------- .../app/core/common/enum/permission.enum.ts | 1 - .../app/core/model/description/description.ts | 5 ++ .../description/description.service.ts | 7 +- .../editor/description-editor.component.ts | 33 ++++--- .../editor/description-editor.routing.ts | 9 +- .../dmp-editor.component.html | 4 +- .../dmp-editor.component.ts | 38 +++++++- .../dmp-editor.resolver.ts | 1 + 30 files changed, 322 insertions(+), 141 deletions(-) create mode 100644 dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionSectionPermissionResolver.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 ec12294f8..8f02ec600 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 @@ -56,7 +56,8 @@ public class AuditableAction { public static final EventId Description_UploadFieldFiles = new EventId(6007, "Description_UploadFieldFiles"); public static final EventId Description_GetFieldFile = new EventId(6008, "Description_GetFieldFile"); public static final EventId Description_Validate = new EventId(6009, "Description_Validate"); - + public static final EventId Description_GetDescriptionSectionPermissions = new EventId(6010, "Description_GetDescriptionSectionPermissions"); + 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/authorization/Permission.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java index 12ff43b0a..df7fa3a08 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 @@ -74,7 +74,6 @@ public final class Permission { public static String DeleteDmp = "DeleteDmp"; public static String CloneDmp = "CloneDmp"; public static String CreateNewVersionDmp = "CreateNewVersionDmp"; - public static String ExportDmp = "ExportDmp"; public static String FinalizeDmp = "FinalizeDmp"; public static String UndoFinalizeDmp = "UndoFinalizeDmp"; public static String AssignDmpUsers = "AssignDmpUsers"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolver.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolver.java index 345829a3f..8cfa3f1f2 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolver.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolver.java @@ -16,4 +16,8 @@ public interface AuthorizationContentResolver { AffiliatedResource descriptionAffiliation(UUID id); Map descriptionsAffiliation(List ids); + + AffiliatedResource descriptionsAffiliationBySection(UUID dmpId, UUID sectionId); + + Map descriptionsAffiliationBySections(UUID dmpId, List sectionIds); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolverImpl.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolverImpl.java index 2fda5280c..85bf84759 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolverImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/authorizationcontentresolver/AuthorizationContentResolverImpl.java @@ -5,11 +5,14 @@ import eu.eudat.authorization.PermissionNameProvider; import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.scope.user.UserScope; import eu.eudat.data.DescriptionEntity; +import eu.eudat.data.DmpDescriptionTemplateEntity; import eu.eudat.data.DmpEntity; import eu.eudat.data.DmpUserEntity; import eu.eudat.model.Description; +import eu.eudat.model.DmpDescriptionTemplate; import eu.eudat.model.DmpUser; import eu.eudat.query.DescriptionQuery; +import eu.eudat.query.DmpDescriptionTemplateQuery; import eu.eudat.query.DmpUserQuery; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.fieldset.BaseFieldSet; @@ -54,7 +57,7 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes List idsToResolve = this.getAffiliatedFromCache(ids, userId, affiliatedResources, DmpEntity.class.getSimpleName()); if (idsToResolve.isEmpty()) return affiliatedResources; - List dmpUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(ids).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._dmp)); + List dmpUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(ids).sectionIsEmpty(true).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._dmp)); for (DmpUserEntity dmpUser : dmpUsers){ affiliatedResources.get(dmpUser.getDmpId()).getDmpUserRoles().add(dmpUser.getRole()); @@ -80,14 +83,23 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes List idsToResolve = this.getAffiliatedFromCache(ids, userId, affiliatedResources, DescriptionEntity.class.getSimpleName()); if (idsToResolve.isEmpty()) return affiliatedResources; - List descriptionEntities = this.queryFactory.query(DescriptionQuery.class).ids(ids).collectAs(new BaseFieldSet().ensure(Description._id).ensure(Description._dmp)); - List dmpUsers = this.queryFactory.query(DmpUserQuery.class).descriptionIds(ids).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._dmp)); + List descriptionEntities = this.queryFactory.query(DescriptionQuery.class).ids(ids).collectAs(new BaseFieldSet().ensure(Description._id).ensure(Description._dmpDescriptionTemplate).ensure(Description._dmp)); + List dmpDescriptionTemplateEntities = this.queryFactory.query(DmpDescriptionTemplateQuery.class).ids(descriptionEntities.stream().map(DescriptionEntity::getDmpDescriptionTemplateId).distinct().toList()).collectAs(new BaseFieldSet().ensure(DmpDescriptionTemplate._id).ensure(DmpDescriptionTemplate._sectionId)); + Map dmpDescriptionTemplateEntityMap = dmpDescriptionTemplateEntities == null ? new HashMap<>() : dmpDescriptionTemplateEntities.stream().collect(Collectors.toMap(DmpDescriptionTemplateEntity::getId, x-> x)); + + List dmpUsers = this.queryFactory.query(DmpUserQuery.class).descriptionIds(ids).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._sectionId).ensure(DmpUser._dmp)); Map> dmpUsersMap = dmpUsers.stream().collect(Collectors.groupingBy(DmpUserEntity::getDmpId)); for (DescriptionEntity description : descriptionEntities){ List dmpDescriptionUsers = dmpUsersMap.getOrDefault(description.getDmpId(), new ArrayList<>()); for (DmpUserEntity dmpUser : dmpDescriptionUsers) { - affiliatedResources.get(description.getId()).getDmpUserRoles().add(dmpUser.getRole()); + if (dmpUser.getSectionId() == null) affiliatedResources.get(description.getId()).getDmpUserRoles().add(dmpUser.getRole()); + else { + DmpDescriptionTemplateEntity dmpDescriptionTemplateEntity = dmpDescriptionTemplateEntityMap.getOrDefault(description.getDmpDescriptionTemplateId(), null); + if (dmpDescriptionTemplateEntity != null && dmpUser.getSectionId().equals(dmpDescriptionTemplateEntity.getSectionId())){ + affiliatedResources.get(description.getId()).getDmpUserRoles().add(dmpUser.getRole()); + } + } } } @@ -95,6 +107,37 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes return affiliatedResources; } + @Override + public AffiliatedResource descriptionsAffiliationBySection(UUID dmpId, UUID sectionId){ + return this.descriptionsAffiliationBySections(dmpId, List.of(sectionId)).getOrDefault(sectionId, new AffiliatedResource()); + } + + @Override + public Map descriptionsAffiliationBySections(UUID dmpId, List sectionIds){ + UUID userId = this.userScope.getUserIdSafe(); + Map affiliatedResources = new HashMap<>(); + for (UUID id : sectionIds){ + affiliatedResources.put(id, new AffiliatedResource()); + } + if (userId == null || !userScope.isSet()) return affiliatedResources; + + List dmpUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(dmpId).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._sectionId).ensure(DmpUser._dmp)); + + for (UUID sectionId : sectionIds.stream().distinct().toList()){ + List dmpSectionUsers = dmpUsers.stream().filter(x-> x.getSectionId() == null || x.getSectionId().equals(sectionId)).toList(); + for (DmpUserEntity dmpUser : dmpSectionUsers) { + if (dmpUser.getSectionId() == null) affiliatedResources.get(sectionId).getDmpUserRoles().add(dmpUser.getRole()); + else { + if (dmpUser.getSectionId().equals(sectionId)){ + affiliatedResources.get(sectionId).getDmpUserRoles().add(dmpUser.getRole()); + } + } + } + } + + return affiliatedResources; + } + private List getAffiliatedFromCache(List ids, UUID userId, Map affiliatedResources, String entityType){ List idsToResolve = new ArrayList<>(); for (UUID id : ids){ diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpAssociatedUserCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpAssociatedUserCensor.java index 3305fccb7..3a83988c3 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpAssociatedUserCensor.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DmpAssociatedUserCensor.java @@ -33,7 +33,7 @@ public class DmpAssociatedUserCensor extends BaseCensor { logger.debug(new DataLogEntry("censoring fields", fields)); if (fields == null || fields.isEmpty()) return; - this.authService.authorizeAtLeastOneForce(userId != null ? List.of(new OwnedResource(userId)) : null, Permission.BrowseDmpAssociatedUser); + this.authService.authorizeAtLeastOneForce(userId != null ? List.of(new OwnedResource(userId)) : null, Permission.BrowseDmpAssociatedUser, Permission.DeferredAffiliation); } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/dmpblueprintdefinition/Section.java b/dmp-backend/core/src/main/java/eu/eudat/model/dmpblueprintdefinition/Section.java index 65b64acdf..c7e426d12 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/dmpblueprintdefinition/Section.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/dmpblueprintdefinition/Section.java @@ -32,6 +32,10 @@ public class Section { public final static String _prefillingSources = "prefillingSources"; private List prefillingSources; + public final static String _canCreate = "canCreate"; + private Boolean canCreate; + + public UUID getId() { return id; } @@ -95,6 +99,14 @@ public class Section { public void setPrefillingSources(List prefillingSources) { this.prefillingSources = prefillingSources; } + + public Boolean getCanCreate() { + return canCreate; + } + + public void setCanCreate(Boolean canCreate) { + this.canCreate = canCreate; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionSectionPermissionResolver.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionSectionPermissionResolver.java new file mode 100644 index 000000000..e326cd2de --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DescriptionSectionPermissionResolver.java @@ -0,0 +1,89 @@ +package eu.eudat.model.persist; + +import eu.eudat.commons.validation.BaseValidator; +import eu.eudat.convention.ConventionService; +import eu.eudat.errorcode.ErrorThesaurusProperties; +import gr.cite.tools.validation.specification.Specification; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class DescriptionSectionPermissionResolver { + + private UUID dmpId; + public static final String _dmpId = "dmpId"; + + private List sectionIds; + + public static final String _sectionIds = "sectionIds"; + + private List permissions; + + public static final String _permissions = "permissions"; + + public UUID getDmpId() { + return dmpId; + } + + public void setDmpId(UUID dmpId) { + this.dmpId = dmpId; + } + + public List getSectionIds() { + return sectionIds; + } + + public void setSectionIds(List sectionIds) { + this.sectionIds = sectionIds; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } + + @Component(DescriptionSectionPermissionResolverPersistValidator.ValidatorName) + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class DescriptionSectionPermissionResolverPersistValidator extends BaseValidator { + + public static final String ValidatorName = "DescriptionSectionPermissionResolverPersistValidator"; + + private final MessageSource messageSource; + + protected DescriptionSectionPermissionResolverPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) { + super(conventionService, errors); + this.messageSource = messageSource; + } + + @Override + protected Class modelClass() { + return DescriptionSectionPermissionResolver.class; + } + + @Override + protected List specifications(DescriptionSectionPermissionResolver item) { + return Arrays.asList( + this.spec() + .must(() -> this.isValidGuid(item.getDmpId())) + .failOn(DescriptionSectionPermissionResolver._dmpId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionSectionPermissionResolver._dmpId}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> item.getPermissions() != null && !item.getPermissions().isEmpty()) + .failOn(DescriptionSectionPermissionResolver._permissions).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionSectionPermissionResolver._permissions}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> item.getSectionIds() != null && !item.getSectionIds().isEmpty()) + .failOn(DescriptionSectionPermissionResolver._sectionIds).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionSectionPermissionResolver._sectionIds}, LocaleContextHolder.getLocale())) + + ); + } + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/LockPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/LockPersist.java index 8d83705f7..2326a3c0b 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/LockPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/LockPersist.java @@ -118,3 +118,4 @@ public class LockPersist { } } + diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionReferenceQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionReferenceQuery.java index 3d4f7d49a..96be0d389 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionReferenceQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionReferenceQuery.java @@ -158,15 +158,7 @@ public class DescriptionReferenceQuery extends QueryBase predicates = new ArrayList<>(); if (userId != null || usePublic ) { - UUID finalUserId = userId; - Subquery descriptionSubquery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>( - new BuildSubQueryInput.Builder<>(DescriptionEntity.class, UUID.class, queryContext) - .keyPathFunc((subQueryRoot) -> subQueryRoot.get(DescriptionEntity._id)) - .filterFunc((subQueryRoot, cb) -> - cb.in(subQueryRoot.get(DescriptionEntity._dmpDescriptionTemplateId)).value(queryUtilsService.buildDmpAuthZSubQuery(queryContext.Query, queryContext.CriteriaBuilder, finalUserId, usePublic)) - ) - )); - predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionReferenceEntity._descriptionId)).value(descriptionSubquery)); + predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionReferenceEntity._descriptionId)).value(queryUtilsService.buildDescriptionAuthZSubQuery(queryContext.Query, queryContext.CriteriaBuilder, userId, usePublic))); } if (!predicates.isEmpty()) { Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTagQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTagQuery.java index 55f31cbf2..3c0fba6c4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTagQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTagQuery.java @@ -144,37 +144,6 @@ public class DescriptionTagQuery extends QueryBase { } - @Override - protected Predicate applyAuthZ(QueryContext queryContext) { - if (this.authorize.contains(AuthorizationFlags.None)) return null; - if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseDescriptionTag)) return null; - UUID userId; - boolean usePublic = this.authorize.contains(AuthorizationFlags.Public); - if (this.authorize.contains(AuthorizationFlags.DmpAssociated)) userId = this.userScope.getUserIdSafe(); - else userId = null; - if (this.authorize.contains(AuthorizationFlags.Owner)) userId = this.userScope.getUserIdSafe(); - - List predicates = new ArrayList<>(); - if (userId != null || usePublic ) { - UUID finalUserId = userId; - Subquery descriptionSubquery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>( - new BuildSubQueryInput.Builder<>(DescriptionEntity.class, UUID.class, queryContext) - .keyPathFunc((subQueryRoot) -> subQueryRoot.get(DescriptionEntity._id)) - .filterFunc((subQueryRoot, cb) -> - cb.in(subQueryRoot.get(DescriptionEntity._dmpDescriptionTemplateId)).value(queryUtilsService.buildDmpAuthZSubQuery(queryContext.Query, queryContext.CriteriaBuilder, finalUserId, usePublic)) - ) - )); - predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionTagEntity._descriptionId)).value(descriptionSubquery)); - } - if (predicates.size() > 0) { - Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); - return queryContext.CriteriaBuilder.and(predicatesArray); - } else { - return queryContext.CriteriaBuilder.or(); //Creates a false query - } - } - - @Override protected Predicate applyFilters(QueryContext queryContext) { List predicates = new ArrayList<>(); diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/DmpUserQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/DmpUserQuery.java index 4a76d6092..14a7eddd9 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/DmpUserQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/DmpUserQuery.java @@ -42,6 +42,7 @@ public class DmpUserQuery extends QueryBase { private Collection userRoles; private Collection sectionIds; + private Boolean sectionIsEmpty; private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); @@ -149,6 +150,11 @@ public class DmpUserQuery extends QueryBase { this.sectionIds = values; return this; } + + public DmpUserQuery sectionIsEmpty(Boolean sectionIsEmpty) { + this.sectionIsEmpty = sectionIsEmpty; + return this; + } public DmpUserQuery authorize(EnumSet values) { this.authorize = values; @@ -224,6 +230,10 @@ public class DmpUserQuery extends QueryBase { inClause.value(item); predicates.add(inClause); } + if (this.sectionIsEmpty != null){ + if(this.sectionIsEmpty) predicates.add(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(DmpUserEntity._sectionId))); + else predicates.add(queryContext.CriteriaBuilder.isNotNull(queryContext.Root.get(DmpUserEntity._sectionId))); + } if (this.descriptionIds != null) { Subquery descriptionSubquery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>( new BuildSubQueryInput.Builder<>(DescriptionEntity.class, UUID.class, queryContext) diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/UserQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/UserQuery.java index 6f73c6b15..312fce85c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/UserQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/UserQuery.java @@ -159,7 +159,7 @@ public class UserQuery extends QueryBase { UUID finalUserId = userId; predicates.add(queryContext.CriteriaBuilder.or( userId != null ? queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(userId) : queryContext.CriteriaBuilder.or(), //Creates a false query - queryContext.CriteriaBuilder.in(queryContext.Root.get(ReferenceEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(DmpUserEntity.class, UUID.class) + queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(DmpUserEntity.class, UUID.class) .query(queryContext.Query) .criteriaBuilder(queryContext.CriteriaBuilder) .keyPathFunc((subQueryRoot) -> subQueryRoot.get(DmpUserEntity._userId)) diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/utils/QueryUtilsServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/query/utils/QueryUtilsServiceImpl.java index 9f787cde8..50d0a6165 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/utils/QueryUtilsServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/utils/QueryUtilsServiceImpl.java @@ -53,9 +53,13 @@ public class QueryUtilsServiceImpl implements QueryUtilsService { usePublic ? cb.and( cb.equal(subQueryRoot.get(DescriptionEntity._status), DescriptionStatus.Finalized), cb.equal(subQueryRoot.get(DescriptionEntity._isActive), IsActive.Active), - cb.in(subQueryRoot.get(DescriptionEntity._dmpId)).value(this.buildDmpAuthZSubQuery(query, criteriaBuilder, userId, usePublic)) + cb.in(subQueryRoot.get(DescriptionEntity._dmpId)).value(this.buildPublicDmpAuthZSubQuery(query, criteriaBuilder, usePublic)) ): cb.or(), //Creates a false query - userId != null ? cb.equal(subQueryRoot.get(DescriptionEntity._createdById), userId) : cb.or() //Creates a false query + userId != null ? + cb.or( + cb.equal(subQueryRoot.get(DescriptionEntity._createdById), userId), + cb.in(subQueryRoot.get(DescriptionEntity._dmpId)).value(this.buildDmpUserAuthZSubQuery(query, criteriaBuilder, userId)) + ) : cb.or() //Creates a false query ) ) )); 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 ebef5ee36..a377a67a8 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 @@ -6,6 +6,7 @@ import eu.eudat.model.DescriptionValidationResult; import eu.eudat.model.StorageFile; import eu.eudat.model.persist.DescriptionFieldFilePersist; import eu.eudat.model.persist.DescriptionPersist; +import eu.eudat.model.persist.DescriptionSectionPermissionResolver; import eu.eudat.model.persist.DescriptionStatusPersist; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyForbiddenException; @@ -18,11 +19,14 @@ import org.springframework.web.multipart.MultipartFile; import javax.management.InvalidApplicationException; import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.UUID; public interface DescriptionService { - Description persist(DescriptionPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException; + Map> getDescriptionSectionPermissions(DescriptionSectionPermissionResolver model); + + Description persist(DescriptionPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException; Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException; 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 419dd3be1..ae9b1e566 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 @@ -1,5 +1,6 @@ package eu.eudat.service.description; +import eu.eudat.authorization.AffiliatedResource; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver; @@ -26,7 +27,6 @@ import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent; import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler; import eu.eudat.model.*; import eu.eudat.model.builder.DescriptionBuilder; -import eu.eudat.model.builder.DescriptionTemplateBuilder; import eu.eudat.model.deleter.DescriptionDeleter; import eu.eudat.model.deleter.DescriptionReferenceDeleter; import eu.eudat.model.deleter.DescriptionTagDeleter; @@ -50,7 +50,6 @@ 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 gr.cite.tools.validation.ValidationResult; import gr.cite.tools.validation.ValidatorFactory; import jakarta.persistence.EntityManager; import org.apache.commons.io.FilenameUtils; @@ -138,6 +137,24 @@ public class DescriptionServiceImpl implements DescriptionService { this.authorizationContentResolver = authorizationContentResolver; } + @Override + public Map> getDescriptionSectionPermissions(DescriptionSectionPermissionResolver model) { + logger.debug(new MapLogEntry("get description section permissions").And("model", model)); + + Map> response = new HashMap<>(); + + Map affiliatedResourceMap = this.authorizationContentResolver.descriptionsAffiliationBySections(model.getDmpId(), model.getSectionIds()); + for (UUID sectionId : model.getSectionIds().stream().distinct().toList()){ + AffiliatedResource affiliatedResource = affiliatedResourceMap.getOrDefault(sectionId, null); + response.put(sectionId, new ArrayList<>()); + for (String permission : model.getPermissions()){ + if (this.authorizationService.authorizeAtLeastOne(List.of(affiliatedResource), permission)) response.get(sectionId).add(permission); + } + } + + return response; + } + //region Persist @Override @@ -145,9 +162,12 @@ public class DescriptionServiceImpl implements DescriptionService { logger.debug(new MapLogEntry("persisting data description").And("model", model).And("fields", fields)); Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); - if (isUpdate) this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription); - else this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(model.getDmpId())), Permission.EditDescription); + DmpDescriptionTemplateEntity dmpDescriptionTemplate = this.entityManager.find(DmpDescriptionTemplateEntity.class, model.getDmpDescriptionTemplateId()); + if (dmpDescriptionTemplate == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDmpDescriptionTemplateId(), DmpDescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + if (isUpdate) this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription); + else this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionsAffiliationBySection(model.getDmpId(), dmpDescriptionTemplate.getSectionId())), Permission.EditDescription); DescriptionEntity data; if (isUpdate) { @@ -167,9 +187,6 @@ public class DescriptionServiceImpl implements DescriptionService { data.setDmpDescriptionTemplateId(model.getDmpDescriptionTemplateId()); } - DmpDescriptionTemplateEntity dmpDescriptionTemplate = this.entityManager.find(DmpDescriptionTemplateEntity.class, data.getDmpDescriptionTemplateId()); - if (dmpDescriptionTemplate == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{data.getDmpDescriptionTemplateId(), DmpDescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale())); - DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, model.getDescriptionTemplateId()); if (descriptionTemplateEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale())); @@ -267,11 +284,14 @@ public class DescriptionServiceImpl implements DescriptionService { switch (status) { case Draft: event.setNotificationType(notificationProperties.getDescriptionModifiedType()); + break; case Finalized: event.setNotificationType(notificationProperties.getDescriptionFinalisedType()); + break; default: throw new MyApplicationException("Unsupported Description Status."); } + return event; } // public List getFieldById(String id){ diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpService.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpService.java index 50b6dec11..54a8734fb 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpService.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpService.java @@ -32,7 +32,7 @@ public interface DmpService { Dmp buildClone(CloneDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, IOException, InvalidApplicationException; - List assignUsers(UUID dmp, List model, FieldSet fields) throws InvalidApplicationException, IOException; + List assignUsers(UUID dmp, List model, FieldSet fields, boolean disableDelete) throws InvalidApplicationException, IOException; Dmp removeUser(DmpUserRemovePersist model, FieldSet fields) throws InvalidApplicationException, IOException; ResponseEntity export(UUID id, String transformerId, String exportType) throws InvalidApplicationException, IOException; diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java index b11b7d16a..9cf16d5b1 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java @@ -492,7 +492,7 @@ public class DmpServiceImpl implements DmpService { } @Override - public List assignUsers(UUID dmpId, List model, FieldSet fieldSet) throws InvalidApplicationException, IOException { + public List assignUsers(UUID dmpId, List model, FieldSet fieldSet, boolean disableDelete) throws InvalidApplicationException, IOException { this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(dmpId)), Permission.AssignDmpUsers); DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, dmpId); @@ -522,7 +522,7 @@ public class DmpServiceImpl implements DmpService { } List toDelete = existingUsers.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getUserId()))).collect(Collectors.toList()); - if (!toDelete.isEmpty()) this.deleterFactory.deleter(DmpUserDeleter.class).delete(toDelete); + if (!toDelete.isEmpty() && !disableDelete) this.deleterFactory.deleter(DmpUserDeleter.class).delete(toDelete); this.entityManager.flush(); @@ -913,7 +913,7 @@ public class DmpServiceImpl implements DmpService { } } - if(!usersToAssign.isEmpty()) this.assignUsers(id, usersToAssign, null); + if(!usersToAssign.isEmpty()) this.assignUsers(id, usersToAssign, null, true); } private void sendDmpInvitationExistingUser(UUID userId, DmpEntity dmp, DmpUserRole role) throws InvalidApplicationException { diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java index 334b0a83b..29ad47987 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/lock/LockServiceImpl.java @@ -1,5 +1,6 @@ package eu.eudat.service.lock; +import eu.eudat.authorization.AffiliatedResource; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver; @@ -80,7 +81,9 @@ public class LockServiceImpl implements LockService { public Lock persist(LockPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields)); - this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(model.getTarget())), Permission.EditLock); + AffiliatedResource affiliatedResourceDmp = this.authorizationContentResolver.dmpAffiliation(model.getTarget()); + AffiliatedResource affiliatedResourceDescription = this.authorizationContentResolver.descriptionAffiliation(model.getTarget()); + this.authorizationService.authorizeAtLeastOneForce(List.of(affiliatedResourceDmp, affiliatedResourceDescription), Permission.EditLock); Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); @@ -179,7 +182,9 @@ public class LockServiceImpl implements LockService { public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { logger.debug("deleting : {}", id); - this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(id)), Permission.DeleteLock); + AffiliatedResource affiliatedResourceDmp = this.authorizationContentResolver.dmpAffiliation(id); + AffiliatedResource affiliatedResourceDescription = this.authorizationContentResolver.descriptionAffiliation(id); + this.authorizationService.authorizeAtLeastOneForce(List.of(affiliatedResourceDmp, affiliatedResourceDescription), Permission.DeleteLock); this.deleterFactory.deleter(LockDeleter.class).deleteAndSaveByIds(List.of(id)); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DescriptionController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DescriptionController.java index b155696ea..a0dc44c26 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DescriptionController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DescriptionController.java @@ -10,6 +10,7 @@ import eu.eudat.data.StorageFileEntity; import eu.eudat.model.*; import eu.eudat.model.builder.PublicDescriptionBuilder; import eu.eudat.model.persist.DescriptionFieldFilePersist; +import eu.eudat.model.persist.DescriptionSectionPermissionResolver; import eu.eudat.service.storage.StorageFileService; import gr.cite.tools.validation.ValidationFilterAnnotation; import eu.eudat.model.builder.DescriptionBuilder; @@ -185,6 +186,19 @@ public class DescriptionController { return persisted; } + @PostMapping("get-description-section-permissions") + @ValidationFilterAnnotation(validator = DescriptionSectionPermissionResolver.DescriptionSectionPermissionResolverPersistValidator.ValidatorName, argumentName = "model") + public Map> getDescriptionSectionPermissions(@RequestBody DescriptionSectionPermissionResolver model) { + logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model)); + Map> persisted = this.descriptionService.getDescriptionSectionPermissions(model); + + this.auditService.track(AuditableAction.Description_GetDescriptionSectionPermissions, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model) + )); + + return persisted; + } + @GetMapping("validate") public List validate(@RequestParam(value="descriptionIds") List descriptionIds) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("validating" + Description.class.getSimpleName()).And("descriptionIds", descriptionIds)); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DmpController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DmpController.java index eff6a60a9..d302fbdc5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DmpController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DmpController.java @@ -242,7 +242,7 @@ public class DmpController { public QueryResult assignUsers(@PathVariable("id") UUID id, @RequestBody List model, FieldSet fieldSet) throws InvalidApplicationException, IOException { logger.debug(new MapLogEntry("assigning users to dmp").And("model", model).And("fieldSet", fieldSet)); - List persisted = this.dmpService.assignUsers(id, model, fieldSet); + List persisted = this.dmpService.assignUsers(id, model, fieldSet, false); this.auditService.track(AuditableAction.Dmp_Assign_Users, Map.ofEntries( new AbstractMap.SimpleEntry("model", model), diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/LockController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/LockController.java index 8e8d98ba3..cb909099d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/LockController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/LockController.java @@ -1,6 +1,7 @@ package eu.eudat.controllers; import eu.eudat.audit.AuditableAction; +import eu.eudat.authorization.AffiliatedResource; import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver; @@ -156,7 +157,7 @@ public class LockController { @GetMapping("target/status/{id}") public Boolean getLocked(@PathVariable("id") UUID targetId) throws Exception { logger.debug(new MapLogEntry("is locked" + Lock.class.getSimpleName()).And("targetId", targetId)); - this.authService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(targetId)), Permission.BrowseLock); + this.authService.authorizeForce(Permission.BrowseLock); Boolean isLocked = this.lockService.isLocked(targetId); this.auditService.track(AuditableAction.Lock_IsLocked, Map.ofEntries( @@ -168,8 +169,9 @@ public class LockController { @Transactional @DeleteMapping("target/unlock/{id}") public boolean unlock(@PathVariable("id") UUID targetId) throws Exception { - logger.debug(new MapLogEntry("unlock" + Lock.class.getSimpleName()).And("targetId", targetId)); - this.authService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.dmpAffiliation(targetId)), Permission.BrowseLock); + AffiliatedResource affiliatedResourceDmp = this.authorizationContentResolver.dmpAffiliation(targetId); + AffiliatedResource affiliatedResourceDescription = this.authorizationContentResolver.descriptionAffiliation(targetId); + this.authService.authorizeAtLeastOneForce(List.of(affiliatedResourceDmp, affiliatedResourceDescription), Permission.EditLock); this.lockService.unlock(targetId); this.auditService.track(AuditableAction.Lock_UnLocked, Map.ofEntries( diff --git a/dmp-backend/web/src/main/resources/config/permissions.yml b/dmp-backend/web/src/main/resources/config/permissions.yml index d1ae62801..87e3c576e 100644 --- a/dmp-backend/web/src/main/resources/config/permissions.yml +++ b/dmp-backend/web/src/main/resources/config/permissions.yml @@ -147,9 +147,7 @@ permissions: dmp: roles: - Owner - - User - DescriptionContributor - - Reviewer clients: [ ] allowAnonymous: false allowAuthenticated: false @@ -159,9 +157,7 @@ permissions: dmp: roles: - Owner - - User - DescriptionContributor - - Reviewer clients: [ ] allowAnonymous: false allowAuthenticated: false @@ -171,9 +167,7 @@ permissions: dmp: roles: - Owner - - User - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -184,9 +178,7 @@ permissions: dmp: roles: - Owner - - User - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -241,6 +233,12 @@ permissions: BrowseDmpAssociatedUser: roles: - Admin + dmp: + roles: + - Owner + - User + - DescriptionContributor + - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -380,9 +378,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -393,9 +388,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -406,9 +398,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -419,22 +408,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer - claims: [ ] - clients: [ ] - allowAnonymous: false - allowAuthenticated: false - ExportDmp: - roles: - - Admin - dmp: - roles: - - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -445,9 +418,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -458,9 +428,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -471,9 +438,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -484,9 +448,6 @@ permissions: dmp: roles: - Owner - - User - - DescriptionContributor - - Reviewer claims: [ ] clients: [ ] allowAnonymous: false @@ -806,12 +767,9 @@ permissions: BrowseLock: roles: - Admin - dmp: - roles: - - Owner - - User - - DescriptionContributor - - Reviewer + - DescriptionTemplateEditor + - Manager + - User clients: [ ] allowAnonymous: false allowAuthenticated: false diff --git a/dmp-frontend/src/app/core/common/enum/permission.enum.ts b/dmp-frontend/src/app/core/common/enum/permission.enum.ts index a2c6c01f0..034ce6d21 100644 --- a/dmp-frontend/src/app/core/common/enum/permission.enum.ts +++ b/dmp-frontend/src/app/core/common/enum/permission.enum.ts @@ -10,7 +10,6 @@ export enum AppPermission { DeleteDmpBlueprint = "DeleteDmpBlueprint", //Description - NewDescription = "NewDescription", BrowseDescription = "BrowseDescription", EditDescription = "EditDescription", FinalizeDescription = "FinalizeDescription", diff --git a/dmp-frontend/src/app/core/model/description/description.ts b/dmp-frontend/src/app/core/model/description/description.ts index 2c2f2890d..1f722dff8 100644 --- a/dmp-frontend/src/app/core/model/description/description.ts +++ b/dmp-frontend/src/app/core/model/description/description.ts @@ -144,3 +144,8 @@ export interface PublicDescriptionTemplate { label: string; description: string; } +export interface DescriptionSectionPermissionResolver { + dmpId: Guid; + sectionIds: Guid[]; + permissions: string[]; +} 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 ea122fbb1..3c07826e3 100644 --- a/dmp-frontend/src/app/core/services/description/description.service.ts +++ b/dmp-frontend/src/app/core/services/description/description.service.ts @@ -1,7 +1,7 @@ import { HttpClient, HttpHeaders, HttpParamsOptions, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { IsActive } from '@app/core/common/enum/is-active.enum'; -import { Description, DescriptionPersist, DescriptionStatusPersist, PublicDescription } from '@app/core/model/description/description'; +import { Description, DescriptionPersist, DescriptionSectionPermissionResolver, DescriptionStatusPersist, PublicDescription } from '@app/core/model/description/description'; import { DescriptionLookup } from '@app/core/query/description.lookup'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; @@ -33,6 +33,11 @@ export class DescriptionService { return this.http.post>(url, q).pipe(catchError((error: any) => throwError(error))); } + getDescriptionSectionPermissions(q: DescriptionSectionPermissionResolver): Observable> { + const url = `${this.apiBase}/get-description-section-permissions`; + return this.http.post>(url, q).pipe(catchError((error: any) => throwError(error))); + } + publicQuery(q: DescriptionLookup): Observable> { const url = `${this.apiBase}/public/query`; const params = new BaseHttpParams(); diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts index 1033e6566..0e73fe8be 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts @@ -6,7 +6,7 @@ import { DescriptionStatus } from '@app/core/common/enum/description-status'; import { DmpStatus } from '@app/core/common/enum/dmp-status'; import { IsActive } from '@app/core/common/enum/is-active.enum'; import { AppPermission } from '@app/core/common/enum/permission.enum'; -import { Description, DescriptionPersist, DescriptionStatusPersist } from '@app/core/model/description/description'; +import { Description, DescriptionPersist, DescriptionSectionPermissionResolver, DescriptionStatusPersist } from '@app/core/model/description/description'; import { AuthService } from '@app/core/services/auth/auth.service'; import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service'; import { DescriptionService } from '@app/core/services/description/description.service'; @@ -588,18 +588,29 @@ export class DescriptionEditorComponent extends BaseEditor x === AppPermission.EditDescription) || this.item.dmp.authorizationFlags?.some(x => x === AppPermission.EditDmp) ||this.authService.hasPermission(AppPermission.EditDescription); - this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !canedit); - //this.visibilityRulesService.buildVisibilityRules(this.visibilityRulesService.getVisibilityRulesFromDescriptionTempalte(this.item.descriptionTemplate), this.formGroup); - - // this.selectedSystemFields = this.selectedSystemFieldDisabled(); - this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); - if (this.editorModel.status == DescriptionStatus.Finalized || this.isDeleted) { - this.formGroup.disable(); + const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { + dmpId: this.item.dmp.id, + sectionIds: [this.item.dmpDescriptionTemplate.sectionId], + permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription] } + this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel) + .pipe(takeUntil(this._destroyed)).subscribe( + permissionPerSection => { + const canedit = permissionPerSection && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.EditDescription); + this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !canedit); + //this.visibilityRulesService.buildVisibilityRules(this.visibilityRulesService.getVisibilityRulesFromDescriptionTempalte(this.item.descriptionTemplate), this.formGroup); + + // this.selectedSystemFields = this.selectedSystemFieldDisabled(); + this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); + if (this.editorModel.status == DescriptionStatus.Finalized || this.isDeleted) { + this.formGroup.disable(); + } + + this.registerFormListeners(); + }, + error => this.onCallbackError(error) + ); - this.registerFormListeners(); } refreshData(): void { diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts index 6f08619da..e86406d08 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts @@ -39,10 +39,11 @@ const routes: Routes = [ data: { ...BreadcrumbService.generateRouteDataConfiguration({ title: 'BREADCRUMBS.EDIT-DESCRIPTION' - }), - authContext: { - permissions: [AppPermission.EditDescription] - } + }) + // , + // authContext: { + // permissions: [AppPermission.EditDescription] + // } } }, { diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html index 30b78b2e3..918378dcd 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html @@ -90,12 +90,12 @@
  • {{'DMP-EDITOR.DESCRIPTION' | translate}}: {{ description.label }}
    - close + close check
  • -