From d93ade9594813a0e5894d631ca304357d7e2d467 Mon Sep 17 00:00:00 2001 From: rubikscraft Date: Mon, 28 Mar 2022 16:57:37 +0200 Subject: [PATCH] refactor frontend guards --- .../validators/permissions.validator.ts | 8 +--- frontend/src/app/guards/permission.guard.ts | 45 ++++++++++++++----- .../src/validators/permissions.validator.ts | 12 +++++ 3 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 shared/src/validators/permissions.validator.ts diff --git a/backend/src/models/validators/permissions.validator.ts b/backend/src/models/validators/permissions.validator.ts index ce423b4..973c4bd 100644 --- a/backend/src/models/validators/permissions.validator.ts +++ b/backend/src/models/validators/permissions.validator.ts @@ -1,10 +1,6 @@ -import { isArray, isEnum, isString } from 'class-validator'; +import { isPermissionsArray as isPArr } from 'picsur-shared/dist/validators/permissions.validator'; import { Permissions, PermissionsList } from '../dto/permissions.dto'; export function isPermissionsArray(value: any): value is Permissions { - if (!isArray(value)) return false; - if (!value.every((item: unknown) => isString(item))) return false; - if (!value.every((item: string) => isEnum(item, PermissionsList))) - return false; - return true; + return isPArr(value, PermissionsList); } diff --git a/frontend/src/app/guards/permission.guard.ts b/frontend/src/app/guards/permission.guard.ts index 7030e44..17812be 100644 --- a/frontend/src/app/guards/permission.guard.ts +++ b/frontend/src/app/guards/permission.guard.ts @@ -6,17 +6,34 @@ import { Router, RouterStateSnapshot } from '@angular/router'; +import { HasFailed } from 'picsur-shared/dist/types'; +import { isPermissionsArray } from 'picsur-shared/dist/validators/permissions.validator'; import { PRouteData } from '../models/picsur-routes'; import { PermissionService } from '../services/api/permission.service'; +import { Logger } from '../services/logger/logger.service'; @Injectable({ providedIn: 'root', }) export class PermissionGuard implements CanActivate, CanActivateChild { + private readonly logger = new Logger('PermissionGuard'); + private allPermissionsArray: string[] | null = null; + constructor( private permissionService: PermissionService, private router: Router - ) {} + ) { + this.setupAllPermissions().catch(this.logger.error); + } + + private async setupAllPermissions() { + const permissions = await this.permissionService.fetchAllPermission(); + if (HasFailed(permissions)) { + return this.logger.error(`Could not fetch all permissions`); + } + + this.allPermissionsArray = permissions; + } async canActivateChild( childRoute: ActivatedRouteSnapshot, @@ -33,25 +50,29 @@ export class PermissionGuard implements CanActivate, CanActivateChild { private async can(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const requiredPermissions: string[] = this.nestedPermissions(route); - // TODO: revive - // if (!isPermissionsArray(requiredPermissions)) { - // throw new Error( - // `PermissionGuard: route data 'permissions' must be an array of Permission values` - // ); - // } + + // Check if permissions array is valid + // But only if we actually have the data + if ( + this.allPermissionsArray !== null && + !isPermissionsArray(requiredPermissions, this.allPermissionsArray) + ) { + this.logger.error(`Permissions array is invalid: ${requiredPermissions}`); + return false; + } const ourPermissions = await this.permissionService.loadedSnapshot(); - - const isOk = requiredPermissions.every((permission) => + const weHavePermission = requiredPermissions.every((permission) => ourPermissions.includes(permission) ); - if (!isOk) { + if (!weHavePermission) this.router.navigate(['/error/401'], { replaceUrl: true }); - } - return isOk; + + return weHavePermission; } + // This aggregates nested permission for deep routes private nestedPermissions(route: ActivatedRouteSnapshot): string[] { const data: PRouteData = route.data; diff --git a/shared/src/validators/permissions.validator.ts b/shared/src/validators/permissions.validator.ts new file mode 100644 index 0000000..d7478f3 --- /dev/null +++ b/shared/src/validators/permissions.validator.ts @@ -0,0 +1,12 @@ +import { isArray, isEnum, isString } from 'class-validator'; + +export function isPermissionsArray( + value: any, + permissionsList: string[], +): value is string[] { + if (!isArray(value)) return false; + if (!value.every((item: unknown) => isString(item))) return false; + if (!value.every((item: string) => isEnum(item, permissionsList))) + return false; + return true; +}