refactor(core): Consolidate executions controllers (no-changelog) (#8349)

This commit is contained in:
Iván Ovejero 2024-01-16 16:52:21 +01:00 committed by GitHub
parent b267bf07e3
commit 7bb2d1799e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 64 additions and 166 deletions

View file

@ -39,7 +39,8 @@ import {
TEMPLATES_DIR, TEMPLATES_DIR,
} from '@/constants'; } from '@/constants';
import { credentialsController } from '@/credentials/credentials.controller'; import { credentialsController } from '@/credentials/credentials.controller';
import type { CurlHelper, ExecutionRequest } from '@/requests'; import type { CurlHelper } from '@/requests';
import type { ExecutionRequest } from '@/executions/execution.request';
import { registerController } from '@/decorators'; import { registerController } from '@/decorators';
import { AuthController } from '@/controllers/auth.controller'; import { AuthController } from '@/controllers/auth.controller';
import { BinaryDataController } from '@/controllers/binaryData.controller'; import { BinaryDataController } from '@/controllers/binaryData.controller';
@ -56,7 +57,7 @@ import { TranslationController } from '@/controllers/translation.controller';
import { UsersController } from '@/controllers/users.controller'; import { UsersController } from '@/controllers/users.controller';
import { WorkflowStatisticsController } from '@/controllers/workflowStatistics.controller'; import { WorkflowStatisticsController } from '@/controllers/workflowStatistics.controller';
import { ExternalSecretsController } from '@/ExternalSecrets/ExternalSecrets.controller.ee'; import { ExternalSecretsController } from '@/ExternalSecrets/ExternalSecrets.controller.ee';
import { executionsController } from '@/executions/executions.controller'; import { ExecutionsController } from '@/executions/executions.controller';
import { isApiEnabled, loadPublicApiVersions } from '@/PublicApi'; import { isApiEnabled, loadPublicApiVersions } from '@/PublicApi';
import type { ICredentialsOverwrite, IDiagnosticInfo, IExecutionsStopData } from '@/Interfaces'; import type { ICredentialsOverwrite, IDiagnosticInfo, IExecutionsStopData } from '@/Interfaces';
import { ActiveExecutions } from '@/ActiveExecutions'; import { ActiveExecutions } from '@/ActiveExecutions';
@ -247,6 +248,7 @@ export class Server extends AbstractServer {
RoleController, RoleController,
ActiveWorkflowsController, ActiveWorkflowsController,
WorkflowsController, WorkflowsController,
ExecutionsController,
]; ];
if (process.env.NODE_ENV !== 'production' && Container.get(MultiMainSetup).isEnabled) { if (process.env.NODE_ENV !== 'production' && Container.get(MultiMainSetup).isEnabled) {
@ -397,12 +399,6 @@ export class Server extends AbstractServer {
}), }),
); );
// ----------------------------------------
// Executions
// ----------------------------------------
this.app.use(`/${this.restEndpoint}/executions`, executionsController);
// ---------------------------------------- // ----------------------------------------
// Executing Workflows // Executing Workflows
// ---------------------------------------- // ----------------------------------------

View file

@ -4,7 +4,7 @@ import type { WorkflowStatistics } from '@db/entities/WorkflowStatistics';
import { StatisticsNames } from '@db/entities/WorkflowStatistics'; import { StatisticsNames } from '@db/entities/WorkflowStatistics';
import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository';
import { WorkflowStatisticsRepository } from '@db/repositories/workflowStatistics.repository'; import { WorkflowStatisticsRepository } from '@db/repositories/workflowStatistics.repository';
import { ExecutionRequest } from '@/requests'; import { ExecutionRequest } from '@/executions/execution.request';
import type { IWorkflowStatisticsDataLoaded } from '@/Interfaces'; import type { IWorkflowStatisticsDataLoaded } from '@/Interfaces';
import { Logger } from '@/Logger'; import { Logger } from '@/Logger';
import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error';

View file

@ -0,0 +1,29 @@
import type { IExecutionDeleteFilter } from '@/Interfaces';
import type { AuthenticatedRequest } from '@/requests';
export declare namespace ExecutionRequest {
namespace QueryParam {
type GetAll = {
filter: string; // '{ waitTill: string; finished: boolean, [other: string]: string }'
limit: string;
lastId: string;
firstId: string;
};
type GetAllCurrent = {
filter: string; // '{ workflowId: string }'
};
}
type GetAll = AuthenticatedRequest<{}, {}, {}, QueryParam.GetAll>;
type Get = AuthenticatedRequest<{ id: string }, {}, {}, { unflattedResponse: 'true' | 'false' }>;
type Delete = AuthenticatedRequest<{}, {}, IExecutionDeleteFilter>;
type Retry = AuthenticatedRequest<{ id: string }, {}, { loadWorkflow: boolean }, {}>;
type Stop = AuthenticatedRequest<{ id: string }>;
type GetAllCurrent = AuthenticatedRequest<{}, {}, {}, QueryParam.GetAllCurrent>;
}

View file

@ -1,68 +0,0 @@
import express from 'express';
import type {
IExecutionFlattedResponse,
IExecutionResponse,
IExecutionsListResponse,
} from '@/Interfaces';
import type { ExecutionRequest } from '@/requests';
import * as ResponseHelper from '@/ResponseHelper';
import { isSharingEnabled } from '@/UserManagement/UserManagementHelper';
import { EEExecutionsService } from './executions.service.ee';
export const EEExecutionsController = express.Router();
EEExecutionsController.use((req, res, next) => {
if (!isSharingEnabled()) {
// skip ee router and use free one
next('router');
return;
}
// use ee router
next();
});
/**
* GET /executions
*/
EEExecutionsController.get(
'/',
ResponseHelper.send(async (req: ExecutionRequest.GetAll): Promise<IExecutionsListResponse> => {
return EEExecutionsService.getExecutionsList(req);
}),
);
/**
* GET /executions/:id
*/
EEExecutionsController.get(
'/:id(\\d+)',
ResponseHelper.send(
async (
req: ExecutionRequest.Get,
): Promise<IExecutionResponse | IExecutionFlattedResponse | undefined> => {
return EEExecutionsService.getExecution(req);
},
),
);
/**
* POST /executions/:id/retry
*/
EEExecutionsController.post(
'/:id/retry',
ResponseHelper.send(async (req: ExecutionRequest.Retry): Promise<boolean> => {
return EEExecutionsService.retryExecution(req);
}),
);
/**
* POST /executions/delete
* INFORMATION: We use POST instead of DELETE to not run into any issues with the query data
* getting too long
*/
EEExecutionsController.post(
'/delete',
ResponseHelper.send(async (req: ExecutionRequest.Delete): Promise<void> => {
await EEExecutionsService.deleteExecutions(req);
}),
);

View file

@ -1,59 +1,31 @@
import express from 'express'; import { ExecutionRequest } from './execution.request';
import type {
IExecutionFlattedResponse,
IExecutionResponse,
IExecutionsListResponse,
} from '@/Interfaces';
import * as ResponseHelper from '@/ResponseHelper';
import type { ExecutionRequest } from '@/requests';
import { EEExecutionsController } from './executions.controller.ee';
import { ExecutionsService } from './executions.service'; import { ExecutionsService } from './executions.service';
import { Authorized, Get, Post, RestController } from '@/decorators';
import { EnterpriseExecutionsService } from './executions.service.ee';
import { isSharingEnabled } from '@/UserManagement/UserManagementHelper';
export const executionsController = express.Router(); @Authorized()
executionsController.use('/', EEExecutionsController); @RestController('/executions')
export class ExecutionsController {
/** @Get('/')
* GET /executions async getExecutionsList(req: ExecutionRequest.GetAll) {
*/
executionsController.get(
'/',
ResponseHelper.send(async (req: ExecutionRequest.GetAll): Promise<IExecutionsListResponse> => {
return ExecutionsService.getExecutionsList(req); return ExecutionsService.getExecutionsList(req);
}), }
);
/** @Get('/:id')
* GET /executions/:id async getExecution(req: ExecutionRequest.Get) {
*/ return isSharingEnabled()
executionsController.get( ? EnterpriseExecutionsService.getExecution(req)
'/:id(\\d+)', : ExecutionsService.getExecution(req);
ResponseHelper.send( }
async (
req: ExecutionRequest.Get,
): Promise<IExecutionResponse | IExecutionFlattedResponse | undefined> => {
return ExecutionsService.getExecution(req);
},
),
);
/** @Post('/:id/retry')
* POST /executions/:id/retry async retryExecution(req: ExecutionRequest.Retry) {
*/
executionsController.post(
'/:id/retry',
ResponseHelper.send(async (req: ExecutionRequest.Retry): Promise<boolean> => {
return ExecutionsService.retryExecution(req); return ExecutionsService.retryExecution(req);
}), }
);
/** @Post('/delete')
* POST /executions/delete async deleteExecutions(req: ExecutionRequest.Delete) {
* INFORMATION: We use POST instead of DELETE to not run into any issues with the query data return ExecutionsService.deleteExecutions(req);
* getting too long }
*/ }
executionsController.post(
'/delete',
ResponseHelper.send(async (req: ExecutionRequest.Delete): Promise<void> => {
await ExecutionsService.deleteExecutions(req);
}),
);

View file

@ -1,14 +1,14 @@
import type { User } from '@db/entities/User'; import type { User } from '@db/entities/User';
import { getSharedWorkflowIds } from '@/WorkflowHelpers'; import { getSharedWorkflowIds } from '@/WorkflowHelpers';
import { ExecutionsService } from './executions.service'; import { ExecutionsService } from './executions.service';
import type { ExecutionRequest } from '@/requests'; import type { ExecutionRequest } from './execution.request';
import type { IExecutionResponse, IExecutionFlattedResponse } from '@/Interfaces'; import type { IExecutionResponse, IExecutionFlattedResponse } from '@/Interfaces';
import { EnterpriseWorkflowService } from '../workflows/workflow.service.ee'; import { EnterpriseWorkflowService } from '../workflows/workflow.service.ee';
import type { WorkflowWithSharingsAndCredentials } from '@/workflows/workflows.types'; import type { WorkflowWithSharingsAndCredentials } from '@/workflows/workflows.types';
import Container from 'typedi'; import Container from 'typedi';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository'; import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
export class EEExecutionsService extends ExecutionsService { export class EnterpriseExecutionsService extends ExecutionsService {
/** /**
* Function to get the workflow Ids for a User regardless of role * Function to get the workflow Ids for a User regardless of role
*/ */

View file

@ -21,7 +21,7 @@ import type {
} from '@/Interfaces'; } from '@/Interfaces';
import { NodeTypes } from '@/NodeTypes'; import { NodeTypes } from '@/NodeTypes';
import { Queue } from '@/Queue'; import { Queue } from '@/Queue';
import type { ExecutionRequest } from '@/requests'; import type { ExecutionRequest } from './execution.request';
import { getSharedWorkflowIds } from '@/WorkflowHelpers'; import { getSharedWorkflowIds } from '@/WorkflowHelpers';
import { WorkflowRunner } from '@/WorkflowRunner'; import { WorkflowRunner } from '@/WorkflowRunner';
import * as GenericHelpers from '@/GenericHelpers'; import * as GenericHelpers from '@/GenericHelpers';

View file

@ -13,12 +13,7 @@ import type {
import { IsBoolean, IsEmail, IsIn, IsOptional, IsString, Length } from 'class-validator'; import { IsBoolean, IsEmail, IsIn, IsOptional, IsString, Length } from 'class-validator';
import { NoXss } from '@db/utils/customValidators'; import { NoXss } from '@db/utils/customValidators';
import type { import type { PublicUser, SecretsProvider, SecretsProviderState } from '@/Interfaces';
PublicUser,
IExecutionDeleteFilter,
SecretsProvider,
SecretsProviderState,
} from '@/Interfaces';
import type { Role, RoleNames } from '@db/entities/Role'; import type { Role, RoleNames } from '@db/entities/Role';
import type { User } from '@db/entities/User'; import type { User } from '@db/entities/User';
import type { UserManagementMailer } from '@/UserManagement/email'; import type { UserManagementMailer } from '@/UserManagement/email';
@ -171,32 +166,6 @@ export declare namespace CredentialRequest {
type Share = AuthenticatedRequest<{ credentialId: string }, {}, { shareWithIds: string[] }>; type Share = AuthenticatedRequest<{ credentialId: string }, {}, { shareWithIds: string[] }>;
} }
// ----------------------------------
// /executions
// ----------------------------------
export declare namespace ExecutionRequest {
namespace QueryParam {
type GetAll = {
filter: string; // '{ waitTill: string; finished: boolean, [other: string]: string }'
limit: string;
lastId: string;
firstId: string;
};
type GetAllCurrent = {
filter: string; // '{ workflowId: string }'
};
}
type GetAll = AuthenticatedRequest<{}, {}, {}, QueryParam.GetAll>;
type Get = AuthenticatedRequest<{ id: string }, {}, {}, { unflattedResponse: 'true' | 'false' }>;
type Delete = AuthenticatedRequest<{}, {}, IExecutionDeleteFilter>;
type Retry = AuthenticatedRequest<{ id: string }, {}, { loadWorkflow: boolean }, {}>;
type Stop = AuthenticatedRequest<{ id: string }>;
type GetAllCurrent = AuthenticatedRequest<{}, {}, {}, QueryParam.GetAllCurrent>;
}
// ---------------------------------- // ----------------------------------
// /me // /me
// ---------------------------------- // ----------------------------------

View file

@ -131,8 +131,8 @@ export const setupTestServer = ({
break; break;
case 'executions': case 'executions':
const { executionsController } = await import('@/executions/executions.controller'); const { ExecutionsController } = await import('@/executions/executions.controller');
app.use(`/${REST_PATH_SEGMENT}/executions`, executionsController); registerController(app, ExecutionsController);
break; break;
case 'variables': case 'variables':