diff --git a/backend/core/pom.xml b/backend/core/pom.xml
index efa0217cb..6f0c0f994 100644
--- a/backend/core/pom.xml
+++ b/backend/core/pom.xml
@@ -46,7 +46,7 @@
gr.cite
oidc-authz
- 2.1.0
+ 2.2.0
org.opencdmp
diff --git a/backend/core/src/main/java/org/opencdmp/event/EventBroker.java b/backend/core/src/main/java/org/opencdmp/event/EventBroker.java
index defc5be38..fe4ad8ecf 100644
--- a/backend/core/src/main/java/org/opencdmp/event/EventBroker.java
+++ b/backend/core/src/main/java/org/opencdmp/event/EventBroker.java
@@ -53,6 +53,10 @@ public class EventBroker {
this.applicationEventPublisher.publishEvent(event);
}
+ public void emit(PlanStatusTouchedEvent event) {
+ this.applicationEventPublisher.publishEvent(event);
+ }
+
public void emit(TagTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}
diff --git a/backend/core/src/main/java/org/opencdmp/event/PlanStatusTouchedEvent.java b/backend/core/src/main/java/org/opencdmp/event/PlanStatusTouchedEvent.java
new file mode 100644
index 000000000..0822dc2a9
--- /dev/null
+++ b/backend/core/src/main/java/org/opencdmp/event/PlanStatusTouchedEvent.java
@@ -0,0 +1,24 @@
+package org.opencdmp.event;
+
+import java.util.UUID;
+
+public class PlanStatusTouchedEvent {
+
+ public PlanStatusTouchedEvent() {
+ }
+
+ public PlanStatusTouchedEvent(UUID id) {
+ this.id = id;
+ }
+
+ private UUID id;
+
+ public UUID getId() {
+ return id;
+ }
+
+ public void setId(UUID id) {
+ this.id = id;
+ }
+
+}
diff --git a/backend/core/src/main/java/org/opencdmp/event/PlanTouchedEvent.java b/backend/core/src/main/java/org/opencdmp/event/PlanTouchedEvent.java
index 13f362c3a..edc4feab7 100644
--- a/backend/core/src/main/java/org/opencdmp/event/PlanTouchedEvent.java
+++ b/backend/core/src/main/java/org/opencdmp/event/PlanTouchedEvent.java
@@ -22,3 +22,4 @@ public class PlanTouchedEvent {
}
}
+
diff --git a/backend/core/src/main/java/org/opencdmp/query/PlanStatusQuery.java b/backend/core/src/main/java/org/opencdmp/query/PlanStatusQuery.java
index 503757bfa..add261cc3 100644
--- a/backend/core/src/main/java/org/opencdmp/query/PlanStatusQuery.java
+++ b/backend/core/src/main/java/org/opencdmp/query/PlanStatusQuery.java
@@ -193,6 +193,8 @@ public class PlanStatusQuery extends QueryBase {
return PlanStatusEntity._internalStatus;
else if (item.prefix(PlanStatus._definition))
return PlanStatusEntity._definition;
+ else if (item.match(PlanStatus._definition))
+ return PlanStatusEntity._definition;
else if (item.match(PlanStatus._createdAt))
return PlanStatusEntity._createdAt;
else if (item.match(PlanStatus._updatedAt))
diff --git a/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusService.java b/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusService.java
index a2df92905..6af2ea77c 100644
--- a/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusService.java
+++ b/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusService.java
@@ -1,5 +1,6 @@
package org.opencdmp.service.planstatus;
+import gr.cite.commons.web.authz.configuration.Permission;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
@@ -10,6 +11,7 @@ import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
import org.opencdmp.model.planstatus.PlanStatus;
import javax.management.InvalidApplicationException;
+import java.util.HashMap;
import java.util.List;
import java.util.UUID;
diff --git a/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusServiceImpl.java
index d9bdb9e5f..378ed2d8f 100644
--- a/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusServiceImpl.java
+++ b/backend/core/src/main/java/org/opencdmp/service/planstatus/PlanStatusServiceImpl.java
@@ -1,5 +1,6 @@
package org.opencdmp.service.planstatus;
+import gr.cite.commons.web.authz.configuration.PermissionPolicyContext;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
@@ -29,6 +30,8 @@ import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.EventBroker;
+import org.opencdmp.event.PlanStatusTouchedEvent;
+import org.opencdmp.event.PlanTouchedEvent;
import org.opencdmp.model.builder.planstatus.PlanStatusBuilder;
import org.opencdmp.model.deleter.PlanStatusDeleter;
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationItemPersist;
@@ -36,6 +39,7 @@ import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationPe
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionPersist;
import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
import org.opencdmp.model.planstatus.PlanStatus;
+import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
import org.opencdmp.query.PlanStatusQuery;
import org.opencdmp.service.planworkflow.PlanWorkflowService;
import org.slf4j.LoggerFactory;
@@ -45,9 +49,7 @@ import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -66,7 +68,7 @@ public class PlanStatusServiceImpl implements PlanStatusService {
private final ErrorThesaurusProperties errors;
private final QueryFactory queryFactory;
private final PlanWorkflowService planWorkflowService;
-
+ private final EventBroker eventBroker;
public PlanStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, EventBroker eventBroker, QueryFactory queryFactory, PlanWorkflowService planWorkflowService) {
this.builderFactory = builderFactory;
this.deleterFactory = deleterFactory;
@@ -79,6 +81,7 @@ public class PlanStatusServiceImpl implements PlanStatusService {
this.errors = errors;
this.queryFactory = queryFactory;
this.planWorkflowService = planWorkflowService;
+ this.eventBroker = eventBroker;
}
@Override
@@ -115,6 +118,8 @@ public class PlanStatusServiceImpl implements PlanStatusService {
this.entityManager.flush();
+ this.eventBroker.emit(new PlanStatusTouchedEvent(data.getId()));
+
return this.builderFactory.builder(PlanStatusBuilder.class).build(BaseFieldSet.build(fields, PlanStatus._id), data);
}
diff --git a/backend/web/pom.xml b/backend/web/pom.xml
index c5ec3c171..29727e9ef 100644
--- a/backend/web/pom.xml
+++ b/backend/web/pom.xml
@@ -128,6 +128,11 @@
exceptions-web
2.2.0
+
+ gr.cite
+ oidc-authz
+ 2.2.0
+
diff --git a/backend/web/src/main/java/org/opencdmp/configurations/OpencdmpPermissionPolicyContextImpl.java b/backend/web/src/main/java/org/opencdmp/configurations/OpencdmpPermissionPolicyContextImpl.java
new file mode 100644
index 000000000..82f23052f
--- /dev/null
+++ b/backend/web/src/main/java/org/opencdmp/configurations/OpencdmpPermissionPolicyContextImpl.java
@@ -0,0 +1,62 @@
+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.commons.XmlHandlingService;
+import org.opencdmp.commons.enums.IsActive;
+import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
+import org.opencdmp.data.PlanStatusEntity;
+import org.opencdmp.event.PlanStatusTouchedEvent;
+import org.opencdmp.model.planstatus.PlanStatus;
+import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
+import org.opencdmp.query.PlanStatusQuery;
+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 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) {
+ super(authorizationConfiguration);
+ this.queryFactory = queryFactory;
+ this.xmlHandlingService = xmlHandlingService;
+ }
+
+ @EventListener
+ public void handleTenantTouchedEvent(PlanStatusTouchedEvent event) {
+ this.refresh(true);
+ }
+
+ @Override
+ public void refresh(boolean force) {
+ if (!force && this.policies != null) return;
+ this.policies = this.authorizationConfiguration.getRawPolicies();
+ this.extendedClaims = this.authorizationConfiguration.getRawExtendedClaims();
+ this.policies.putAll(this.buildPlanStatusPolicies());
+ logger.info("Authorization policies found: {}", this.policies.size());
+ this.reload();
+ }
+
+ private HashMap buildPlanStatusPolicies(){
+ HashMap policies = new HashMap<>();
+ List 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 && 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;
+ }
+}
diff --git a/backend/web/src/main/java/org/opencdmp/configurations/SecurityConfiguration.java b/backend/web/src/main/java/org/opencdmp/configurations/SecurityConfiguration.java
index 065766c5f..460a1cab3 100644
--- a/backend/web/src/main/java/org/opencdmp/configurations/SecurityConfiguration.java
+++ b/backend/web/src/main/java/org/opencdmp/configurations/SecurityConfiguration.java
@@ -3,7 +3,6 @@ package org.opencdmp.configurations;
import org.opencdmp.authorization.*;
import gr.cite.commons.web.authz.handler.AuthorizationHandler;
-import gr.cite.commons.web.authz.handler.PermissionClientAuthorizationHandler;
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
import gr.cite.commons.web.authz.policy.AuthorizationRequirementMapper;
import gr.cite.commons.web.authz.policy.AuthorizationResource;
@@ -26,9 +25,7 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
@Configuration
@EnableWebSecurity
@@ -42,10 +39,10 @@ public class SecurityConfiguration {
@Autowired
public SecurityConfiguration(WebSecurityProperties webSecurityProperties,
- @Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver authenticationManagerResolver,
- @Qualifier("apiKeyFilter") Filter apiKeyFilter,
- @Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler,
- @Qualifier("affiliatedAuthorizationHandler") AffiliatedAuthorizationHandler affiliatedAuthorizationHandler) {
+ @Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver authenticationManagerResolver,
+ @Qualifier("apiKeyFilter") Filter apiKeyFilter,
+ @Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler,
+ @Qualifier("affiliatedAuthorizationHandler") AffiliatedAuthorizationHandler affiliatedAuthorizationHandler) {
this.webSecurityProperties = webSecurityProperties;
this.authenticationManagerResolver = authenticationManagerResolver;
this.apiKeyFilter = apiKeyFilter;
@@ -107,6 +104,11 @@ public class SecurityConfiguration {
};
}
+// @Bean()
+// public PermissionPolicyContext permissionPolicyContext(){
+// return new PermissionPolicyContextImpl(configuration);
+// }
+
@Bean
AuthorizationRequirementMapper authorizationRequirementMapper() {
return new AuthorizationRequirementMapper() {
@@ -147,4 +149,5 @@ public class SecurityConfiguration {
}
return endpoint;
}
-}
\ No newline at end of file
+}
+
diff --git a/backend/web/src/main/java/org/opencdmp/models/AccountBuilder.java b/backend/web/src/main/java/org/opencdmp/models/AccountBuilder.java
index 6a58e7e5b..bfc1b2562 100644
--- a/backend/web/src/main/java/org/opencdmp/models/AccountBuilder.java
+++ b/backend/web/src/main/java/org/opencdmp/models/AccountBuilder.java
@@ -1,7 +1,7 @@
package org.opencdmp.models;
-import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration;
import gr.cite.commons.web.authz.configuration.Permission;
+import gr.cite.commons.web.authz.configuration.PermissionPolicyContext;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
@@ -33,7 +33,7 @@ public class AccountBuilder {
private final ClaimExtractor claimExtractor;
private final Set excludeMoreClaim;
private final CurrentPrincipalResolver currentPrincipalResolver;
- private final AuthorizationConfiguration authorizationConfiguration;
+ private final PermissionPolicyContext permissionPolicyContext;
private final AuthorizationContentResolver authorizationContentResolver;
private final JsonHandlingService jsonHandlingService;
private final UserScope userScope;
@@ -42,10 +42,10 @@ public class AccountBuilder {
private final QueryFactory queryFactory;
private final BuilderFactory builderFactory;
- public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, AuthorizationConfiguration authorizationConfiguration, AuthorizationContentResolver authorizationContentResolver, JsonHandlingService jsonHandlingService, UserScope userScope, TenantEntityManager entityManager, TenantScope tenantScope, QueryFactory queryFactory, BuilderFactory builderFactory) {
+ public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, PermissionPolicyContext permissionPolicyContext, AuthorizationContentResolver authorizationContentResolver, JsonHandlingService jsonHandlingService, UserScope userScope, TenantEntityManager entityManager, TenantScope tenantScope, QueryFactory queryFactory, BuilderFactory builderFactory) {
this.claimExtractor = claimExtractor;
this.currentPrincipalResolver = currentPrincipalResolver;
- this.authorizationConfiguration = authorizationConfiguration;
+ this.permissionPolicyContext = permissionPolicyContext;
this.authorizationContentResolver = authorizationContentResolver;
this.jsonHandlingService = jsonHandlingService;
this.userScope = userScope;
@@ -107,8 +107,8 @@ public class AccountBuilder {
}
if (fields.hasField(Account._permissions)) {
List roles = this.claimExtractor.roles(this.currentPrincipalResolver.currentPrincipal());
- Set permissions = this.authorizationConfiguration.permissionsOfRoles(roles);
- for (Map.Entry permissionEntry : this.authorizationConfiguration.getRawPolicies().entrySet()){
+ Set permissions = this.permissionPolicyContext.permissionsOfRoles(roles);
+ for (Map.Entry permissionEntry : this.permissionPolicyContext.getRawPolicies().entrySet()){
if (permissionEntry.getValue().getAllowAuthenticated()){
permissions.add(permissionEntry.getKey());
}