mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
chore: Pull the identical run-less getCredentials into the node execution context base (#38048)
Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
e88301b65d
commit
b93c6bc96e
|
|
@ -364,6 +364,38 @@ describe('NodeExecutionContext', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('_getRunlessCredentials', () => {
|
||||
it('should pass placeholder execute data that only carries the node', async () => {
|
||||
const credentialDetails = { id: 'cred-runless', name: 'Runless Cred' };
|
||||
const runlessNode = mock<INode>({ type: 'n8n-nodes-base.httpRequest' });
|
||||
runlessNode.credentials = { someCred: credentialDetails };
|
||||
|
||||
const mockCredentialsHelper = {
|
||||
getDecrypted: vi.fn().mockResolvedValue({ token: 'ok' }),
|
||||
getCredentialsProperties: vi.fn(),
|
||||
isCredentialUsableByNode: vi.fn().mockReturnValue(true),
|
||||
};
|
||||
|
||||
const ctx = new TestContext(
|
||||
workflow,
|
||||
runlessNode,
|
||||
mock<IWorkflowExecuteAdditionalData>({ credentialsHelper: mockCredentialsHelper }),
|
||||
mode,
|
||||
);
|
||||
|
||||
await expect(ctx['_getRunlessCredentials']('someCred')).resolves.toEqual({ token: 'ok' });
|
||||
expect(mockCredentialsHelper.getDecrypted).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
credentialDetails,
|
||||
'someCred',
|
||||
mode,
|
||||
{ data: {}, node: runlessNode, source: null },
|
||||
false,
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prepareOutputData', () => {
|
||||
it('should return the input array wrapped in another array', async () => {
|
||||
const outputData = [mock<INodeExecutionData>(), mock<INodeExecutionData>()];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { UnexpectedError } from 'n8n-workflow';
|
||||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IExecuteData,
|
||||
INode,
|
||||
IHookFunctions,
|
||||
IWorkflowExecuteAdditionalData,
|
||||
|
|
@ -37,12 +36,7 @@ export class HookContext extends NodeExecutionContext implements IHookFunctions
|
|||
}
|
||||
|
||||
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {
|
||||
// No real task run backs a webhook-registration hook, so this only exists to
|
||||
// surface `node` to the credentials helper (e.g. for policy checks) — `data`/
|
||||
// `source` are unused.
|
||||
const executeData: IExecuteData = { data: {}, node: this.node, source: null };
|
||||
|
||||
return await this._getCredentials<T>(type, executeData);
|
||||
return await this._getRunlessCredentials<T>(type);
|
||||
}
|
||||
|
||||
getNodeWebhookUrl(name: WebhookType): string | undefined {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import get from 'lodash/get';
|
||||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IExecuteData,
|
||||
IGetNodeParameterOptions,
|
||||
INode,
|
||||
ILoadOptionsFunctions,
|
||||
|
|
@ -45,12 +44,7 @@ export class LoadOptionsContext extends NodeExecutionContext implements ILoadOpt
|
|||
}
|
||||
|
||||
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {
|
||||
// No real task run backs design-time parameter loading, so this only exists to
|
||||
// surface `node` to the credentials helper (e.g. for policy checks) — `data`/`source`
|
||||
// are unused.
|
||||
const executeData: IExecuteData = { data: {}, node: this.node, source: null };
|
||||
|
||||
return await this._getCredentials<T>(type, executeData);
|
||||
return await this._getRunlessCredentials<T>(type);
|
||||
}
|
||||
|
||||
getCurrentNodeParameter(
|
||||
|
|
|
|||
|
|
@ -470,6 +470,18 @@ export abstract class NodeExecutionContext implements Omit<FunctionsBase, 'getCr
|
|||
return decryptedDataObject as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested decrypted credentials for a context that no real task run backs
|
||||
* (a trigger, a poll, a webhook, and so on). The placeholder execute data only exists to
|
||||
* surface `node` to the credentials helper (e.g. for policy checks) — `data`/`source` are
|
||||
* unused.
|
||||
*/
|
||||
protected async _getRunlessCredentials<T extends object = ICredentialDataDecryptedObject>(
|
||||
type: string,
|
||||
) {
|
||||
return await this._getCredentials<T>(type, { data: {}, node: this.node, source: null });
|
||||
}
|
||||
|
||||
@Memoized
|
||||
protected get additionalKeys() {
|
||||
return getAdditionalKeys(this.additionalData, this.mode, this.runExecutionData);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { createDeferredPromise } from '@n8n/utils/promise/deferred-promise';
|
|||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IDataObject,
|
||||
IExecuteData,
|
||||
INode,
|
||||
IPollFunctions,
|
||||
IWorkflowExecuteAdditionalData,
|
||||
|
|
@ -73,10 +72,6 @@ export class PollContext extends NodeExecutionContext implements IPollFunctions
|
|||
}
|
||||
|
||||
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {
|
||||
// No real task run backs a poll, so this only exists to surface `node` to
|
||||
// the credentials helper (e.g. for policy checks) — `data`/`source` are unused.
|
||||
const executeData: IExecuteData = { data: {}, node: this.node, source: null };
|
||||
|
||||
return await this._getCredentials<T>(type, executeData);
|
||||
return await this._getRunlessCredentials<T>(type);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { createDeferredPromise } from '@n8n/utils/promise/deferred-promise';
|
||||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IExecuteData,
|
||||
INode,
|
||||
ITriggerFunctions,
|
||||
IWorkflowExecuteAdditionalData,
|
||||
|
|
@ -66,10 +65,6 @@ export class TriggerContext extends NodeExecutionContext implements ITriggerFunc
|
|||
}
|
||||
|
||||
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {
|
||||
// No real task run backs a trigger, so this only exists to surface `node` to
|
||||
// the credentials helper (e.g. for policy checks) — `data`/`source` are unused.
|
||||
const executeData: IExecuteData = { data: {}, node: this.node, source: null };
|
||||
|
||||
return await this._getCredentials<T>(type, executeData);
|
||||
return await this._getRunlessCredentials<T>(type);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,11 +100,7 @@ export class WebhookContext extends NodeExecutionContext implements IWebhookFunc
|
|||
}
|
||||
|
||||
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {
|
||||
// No real task run backs a webhook call, so this only exists to surface `node`
|
||||
// to the credentials helper (e.g. for policy checks) — `data`/`source` are unused.
|
||||
const executeData: IExecuteData = { data: {}, node: this.node, source: null };
|
||||
|
||||
return await this._getCredentials<T>(type, executeData);
|
||||
return await this._getRunlessCredentials<T>(type);
|
||||
}
|
||||
|
||||
getBodyData() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user