UNPKG

@nmshd/typescript-rest

Version:

A Library to create RESTFul APIs with Typescript

50 lines 2.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.routeRequiresAuthorization = routeRequiresAuthorization; const debug = require("debug"); const Errors = require("../server/model/errors"); const debuggerInstance = debug('typescript-rest:middlewares:routeRequiresAuthorization'); function routeRequiresAuthorization(authenticator, ...permittedRoles) { if (permittedRoles.length === 0) throw new Error('At least one permitted role must be specified.'); const roleRegex = /^[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+){0,}$/; const nonMatchingRoles = permittedRoles.filter((role) => !roleRegex.test(role)); if (nonMatchingRoles.length > 0) { throw new Error(`Invalid permitted role(s) specified: ${nonMatchingRoles.join(', ')}. Roles must match the pattern: ${roleRegex}.`); } return (req, res, next) => { const rawUserRoles = authenticator.getRoles(req, res); if (debuggerInstance.enabled) debuggerInstance('Validating authentication roles: <%j>.', rawUserRoles); const userRoles = rawUserRoles.map(Role.from); const isAuthorized = permittedRoles.some((r) => isRoleMatched(r, userRoles)); if (!isAuthorized) { next(new Errors.ForbiddenError('You are not allowed to access this endpoint.')); return; } next(); }; } function isRoleMatched(permittedRole, userRoles) { return userRoles.some((userRole) => userRole.matches(permittedRole)); } class Role { constructor(role) { this.roleRegex = this.transformUserRole(role); } static from(role) { return new Role(role); } transformUserRole(userRole) { if (!userRole.includes('*')) return new RegExp(`^${userRole}$`); const regexString = userRole .replaceAll('**', '[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+){0,}') .replaceAll('*', '[a-zA-Z0-9_-]+'); return new RegExp(`^${regexString}$`); } matches(permittedRole) { return this.roleRegex.test(permittedRole); } } //# sourceMappingURL=routeRequiresAuthorization.js.map