diff --git a/dmp-backend/core/pom.xml b/dmp-backend/core/pom.xml
index e6c6fac3a..0c81669f0 100644
--- a/dmp-backend/core/pom.xml
+++ b/dmp-backend/core/pom.xml
@@ -21,6 +21,11 @@
1.0-SNAPSHOT
compile
+
+ gr.cite
+ oidc-authz
+ 2.1.0
+
diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java
new file mode 100644
index 000000000..b1868d641
--- /dev/null
+++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java
@@ -0,0 +1,10 @@
+package eu.eudat.authorization;
+
+import java.util.EnumSet;
+
+public enum AuthorizationFlags {
+ None, Permission, Owner;
+ public static final EnumSet OwnerOrPermission = EnumSet.of(Owner, Permission);
+ public static final EnumSet OwnerOrPermissionOrIndicator = EnumSet.of(Owner, Permission);
+ public static final EnumSet OwnerOrPermissionOrIndicatorOrIndicatorAccess = EnumSet.of(Owner, Permission);
+}
diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/OwnedAuthorizationRequirement.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/OwnedAuthorizationRequirement.java
new file mode 100644
index 000000000..e43d2cb06
--- /dev/null
+++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/OwnedAuthorizationRequirement.java
@@ -0,0 +1,6 @@
+package eu.eudat.authorization;
+
+import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
+
+public class OwnedAuthorizationRequirement implements AuthorizationRequirement {
+}
diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/OwnedResource.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/OwnedResource.java
new file mode 100644
index 000000000..58ab094d4
--- /dev/null
+++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/OwnedResource.java
@@ -0,0 +1,26 @@
+package eu.eudat.authorization;
+
+import gr.cite.commons.web.authz.policy.AuthorizationResource;
+
+import java.util.List;
+import java.util.UUID;
+
+public class OwnedResource extends AuthorizationResource {
+ private List userIds;
+
+ public OwnedResource(UUID userId) {
+ this(List.of(userId));
+ }
+
+ public OwnedResource(List userIds) {
+ this.userIds = userIds;
+ }
+
+ public List getUserIds() {
+ return userIds;
+ }
+
+ public void setUserIds(List userIds) {
+ this.userIds = userIds;
+ }
+}
diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java
new file mode 100644
index 000000000..b68deaf62
--- /dev/null
+++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java
@@ -0,0 +1,13 @@
+package eu.eudat.authorization;
+
+public final class Permission {
+
+ //DescriptionTemplateType
+ public static String BrowseDescriptionTemplateType = "BrowseDescriptionTemplateType";
+ public static String EditDescriptionTemplateType = "EditDescriptionTemplateType";
+ public static String DeleteDescriptionTemplateType = "DeleteDescriptionTemplateType";
+
+ // UI Pages
+ public static String ViewDescriptionTemplateTypePage = "ViewDescriptionTemplateTypePage";
+
+}
diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/scope/UserScope.java b/dmp-backend/core/src/main/java/eu/eudat/commons/scope/user/UserScope.java
similarity index 96%
rename from dmp-backend/core/src/main/java/eu/eudat/commons/scope/UserScope.java
rename to dmp-backend/core/src/main/java/eu/eudat/commons/scope/user/UserScope.java
index 99fd79695..717f85e3d 100644
--- a/dmp-backend/core/src/main/java/eu/eudat/commons/scope/UserScope.java
+++ b/dmp-backend/core/src/main/java/eu/eudat/commons/scope/user/UserScope.java
@@ -1,4 +1,4 @@
-package eu.eudat.commons.scope;
+package eu.eudat.commons.scope.user;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java
index 1b621ae12..e4deef226 100644
--- a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java
+++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java
@@ -1,6 +1,8 @@
package eu.eudat.model.censorship;
+import eu.eudat.authorization.Permission;
import eu.eudat.convention.ConventionService;
+import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
@@ -14,15 +16,17 @@ import org.springframework.stereotype.Component;
public class DescriptionTemplateTypeCensor extends BaseCensor{
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeCensor.class));
-
- public DescriptionTemplateTypeCensor(ConventionService conventionService) {
+ protected final AuthorizationService authService;
+ public DescriptionTemplateTypeCensor(ConventionService conventionService, AuthorizationService authService) {
super(conventionService);
+ this.authService = authService;
}
public void censor(FieldSet fields) {
logger.debug(new DataLogEntry("censoring fields", fields));
- if (fields.isEmpty())
- return;
+ if (fields.isEmpty()) return;
+
+ this.authService.authorizeForce(Permission.BrowseDescriptionTemplateType);
}
}
diff --git a/dmp-backend/pom.xml b/dmp-backend/pom.xml
index 719322697..b3444341c 100644
--- a/dmp-backend/pom.xml
+++ b/dmp-backend/pom.xml
@@ -329,6 +329,12 @@
2.1.0
+
+ gr.cite
+ oidc-authz
+ 2.1.0
+
+
diff --git a/dmp-backend/web/src/main/java/eu/eudat/authorization/OwnedAuthorizationHandler.java b/dmp-backend/web/src/main/java/eu/eudat/authorization/OwnedAuthorizationHandler.java
new file mode 100644
index 000000000..f6ef8f821
--- /dev/null
+++ b/dmp-backend/web/src/main/java/eu/eudat/authorization/OwnedAuthorizationHandler.java
@@ -0,0 +1,42 @@
+package eu.eudat.authorization;
+
+import eu.eudat.commons.scope.user.UserScope;
+import gr.cite.commons.web.authz.handler.AuthorizationHandler;
+import gr.cite.commons.web.authz.handler.AuthorizationHandlerContext;
+import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
+import gr.cite.commons.web.oidc.principal.MyPrincipal;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("ownedAuthorizationHandler")
+public class OwnedAuthorizationHandler extends AuthorizationHandler {
+
+ private final UserScope userScope;
+
+ @Autowired
+ public OwnedAuthorizationHandler(UserScope userScope) {
+ this.userScope = userScope;
+ }
+
+ @Override
+ public int handleRequirement(AuthorizationHandlerContext context, Object resource, AuthorizationRequirement requirement) {
+ OwnedAuthorizationRequirement req = (OwnedAuthorizationRequirement) requirement;
+
+ OwnedResource rs = (OwnedResource) resource;
+
+ boolean isAuthenticated = ((MyPrincipal) context.getPrincipal()).isAuthenticated();
+ if (!isAuthenticated) return ACCESS_NOT_DETERMINED;
+
+ if (this.userScope.getUserIdSafe() == null) return ACCESS_NOT_DETERMINED;
+
+ if (rs != null && rs.getUserIds() != null && rs.getUserIds().contains(this.userScope.getUserIdSafe())) return ACCESS_GRANTED;
+
+ return ACCESS_NOT_DETERMINED;
+ }
+
+ @Override
+ public Class extends AuthorizationRequirement> supporting() {
+ return OwnedAuthorizationRequirement.class;
+ }
+
+}
diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java
index d5477240b..f734459b6 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/SecurityConfiguration.java
@@ -1,6 +1,16 @@
package eu.eudat.configurations;
+import eu.eudat.authorization.OwnedAuthorizationHandler;
+import eu.eudat.authorization.OwnedAuthorizationRequirement;
+import eu.eudat.authorization.OwnedResource;
+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;
+import gr.cite.commons.web.authz.policy.resolver.AuthorizationPolicyConfigurer;
+import gr.cite.commons.web.authz.policy.resolver.AuthorizationPolicyResolverStrategy;
import gr.cite.commons.web.oidc.configuration.WebSecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -17,24 +27,28 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
+
import java.util.List;
import java.util.Set;
@Configuration
@EnableWebSecurity
-public class SecurityConfiguration {
+public class SecurityConfiguration {
private final WebSecurityProperties webSecurityProperties;
private final AuthenticationManagerResolver authenticationManagerResolver;
private final Filter apiKeyFilter;
+ private final OwnedAuthorizationHandler ownedAuthorizationHandler;
@Autowired
public SecurityConfiguration(WebSecurityProperties webSecurityProperties,
- @Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver authenticationManagerResolver,
- @Qualifier("apiKeyFilter") Filter apiKeyFilter) {
+ @Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver authenticationManagerResolver,
+ @Qualifier("apiKeyFilter") Filter apiKeyFilter,
+ @Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler) {
this.webSecurityProperties = webSecurityProperties;
this.authenticationManagerResolver = authenticationManagerResolver;
this.apiKeyFilter = apiKeyFilter;
+ this.ownedAuthorizationHandler = ownedAuthorizationHandler;
}
@Bean
@@ -52,60 +66,61 @@ public class SecurityConfiguration {
return tempHttp.build();
}
-// @Bean
-// AuthorizationPolicyConfigurer authorizationPolicyConfigurer() {
-// return new AuthorizationPolicyConfigurer() {
-//
-// @Override
-// public AuthorizationPolicyResolverStrategy strategy() {
-// return AuthorizationPolicyResolverStrategy.STRICT_CONSENSUS_BASED;
-// }
-//
-// //Here you can register your custom authorization handlers, which will get used as well as the existing ones
-// //This is optional and can be omitted
-// //If not set / set to null, only the default authorization handlers will be used
-// @Override
-// public List> addCustomHandlers() {
-// return null;
-// }
-//
-// //Here you can register your custom authorization requirements (if any)
-// //This is optional and can be omitted
-// //If not set / set to null, only the default authorization requirements will be used
-// @Override
-// public List extends AuthorizationRequirement> extendRequirements() {
-// return List.of(
-//// new TimeOfDayAuthorizationRequirement(new TimeOfDay("08:00","16:00"), true)
-// );
-// }
-//
-// //Here you can select handlers you want to disable by providing the classes they are implemented by
-// //You can disable any handler (including any custom one)
-// //This is optional and can be omitted
-// //If not set / set to null, all the handlers will be invoked, based on their requirement support
-// //In the example below, the default client handler will be ignored by the resolver
-// @Override
-// public List>> disableHandlers() {
-// return List.of(PermissionClientAuthorizationHandler.class);
-// }
-// };
-// }
-//
-// @Bean
-// AuthorizationRequirementMapper authorizationRequirementMapper() {
-// return new AuthorizationRequirementMapper() {
-// @Override
-// public AuthorizationRequirement map(AuthorizationResource resource, boolean matchAll, String[] permissions) {
-// Class> type = resource.getClass();
-// if (!AuthorizationResource.class.isAssignableFrom(type)) throw new IllegalArgumentException("resource");
-//
-// if (OwnedResource.class.equals(type)) {
-// return new OwnedAuthorizationRequirement();
-// }
-// throw new IllegalArgumentException("resource");
-// }
-// };
-// }
+ @Bean
+ AuthorizationPolicyConfigurer authorizationPolicyConfigurer() {
+ return new AuthorizationPolicyConfigurer() {
+
+ @Override
+ public AuthorizationPolicyResolverStrategy strategy() {
+ return AuthorizationPolicyResolverStrategy.STRICT_CONSENSUS_BASED;
+ }
+
+ //Here you can register your custom authorization handlers, which will get used as well as the existing ones
+ //This is optional and can be omitted
+ //If not set / set to null, only the default authorization handlers will be used
+ @Override
+ public List> addCustomHandlers() {
+ return List.of( ownedAuthorizationHandler);
+ }
+
+ //Here you can register your custom authorization requirements (if any)
+ //This is optional and can be omitted
+ //If not set / set to null, only the default authorization requirements will be used
+ @Override
+ public List extends AuthorizationRequirement> extendRequirements() {
+ return List.of(
+// new TimeOfDayAuthorizationRequirement(new TimeOfDay("08:00","16:00"), true)
+ );
+ }
+
+ //Here you can select handlers you want to disable by providing the classes they are implemented by
+ //You can disable any handler (including any custom one)
+ //This is optional and can be omitted
+ //If not set / set to null, all the handlers will be invoked, based on their requirement support
+ //In the example below, the default client handler will be ignored by the resolver
+ @Override
+ public List>> disableHandlers() {
+ return List.of(PermissionClientAuthorizationHandler.class);
+ }
+ };
+ }
+
+ @Bean
+ AuthorizationRequirementMapper authorizationRequirementMapper() {
+ return new AuthorizationRequirementMapper() {
+ @Override
+ public AuthorizationRequirement map(AuthorizationResource resource, boolean matchAll, String[] permissions) {
+ Class> type = resource.getClass();
+ if (!AuthorizationResource.class.isAssignableFrom(type)) throw new IllegalArgumentException("resource");
+
+ if (OwnedResource.class.equals(type)) {
+ return new OwnedAuthorizationRequirement();
+ }
+ throw new IllegalArgumentException("resource");
+ }
+ };
+ }
+
private String[] buildAntPatterns(Set endpoints) {
if (endpoints == null) {
diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java
index a554d13ce..8170b8c72 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java
@@ -1,6 +1,6 @@
package eu.eudat.configurations;
-import eu.eudat.commons.scope.UserScope;
+import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.interceptors.UserInterceptor;
import eu.eudat.logic.handlers.PrincipalArgumentResolver;
import eu.eudat.logic.services.ApiContext;
diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java
index 0aaa176bd..344d5437a 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/PrincipalController.java
@@ -55,7 +55,8 @@ public class PrincipalController {
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._authenticatedAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._expiresAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._more),
- Account._roles);
+ Account._roles,
+ Account._permissions);
}
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
diff --git a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java
index 373f9a52c..a488952c0 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/interceptors/UserInterceptor.java
@@ -3,16 +3,14 @@ package eu.eudat.interceptors;
import eu.eudat.commons.enums.ProviderType;
import eu.eudat.commons.enums.Status;
-import eu.eudat.commons.scope.UserScope;
+import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.data.CredentialEntity;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.exceptions.security.NullEmailException;
-import eu.eudat.query.CredentialQuery;
import eu.eudat.types.Authorities;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
-import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import jakarta.persistence.EntityManager;
@@ -72,6 +70,7 @@ public class UserInterceptor implements WebRequestInterceptor {
UUID userId = null;
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
+ var aa = this.claimExtractor.roles(this.currentPrincipalResolver.currentPrincipal());
UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
if (cacheValue != null) {
userId = cacheValue.getUserId();
diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/PrincipalArgumentResolver.java b/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/PrincipalArgumentResolver.java
index 5cdb96839..f185cfe2e 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/PrincipalArgumentResolver.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/PrincipalArgumentResolver.java
@@ -1,6 +1,6 @@
package eu.eudat.logic.handlers;
-import eu.eudat.commons.scope.UserScope;
+import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/v2/Account.java b/dmp-backend/web/src/main/java/eu/eudat/models/v2/Account.java
index 3991ef43d..f82e33126 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/models/v2/Account.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/models/v2/Account.java
@@ -139,6 +139,9 @@ public class Account {
public final static String _principal = "principal";
private PrincipalInfo principal;
+ public final static String _permissions = "permissions";
+ private List permissions;
+
public PrincipalInfo getPrincipal() {
return principal;
}
@@ -162,4 +165,16 @@ public class Account {
public void setRoles(List roles) {
this.roles = roles;
}
+
+ public void setAuthenticated(Boolean authenticated) {
+ isAuthenticated = authenticated;
+ }
+
+ public List getPermissions() {
+ return permissions;
+ }
+
+ public void setPermissions(List permissions) {
+ this.permissions = permissions;
+ }
}
diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/v2/AccountBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/models/v2/AccountBuilder.java
index 67bad2fcc..ad1a31b50 100644
--- a/dmp-backend/web/src/main/java/eu/eudat/models/v2/AccountBuilder.java
+++ b/dmp-backend/web/src/main/java/eu/eudat/models/v2/AccountBuilder.java
@@ -1,10 +1,10 @@
package eu.eudat.models.v2;
-import eu.eudat.commons.scope.UserScope;
+import eu.eudat.commons.scope.user.UserScope;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.logic.services.ApiContext;
-import eu.eudat.types.Authorities;
+import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration;
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;
@@ -24,11 +24,13 @@ public class AccountBuilder {
private final ClaimExtractor claimExtractor;
private final Set excludeMoreClaim;
private final CurrentPrincipalResolver currentPrincipalResolver;
+ private final AuthorizationConfiguration authorizationConfiguration;
private final ApiContext apiContext;
private final UserScope userScope;
- public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, ApiContext apiContext, UserScope userScope) {
+ public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, AuthorizationConfiguration authorizationConfiguration, ApiContext apiContext, UserScope userScope) {
this.claimExtractor = claimExtractor;
this.currentPrincipalResolver = currentPrincipalResolver;
+ this.authorizationConfiguration = authorizationConfiguration;
this.apiContext = apiContext;
this.userScope = userScope;
this.excludeMoreClaim = Set.of(
@@ -93,6 +95,11 @@ public class AccountBuilder {
model.getRoles().add(item.getRole());
}
}
+ if (fields.hasField(Account._permissions)) {
+ List roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
+ Set permissions = authorizationConfiguration.permissionsOfRoles(roles);
+ model.setPermissions(new ArrayList<>(permissions));
+ }
return model;
}
}
diff --git a/dmp-backend/web/src/main/resources/config/application.yml b/dmp-backend/web/src/main/resources/config/application.yml
index e0cf36a95..ced49fdd3 100644
--- a/dmp-backend/web/src/main/resources/config/application.yml
+++ b/dmp-backend/web/src/main/resources/config/application.yml
@@ -4,6 +4,7 @@ spring:
config:
import: optional:classpath:config/app.env[.properties], optional:file:../config/app.env[.properties],
optional:classpath:config/db.yml[.yml], optional:classpath:config/db-${spring.profiles.active}.yml[.yml], optional:file:../config/db-${spring.profiles.active}.yml[.yml],
+ optional:classpath:config/permissions.yml[.yml], optional:classpath:config/permissions-${spring.profiles.active}.yml[.yml], optional:file:../config/permissions-${spring.profiles.active}.yml[.yml],
optional:classpath:config/security.yml[.yml], optional:classpath:config/security-${spring.profiles.active}.yml[.yml], optional:file:../config/security-${spring.profiles.active}.yml[.yml],
optional:classpath:config/server.yml[.yml], optional:classpath:config/server-${spring.profiles.active}.yml[.yml], optional:file:../config/server-${spring.profiles.active}.yml[.yml],
optional:classpath:config/logging.yml[.yml], optional:classpath:config/logging-${spring.profiles.active}.yml[.yml], optional:file:../config/logging-${spring.profiles.active}.yml[.yml],
diff --git a/dmp-backend/web/src/main/resources/config/permissions.yml b/dmp-backend/web/src/main/resources/config/permissions.yml
new file mode 100644
index 000000000..68f99ab75
--- /dev/null
+++ b/dmp-backend/web/src/main/resources/config/permissions.yml
@@ -0,0 +1,31 @@
+permissions:
+ extendedClaims: [ ]
+ policies:
+ # Users
+ BrowseDescriptionTemplateType:
+ roles:
+ - Admin
+ clients: [ ]
+ allowAnonymous: true
+ allowAuthenticated: false
+ EditDescriptionTemplateType:
+ roles:
+ - Admin
+ clients: [ ]
+ allowAnonymous: false
+ allowAuthenticated: false
+ DeleteDescriptionTemplateType:
+ roles:
+ - Admin
+ claims: [ ]
+ clients: [ ]
+ allowAnonymous: false
+ allowAuthenticated: false
+
+ # ViewPage Permissions
+ ViewDatasetPage:
+ roles:
+ - Admin
+ clients: [ ]
+ allowAnonymous: false
+ allowAuthenticated: false
diff --git a/dmp-frontend/src/app/core/common/enum/permission.enum.ts b/dmp-frontend/src/app/core/common/enum/permission.enum.ts
new file mode 100644
index 000000000..063694faf
--- /dev/null
+++ b/dmp-frontend/src/app/core/common/enum/permission.enum.ts
@@ -0,0 +1,10 @@
+export enum AppPermission {
+ //DescriptionTemplateType
+ BrowseDescriptionTemplateType = "BrowseDescriptionTemplateType",
+ EditDescriptionTemplateType = "EditDescriptionTemplateType",
+ DeleteDescriptionTemplateType = "DeleteDescriptionTemplateType",
+
+ // UI Pages
+ ViewDescriptionTemplateTypePage = "ViewDescriptionTemplateTypePage"
+}
+
diff --git a/dmp-frontend/src/app/core/model/auth/principal.ts b/dmp-frontend/src/app/core/model/auth/principal.ts
index eb916313c..c0012e7cd 100644
--- a/dmp-frontend/src/app/core/model/auth/principal.ts
+++ b/dmp-frontend/src/app/core/model/auth/principal.ts
@@ -1,10 +1,12 @@
import { AppRole } from "@app/core/common/enum/app-role";
+import { AppPermission } from "@app/core/common/enum/permission.enum";
import { Guid } from "@common/types/guid";
export interface AppAccount {
isAuthenticated: boolean;
// permissions: AppPermission[];
roles: AppRole[];
+ permissions: AppPermission[];
principal: AppPrincipalInfo;
profile: UserProfileInfo;
}
diff --git a/dmp-frontend/src/app/core/services/auth/auth.service.ts b/dmp-frontend/src/app/core/services/auth/auth.service.ts
index ee4ad8e11..66238f10a 100644
--- a/dmp-frontend/src/app/core/services/auth/auth.service.ts
+++ b/dmp-frontend/src/app/core/services/auth/auth.service.ts
@@ -14,8 +14,12 @@ import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
import { NgZone } from '@angular/core';
import { PrincipalService } from '../http/principal.service';
import { AppRole } from '@app/core/common/enum/app-role';
+import { AppPermission } from '@app/core/common/enum/permission.enum';
-
+export interface ResolutionContext {
+ roles: AppRole[];
+ permissions: AppPermission[];
+}
export interface AuthenticationState {
loginStatus: LoginStatus;
}
@@ -303,4 +307,37 @@ export class AuthService extends BaseService {
this.zone.run(() => this.router.navigate([returnUrl]));
}
+ public hasPermission(permission: AppPermission): boolean {
+ // if (!this.installationConfiguration.appServiceEnabled) { return true; } //TODO: maybe reconsider
+ return this.evaluatePermission(this.appAccount?.permissions || [], permission);
+
+ }
+ private evaluatePermission(availablePermissions: string[], permissionToCheck: string): boolean {
+ if (!permissionToCheck) { return false; }
+ if (this.hasRole(AppRole.Admin)) { return true; }
+ return availablePermissions.map(x => x.toLowerCase()).includes(permissionToCheck.toLowerCase());
+ }
+ public hasAnyPermission(permissions: AppPermission[]): boolean {
+ if (!permissions) { return false; }
+ return permissions.filter((p) => this.hasPermission(p)).length > 0;
+ }
+
+ public authorize(context: ResolutionContext): boolean {
+
+ if (!context || this.hasRole(AppRole.Admin)) { return true; }
+
+ let roleAuthorized = false;
+ if (context.roles && context.roles.length > 0) {
+ roleAuthorized = this.hasAnyRole(context.roles);
+ }
+
+ let permissionAuthorized = false;
+ if (context.permissions && context.permissions.length > 0) {
+ permissionAuthorized = this.hasAnyPermission(context.permissions);
+ }
+
+ if (roleAuthorized || permissionAuthorized) { return true; }
+
+ return false;
+ }
}