refactor frontend guards
This commit is contained in:
parent
060247c0db
commit
d93ade9594
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
12
shared/src/validators/permissions.validator.ts
Normal file
12
shared/src/validators/permissions.validator.ts
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue