export interface IRolesMap { [ s ] : string [ ] ; } export interface IRole { id : number | string ; name : string ; } export interface IUser { id : number | string ; username : string ; passwordHash : string ; roles : IRole [ ] ; } param roles returns { IRolesMap } export function fillMissingRoles ( roles ) { if ( roles instanceof Array ) { return roles . reduce ( ( accumulator , role ) => ( { ... accumulator , [ role ] : [ ] , } ) , { } ) ; } return Object . entries ( roles ) . reduce ( ( accumulator , [ key , value ] ) => { accumulator [ key ] = value ; value . forEach ( ( role ) => { if ( ! accumulator [ role ] ) { accumulator [ role ] = [ ] ; } } ) ; return accumulator ; } , { } as IRolesMap ) ; } param userRoles param availableRoles returns { string [ ] } export function getDeeperRoles ( userRoles , availableRoles ) { return userRoles . filter ( ( role ) => ! ! availableRoles [ role ] ) . reduce ( ( accumulator , role ) => [ ... accumulator , ... availableRoles [ role ] . filter ( ( roleToAdd ) => ! accumulator . includes ( roleToAdd ) ) , ] , [ ] ) ; } param userRoles param availableRoles returns { string [ ] } export function excludeRoles ( userRoles , availableRoles ) { return Object . entries ( availableRoles ) . filter ( ( [ key , value ] ) => userRoles . indexOf ( key ) < 0 ) . reduce ( ( accumulator , [ key , value ] ) => ( { ... accumulator , [ key ] : value , } ) , { } ) ; } param userRoles param requiredRole param availableRoles returns { boolean } export function checkRole ( userRoles , requiredRole , availableRoles ) { if ( userRoles . length <= 0 ) { return false ; } if ( userRoles . indexOf ( requiredRole ) >= 0 ) { return true ; } return checkRole ( getDeeperRoles ( userRoles , availableRoles ) , requiredRole , excludeRoles ( userRoles , availableRoles ) ) ; } param userRoles param requiredRoles param availableRoles param exact return { boolean } export function checkRoles ( userRoles , requiredRoles , availableRoles , exact = false ) { if ( userRoles . length <= 0 ) { return false ; } return requiredRoles . map ( ( role ) => typeof role === 'object' ? checkRoles ( userRoles , role , availableRoles , true ) : checkRole ( userRoles , role , availableRoles ) ) . reduce ( ( accumulator , currentValue ) => exact ? accumulator && currentValue : accumulator || currentValue ) ; } param { IUser } user param roles param allRoles returns { boolean } export function isGranted ( userRoles , roles , allRoles ) { if ( typeof roles === 'string' ) { return checkRole ( userRoles , roles , allRoles ) ; } if ( typeof roles === 'object' ) { return checkRoles ( userRoles , roles , allRoles ) ; } throw new Error ( 'Unknown role type' ) ; } param { IUser } user param roles param allRoles returns { boolean } export function isUserGranted ( user , roles , allRoles ) { return isGranted ( user . roles . map ( ( role ) => role . name ) , roles , allRoles ) ; } param rolesHierarchy returns { function export default function hierarchyProvider ( rolesHierarchy ) { const fullRoles = fillMissingRoles ( rolesHierarchy ) ; return { isGranted : ( userRoles , roles ) => isGranted ( userRoles , roles , fullRoles ) , isUserGranted : ( user , roles ) => isUserGranted ( user , roles , fullRoles ) , } ; }