UNPKG

n8n

Version:

n8n Workflow Automation Tool

176 lines • 8.72 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PublicApiControllerRegistry = void 0; const decorators_1 = require("@n8n/decorators"); const di_1 = require("@n8n/di"); const express_1 = require("express"); const feature_not_licensed_error_1 = require("../errors/feature-not-licensed.error"); const bad_request_error_1 = require("../errors/response-errors/bad-request.error"); const event_service_1 = require("../events/event.service"); const license_1 = require("../license"); const check_access_1 = require("../permissions.ee/check-access"); const public_api_route_resolver_1 = require("../public-api/public-api-route-resolver"); const global_middleware_1 = require("../public-api/v1/shared/middlewares/global.middleware"); const public_api_error_response_1 = require("../public-api/v1/public-api-error-response"); const auth_strategy_registry_1 = require("../services/auth-strategy.registry"); const last_active_at_service_1 = require("../services/last-active-at.service"); let PublicApiControllerRegistry = class PublicApiControllerRegistry { constructor(metadata, authStrategyRegistry, lastActiveAtService, eventService) { this.metadata = metadata; this.authStrategyRegistry = authStrategyRegistry; this.lastActiveAtService = lastActiveAtService; this.eventService = eventService; } activate(router, apiVersion) { for (const controllerClass of this.metadata.controllerClasses) { const metadata = this.metadata.getControllerMetadata(controllerClass); if (!metadata.isPublicApi) continue; this.activateController(router, controllerClass, apiVersion); } } activateController(parent, controllerClass, apiVersion) { const metadata = this.metadata.getControllerMetadata(controllerClass); const controllerRouter = (0, express_1.Router)({ mergeParams: true }); const prefix = metadata.basePath.replace(/\/+/g, '/').replace(/\/$/, '') || '/'; parent.use(prefix === '' ? '/' : prefix, controllerRouter); const controller = di_1.Container.get(controllerClass); const controllerMiddlewares = metadata.middlewares.map((handlerName) => controller[handlerName].bind(controller)); for (const [handlerName, route] of metadata.routes) { const resolvedArgs = (0, public_api_route_resolver_1.resolveRouteArgs)(controllerClass, handlerName, route.args); const successStatus = (0, public_api_route_resolver_1.resolveSuccessStatus)(controllerClass.name, handlerName, route.successStatus); const handler = async (req, res) => { const args = [req, res]; for (const arg of resolvedArgs) { if (arg.type === 'param') { args.push(req.params[arg.key]); } else { const output = arg.dto.safeParse(req[arg.type]); if (output.success) { args.push(output.data); } else { throw new bad_request_error_1.BadRequestError(output.error.errors[0]?.message ?? 'Invalid request'); } } } const result = await controller[handlerName](...args); if (res.headersSent) return; if (successStatus === 204) { res.status(204).send(); return; } if (route.responseDto) { res.status(successStatus).json(route.responseDto.parse(result)); return; } res.status(successStatus).json(result); }; const middlewares = []; if (route.deprecated) { middlewares.push((0, global_middleware_1.deprecated)(route.deprecated)); } middlewares.push(this.createAuthMiddleware(apiVersion)); if (route.apiKeyScope) { middlewares.push(this.createApiKeyScopeMiddleware(route.apiKeyScope)); } if (route.accessScope) { middlewares.push(this.createAccessScopeMiddleware(route.accessScope)); } if (route.licenseFeature) { middlewares.push(this.createLicenseMiddleware(route.licenseFeature)); } middlewares.push(...controllerMiddlewares, ...(route.middlewares ?? [])); const finalHandler = async (req, res, next) => { try { await handler(req, res); } catch (error) { if (res.headersSent) { next(error); return; } (0, public_api_error_response_1.sendPublicApiErrorResponse)(res, error instanceof Error ? error : new Error(String(error))); } }; controllerRouter[route.method](route.path, ...middlewares, finalHandler); } } createAuthMiddleware(apiVersion) { return async (req, res, next) => { const authenticated = await this.authStrategyRegistry.authenticate(req); if (!authenticated) { res.status(401).json({ message: 'Unauthorized' }); return; } const userId = req.user?.id; if (userId) { this.lastActiveAtService.updateLastActiveIfStale(userId).catch(() => undefined); this.eventService.emit('public-api-invoked', { userId, path: req.path, method: req.method, apiVersion, userAgent: req.headers['user-agent'], }); } next(); }; } createApiKeyScopeMiddleware(requirement) { return (req, res, next) => { const { tokenGrant } = req; if (!tokenGrant || !(0, public_api_route_resolver_1.apiKeyScopesSatisfy)(tokenGrant.apiKeyScopes, requirement)) { res.status(403).json({ message: 'Forbidden' }); return; } next(); }; } createLicenseMiddleware(feature) { return (_req, res, next) => { if (!di_1.Container.get(license_1.License).isLicensed(feature)) { res.status(403).json({ message: new feature_not_licensed_error_1.FeatureNotLicensedError(feature).message }); return; } next(); }; } createAccessScopeMiddleware(accessScope) { return async (req, res, next) => { const authReq = req; if (!authReq.user) { res.status(401).json({ message: 'Unauthorized' }); return; } try { if (!(await (0, check_access_1.userHasScopes)(authReq.user, [accessScope.scope], accessScope.globalOnly, req.params))) { res.status(403).json({ message: 'Forbidden' }); return; } } catch (error) { (0, public_api_error_response_1.sendPublicApiErrorResponse)(res, error instanceof Error ? error : new Error(String(error))); return; } next(); }; } }; exports.PublicApiControllerRegistry = PublicApiControllerRegistry; exports.PublicApiControllerRegistry = PublicApiControllerRegistry = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [decorators_1.ControllerRegistryMetadata, auth_strategy_registry_1.AuthStrategyRegistry, last_active_at_service_1.LastActiveAtService, event_service_1.EventService]) ], PublicApiControllerRegistry); //# sourceMappingURL=public-api-controller.registry.js.map