status authz changes
This commit is contained in:
parent
ff52d32d32
commit
fcacf93024
|
@ -0,0 +1,24 @@
|
|||
package org.opencdmp.event;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class DescriptionStatusTouchedEvent {
|
||||
|
||||
public DescriptionStatusTouchedEvent() {
|
||||
}
|
||||
|
||||
public DescriptionStatusTouchedEvent(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private UUID id;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
|
@ -57,6 +57,10 @@ public class EventBroker {
|
|||
this.applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
|
||||
public void emit(DescriptionStatusTouchedEvent event) {
|
||||
this.applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
|
||||
public void emit(TagTouchedEvent event) {
|
||||
this.applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
|
|
|
@ -200,6 +200,8 @@ public class DescriptionStatusQuery extends QueryBase<DescriptionStatusEntity> {
|
|||
return DescriptionStatusEntity._tenantId;
|
||||
else if (item.match(DescriptionStatus._internalStatus))
|
||||
return DescriptionStatusEntity._internalStatus;
|
||||
else if (item.match(DescriptionStatusEntity._definition))
|
||||
return DescriptionStatusEntity._definition;
|
||||
else if (item.prefix(DescriptionStatusEntity._definition))
|
||||
return DescriptionStatusEntity._definition;
|
||||
else
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package org.opencdmp.service.custompolicy;
|
||||
|
||||
|
||||
import gr.cite.tools.cache.CacheOptions;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "cache.custom-policy-by-tenant")
|
||||
public class CustomPolicyCacheOptions extends CacheOptions {
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package org.opencdmp.service.custompolicy;
|
||||
|
||||
|
||||
import gr.cite.tools.cache.CacheService;
|
||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
|
||||
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class CustomPolicyCacheService extends CacheService<CustomPolicyCacheService.CustomPolicyCacheValue> {
|
||||
|
||||
public static class CustomPolicyCacheValue {
|
||||
|
||||
public CustomPolicyCacheValue() {}
|
||||
|
||||
|
||||
public CustomPolicyCacheValue(String tenantCode, Map<UUID, PlanStatusDefinitionEntity> planStatusDefinitionMap, Map<UUID, DescriptionStatusDefinitionEntity> descriptionStatusDefinitionMap) {
|
||||
this.tenantCode = tenantCode;
|
||||
this.planStatusDefinitionMap = planStatusDefinitionMap;
|
||||
this.descriptionStatusDefinitionMap = descriptionStatusDefinitionMap;
|
||||
}
|
||||
|
||||
private String tenantCode;
|
||||
private Map<UUID, PlanStatusDefinitionEntity> planStatusDefinitionMap;
|
||||
private Map<UUID, DescriptionStatusDefinitionEntity> descriptionStatusDefinitionMap;
|
||||
|
||||
public String getTenantCode() {
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
public void setTenantCode(String tenantCode) {
|
||||
this.tenantCode = tenantCode;
|
||||
}
|
||||
|
||||
public Map<UUID, PlanStatusDefinitionEntity> getPlanStatusDefinitionMap() {
|
||||
return planStatusDefinitionMap;
|
||||
}
|
||||
|
||||
public void setPlanStatusDefinitionMap(Map<UUID, PlanStatusDefinitionEntity> planStatusDefinitionMap) {
|
||||
this.planStatusDefinitionMap = planStatusDefinitionMap;
|
||||
}
|
||||
|
||||
public Map<UUID, DescriptionStatusDefinitionEntity> getDescriptionStatusDefinitionMap() {
|
||||
return descriptionStatusDefinitionMap;
|
||||
}
|
||||
|
||||
public void setDescriptionStatusDefinitionMap(Map<UUID, DescriptionStatusDefinitionEntity> descriptionStatusDefinitionMap) {
|
||||
this.descriptionStatusDefinitionMap = descriptionStatusDefinitionMap;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public CustomPolicyCacheService(CustomPolicyCacheOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<CustomPolicyCacheValue> valueClass() {return CustomPolicyCacheValue.class;}
|
||||
|
||||
|
||||
public String keyOf(CustomPolicyCacheValue value) {
|
||||
return this.buildKey(value.getTenantCode());
|
||||
}
|
||||
|
||||
public String buildKey(String tenantCode) {
|
||||
HashMap<String, String> keyParts = new HashMap<>();
|
||||
keyParts.put("$tenantCode$", tenantCode);
|
||||
return this.generateKey(keyParts);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.opencdmp.service.custompolicy;
|
||||
|
||||
|
||||
import gr.cite.commons.web.authz.configuration.Permission;
|
||||
import org.opencdmp.commons.enums.PlanUserRole;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface CustomPolicyService {
|
||||
|
||||
HashMap<String, Permission> buildPlanStatusPolicies();
|
||||
|
||||
String getPlanStatusCanEditStatusPermission(UUID id);
|
||||
|
||||
HashMap<String, Permission> buildDescriptionStatusPolicies();
|
||||
|
||||
String getDescriptionStatusCanEditStatusPermission(UUID id);
|
||||
|
||||
String getPlanStatusCanEditStatusAffiliatedPermission(UUID id, PlanUserRole planUserRole);
|
||||
|
||||
String getDescriptionStatusCanEditStatusAffiliatedPermission(UUID id, PlanUserRole planUserRole);
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package org.opencdmp.service.custompolicy;
|
||||
|
||||
import gr.cite.commons.web.authz.configuration.Permission;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.opencdmp.commons.XmlHandlingService;
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.commons.enums.PlanUserRole;
|
||||
import org.opencdmp.commons.scope.tenant.TenantScope;
|
||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
|
||||
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
|
||||
import org.opencdmp.data.DescriptionStatusEntity;
|
||||
import org.opencdmp.data.PlanStatusEntity;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatusDefinitionAuthorization;
|
||||
import org.opencdmp.model.planstatus.PlanStatus;
|
||||
import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
|
||||
import org.opencdmp.query.DescriptionStatusQuery;
|
||||
import org.opencdmp.query.PlanStatusQuery;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class CustomPolicyServiceImpl implements CustomPolicyService{
|
||||
private final QueryFactory queryFactory;
|
||||
private final XmlHandlingService xmlHandlingService;
|
||||
private final TenantScope tenantScope;
|
||||
private final CustomPolicyCacheService customPolicyCacheService;
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(CustomPolicyServiceImpl.class));
|
||||
|
||||
public CustomPolicyServiceImpl(QueryFactory queryFactory, XmlHandlingService xmlHandlingService, TenantScope tenantScope, CustomPolicyCacheService customPolicyCacheService) {
|
||||
this.queryFactory = queryFactory;
|
||||
this.xmlHandlingService = xmlHandlingService;
|
||||
this.tenantScope = tenantScope;
|
||||
this.customPolicyCacheService = customPolicyCacheService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, Permission> buildPlanStatusPolicies() {
|
||||
HashMap<String, Permission> policies = new HashMap<>();
|
||||
String tenantCode = null;
|
||||
try {
|
||||
tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : "";
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CustomPolicyCacheService.CustomPolicyCacheValue cacheValue = this.customPolicyCacheService.lookup(this.customPolicyCacheService.buildKey(tenantCode));
|
||||
if (cacheValue == null || cacheValue.getPlanStatusDefinitionMap() == null) {
|
||||
Map<UUID, PlanStatusDefinitionEntity> definitionStatusMap = new HashMap<>();
|
||||
List<PlanStatusEntity> entities = this.queryFactory.query(PlanStatusQuery.class).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanStatus._id).ensure(PlanStatus._definition));
|
||||
for (PlanStatusEntity entity: entities) {
|
||||
PlanStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(PlanStatusDefinitionEntity.class, entity.getDefinition());
|
||||
if (definition != null) {
|
||||
definitionStatusMap.put(entity.getId(), definition);
|
||||
if (definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
|
||||
policies.put(this.getPlanStatusCanEditStatusPermission(entity.getId()), new Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cacheValue != null && cacheValue.getDescriptionStatusDefinitionMap() != null) {
|
||||
cacheValue = new CustomPolicyCacheService.CustomPolicyCacheValue(tenantCode, definitionStatusMap, cacheValue.getDescriptionStatusDefinitionMap());
|
||||
} else {
|
||||
cacheValue = new CustomPolicyCacheService.CustomPolicyCacheValue(tenantCode, definitionStatusMap, null);
|
||||
}
|
||||
this.customPolicyCacheService.put(cacheValue);
|
||||
} else {
|
||||
for (UUID statusId: cacheValue.getPlanStatusDefinitionMap().keySet()) {
|
||||
PlanStatusDefinitionEntity definition = cacheValue.getPlanStatusDefinitionMap().get(statusId);
|
||||
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
|
||||
policies.put(this.getPlanStatusCanEditStatusPermission(statusId), new Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return policies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, Permission> buildDescriptionStatusPolicies(){
|
||||
HashMap<String, Permission> policies = new HashMap<>();
|
||||
String tenantCode = null;
|
||||
try {
|
||||
tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : "";
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CustomPolicyCacheService.CustomPolicyCacheValue cacheValue = this.customPolicyCacheService.lookup(this.customPolicyCacheService.buildKey(tenantCode));
|
||||
if (cacheValue == null || cacheValue.getDescriptionStatusDefinitionMap() == null) {
|
||||
Map<UUID, DescriptionStatusDefinitionEntity> definitionStatusMap = new HashMap<>();
|
||||
List<DescriptionStatusEntity> entities = this.queryFactory.query(DescriptionStatusQuery.class).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(DescriptionStatus._id).ensure(DescriptionStatus._definition));
|
||||
for (DescriptionStatusEntity entity : entities) {
|
||||
DescriptionStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionStatusDefinitionEntity.class, entity.getDefinition());
|
||||
if (definition != null) {
|
||||
definitionStatusMap.put(entity.getId(), definition);
|
||||
if (definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
|
||||
policies.put(this.getDescriptionStatusCanEditStatusPermission(entity.getId()), new Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cacheValue != null && cacheValue.getPlanStatusDefinitionMap() != null) {
|
||||
cacheValue = new CustomPolicyCacheService.CustomPolicyCacheValue(tenantCode, cacheValue.getPlanStatusDefinitionMap(), definitionStatusMap);
|
||||
} else {
|
||||
cacheValue = new CustomPolicyCacheService.CustomPolicyCacheValue(tenantCode, null, definitionStatusMap);
|
||||
}
|
||||
this.customPolicyCacheService.put(cacheValue);
|
||||
} else {
|
||||
for (UUID statusId: cacheValue.getDescriptionStatusDefinitionMap().keySet()) {
|
||||
DescriptionStatusDefinitionEntity definition = cacheValue.getDescriptionStatusDefinitionMap().get(statusId);
|
||||
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
|
||||
policies.put(this.getDescriptionStatusCanEditStatusPermission(statusId), new Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return policies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlanStatusCanEditStatusPermission(UUID id){
|
||||
return "PlanStatus" + "_" + id + "_" + PlanStatusDefinitionAuthorization._edit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescriptionStatusCanEditStatusPermission(UUID id){
|
||||
return "DescriptionStatus" + "_" + id + "_" + DescriptionStatusDefinitionAuthorization._edit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlanStatusCanEditStatusAffiliatedPermission(UUID id, PlanUserRole planUserRole){
|
||||
return "PlanStatus" + "_" + id + "_" + planUserRole.name() + "_" + PlanStatusDefinitionAuthorization._edit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescriptionStatusCanEditStatusAffiliatedPermission(UUID id, PlanUserRole planUserRole){
|
||||
return "DescriptionStatus" + "_" + id + "_" + planUserRole.name() + "_" + DescriptionStatusDefinitionAuthorization._edit;
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@ import org.opencdmp.model.reference.Reference;
|
|||
import org.opencdmp.model.referencetype.ReferenceType;
|
||||
import org.opencdmp.query.*;
|
||||
import org.opencdmp.service.accounting.AccountingService;
|
||||
import org.opencdmp.service.custompolicy.CustomPolicyService;
|
||||
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
||||
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||
import org.opencdmp.service.elastic.ElasticService;
|
||||
|
@ -144,6 +145,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
private final UsageLimitService usageLimitService;
|
||||
private final AccountingService accountingService;
|
||||
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||
private final CustomPolicyService customPolicyService;
|
||||
|
||||
@Autowired
|
||||
public DescriptionServiceImpl(
|
||||
|
@ -158,7 +160,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
QueryFactory queryFactory,
|
||||
JsonHandlingService jsonHandlingService,
|
||||
UserScope userScope,
|
||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService) {
|
||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService, CustomPolicyService customPolicyService) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -188,6 +190,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
this.usageLimitService = usageLimitService;
|
||||
this.accountingService = accountingService;
|
||||
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||
this.customPolicyService = customPolicyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -499,8 +502,16 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
|
||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription);
|
||||
|
||||
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
||||
DescriptionEntity data = this.queryFactory.query(DescriptionQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(model.getId()).isActive(IsActive.Active).first();
|
||||
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
try {
|
||||
this.authorizationService.authorizeForce(this.customPolicyService.getDescriptionStatusCanEditStatusPermission(model.getStatusId()));
|
||||
} catch (Exception e) {
|
||||
PlanUserEntity planUserEntity = this.queryFactory.query(PlanUserQuery.class).planIds(data.getPlanId()).userIds(this.userScope.getUserId()).isActives(IsActive.Active).firstAs(new BaseFieldSet().ensure(PlanUser._role));
|
||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(data.getPlanId())), this.customPolicyService.getDescriptionStatusCanEditStatusAffiliatedPermission(model.getStatusId(), planUserEntity.getRole()));
|
||||
}
|
||||
|
||||
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
||||
if (!data.getStatusId().equals(model.getStatusId())){
|
||||
DescriptionStatusEntity oldStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(data.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
|
||||
|
|
|
@ -26,6 +26,9 @@ import org.opencdmp.convention.ConventionService;
|
|||
import org.opencdmp.data.DescriptionEntity;
|
||||
import org.opencdmp.data.DescriptionStatusEntity;
|
||||
import org.opencdmp.data.TenantEntityManager;
|
||||
import org.opencdmp.event.DescriptionStatusTouchedEvent;
|
||||
import org.opencdmp.event.EventBroker;
|
||||
import org.opencdmp.event.PlanStatusTouchedEvent;
|
||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||
import org.opencdmp.model.deleter.DescriptionStatusDeleter;
|
||||
import org.opencdmp.model.description.Description;
|
||||
|
@ -63,8 +66,9 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
|||
private final XmlHandlingService xmlHandlingService;
|
||||
private final QueryFactory queryFactory;
|
||||
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||
private final EventBroker eventBroker;
|
||||
|
||||
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, QueryFactory queryFactory, DescriptionWorkflowService descriptionWorkflowService) {
|
||||
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, QueryFactory queryFactory, DescriptionWorkflowService descriptionWorkflowService, EventBroker eventBroker) {
|
||||
this.builderFactory = builderFactory;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
||||
|
@ -75,6 +79,7 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
|||
this.xmlHandlingService = xmlHandlingService;
|
||||
this.queryFactory = queryFactory;
|
||||
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||
this.eventBroker = eventBroker;
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,6 +117,8 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
|||
|
||||
this.entityManager.flush();
|
||||
|
||||
this.eventBroker.emit(new DescriptionStatusTouchedEvent(data.getId()));
|
||||
|
||||
return this.builderFactory.builder(DescriptionStatusBuilder.class).build(BaseFieldSet.build(fields, DescriptionStatus._id), data);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ import org.opencdmp.model.referencetype.ReferenceType;
|
|||
import org.opencdmp.query.*;
|
||||
import org.opencdmp.service.accounting.AccountingService;
|
||||
import org.opencdmp.service.actionconfirmation.ActionConfirmationService;
|
||||
import org.opencdmp.service.custompolicy.CustomPolicyService;
|
||||
import org.opencdmp.service.description.DescriptionService;
|
||||
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
||||
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||
|
@ -187,6 +188,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
private final AccountingService accountingService;
|
||||
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||
private final PlanWorkflowServiceImpl planWorkflowService;
|
||||
private final CustomPolicyService customPolicyService;
|
||||
|
||||
@Autowired
|
||||
public PlanServiceImpl(
|
||||
|
@ -209,7 +211,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
FileTransformerService fileTransformerService,
|
||||
ValidatorFactory validatorFactory,
|
||||
ElasticService elasticService, DescriptionTemplateService descriptionTemplateService,
|
||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService, PlanWorkflowServiceImpl planWorkflowService) {
|
||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService, PlanWorkflowServiceImpl planWorkflowService, CustomPolicyService customPolicyService) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -240,6 +242,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
this.accountingService = accountingService;
|
||||
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||
this.planWorkflowService = planWorkflowService;
|
||||
this.customPolicyService = customPolicyService;
|
||||
}
|
||||
|
||||
public Plan persist(PlanPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
|
||||
|
@ -1610,6 +1613,14 @@ public class PlanServiceImpl implements PlanService {
|
|||
public void setStatus(UUID id, UUID newStatusId, List<UUID> descriptionIds) throws InvalidApplicationException, IOException {
|
||||
PlanEntity plan = this.queryFactory.query(PlanQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(id).isActive(IsActive.Active).first();
|
||||
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
try {
|
||||
this.authorizationService.authorizeForce(this.customPolicyService.getPlanStatusCanEditStatusPermission(newStatusId));
|
||||
} catch (Exception e) {
|
||||
PlanUserEntity planUserEntity = this.queryFactory.query(PlanUserQuery.class).planIds(id).userIds(this.userScope.getUserId()).isActives(IsActive.Active).firstAs(new BaseFieldSet().ensure(PlanUser._role));
|
||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(id)), this.customPolicyService.getPlanStatusCanEditStatusAffiliatedPermission(newStatusId, planUserEntity.getRole()));
|
||||
}
|
||||
|
||||
if (plan.getStatusId().equals(newStatusId)) throw new MyApplicationException("Old status equals with new");
|
||||
|
||||
PlanStatusEntity oldPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, plan.getStatusId(), true);
|
||||
|
|
|
@ -6,19 +6,23 @@ import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
|
|||
import gr.cite.commons.web.oidc.principal.MyPrincipal;
|
||||
import org.opencdmp.commons.enums.PlanUserRole;
|
||||
import org.opencdmp.commons.enums.UserDescriptionTemplateRole;
|
||||
import org.opencdmp.configurations.OpencdmpPermissionPolicyContextImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
@Component("affiliatedAuthorizationHandler")
|
||||
public class AffiliatedAuthorizationHandler extends AuthorizationHandler<AffiliatedAuthorizationRequirement> {
|
||||
|
||||
private final CustomPermissionAttributesConfiguration myConfiguration;
|
||||
private final OpencdmpPermissionPolicyContextImpl opencdmpPermissionPolicyContext;
|
||||
|
||||
@Autowired
|
||||
public AffiliatedAuthorizationHandler(CustomPermissionAttributesConfiguration myConfiguration) {
|
||||
public AffiliatedAuthorizationHandler(CustomPermissionAttributesConfiguration myConfiguration, OpencdmpPermissionPolicyContextImpl opencdmpPermissionPolicyContext) {
|
||||
this.myConfiguration = myConfiguration;
|
||||
this.opencdmpPermissionPolicyContext = opencdmpPermissionPolicyContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,7 +48,16 @@ public class AffiliatedAuthorizationHandler extends AuthorizationHandler<Affilia
|
|||
CustomPermissionAttributesProperties.MyPermission policy = this.myConfiguration.getMyPolicies().get(permission);
|
||||
boolean hasPlanPermission = policy != null && this.hasPermission(policy.getPlan(), planUserRoles);
|
||||
boolean hasDescriptionTemplatePermission = policy != null && this.hasPermission(policy.getDescriptionTemplate(), userDescriptionTemplateRoles);
|
||||
if (hasPlanPermission || hasDescriptionTemplatePermission) hits += 1;
|
||||
|
||||
boolean hasPlanCustomPermission = false;
|
||||
if (permission.startsWith("PlanStatus_") || permission.startsWith("DescriptionStatus_")) {
|
||||
HashMap<String, CustomPermissionAttributesProperties. MyPermission> customPolicies = this.opencdmpPermissionPolicyContext.buildAffiliatedCustomPermissions();
|
||||
if (customPolicies == null || customPolicies.isEmpty()) return ACCESS_DENIED;
|
||||
CustomPermissionAttributesProperties.MyPermission customPolicy = customPolicies.get(permission);
|
||||
hasPlanCustomPermission = customPolicy != null && this.hasPermission(customPolicy.getPlan(), planUserRoles);
|
||||
}
|
||||
|
||||
if (hasPlanPermission || hasPlanCustomPermission || hasDescriptionTemplatePermission) hits += 1;
|
||||
}
|
||||
if ((req.getMatchAll() && req.getRequiredPermissions().size() == hits) || (!req.getMatchAll() && hits > 0))
|
||||
return ACCESS_GRANTED;
|
||||
|
|
|
@ -1,39 +1,54 @@
|
|||
package org.opencdmp.configurations;
|
||||
|
||||
import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration;
|
||||
import gr.cite.commons.web.authz.configuration.Permission;
|
||||
import gr.cite.commons.web.authz.configuration.PermissionPolicyContextImpl;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.opencdmp.authorization.CustomPermissionAttributesProperties;
|
||||
import org.opencdmp.authorization.PlanRole;
|
||||
import org.opencdmp.commons.XmlHandlingService;
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.commons.enums.PlanUserRole;
|
||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
|
||||
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
|
||||
import org.opencdmp.data.DescriptionStatusEntity;
|
||||
import org.opencdmp.data.PlanStatusEntity;
|
||||
import org.opencdmp.event.DescriptionStatusTouchedEvent;
|
||||
import org.opencdmp.event.PlanStatusTouchedEvent;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||
import org.opencdmp.model.planstatus.PlanStatus;
|
||||
import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
|
||||
import org.opencdmp.query.DescriptionStatusQuery;
|
||||
import org.opencdmp.query.PlanStatusQuery;
|
||||
import org.opencdmp.service.custompolicy.CustomPolicyService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@Service
|
||||
public class OpencdmpPermissionPolicyContextImpl extends PermissionPolicyContextImpl {
|
||||
private final CustomPolicyService customPolicyService;
|
||||
private final QueryFactory queryFactory;
|
||||
private final XmlHandlingService xmlHandlingService;
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(OpencdmpPermissionPolicyContextImpl.class));
|
||||
|
||||
public OpencdmpPermissionPolicyContextImpl(AuthorizationConfiguration authorizationConfiguration, QueryFactory queryFactory, XmlHandlingService xmlHandlingService) {
|
||||
public OpencdmpPermissionPolicyContextImpl(AuthorizationConfiguration authorizationConfiguration, CustomPolicyService customPolicyService, QueryFactory queryFactory, XmlHandlingService xmlHandlingService) {
|
||||
super(authorizationConfiguration);
|
||||
this.customPolicyService = customPolicyService;
|
||||
this.queryFactory = queryFactory;
|
||||
this.xmlHandlingService = xmlHandlingService;
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleTenantTouchedEvent(PlanStatusTouchedEvent event) {
|
||||
public void handlePlanTouchedEvent(PlanStatusTouchedEvent event) {
|
||||
this.refresh(true);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleDescriptionStatusTouchedEvent(DescriptionStatusTouchedEvent event) {
|
||||
this.refresh(true);
|
||||
}
|
||||
|
||||
|
@ -42,21 +57,42 @@ public class OpencdmpPermissionPolicyContextImpl extends PermissionPolicyContext
|
|||
if (!force && this.policies != null) return;
|
||||
this.policies = this.authorizationConfiguration.getRawPolicies();
|
||||
this.extendedClaims = this.authorizationConfiguration.getRawExtendedClaims();
|
||||
this.policies.putAll(this.buildPlanStatusPolicies());
|
||||
this.policies.putAll(this.customPolicyService.buildPlanStatusPolicies());
|
||||
this.policies.putAll(this.customPolicyService.buildDescriptionStatusPolicies());
|
||||
logger.info("Authorization policies found: {}", this.policies.size());
|
||||
this.reload();
|
||||
}
|
||||
|
||||
private HashMap<String, Permission> buildPlanStatusPolicies(){
|
||||
HashMap<String, gr.cite.commons.web.authz.configuration.Permission> policies = new HashMap<>();
|
||||
List<PlanStatusEntity> entities = this.queryFactory.query(PlanStatusQuery.class).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanStatus._id).ensure(PlanStatus._definition));
|
||||
for (PlanStatusEntity entity : entities) {
|
||||
public HashMap<String, CustomPermissionAttributesProperties.MyPermission> buildAffiliatedCustomPermissions() {
|
||||
HashMap<String, CustomPermissionAttributesProperties.MyPermission> affiliatedCustomPermissions = new HashMap<>();
|
||||
List<PlanStatusEntity> planStatusEntities = this.queryFactory.query(PlanStatusQuery.class).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanStatus._id).ensure(PlanStatus._definition));
|
||||
if (planStatusEntities != null) {
|
||||
for (PlanStatusEntity entity : planStatusEntities) {
|
||||
PlanStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(PlanStatusDefinitionEntity.class, entity.getDefinition());
|
||||
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) policies.put(this.getPlanStatusCanEditStatusPermission(entity.getId()), new gr.cite.commons.web.authz.configuration.Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
|
||||
}
|
||||
return policies;
|
||||
}
|
||||
private String getPlanStatusCanEditStatusPermission(UUID id){
|
||||
return "PlanStatus" + "_" + id + "_" + PlanStatusDefinitionAuthorization._edit;
|
||||
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null && definition.getAuthorization().getEdit().getPlanRoles() != null){
|
||||
for (PlanUserRole planUserRole: definition.getAuthorization().getEdit().getPlanRoles()) {
|
||||
PlanRole planRole = new PlanRole(new HashSet<>(List.of(planUserRole)));
|
||||
CustomPermissionAttributesProperties.MyPermission myPermission = new CustomPermissionAttributesProperties.MyPermission(planRole, null);
|
||||
affiliatedCustomPermissions.put(this.customPolicyService.getPlanStatusCanEditStatusAffiliatedPermission(entity.getId(), planUserRole), myPermission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DescriptionStatusEntity> descriptionStatusEntities = this.queryFactory.query(DescriptionStatusQuery.class).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(DescriptionStatus._id).ensure(DescriptionStatus._definition));
|
||||
if (descriptionStatusEntities != null) {
|
||||
for (DescriptionStatusEntity entity : descriptionStatusEntities) {
|
||||
DescriptionStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionStatusDefinitionEntity.class, entity.getDefinition());
|
||||
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null && definition.getAuthorization().getEdit().getPlanRoles() != null){
|
||||
for (PlanUserRole planUserRole: definition.getAuthorization().getEdit().getPlanRoles()) {
|
||||
PlanRole planRole = new PlanRole(new HashSet<>(List.of(planUserRole)));
|
||||
CustomPermissionAttributesProperties.MyPermission myPermission = new CustomPermissionAttributesProperties.MyPermission(planRole, null);
|
||||
affiliatedCustomPermissions.put(this.customPolicyService.getDescriptionStatusCanEditStatusAffiliatedPermission(entity.getId(), planUserRole), myPermission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return affiliatedCustomPermissions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,12 @@ cache:
|
|||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 20
|
||||
- names: [ "customPolicyByTenant" ]
|
||||
allowNullValues: true
|
||||
initialCapacity: 100
|
||||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 600
|
||||
mapCaches:
|
||||
userBySubjectId:
|
||||
name: userBySubjectId
|
||||
|
@ -129,3 +135,6 @@ cache:
|
|||
affiliation:
|
||||
name: affiliation
|
||||
keyPattern: affiliation_$entity$_$user$_$tenant$_$type$:v0
|
||||
customPolicyByTenant:
|
||||
name: customPolicyByTenant
|
||||
keyPattern: custom_policy_by_tenant$tenant_code$:v0
|
Loading…
Reference in New Issue