107 lines
3.5 KiB
TypeScript
107 lines
3.5 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
|
|
import { BehaviorSubject, Observable, of } from 'rxjs';
|
|
|
|
import { isArray, isString, toArray } from '../utils';
|
|
import { IqserPermissions, PermissionValidationFn } from '../types';
|
|
import { List } from '../../utils';
|
|
import { map } from 'rxjs/operators';
|
|
|
|
@Injectable({
|
|
providedIn: 'root',
|
|
})
|
|
export class IqserPermissionsService {
|
|
readonly permissions$: Observable<IqserPermissions>;
|
|
readonly #permissions$ = new BehaviorSubject<IqserPermissions>({});
|
|
|
|
constructor() {
|
|
this.permissions$ = this.#permissions$.asObservable();
|
|
}
|
|
|
|
clear(): void {
|
|
this.#permissions$.next({});
|
|
}
|
|
|
|
has(permission: string): boolean;
|
|
has(permissions: List): boolean;
|
|
has(permissions: string | List): boolean;
|
|
has(permissions: string | List): boolean {
|
|
return this.#evaluate(permissions).every(result => result);
|
|
}
|
|
|
|
hasSome(permissions: List | string): boolean {
|
|
return this.#evaluate(permissions).some(result => result);
|
|
}
|
|
|
|
load(permissions: IqserPermissions | List) {
|
|
return this.#reduce(permissions);
|
|
}
|
|
|
|
add(permissions: string | List | IqserPermissions) {
|
|
const _permissions = isString(permissions) ? { [permissions]: () => true } : permissions;
|
|
return this.#reduce(_permissions, this.#permissions$.value);
|
|
}
|
|
|
|
remove(permission: string) {
|
|
const permissions = { ...this.#permissions$.value };
|
|
delete permissions[permission];
|
|
this.#permissions$.next(permissions);
|
|
}
|
|
|
|
get(): IqserPermissions;
|
|
|
|
get(permission: string): PermissionValidationFn | undefined;
|
|
|
|
get(permission?: string): IqserPermissions | PermissionValidationFn | undefined {
|
|
return permission ? this.#permissions$.value[permission] : this.#permissions$.value;
|
|
}
|
|
|
|
has$(permission: string): Observable<boolean>;
|
|
|
|
has$(permissions: List): Observable<boolean>;
|
|
|
|
has$(permissions: string | List): Observable<boolean>;
|
|
|
|
has$(permissions: string | List) {
|
|
const isEmpty = !permissions || permissions.length === 0;
|
|
if (isEmpty) {
|
|
return of(true);
|
|
}
|
|
|
|
return this.permissions$.pipe(
|
|
map(all => toArray(permissions).map(permission => all[permission]?.(permission, all) ?? false)),
|
|
map(results => results.every(result => result)),
|
|
);
|
|
}
|
|
|
|
#evaluate(permissions: List | string) {
|
|
const isEmpty = !permissions || permissions.length === 0;
|
|
if (isEmpty) {
|
|
return [true];
|
|
}
|
|
|
|
const all = this.#permissions$.value;
|
|
return toArray(permissions).map(permission => all[permission]?.(permission, all) ?? false);
|
|
}
|
|
|
|
#reduce(permissions: IqserPermissions | List, initialValue = {} as IqserPermissions) {
|
|
if (isArray(permissions)) {
|
|
return this.#permissions$.next(this.#reduceList(permissions, initialValue));
|
|
}
|
|
|
|
return this.#permissions$.next(this.#reduceObject(permissions, initialValue));
|
|
}
|
|
|
|
#reduceObject(permissions: IqserPermissions, initialValue: IqserPermissions = {}) {
|
|
return Object.entries(permissions).reduce((acc, [permission, validationFn]) => {
|
|
return { ...acc, [permission]: validationFn };
|
|
}, initialValue);
|
|
}
|
|
|
|
#reduceList(permissions: List, initialValue: IqserPermissions = {}): IqserPermissions {
|
|
return permissions.reduce((acc, permission) => {
|
|
return { ...acc, [permission]: () => true };
|
|
}, initialValue);
|
|
}
|
|
}
|