mirror of
https://github.com/n8n-io/n8n
synced 2026-04-21 15:47:20 +00:00
fix(core): Guard against undefined config properties in credential overwrites (#28573)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
25e07cab5a
commit
77d27bc826
2 changed files with 40 additions and 4 deletions
|
|
@ -113,6 +113,36 @@ describe('CredentialsOverwrites', () => {
|
|||
expect(result).toEqual(data);
|
||||
});
|
||||
|
||||
it('should not crash when skipTypes is undefined', () => {
|
||||
// Simulate version mismatch where skipTypes is not present on the config object
|
||||
globalConfig.credentials.overwrite.skipTypes =
|
||||
undefined as unknown as CommaSeparatedStringArray<string>;
|
||||
|
||||
const result = credentialsOverwrites.applyOverwrite('test', {
|
||||
username: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({ username: 'user', password: 'pass' });
|
||||
});
|
||||
|
||||
it('should not crash when overwrite config object is undefined', () => {
|
||||
// Simulate a DI/version mismatch where the nested overwrite config is undefined
|
||||
const savedOverwrite = globalConfig.credentials.overwrite;
|
||||
globalConfig.credentials.overwrite = undefined as never;
|
||||
|
||||
try {
|
||||
const result = credentialsOverwrites.applyOverwrite('test', {
|
||||
username: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
expect(result).toEqual({ username: 'user', password: 'pass' });
|
||||
} finally {
|
||||
globalConfig.credentials.overwrite = savedOverwrite;
|
||||
}
|
||||
});
|
||||
|
||||
describe('N8N_SKIP_CREDENTIAL_OVERWRITE', () => {
|
||||
beforeEach(() => {
|
||||
globalConfig.credentials.overwrite.skipTypes = [
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ export class CredentialsOverwrites {
|
|||
// customized (any overwrite field has a non-empty value that differs from
|
||||
// the overwrite value). Since overwrites are never persisted to the DB,
|
||||
// any non-empty stored value that differs from the overwrite is user-set.
|
||||
if (this.globalConfig.credentials.overwrite.skipTypes.includes(type)) {
|
||||
if (this.globalConfig.credentials.overwrite?.skipTypes?.includes(type)) {
|
||||
const isFieldCustomized = (key: string) => {
|
||||
const storedValue = data[key];
|
||||
return (
|
||||
|
|
@ -208,11 +208,17 @@ export class CredentialsOverwrites {
|
|||
|
||||
private get(name: string): ICredentialDataDecryptedObject | undefined {
|
||||
const parentTypes = this.credentialTypes.getParentTypes(name);
|
||||
return [name, ...parentTypes]
|
||||
const entries = [name, ...parentTypes]
|
||||
.reverse()
|
||||
.map((type) => this.overwriteData[type])
|
||||
.filter((type) => !!type)
|
||||
.reduce((acc, current) => Object.assign(acc, current), {});
|
||||
.filter((type): type is ICredentialDataDecryptedObject => !!type);
|
||||
|
||||
if (entries.length === 0) return undefined;
|
||||
|
||||
return entries.reduce(
|
||||
(acc, current) => Object.assign(acc, current),
|
||||
{} as ICredentialDataDecryptedObject,
|
||||
);
|
||||
}
|
||||
|
||||
getAll(): ICredentialsOverwrite {
|
||||
|
|
|
|||
Loading…
Reference in a new issue