task #9088 Authorization model should be changed to be Permission based

This commit is contained in:
Efstratios Giannopoulos 2023-10-17 15:22:05 +03:00
parent 419c4d64f8
commit 7ed111e936
21 changed files with 302 additions and 72 deletions

View File

@ -21,6 +21,11 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authz</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,10 @@
package eu.eudat.authorization;
import java.util.EnumSet;
public enum AuthorizationFlags {
None, Permission, Owner;
public static final EnumSet<AuthorizationFlags> OwnerOrPermission = EnumSet.of(Owner, Permission);
public static final EnumSet<AuthorizationFlags> OwnerOrPermissionOrIndicator = EnumSet.of(Owner, Permission);
public static final EnumSet<AuthorizationFlags> OwnerOrPermissionOrIndicatorOrIndicatorAccess = EnumSet.of(Owner, Permission);
}

View File

@ -0,0 +1,6 @@
package eu.eudat.authorization;
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
public class OwnedAuthorizationRequirement implements AuthorizationRequirement {
}

View File

@ -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<UUID> userIds;
public OwnedResource(UUID userId) {
this(List.of(userId));
}
public OwnedResource(List<UUID> userIds) {
this.userIds = userIds;
}
public List<UUID> getUserIds() {
return userIds;
}
public void setUserIds(List<UUID> userIds) {
this.userIds = userIds;
}
}

View File

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

View File

@ -1,4 +1,4 @@
package eu.eudat.commons.scope; package eu.eudat.commons.scope.user;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,6 +1,8 @@
package eu.eudat.model.censorship; package eu.eudat.model.censorship;
import eu.eudat.authorization.Permission;
import eu.eudat.convention.ConventionService; import eu.eudat.convention.ConventionService;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry; import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
@ -14,15 +16,17 @@ import org.springframework.stereotype.Component;
public class DescriptionTemplateTypeCensor extends BaseCensor{ public class DescriptionTemplateTypeCensor extends BaseCensor{
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeCensor.class)); private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeCensor.class));
protected final AuthorizationService authService;
public DescriptionTemplateTypeCensor(ConventionService conventionService) { public DescriptionTemplateTypeCensor(ConventionService conventionService, AuthorizationService authService) {
super(conventionService); super(conventionService);
this.authService = authService;
} }
public void censor(FieldSet fields) { public void censor(FieldSet fields) {
logger.debug(new DataLogEntry("censoring fields", fields)); logger.debug(new DataLogEntry("censoring fields", fields));
if (fields.isEmpty()) if (fields.isEmpty()) return;
return;
this.authService.authorizeForce(Permission.BrowseDescriptionTemplateType);
} }
} }

View File

@ -329,6 +329,12 @@
<version>2.1.0</version> <version>2.1.0</version>
</dependency> </dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authz</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>

View File

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

View File

@ -1,6 +1,16 @@
package eu.eudat.configurations; 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 gr.cite.commons.web.oidc.configuration.WebSecurityProperties;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; 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.Filter;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
public class SecurityConfiguration { public class SecurityConfiguration {
private final WebSecurityProperties webSecurityProperties; private final WebSecurityProperties webSecurityProperties;
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver; private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
private final Filter apiKeyFilter; private final Filter apiKeyFilter;
private final OwnedAuthorizationHandler ownedAuthorizationHandler;
@Autowired @Autowired
public SecurityConfiguration(WebSecurityProperties webSecurityProperties, public SecurityConfiguration(WebSecurityProperties webSecurityProperties,
@Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver, @Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver,
@Qualifier("apiKeyFilter") Filter apiKeyFilter) { @Qualifier("apiKeyFilter") Filter apiKeyFilter,
@Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler) {
this.webSecurityProperties = webSecurityProperties; this.webSecurityProperties = webSecurityProperties;
this.authenticationManagerResolver = authenticationManagerResolver; this.authenticationManagerResolver = authenticationManagerResolver;
this.apiKeyFilter = apiKeyFilter; this.apiKeyFilter = apiKeyFilter;
this.ownedAuthorizationHandler = ownedAuthorizationHandler;
} }
@Bean @Bean
@ -52,60 +66,61 @@ public class SecurityConfiguration {
return tempHttp.build(); return tempHttp.build();
} }
// @Bean @Bean
// AuthorizationPolicyConfigurer authorizationPolicyConfigurer() { AuthorizationPolicyConfigurer authorizationPolicyConfigurer() {
// return new AuthorizationPolicyConfigurer() { return new AuthorizationPolicyConfigurer() {
//
// @Override @Override
// public AuthorizationPolicyResolverStrategy strategy() { public AuthorizationPolicyResolverStrategy strategy() {
// return AuthorizationPolicyResolverStrategy.STRICT_CONSENSUS_BASED; return AuthorizationPolicyResolverStrategy.STRICT_CONSENSUS_BASED;
// } }
//
// //Here you can register your custom authorization handlers, which will get used as well as the existing ones //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 //This is optional and can be omitted
// //If not set / set to null, only the default authorization handlers will be used //If not set / set to null, only the default authorization handlers will be used
// @Override @Override
// public List<AuthorizationHandler<? extends AuthorizationRequirement>> addCustomHandlers() { public List<AuthorizationHandler<? extends AuthorizationRequirement>> addCustomHandlers() {
// return null; return List.of( ownedAuthorizationHandler);
// } }
//
// //Here you can register your custom authorization requirements (if any) //Here you can register your custom authorization requirements (if any)
// //This is optional and can be omitted //This is optional and can be omitted
// //If not set / set to null, only the default authorization requirements will be used //If not set / set to null, only the default authorization requirements will be used
// @Override @Override
// public List<? extends AuthorizationRequirement> extendRequirements() { public List<? extends AuthorizationRequirement> extendRequirements() {
// return List.of( return List.of(
//// new TimeOfDayAuthorizationRequirement(new TimeOfDay("08:00","16:00"), true) // 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 //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) //You can disable any handler (including any custom one)
// //This is optional and can be omitted //This is optional and can be omitted
// //If not set / set to null, all the handlers will be invoked, based on their requirement support //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 //In the example below, the default client handler will be ignored by the resolver
// @Override @Override
// public List<Class<? extends AuthorizationHandler<? extends AuthorizationRequirement>>> disableHandlers() { public List<Class<? extends AuthorizationHandler<? extends AuthorizationRequirement>>> disableHandlers() {
// return List.of(PermissionClientAuthorizationHandler.class); return List.of(PermissionClientAuthorizationHandler.class);
// } }
// }; };
// } }
//
// @Bean @Bean
// AuthorizationRequirementMapper authorizationRequirementMapper() { AuthorizationRequirementMapper authorizationRequirementMapper() {
// return new AuthorizationRequirementMapper() { return new AuthorizationRequirementMapper() {
// @Override @Override
// public AuthorizationRequirement map(AuthorizationResource resource, boolean matchAll, String[] permissions) { public AuthorizationRequirement map(AuthorizationResource resource, boolean matchAll, String[] permissions) {
// Class<?> type = resource.getClass(); Class<?> type = resource.getClass();
// if (!AuthorizationResource.class.isAssignableFrom(type)) throw new IllegalArgumentException("resource"); if (!AuthorizationResource.class.isAssignableFrom(type)) throw new IllegalArgumentException("resource");
//
// if (OwnedResource.class.equals(type)) { if (OwnedResource.class.equals(type)) {
// return new OwnedAuthorizationRequirement(); return new OwnedAuthorizationRequirement();
// } }
// throw new IllegalArgumentException("resource"); throw new IllegalArgumentException("resource");
// } }
// }; };
// } }
private String[] buildAntPatterns(Set<String> endpoints) { private String[] buildAntPatterns(Set<String> endpoints) {
if (endpoints == null) { if (endpoints == null) {

View File

@ -1,6 +1,6 @@
package eu.eudat.configurations; 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.interceptors.UserInterceptor;
import eu.eudat.logic.handlers.PrincipalArgumentResolver; import eu.eudat.logic.handlers.PrincipalArgumentResolver;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;

View File

@ -55,7 +55,8 @@ public class PrincipalController {
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._authenticatedAt), BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._authenticatedAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._expiresAt), BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._expiresAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._more), BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._more),
Account._roles); Account._roles,
Account._permissions);
} }
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal(); MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();

View File

@ -3,16 +3,14 @@ package eu.eudat.interceptors;
import eu.eudat.commons.enums.ProviderType; import eu.eudat.commons.enums.ProviderType;
import eu.eudat.commons.enums.Status; 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.CredentialEntity;
import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole; import eu.eudat.data.entities.UserRole;
import eu.eudat.exceptions.security.NullEmailException; import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.query.CredentialQuery;
import eu.eudat.types.Authorities; import eu.eudat.types.Authorities;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver; import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; 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.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
@ -72,6 +70,7 @@ public class UserInterceptor implements WebRequestInterceptor {
UUID userId = null; UUID userId = null;
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) { if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal()); 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)); UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
if (cacheValue != null) { if (cacheValue != null) {
userId = cacheValue.getUserId(); userId = cacheValue.getUserId();

View File

@ -1,6 +1,6 @@
package eu.eudat.logic.handlers; 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.exceptions.security.UnauthorisedException;
import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.operations.authentication.AuthenticationService; import eu.eudat.logic.services.operations.authentication.AuthenticationService;

View File

@ -139,6 +139,9 @@ public class Account {
public final static String _principal = "principal"; public final static String _principal = "principal";
private PrincipalInfo principal; private PrincipalInfo principal;
public final static String _permissions = "permissions";
private List<String> permissions;
public PrincipalInfo getPrincipal() { public PrincipalInfo getPrincipal() {
return principal; return principal;
} }
@ -162,4 +165,16 @@ public class Account {
public void setRoles(List<Integer> roles) { public void setRoles(List<Integer> roles) {
this.roles = roles; this.roles = roles;
} }
public void setAuthenticated(Boolean authenticated) {
isAuthenticated = authenticated;
}
public List<String> getPermissions() {
return permissions;
}
public void setPermissions(List<String> permissions) {
this.permissions = permissions;
}
} }

View File

@ -1,10 +1,10 @@
package eu.eudat.models.v2; 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.UserInfo;
import eu.eudat.data.entities.UserRole; import eu.eudat.data.entities.UserRole;
import eu.eudat.logic.services.ApiContext; 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.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal; import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor; import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
@ -24,11 +24,13 @@ public class AccountBuilder {
private final ClaimExtractor claimExtractor; private final ClaimExtractor claimExtractor;
private final Set<String> excludeMoreClaim; private final Set<String> excludeMoreClaim;
private final CurrentPrincipalResolver currentPrincipalResolver; private final CurrentPrincipalResolver currentPrincipalResolver;
private final AuthorizationConfiguration authorizationConfiguration;
private final ApiContext apiContext; private final ApiContext apiContext;
private final UserScope userScope; 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.claimExtractor = claimExtractor;
this.currentPrincipalResolver = currentPrincipalResolver; this.currentPrincipalResolver = currentPrincipalResolver;
this.authorizationConfiguration = authorizationConfiguration;
this.apiContext = apiContext; this.apiContext = apiContext;
this.userScope = userScope; this.userScope = userScope;
this.excludeMoreClaim = Set.of( this.excludeMoreClaim = Set.of(
@ -93,6 +95,11 @@ public class AccountBuilder {
model.getRoles().add(item.getRole()); model.getRoles().add(item.getRole());
} }
} }
if (fields.hasField(Account._permissions)) {
List<String> roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
Set<String> permissions = authorizationConfiguration.permissionsOfRoles(roles);
model.setPermissions(new ArrayList<>(permissions));
}
return model; return model;
} }
} }

View File

@ -4,6 +4,7 @@ spring:
config: config:
import: optional:classpath:config/app.env[.properties], optional:file:../config/app.env[.properties], 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/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/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/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], optional:classpath:config/logging.yml[.yml], optional:classpath:config/logging-${spring.profiles.active}.yml[.yml], optional:file:../config/logging-${spring.profiles.active}.yml[.yml],

View File

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

View File

@ -0,0 +1,10 @@
export enum AppPermission {
//DescriptionTemplateType
BrowseDescriptionTemplateType = "BrowseDescriptionTemplateType",
EditDescriptionTemplateType = "EditDescriptionTemplateType",
DeleteDescriptionTemplateType = "DeleteDescriptionTemplateType",
// UI Pages
ViewDescriptionTemplateTypePage = "ViewDescriptionTemplateTypePage"
}

View File

@ -1,10 +1,12 @@
import { AppRole } from "@app/core/common/enum/app-role"; import { AppRole } from "@app/core/common/enum/app-role";
import { AppPermission } from "@app/core/common/enum/permission.enum";
import { Guid } from "@common/types/guid"; import { Guid } from "@common/types/guid";
export interface AppAccount { export interface AppAccount {
isAuthenticated: boolean; isAuthenticated: boolean;
// permissions: AppPermission[]; // permissions: AppPermission[];
roles: AppRole[]; roles: AppRole[];
permissions: AppPermission[];
principal: AppPrincipalInfo; principal: AppPrincipalInfo;
profile: UserProfileInfo; profile: UserProfileInfo;
} }

View File

@ -14,8 +14,12 @@ import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
import { NgZone } from '@angular/core'; import { NgZone } from '@angular/core';
import { PrincipalService } from '../http/principal.service'; import { PrincipalService } from '../http/principal.service';
import { AppRole } from '@app/core/common/enum/app-role'; 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 { export interface AuthenticationState {
loginStatus: LoginStatus; loginStatus: LoginStatus;
} }
@ -303,4 +307,37 @@ export class AuthService extends BaseService {
this.zone.run(() => this.router.navigate([returnUrl])); 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;
}
} }