n8n-nodes-base 1.121.54 → 1.121.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/credentials/CiscoSecureEndpointApi.credentials.d.ts +1 -1
- package/dist/credentials/CiscoSecureEndpointApi.credentials.d.ts.map +1 -1
- package/dist/credentials/CiscoSecureEndpointApi.credentials.js +40 -16
- package/dist/credentials/CiscoSecureEndpointApi.credentials.js.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.d.ts.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js +14 -5
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/helpers/glob.worker.d.ts +18 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/glob.worker.d.ts.map +1 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/glob.worker.js +22 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/glob.worker.js.map +1 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.d.ts +5 -1
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.d.ts.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.js +87 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.js.map +1 -1
- package/dist/nodes/Form/utils/formCompletionUtils.d.ts.map +1 -1
- package/dist/nodes/Form/utils/formCompletionUtils.js +10 -3
- package/dist/nodes/Form/utils/formCompletionUtils.js.map +1 -1
- package/dist/nodes/Git/Git.node.d.ts +1 -0
- package/dist/nodes/Git/Git.node.d.ts.map +1 -1
- package/dist/nodes/Git/Git.node.js +114 -12
- package/dist/nodes/Git/Git.node.js.map +1 -1
- package/dist/nodes/Google/Drive/v1/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/Google/Drive/v1/GenericFunctions.js +3 -0
- package/dist/nodes/Google/Drive/v1/GenericFunctions.js.map +1 -1
- package/dist/nodes/HttpRequest/GenericFunctions.d.ts +6 -0
- package/dist/nodes/HttpRequest/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/HttpRequest/GenericFunctions.js +17 -1
- package/dist/nodes/HttpRequest/GenericFunctions.js.map +1 -1
- package/dist/nodes/HttpRequest/V1/HttpRequestV1.node.js +1 -1
- package/dist/nodes/HttpRequest/V1/HttpRequestV1.node.js.map +1 -1
- package/dist/nodes/HttpRequest/V2/HttpRequestV2.node.js +1 -1
- package/dist/nodes/HttpRequest/V2/HttpRequestV2.node.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.d.ts.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js +16 -12
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/utils/binaryData.d.ts.map +1 -1
- package/dist/nodes/HttpRequest/V3/utils/binaryData.js +9 -3
- package/dist/nodes/HttpRequest/V3/utils/binaryData.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/utils/response-context.d.ts +11 -0
- package/dist/nodes/HttpRequest/V3/utils/response-context.d.ts.map +1 -0
- package/dist/nodes/HttpRequest/V3/utils/response-context.js +22 -0
- package/dist/nodes/HttpRequest/V3/utils/response-context.js.map +1 -0
- package/dist/nodes/Microsoft/Outlook/v2/actions/contact/getAll.operation.d.ts.map +1 -1
- package/dist/nodes/Microsoft/Outlook/v2/actions/contact/getAll.operation.js +5 -2
- package/dist/nodes/Microsoft/Outlook/v2/actions/contact/getAll.operation.js.map +1 -1
- package/dist/nodes/Microsoft/SharePoint/helpers/utils.d.ts +2 -1
- package/dist/nodes/Microsoft/SharePoint/helpers/utils.d.ts.map +1 -1
- package/dist/nodes/Microsoft/SharePoint/helpers/utils.js +4 -4
- package/dist/nodes/Microsoft/SharePoint/helpers/utils.js.map +1 -1
- package/dist/nodes/Microsoft/Teams/MicrosoftTeamsTrigger.node.d.ts.map +1 -1
- package/dist/nodes/Microsoft/Teams/MicrosoftTeamsTrigger.node.js +47 -14
- package/dist/nodes/Microsoft/Teams/MicrosoftTeamsTrigger.node.js.map +1 -1
- package/dist/nodes/Microsoft/Teams/v2/helpers/types.d.ts +1 -0
- package/dist/nodes/Microsoft/Teams/v2/helpers/types.d.ts.map +1 -1
- package/dist/nodes/Microsoft/Teams/v2/helpers/utils-trigger.d.ts +5 -2
- package/dist/nodes/Microsoft/Teams/v2/helpers/utils-trigger.d.ts.map +1 -1
- package/dist/nodes/Microsoft/Teams/v2/helpers/utils-trigger.js +49 -1
- package/dist/nodes/Microsoft/Teams/v2/helpers/utils-trigger.js.map +1 -1
- package/dist/nodes/MongoDb/GenericFunctions.d.ts +4 -2
- package/dist/nodes/MongoDb/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/MongoDb/GenericFunctions.js +55 -72
- package/dist/nodes/MongoDb/GenericFunctions.js.map +1 -1
- package/dist/nodes/MongoDb/MongoDb.node.d.ts.map +1 -1
- package/dist/nodes/MongoDb/MongoDb.node.js +63 -26
- package/dist/nodes/MongoDb/MongoDb.node.js.map +1 -1
- package/dist/nodes/MongoDb/MongoDbProperties.js +1 -1
- package/dist/nodes/MongoDb/MongoDbProperties.js.map +1 -1
- package/dist/nodes/MySql/v1/MySqlV1.node.d.ts.map +1 -1
- package/dist/nodes/MySql/v1/MySqlV1.node.js +2 -1
- package/dist/nodes/MySql/v1/MySqlV1.node.js.map +1 -1
- package/dist/nodes/MySql/v2/actions/database/executeQuery.operation.d.ts.map +1 -1
- package/dist/nodes/MySql/v2/actions/database/executeQuery.operation.js +2 -1
- package/dist/nodes/MySql/v2/actions/database/executeQuery.operation.js.map +1 -1
- package/dist/nodes/MySql/v2/helpers/utils.d.ts.map +1 -1
- package/dist/nodes/MySql/v2/helpers/utils.js +14 -10
- package/dist/nodes/MySql/v2/helpers/utils.js.map +1 -1
- package/dist/nodes/NocoDB/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/NocoDB/GenericFunctions.js +11 -0
- package/dist/nodes/NocoDB/GenericFunctions.js.map +1 -1
- package/dist/nodes/NocoDB/isSameOrigin.d.ts +6 -0
- package/dist/nodes/NocoDB/isSameOrigin.d.ts.map +1 -0
- package/dist/nodes/NocoDB/isSameOrigin.js +16 -0
- package/dist/nodes/NocoDB/isSameOrigin.js.map +1 -0
- package/dist/nodes/Okta/UserDescription.js +3 -3
- package/dist/nodes/Okta/UserDescription.js.map +1 -1
- package/dist/nodes/QuickBase/GenericFunctions.d.ts +6 -0
- package/dist/nodes/QuickBase/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/QuickBase/GenericFunctions.js +25 -0
- package/dist/nodes/QuickBase/GenericFunctions.js.map +1 -1
- package/dist/nodes/QuickBase/QuickBase.node.d.ts.map +1 -1
- package/dist/nodes/QuickBase/QuickBase.node.js +7 -2
- package/dist/nodes/QuickBase/QuickBase.node.js.map +1 -1
- package/dist/nodes/QuickBase/RecordDescription.d.ts.map +1 -1
- package/dist/nodes/QuickBase/RecordDescription.js +58 -0
- package/dist/nodes/QuickBase/RecordDescription.js.map +1 -1
- package/dist/nodes/ReadBinaryFiles/ReadBinaryFiles.node.d.ts.map +1 -1
- package/dist/nodes/ReadBinaryFiles/ReadBinaryFiles.node.js +2 -5
- package/dist/nodes/ReadBinaryFiles/ReadBinaryFiles.node.js.map +1 -1
- package/dist/nodes/SeaTable/v1/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/SeaTable/v1/GenericFunctions.js +6 -1
- package/dist/nodes/SeaTable/v1/GenericFunctions.js.map +1 -1
- package/dist/nodes/SeaTable/v2/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/SeaTable/v2/GenericFunctions.js +6 -1
- package/dist/nodes/SeaTable/v2/GenericFunctions.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/asset/upload.operation.d.ts.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/asset/upload.operation.js +4 -14
- package/dist/nodes/SeaTable/v2/actions/asset/upload.operation.js.map +1 -1
- package/dist/nodes/ServiceNow/ServiceNow.node.d.ts.map +1 -1
- package/dist/nodes/ServiceNow/ServiceNow.node.js +24 -16
- package/dist/nodes/ServiceNow/ServiceNow.node.js.map +1 -1
- package/dist/nodes/Snowflake/Snowflake.node.d.ts.map +1 -1
- package/dist/nodes/Snowflake/Snowflake.node.js +2 -1
- package/dist/nodes/Snowflake/Snowflake.node.js.map +1 -1
- package/dist/typecheck.tsbuildinfo +1 -1
- package/dist/types/nodes.json +6 -6
- package/dist/utils/query-escaping.d.ts +16 -0
- package/dist/utils/query-escaping.d.ts.map +1 -0
- package/dist/utils/query-escaping.js +21 -0
- package/dist/utils/query-escaping.js.map +1 -0
- package/dist/utils/query-parameters.d.ts +23 -0
- package/dist/utils/query-parameters.d.ts.map +1 -0
- package/dist/utils/query-parameters.js +152 -0
- package/dist/utils/query-parameters.js.map +1 -0
- package/dist/utils/sendAndWait/utils.d.ts.map +1 -1
- package/dist/utils/sendAndWait/utils.js +8 -0
- package/dist/utils/sendAndWait/utils.js.map +1 -1
- package/dist/utils/sql-query-parameters.d.ts +6 -0
- package/dist/utils/sql-query-parameters.d.ts.map +1 -0
- package/dist/utils/sql-query-parameters.js +119 -0
- package/dist/utils/sql-query-parameters.js.map +1 -0
- package/dist/utils/workflowInputsResourceMapping/GenericFunctions.d.ts.map +1 -1
- package/dist/utils/workflowInputsResourceMapping/GenericFunctions.js +1 -3
- package/dist/utils/workflowInputsResourceMapping/GenericFunctions.js.map +1 -1
- package/package.json +9 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ICredentialDataDecryptedObject, type ICredentialTestRequest, type ICredentialType, type IHttpRequestOptions, type INodeProperties } from 'n8n-workflow';
|
|
2
2
|
export declare class CiscoSecureEndpointApi implements ICredentialType {
|
|
3
3
|
name: string;
|
|
4
4
|
displayName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CiscoSecureEndpointApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/CiscoSecureEndpointApi.credentials.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"CiscoSecureEndpointApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/CiscoSecureEndpointApi.credentials.ts"],"names":[],"mappings":"AACA,OAAO,EAIN,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,MAAM,cAAc,CAAC;AAiBtB,qBAAa,sBAAuB,YAAW,eAAe;IAC7D,IAAI,SAA4B;IAEhC,WAAW,SAAqC;IAEhD,gBAAgB,SAAyB;IAEzC,IAAI;;;MAAiF;IAErF,eAAe;;;;MAIb;IAEF,UAAU,EAAE,eAAe,EAAE,CAyB3B;IAEI,YAAY,CACjB,WAAW,EAAE,8BAA8B,EAC3C,cAAc,EAAE,mBAAmB,GACjC,OAAO,CAAC,mBAAmB,CAAC;IA4E/B,IAAI,EAAE,sBAAsB,CAQ1B;CACF"}
|
|
@@ -5,6 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.CiscoSecureEndpointApi = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
9
|
+
// `region` is interpolated into the token-exchange host, so the stored value must stay
|
|
10
|
+
// inside this fixed set. The options field and the runtime check both read it from here.
|
|
11
|
+
const REGION_OPTIONS = [
|
|
12
|
+
{ name: 'Asia Pacific, Japan, and China', value: 'apjc.amp' },
|
|
13
|
+
{ name: 'Europe', value: 'eu.amp' },
|
|
14
|
+
{ name: 'North America', value: 'amp' },
|
|
15
|
+
];
|
|
16
|
+
function assertSupportedRegion(region) {
|
|
17
|
+
if (typeof region !== 'string' || !REGION_OPTIONS.some((option) => option.value === region)) {
|
|
18
|
+
throw new n8n_workflow_1.UserError('Unsupported Cisco Secure Endpoint region');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
8
21
|
class CiscoSecureEndpointApi {
|
|
9
22
|
name = 'ciscoSecureEndpointApi';
|
|
10
23
|
displayName = 'Cisco Secure Endpoint (AMP) API';
|
|
@@ -20,20 +33,7 @@ class CiscoSecureEndpointApi {
|
|
|
20
33
|
displayName: 'Region',
|
|
21
34
|
name: 'region',
|
|
22
35
|
type: 'options',
|
|
23
|
-
options: [
|
|
24
|
-
{
|
|
25
|
-
name: 'Asia Pacific, Japan, and China',
|
|
26
|
-
value: 'apjc.amp',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'Europe',
|
|
30
|
-
value: 'eu.amp',
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
name: 'North America',
|
|
34
|
-
value: 'amp',
|
|
35
|
-
},
|
|
36
|
-
],
|
|
36
|
+
options: [...REGION_OPTIONS],
|
|
37
37
|
default: 'amp',
|
|
38
38
|
},
|
|
39
39
|
{
|
|
@@ -58,6 +58,26 @@ class CiscoSecureEndpointApi {
|
|
|
58
58
|
const clientId = credentials.clientId;
|
|
59
59
|
const clientSecret = credentials.clientSecret;
|
|
60
60
|
const region = credentials.region;
|
|
61
|
+
assertSupportedRegion(region);
|
|
62
|
+
// These token POSTs go through axios directly, so apply the credential's own
|
|
63
|
+
// allow-list to each request host instead of relying on the node HTTP layer.
|
|
64
|
+
const allowedDomains = (0, n8n_workflow_1.getCredentialAllowedDomains)(credentials);
|
|
65
|
+
if (credentials.allowedHttpRequestDomains === 'domains' && !allowedDomains) {
|
|
66
|
+
throw new n8n_workflow_1.UserError('No allowed domains specified. Configure allowed domains or change restriction setting.');
|
|
67
|
+
}
|
|
68
|
+
const assertHostAllowed = (url) => {
|
|
69
|
+
if (allowedDomains && !(0, n8n_workflow_1.isDomainAllowed)(url, { allowedDomains })) {
|
|
70
|
+
throw new n8n_workflow_1.UserError(`Domain not allowed: This credential is restricted from accessing ${new URL(url).host}. Only the following domains are allowed: ${allowedDomains}`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
// axios follows redirects on its own, so re-check each redirect target against the
|
|
74
|
+
// allow-list, not only the initial URL.
|
|
75
|
+
const beforeRedirect = (redirectedRequest) => {
|
|
76
|
+
if (redirectedRequest.href)
|
|
77
|
+
assertHostAllowed(redirectedRequest.href);
|
|
78
|
+
};
|
|
79
|
+
const secureXTokenUrl = `https://visibility.${region}.cisco.com/iroh/oauth2/token`;
|
|
80
|
+
assertHostAllowed(secureXTokenUrl);
|
|
61
81
|
const secureXToken = await (0, axios_1.default)({
|
|
62
82
|
headers: {
|
|
63
83
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -71,8 +91,11 @@ class CiscoSecureEndpointApi {
|
|
|
71
91
|
data: new URLSearchParams({
|
|
72
92
|
grant_type: 'client_credentials',
|
|
73
93
|
}).toString(),
|
|
74
|
-
url:
|
|
94
|
+
url: secureXTokenUrl,
|
|
95
|
+
beforeRedirect,
|
|
75
96
|
});
|
|
97
|
+
const secureEndpointTokenUrl = `https://api.${region}.cisco.com/v3/access_tokens`;
|
|
98
|
+
assertHostAllowed(secureEndpointTokenUrl);
|
|
76
99
|
const secureEndpointToken = await (0, axios_1.default)({
|
|
77
100
|
headers: {
|
|
78
101
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -83,7 +106,8 @@ class CiscoSecureEndpointApi {
|
|
|
83
106
|
data: new URLSearchParams({
|
|
84
107
|
grant_type: 'client_credentials',
|
|
85
108
|
}).toString(),
|
|
86
|
-
url:
|
|
109
|
+
url: secureEndpointTokenUrl,
|
|
110
|
+
beforeRedirect,
|
|
87
111
|
});
|
|
88
112
|
const requestOptionsWithAuth = {
|
|
89
113
|
...requestOptions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CiscoSecureEndpointApi.credentials.js","sourceRoot":"","sources":["../../credentials/CiscoSecureEndpointApi.credentials.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;
|
|
1
|
+
{"version":3,"file":"CiscoSecureEndpointApi.credentials.js","sourceRoot":"","sources":["../../credentials/CiscoSecureEndpointApi.credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.operation.d.ts","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/actions/read.operation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"read.operation.d.ts","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/actions/read.operation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAEf,MAAM,cAAc,CAAC;AAWtB,eAAO,MAAM,UAAU,EAAE,eAAe,EAsDvC,CAAC;AAQF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;GAAmD,CAAC;AAE5E,wBAAsB,OAAO,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,kBAAkB,EAAE,iCAoGjF"}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.description = exports.properties = void 0;
|
|
7
4
|
exports.execute = execute;
|
|
8
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
9
5
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
10
6
|
const utilities_1 = require("../../../../utils/utilities");
|
|
11
7
|
const utils_1 = require("../helpers/utils");
|
|
@@ -72,6 +68,10 @@ exports.description = (0, utilities_1.updateDisplayOptions)(displayOptions, expo
|
|
|
72
68
|
async function execute(items) {
|
|
73
69
|
const returnData = [];
|
|
74
70
|
let fileSelector;
|
|
71
|
+
// One glob-time budget for the whole execution, so N items cannot each burn a
|
|
72
|
+
// full timeout. Only time spent globbing is charged — file reads in between
|
|
73
|
+
// must not make a later selector look slow.
|
|
74
|
+
let remainingGlobMs = utils_1.GLOB_TIMEOUT_MS;
|
|
75
75
|
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
76
76
|
try {
|
|
77
77
|
fileSelector = String(this.getNodeParameter('fileSelector', itemIndex));
|
|
@@ -84,7 +84,16 @@ async function execute(items) {
|
|
|
84
84
|
if (options.dataPropertyName) {
|
|
85
85
|
dataPropertyName = options.dataPropertyName;
|
|
86
86
|
}
|
|
87
|
-
const
|
|
87
|
+
const startedGlobAt = Date.now();
|
|
88
|
+
let files;
|
|
89
|
+
try {
|
|
90
|
+
files = await (0, utils_1.globWithDeadline)(this.getNode(), fileSelector, {}, itemIndex, remainingGlobMs);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
// Charge the budget even when the glob times out, so a failing item
|
|
94
|
+
// cannot hand the next one (with Continue On Fail) a fresh full budget.
|
|
95
|
+
remainingGlobMs -= Date.now() - startedGlobAt;
|
|
96
|
+
}
|
|
88
97
|
const newItems = [];
|
|
89
98
|
for (const filePath of files) {
|
|
90
99
|
const stream = await this.helpers.createReadStream(await this.helpers.resolvePath(filePath));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.operation.js","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/actions/read.operation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"read.operation.js","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/actions/read.operation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import glob from 'fast-glob';
|
|
2
|
+
export interface GlobWorkerData {
|
|
3
|
+
pattern: string;
|
|
4
|
+
options: glob.Options;
|
|
5
|
+
}
|
|
6
|
+
export type GlobWorkerError = {
|
|
7
|
+
message: string;
|
|
8
|
+
code?: string;
|
|
9
|
+
path?: string;
|
|
10
|
+
};
|
|
11
|
+
export type GlobWorkerResponse = {
|
|
12
|
+
ok: true;
|
|
13
|
+
files: string[];
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
error: GlobWorkerError;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=glob.worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.worker.d.ts","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/helpers/glob.worker.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAM7B,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC;CACtB;AAID,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,kBAAkB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
7
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
8
|
+
const { pattern, options } = node_worker_threads_1.workerData;
|
|
9
|
+
(0, fast_glob_1.default)(pattern, options)
|
|
10
|
+
.then((files) => node_worker_threads_1.parentPort?.postMessage({ ok: true, files }))
|
|
11
|
+
.catch((error) => {
|
|
12
|
+
const errno = error;
|
|
13
|
+
node_worker_threads_1.parentPort?.postMessage({
|
|
14
|
+
ok: false,
|
|
15
|
+
error: {
|
|
16
|
+
message: error instanceof Error ? error.message : String(error),
|
|
17
|
+
code: errno?.code,
|
|
18
|
+
path: errno?.path,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=glob.worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.worker.js","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/helpers/glob.worker.ts"],"names":[],"mappings":";;;;;AAAA,0DAA6B;AAC7B,6DAA6D;AAkB7D,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,gCAA4B,CAAC;AAE1D,IAAA,mBAAI,EAAC,OAAO,EAAE,OAAO,CAAC;KACpB,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,gCAAU,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAA+B,CAAC,CAAC;KAC1F,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACzB,MAAM,KAAK,GAAG,KAA8B,CAAC;IAC7C,gCAAU,EAAE,WAAW,CAAC;QACvB,EAAE,EAAE,KAAK;QACT,KAAK,EAAE;YACN,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC/D,IAAI,EAAE,KAAK,EAAE,IAAI;YACjB,IAAI,EAAE,KAAK,EAAE,IAAI;SACjB;KAC4B,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import glob from 'fast-glob';
|
|
2
|
+
import type { IDataObject, IExecuteFunctions, INode } from 'n8n-workflow';
|
|
2
3
|
import { NodeOperationError } from 'n8n-workflow';
|
|
3
4
|
export declare function errorMapper(this: IExecuteFunctions, error: Error, itemIndex: number, context?: IDataObject): NodeOperationError;
|
|
4
5
|
export declare function escapeSpecialCharacters(str: string): string;
|
|
6
|
+
export declare const GLOB_TIMEOUT_MS = 10000;
|
|
7
|
+
export declare function isTriviallyCheapSelector(selector: string): boolean;
|
|
8
|
+
export declare function globWithDeadline(node: INode, pattern: string, options?: glob.Options, itemIndex?: number, budgetMs?: number): Promise<string[]>;
|
|
5
9
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/helpers/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/helpers/utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOlD,wBAAgB,WAAW,CAC1B,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,WAAW,sBA0BrB;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,UAKlD;AAOD,eAAO,MAAM,eAAe,QAAS,CAAC;AAiCtC,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAIlE;AAED,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,IAAI,CAAC,OAAY,EAC1B,SAAS,SAAI,EACb,QAAQ,SAAkB,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiCnB"}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GLOB_TIMEOUT_MS = void 0;
|
|
3
7
|
exports.errorMapper = errorMapper;
|
|
4
8
|
exports.escapeSpecialCharacters = escapeSpecialCharacters;
|
|
9
|
+
exports.isTriviallyCheapSelector = isTriviallyCheapSelector;
|
|
10
|
+
exports.globWithDeadline = globWithDeadline;
|
|
11
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
5
12
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
13
|
+
const node_fs_1 = require("node:fs");
|
|
14
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
6
16
|
function errorMapper(error, itemIndex, context) {
|
|
7
17
|
let message;
|
|
8
18
|
let description;
|
|
@@ -32,4 +42,81 @@ function escapeSpecialCharacters(str) {
|
|
|
32
42
|
str = str.replace(/[()]/g, '\\$&');
|
|
33
43
|
return str;
|
|
34
44
|
}
|
|
45
|
+
// Matching a free-form selector can cost far more than the files it returns —
|
|
46
|
+
// e.g. many `*` in one segment, or a deep `**` walk. Run it off the main event
|
|
47
|
+
// loop so a slow selector can be bounded and terminated, keeping the instance
|
|
48
|
+
// responsive. One budget covers a whole node execution (see read.operation),
|
|
49
|
+
// and it counts glob time only, so file reads between items never spend it.
|
|
50
|
+
exports.GLOB_TIMEOUT_MS = 10_000;
|
|
51
|
+
// Compiled output is `helpers/utils.js`, with `glob.worker.js` beside it. Under
|
|
52
|
+
// Vitest the source `.ts` runs, whose sibling `.js` is absent, so fall back to
|
|
53
|
+
// the build output (the package is built before tests run). `lastIndexOf` keeps
|
|
54
|
+
// the mapping correct even when a parent directory is also named `nodes`.
|
|
55
|
+
function resolveGlobWorkerPath() {
|
|
56
|
+
const { dir } = node_path_1.default.parse(__filename);
|
|
57
|
+
const sibling = node_path_1.default.join(dir, 'glob.worker.js');
|
|
58
|
+
if ((0, node_fs_1.existsSync)(sibling))
|
|
59
|
+
return sibling;
|
|
60
|
+
const marker = `${node_path_1.default.sep}nodes${node_path_1.default.sep}`;
|
|
61
|
+
const at = dir.lastIndexOf(marker);
|
|
62
|
+
const distDir = `${dir.slice(0, at)}${node_path_1.default.sep}dist${dir.slice(at)}`;
|
|
63
|
+
return node_path_1.default.join(distDir, 'glob.worker.js');
|
|
64
|
+
}
|
|
65
|
+
function tooComplexError(node, itemIndex) {
|
|
66
|
+
return new n8n_workflow_1.NodeOperationError(node, 'File(s) Selector is too complex', {
|
|
67
|
+
itemIndex,
|
|
68
|
+
description: 'The selector took too long to evaluate. Use a more specific pattern with fewer wildcards.',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const MAX_MAIN_THREAD_WILDCARDS = 2;
|
|
72
|
+
// A whitelist fast path, never a security check: it only returns true for a
|
|
73
|
+
// selector that provably cannot backtrack or recurse, so the match is safe to
|
|
74
|
+
// run inline and skip the worker. Anything with glob syntax we would have to
|
|
75
|
+
// parse — braces, parens/extglob, classes, escapes, `!`, or a `**` globstar —
|
|
76
|
+
// falls through to the worker instead, as does more than a couple of `*`. `?`
|
|
77
|
+
// is fixed-width, so its count is irrelevant.
|
|
78
|
+
function isTriviallyCheapSelector(selector) {
|
|
79
|
+
if (selector.includes('**'))
|
|
80
|
+
return false;
|
|
81
|
+
if (/[{}()[\]\\!]/.test(selector))
|
|
82
|
+
return false;
|
|
83
|
+
return (selector.match(/\*/g)?.length ?? 0) <= MAX_MAIN_THREAD_WILDCARDS;
|
|
84
|
+
}
|
|
85
|
+
async function globWithDeadline(node, pattern, options = {}, itemIndex = 0, budgetMs = exports.GLOB_TIMEOUT_MS) {
|
|
86
|
+
// Plain selectors run inline; only the rest pay for a worker and a deadline.
|
|
87
|
+
if (isTriviallyCheapSelector(pattern))
|
|
88
|
+
return await (0, fast_glob_1.default)(pattern, options);
|
|
89
|
+
if (budgetMs <= 0)
|
|
90
|
+
throw tooComplexError(node, itemIndex);
|
|
91
|
+
const worker = new node_worker_threads_1.Worker(resolveGlobWorkerPath(), {
|
|
92
|
+
workerData: { pattern, options },
|
|
93
|
+
});
|
|
94
|
+
let timer;
|
|
95
|
+
try {
|
|
96
|
+
return await new Promise((resolve, reject) => {
|
|
97
|
+
timer = setTimeout(() => reject(tooComplexError(node, itemIndex)), budgetMs);
|
|
98
|
+
worker.once('message', (response) => {
|
|
99
|
+
if (response.ok)
|
|
100
|
+
return resolve(response.files);
|
|
101
|
+
// Reattach `code`/`path` so errorMapper and NodeApiError see the real values.
|
|
102
|
+
const error = new Error(response.error.message);
|
|
103
|
+
error.code = response.error.code;
|
|
104
|
+
error.path = response.error.path;
|
|
105
|
+
reject(error);
|
|
106
|
+
});
|
|
107
|
+
worker.once('error', reject);
|
|
108
|
+
worker.once('exit', (code) => {
|
|
109
|
+
if (code !== 0)
|
|
110
|
+
reject(new Error(`Glob worker stopped with exit code ${code}`));
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
if (timer)
|
|
116
|
+
clearTimeout(timer);
|
|
117
|
+
// Fire-and-forget: tear the thread down without blocking the result or
|
|
118
|
+
// letting a terminate rejection mask the real outcome.
|
|
119
|
+
void worker.terminate().catch(() => { });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
35
122
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/helpers/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../nodes/Files/ReadWriteFile/helpers/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formCompletionUtils.d.ts","sourceRoot":"","sources":["../../../../nodes/Form/utils/formCompletionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAIzB,MAAM,cAAc,CAAC;AAQtB,eAAO,MAAM,cAAc,GAC1B,SAAS,iBAAiB,KACxB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAsBnE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAChC,SAAS,iBAAiB,EAC1B,KAAK,QAAQ,EACb,SAAS,kBAAkB,KACzB,OAAO,CAAC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"formCompletionUtils.d.ts","sourceRoot":"","sources":["../../../../nodes/Form/utils/formCompletionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAIzB,MAAM,cAAc,CAAC;AAQtB,eAAO,MAAM,cAAc,GAC1B,SAAS,iBAAiB,KACxB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAsBnE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAChC,SAAS,iBAAiB,EAC1B,KAAK,QAAQ,EACb,SAAS,kBAAkB,KACzB,OAAO,CAAC,oBAAoB,CAmD9B,CAAC"}
|
|
@@ -31,7 +31,7 @@ exports.binaryResponse = binaryResponse;
|
|
|
31
31
|
const renderFormCompletion = async (context, res, trigger) => {
|
|
32
32
|
const completionTitle = context.getNodeParameter('completionTitle', '');
|
|
33
33
|
const completionMessage = context.getNodeParameter('completionMessage', '');
|
|
34
|
-
const redirectUrl = context.getNodeParameter('redirectUrl', '');
|
|
34
|
+
const redirectUrl = (0, utils_1.validateSafeRedirectUrl)(context.getNodeParameter('redirectUrl', '')) ?? undefined;
|
|
35
35
|
const options = context.getNodeParameter('options', {});
|
|
36
36
|
const respondWith = context.getNodeParameter('respondWith', '');
|
|
37
37
|
const binary = respondWith === 'returnBinary' ? await (0, exports.binaryResponse)(context) : '';
|
|
@@ -43,9 +43,16 @@ const renderFormCompletion = async (context, res, trigger) => {
|
|
|
43
43
|
title = context.evaluateExpression(`{{ $('${trigger?.name}').params.formTitle }}`);
|
|
44
44
|
}
|
|
45
45
|
const appendAttribution = context.evaluateExpression(`{{ $('${trigger?.name}').params.options?.appendAttribution === false ? false : true }}`);
|
|
46
|
-
|
|
46
|
+
// Without a valid URL the page shows the completion card, so it keeps the sandbox.
|
|
47
|
+
const redirects = respondWith === 'redirect' && redirectUrl !== undefined;
|
|
48
|
+
if (!redirects && !(0, n8n_core_1.isFormHtmlSandboxingDisabled)()) {
|
|
47
49
|
res.setHeader('Content-Security-Policy', (0, n8n_core_1.getHtmlSandboxCSP)());
|
|
48
50
|
}
|
|
51
|
+
else {
|
|
52
|
+
// The form route sandboxes every response. Remove it here: the redirect does not
|
|
53
|
+
// work under the sandbox (n8n-io/n8n#20303).
|
|
54
|
+
res.removeHeader('Content-Security-Policy');
|
|
55
|
+
}
|
|
49
56
|
res.render('form-trigger-completion', {
|
|
50
57
|
title: completionTitle,
|
|
51
58
|
message: (0, utils_1.sanitizeHtml)(completionMessage),
|
|
@@ -54,7 +61,7 @@ const renderFormCompletion = async (context, res, trigger) => {
|
|
|
54
61
|
responseText,
|
|
55
62
|
responseBinary: encodeURIComponent(JSON.stringify(binary)),
|
|
56
63
|
dangerousCustomCss: (0, utils_1.sanitizeCustomCss)(options.customCss),
|
|
57
|
-
redirectUrl
|
|
64
|
+
redirectUrl,
|
|
58
65
|
});
|
|
59
66
|
return { noWebhookResponse: true };
|
|
60
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formCompletionUtils.js","sourceRoot":"","sources":["../../../../nodes/Form/utils/formCompletionUtils.ts"],"names":[],"mappings":";;;AACA,uCAA2E;AAC3E,+CAOsB;AAEtB,mCAAmF;AAEnF,MAAM,qBAAqB,GAAG,CAAC,OAA0B,EAAE,QAAgB,EAAe,EAAE;IAC3F,OAAO,OAAO,CAAC,kBAAkB,CAAC,SAAS,QAAQ,sBAAsB,CAAgB,CAAC;AAC3F,CAAC,CAAC;AAEK,MAAM,cAAc,GAAG,KAAK,EAClC,OAA0B,EAC2C,EAAE;IACvE,MAAM,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,EAAE,CAAW,CAAC;IACxF,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,WAAW;SAC5B,OAAO,EAAE;SACT,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,qBAAqB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjG,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,IAAI,+BAAgB,CAAC,6BAA6B,kBAAkB,SAAS,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAClE,kBAAkB,CACH,CAAC;IAEjB,OAAO;QACN,yDAAyD;QACzD,0CAA0C;QAC1C,IAAI,EAAE,UAAU,CAAC,EAAE;YAClB,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAC5F,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QACxB,QAAQ,EAAE,UAAU,CAAC,QAAQ,IAAI,MAAM;QACvC,IAAI,EAAE,UAAU,CAAC,QAAQ;KACzB,CAAC;AACH,CAAC,CAAC;AAxBW,QAAA,cAAc,kBAwBzB;AAEK,MAAM,oBAAoB,GAAG,KAAK,EACxC,OAA0B,EAC1B,GAAa,EACb,OAA2B,EACK,EAAE;IAClC,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,EAAE,CAAW,CAAC;IAClF,MAAM,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,EAAE,CAAW,CAAC;IACtF,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"formCompletionUtils.js","sourceRoot":"","sources":["../../../../nodes/Form/utils/formCompletionUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare const fileUrlToGitPath: (reference: string) => string;
|
|
2
3
|
export declare class Git implements INodeType {
|
|
3
4
|
description: INodeTypeDescription;
|
|
4
5
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Git.node.d.ts","sourceRoot":"","sources":["../../../nodes/Git/Git.node.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAEpB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Git.node.d.ts","sourceRoot":"","sources":["../../../nodes/Git/Git.node.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAEpB,MAAM,cAAc,CAAC;AA8DtB,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,KAAG,MAyBpD,CAAC;AAwDF,qBAAa,GAAI,YAAW,SAAS;IACpC,WAAW,EAAE,oBAAoB,CAoL/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAk0BvE"}
|
|
@@ -3,18 +3,87 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Git = void 0;
|
|
6
|
+
exports.Git = exports.fileUrlToGitPath = void 0;
|
|
7
7
|
const config_1 = require("@n8n/config");
|
|
8
8
|
const di_1 = require("@n8n/di");
|
|
9
9
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
10
10
|
const node_crypto_1 = require("node:crypto");
|
|
11
11
|
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const node_os_1 = require("node:os");
|
|
12
13
|
const path_1 = require("path");
|
|
13
14
|
const simple_git_1 = __importDefault(require("simple-git"));
|
|
14
15
|
const url_1 = require("url");
|
|
15
16
|
const descriptions_1 = require("./descriptions");
|
|
16
17
|
const GenericFunctions_1 = require("./GenericFunctions");
|
|
17
18
|
const REMOTE_HELPER_TRANSPORT = /^[a-zA-Z][a-zA-Z0-9+.-]*::/;
|
|
19
|
+
const utf8Decoder = new TextDecoder('utf-8', { fatal: true });
|
|
20
|
+
// Decode `%XX` runs to bytes like git does; throw on invalid UTF-8 or NUL so a path that
|
|
21
|
+
// cannot be compared to git's byte-for-byte is denied, not checked against a lossy `U+FFFD`.
|
|
22
|
+
const decodeGitPercentEscapes = (segment) => segment.replace(/(?:%[0-9a-fA-F]{2})+/g, (run) => {
|
|
23
|
+
const decoded = utf8Decoder.decode(Uint8Array.from(run.match(/%[0-9a-fA-F]{2}/g).map((pair) => parseInt(pair.slice(1), 16))));
|
|
24
|
+
if (decoded.includes('\0')) {
|
|
25
|
+
throw new n8n_workflow_1.ApplicationError('Repository reference contains a NUL byte');
|
|
26
|
+
}
|
|
27
|
+
return decoded;
|
|
28
|
+
});
|
|
29
|
+
// Reconstruct the path git's file transport opens, without the normalisation `URL` applies:
|
|
30
|
+
// `URL` splits off `?`/`#` and collapses `..` lexically; git keeps them and lets the kernel
|
|
31
|
+
// resolve `..` after symlinks. Validate what git opens, not a URL-normalised derivative.
|
|
32
|
+
const fileUrlToGitPath = (reference) => {
|
|
33
|
+
const hasAuthority = /^file:\/\//i.test(reference);
|
|
34
|
+
// Decode before splitting: git decodes first, so a `%2F` in the authority shifts the boundary.
|
|
35
|
+
let path = decodeGitPercentEscapes(reference.replace(/^file:(\/\/)?/i, ''));
|
|
36
|
+
if (hasAuthority) {
|
|
37
|
+
const pathStart = path.indexOf('/');
|
|
38
|
+
const authority = pathStart === -1 ? path : path.slice(0, pathStart);
|
|
39
|
+
// `file://C:/repo` puts a Windows drive, not a host, in the authority slot; keep it as
|
|
40
|
+
// the path. On POSIX git reads `C:` as a named authority and opens the path after it,
|
|
41
|
+
// so the drive-letter case only holds on Windows. A real named authority is not a local
|
|
42
|
+
// path (the OS can read it as a UNC share on Windows), so refuse anything but an empty
|
|
43
|
+
// host or `localhost` rather than guess which side wins.
|
|
44
|
+
if (process.platform === 'win32' && /^[a-zA-Z]:$/.test(authority)) {
|
|
45
|
+
return path;
|
|
46
|
+
}
|
|
47
|
+
if (authority !== '' && authority.toLowerCase() !== 'localhost') {
|
|
48
|
+
throw new n8n_workflow_1.ApplicationError('Repository reference has an unsupported file authority');
|
|
49
|
+
}
|
|
50
|
+
path = pathStart === -1 ? '' : path.slice(pathStart);
|
|
51
|
+
}
|
|
52
|
+
// `file:///C:/repo` -> `C:/repo`: drop the slash git strips before a Windows drive letter.
|
|
53
|
+
if (process.platform === 'win32' && /^\/[a-zA-Z]:[\\/]/.test(path)) {
|
|
54
|
+
path = path.slice(1);
|
|
55
|
+
}
|
|
56
|
+
return path;
|
|
57
|
+
};
|
|
58
|
+
exports.fileUrlToGitPath = fileUrlToGitPath;
|
|
59
|
+
// Ask git which git directory a candidate resolves to, so the gitfile (`gitdir: <path>`) is
|
|
60
|
+
// parsed exactly as git parses it at clone time, not by a reimplementation that drifts from
|
|
61
|
+
// git's byte semantics. Runs with the command-bearing config pinned and a clean env, like the
|
|
62
|
+
// operation itself, so resolution cannot invoke an external program.
|
|
63
|
+
const resolveGitDirWithGit = async (candidate) => {
|
|
64
|
+
const config = ['core.hooksPath=/dev/null'];
|
|
65
|
+
const unsafe = { allowUnsafeHooksPath: true };
|
|
66
|
+
for (const [key, value, unsafeFlag] of COMMAND_CONFIG_KEYS) {
|
|
67
|
+
config.push(`${key}=${value}`);
|
|
68
|
+
unsafe[unsafeFlag] = true;
|
|
69
|
+
}
|
|
70
|
+
const env = Object.create(null);
|
|
71
|
+
env.GIT_TERMINAL_PROMPT = '0';
|
|
72
|
+
try {
|
|
73
|
+
// `--resolve-git-dir` takes an absolute path, so git's cwd does not steer resolution.
|
|
74
|
+
const resolver = (0, simple_git_1.default)({ baseDir: (0, node_os_1.tmpdir)(), config, unsafe }).env(env);
|
|
75
|
+
const output = await resolver.raw(['rev-parse', '--resolve-git-dir', candidate]);
|
|
76
|
+
// git prints the path and a single terminator. Strip only that terminator: a trailing
|
|
77
|
+
// space, or an embedded newline, is a real byte of a POSIX directory name. Windows
|
|
78
|
+
// forbids `\r`/`\n` in a name, so there the terminator can include `\r`.
|
|
79
|
+
return process.platform === 'win32' ? output.replace(/\r?\n$/, '') : output.replace(/\n$/, '');
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// git could not resolve a git directory from this candidate. The clone runs the same
|
|
83
|
+
// git, so a candidate git cannot resolve here is one git cannot open there either.
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
18
87
|
// Deliberately distinct from the `repositoryPath` message so the two guards can be told apart.
|
|
19
88
|
const REPOSITORY_OUT_OF_BOUNDS_MESSAGE = 'The git repository containing this path is outside the allowed file paths';
|
|
20
89
|
const REPOSITORY_OUT_OF_BOUNDS_DESCRIPTION = "The working tree or the git directory of this repository is outside the allowed file paths, matched by the blocked file patterns, or inside n8n's own directories";
|
|
@@ -226,7 +295,9 @@ class Git {
|
|
|
226
295
|
};
|
|
227
296
|
const prepareRepository = async (repositoryPath) => {
|
|
228
297
|
const authentication = this.getNodeParameter('authentication', 0);
|
|
229
|
-
|
|
298
|
+
// Skip `file:` refs: they carry no credentials, and `new URL` would collapse `..`
|
|
299
|
+
// and diverge from the path the allowed-path check validated.
|
|
300
|
+
if (authentication === 'gitPassword' && !/^file:/i.test(repositoryPath.trim())) {
|
|
230
301
|
const gitCredentials = await this.getCredentials('gitPassword');
|
|
231
302
|
const url = new url_1.URL(repositoryPath);
|
|
232
303
|
url.username = gitCredentials.username;
|
|
@@ -298,9 +369,39 @@ class Git {
|
|
|
298
369
|
if (this.helpers.isFilePathBlocked(resolvedLocalRepositoryPath)) {
|
|
299
370
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Access to the ${repositoryType} repository path is not allowed`);
|
|
300
371
|
}
|
|
372
|
+
await assertGitLinkTargetAllowed(resolvedLocalRepositoryPath, repositoryType);
|
|
373
|
+
};
|
|
374
|
+
// git discovers a repository through a `.git` gitfile (`gitdir: <path>`), which can point
|
|
375
|
+
// the real git directory anywhere, including outside the allowed paths. Resolve the
|
|
376
|
+
// pointer with git and bound-check the directory git would open.
|
|
377
|
+
const assertGitLinkTargetAllowed = async (resolvedRepositoryPath, repositoryType) => {
|
|
378
|
+
// The same locations git appends to a local source, built like git does: a bare path
|
|
379
|
+
// and a `.git` suffix with no separator, so `<path>.git` and `<path>.git/.git` are
|
|
380
|
+
// siblings of the source, not children.
|
|
381
|
+
const candidates = [
|
|
382
|
+
resolvedRepositoryPath,
|
|
383
|
+
(0, path_1.join)(resolvedRepositoryPath, '.git'),
|
|
384
|
+
`${resolvedRepositoryPath}.git`,
|
|
385
|
+
`${resolvedRepositoryPath}.git${path_1.sep}.git`,
|
|
386
|
+
];
|
|
387
|
+
for (const candidate of candidates) {
|
|
388
|
+
const gitDir = await resolveGitDirWithGit(candidate);
|
|
389
|
+
if (gitDir === undefined) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const resolvedGitDir = await resolvePathAllowingMissingParents(gitDir);
|
|
393
|
+
if (this.helpers.isFilePathBlocked((0, GenericFunctions_1.ownerOfGitDir)(resolvedGitDir))) {
|
|
394
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Access to the ${repositoryType} repository path is not allowed`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
301
397
|
};
|
|
302
398
|
const assertRepositoryReferenceAllowed = async (repository, repositoryType) => {
|
|
303
399
|
const trimmedRepository = repository.trim();
|
|
400
|
+
// git clones the raw value, so surrounding whitespace would make it open a path this
|
|
401
|
+
// check never saw. Refuse it instead of validating a trimmed stand-in.
|
|
402
|
+
if (repository !== trimmedRepository) {
|
|
403
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `${repositoryType === 'source' ? 'Source' : 'Target'} repository cannot have leading or trailing whitespace`);
|
|
404
|
+
}
|
|
304
405
|
if (trimmedRepository.startsWith('-')) {
|
|
305
406
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `${repositoryType === 'source' ? 'Source' : 'Target'} repository cannot start with a hyphen`);
|
|
306
407
|
}
|
|
@@ -312,15 +413,16 @@ class Git {
|
|
|
312
413
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `${repositoryType === 'source' ? 'Source' : 'Target'} repository protocol is not allowed`);
|
|
313
414
|
}
|
|
314
415
|
if (hasUrlScheme(trimmedRepository)) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
416
|
+
// git uses its local transport for any `file:` scheme, even one `new URL` rejects.
|
|
417
|
+
if (/^file:/i.test(trimmedRepository)) {
|
|
418
|
+
let gitPath;
|
|
419
|
+
try {
|
|
420
|
+
gitPath = (0, exports.fileUrlToGitPath)(trimmedRepository);
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Access to the ${repositoryType} repository path is not allowed`);
|
|
424
|
+
}
|
|
425
|
+
await assertLocalRepositoryPathAllowed(gitPath, repositoryType);
|
|
324
426
|
}
|
|
325
427
|
return;
|
|
326
428
|
}
|
|
@@ -847,7 +949,7 @@ class Git {
|
|
|
847
949
|
});
|
|
848
950
|
continue;
|
|
849
951
|
}
|
|
850
|
-
throw error;
|
|
952
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex });
|
|
851
953
|
}
|
|
852
954
|
}
|
|
853
955
|
return [returnItems];
|