UNPKG

unleash-server

Version:

Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.

125 lines 4.28 kB
import { Router, } from 'express'; import { NONE } from '../types/index.js'; import { handleErrors } from './util.js'; import requireContentType from '../middleware/content_type_checker.js'; import { PermissionError } from '../error/index.js'; import { fromOpenApiValidationErrors } from '../error/bad-data-error.js'; import { storeRequestedRoute } from '../middleware/response-time-metrics.js'; const checkPermission = (permission = []) => async (req, res, next) => { const permissions = (Array.isArray(permission) ? permission : [permission]).filter((p) => p !== NONE); if (!permissions.length) { return next(); } if (req.checkRbac && (await req.checkRbac(permissions))) { return next(); } return res.status(403).json(new PermissionError(permissions)).end(); }; const checkPrivateProjectPermissions = () => async (req, res, next) => { if (!req.checkPrivateProjectPermissions || (await req.checkPrivateProjectPermissions())) { return next(); } return res.status(404).end(); }; const openAPIValidationMiddleware = async (err, req, res, next) => { if (err?.status && err.validationErrors) { const apiError = fromOpenApiValidationErrors(req, err.validationErrors); res.status(apiError.statusCode).json(apiError); } else { next(err); } }; /** * Base class for Controllers to standardize binding to express Router. * * This class will take care of the following: * - try/catch inside RequestHandler * - await if the RequestHandler returns a promise. * - access control */ export default class Controller { constructor(config) { this.ownLogger = config.getLogger(`controller/${this.constructor.name}`); this.app = Router(); this.config = config; } useRouteErrorHandler(handler) { return async (req, res) => { try { await handler(req, res); } catch (error) { handleErrors(res, this.ownLogger, error); } }; } useContentTypeMiddleware(options) { const { middleware = [], acceptedContentTypes = [] } = options; return options.method === 'get' || options.acceptAnyContentType ? middleware : [requireContentType(...acceptedContentTypes), ...middleware]; } route(options) { this.app[options.method](options.path, storeRequestedRoute, checkPermission(options.permission), checkPrivateProjectPermissions(), this.useContentTypeMiddleware(options), this.useRouteErrorHandler(options.handler.bind(this))); this.app.use(options.path, openAPIValidationMiddleware); } get(path, handler, permission = NONE) { this.route({ method: 'get', path, handler, permission, }); } post(path, handler, permission = NONE, ...acceptedContentTypes) { this.route({ method: 'post', path, handler, permission, acceptedContentTypes, }); } put(path, handler, permission = NONE, ...acceptedContentTypes) { this.route({ method: 'put', path, handler, permission, acceptedContentTypes, }); } patch(path, handler, permission = NONE, ...acceptedContentTypes) { this.route({ method: 'patch', path, handler, permission, acceptedContentTypes, }); } delete(path, handler, permission = NONE) { this.route({ method: 'delete', path, handler, permission, acceptAnyContentType: true, }); } fileupload(path, filehandler, handler, permission = NONE) { this.app.post(path, storeRequestedRoute, checkPermission(permission), checkPrivateProjectPermissions(), filehandler.bind(this), this.useRouteErrorHandler(handler.bind(this))); } use(path, router) { this.app.use(path, router); } useWithMiddleware(path, router, middleware) { this.app.use(path, middleware, router); } get router() { return this.app; } } //# sourceMappingURL=controller.js.map