Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-03-19 17:26:08 +02:00
commit 28ae763eb8
30 changed files with 322 additions and 141 deletions

View File

@ -56,6 +56,7 @@ 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");

View File

@ -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";

View File

@ -16,4 +16,8 @@ public interface AuthorizationContentResolver {
AffiliatedResource descriptionAffiliation(UUID id);
Map<UUID, AffiliatedResource> descriptionsAffiliation(List<UUID> ids);
AffiliatedResource descriptionsAffiliationBySection(UUID dmpId, UUID sectionId);
Map<UUID, AffiliatedResource> descriptionsAffiliationBySections(UUID dmpId, List<UUID> sectionIds);
}

View File

@ -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<UUID> idsToResolve = this.getAffiliatedFromCache(ids, userId, affiliatedResources, DmpEntity.class.getSimpleName());
if (idsToResolve.isEmpty()) return affiliatedResources;
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(ids).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._dmp));
List<DmpUserEntity> 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<UUID> idsToResolve = this.getAffiliatedFromCache(ids, userId, affiliatedResources, DescriptionEntity.class.getSimpleName());
if (idsToResolve.isEmpty()) return affiliatedResources;
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).ids(ids).collectAs(new BaseFieldSet().ensure(Description._id).ensure(Description._dmp));
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class).descriptionIds(ids).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._role).ensure(DmpUser._dmp));
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).ids(ids).collectAs(new BaseFieldSet().ensure(Description._id).ensure(Description._dmpDescriptionTemplate).ensure(Description._dmp));
List<DmpDescriptionTemplateEntity> dmpDescriptionTemplateEntities = this.queryFactory.query(DmpDescriptionTemplateQuery.class).ids(descriptionEntities.stream().map(DescriptionEntity::getDmpDescriptionTemplateId).distinct().toList()).collectAs(new BaseFieldSet().ensure(DmpDescriptionTemplate._id).ensure(DmpDescriptionTemplate._sectionId));
Map<UUID, DmpDescriptionTemplateEntity> dmpDescriptionTemplateEntityMap = dmpDescriptionTemplateEntities == null ? new HashMap<>() : dmpDescriptionTemplateEntities.stream().collect(Collectors.toMap(DmpDescriptionTemplateEntity::getId, x-> x));
List<DmpUserEntity> 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<UUID, List<DmpUserEntity>> dmpUsersMap = dmpUsers.stream().collect(Collectors.groupingBy(DmpUserEntity::getDmpId));
for (DescriptionEntity description : descriptionEntities){
List<DmpUserEntity> 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<UUID, AffiliatedResource> descriptionsAffiliationBySections(UUID dmpId, List<UUID> sectionIds){
UUID userId = this.userScope.getUserIdSafe();
Map<UUID, AffiliatedResource> affiliatedResources = new HashMap<>();
for (UUID id : sectionIds){
affiliatedResources.put(id, new AffiliatedResource());
}
if (userId == null || !userScope.isSet()) return affiliatedResources;
List<DmpUserEntity> 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<DmpUserEntity> 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<UUID> getAffiliatedFromCache(List<UUID> ids, UUID userId, Map<UUID, AffiliatedResource> affiliatedResources, String entityType){
List<UUID> idsToResolve = new ArrayList<>();
for (UUID id : ids){

View File

@ -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);
}
}

View File

@ -32,6 +32,10 @@ public class Section {
public final static String _prefillingSources = "prefillingSources";
private List<PrefillingSource> 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<PrefillingSource> prefillingSources) {
this.prefillingSources = prefillingSources;
}
public Boolean getCanCreate() {
return canCreate;
}
public void setCanCreate(Boolean canCreate) {
this.canCreate = canCreate;
}
}

View File

@ -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<UUID> sectionIds;
public static final String _sectionIds = "sectionIds";
private List<String> permissions;
public static final String _permissions = "permissions";
public UUID getDmpId() {
return dmpId;
}
public void setDmpId(UUID dmpId) {
this.dmpId = dmpId;
}
public List<UUID> getSectionIds() {
return sectionIds;
}
public void setSectionIds(List<UUID> sectionIds) {
this.sectionIds = sectionIds;
}
public List<String> getPermissions() {
return permissions;
}
public void setPermissions(List<String> permissions) {
this.permissions = permissions;
}
@Component(DescriptionSectionPermissionResolverPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class DescriptionSectionPermissionResolverPersistValidator extends BaseValidator<DescriptionSectionPermissionResolver> {
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<DescriptionSectionPermissionResolver> modelClass() {
return DescriptionSectionPermissionResolver.class;
}
@Override
protected List<Specification> 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()))
);
}
}
}

View File

@ -118,3 +118,4 @@ public class LockPersist {
}
}

View File

@ -158,15 +158,7 @@ public class DescriptionReferenceQuery extends QueryBase<DescriptionReferenceEnt
List<Predicate> predicates = new ArrayList<>();
if (userId != null || usePublic ) {
UUID finalUserId = userId;
Subquery<UUID> 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]);

View File

@ -144,37 +144,6 @@ public class DescriptionTagQuery extends QueryBase<DescriptionTagEntity> {
}
@Override
protected <X, Y> Predicate applyAuthZ(QueryContext<X, Y> 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<Predicate> predicates = new ArrayList<>();
if (userId != null || usePublic ) {
UUID finalUserId = userId;
Subquery<UUID> 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 <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();

View File

@ -42,6 +42,7 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
private Collection<DmpUserRole> userRoles;
private Collection<UUID> sectionIds;
private Boolean sectionIsEmpty;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@ -150,6 +151,11 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
return this;
}
public DmpUserQuery sectionIsEmpty(Boolean sectionIsEmpty) {
this.sectionIsEmpty = sectionIsEmpty;
return this;
}
public DmpUserQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
@ -224,6 +230,10 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
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<UUID> descriptionSubquery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(
new BuildSubQueryInput.Builder<>(DescriptionEntity.class, UUID.class, queryContext)

View File

@ -159,7 +159,7 @@ public class UserQuery extends QueryBase<UserEntity> {
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))

View File

@ -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
)
)
));

View File

@ -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<UUID, List<String>> 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;

View File

@ -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<UUID, List<String>> getDescriptionSectionPermissions(DescriptionSectionPermissionResolver model) {
logger.debug(new MapLogEntry("get description section permissions").And("model", model));
Map<UUID, List<String>> response = new HashMap<>();
Map<UUID, AffiliatedResource> 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<eu.eudat.commons.types.descriptiontemplate.FieldEntity> getFieldById(String id){

View File

@ -32,7 +32,7 @@ public interface DmpService {
Dmp buildClone(CloneDmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, IOException, InvalidApplicationException;
List<DmpUser> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fields) throws InvalidApplicationException, IOException;
List<DmpUser> assignUsers(UUID dmp, List<DmpUserPersist> model, FieldSet fields, boolean disableDelete) throws InvalidApplicationException, IOException;
Dmp removeUser(DmpUserRemovePersist model, FieldSet fields) throws InvalidApplicationException, IOException;
ResponseEntity<byte[]> export(UUID id, String transformerId, String exportType) throws InvalidApplicationException, IOException;

View File

@ -492,7 +492,7 @@ public class DmpServiceImpl implements DmpService {
}
@Override
public List<DmpUser> assignUsers(UUID dmpId, List<DmpUserPersist> model, FieldSet fieldSet) throws InvalidApplicationException, IOException {
public List<DmpUser> assignUsers(UUID dmpId, List<DmpUserPersist> 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<DmpUserEntity> 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();
@ -916,7 +916,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 {

View File

@ -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));
}

View File

@ -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<UUID, List<String>> getDescriptionSectionPermissions(@RequestBody DescriptionSectionPermissionResolver model) {
logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model));
Map<UUID, List<String>> persisted = this.descriptionService.getDescriptionSectionPermissions(model);
this.auditService.track(AuditableAction.Description_GetDescriptionSectionPermissions, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model)
));
return persisted;
}
@GetMapping("validate")
public List<DescriptionValidationResult> validate(@RequestParam(value="descriptionIds") List<UUID> descriptionIds) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("validating" + Description.class.getSimpleName()).And("descriptionIds", descriptionIds));

View File

@ -242,7 +242,7 @@ public class DmpController {
public QueryResult<DmpUser> assignUsers(@PathVariable("id") UUID id, @RequestBody List<DmpUserPersist> model, FieldSet fieldSet) throws InvalidApplicationException, IOException {
logger.debug(new MapLogEntry("assigning users to dmp").And("model", model).And("fieldSet", fieldSet));
List<DmpUser> persisted = this.dmpService.assignUsers(id, model, fieldSet);
List<DmpUser> persisted = this.dmpService.assignUsers(id, model, fieldSet, false);
this.auditService.track(AuditableAction.Dmp_Assign_Users, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model),

View File

@ -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(

View File

@ -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

View File

@ -10,7 +10,6 @@ export enum AppPermission {
DeleteDmpBlueprint = "DeleteDmpBlueprint",
//Description
NewDescription = "NewDescription",
BrowseDescription = "BrowseDescription",
EditDescription = "EditDescription",
FinalizeDescription = "FinalizeDescription",

View File

@ -144,3 +144,8 @@ export interface PublicDescriptionTemplate {
label: string;
description: string;
}
export interface DescriptionSectionPermissionResolver {
dmpId: Guid;
sectionIds: Guid[];
permissions: string[];
}

View File

@ -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<QueryResult<Description>>(url, q).pipe(catchError((error: any) => throwError(error)));
}
getDescriptionSectionPermissions(q: DescriptionSectionPermissionResolver): Observable<Map<Guid, string[]>> {
const url = `${this.apiBase}/get-description-section-permissions`;
return this.http.post<Map<Guid, string[]>>(url, q).pipe(catchError((error: any) => throwError(error)));
}
publicQuery(q: DescriptionLookup): Observable<QueryResult<PublicDescription>> {
const url = `${this.apiBase}/public/query`;
const params = new BaseHttpParams();

View File

@ -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<DescriptionEditorMode
}
buildForm() {
const canedit = this.isNew ? this.authService.hasPermission(AppPermission.NewDescription) :
this.item.authorizationFlags?.some(x => 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 {

View File

@ -39,10 +39,11 @@ const routes: Routes = [
data: {
...BreadcrumbService.generateRouteDataConfiguration({
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
}),
authContext: {
permissions: [AppPermission.EditDescription]
}
})
// ,
// authContext: {
// permissions: [AppPermission.EditDescription]
// }
}
},
{

View File

@ -90,12 +90,12 @@
<li *ngFor="let description of descriptionsInSection(section.id); let descriptionIndex = index" (click)="editDescription(description.id, false)" class="active-dataset">
<div class="d-flex flex-direction-row">
<div class="label" matTooltip="{{description.label}}">{{'DMP-EDITOR.DESCRIPTION' | translate}}: {{ description.label }}</div>
<mat-icon *ngIf="description.status !== descriptionStatusEnum.Finalized" class="ml-2 mr-2 remove-dataset size-16" matTooltip="{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}" (click)="$event.stopPropagation(); removeDescription(description.id)">close</mat-icon>
<mat-icon *ngIf="description.status !== descriptionStatusEnum.Finalized && canDeleteSection(section.id)" class="ml-2 mr-2 remove-dataset size-16" matTooltip="{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}" (click)="$event.stopPropagation(); removeDescription(description.id)">close</mat-icon>
<mat-icon *ngIf="description.status === descriptionStatusEnum.Finalized" class="ml-2 mr-2 status-icon check-icon size-16" matTooltip="{{'TYPES.DATASET-STATUS.FINALISED' | translate}}">check</mat-icon>
</div>
</li>
</ol>
<ul *ngIf="item.id && section.hasTemplates" class="add-dataset-option">
<ul *ngIf="item.id && section.hasTemplates && canEditSection(section.id)" class="add-dataset-option">
<li>
<a class="add-dataset-action" [routerLink]="['/descriptions/edit/' + item.id + '/' + section.id]">
<mat-icon>add</mat-icon>{{'DMP-EDITOR.ACTIONS.ADD-DESCRIPTION-IN-SECTION' | translate}}

View File

@ -47,6 +47,8 @@ import { DmpEditorService } from './dmp-editor.service';
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
import { DmpUserType } from '@app/core/common/enum/dmp-user-type';
import { DescriptionService } from '@app/core/services/description/description.service';
import { DescriptionSectionPermissionResolver } from '@app/core/model/description/description';
import { UUID } from 'crypto';
@Component({
selector: 'app-dmp-editor',
@ -73,6 +75,9 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
dmpUserTypeEnum = DmpUserType;
dmpUserTypeEnumValues = this.enumUtils.getEnumValues<DmpUserType>(DmpUserType);
dmpUserRoleEnumValues = this.enumUtils.getEnumValues<DmpUserRole>(DmpUserRole);
permissionPerSection: Map<Guid, string[]>;
singleAutocompleteBlueprintConfiguration: SingleAutoCompleteConfiguration = {
initialItems: (data?: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(null, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(searchQuery, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)),
@ -94,6 +99,19 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDmp));
}
protected canEditSection(id: Guid): boolean {
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDescription) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDescription) || (
this.permissionPerSection && this.permissionPerSection[id.toString()] && this.permissionPerSection[id.toString()].some(x => x === AppPermission.EditDescription)
));
}
protected canDeleteSection(id: Guid): boolean {
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.DeleteDescription) || this.item?.authorizationFlags?.some(x => x === AppPermission.DeleteDescription) || (
this.permissionPerSection && this.permissionPerSection[id.toString()] && this.permissionPerSection[id.toString()].some(x => x === AppPermission.DeleteDescription)
));
}
private hasPermission(permission: AppPermission): boolean {
return this.authService.hasPermission(permission) || this.item?.authorizationFlags?.some(x => x === permission) || this.editorModel?.permissions?.includes(permission);
@ -198,7 +216,21 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
this.selectedBlueprint = data?.blueprint;
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
this.buildForm();
const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = {
dmpId: data.id,
sectionIds: data?.blueprint?.definition?.sections?.map(x => x.id),
permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription]
}
this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel)
.pipe(takeUntil(this._destroyed)).subscribe(
complete => {
this.permissionPerSection = complete,
this.buildForm();
},
error => this.onCallbackError(error)
);
} catch (error) {
this.logger.error('Could not parse Dmp item: ' + data + error);
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);

View File

@ -42,6 +42,7 @@ export class DmpEditorResolver extends BaseEditorResolver {
[nameof<Dmp>(x => x.authorizationFlags), AppPermission.EditDmp].join('.'),
[nameof<Dmp>(x => x.authorizationFlags), AppPermission.DeleteDmp].join('.'),
[nameof<Dmp>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
[nameof<Dmp>(x => x.properties), nameof<DmpProperties>(x => x.dmpBlueprintValues), nameof<DmpBlueprintValue>(x => x.fieldId)].join('.'),
[nameof<Dmp>(x => x.properties), nameof<DmpProperties>(x => x.dmpBlueprintValues), nameof<DmpBlueprintValue>(x => x.fieldValue)].join('.'),