plan status authz changes

This commit is contained in:
Efstratios Giannopoulos 2024-09-27 14:49:25 +03:00
parent 38542c65ad
commit ff52d32d32
11 changed files with 128 additions and 20 deletions

View File

@ -46,7 +46,7 @@
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authz</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.opencdmp</groupId>

View File

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

View File

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

View File

@ -22,3 +22,4 @@ public class PlanTouchedEvent {
}
}

View File

@ -193,6 +193,8 @@ public class PlanStatusQuery extends QueryBase<PlanStatusEntity> {
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))

View File

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

View File

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

View File

@ -128,6 +128,11 @@
<artifactId>exceptions-web</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authz</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>

View File

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

View File

@ -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<HttpServletRequest> authenticationManagerResolver,
@Qualifier("apiKeyFilter") Filter apiKeyFilter,
@Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler,
@Qualifier("affiliatedAuthorizationHandler") AffiliatedAuthorizationHandler affiliatedAuthorizationHandler) {
@Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver<HttpServletRequest> 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() {
@ -148,3 +150,4 @@ public class SecurityConfiguration {
return endpoint;
}
}

View File

@ -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<String> 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<String> roles = this.claimExtractor.roles(this.currentPrincipalResolver.currentPrincipal());
Set<String> permissions = this.authorizationConfiguration.permissionsOfRoles(roles);
for (Map.Entry<String, Permission> permissionEntry : this.authorizationConfiguration.getRawPolicies().entrySet()){
Set<String> permissions = this.permissionPolicyContext.permissionsOfRoles(roles);
for (Map.Entry<String, Permission> permissionEntry : this.permissionPolicyContext.getRawPolicies().entrySet()){
if (permissionEntry.getValue().getAllowAuthenticated()){
permissions.add(permissionEntry.getKey());
}