UNPKG

@nebular/security

Version:
248 lines (238 loc) 10.2 kB
import * as i0 from '@angular/core'; import { InjectionToken, Injectable, Optional, Inject, Directive, Input, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { map, takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; const NB_SECURITY_OPTIONS_TOKEN = new InjectionToken('Nebular Security Options'); /** * @license * Copyright Akveo. All Rights Reserved. * Licensed under the MIT License. See License.txt in the project root for license information. */ const shallowObjectClone = (o) => Object.assign({}, o); const shallowArrayClone = (a) => Object.assign([], a); const popParent = (abilities) => { const parent = abilities.parent; delete abilities.parent; return parent; }; /** * Common acl service. */ class NbAclService { static { this.ANY_RESOURCE = '*'; } constructor(settings = {}) { this.settings = settings; this.state = {}; if (settings.accessControl) { this.setAccessControl(settings.accessControl); } } /** * Set/Reset ACL list * @param {NbAccessControl} list */ setAccessControl(list) { for (const [role, value] of Object.entries(list)) { const abilities = shallowObjectClone(value); const parent = popParent(abilities); this.register(role, parent, abilities); } } /** * Register a new role with a list of abilities (permission/resources combinations) * @param {string} role * @param {string} parent * @param {[permission: string]: string|string[]} abilities */ register(role, parent = null, abilities = {}) { this.validateRole(role); this.state[role] = { parent: parent, }; for (const [permission, value] of Object.entries(abilities)) { const resources = typeof value === 'string' ? [value] : value; this.allow(role, permission, shallowArrayClone(resources)); } } /** * Allow a permission for specific resources to a role * @param {string} role * @param {string} permission * @param {string | string[]} resource */ allow(role, permission, resource) { this.validateRole(role); if (!this.getRole(role)) { this.register(role, null, {}); } resource = typeof resource === 'string' ? [resource] : resource; let resources = shallowArrayClone(this.getRoleResources(role, permission)); resources = resources.concat(resource); this.state[role][permission] = resources.filter((item, pos) => resources.indexOf(item) === pos); } /** * Check whether the role has a permission to a resource * @param {string} role * @param {string} permission * @param {string} resource * @returns {boolean} */ can(role, permission, resource) { this.validateResource(resource); const parentRole = this.getRoleParent(role); const parentCan = parentRole && this.can(this.getRoleParent(role), permission, resource); return parentCan || this.exactCan(role, permission, resource); } getRole(role) { return this.state[role]; } validateRole(role) { if (!role) { throw new Error('NbAclService: role name cannot be empty'); } } validateResource(resource) { if (!resource || [NbAclService.ANY_RESOURCE].includes(resource)) { throw new Error(`NbAclService: cannot use empty or bulk '*' resource placeholder with 'can' method`); } } exactCan(role, permission, resource) { const resources = this.getRoleResources(role, permission); return resources.includes(resource) || resources.includes(NbAclService.ANY_RESOURCE); } getRoleResources(role, permission) { return this.getRoleAbilities(role)[permission] || []; } getRoleAbilities(role) { const abilities = shallowObjectClone(this.state[role] || {}); popParent(shallowObjectClone(this.state[role] || {})); return abilities; } getRoleParent(role) { return this.state[role] ? this.state[role].parent : null; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbAclService, deps: [{ token: NB_SECURITY_OPTIONS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbAclService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbAclService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NB_SECURITY_OPTIONS_TOKEN] }] }] }); class NbRoleProvider { } /** * @license * Copyright Akveo. All Rights Reserved. * Licensed under the MIT License. See License.txt in the project root for license information. */ /** * Access checker service. * * Injects `NbRoleProvider` to determine current user role, and checks access permissions using `NbAclService` */ class NbAccessChecker { constructor(roleProvider, acl) { this.roleProvider = roleProvider; this.acl = acl; } /** * Checks whether access is granted or not * * @param {string} permission * @param {string} resource * @returns {Observable<boolean>} */ isGranted(permission, resource) { return this.roleProvider.getRole() .pipe(map((role) => Array.isArray(role) ? role : [role]), map((roles) => { return roles.some(role => this.acl.can(role, permission, resource)); })); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbAccessChecker, deps: [{ token: NbRoleProvider }, { token: NbAclService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbAccessChecker }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbAccessChecker, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: NbRoleProvider }, { type: NbAclService }] }); class NbIsGrantedDirective { constructor(templateRef, viewContainer, accessChecker) { this.templateRef = templateRef; this.viewContainer = viewContainer; this.accessChecker = accessChecker; this.destroy$ = new Subject(); this.hasView = false; } set nbIsGranted([permission, resource]) { this.accessChecker.isGranted(permission, resource) .pipe(takeUntil(this.destroy$)) .subscribe((can) => { if (can && !this.hasView) { this.viewContainer.createEmbeddedView(this.templateRef); this.hasView = true; } else if (!can && this.hasView) { this.viewContainer.clear(); this.hasView = false; } }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbIsGrantedDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: NbAccessChecker }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.6", type: NbIsGrantedDirective, isStandalone: false, selector: "[nbIsGranted]", inputs: { nbIsGranted: "nbIsGranted" }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbIsGrantedDirective, decorators: [{ type: Directive, args: [{ selector: '[nbIsGranted]', standalone: false }] }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: NbAccessChecker }], propDecorators: { nbIsGranted: [{ type: Input }] } }); class NbSecurityModule { static forRoot(nbSecurityOptions) { return { ngModule: NbSecurityModule, providers: [ { provide: NB_SECURITY_OPTIONS_TOKEN, useValue: nbSecurityOptions }, NbAclService, NbAccessChecker, ], }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbSecurityModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.6", ngImport: i0, type: NbSecurityModule, declarations: [NbIsGrantedDirective], imports: [CommonModule], exports: [NbIsGrantedDirective] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbSecurityModule, imports: [CommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: NbSecurityModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule, ], declarations: [ NbIsGrantedDirective, ], exports: [ NbIsGrantedDirective, ], }] }] }); /** * @license * Copyright Akveo. All Rights Reserved. * Licensed under the MIT License. See License.txt in the project root for license information. */ /** * Generated bundle index. Do not edit. */ export { NB_SECURITY_OPTIONS_TOKEN, NbAccessChecker, NbAclService, NbIsGrantedDirective, NbRoleProvider, NbSecurityModule }; //# sourceMappingURL=nebular-security.mjs.map