description authz
This commit is contained in:
parent
c62a945a6a
commit
266c05ee80
|
@ -101,6 +101,7 @@ public final class Permission {
|
||||||
//Description
|
//Description
|
||||||
public static String BrowseDescription = "BrowseDescription";
|
public static String BrowseDescription = "BrowseDescription";
|
||||||
public static String EditDescription = "EditDescription";
|
public static String EditDescription = "EditDescription";
|
||||||
|
public static String FinalizeDescription = "FinalizeDescription";
|
||||||
public static String DeleteDescription = "DeleteDescription";
|
public static String DeleteDescription = "DeleteDescription";
|
||||||
public static String CloneDescription = "CloneDescription";
|
public static String CloneDescription = "CloneDescription";
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,8 @@ public interface AuthorizationContentResolver {
|
||||||
AffiliatedResource dmpAffiliation(UUID id);
|
AffiliatedResource dmpAffiliation(UUID id);
|
||||||
|
|
||||||
Map<UUID, AffiliatedResource> dmpsAffiliation(List<UUID> ids);
|
Map<UUID, AffiliatedResource> dmpsAffiliation(List<UUID> ids);
|
||||||
|
|
||||||
|
AffiliatedResource descriptionAffiliation(UUID id);
|
||||||
|
|
||||||
|
Map<UUID, AffiliatedResource> descriptionsAffiliation(List<UUID> ids);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,12 @@ import eu.eudat.authorization.AffiliatedResource;
|
||||||
import eu.eudat.authorization.PermissionNameProvider;
|
import eu.eudat.authorization.PermissionNameProvider;
|
||||||
import eu.eudat.commons.enums.IsActive;
|
import eu.eudat.commons.enums.IsActive;
|
||||||
import eu.eudat.commons.scope.user.UserScope;
|
import eu.eudat.commons.scope.user.UserScope;
|
||||||
|
import eu.eudat.data.DescriptionEntity;
|
||||||
import eu.eudat.data.DmpEntity;
|
import eu.eudat.data.DmpEntity;
|
||||||
import eu.eudat.data.DmpUserEntity;
|
import eu.eudat.data.DmpUserEntity;
|
||||||
|
import eu.eudat.model.Description;
|
||||||
import eu.eudat.model.DmpUser;
|
import eu.eudat.model.DmpUser;
|
||||||
|
import eu.eudat.query.DescriptionQuery;
|
||||||
import eu.eudat.query.DmpUserQuery;
|
import eu.eudat.query.DmpUserQuery;
|
||||||
import gr.cite.tools.data.query.QueryFactory;
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
|
@ -14,6 +17,7 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.context.annotation.RequestScope;
|
import org.springframework.web.context.annotation.RequestScope;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequestScope
|
@RequestScope
|
||||||
|
@ -60,6 +64,37 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
|
||||||
return affiliatedResources;
|
return affiliatedResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AffiliatedResource descriptionAffiliation(UUID id) {
|
||||||
|
return this.descriptionsAffiliation(List.of(id)).getOrDefault(id, new AffiliatedResource());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Map<UUID, AffiliatedResource> descriptionsAffiliation(List<UUID> ids){
|
||||||
|
UUID userId = this.userScope.getUserIdSafe();
|
||||||
|
Map<UUID, AffiliatedResource> affiliatedResources = new HashMap<>();
|
||||||
|
for (UUID id : ids){
|
||||||
|
affiliatedResources.put(id, new AffiliatedResource());
|
||||||
|
}
|
||||||
|
if (userId == null || !userScope.isSet()) return affiliatedResources;
|
||||||
|
|
||||||
|
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));
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ensureAffiliatedInCache(idsToResolve, userId, affiliatedResources, DescriptionEntity.class.getSimpleName());
|
||||||
|
return affiliatedResources;
|
||||||
|
}
|
||||||
|
|
||||||
private List<UUID> getAffiliatedFromCache(List<UUID> ids, UUID userId, Map<UUID, AffiliatedResource> affiliatedResources, String entityType){
|
private List<UUID> getAffiliatedFromCache(List<UUID> ids, UUID userId, Map<UUID, AffiliatedResource> affiliatedResources, String entityType){
|
||||||
List<UUID> idsToResolve = new ArrayList<>();
|
List<UUID> idsToResolve = new ArrayList<>();
|
||||||
for (UUID id : ids){
|
for (UUID id : ids){
|
||||||
|
|
|
@ -71,6 +71,9 @@ public class Description {
|
||||||
|
|
||||||
public static final String _descriptionTemplate = "descriptionTemplate";
|
public static final String _descriptionTemplate = "descriptionTemplate";
|
||||||
|
|
||||||
|
private List<String> authorizationFlags;
|
||||||
|
public static final String _authorizationFlags = "authorizationFlags";
|
||||||
|
|
||||||
private Dmp dmp;
|
private Dmp dmp;
|
||||||
|
|
||||||
public static final String _dmp = "dmp";
|
public static final String _dmp = "dmp";
|
||||||
|
@ -203,4 +206,12 @@ public class Description {
|
||||||
public void setDescriptionTemplate(DescriptionTemplate descriptionTemplate) {
|
public void setDescriptionTemplate(DescriptionTemplate descriptionTemplate) {
|
||||||
this.descriptionTemplate = descriptionTemplate;
|
this.descriptionTemplate = descriptionTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getAuthorizationFlags() {
|
||||||
|
return authorizationFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorizationFlags(List<String> authorizationFlags) {
|
||||||
|
this.authorizationFlags = authorizationFlags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package eu.eudat.model.builder;
|
package eu.eudat.model.builder;
|
||||||
|
|
||||||
|
import eu.eudat.authorization.AffiliatedResource;
|
||||||
import eu.eudat.authorization.AuthorizationFlags;
|
import eu.eudat.authorization.AuthorizationFlags;
|
||||||
|
import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver;
|
||||||
import eu.eudat.commons.JsonHandlingService;
|
import eu.eudat.commons.JsonHandlingService;
|
||||||
import eu.eudat.commons.XmlHandlingService;
|
import eu.eudat.commons.XmlHandlingService;
|
||||||
import eu.eudat.commons.types.description.PropertyDefinitionEntity;
|
import eu.eudat.commons.types.description.PropertyDefinitionEntity;
|
||||||
|
@ -8,10 +10,12 @@ import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity;
|
||||||
import eu.eudat.convention.ConventionService;
|
import eu.eudat.convention.ConventionService;
|
||||||
import eu.eudat.data.DescriptionEntity;
|
import eu.eudat.data.DescriptionEntity;
|
||||||
import eu.eudat.data.DescriptionTemplateEntity;
|
import eu.eudat.data.DescriptionTemplateEntity;
|
||||||
|
import eu.eudat.data.DmpEntity;
|
||||||
import eu.eudat.data.UserRoleEntity;
|
import eu.eudat.data.UserRoleEntity;
|
||||||
import eu.eudat.model.*;
|
import eu.eudat.model.*;
|
||||||
import eu.eudat.model.builder.descriptionpropertiesdefinition.PropertyDefinitionBuilder;
|
import eu.eudat.model.builder.descriptionpropertiesdefinition.PropertyDefinitionBuilder;
|
||||||
import eu.eudat.query.*;
|
import eu.eudat.query.*;
|
||||||
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
import gr.cite.tools.data.query.QueryFactory;
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
import gr.cite.tools.exception.MyApplicationException;
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
@ -37,6 +41,8 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
private final BuilderFactory builderFactory;
|
private final BuilderFactory builderFactory;
|
||||||
private final JsonHandlingService jsonHandlingService;
|
private final JsonHandlingService jsonHandlingService;
|
||||||
private final XmlHandlingService xmlHandlingService;
|
private final XmlHandlingService xmlHandlingService;
|
||||||
|
private final AuthorizationService authorizationService;
|
||||||
|
private final AuthorizationContentResolver authorizationContentResolver;
|
||||||
|
|
||||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
|
||||||
|
@ -44,12 +50,14 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
public DescriptionBuilder(
|
public DescriptionBuilder(
|
||||||
ConventionService conventionService,
|
ConventionService conventionService,
|
||||||
QueryFactory queryFactory,
|
QueryFactory queryFactory,
|
||||||
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService) {
|
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, AuthorizationService authorizationService, AuthorizationContentResolver authorizationContentResolver) {
|
||||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionBuilder.class)));
|
super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionBuilder.class)));
|
||||||
this.queryFactory = queryFactory;
|
this.queryFactory = queryFactory;
|
||||||
this.builderFactory = builderFactory;
|
this.builderFactory = builderFactory;
|
||||||
this.jsonHandlingService = jsonHandlingService;
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
this.xmlHandlingService = xmlHandlingService;
|
this.xmlHandlingService = xmlHandlingService;
|
||||||
|
this.authorizationService = authorizationService;
|
||||||
|
this.authorizationContentResolver = authorizationContentResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DescriptionBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
public DescriptionBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||||
|
@ -86,6 +94,9 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
|
|
||||||
Map<UUID, DefinitionEntity> definitionEntityMap = !definitionPropertiesFields.isEmpty() ? this.collectDescriptionTemplateDefinitions(data) : null;
|
Map<UUID, DefinitionEntity> definitionEntityMap = !definitionPropertiesFields.isEmpty() ? this.collectDescriptionTemplateDefinitions(data) : null;
|
||||||
|
|
||||||
|
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Description._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
|
||||||
|
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.descriptionsAffiliation(data.stream().map(DescriptionEntity::getId).collect(Collectors.toList()));
|
||||||
|
|
||||||
List<Description> models = new ArrayList<>();
|
List<Description> models = new ArrayList<>();
|
||||||
for (DescriptionEntity d : data) {
|
for (DescriptionEntity d : data) {
|
||||||
Description m = new Description();
|
Description m = new Description();
|
||||||
|
@ -108,6 +119,7 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
||||||
PropertyDefinitionEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(PropertyDefinitionEntity.class, d.getProperties());
|
PropertyDefinitionEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(PropertyDefinitionEntity.class, d.getProperties());
|
||||||
m.setProperties(this.builderFactory.builder(PropertyDefinitionBuilder.class).withDefinition(definitionEntityMap != null ? definitionEntityMap.getOrDefault(d.getDescriptionTemplateId(), null) : null).authorize(this.authorize).build(definitionPropertiesFields, propertyDefinition));
|
m.setProperties(this.builderFactory.builder(PropertyDefinitionBuilder.class).withDefinition(definitionEntityMap != null ? definitionEntityMap.getOrDefault(d.getDescriptionTemplateId(), null) : null).authorize(this.authorize).build(definitionPropertiesFields, propertyDefinition));
|
||||||
}
|
}
|
||||||
|
if (affiliatedResourceMap != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
|
||||||
models.add(m);
|
models.add(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,6 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
|
||||||
Map<UUID, List<DmpDescriptionTemplate>> dmpDescriptionTemplatesMap = this.collectDmpDescriptionTemplates(dmpDescriptionTemplatesFields, data);
|
Map<UUID, List<DmpDescriptionTemplate>> dmpDescriptionTemplatesMap = this.collectDmpDescriptionTemplates(dmpDescriptionTemplatesFields, data);
|
||||||
|
|
||||||
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Dmp._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
|
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Dmp._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
|
||||||
|
|
||||||
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.dmpsAffiliation(data.stream().map(DmpEntity::getId).collect(Collectors.toList()));
|
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.dmpsAffiliation(data.stream().map(DmpEntity::getId).collect(Collectors.toList()));
|
||||||
|
|
||||||
FieldSet propertiesFields = fields.extractPrefixed(this.asPrefix(Dmp._properties));
|
FieldSet propertiesFields = fields.extractPrefixed(this.asPrefix(Dmp._properties));
|
||||||
|
@ -121,7 +120,7 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
|
||||||
DmpPropertiesEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(DmpPropertiesEntity.class, d.getProperties());
|
DmpPropertiesEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(DmpPropertiesEntity.class, d.getProperties());
|
||||||
m.setProperties(this.builderFactory.builder(DmpPropertiesBuilder.class).authorize(this.authorize).build(propertiesFields, propertyDefinition));
|
m.setProperties(this.builderFactory.builder(DmpPropertiesBuilder.class).authorize(this.authorize).build(propertiesFields, propertyDefinition));
|
||||||
}
|
}
|
||||||
if (authorizationFlags != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
|
if (affiliatedResourceMap != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
|
||||||
models.add(m);
|
models.add(m);
|
||||||
}
|
}
|
||||||
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class TagCensor extends BaseCensor {
|
||||||
if (fields == null || fields.isEmpty())
|
if (fields == null || fields.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.authService.authorizeForce(Permission.BrowseTag);
|
this.authService.authorizeForce(Permission.BrowseTag, Permission.DeferredAffiliation);
|
||||||
FieldSet createdByFields = fields.extractPrefixed(this.asIndexerPrefix(Tag._createdBy));
|
FieldSet createdByFields = fields.extractPrefixed(this.asIndexerPrefix(Tag._createdBy));
|
||||||
this.censorFactory.censor(UserCensor.class).censor(createdByFields, userId);
|
this.censorFactory.censor(UserCensor.class).censor(createdByFields, userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,6 +314,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
|
||||||
else if (item.prefix(Description._descriptionTemplate) || item.prefix(PublicDescription._descriptionTemplate)) return DescriptionEntity._descriptionTemplateId;
|
else if (item.prefix(Description._descriptionTemplate) || item.prefix(PublicDescription._descriptionTemplate)) return DescriptionEntity._descriptionTemplateId;
|
||||||
else if (item.match(Description._descriptionTemplate) || item.match(PublicDescription._descriptionTemplate)) return DescriptionEntity._descriptionTemplateId;
|
else if (item.match(Description._descriptionTemplate) || item.match(PublicDescription._descriptionTemplate)) return DescriptionEntity._descriptionTemplateId;
|
||||||
else if (item.prefix(Description._dmp)) return DescriptionEntity._dmpId;
|
else if (item.prefix(Description._dmp)) return DescriptionEntity._dmpId;
|
||||||
|
else if (item.match(Description._dmp)) return DescriptionEntity._dmpId;
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@ import eu.eudat.authorization.Permission;
|
||||||
import eu.eudat.commons.enums.DmpUserRole;
|
import eu.eudat.commons.enums.DmpUserRole;
|
||||||
import eu.eudat.commons.enums.IsActive;
|
import eu.eudat.commons.enums.IsActive;
|
||||||
import eu.eudat.commons.scope.user.UserScope;
|
import eu.eudat.commons.scope.user.UserScope;
|
||||||
import eu.eudat.data.DmpReferenceEntity;
|
import eu.eudat.data.*;
|
||||||
import eu.eudat.data.DmpUserEntity;
|
|
||||||
import eu.eudat.data.ReferenceEntity;
|
|
||||||
import eu.eudat.model.DmpUser;
|
import eu.eudat.model.DmpUser;
|
||||||
import eu.eudat.model.PublicDmpUser;
|
import eu.eudat.model.PublicDmpUser;
|
||||||
import eu.eudat.query.utils.BuildSubQueryInput;
|
import eu.eudat.query.utils.BuildSubQueryInput;
|
||||||
|
@ -19,6 +17,7 @@ import gr.cite.tools.data.query.QueryContext;
|
||||||
import jakarta.persistence.Tuple;
|
import jakarta.persistence.Tuple;
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import jakarta.persistence.criteria.Subquery;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -36,6 +35,8 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
|
||||||
|
|
||||||
private Collection<UUID> dmpIds;
|
private Collection<UUID> dmpIds;
|
||||||
|
|
||||||
|
private Collection<UUID> descriptionIds;
|
||||||
|
|
||||||
private Collection<UUID> userIds;
|
private Collection<UUID> userIds;
|
||||||
|
|
||||||
private Collection<DmpUserRole> userRoles;
|
private Collection<DmpUserRole> userRoles;
|
||||||
|
@ -89,6 +90,21 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DmpUserQuery descriptionIds(UUID value) {
|
||||||
|
this.descriptionIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DmpUserQuery descriptionIds(UUID... value) {
|
||||||
|
this.descriptionIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DmpUserQuery descriptionIds(Collection<UUID> values) {
|
||||||
|
this.descriptionIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DmpUserQuery userRoles(DmpUserRole value) {
|
public DmpUserQuery userRoles(DmpUserRole value) {
|
||||||
this.userRoles = List.of(value);
|
this.userRoles = List.of(value);
|
||||||
return this;
|
return this;
|
||||||
|
@ -161,7 +177,7 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Boolean isFalseQuery() {
|
protected Boolean isFalseQuery() {
|
||||||
return this.isEmpty(this.ids) || this.isEmpty(this.dmpIds) || this.isEmpty(this.userIds);
|
return this.isEmpty(this.ids) || this.isEmpty(this.dmpIds) || this.isEmpty(this.descriptionIds) || this.isEmpty(this.userIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -208,6 +224,19 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
|
||||||
inClause.value(item);
|
inClause.value(item);
|
||||||
predicates.add(inClause);
|
predicates.add(inClause);
|
||||||
}
|
}
|
||||||
|
if (this.descriptionIds != null) {
|
||||||
|
Subquery<UUID> descriptionSubquery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(
|
||||||
|
new BuildSubQueryInput.Builder<>(DescriptionEntity.class, UUID.class, queryContext)
|
||||||
|
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(DescriptionEntity._dmpId))
|
||||||
|
.filterFunc((subQueryRoot, cb) -> {
|
||||||
|
CriteriaBuilder.In<UUID> inClause = cb.in(subQueryRoot.get(DmpUserEntity._id));
|
||||||
|
for (UUID item : this.descriptionIds)
|
||||||
|
inClause.value(item);
|
||||||
|
return inClause;
|
||||||
|
})
|
||||||
|
));
|
||||||
|
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpUserEntity._dmpId)).value(descriptionSubquery));
|
||||||
|
}
|
||||||
if (this.userIds != null) {
|
if (this.userIds != null) {
|
||||||
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpUserEntity._userId));
|
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpUserEntity._userId));
|
||||||
for (UUID item : this.userIds)
|
for (UUID item : this.userIds)
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
package eu.eudat.query;
|
package eu.eudat.query;
|
||||||
|
|
||||||
import eu.eudat.authorization.AuthorizationFlags;
|
import eu.eudat.authorization.AuthorizationFlags;
|
||||||
|
import eu.eudat.authorization.Permission;
|
||||||
import eu.eudat.commons.enums.IsActive;
|
import eu.eudat.commons.enums.IsActive;
|
||||||
|
import eu.eudat.commons.scope.user.UserScope;
|
||||||
|
import eu.eudat.data.DescriptionTagEntity;
|
||||||
|
import eu.eudat.data.DmpReferenceEntity;
|
||||||
|
import eu.eudat.data.ReferenceEntity;
|
||||||
import eu.eudat.data.TagEntity;
|
import eu.eudat.data.TagEntity;
|
||||||
import eu.eudat.model.Tag;
|
import eu.eudat.model.Tag;
|
||||||
|
import eu.eudat.query.utils.BuildSubQueryInput;
|
||||||
|
import eu.eudat.query.utils.QueryUtilsService;
|
||||||
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.tools.data.query.FieldResolver;
|
import gr.cite.tools.data.query.FieldResolver;
|
||||||
import gr.cite.tools.data.query.QueryBase;
|
import gr.cite.tools.data.query.QueryBase;
|
||||||
import gr.cite.tools.data.query.QueryContext;
|
import gr.cite.tools.data.query.QueryContext;
|
||||||
|
@ -35,7 +43,14 @@ public class TagQuery extends QueryBase<TagEntity> {
|
||||||
|
|
||||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
|
||||||
public TagQuery() {
|
private final UserScope userScope;
|
||||||
|
private final AuthorizationService authService;
|
||||||
|
private final QueryUtilsService queryUtilsService;
|
||||||
|
|
||||||
|
public TagQuery(UserScope userScope, AuthorizationService authService, QueryUtilsService queryUtilsService) {
|
||||||
|
this.userScope = userScope;
|
||||||
|
this.authService = authService;
|
||||||
|
this.queryUtilsService = queryUtilsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagQuery like(String value) {
|
public TagQuery like(String value) {
|
||||||
|
@ -153,6 +168,37 @@ public class TagQuery extends QueryBase<TagEntity> {
|
||||||
protected Class<TagEntity> entityClass() {
|
protected Class<TagEntity> entityClass() {
|
||||||
return TagEntity.class;
|
return TagEntity.class;
|
||||||
}
|
}
|
||||||
|
@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.BrowseTag)) return null;
|
||||||
|
UUID userId;
|
||||||
|
boolean usePublic = this.authorize.contains(AuthorizationFlags.Public);
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.DmpAssociated)) userId = this.userScope.getUserIdSafe();
|
||||||
|
else userId = null;
|
||||||
|
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
if (userId != null || usePublic ) {
|
||||||
|
predicates.add(queryContext.CriteriaBuilder.or(
|
||||||
|
queryContext.CriteriaBuilder.isNull(queryContext.Root.get(TagEntity._createdById)),
|
||||||
|
userId != null ? queryContext.CriteriaBuilder.equal(queryContext.Root.get(TagEntity._createdById), userId) : queryContext.CriteriaBuilder.or(), //Creates a false query
|
||||||
|
queryContext.CriteriaBuilder.in(queryContext.Root.get(TagEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(DescriptionTagEntity.class, UUID.class)
|
||||||
|
.query(queryContext.Query)
|
||||||
|
.criteriaBuilder(queryContext.CriteriaBuilder)
|
||||||
|
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(DescriptionTagEntity._tagId))
|
||||||
|
.filterFunc((subQueryRoot, cb) ->
|
||||||
|
cb.in(subQueryRoot.get(DescriptionTagEntity._descriptionId)).value(queryUtilsService.buildDescriptionAuthZSubQuery(queryContext.Query, queryContext.CriteriaBuilder, userId, usePublic))
|
||||||
|
)
|
||||||
|
))) //Creates a false query
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (!predicates.isEmpty()) {
|
||||||
|
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||||
|
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||||
|
} else {
|
||||||
|
return queryContext.CriteriaBuilder.or(); //Creates a false query
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
|
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.eudat.service.description;
|
||||||
|
|
||||||
import eu.eudat.authorization.AuthorizationFlags;
|
import eu.eudat.authorization.AuthorizationFlags;
|
||||||
import eu.eudat.authorization.Permission;
|
import eu.eudat.authorization.Permission;
|
||||||
|
import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver;
|
||||||
import eu.eudat.commons.JsonHandlingService;
|
import eu.eudat.commons.JsonHandlingService;
|
||||||
import eu.eudat.commons.XmlHandlingService;
|
import eu.eudat.commons.XmlHandlingService;
|
||||||
import eu.eudat.commons.enums.*;
|
import eu.eudat.commons.enums.*;
|
||||||
|
@ -96,6 +97,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
private final StorageFileProperties storageFileConfig;
|
private final StorageFileProperties storageFileConfig;
|
||||||
private final StorageFileService storageFileService;
|
private final StorageFileService storageFileService;
|
||||||
private final DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler;
|
private final DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler;
|
||||||
|
private final AuthorizationContentResolver authorizationContentResolver;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DescriptionServiceImpl(
|
public DescriptionServiceImpl(
|
||||||
|
@ -110,7 +112,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
QueryFactory queryFactory,
|
QueryFactory queryFactory,
|
||||||
JsonHandlingService jsonHandlingService,
|
JsonHandlingService jsonHandlingService,
|
||||||
UserScope userScope,
|
UserScope userScope,
|
||||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler) {
|
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
@ -131,6 +133,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
this.storageFileConfig = storageFileConfig;
|
this.storageFileConfig = storageFileConfig;
|
||||||
this.storageFileService = storageFileService;
|
this.storageFileService = storageFileService;
|
||||||
this.descriptionTouchedIntegrationEventHandler = descriptionTouchedIntegrationEventHandler;
|
this.descriptionTouchedIntegrationEventHandler = descriptionTouchedIntegrationEventHandler;
|
||||||
|
this.authorizationContentResolver = authorizationContentResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Persist
|
//region Persist
|
||||||
|
@ -139,9 +142,10 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
public Description persist(DescriptionPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
|
public Description persist(DescriptionPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
|
||||||
logger.debug(new MapLogEntry("persisting data description").And("model", model).And("fields", fields));
|
logger.debug(new MapLogEntry("persisting data description").And("model", model).And("fields", fields));
|
||||||
|
|
||||||
this.authorizationService.authorizeForce(Permission.EditDescription);
|
|
||||||
|
|
||||||
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
|
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);
|
||||||
|
|
||||||
|
|
||||||
DescriptionEntity data;
|
DescriptionEntity data;
|
||||||
if (isUpdate) {
|
if (isUpdate) {
|
||||||
|
@ -336,13 +340,14 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
public Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException {
|
public Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException {
|
||||||
logger.debug(new MapLogEntry("persisting data dmp").And("model", model).And("fields", fields));
|
logger.debug(new MapLogEntry("persisting data dmp").And("model", model).And("fields", fields));
|
||||||
|
|
||||||
this.authorizationService.authorizeForce(Permission.EditDescription);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription);
|
||||||
|
|
||||||
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
||||||
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (data == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
||||||
if (!data.getStatus().equals(model.getStatus())){
|
if (!data.getStatus().equals(model.getStatus())){
|
||||||
if (data.getStatus().equals(DescriptionStatus.Finalized)){
|
if (data.getStatus().equals(DescriptionStatus.Finalized)){
|
||||||
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
|
||||||
DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, data.getDmpId());
|
DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, data.getDmpId());
|
||||||
if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{data.getDmpId(), DmpEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{data.getDmpId(), DmpEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
if(!dmpEntity.getStatus().equals(DmpStatus.Draft)) throw new MyValidationException(this.errors.getDmpIsFinalized().getCode(), this.errors.getDmpIsFinalized().getMessage());
|
if(!dmpEntity.getStatus().equals(DmpStatus.Draft)) throw new MyValidationException(this.errors.getDmpIsFinalized().getCode(), this.errors.getDmpIsFinalized().getMessage());
|
||||||
|
@ -650,7 +655,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException {
|
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException {
|
||||||
logger.debug("deleting description: {}", id);
|
logger.debug("deleting description: {}", id);
|
||||||
|
|
||||||
this.authorizationService.authorizeForce(Permission.DeleteDescription);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(id)), Permission.DeleteDescription);
|
||||||
|
|
||||||
this.deleterFactory.deleter(DescriptionDeleter.class).deleteAndSaveByIds(List.of(id), false);
|
this.deleterFactory.deleter(DescriptionDeleter.class).deleteAndSaveByIds(List.of(id), false);
|
||||||
}
|
}
|
||||||
|
@ -663,7 +668,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
public void clone(UUID dmpId, UUID descriptionId) throws InvalidApplicationException, IOException {
|
public void clone(UUID dmpId, UUID descriptionId) throws InvalidApplicationException, IOException {
|
||||||
logger.debug("cloning description: {} with description: {}", descriptionId, dmpId);
|
logger.debug("cloning description: {} with description: {}", descriptionId, dmpId);
|
||||||
|
|
||||||
this.authorizationService.authorizeForce(Permission.CloneDescription);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(descriptionId)), Permission.CloneDescription);
|
||||||
|
|
||||||
DescriptionEntity existing = this.queryFactory.query(DescriptionQuery.class).ids(descriptionId).isActive(IsActive.Active).first();
|
DescriptionEntity existing = this.queryFactory.query(DescriptionQuery.class).ids(descriptionId).isActive(IsActive.Active).first();
|
||||||
|
|
||||||
|
@ -743,7 +748,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StorageFile uploadFieldFile(DescriptionFieldFilePersist model, MultipartFile file, FieldSet fields) throws IOException {
|
public StorageFile uploadFieldFile(DescriptionFieldFilePersist model, MultipartFile file, FieldSet fields) throws IOException {
|
||||||
this.authorizationService.authorizeForce(Permission.EditDescription);
|
//this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(descriptionId)), Permission.CloneDescription);
|
||||||
|
this.authorizationService.authorizeForce(Permission.EditDescription);//TODO: Missing Description or dmp for authz
|
||||||
|
|
||||||
DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).ids(model.getDescriptionTemplateId()).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).first();
|
DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).ids(model.getDescriptionTemplateId()).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).first();
|
||||||
if (descriptionTemplate == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (descriptionTemplate == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
@ -783,7 +789,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId) {
|
public StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId) {
|
||||||
this.authorizationService.authorizeForce(Permission.BrowseDescription);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(descriptionId)), Permission.BrowseDescription);
|
||||||
|
|
||||||
DescriptionEntity descriptionEntity = this.queryFactory.query(DescriptionQuery.class).isActive(IsActive.Active).ids(descriptionId).first();
|
DescriptionEntity descriptionEntity = this.queryFactory.query(DescriptionQuery.class).isActive(IsActive.Active).ids(descriptionId).first();
|
||||||
if (descriptionEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (descriptionEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
|
|
@ -132,18 +132,48 @@ permissions:
|
||||||
BrowseDescription:
|
BrowseDescription:
|
||||||
roles:
|
roles:
|
||||||
- Admin
|
- Admin
|
||||||
|
dmp:
|
||||||
|
roles:
|
||||||
|
- Owner
|
||||||
|
- User
|
||||||
|
- DescriptionContributor
|
||||||
|
- Reviewer
|
||||||
clients: [ ]
|
clients: [ ]
|
||||||
allowAnonymous: false
|
allowAnonymous: false
|
||||||
allowAuthenticated: false
|
allowAuthenticated: false
|
||||||
EditDescription:
|
EditDescription:
|
||||||
roles:
|
roles:
|
||||||
- Admin
|
- Admin
|
||||||
|
dmp:
|
||||||
|
roles:
|
||||||
|
- Owner
|
||||||
|
- User
|
||||||
|
- DescriptionContributor
|
||||||
|
- Reviewer
|
||||||
|
clients: [ ]
|
||||||
|
allowAnonymous: false
|
||||||
|
allowAuthenticated: false
|
||||||
|
FinalizeDescription:
|
||||||
|
roles:
|
||||||
|
- Admin
|
||||||
|
dmp:
|
||||||
|
roles:
|
||||||
|
- Owner
|
||||||
|
- User
|
||||||
|
- DescriptionContributor
|
||||||
|
- Reviewer
|
||||||
clients: [ ]
|
clients: [ ]
|
||||||
allowAnonymous: false
|
allowAnonymous: false
|
||||||
allowAuthenticated: false
|
allowAuthenticated: false
|
||||||
DeleteDescription:
|
DeleteDescription:
|
||||||
roles:
|
roles:
|
||||||
- Admin
|
- Admin
|
||||||
|
dmp:
|
||||||
|
roles:
|
||||||
|
- Owner
|
||||||
|
- User
|
||||||
|
- DescriptionContributor
|
||||||
|
- Reviewer
|
||||||
claims: [ ]
|
claims: [ ]
|
||||||
clients: [ ]
|
clients: [ ]
|
||||||
allowAnonymous: false
|
allowAnonymous: false
|
||||||
|
@ -151,11 +181,16 @@ permissions:
|
||||||
CloneDescription:
|
CloneDescription:
|
||||||
roles:
|
roles:
|
||||||
- Admin
|
- Admin
|
||||||
|
dmp:
|
||||||
|
roles:
|
||||||
|
- Owner
|
||||||
|
- User
|
||||||
|
- DescriptionContributor
|
||||||
|
- Reviewer
|
||||||
claims: [ ]
|
claims: [ ]
|
||||||
clients: [ ]
|
clients: [ ]
|
||||||
allowAnonymous: false
|
allowAnonymous: false
|
||||||
allowAuthenticated: false
|
allowAuthenticated: false
|
||||||
|
|
||||||
# Tag
|
# Tag
|
||||||
BrowseTag:
|
BrowseTag:
|
||||||
roles:
|
roles:
|
||||||
|
|
|
@ -10,8 +10,10 @@ export enum AppPermission {
|
||||||
DeleteDmpBlueprint = "DeleteDmpBlueprint",
|
DeleteDmpBlueprint = "DeleteDmpBlueprint",
|
||||||
|
|
||||||
//Description
|
//Description
|
||||||
|
NewDescription = "NewDescription",
|
||||||
BrowseDescription = "BrowseDescription",
|
BrowseDescription = "BrowseDescription",
|
||||||
EditDescription = "EditDescription",
|
EditDescription = "EditDescription",
|
||||||
|
FinalizeDescription = "FinalizeDescription",
|
||||||
DeleteDescription= "DeleteDescription",
|
DeleteDescription= "DeleteDescription",
|
||||||
|
|
||||||
//Dmp
|
//Dmp
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Dmp, DmpDescriptionTemplate, PublicDmp } from "../dmp/dmp";
|
||||||
import { Reference, ReferencePersist } from "../reference/reference";
|
import { Reference, ReferencePersist } from "../reference/reference";
|
||||||
import { Tag } from "../tag/tag";
|
import { Tag } from "../tag/tag";
|
||||||
import { User } from "../user/user";
|
import { User } from "../user/user";
|
||||||
|
import { AppPermission } from "@app/core/common/enum/permission.enum";
|
||||||
|
|
||||||
export interface Description extends BaseEntity {
|
export interface Description extends BaseEntity {
|
||||||
label?: string;
|
label?: string;
|
||||||
|
@ -19,6 +20,7 @@ export interface Description extends BaseEntity {
|
||||||
descriptionTemplate?: DescriptionTemplate;
|
descriptionTemplate?: DescriptionTemplate;
|
||||||
dmpDescriptionTemplate?: DmpDescriptionTemplate;
|
dmpDescriptionTemplate?: DmpDescriptionTemplate;
|
||||||
dmp?: Dmp;
|
dmp?: Dmp;
|
||||||
|
authorizationFlags?: AppPermission[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,24 +78,6 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
step: number = 0;
|
step: number = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected get canDelete(): boolean {
|
|
||||||
return !this.isDeleted && !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get canSave(): boolean {
|
|
||||||
return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get canFinalize(): boolean {
|
|
||||||
return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private hasPermission(permission: AppPermission): boolean {
|
|
||||||
return this.authService.hasPermission(permission) || this.editorModel?.permissions?.includes(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
// BaseFormEditor injected dependencies
|
// BaseFormEditor injected dependencies
|
||||||
protected dialog: MatDialog,
|
protected dialog: MatDialog,
|
||||||
|
@ -606,7 +588,9 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
}
|
}
|
||||||
|
|
||||||
buildForm() {
|
buildForm() {
|
||||||
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditDescription));
|
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.visibilityRulesService.buildVisibilityRules(this.visibilityRulesService.getVisibilityRulesFromDescriptionTempalte(this.item.descriptionTemplate), this.formGroup);
|
||||||
|
|
||||||
// this.selectedSystemFields = this.selectedSystemFieldDisabled();
|
// this.selectedSystemFields = this.selectedSystemFieldDisabled();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||||
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
import { DescriptionTemplate, DescriptionTemplateBaseFieldData, DescriptionTemplateDefinition, DescriptionTemplateExternalDatasetData, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateMultiplicity, DescriptionTemplatePage, DescriptionTemplateReferenceTypeData, DescriptionTemplateRule, DescriptionTemplateSection, DescriptionTemplateSelectData, DescriptionTemplateSelectOption, DescriptionTemplateUploadData, DescriptionTemplateUploadOption } from '@app/core/model/description-template/description-template';
|
import { DescriptionTemplate, DescriptionTemplateBaseFieldData, DescriptionTemplateDefinition, DescriptionTemplateExternalDatasetData, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateMultiplicity, DescriptionTemplatePage, DescriptionTemplateReferenceTypeData, DescriptionTemplateRule, DescriptionTemplateSection, DescriptionTemplateSelectData, DescriptionTemplateSelectOption, DescriptionTemplateUploadData, DescriptionTemplateUploadOption } from '@app/core/model/description-template/description-template';
|
||||||
import { Description, DescriptionExternalIdentifier, DescriptionField, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionReference, DescriptionTag } from '@app/core/model/description/description';
|
import { Description, DescriptionExternalIdentifier, DescriptionField, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionReference, DescriptionTag } from '@app/core/model/description/description';
|
||||||
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
||||||
|
@ -50,6 +51,10 @@ export class DescriptionEditorResolver extends BaseEditorResolver {
|
||||||
nameof<Description>(x => x.description),
|
nameof<Description>(x => x.description),
|
||||||
nameof<Description>(x => x.status),
|
nameof<Description>(x => x.status),
|
||||||
|
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'),
|
||||||
|
|
||||||
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
|
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||||
|
|
||||||
|
@ -124,6 +129,8 @@ export class DescriptionEditorResolver extends BaseEditorResolver {
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.status)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.status)].join('.'),
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.isActive)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.isActive)].join('.'),
|
||||||
|
|
||||||
|
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.authorizationFlags), AppPermission.EditDmp].join('.'),
|
||||||
|
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.id)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.id)].join('.'),
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.isActive)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.isActive)].join('.'),
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition)].join('.'),
|
||||||
|
|
|
@ -21,10 +21,11 @@ const routes: Routes = [
|
||||||
data: {
|
data: {
|
||||||
...BreadcrumbService.generateRouteDataConfiguration({
|
...BreadcrumbService.generateRouteDataConfiguration({
|
||||||
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
|
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
|
||||||
}),
|
})
|
||||||
authContext: {
|
// ,
|
||||||
permissions: [AppPermission.EditDescription]
|
// authContext: {
|
||||||
}
|
// permissions: [AppPermission.EditDescription]
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -55,10 +56,11 @@ const routes: Routes = [
|
||||||
data: {
|
data: {
|
||||||
...BreadcrumbService.generateRouteDataConfiguration({
|
...BreadcrumbService.generateRouteDataConfiguration({
|
||||||
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
|
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
|
||||||
}),
|
})
|
||||||
authContext: {
|
// ,
|
||||||
permissions: [AppPermission.EditDescription]
|
// authContext: {
|
||||||
}
|
// permissions: [AppPermission.EditDescription]
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -72,10 +74,11 @@ const routes: Routes = [
|
||||||
data: {
|
data: {
|
||||||
...BreadcrumbService.generateRouteDataConfiguration({
|
...BreadcrumbService.generateRouteDataConfiguration({
|
||||||
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
|
title: 'BREADCRUMBS.EDIT-DESCRIPTION'
|
||||||
}),
|
})
|
||||||
authContext: {
|
// ,
|
||||||
permissions: [AppPermission.EditDescription]
|
// authContext: {
|
||||||
}
|
// permissions: [AppPermission.EditDescription]
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { MatSort } from '@angular/material/sort';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { DescriptionStatus } from '@app/core/common/enum/description-status';
|
import { DescriptionStatus } from '@app/core/common/enum/description-status';
|
||||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||||
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
|
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
|
||||||
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
|
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
|
||||||
import { Description } from '@app/core/model/description/description';
|
import { Description } from '@app/core/model/description/description';
|
||||||
|
@ -196,6 +197,11 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
|
||||||
nameof<Description>(x => x.label),
|
nameof<Description>(x => x.label),
|
||||||
nameof<Description>(x => x.status),
|
nameof<Description>(x => x.status),
|
||||||
nameof<Description>(x => x.updatedAt),
|
nameof<Description>(x => x.updatedAt),
|
||||||
|
|
||||||
|
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
|
||||||
|
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
<div *ngIf="description.status === descriptionStatusEnum.Finalized" class="col-auto description-title">{{description.label}}</div>
|
<div *ngIf="description.status === descriptionStatusEnum.Finalized" class="col-auto description-title">{{description.label}}</div>
|
||||||
<div *ngIf="description.status === descriptionStatusEnum.Draft" class="col-auto description-title-draft">{{description.label}}</div>
|
<div *ngIf="description.status === descriptionStatusEnum.Draft" class="col-auto description-title-draft">{{description.label}}</div>
|
||||||
<div class="description-subtitle">
|
<div class="description-subtitle">
|
||||||
<span *ngIf="isUserDescriptionRelated()" class="col-auto">{{ enumUtils.toDmpUserRolesString(dmpService.getCurrentUserRolesInDmp(description?.dmp?.dmpUsers)) }}</span>
|
<span *ngIf="canEdit" class="col-auto">{{ enumUtils.toDmpUserRolesString(dmpService.getCurrentUserRolesInDmp(description?.dmp?.dmpUsers)) }}</span>
|
||||||
<span *ngIf="isUserDescriptionRelated()">.</span>
|
<span *ngIf="canEdit">.</span>
|
||||||
<span class="col-auto" *ngIf="description.status === descriptionStatusEnum.Finalized && description.dmp.accessType === dmpAccessTypeEnum.Public"><span class="material-icons icon-align">public</span>{{'DESCRIPTION-LISTING.STATES.PUBLIC' | translate}}</span>
|
<span class="col-auto" *ngIf="description.status === descriptionStatusEnum.Finalized && description.dmp.accessType === dmpAccessTypeEnum.Public"><span class="material-icons icon-align">public</span>{{'DESCRIPTION-LISTING.STATES.PUBLIC' | translate}}</span>
|
||||||
<span *ngIf="description.status === descriptionStatusEnum.Finalized && description.dmp.accessType != dmpAccessTypeEnum.Public" class="col-auto"><span class="material-icons icon-align">done</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span>
|
<span *ngIf="description.status === descriptionStatusEnum.Finalized && description.dmp.accessType != dmpAccessTypeEnum.Public" class="col-auto"><span class="material-icons icon-align">done</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span>
|
||||||
<span *ngIf="description.status === descriptionStatusEnum.Draft" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span>
|
<span *ngIf="description.status === descriptionStatusEnum.Draft" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span>
|
||||||
|
@ -27,13 +27,13 @@
|
||||||
<a class="col-auto border-right pointer" *ngIf="fileTransformerService.availableFormats && fileTransformerService.availableFormats.length > 0" [matMenuTriggerFor]="exportMenu"><span class="material-icons icon-align pr-2">open_in_new</span>{{'DESCRIPTION-LISTING.ACTIONS.EXPORT' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="fileTransformerService.availableFormats && fileTransformerService.availableFormats.length > 0" [matMenuTriggerFor]="exportMenu"><span class="material-icons icon-align pr-2">open_in_new</span>{{'DESCRIPTION-LISTING.ACTIONS.EXPORT' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="isUserOwner" (click)="openShareDialog(description.dmp.id, description.dmp.label)"><span class="material-icons icon-align pr-2">group_add</span>{{'DESCRIPTION-LISTING.ACTIONS.INVITE-SHORT' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="isUserOwner" (click)="openShareDialog(description.dmp.id, description.dmp.label)"><span class="material-icons icon-align pr-2">group_add</span>{{'DESCRIPTION-LISTING.ACTIONS.INVITE-SHORT' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="isAuthenticated()" (click)="copyToDmp(description)"><span class="material-icons icon-align pr-2">file_copy</span>{{'DESCRIPTION-LISTING.ACTIONS.COPY-DESCRIPTION' | translate}}</a>
|
<a class="col-auto border-right pointer" *ngIf="isAuthenticated()" (click)="copyToDmp(description)"><span class="material-icons icon-align pr-2">file_copy</span>{{'DESCRIPTION-LISTING.ACTIONS.COPY-DESCRIPTION' | translate}}</a>
|
||||||
<a class="col-auto border-right pointer" *ngIf="isAuthenticated() && isUserDescriptionRelated()" (click)="deleteClicked(description.id)"><span class="material-icons icon-align pr-2">delete</span>{{ 'DESCRIPTION-LISTING.ACTIONS.DELETE' | translate }}</a>
|
<a class="col-auto border-right pointer" *ngIf="canDelete" (click)="deleteClicked(description.id)"><span class="material-icons icon-align pr-2">delete</span>{{ 'DESCRIPTION-LISTING.ACTIONS.DELETE' | translate }}</a>
|
||||||
</div>
|
</div>
|
||||||
<mat-menu #actionsMenu="matMenu">
|
<mat-menu #actionsMenu="matMenu">
|
||||||
<button *ngIf="isAuthenticated()" mat-menu-item (click)="copyToDmp(description)" class="menu-item">
|
<button *ngIf="isAuthenticated()" mat-menu-item (click)="copyToDmp(description)" class="menu-item">
|
||||||
<mat-icon>file_copy</mat-icon>{{'DESCRIPTION-LISTING.ACTIONS.COPY-DESCRIPTION' | translate}}
|
<mat-icon>file_copy</mat-icon>{{'DESCRIPTION-LISTING.ACTIONS.COPY-DESCRIPTION' | translate}}
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="isUserDescriptionRelated()" mat-menu-item (click)="deleteClicked(description.id)" class="menu-item">
|
<button *ngIf="canDelete" mat-menu-item (click)="deleteClicked(description.id)" class="menu-item">
|
||||||
<mat-icon>delete</mat-icon>{{ 'DESCRIPTION-LISTING.ACTIONS.DELETE' | translate }}
|
<mat-icon>delete</mat-icon>{{ 'DESCRIPTION-LISTING.ACTIONS.DELETE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
|
@ -26,6 +26,7 @@ import * as FileSaver from 'file-saver';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { DescriptionStatus } from '../../../../core/common/enum/description-status';
|
import { DescriptionStatus } from '../../../../core/common/enum/description-status';
|
||||||
import { DescriptionCopyDialogComponent } from '../../description-copy-dialog/description-copy-dialog.component';
|
import { DescriptionCopyDialogComponent } from '../../description-copy-dialog/description-copy-dialog.component';
|
||||||
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-description-listing-item-component',
|
selector: 'app-description-listing-item-component',
|
||||||
|
@ -44,6 +45,8 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
|
||||||
isUserOwner: boolean;
|
isUserOwner: boolean;
|
||||||
descriptionStatusEnum = DescriptionStatus;
|
descriptionStatusEnum = DescriptionStatus;
|
||||||
dmpAccessTypeEnum = DmpAccessType;
|
dmpAccessTypeEnum = DmpAccessType;
|
||||||
|
canDelete: boolean = false;
|
||||||
|
canEdit: boolean = false;
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -80,6 +83,13 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
|
||||||
this.isDeleted = false;
|
this.isDeleted = false;
|
||||||
this.setIsUserOwner();
|
this.setIsUserOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.canDelete = this.authService.hasPermission(AppPermission.DeleteDescription) ||
|
||||||
|
this.description.authorizationFlags?.some(x => x === AppPermission.DeleteDescription);
|
||||||
|
|
||||||
|
this.canEdit = this.authService.hasPermission(AppPermission.EditDescription) ||
|
||||||
|
this.description.authorizationFlags?.some(x => x === AppPermission.EditDescription);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsUserOwner() {
|
setIsUserOwner() {
|
||||||
|
@ -240,11 +250,4 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
|
||||||
onDeleteCallbackError(error) {
|
onDeleteCallbackError(error) {
|
||||||
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
|
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
isUserDescriptionRelated(): boolean {
|
|
||||||
const principalId: Guid = this.authService.userId();
|
|
||||||
return this.description.dmp.dmpUsers.some(x => (x.user.id === principalId));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
<p class="col description-label p-0 ml-3 mb-0">{{ description.label }}</p>
|
<p class="col description-label p-0 ml-3 mb-0">{{ description.label }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="row d-flex align-items-center mt-3 mb-4 label-txt">
|
<div class="row d-flex align-items-center mt-3 mb-4 label-txt">
|
||||||
<div *ngIf="isUserDescriptionRelated()" class="d-flex">
|
<div *ngIf="canEdit" class="d-flex">
|
||||||
<p class="ml-0 mb-0 label2-txt">
|
<p class="ml-0 mb-0 label2-txt">
|
||||||
{{ enumUtils.toDmpUserRolesString(dmpService.getCurrentUserRolesInDmp(description?.dmp?.dmpUsers)) }}
|
{{ enumUtils.toDmpUserRolesString(dmpService.getCurrentUserRolesInDmp(description?.dmp?.dmpUsers)) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<span *ngIf="isUserDescriptionRelated()" class="ml-2 mr-2">.</span>
|
<span *ngIf="canEdit" class="ml-2 mr-2">.</span>
|
||||||
<div *ngIf="description.status === descriptionStatusEnum.Finalized && description.dmp.accessType === dmpAccessTypeEnum.Public" class="d-flex flex-row">
|
<div *ngIf="description.status === descriptionStatusEnum.Finalized && description.dmp.accessType === dmpAccessTypeEnum.Public" class="d-flex flex-row">
|
||||||
<mat-icon class="status-icon">public</mat-icon>
|
<mat-icon class="status-icon">public</mat-icon>
|
||||||
{{'DESCRIPTION-OVERVIEW.PUBLIC' | translate}}
|
{{'DESCRIPTION-OVERVIEW.PUBLIC' | translate}}
|
||||||
|
@ -39,13 +39,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-4 pb-3">
|
<div class="row mb-4 pb-3">
|
||||||
<button *ngIf="isDraftDescription(description) && !lockStatus" (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
|
<button *ngIf="canEdit && isDraftDescription(description) && !lockStatus" (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
|
||||||
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="isAuthenticated()" (click)="openCopyToDmpDialog()" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.CLONE' | translate}}" matTooltipPosition="above">
|
<button *ngIf="canEdit" (click)="openCopyToDmpDialog()" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.CLONE' | translate}}" matTooltipPosition="above">
|
||||||
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
|
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="isUserDescriptionRelated() && !lockStatus" (click)="deleteClicked()" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.DELETE' | translate}}" matTooltipPosition="above">
|
<button *ngIf="canDelete && !lockStatus" (click)="deleteClicked()" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.DELETE' | translate}}" matTooltipPosition="above">
|
||||||
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
|
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,7 +92,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 col-lg-4 p-0">
|
<div class="col-md-4 col-lg-4 p-0">
|
||||||
<div class="frame mb-3 pt-4 pl-3 pr-5 pb-1" *ngIf="isAuthenticated()">
|
<div class="frame mb-3 pt-4 pl-3 pr-5 pb-1" *ngIf="isAuthenticated()">
|
||||||
<div *ngIf="isDraftDescription(description) && !lockStatus">
|
<div *ngIf="canFinalize && isDraftDescription(description) && !lockStatus">
|
||||||
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(description)">
|
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(description)">
|
||||||
<button mat-mini-fab class="finalize-btn">
|
<button mat-mini-fab class="finalize-btn">
|
||||||
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
||||||
|
@ -141,10 +141,10 @@
|
||||||
<p class="authors-role">{{ enumUtils.toDmpUserRoleString(dmpUser.role) }}</p>
|
<p class="authors-role">{{ enumUtils.toDmpUserRoleString(dmpUser.role) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button *ngIf="isUserOwner && description.dmp?.status === dmpStatusEnum.Draft && dmpUser.role === dmpUserRoleEnum.Owner" (click)="removeUserFromDmp(dmpUser)" class="remove-btn">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}</button>
|
<button *ngIf="canInviteDmpUsers && description.dmp?.status === dmpStatusEnum.Draft && dmpUser.role === dmpUserRoleEnum.Owner" (click)="removeUserFromDmp(dmpUser)" class="remove-btn">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isUserOwner" class="row mt-3 mb-3 d-flex align-items-center justify-content-center">
|
<div *ngIf="canInviteDmpUsers" class="row mt-3 mb-3 d-flex align-items-center justify-content-center">
|
||||||
<button mat-raised-button class="invite-btn" (click)="openShareDialog(description.dmp.id, description.dmp.label)">
|
<button mat-raised-button class="invite-btn" (click)="openShareDialog(description.dmp.id, description.dmp.label)">
|
||||||
<mat-icon>group_add</mat-icon>
|
<mat-icon>group_add</mat-icon>
|
||||||
{{'DESCRIPTION-OVERVIEW.ACTIONS.INVITE-SHORT' | translate}}
|
{{'DESCRIPTION-OVERVIEW.ACTIONS.INVITE-SHORT' | translate}}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import { filter, takeUntil } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
|
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
|
||||||
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
|
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
|
||||||
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -49,7 +50,6 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
isPublicView = true;
|
isPublicView = true;
|
||||||
hasPublishButton: boolean = true;
|
hasPublishButton: boolean = true;
|
||||||
// breadCrumbs: Observable<BreadcrumbItem[]> = observableOf();
|
// breadCrumbs: Observable<BreadcrumbItem[]> = observableOf();
|
||||||
isUserOwner: boolean;
|
|
||||||
expand = false;
|
expand = false;
|
||||||
lockStatus: Boolean;
|
lockStatus: Boolean;
|
||||||
descriptionStatusEnum = DescriptionStatus;
|
descriptionStatusEnum = DescriptionStatus;
|
||||||
|
@ -57,6 +57,11 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
dmpStatusEnum = DmpStatus;
|
dmpStatusEnum = DmpStatus;
|
||||||
dmpUserRoleEnum = DmpUserRole;
|
dmpUserRoleEnum = DmpUserRole;
|
||||||
|
|
||||||
|
canEdit = false;
|
||||||
|
canDelete = false;
|
||||||
|
canFinalize = false;
|
||||||
|
canInviteDmpUsers = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
@ -72,6 +77,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
public enumUtils: EnumUtils,
|
public enumUtils: EnumUtils,
|
||||||
private matomoService: MatomoService,
|
private matomoService: MatomoService,
|
||||||
private fileUtils: FileUtils,
|
private fileUtils: FileUtils,
|
||||||
|
private authService: AuthService,
|
||||||
public fileTransformerService: FileTransformerService,
|
public fileTransformerService: FileTransformerService,
|
||||||
private referenceTypeService: ReferenceTypeService,
|
private referenceTypeService: ReferenceTypeService,
|
||||||
private fb: UntypedFormBuilder,
|
private fb: UntypedFormBuilder,
|
||||||
|
@ -81,6 +87,10 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.matomoService.trackPageView('Description Overview');
|
this.matomoService.trackPageView('Description Overview');
|
||||||
|
this.canDelete = false;
|
||||||
|
this.canEdit = false;
|
||||||
|
this.canFinalize = false;
|
||||||
|
this.canInviteDmpUsers = false;
|
||||||
// Gets description data using parameter id
|
// Gets description data using parameter id
|
||||||
this.route.params
|
this.route.params
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
|
@ -97,11 +107,22 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
this.researchers = this.referenceService.getReferencesForTypes(this.description?.dmp?.dmpReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
this.researchers = this.referenceService.getReferencesForTypes(this.description?.dmp?.dmpReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
||||||
// this.users = this.description.dmp.users;
|
// this.users = this.description.dmp.users;
|
||||||
this.checkLockStatus(this.description.id);
|
this.checkLockStatus(this.description.id);
|
||||||
this.setIsUserOwner();
|
this.canDelete = this.authService.hasPermission(AppPermission.DeleteDescription) ||
|
||||||
|
this.description.authorizationFlags?.some(x => x === AppPermission.DeleteDescription);
|
||||||
|
|
||||||
|
this.canEdit = this.authService.hasPermission(AppPermission.EditDescription) ||
|
||||||
|
this.description.authorizationFlags?.some(x => x === AppPermission.EditDescription);
|
||||||
|
|
||||||
|
this.canFinalize = this.authService.hasPermission(AppPermission.FinalizeDescription) ||
|
||||||
|
this.description.authorizationFlags?.some(x => x === AppPermission.FinalizeDescription);
|
||||||
|
|
||||||
|
this.canInviteDmpUsers = this.authService.hasPermission(AppPermission.InviteDmpUsers) ||
|
||||||
|
this.description.dmp?.authorizationFlags?.some(x => x === AppPermission.InviteDmpUsers);
|
||||||
// const breadCrumbs = [];
|
// const breadCrumbs = [];
|
||||||
// breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DESCRIPTION-DESCRIPTIONS'), url: "/descriptions" });
|
// breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DESCRIPTION-DESCRIPTIONS'), url: "/descriptions" });
|
||||||
// breadCrumbs.push({ parentComponentName: 'DescriptionListingComponent', label: this.description.label, url: '/descriptions/overview/' + this.description.id });
|
// breadCrumbs.push({ parentComponentName: 'DescriptionListingComponent', label: this.description.label, url: '/descriptions/overview/' + this.description.id });
|
||||||
// this.breadCrumbs = observableOf(breadCrumbs);
|
// this.breadCrumbs = observableOf(breadCrumbs);
|
||||||
|
|
||||||
}, (error: any) => {
|
}, (error: any) => {
|
||||||
if (error.status === 404) {
|
if (error.status === 404) {
|
||||||
return this.onFetchingDeletedCallbackError('/descriptions/');
|
return this.onFetchingDeletedCallbackError('/descriptions/');
|
||||||
|
@ -172,12 +193,6 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
this.router.navigateByUrl('/reload', { skipLocationChange: true }).then(() => this.router.navigate([path]));
|
this.router.navigateByUrl('/reload', { skipLocationChange: true }).then(() => this.router.navigate([path]));
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsUserOwner() {
|
|
||||||
if (this.description) {
|
|
||||||
const principalId: Guid = this.authentication.userId();
|
|
||||||
if (principalId) this.isUserOwner = !!this.description.dmp.dmpUsers.find(x => (x.role === DmpUserRole.Owner) && (principalId === x.id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isUserAuthor(userId: Guid): boolean {
|
isUserAuthor(userId: Guid): boolean {
|
||||||
if (this.isAuthenticated()) {
|
if (this.isAuthenticated()) {
|
||||||
|
@ -186,11 +201,6 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isUserDescriptionRelated(): boolean {
|
|
||||||
const principalId: Guid = this.authentication.userId();
|
|
||||||
return this.description.dmp.dmpUsers.some(x => (x.user.id === principalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
openShareDialog(rowId: any, rowName: any) {
|
openShareDialog(rowId: any, rowName: any) {
|
||||||
// TODO: add dialog
|
// TODO: add dialog
|
||||||
|
@ -439,6 +449,11 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
nameof<Description>(x => x.status),
|
nameof<Description>(x => x.status),
|
||||||
nameof<Description>(x => x.updatedAt),
|
nameof<Description>(x => x.updatedAt),
|
||||||
nameof<Description>(x => x.hash),
|
nameof<Description>(x => x.hash),
|
||||||
|
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
|
||||||
|
[nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'),
|
||||||
|
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
||||||
|
@ -449,6 +464,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.label)].join('.'),
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.label)].join('.'),
|
||||||
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.accessType)].join('.'),
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.accessType)].join('.'),
|
||||||
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.status)].join('.'),
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.status)].join('.'),
|
||||||
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.authorizationFlags),AppPermission.InviteDmpUsers].join('.'),
|
||||||
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.id)].join('.'),
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.id)].join('.'),
|
||||||
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.name)].join('.'),
|
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.name)].join('.'),
|
||||||
|
|
|
@ -82,20 +82,20 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
|
||||||
};
|
};
|
||||||
|
|
||||||
protected get canDelete(): boolean {
|
protected get canDelete(): boolean {
|
||||||
return !this.isDeleted && !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteDmp);
|
return !this.isDeleted && !this.isNew && (this.hasPermission(this.authService.permissionEnum.DeleteDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.DeleteDmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get canSave(): boolean {
|
protected get canSave(): boolean {
|
||||||
return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditDmp);
|
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get canFinalize(): boolean {
|
protected get canFinalize(): boolean {
|
||||||
return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditDmp);
|
return !this.isDeleted && (this.hasPermission(this.authService.permissionEnum.EditDmp) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private hasPermission(permission: AppPermission): boolean {
|
private hasPermission(permission: AppPermission): boolean {
|
||||||
return this.authService.hasPermission(permission) || this.editorModel?.permissions?.includes(permission);
|
return this.authService.hasPermission(permission) || this.item?.authorizationFlags?.some(x => x === permission) || this.editorModel?.permissions?.includes(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -40,6 +40,7 @@ export class DmpEditorResolver extends BaseEditorResolver {
|
||||||
nameof<Dmp>(x => x.hash),
|
nameof<Dmp>(x => x.hash),
|
||||||
|
|
||||||
[nameof<Dmp>(x => x.authorizationFlags), AppPermission.EditDmp].join('.'),
|
[nameof<Dmp>(x => x.authorizationFlags), AppPermission.EditDmp].join('.'),
|
||||||
|
[nameof<Dmp>(x => x.authorizationFlags), AppPermission.DeleteDmp].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.fieldId)].join('.'),
|
||||||
[nameof<Dmp>(x => x.properties), nameof<DmpProperties>(x => x.dmpBlueprintValues), nameof<DmpBlueprintValue>(x => x.fieldValue)].join('.'),
|
[nameof<Dmp>(x => x.properties), nameof<DmpProperties>(x => x.dmpBlueprintValues), nameof<DmpBlueprintValue>(x => x.fieldValue)].join('.'),
|
||||||
|
|
Loading…
Reference in New Issue