n8n
Version:
n8n Workflow Automation Tool
176 lines • 8.72 kB
JavaScript
;
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