n8n
Version:
n8n Workflow Automation Tool
347 lines • 17.6 kB
JavaScript
"use strict";
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.CredentialsHelper = void 0;
exports.createCredentialsFromCredentialsEntity = createCredentialsFromCredentialsEntity;
const backend_common_1 = require("@n8n/backend-common");
const db_1 = require("@n8n/db");
const di_1 = require("@n8n/di");
const typeorm_1 = require("@n8n/typeorm");
const n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const constants_1 = require("./constants");
const dynamic_credentials_proxy_1 = require("./credentials/dynamic-credentials-proxy");
const credential_not_found_error_1 = require("./errors/credential-not-found.error");
const credential_types_1 = require("./credential-types");
const credentials_overwrites_1 = require("./credentials-overwrites");
const external_secrets_config_1 = require("./modules/external-secrets.ee/external-secrets.config");
const ai_gateway_service_1 = require("./services/ai-gateway.service");
const mockNode = {
name: '',
typeVersion: 1,
type: 'mock',
position: [0, 0],
parameters: {},
};
const mockNodesData = {
mock: {
sourcePath: '',
type: {
description: { properties: [] },
},
},
};
const mockNodeTypes = {
getKnownTypes() {
return {};
},
getByName(nodeType) {
return mockNodesData[nodeType]?.type;
},
getByNameAndVersion(nodeType, version) {
if (!mockNodesData[nodeType]) {
throw new n8n_workflow_1.UnexpectedError(constants_1.RESPONSE_ERROR_MESSAGES.NO_NODE, {
tags: { nodeType },
});
}
return n8n_workflow_1.NodeHelpers.getVersionedNodeType(mockNodesData[nodeType].type, version);
},
};
let CredentialsHelper = class CredentialsHelper extends n8n_workflow_1.ICredentialsHelper {
constructor(credentialTypes, credentialsOverwrites, credentialsRepository, dynamicCredentialsProxy, secretsProviderConnectionRepository, licenseState, externalSecretsConfig, aiGatewayService) {
super();
this.credentialTypes = credentialTypes;
this.credentialsOverwrites = credentialsOverwrites;
this.credentialsRepository = credentialsRepository;
this.dynamicCredentialsProxy = dynamicCredentialsProxy;
this.secretsProviderConnectionRepository = secretsProviderConnectionRepository;
this.licenseState = licenseState;
this.externalSecretsConfig = externalSecretsConfig;
this.aiGatewayService = aiGatewayService;
}
async authenticate(credentials, typeName, incomingRequestOptions, workflow, node) {
const requestOptions = incomingRequestOptions;
const credentialType = this.credentialTypes.getByName(typeName);
if (credentialType.authenticate) {
if (typeof credentialType.authenticate === 'function') {
return await credentialType.authenticate(credentials, requestOptions);
}
if (typeof credentialType.authenticate === 'object') {
let keyResolved;
let valueResolved;
const { authenticate } = credentialType;
if (requestOptions.headers === undefined) {
requestOptions.headers = {};
}
if (authenticate.type === 'generic') {
Object.entries(authenticate.properties).forEach(([outerKey, outerValue]) => {
Object.entries(outerValue).forEach(([key, value]) => {
keyResolved = this.resolveValue(key, { $credentials: credentials }, workflow, node);
valueResolved = this.resolveValue(value, { $credentials: credentials }, workflow, node);
if (!requestOptions[outerKey]) {
requestOptions[outerKey] = {};
}
requestOptions[outerKey][keyResolved] = valueResolved;
});
});
}
}
}
return requestOptions;
}
async preAuthentication(helpers, credentials, typeName, node, credentialsExpired) {
const credentialType = this.credentialTypes.getByName(typeName);
const expirableProperty = credentialType.properties.find((property) => property.type === 'hidden' && property?.typeOptions?.expirable === true);
if (expirableProperty?.name === undefined) {
return undefined;
}
const isTestingCredentials = node?.parameters?.temp === '' && node?.type === 'n8n-nodes-base.noOp';
if (credentialType.preAuthentication) {
if (typeof credentialType.preAuthentication === 'function') {
if (credentials[expirableProperty?.name] === '' ||
credentialsExpired ||
isTestingCredentials) {
const output = await credentialType.preAuthentication.call(helpers, credentials);
if (output[expirableProperty.name] === undefined) {
return undefined;
}
if (node.credentials) {
await this.updateCredentials(node.credentials[credentialType.name], credentialType.name, Object.assign(credentials, output));
return Object.assign(credentials, output);
}
}
}
}
return undefined;
}
async runPreAuthentication(helpers, credentials, typeName) {
const credentialType = this.credentialTypes.getByName(typeName);
if (typeof credentialType.preAuthentication !== 'function') {
return undefined;
}
const output = await credentialType.preAuthentication.call(helpers, credentials);
return output ?? undefined;
}
resolveValue(parameterValue, additionalKeys, workflow, node) {
if (!(0, n8n_workflow_1.isExpression)(parameterValue)) {
return parameterValue;
}
const returnValue = workflow.expression.getSimpleParameterValue(node, parameterValue, 'internal', additionalKeys, undefined, '');
if (!returnValue) {
return '';
}
return returnValue.toString();
}
getParentTypes(typeName) {
return this.credentialTypes.getParentTypes(typeName);
}
async getCredentials(nodeCredential, type) {
const credential = await this.getCredentialsEntity(nodeCredential, type);
return new n8n_core_1.Credentials({ id: credential.id, name: credential.name }, credential.type, credential.data);
}
async getCredentialsEntity(nodeCredential, type) {
if (!nodeCredential.id) {
throw new n8n_workflow_1.UnexpectedError('Found credential with no ID.', {
extra: { credentialName: nodeCredential.name },
tags: { credentialType: type },
});
}
let credential;
try {
credential = await this.credentialsRepository.findOneByOrFail({
id: nodeCredential.id,
type,
});
}
catch (error) {
if (error instanceof typeorm_1.EntityNotFoundError) {
throw new credential_not_found_error_1.CredentialNotFoundError(nodeCredential.id, type);
}
throw error;
}
return credential;
}
getCredentialsProperties(type) {
const credentialTypeData = this.credentialTypes.getByName(type);
if (credentialTypeData === undefined) {
throw new n8n_workflow_1.UnexpectedError('Unknown credential type', { tags: { credentialType: type } });
}
if (credentialTypeData.extends === undefined) {
if (['oAuth1Api', 'oAuth2Api'].includes(type)) {
return [
...credentialTypeData.properties,
{
displayName: 'oauthTokenData',
name: 'oauthTokenData',
type: 'json',
required: false,
default: {},
},
];
}
return credentialTypeData.properties;
}
const combineProperties = [];
for (const credentialsTypeName of credentialTypeData.extends) {
const mergeCredentialProperties = this.getCredentialsProperties(credentialsTypeName);
n8n_workflow_1.NodeHelpers.mergeNodeProperties(combineProperties, mergeCredentialProperties);
}
n8n_workflow_1.NodeHelpers.mergeNodeProperties(combineProperties, credentialTypeData.properties);
return combineProperties;
}
async getDecrypted(additionalData, nodeCredentials, type, mode, executeData, raw, expressionResolveValues) {
if (nodeCredentials.__aiGatewayManaged) {
const { userId, workflowId, projectId, executionId } = additionalData;
return await this.aiGatewayService.getSyntheticCredential({
credentialType: type,
userId,
workflowId,
projectId,
executionId,
});
}
const credentialsEntity = await this.getCredentialsEntity(nodeCredentials, type);
const credentials = new n8n_core_1.Credentials({ id: credentialsEntity.id, name: credentialsEntity.name }, credentialsEntity.type, credentialsEntity.data);
let decryptedDataOriginal = await credentials.getData();
const effectiveMode = additionalData.rootExecutionMode ?? mode;
const skipDynamicResolution = effectiveMode === 'manual' || effectiveMode === 'internal';
if (additionalData.executionContext?.credentials !== undefined || !skipDynamicResolution) {
const resolveResult = await this.dynamicCredentialsProxy.resolveIfNeeded({
id: credentialsEntity.id,
name: credentialsEntity.name,
type: credentialsEntity.type,
isResolvable: credentialsEntity.isResolvable,
resolverId: credentialsEntity.resolverId ?? undefined,
}, decryptedDataOriginal, additionalData.executionContext, additionalData.workflowSettings);
decryptedDataOriginal = resolveResult.data;
if (resolveResult.isDynamic) {
additionalData.currentNodeUsedDynamicCredentials = true;
}
}
if (raw === true) {
return decryptedDataOriginal;
}
if (this.licenseState.isExternalSecretsLicensed() &&
this.externalSecretsConfig.externalSecretsForProjects) {
const accessibleProviderKeys = await this.secretsProviderConnectionRepository.findAllAccessibleProviderKeysByCredentialId(credentialsEntity.id);
additionalData.externalSecretProviderKeysAccessibleByCredential = new Set(accessibleProviderKeys);
}
return await this.applyDefaultsAndOverwrites(additionalData, decryptedDataOriginal, type, mode, executeData, expressionResolveValues);
}
async applyDefaultsAndOverwrites(additionalData, decryptedDataOriginal, type, mode, executeData, expressionResolveValues) {
const credentialsProperties = this.getCredentialsProperties(type);
const dataWithOverwrites = this.credentialsOverwrites.applyOverwrite(type, decryptedDataOriginal);
let decryptedData = n8n_workflow_1.NodeHelpers.getNodeParameters(credentialsProperties, dataWithOverwrites, true, false, null, null);
if (decryptedDataOriginal.oauthTokenData !== undefined) {
decryptedData.oauthTokenData = decryptedDataOriginal.oauthTokenData;
}
if (decryptedData.allowedHttpRequestDomains === undefined &&
decryptedDataOriginal.allowedHttpRequestDomains !== undefined) {
decryptedData.allowedHttpRequestDomains = decryptedDataOriginal.allowedHttpRequestDomains;
}
if (decryptedData.allowedDomains === undefined &&
decryptedDataOriginal.allowedDomains !== undefined) {
decryptedData.allowedDomains = decryptedDataOriginal.allowedDomains;
}
if (decryptedData.useDynamicClientRegistration) {
decryptedData.clientId = decryptedDataOriginal.clientId;
decryptedData.clientSecret = decryptedDataOriginal.clientSecret;
decryptedData.authUrl = decryptedDataOriginal.authUrl;
decryptedData.accessTokenUrl = decryptedDataOriginal.accessTokenUrl;
decryptedData.grantType = decryptedDataOriginal.grantType;
decryptedData.authentication = decryptedDataOriginal.authentication;
}
const additionalKeys = (0, n8n_core_1.getAdditionalKeys)(additionalData, mode, null);
if (expressionResolveValues) {
try {
decryptedData = expressionResolveValues.workflow.expression.getParameterValue(decryptedData, expressionResolveValues.runExecutionData, expressionResolveValues.runIndex, expressionResolveValues.itemIndex, expressionResolveValues.node.name, expressionResolveValues.connectionInputData, mode, additionalKeys, executeData, false, decryptedData);
}
catch (e) {
e.message += ' [Error resolving credentials]';
throw e;
}
}
else {
const workflow = new n8n_workflow_1.Workflow({
nodes: [mockNode],
connections: {},
active: false,
nodeTypes: mockNodeTypes,
});
await workflow.expression.acquireIsolate();
try {
decryptedData = workflow.expression.getComplexParameterValue(mockNode, decryptedData, mode, additionalKeys, undefined, undefined, decryptedData);
}
finally {
await workflow.expression.releaseIsolate();
}
}
return decryptedData;
}
async updateCredentials(nodeCredentials, type, data) {
const credentials = await this.getCredentials(nodeCredentials, type);
await credentials.setData(data);
const newCredentialsData = credentials.getDataToSave();
newCredentialsData.updatedAt = new Date();
const findQuery = {
id: credentials.id,
type,
};
await this.credentialsRepository.update(findQuery, newCredentialsData);
}
async updateCredentialsOauthTokenData(nodeCredentials, type, data, additionalData) {
const credentialsEntity = await this.getCredentialsEntity(nodeCredentials, type);
const resolverId = credentialsEntity.resolverId ?? additionalData.workflowSettings?.credentialResolverId;
if (credentialsEntity.isResolvable &&
resolverId &&
additionalData.executionContext?.credentials) {
const credentials = await this.getCredentials(nodeCredentials, type);
const staticData = await credentials.getData();
await this.dynamicCredentialsProxy.storeOAuthTokenDataIfNeeded({
id: credentialsEntity.id,
name: credentialsEntity.name,
type: credentialsEntity.type,
isResolvable: credentialsEntity.isResolvable,
resolverId,
}, data.oauthTokenData, additionalData.executionContext, staticData, additionalData.workflowSettings);
return;
}
const credentials = await this.getCredentials(nodeCredentials, type);
await credentials.updateData({ oauthTokenData: data.oauthTokenData });
const newCredentialsData = credentials.getDataToSave();
newCredentialsData.updatedAt = new Date();
const findQuery = {
id: credentials.id,
type,
};
await this.credentialsRepository.update(findQuery, newCredentialsData);
}
};
exports.CredentialsHelper = CredentialsHelper;
exports.CredentialsHelper = CredentialsHelper = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [credential_types_1.CredentialTypes,
credentials_overwrites_1.CredentialsOverwrites,
db_1.CredentialsRepository,
dynamic_credentials_proxy_1.DynamicCredentialsProxy,
db_1.SecretsProviderConnectionRepository,
backend_common_1.LicenseState,
external_secrets_config_1.ExternalSecretsConfig,
ai_gateway_service_1.AiGatewayService])
], CredentialsHelper);
function createCredentialsFromCredentialsEntity(credential, encrypt = false) {
const { id, name, type, data } = credential;
if (encrypt) {
return new n8n_core_1.Credentials({ id: null, name }, type);
}
return new n8n_core_1.Credentials({ id, name }, type, data);
}
//# sourceMappingURL=credentials-helper.js.map