File

src/lib/authorization.service.ts

Index

Properties
Methods

Methods

Public checkPermission
checkPermission(identifier: string | string[], permissions: string[], scope?: string | null)
Parameters :
Name Type Optional
identifier string | string[] No
permissions string[] No
scope string | null Yes
Returns : boolean
Public getPermissions
getPermissions()
Returns : string[]
Public getPermissions$
getPermissions$()
Returns : Observable<string[]>
Public hasPermission
hasPermission(identifier: string | string[], scope?: string | null, ignorePermissionList?: string[])
Parameters :
Name Type Optional
identifier string | string[] No
scope string | null Yes
ignorePermissionList string[] Yes
Returns : boolean
Public hasPermission$
hasPermission$(identifier: string | string[], scope?: string | null, ignorePermissionList?: string[])
Parameters :
Name Type Optional
identifier string | string[] No
scope string | null Yes
ignorePermissionList string[] Yes
Returns : Observable<boolean>
Public setPermissions
setPermissions(permissions: string[])
Parameters :
Name Type Optional
permissions string[] No
Returns : void

Properties

Public Readonly disabled
Default value : inject(RXAP_DISABLE_AUTHORIZATION, { optional: true }) ?? false
Protected Readonly permissions$
Default value : new BehaviorSubject<string[]>([])
import {
  inject,
  Injectable,
  isDevMode,
} from '@angular/core';
import { coerceArray } from '@rxap/utilities';
import {
  BehaviorSubject,
  Observable,
} from 'rxjs';
import {
  distinctUntilChanged,
  map,
} from 'rxjs/operators';
import { RXAP_DISABLE_AUTHORIZATION } from './tokens';

@Injectable({ providedIn: 'root' })
export class AuthorizationService {

  protected readonly permissions$ = new BehaviorSubject<string[]>([]);

  public readonly disabled = inject(RXAP_DISABLE_AUTHORIZATION, { optional: true }) ?? false;

  public setPermissions(permissions: string[]): void {
    this.permissions$.next(permissions);
  }

  public checkPermission(
    identifier: string | string[],
    permissions: string[],
    scope?: string | null,
  ): boolean {

    if (this.disabled) {
      console.warn('Authorization is disabled! Granting all permissions!');
      return true;
    }

    identifier = coerceArray(identifier);

    if (!identifier.length) {
      return true;
    }

    if (isDevMode()) {
      console.log(
        `check permission for [${ identifier.join(', ') }]${ scope ? ` with scope '${ scope }': ` : ' :' }`,
        permissions,
      );
    }

    // holds all permission, but if a scope is defined only permissions without scope
    // or with the matching scope and the scope prefix is removed
    let permissionSubset = permissions;

    if (scope) {
      permissionSubset = permissions
        .filter(
          (permission) =>
            !permission.match(/\//) ||
            permission.match(new RegExp(`^${ scope.replace('.', '\\.') }/`)),
        ).map((permission) =>
          permission.replace(
            new RegExp(`^${ scope.replace('.', '\\.') }/`),
            '',
          ),
        ).sort((a, b) => a.length - b.length);
    }

    if (identifier.every(id => permissionSubset.includes(id))) {
      return true;
    }

    const permissionRegexList = permissionSubset.map((permission) => {

      const permissionRegex = permission
        .replace('.', '\\.')
        .replace('*', '.+');

      if (permission[0] === '*' && permission[permission.length - 1] === '*') {
        return new RegExp(permissionRegex);
      } else if (permission[0] === '*') {
        return new RegExp(`${ permissionRegex }$`);
      } else if (permission[permission.length - 1] === '*') {
        return new RegExp(`^${ permissionRegex }`);
      } else {
        return new RegExp(`^${ permissionRegex }$`);
      }

    });

    return identifier.every(id => permissionRegexList.some((permissionRegex) =>
      id.match(permissionRegex),
    ));
  }

  public hasPermission$(
    identifier: string | string[],
    scope?: string | null,
    ignorePermissionList?: string[],
  ): Observable<boolean> {
    return this.permissions$.pipe(
      map((permissions) => ignorePermissionList ?
        permissions.filter((permission) => !ignorePermissionList.includes(permission)) :
        permissions.slice()),
      map((permissions) =>
        this.checkPermission(identifier, permissions, scope),
      ),
      distinctUntilChanged(),
    );
  }

  public hasPermission(
    identifier: string | string[],
    scope?: string | null,
    ignorePermissionList?: string[],
  ): boolean {
    const allPermissions = this.getPermissions();
    const permissions = ignorePermissionList ?
      allPermissions.filter((permission) => !ignorePermissionList.includes(permission)) :
      allPermissions;

    return this.checkPermission(identifier, permissions, scope);
  }

  public getPermissions$(): Observable<string[]> {
    return this.permissions$.asObservable().pipe(map(permissions => permissions.slice()));
  }

  public getPermissions(): string[] {
    return this.permissions$.value.slice();
  }

}

results matching ""

    No results matching ""