refactor(core): Use Dependency Injection for all Controller classes (no-changelog) (#8146)

## Review / Merge checklist
- [x] PR title and summary are descriptive
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2023-12-27 11:50:43 +01:00
committed by GitHub
parent 518a99e528
commit f69ddcd796
51 changed files with 209 additions and 522 deletions

View File

@@ -1,9 +1,7 @@
import { Service } from 'typedi';
import { Authorized, Get, RestController } from '@/decorators';
import { WorkflowRequest } from '@/requests';
import { ActiveWorkflowsService } from '@/services/activeWorkflows.service';
@Service()
@Authorized()
@RestController('/active-workflows')
export class ActiveWorkflowsController {

View File

@@ -1,6 +1,5 @@
import validator from 'validator';
import { In } from 'typeorm';
import { Service } from 'typedi';
import { Authorized, Get, Post, RestController } from '@/decorators';
import { issueCookie, resolveJwt } from '@/auth/jwt';
import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from '@/constants';
@@ -27,7 +26,6 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { UnauthorizedError } from '@/errors/response-errors/unauthorized.error';
import { ApplicationError } from 'n8n-workflow';
@Service()
@RestController()
export class AuthController {
constructor(

View File

@@ -1,11 +1,9 @@
import { Service } from 'typedi';
import express from 'express';
import { BinaryDataService, FileNotFoundError, isValidNonDefaultMode } from 'n8n-core';
import { Get, RestController } from '@/decorators';
import { BinaryDataRequest } from '@/requests';
@RestController('/binary-data')
@Service()
export class BinaryDataController {
constructor(private readonly binaryDataService: BinaryDataService) {}

View File

@@ -1,4 +1,3 @@
import { Service } from 'typedi';
import { Request, Response, NextFunction } from 'express';
import config from '@/config';
import {
@@ -42,14 +41,13 @@ export function isNpmError(error: unknown): error is { code: number; stdout: str
return typeof error === 'object' && error !== null && 'code' in error && 'stdout' in error;
}
@Service()
@Authorized()
@RestController('/community-packages')
export class CommunityPackagesController {
constructor(
private push: Push,
private internalHooks: InternalHooks,
private communityPackagesService: CommunityPackagesService,
private readonly push: Push,
private readonly internalHooks: InternalHooks,
private readonly communityPackagesService: CommunityPackagesService,
) {}
// TODO: move this into a new decorator `@IfConfig('executions.mode', 'queue')`

View File

@@ -1,4 +1,3 @@
import { Service } from 'typedi';
import { Get, RestController } from '@/decorators';
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
import { MultiMainSetup } from '@/services/orchestration/main/MultiMainSetup.ee';
@@ -6,7 +5,6 @@ import { WorkflowRepository } from '@/databases/repositories/workflow.repository
import { In } from 'typeorm';
@RestController('/debug')
@Service()
export class DebugController {
constructor(
private readonly multiMainSetup: MultiMainSetup,

View File

@@ -1,4 +1,3 @@
import { Service } from 'typedi';
import type { RequestHandler } from 'express';
import { NextFunction, Response } from 'express';
import type {
@@ -22,7 +21,6 @@ const assertMethodName: RequestHandler = (req, res, next) => {
next();
};
@Service()
@Authorized()
@RestController('/dynamic-node-parameters')
export class DynamicNodeParametersController {

View File

@@ -1,5 +1,4 @@
import { Request } from 'express';
import { Container, Service } from 'typedi';
import { v4 as uuid } from 'uuid';
import config from '@/config';
import type { Role } from '@db/entities/Role';
@@ -64,7 +63,6 @@ type PushRequest = Request<
}
>;
@Service()
@NoAuthRequired()
@RestController('/e2e')
export class E2EController {
@@ -89,12 +87,13 @@ export class E2EController {
constructor(
license: License,
private roleRepo: RoleRepository,
private settingsRepo: SettingsRepository,
private userRepo: UserRepository,
private workflowRunner: ActiveWorkflowRunner,
private mfaService: MfaService,
private cacheService: CacheService,
private readonly roleRepo: RoleRepository,
private readonly settingsRepo: SettingsRepository,
private readonly userRepo: UserRepository,
private readonly workflowRunner: ActiveWorkflowRunner,
private readonly mfaService: MfaService,
private readonly cacheService: CacheService,
private readonly push: Push,
private readonly passwordUtility: PasswordUtility,
) {
license.isFeatureEnabled = (feature: BooleanLicenseFeature) =>
@@ -112,14 +111,8 @@ export class E2EController {
}
@Post('/push')
async push(req: PushRequest) {
const pushInstance = Container.get(Push);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const sessionId = Object.keys(pushInstance.getBackend().connections as object)[0];
pushInstance.send(req.body.type, req.body.data, sessionId);
async pushSend(req: PushRequest) {
this.push.broadcast(req.body.type, req.body.data);
}
@Patch('/feature')

View File

@@ -1,12 +1,11 @@
import { In } from 'typeorm';
import Container, { Service } from 'typedi';
import { Response } from 'express';
import config from '@/config';
import { Authorized, NoAuthRequired, Post, RequireGlobalScope, RestController } from '@/decorators';
import { issueCookie } from '@/auth/jwt';
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
import { Response } from 'express';
import { UserRequest } from '@/requests';
import { Config } from '@/config';
import { IExternalHooksClass, IInternalHooksClass } from '@/Interfaces';
import { License } from '@/License';
import { UserService } from '@/services/user.service';
import { Logger } from '@/Logger';
@@ -17,20 +16,20 @@ import type { User } from '@/databases/entities/User';
import validator from 'validator';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { UnauthorizedError } from '@/errors/response-errors/unauthorized.error';
import { InternalHooks } from '@/InternalHooks';
import { ExternalHooks } from '@/ExternalHooks';
@Service()
@Authorized()
@RestController('/invitations')
export class InvitationController {
constructor(
private readonly config: Config,
private readonly logger: Logger,
private readonly internalHooks: IInternalHooksClass,
private readonly externalHooks: IExternalHooksClass,
private readonly internalHooks: InternalHooks,
private readonly externalHooks: ExternalHooks,
private readonly userService: UserService,
private readonly license: License,
private readonly passwordUtility: PasswordUtility,
private readonly postHog?: PostHogClient,
private readonly postHog: PostHogClient,
) {}
/**
@@ -40,7 +39,7 @@ export class InvitationController {
@Post('/')
@RequireGlobalScope('user:create')
async inviteUser(req: UserRequest.Invite) {
const isWithinUsersLimit = Container.get(License).isWithinUsersLimit();
const isWithinUsersLimit = this.license.isWithinUsersLimit();
if (isSamlLicensedAndEnabled()) {
this.logger.debug(
@@ -58,7 +57,7 @@ export class InvitationController {
throw new UnauthorizedError(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED);
}
if (!this.config.getEnv('userManagement.isInstanceOwnerSetUp')) {
if (!config.getEnv('userManagement.isInstanceOwnerSetUp')) {
this.logger.debug(
'Request to send email invite(s) to user(s) failed because the owner account is not set up',
);

View File

@@ -1,8 +1,9 @@
import pick from 'lodash/pick';
import { Authorized, Get, Post, Put, RestController, RequireGlobalScope } from '@/decorators';
import { getLdapConfig, getLdapSynchronizations, updateLdapConfig } from '@/Ldap/helpers';
import { LdapService } from '@/Ldap/LdapService.ee';
import { LdapSync } from '@/Ldap/LdapSync.ee';
import { LdapManager } from '@/Ldap/LdapManager.ee';
import type { LdapService } from '@/Ldap/LdapService.ee';
import type { LdapSync } from '@/Ldap/LdapSync.ee';
import { LdapConfiguration } from '@/Ldap/types';
import { NON_SENSIBLE_LDAP_CONFIG_PROPERTIES } from '@/Ldap/constants';
import { InternalHooks } from '@/InternalHooks';
@@ -11,11 +12,15 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error';
@Authorized()
@RestController('/ldap')
export class LdapController {
constructor(
private ldapService: LdapService,
private ldapSync: LdapSync,
private internalHooks: InternalHooks,
) {}
private ldapService: LdapService;
private ldapSync: LdapSync;
constructor(private readonly internalHooks: InternalHooks) {
const { service, sync } = LdapManager.getInstance();
this.ldapService = service;
this.ldapSync = sync;
}
@Get('/config')
@RequireGlobalScope('ldap:manage')

View File

@@ -1,7 +1,6 @@
import validator from 'validator';
import { plainToInstance } from 'class-transformer';
import { Response } from 'express';
import { Service } from 'typedi';
import { randomBytes } from 'crypto';
import { Authorized, Delete, Get, Patch, Post, RestController } from '@/decorators';
import { PasswordUtility } from '@/services/password.utility';
@@ -22,7 +21,6 @@ import { ExternalHooks } from '@/ExternalHooks';
import { InternalHooks } from '@/InternalHooks';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
@Service()
@Authorized()
@RestController('/me')
export class MeController {

View File

@@ -1,10 +1,8 @@
import { Service } from 'typedi';
import { Authorized, Delete, Get, Post, RestController } from '@/decorators';
import { AuthenticatedRequest, MFA } from '@/requests';
import { MfaService } from '@/Mfa/mfa.service';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
@Service()
@Authorized()
@RestController('/mfa')
export class MFAController {

View File

@@ -3,22 +3,19 @@ import get from 'lodash/get';
import { Request } from 'express';
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
import { Authorized, Post, RestController } from '@/decorators';
import { Config } from '@/config';
import config from '@/config';
import { NodeTypes } from '@/NodeTypes';
@Authorized()
@RestController('/node-types')
export class NodeTypesController {
constructor(
private readonly config: Config,
private readonly nodeTypes: NodeTypes,
) {}
constructor(private readonly nodeTypes: NodeTypes) {}
@Post('/')
async getNodeInfo(req: Request) {
const nodeInfos = get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[];
const defaultLocale = this.config.getEnv('defaultLocale');
const defaultLocale = config.getEnv('defaultLocale');
if (defaultLocale === 'en') {
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {

View File

@@ -1,4 +1,3 @@
import { Service } from 'typedi';
import { Response } from 'express';
import type { AxiosRequestConfig } from 'axios';
import axios from 'axios';
@@ -30,7 +29,6 @@ const algorithmMap = {
/* eslint-enable */
} as const;
@Service()
@Authorized()
@RestController('/oauth1-credential')
export class OAuth1CredentialController extends AbstractOAuthController {

View File

@@ -1,4 +1,3 @@
import { Service } from 'typedi';
import type { ClientOAuth2Options } from '@n8n/client-oauth2';
import { ClientOAuth2 } from '@n8n/client-oauth2';
import Csrf from 'csrf';
@@ -31,7 +30,6 @@ interface CsrfStateParam {
token: string;
}
@Service()
@Authorized()
@RestController('/oauth2-credential')
export class OAuth2CredentialController extends AbstractOAuthController {

View File

@@ -1,12 +1,10 @@
import { Authorized, Post, RestController, RequireGlobalScope } from '@/decorators';
import { OrchestrationRequest } from '@/requests';
import { Service } from 'typedi';
import { SingleMainSetup } from '@/services/orchestration/main/SingleMainSetup';
import { License } from '../License';
import { License } from '@/License';
@Authorized()
@RestController('/orchestration')
@Service()
export class OrchestrationController {
constructor(
private readonly singleMainSetup: SingleMainSetup,

View File

@@ -1,29 +1,29 @@
import validator from 'validator';
import { Response } from 'express';
import config from '@/config';
import { validateEntity } from '@/GenericHelpers';
import { Authorized, Post, RestController } from '@/decorators';
import { PasswordUtility } from '@/services/password.utility';
import { issueCookie } from '@/auth/jwt';
import { Response } from 'express';
import { Config } from '@/config';
import { OwnerRequest } from '@/requests';
import { IInternalHooksClass } from '@/Interfaces';
import { SettingsRepository } from '@db/repositories/settings.repository';
import { PostHogClient } from '@/posthog';
import { UserService } from '@/services/user.service';
import { Logger } from '@/Logger';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { InternalHooks } from '@/InternalHooks';
@Authorized(['global', 'owner'])
@RestController('/owner')
export class OwnerController {
constructor(
private readonly config: Config,
private readonly logger: Logger,
private readonly internalHooks: IInternalHooksClass,
private readonly internalHooks: InternalHooks,
private readonly settingsRepository: SettingsRepository,
private readonly userService: UserService,
private readonly passwordUtility: PasswordUtility,
private readonly postHog?: PostHogClient,
private readonly postHog: PostHogClient,
) {}
/**
@@ -35,7 +35,7 @@ export class OwnerController {
const { email, firstName, lastName, password } = req.body;
const { id: userId, globalRole } = req.user;
if (this.config.getEnv('userManagement.isInstanceOwnerSetUp')) {
if (config.getEnv('userManagement.isInstanceOwnerSetUp')) {
this.logger.debug(
'Request to claim instance ownership failed because instance owner already exists',
{
@@ -94,7 +94,7 @@ export class OwnerController {
{ value: JSON.stringify(true) },
);
this.config.set('userManagement.isInstanceOwnerSetUp', true);
config.set('userManagement.isInstanceOwnerSetUp', true);
this.logger.debug('Setting isInstanceOwnerSetUp updated successfully', { userId });

View File

@@ -1,6 +1,5 @@
import { Response } from 'express';
import { rateLimit } from 'express-rate-limit';
import { Service } from 'typedi';
import { IsNull, Not } from 'typeorm';
import validator from 'validator';
@@ -31,7 +30,6 @@ const throttle = rateLimit({
message: { message: 'Too many requests' },
});
@Service()
@RestController()
export class PasswordResetController {
constructor(

View File

@@ -1,9 +1,7 @@
import { License } from '@/License';
import { Get, RestController } from '@/decorators';
import { RoleService } from '@/services/role.service';
import { Service } from 'typedi';
@Service()
@RestController('/roles')
export class RoleController {
constructor(

View File

@@ -12,16 +12,14 @@ import {
} from '@/decorators';
import { TagService } from '@/services/tag.service';
import { TagsRequest } from '@/requests';
import { Service } from 'typedi';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
@Authorized()
@RestController('/tags')
@Service()
export class TagsController {
private config = config;
constructor(private tagService: TagService) {}
constructor(private readonly tagService: TagService) {}
// TODO: move this into a new decorator `@IfEnabled('workflowTagsDisabled')`
@Middleware()

View File

@@ -1,12 +1,12 @@
import type { Request } from 'express';
import { ICredentialTypes } from 'n8n-workflow';
import { join } from 'path';
import { access } from 'fs/promises';
import { Authorized, Get, RestController } from '@/decorators';
import { Config } from '@/config';
import config from '@/config';
import { NODES_BASE_DIR } from '@/constants';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
import { CredentialTypes } from '@/CredentialTypes';
export const CREDENTIAL_TRANSLATIONS_DIR = 'n8n-nodes-base/dist/credentials/translations';
export const NODE_HEADERS_PATH = join(NODES_BASE_DIR, 'dist/nodes/headers');
@@ -18,10 +18,7 @@ export declare namespace TranslationRequest {
@Authorized()
@RestController('/')
export class TranslationController {
constructor(
private config: Config,
private credentialTypes: ICredentialTypes,
) {}
constructor(private readonly credentialTypes: CredentialTypes) {}
@Get('/credential-translation')
async getCredentialTranslation(req: TranslationRequest.Credential) {
@@ -30,7 +27,7 @@ export class TranslationController {
if (!this.credentialTypes.recognizes(credentialType))
throw new BadRequestError(`Invalid Credential type: "${credentialType}"`);
const defaultLocale = this.config.getEnv('defaultLocale');
const defaultLocale = config.getEnv('defaultLocale');
const translationPath = join(
CREDENTIAL_TRANSLATIONS_DIR,
defaultLocale,

View File

@@ -6,7 +6,6 @@ import { SharedWorkflow } from '@db/entities/SharedWorkflow';
import { RequireGlobalScope, Authorized, Delete, Get, RestController, Patch } from '@/decorators';
import { ListQuery, UserRequest, UserSettingsUpdatePayload } from '@/requests';
import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner';
import { IExternalHooksClass, IInternalHooksClass } from '@/Interfaces';
import type { PublicUser, ITelemetryUserDeletionData } from '@/Interfaces';
import { AuthIdentity } from '@db/entities/AuthIdentity';
import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository';
@@ -20,14 +19,16 @@ import { UnauthorizedError } from '@/errors/response-errors/unauthorized.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { License } from '@/License';
import { ExternalHooks } from '@/ExternalHooks';
import { InternalHooks } from '@/InternalHooks';
@Authorized()
@RestController('/users')
export class UsersController {
constructor(
private readonly logger: Logger,
private readonly externalHooks: IExternalHooksClass,
private readonly internalHooks: IInternalHooksClass,
private readonly externalHooks: ExternalHooks,
private readonly internalHooks: InternalHooks,
private readonly sharedCredentialsRepository: SharedCredentialsRepository,
private readonly sharedWorkflowRepository: SharedWorkflowRepository,
private readonly activeWorkflowRunner: ActiveWorkflowRunner,

View File

@@ -1,4 +1,3 @@
import { Service } from 'typedi';
import { Response, NextFunction } from 'express';
import { Get, Middleware, RestController } from '@/decorators';
import type { WorkflowStatistics } from '@db/entities/WorkflowStatistics';
@@ -18,12 +17,11 @@ interface WorkflowStatisticsData<T> {
manualError: T;
}
@Service()
@RestController('/workflow-stats')
export class WorkflowStatisticsController {
constructor(
private sharedWorkflowRepository: SharedWorkflowRepository,
private workflowStatisticsRepository: WorkflowStatisticsRepository,
private readonly sharedWorkflowRepository: SharedWorkflowRepository,
private readonly workflowStatisticsRepository: WorkflowStatisticsRepository,
private readonly logger: Logger,
) {}