import { Inject , Injectable , Optional } from '@nestjs/common' ; import { IStorageRbac } from '../interfaces/storage.rbac.interface' ; import { ModuleRef } from '@nestjs/core' ; import { IDynamicStorageRbac } from '../interfaces/dynamic.storage.rbac.interface' ; import { ICacheRBAC } from '../interfaces/cache.rbac.interface' ; @ Injectable ( ) export class StorageRbacService { constructor ( private readonly moduleRef , private readonly rbac , @ Optional ( ) @ Inject ( 'ICacheRBAC' ) private readonly cache ? ) { } async getStorage ( ) { return await this . rbac . getRbac ( ) ; } async getPermissions ( ) { return ( await this . rbac . getRbac ( ) ) . permissions ; } async getGrants ( ) { return ( await this . rbac . getRbac ( ) ) . grants ; } async getRoles ( ) { return ( await this . rbac . getRbac ( ) ) . roles ; } async getGrant ( role ) { const grant = await this . parseGrants ( ) ; return grant [ role ] || [ ] ; } async getFilters ( ) { const result = { } ; const filters = ( await this . getStorage ( ) ) . filters ; for ( const key in filters ) { let filter ; try { filter = this . moduleRef . get ( filters [ key ] ) ; } catch ( e ) { filter = await this . moduleRef . create ( filters [ key ] ) ; } result [ key ] = filter ; } return result ; } private async parseGrants ( ) { if ( this . cache ) { const cache = await this . getFromCache ( ) ; if ( cache ) { return cache ; } } const { grants , permissions } = await this . rbac . getRbac ( ) ; const result = { } ; Object . keys ( grants ) . forEach ( ( key ) => { const grant = grants [ key ] ; result [ key ] = [ ... new Set ( grant . filter ( ( value ) => ! value . startsWith ( '&' ) ) ) , ] . filter ( ( value ) => { if ( value . includes ( '@' ) ) { const spilt = value . split ( '@' ) ; if ( ! permissions [ spilt [ 0 ] ] ) { return false ; } return permissions [ spilt [ 0 ] ] . some ( ( inAction ) => inAction === spilt [ 1 ] ) ; } if ( permissions [ value ] ) { return permissions [ value ] ; } } ) ; } ) ; const findExtendedGrants = { } ; Object . keys ( grants ) . forEach ( ( key ) => { const grant = grants [ key ] ; findExtendedGrants [ key ] = [ ... new Set ( grant . filter ( ( value ) => { if ( value . startsWith ( '&' ) ) { const subGrant = value . substr ( 1 ) ; if ( grants [ value . substr ( 1 ) ] && subGrant !== key ) { return true ; } } return false ; } ) . map ( value => value . substr ( 1 ) ) ) , ] ; } ) ; Object . keys ( findExtendedGrants ) . forEach ( ( key ) => { const grant = findExtendedGrants [ key ] ; grant . forEach ( ( value ) => { result [ key ] = [ ... new Set ( [ ... result [ key ] , ... result [ value ] ] ) ] ; } ) ; } ) ; Object . keys ( result ) . forEach ( ( key ) => { const grant = result [ key ] ; const per = [ ] ; grant . forEach ( ( value ) => { if ( ! value . includes ( '@' ) ) { per . push ( ... permissions [ value ] . map ( ( dd ) => { return `${ value }@${ dd }` ; } ) ) ; } } ) ; result [ key ] = [ ... new Set ( [ ... result [ key ] , ... per ] ) ] ; } ) ; if ( this . cache ) { this . setIntoCache ( result ) ; } return result ; } private async getFromCache ( ) { return this . cache . get ( ) ; } private async setIntoCache ( value ) { await this . cache . set ( value ) ; } }