From b8f03b252eeff7163f6b46640e1e3f6279cc53d4 Mon Sep 17 00:00:00 2001 From: ricardo Date: Wed, 30 Mar 2022 23:11:26 -0400 Subject: [PATCH] :zap: Possibility to add custom middleware --- packages/cli/package.json | 2 + packages/cli/src/PublicApi/middlewares.ts | 12 ++ packages/cli/src/PublicApi/v1/index.ts | 128 +++++++++++++--------- packages/cli/src/Server.ts | 4 +- 4 files changed, 93 insertions(+), 53 deletions(-) create mode 100644 packages/cli/src/PublicApi/middlewares.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index eb0d1a7dcc..a10233cf57 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -92,6 +92,7 @@ "typescript": "~4.3.5" }, "dependencies": { + "@apidevtools/swagger-parser": "^10.0.3", "@oclif/command": "^1.5.18", "@oclif/errors": "^1.2.2", "@rudderstack/rudder-sdk-node": "1.0.6", @@ -133,6 +134,7 @@ "nodemailer": "^6.7.1", "oauth-1.0a": "^2.2.6", "open": "^7.0.0", + "openapi-types": "^10.0.0", "p-cancelable": "^2.0.0", "passport": "^0.5.0", "passport-cookie": "^1.0.9", diff --git a/packages/cli/src/PublicApi/middlewares.ts b/packages/cli/src/PublicApi/middlewares.ts new file mode 100644 index 0000000000..a68c3825ec --- /dev/null +++ b/packages/cli/src/PublicApi/middlewares.ts @@ -0,0 +1,12 @@ +import { NextFunction, Request, Response } from 'express'; + +const sayHello = (req: Request, res: Response, next: NextFunction): void => { + console.log('hello'); + console.log('se llamo esta vegra'); + next(); +}; + +export const middlewares = { + getUsers: [sayHello], + getUser: [sayHello], +}; diff --git a/packages/cli/src/PublicApi/v1/index.ts b/packages/cli/src/PublicApi/v1/index.ts index 5b11d9a5c1..ef3115879e 100644 --- a/packages/cli/src/PublicApi/v1/index.ts +++ b/packages/cli/src/PublicApi/v1/index.ts @@ -8,77 +8,103 @@ import express = require('express'); import { HttpError, OpenAPIV3 } from 'express-openapi-validator/dist/framework/types'; import * as bodyParser from 'body-parser'; +import * as SwaggerParser from '@apidevtools/swagger-parser'; // eslint-disable-next-line import/no-cycle import { Db } from '../..'; import config = require('../../../config'); +import { middlewares } from '../middlewares'; + export interface N8nApp { app: Application; } +type OperationID = 'getUsers' | 'getUser' | undefined; + export const publicApiController = express.Router(); publicApiController.use(bodyParser.json()); -publicApiController.use( - `/v1`, - OpenApiValidator.middleware({ - apiSpec: path.join(__dirname, 'openapi.yml'), - operationHandlers: path.join(__dirname), - validateRequests: true, - validateApiSpec: true, - validateSecurity: { - handlers: { - // eslint-disable-next-line @typescript-eslint/naming-convention - ApiKeyAuth: async (req, scopes, schema: OpenAPIV3.ApiKeySecurityScheme) => { - const apiKey = req.headers[schema.name.toLowerCase()]; +void (async () => { + const { paths = {} } = await SwaggerParser.parse(path.join(__dirname, 'openapi.yml')); + Object.entries(paths).forEach(([routePath, methods]) => { + Object.entries(methods).forEach(([method, data]) => { + const operationId: OperationID = ( + data as { + 'x-eov-operation-id': OperationID; + } + )['x-eov-operation-id']; + if (operationId) { + if (method === 'get') { + publicApiController.get( + routePath.replace(/\{([^}]+)}/g, ':$1'), + ...middlewares[operationId], + ); + } + } + }); + }); - const user = await Db.collections.User?.find({ - where: { - apiKey, - }, - relations: ['globalRole'], - }); + publicApiController.use( + '/', + OpenApiValidator.middleware({ + apiSpec: path.join(__dirname, 'openapi.yml'), + operationHandlers: path.join(__dirname), + validateRequests: true, + validateApiSpec: true, + validateSecurity: { + handlers: { + // eslint-disable-next-line @typescript-eslint/naming-convention + ApiKeyAuth: async (req, scopes, schema: OpenAPIV3.ApiKeySecurityScheme) => { + const apiKey = req.headers[schema.name.toLowerCase()]; - if (!user?.length) { - return false; - } + const user = await Db.collections.User?.find({ + where: { + apiKey, + }, + relations: ['globalRole'], + }); - if (!config.get('userManagement.isInstanceOwnerSetUp')) { - // eslint-disable-next-line @typescript-eslint/no-throw-literal - throw { - status: 400, - }; - } + if (!user?.length) { + return false; + } - if (config.get('userManagement.disabled')) { - // eslint-disable-next-line @typescript-eslint/no-throw-literal - throw { - status: 400, - }; - } + if (!config.get('userManagement.isInstanceOwnerSetUp')) { + // eslint-disable-next-line @typescript-eslint/no-throw-literal + throw { + status: 400, + }; + } - if (user[0].globalRole.name !== 'owner') { - // eslint-disable-next-line @typescript-eslint/no-throw-literal - throw { - status: 403, - }; - } + if (config.get('userManagement.disabled')) { + // eslint-disable-next-line @typescript-eslint/no-throw-literal + throw { + status: 400, + }; + } - [req.user] = user; + if (user[0].globalRole.name !== 'owner') { + // eslint-disable-next-line @typescript-eslint/no-throw-literal + throw { + status: 403, + }; + } - return true; + [req.user] = user; + + return true; + }, }, }, - }, - }), -); + }), + ); -// add error handler -// @ts-ignore -publicApiController.use((error: HttpError, req, res: Response) => { - res.status(error.status || 500).json({ - message: error.message, - errors: error.errors, + // add error handler + // @ts-ignore + publicApiController.use((error: HttpError, req, res: Response) => { + res.status(error.status || 500).json({ + message: error.message, + errors: error.errors, + }); }); -}); +})(); diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 802be9ed78..6e69571b7f 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -172,7 +172,7 @@ import { SharedWorkflow } from './databases/entities/SharedWorkflow'; import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from './constants'; import { credentialsController } from './api/credentials.api'; import { getInstanceBaseUrl, isEmailSetUp } from './UserManagement/UserManagementHelper'; -import { publicApiController } from './PublicApi/v1'; +import { publicApiController as publicApiControllerV1 } from './PublicApi/v1'; require('body-parser-xml')(bodyParser); @@ -580,7 +580,7 @@ class App { return ResponseHelper.sendSuccessResponse(res, {}, true, 204); }); - this.app.use(`/${this.publicApiEndpoint}/`, publicApiController); + this.app.use(`/${this.publicApiEndpoint}/v1`, publicApiControllerV1); // Parse cookies for easier access this.app.use(cookieParser());