first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
import { createMockExecuteFunction } from 'n8n-nodes-base/test/nodes/Helpers';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IExecuteFunctions,
|
||||
INode,
|
||||
ISupplyDataFunctions,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { checkDomainRestrictions } from '../checkDomainRestrictions';
|
||||
|
||||
describe('checkDomainRestrictions', () => {
|
||||
let mockNode: INode;
|
||||
let mockExecuteFunctions: IExecuteFunctions;
|
||||
let mockSupplyDataFunctions: ISupplyDataFunctions;
|
||||
|
||||
beforeEach(() => {
|
||||
mockNode = {
|
||||
id: 'test-node',
|
||||
name: 'Test Node',
|
||||
type: 'test',
|
||||
typeVersion: 1,
|
||||
position: [0, 0] as [number, number],
|
||||
parameters: {},
|
||||
};
|
||||
|
||||
mockExecuteFunctions = createMockExecuteFunction({}, mockNode);
|
||||
mockSupplyDataFunctions = mockExecuteFunctions as unknown as ISupplyDataFunctions;
|
||||
});
|
||||
|
||||
describe('when allowedDomainsType is "domains"', () => {
|
||||
it('should throw error when allowedDomains is empty', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: '',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).toThrow(NodeOperationError);
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).toThrow(
|
||||
'No allowed domains specified. Configure allowed domains or change restriction setting.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when allowedDomains is whitespace only', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: ' ',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).toThrow(NodeOperationError);
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).toThrow(
|
||||
'No allowed domains specified. Configure allowed domains or change restriction setting.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when allowedDomains is undefined', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).toThrow(NodeOperationError);
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).toThrow(
|
||||
'No allowed domains specified. Configure allowed domains or change restriction setting.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when URL is not in allowed domains', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com,test.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://notallowed.com');
|
||||
}).toThrow(NodeOperationError);
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://notallowed.com');
|
||||
}).toThrow(
|
||||
'Domain not allowed: This credential is restricted from accessing https://notallowed.com. Only the following domains are allowed: example.com,test.com',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not throw error when URL is in allowed domains (exact match)', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not throw error when URL is in allowed domains (comma-separated list)', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com,test.com,another.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://test.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not throw error when URL matches wildcard domain', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: '*.example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://sub.example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should work with IExecuteFunctions context', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should work with ISupplyDataFunctions context', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockSupplyDataFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when allowedDomainsType is "none"', () => {
|
||||
it('should not throw error when URL matches credentials URL', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
url: 'https://example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw error when URL does not match credentials URL', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
url: 'https://example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://different.com');
|
||||
}).toThrow(NodeOperationError);
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://different.com');
|
||||
}).toThrow(
|
||||
'Domain not allowed: This credential is restricted from accessing https://different.com. ',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not throw error when credentials URL key does not exist', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://any-url.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should use custom credentialsUrlKey parameter', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
baseUrl: 'https://custom.example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(
|
||||
mockExecuteFunctions,
|
||||
credentials,
|
||||
'https://custom.example.com',
|
||||
'baseUrl',
|
||||
);
|
||||
}).not.toThrow();
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(
|
||||
mockExecuteFunctions,
|
||||
credentials,
|
||||
'https://different.com',
|
||||
'baseUrl',
|
||||
);
|
||||
}).toThrow(NodeOperationError);
|
||||
});
|
||||
|
||||
it('should work with IExecuteFunctions context', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
url: 'https://example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should work with ISupplyDataFunctions context', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
url: 'https://example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockSupplyDataFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when allowedDomainsType is undefined or other value', () => {
|
||||
it('should not throw error when allowedDomainsType is undefined', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://any-url.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not throw error when allowedDomainsType is empty string', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: '',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://any-url.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not throw error when allowedDomainsType is other value', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'other' as any,
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://any-url.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle URLs with paths and query parameters', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(
|
||||
mockExecuteFunctions,
|
||||
credentials,
|
||||
'https://example.com/api/v1/endpoint?param=value',
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle URLs with ports', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com:8080');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle case-insensitive domain matching', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'EXAMPLE.COM',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle domains with trailing dots', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com.',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle multiple domains with spaces in allowedDomains', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'domains',
|
||||
allowedDomains: 'example.com, test.com , another.com',
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://test.com');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle exact URL match for "none" type with different protocols', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
url: 'https://example.com',
|
||||
};
|
||||
|
||||
// Should throw because protocol is different
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'http://example.com');
|
||||
}).toThrow(NodeOperationError);
|
||||
});
|
||||
|
||||
it('should handle exact URL match for "none" type with different paths', () => {
|
||||
const credentials: ICredentialDataDecryptedObject = {
|
||||
allowedHttpRequestDomains: 'none',
|
||||
url: 'https://example.com',
|
||||
};
|
||||
|
||||
// Should throw because path is different
|
||||
expect(() => {
|
||||
checkDomainRestrictions(mockExecuteFunctions, credentials, 'https://example.com/path');
|
||||
}).toThrow(NodeOperationError);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user