import { IRoute , IMethod } from './IRoute' ; import urlGlob , { convertToPattern } from './helpers/urlGlob' ; import { IUser } from '..' ; import { isUserGranted } from './hierarchyProvider' ; import expressMiddlewareAuthorization from './providers/expressMiddlewareAuthorization' ; let routes = [ ] ; export interface ISecuredRoute { path : string ; methods ? : string [ ] ; roles : string | Array < string | string [ ] > ; } export const getExistsingRoute = ( path , routes ) : IRoute => { for ( const route of routes ) { if ( route . path === path ) { return route ; } } return null ; } ; export const getRoleArray = ( roles ) => { const arr = [ ] ; if ( typeof roles === 'string' ) { arr . push ( roles ) ; } else { roles . forEach ( ( role ) => arr . push ( role ) ) ; } return [ ... new Set ( arr ) ] ; } ; export const getMethodsForExistsingRoute = ( existingRoute , methods , roles ) : IMethod [ ] => { const newMethods = methods . map ( ( method ) => ( { allowedRoles : getRoleArray ( roles ) , name : method , } ) ) ; const existingMethods = existingRoute . methods . filter ( ( method ) => newMethods . map ( ( el ) => el . name ) . indexOf ( method . name ) >= 0 ) ; const nonExistingMethods = newMethods . filter ( ( method ) => existingRoute . methods . map ( ( el ) => el . name ) . indexOf ( method . name ) === - 1 ) ; existingMethods . forEach ( ( method ) => { method . allowedRoles = [ ... new Set ( method . allowedRoles . concat ( getRoleArray ( roles ) ) ) , ] ; } ) ; let methodsFromRoute = existingRoute . methods . filter ( ( method ) => existingMethods . map ( ( el ) => el . name ) . indexOf ( method . name ) === - 1 ) ; methodsFromRoute = methodsFromRoute . concat ( existingMethods ) ; return [ ... methodsFromRoute , ... nonExistingMethods ] ; } ; export const createNewRoute = ( path , methods = [ ] , roles ) => { const methodsForRoute = [ ] ; if ( methods . length > 0 ) { methods = [ ... new Set ( methods ) ] ; methods . forEach ( ( methodName ) => { methodsForRoute . push ( { name : methodName , allowedRoles : getRoleArray ( roles ) , } ) ; } ) ; } else { methodsForRoute . push ( { name : '*' , allowedRoles : getRoleArray ( roles ) , } ) ; } const route = { path : convertToPattern ( path ) , methods : methodsForRoute , } ; return route ; } ; export const initRoutes = ( securedRoutes ) : IRoute [ ] => { const routes = [ ] ; securedRoutes . forEach ( ( route ) => { const existingRoute = getExistsingRoute ( convertToPattern ( route . path ) , routes ) ; if ( existingRoute ) { existingRoute . methods = getMethodsForExistsingRoute ( existingRoute , route . methods , route . roles ) ; } else { routes . push ( createNewRoute ( route . path , route . methods , route . roles ) ) ; } } ) ; return routes ; } ; export const register = ( container , config ) => { if ( config . authSecret ) { container . register ( 'authSecret' , config . authSecret ) ; } routes = initRoutes ( config . securedRoutes || [ ] ) ; const server = container . take ( 'server' ) ; server . use ( config . authorizationMiddleware ? config . authorizationMiddleware ( container ) : expressMiddlewareAuthorization ( container ) ) ; } ; export const getRouteFromPath = ( path , routes ) : IRoute => { const route = routes . filter ( ( r ) => urlGlob ( r . path , path ) ) ; if ( route . length === 0 ) return null ; return route [ 0 ] ; } ; export const isRouteNotSecure = ( path ) => { console . warn ( "HadronAuth: isRouteNotSecure is being deprecated. Use isRouteSecure instead." ) ; return getRouteFromPath ( path , routes ) === null ; } ; export const isRouteSecure = ( path ) => getRouteFromPath ( path , routes ) !== null ; export const isAllowed = ( path , allowedMethod , user , allRoles ) : boolean => { try { const route = getRouteFromPath ( path , routes ) ; let isGranted = false ; route . methods . forEach ( ( method ) => { if ( method . name === '*' || method . name . toLowerCase ( ) === allowedMethod . toLowerCase ( ) ) { if ( method . allowedRoles . includes ( '*' ) && user . roles . length > 0 ) { isGranted = true ; } else { isGranted = isUserGranted ( user , method . allowedRoles , { ALL : allRoles , } ) ; } } } ) ; return isGranted ; } catch ( error ) { throw new Error ( 'Unauthorized' ) ; } } ;