mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
refactor(core): Standardize filename casing for controllers and databases (no-changelog) (#10564)
This commit is contained in:
153
packages/cli/src/controllers/oauth/abstract-oauth.controller.ts
Normal file
153
packages/cli/src/controllers/oauth/abstract-oauth.controller.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { Service } from 'typedi';
|
||||
import Csrf from 'csrf';
|
||||
import type { Response } from 'express';
|
||||
import { Credentials } from 'n8n-core';
|
||||
import type { ICredentialDataDecryptedObject, IWorkflowExecuteAdditionalData } from 'n8n-workflow';
|
||||
import { jsonParse, ApplicationError } from 'n8n-workflow';
|
||||
|
||||
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
|
||||
import { CredentialsRepository } from '@db/repositories/credentials.repository';
|
||||
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
||||
import type { ICredentialsDb } from '@/Interfaces';
|
||||
import type { OAuthRequest } from '@/requests';
|
||||
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
|
||||
import { CredentialsHelper } from '@/credentials-helper';
|
||||
import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';
|
||||
import { Logger } from '@/logger';
|
||||
import { ExternalHooks } from '@/external-hooks';
|
||||
import { UrlService } from '@/services/url.service';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
|
||||
export interface CsrfStateParam {
|
||||
cid: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
@Service()
|
||||
export abstract class AbstractOAuthController {
|
||||
abstract oauthVersion: number;
|
||||
|
||||
constructor(
|
||||
protected readonly logger: Logger,
|
||||
protected readonly externalHooks: ExternalHooks,
|
||||
private readonly credentialsHelper: CredentialsHelper,
|
||||
private readonly credentialsRepository: CredentialsRepository,
|
||||
private readonly sharedCredentialsRepository: SharedCredentialsRepository,
|
||||
private readonly urlService: UrlService,
|
||||
private readonly globalConfig: GlobalConfig,
|
||||
) {}
|
||||
|
||||
get baseUrl() {
|
||||
const restUrl = `${this.urlService.getInstanceBaseUrl()}/${this.globalConfig.endpoints.rest}`;
|
||||
return `${restUrl}/oauth${this.oauthVersion}-credential`;
|
||||
}
|
||||
|
||||
protected async getCredential(
|
||||
req: OAuthRequest.OAuth2Credential.Auth,
|
||||
): Promise<CredentialsEntity> {
|
||||
const { id: credentialId } = req.query;
|
||||
|
||||
if (!credentialId) {
|
||||
throw new BadRequestError('Required credential ID is missing');
|
||||
}
|
||||
|
||||
const credential = await this.sharedCredentialsRepository.findCredentialForUser(
|
||||
credentialId,
|
||||
req.user,
|
||||
['credential:read'],
|
||||
);
|
||||
|
||||
if (!credential) {
|
||||
this.logger.error(
|
||||
`OAuth${this.oauthVersion} credential authorization failed because the current user does not have the correct permissions`,
|
||||
{ userId: req.user.id },
|
||||
);
|
||||
throw new NotFoundError(RESPONSE_ERROR_MESSAGES.NO_CREDENTIAL);
|
||||
}
|
||||
|
||||
return credential;
|
||||
}
|
||||
|
||||
protected async getAdditionalData() {
|
||||
return await WorkflowExecuteAdditionalData.getBase();
|
||||
}
|
||||
|
||||
protected async getDecryptedData(
|
||||
credential: ICredentialsDb,
|
||||
additionalData: IWorkflowExecuteAdditionalData,
|
||||
) {
|
||||
return await this.credentialsHelper.getDecrypted(
|
||||
additionalData,
|
||||
credential,
|
||||
credential.type,
|
||||
'internal',
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
protected applyDefaultsAndOverwrites<T>(
|
||||
credential: ICredentialsDb,
|
||||
decryptedData: ICredentialDataDecryptedObject,
|
||||
additionalData: IWorkflowExecuteAdditionalData,
|
||||
) {
|
||||
return this.credentialsHelper.applyDefaultsAndOverwrites(
|
||||
additionalData,
|
||||
decryptedData,
|
||||
credential.type,
|
||||
'internal',
|
||||
) as unknown as T;
|
||||
}
|
||||
|
||||
protected async encryptAndSaveData(
|
||||
credential: ICredentialsDb,
|
||||
decryptedData: ICredentialDataDecryptedObject,
|
||||
) {
|
||||
const credentials = new Credentials(credential, credential.type);
|
||||
credentials.setData(decryptedData);
|
||||
await this.credentialsRepository.update(credential.id, {
|
||||
...credentials.getDataToSave(),
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
}
|
||||
|
||||
/** Get a credential without user check */
|
||||
protected async getCredentialWithoutUser(credentialId: string): Promise<ICredentialsDb | null> {
|
||||
return await this.credentialsRepository.findOneBy({ id: credentialId });
|
||||
}
|
||||
|
||||
createCsrfState(credentialsId: string): [string, string] {
|
||||
const token = new Csrf();
|
||||
const csrfSecret = token.secretSync();
|
||||
const state: CsrfStateParam = {
|
||||
token: token.create(csrfSecret),
|
||||
cid: credentialsId,
|
||||
};
|
||||
return [csrfSecret, Buffer.from(JSON.stringify(state)).toString('base64')];
|
||||
}
|
||||
|
||||
protected decodeCsrfState(encodedState: string): CsrfStateParam {
|
||||
const errorMessage = 'Invalid state format';
|
||||
const decoded = jsonParse<CsrfStateParam>(Buffer.from(encodedState, 'base64').toString(), {
|
||||
errorMessage,
|
||||
});
|
||||
if (typeof decoded.cid !== 'string' || typeof decoded.token !== 'string') {
|
||||
throw new ApplicationError(errorMessage);
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
protected verifyCsrfState(decrypted: ICredentialDataDecryptedObject, state: CsrfStateParam) {
|
||||
const token = new Csrf();
|
||||
return (
|
||||
decrypted.csrfSecret === undefined ||
|
||||
!token.verify(decrypted.csrfSecret as string, state.token)
|
||||
);
|
||||
}
|
||||
|
||||
protected renderCallbackError(res: Response, message: string, reason?: string) {
|
||||
res.render('oauth-error-callback', { error: { message, reason } });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user