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

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,109 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"resource": "blob",
"operation": "create",
"container": { "__rl": true, "value": "mycontainer", "mode": "list" },
"blobCreate": "myblob",
"options": {
"accessTier": "Hot",
"blobType": "BlockBlob",
"cacheControl": "no-cache",
"contentCrc64": "3EDB64E77CB16A4C",
"contentEncoding": "utf8",
"contentLanguage": "en-US",
"contentMd5": "b97f46db5f3be7709d942eefe30e5b45",
"contentType": "application/json",
"encryptionContext": "context",
"encryptionScope": "encryptionScope",
"expiryOption": "Absolute",
"filename": "file.json",
"immutabilityPolicyUntilDate": "2025-01-01T00:00:00",
"immutabilityPolicyMode": "unlocked",
"leaseId": "leaseId123",
"legalHold": true,
"metadata": { "metadataValues": [{ "fieldName": "key1", "fieldValue": "value1" }] },
"origin": "http://contoso.com",
"tags": { "tagValues": [{ "tagName": "tag1", "tagValue": "value1" }] }
},
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [660, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
},
{
"parameters": {
"mode": "jsonToBinary",
"convertAllData": false,
"options": { "useRawData": true }
},
"name": "Move Binary Data",
"type": "n8n-nodes-base.moveBinaryData",
"typeVersion": 1,
"position": [440, 0],
"id": "221e00ed-8c9b-4313-a4d6-b87c64b09d80"
},
{
"parameters": {
"mode": "raw",
"jsonOutput": "{\n \"data\": {\n \"my_field_1\": \"value\",\n \"my_field_2\": 1\n }\n}\n",
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [220, 0],
"id": "6c03903b-0177-4e94-b1ad-4f6ad9e84f62",
"name": "Edit Fields"
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Edit Fields", "type": "main", "index": 0 }]]
},
"Move Binary Data": { "main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]] },
"Edit Fields": { "main": [[{ "node": "Move Binary Data", "type": "main", "index": 0 }]] }
},
"pinData": {
"Azure Storage": [
{
"json": {
"etag": "\"0x22769D26D3F3740\"",
"lastModified": "Thu, 23 Jan 2025 17:53:23 GMT",
"contentMd5": "aWQGHD8kGQd5ZtEN/S1/aw==",
"requestId": "75b87ee3-a7f7-468d-b7d1-e7e7b3173dab",
"version": "2025-01-05",
"date": "Thu, 23 Jan 2025 17:53:23 GMT",
"requestServerEncrypted": true,
"accessControlAllowCredentials": "access-control-allow-credentials",
"accessControlAllowOrigin": "access-control-allow-origin",
"accessControlExposeHeaders": "access-control-expose-headers",
"contentCrc64": "x-ms-content-crc64",
"contentLength": 0,
"encryptionKeySha256": "x-ms-encryption-key-sha256",
"encryptionScope": "x-ms-encryption-scope",
"versionId": "Thu, 23 Jan 2025 17:53:23 GMT",
"keepAlive": "timeout=5",
"server": "Azurite-Blob/3.33.0"
}
}
]
}
}
@@ -0,0 +1,51 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"resource": "blob",
"operation": "delete",
"container": { "__rl": true, "mode": "id", "value": "mycontainer" },
"blob": { "__rl": true, "mode": "id", "value": "myblob" },
"options": { "leaseId": "leaseId123" },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [660, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"requestId": "75b87ee3-a7f7-468d-b7d1-e7e7b3173dab",
"version": "2025-01-05",
"date": "Thu, 23 Jan 2025 17:53:23 GMT",
"deleteTypePermanent": true,
"clientRequestId": "x-ms-client-request-id"
}
}
]
}
}
@@ -0,0 +1,115 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"resource": "blob",
"operation": "get",
"container": { "__rl": true, "value": "mycontainer", "mode": "list" },
"blob": { "__rl": true, "value": "myblob", "mode": "list" },
"options": {
"leaseId": "leaseId123",
"origin": "origin123",
"simplify": false,
"upn": true
},
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [660, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"binary": {
"data": {
"data": "ewoiZGF0YSI6ewoibXlfZmllbGRfMSI6InZhbHVlIiwKIm15X2ZpZWxkXzIiOjEKfQp9",
"fileExtension": "json",
"fileName": "file.json",
"fileSize": "51 B",
"fileType": "json",
"mimeType": "application/json"
}
},
"json": {
"name": "myblob",
"properties": {
"clientRequestId": "x-ms-client-request-id",
"lastModified": "last-modified",
"creationTime": "x-ms-creation-time",
"tagCount": "x-ms-tag-count",
"contentType": "application/json",
"contentRange": "content-range",
"etag": "\"0x22769D26D3F3740\"",
"contentMd5": "content-md5",
"contentCrc64": "x-ms-content-crc64",
"contentEncoding": "content-encoding",
"contentLanguage": "content-language",
"cacheControl": "cache-control",
"contentDisposition": "attachment; filename=\"file.json\"",
"blobSequenceNumber": "x-ms-blob-sequence-number",
"blobType": "x-ms-blob-type",
"copyCompletionTime": "x-ms-copy-completion-time",
"copyStatusDescription": "x-ms-copy-status-description",
"copyId": "x-ms-copy-id",
"copyProgress": "x-ms-copy-progress",
"copySource": "x-ms-copy-source",
"copyStatus": "x-ms-copy-status",
"incrementalCopy": "x-ms-incremental-copy",
"leaseDuration": "x-ms-lease-duration",
"leaseState": "x-ms-lease-state",
"leaseStatus": "x-ms-lease-status",
"accessControlAllowOrigin": "access-control-allow-origin",
"accessControlExposeHeaders": "access-control-expose-headers",
"vary": "vary",
"accessControlAllowCredentials": "access-control-allow-credentials",
"blobCommittedBlockCount": "x-ms-blob-committed-block-count",
"serverEncrypted": "x-ms-server-encrypted",
"encryptionKeySha256": "x-ms-encryption-key-sha256",
"encryptionContext": "x-ms-encryption-context",
"encryptionScope": "x-ms-encryption-scope",
"blobContentMd5": "x-ms-blob-content-md5",
"lastAccessTime": "x-ms-last-access-time",
"blobSealed": "x-ms-blob-sealed",
"immutabilityPolicyUntilDate": "x-ms-immutability-policy-until-date",
"immutabilityPolicyMode": "x-ms-immutability-policy-mode",
"legalHold": "x-ms-legal-hold",
"owner": "x-ms-owner",
"group": "x-ms-group",
"permissions": "x-ms-permissions",
"acl": "x-ms-acl",
"resourceType": "x-ms-resource-type",
"acceptRanges": "accept-ranges",
"date": "Thu, 23 Jan 2025 17:53:23 GMT",
"requestId": "75b87ee3-a7f7-468d-b7d1-e7e7b3173dab",
"version": "2025-01-05"
},
"metadata": { "key1": "value1" }
}
}
]
}
}
@@ -0,0 +1,82 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"resource": "blob",
"operation": "getAll",
"container": { "__rl": true, "value": "mycontainer", "mode": "list" },
"returnAll": true,
"options": { "simplify": false },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [660, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "myblob1",
"properties": {
"creationTime": "Wed, 22 Jan 2025 18:53:15 GMT",
"lastModified": "Wed, 22 Jan 2025 18:53:15 GMT",
"etag": "0x1F8268B228AA730",
"contentLength": 37,
"contentType": "application/json",
"contentMD5": "aWQGHD8kGQd5ZtEN/S1/aw==",
"blobType": "BlockBlob",
"leaseStatus": "unlocked",
"leaseState": "available",
"serverEncrypted": true,
"accessTier": "Hot",
"accessTierInferred": true,
"accessTierChangeTime": "Wed, 22 Jan 2025 18:53:15 GMT"
}
}
},
{
"json": {
"name": "myblob1",
"properties": {
"creationTime": "Wed, 22 Jan 2025 18:53:15 GMT",
"lastModified": "Wed, 22 Jan 2025 18:53:15 GMT",
"etag": "0x1F8268B228AA730",
"contentLength": 37,
"contentType": "application/json",
"contentMD5": "aWQGHD8kGQd5ZtEN/S1/aw==",
"blobType": "BlockBlob",
"leaseStatus": "unlocked",
"leaseState": "available",
"serverEncrypted": true,
"accessTier": "Hot",
"accessTierInferred": true,
"accessTierChangeTime": "Wed, 22 Jan 2025 18:53:15 GMT"
}
}
}
]
}
}
@@ -0,0 +1,76 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"resource": "blob",
"operation": "getAll",
"container": { "__rl": true, "value": "mycontainer", "mode": "list" },
"limit": 1,
"options": {
"fields": [
"copy",
"deleted",
"deletedwithversions",
"immutabilitypolicy",
"metadata",
"legalhold",
"versions",
"uncommittedblobs",
"tags",
"snapshots",
"permissions"
],
"filter": ["deleted", "files", "directories"],
"simplify": true,
"upn": true
},
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [660, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "myblob1",
"properties": {
"creationTime": "Wed, 22 Jan 2025 18:53:15 GMT",
"lastModified": "Wed, 22 Jan 2025 18:53:15 GMT",
"etag": "0x1F8268B228AA730",
"contentLength": 37,
"contentType": "application/json",
"contentMD5": "aWQGHD8kGQd5ZtEN/S1/aw==",
"blobType": "BlockBlob",
"leaseStatus": "unlocked",
"leaseState": "available",
"serverEncrypted": true
}
}
}
]
}
}
@@ -0,0 +1,61 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['blob_create.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'put',
path: '/mycontainer/myblob',
statusCode: 201,
requestHeaders: {
'x-ms-access-tier': 'Hot',
'x-ms-blob-type': 'BlockBlob',
'x-ms-blob-cache-control': 'no-cache',
'x-ms-content-crc64': '3EDB64E77CB16A4C',
'x-ms-blob-content-encoding': 'utf8',
'x-ms-blob-content-language': 'en-US',
'x-ms-blob-content-md5': 'b97f46db5f3be7709d942eefe30e5b45',
'x-ms-blob-content-type': 'application/json',
'x-ms-encryption-context': 'context',
'x-ms-encryption-scope': 'encryptionScope',
'x-ms-expiry-option': 'Absolute',
'x-ms-blob-content-disposition': 'attachment; filename="file.json"',
'x-ms-immutability-policy-until-date': 'Wed, 01 Jan 2025 00:00:00 -0500',
'x-ms-immutability-policy-mode': 'unlocked',
'x-ms-lease-id': 'leaseId123',
'x-ms-legal-hold': 'true',
'x-ms-meta-key1': 'value1',
},
responseBody: '',
responseHeaders: {
server: 'Azurite-Blob/3.33.0',
etag: '"0x22769D26D3F3740"',
'last-modified': 'Thu, 23 Jan 2025 17:53:23 GMT',
'content-md5': 'aWQGHD8kGQd5ZtEN/S1/aw==',
'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab',
'x-ms-version': '2025-01-05',
date: 'Thu, 23 Jan 2025 17:53:23 GMT',
'x-ms-request-server-encrypted': 'true',
'keep-alive': 'timeout=5',
'content-length': '0',
'x-ms-version-id': 'Thu, 23 Jan 2025 17:53:23 GMT',
'access-control-allow-credentials': 'access-control-allow-credentials',
'access-control-allow-origin': 'access-control-allow-origin',
'access-control-expose-headers': 'access-control-expose-headers',
'x-ms-content-crc64': 'x-ms-content-crc64',
'x-ms-encryption-key-sha256': 'x-ms-encryption-key-sha256',
'x-ms-encryption-scope': 'x-ms-encryption-scope',
},
},
],
},
});
});
@@ -0,0 +1,30 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['blob_delete.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'delete',
path: '/mycontainer/myblob',
statusCode: 202,
responseBody: '',
responseHeaders: {
'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab',
'x-ms-version': '2025-01-05',
date: 'Thu, 23 Jan 2025 17:53:23 GMT',
'x-ms-delete-type-permanent': 'true',
'x-ms-client-request-id': 'x-ms-client-request-id',
},
},
],
},
});
});
@@ -0,0 +1,82 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['blob_get.workflow.json'],
assertBinaryData: true,
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/mycontainer/myblob',
statusCode: 200,
responseBody: {
type: 'Buffer',
data: [
123, 10, 34, 100, 97, 116, 97, 34, 58, 123, 10, 34, 109, 121, 95, 102, 105, 101, 108,
100, 95, 49, 34, 58, 34, 118, 97, 108, 117, 101, 34, 44, 10, 34, 109, 121, 95, 102,
105, 101, 108, 100, 95, 50, 34, 58, 49, 10, 125, 10, 125,
],
},
responseHeaders: {
'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab',
'x-ms-version': '2025-01-05',
date: 'Thu, 23 Jan 2025 17:53:23 GMT',
'x-ms-client-request-id': 'x-ms-client-request-id',
'last-modified': 'last-modified',
'x-ms-creation-time': 'x-ms-creation-time',
'x-ms-tag-count': 'x-ms-tag-count',
'content-type': 'application/json',
'content-range': 'content-range',
etag: '"0x22769D26D3F3740"',
'content-md5': 'content-md5',
'x-ms-content-crc64': 'x-ms-content-crc64',
'content-encoding': 'content-encoding',
'content-language': 'content-language',
'cache-control': 'cache-control',
'content-disposition': 'attachment; filename="file.json"',
'x-ms-blob-sequence-number': 'x-ms-blob-sequence-number',
'x-ms-blob-type': 'x-ms-blob-type',
'x-ms-copy-completion-time': 'x-ms-copy-completion-time',
'x-ms-copy-status-description': 'x-ms-copy-status-description',
'x-ms-copy-id': 'x-ms-copy-id',
'x-ms-copy-progress': 'x-ms-copy-progress',
'x-ms-copy-source': 'x-ms-copy-source',
'x-ms-copy-status': 'x-ms-copy-status',
'x-ms-incremental-copy': 'x-ms-incremental-copy',
'x-ms-lease-duration': 'x-ms-lease-duration',
'x-ms-lease-state': 'x-ms-lease-state',
'x-ms-lease-status': 'x-ms-lease-status',
'accept-ranges': 'accept-ranges',
'access-control-allow-origin': 'access-control-allow-origin',
'access-control-expose-headers': 'access-control-expose-headers',
vary: 'vary',
'access-control-allow-credentials': 'access-control-allow-credentials',
'x-ms-blob-committed-block-count': 'x-ms-blob-committed-block-count',
'x-ms-server-encrypted': 'x-ms-server-encrypted',
'x-ms-encryption-key-sha256': 'x-ms-encryption-key-sha256',
'x-ms-encryption-context': 'x-ms-encryption-context',
'x-ms-encryption-scope': 'x-ms-encryption-scope',
'x-ms-blob-content-md5': 'x-ms-blob-content-md5',
'x-ms-last-access-time': 'x-ms-last-access-time',
'x-ms-blob-sealed': 'x-ms-blob-sealed',
'x-ms-immutability-policy-until-date': 'x-ms-immutability-policy-until-date',
'x-ms-immutability-policy-mode': 'x-ms-immutability-policy-mode',
'x-ms-legal-hold': 'x-ms-legal-hold',
'x-ms-owner': 'x-ms-owner',
'x-ms-group': 'x-ms-group',
'x-ms-permissions': 'x-ms-permissions',
'x-ms-acl': 'x-ms-acl',
'x-ms-resource-type': 'x-ms-resource-type',
'x-ms-meta-key1': 'value1',
},
},
],
},
});
});
@@ -0,0 +1,28 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['blob_getAll.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/mycontainer?restype=container&comp=list',
statusCode: 200,
responseBody: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><EnumerationResults ServiceEndpoint="${baseUrl}" ContainerName="item1"><Prefix/><Marker/><MaxResults>1</MaxResults><Blobs><Blob><Name>myblob1</Name><Properties><Creation-Time>Wed, 22 Jan 2025 18:53:15 GMT</Creation-Time><Last-Modified>Wed, 22 Jan 2025 18:53:15 GMT</Last-Modified><Etag>0x1F8268B228AA730</Etag><Content-Length>37</Content-Length><Content-Type>application/json</Content-Type><Content-MD5>aWQGHD8kGQd5ZtEN/S1/aw==</Content-MD5><BlobType>BlockBlob</BlobType><LeaseStatus>unlocked</LeaseStatus><LeaseState>available</LeaseState><ServerEncrypted>true</ServerEncrypted><AccessTier>Hot</AccessTier><AccessTierInferred>true</AccessTierInferred><AccessTierChangeTime>Wed, 22 Jan 2025 18:53:15 GMT</AccessTierChangeTime></Properties></Blob></Blobs><NextMarker>myblob2</NextMarker></EnumerationResults>`,
},
{
method: 'get',
path: '/mycontainer?restype=container&comp=list&marker=myblob2',
statusCode: 200,
responseBody: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><EnumerationResults ServiceEndpoint="${baseUrl}" ContainerName="item1"><Prefix/><Marker/><MaxResults>1</MaxResults><Blobs><Blob><Name>myblob1</Name><Properties><Creation-Time>Wed, 22 Jan 2025 18:53:15 GMT</Creation-Time><Last-Modified>Wed, 22 Jan 2025 18:53:15 GMT</Last-Modified><Etag>0x1F8268B228AA730</Etag><Content-Length>37</Content-Length><Content-Type>application/json</Content-Type><Content-MD5>aWQGHD8kGQd5ZtEN/S1/aw==</Content-MD5><BlobType>BlockBlob</BlobType><LeaseStatus>unlocked</LeaseStatus><LeaseState>available</LeaseState><ServerEncrypted>true</ServerEncrypted><AccessTier>Hot</AccessTier><AccessTierInferred>true</AccessTierInferred><AccessTierChangeTime>Wed, 22 Jan 2025 18:53:15 GMT</AccessTierChangeTime></Properties></Blob></Blobs><NextMarker></NextMarker></EnumerationResults>`,
},
],
},
});
});
@@ -0,0 +1,22 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['blob_getAllLimitOptions.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/mycontainer?restype=container&comp=list&maxresults=1&include=copy%2Cdeleted%2Cdeletedwithversions%2Cimmutabilitypolicy%2Cmetadata%2Clegalhold%2Cversions%2Cuncommittedblobs%2Ctags%2Csnapshots%2Cpermissions&showonly=deleted%2Cfiles%2Cdirectories',
statusCode: 200,
responseBody: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><EnumerationResults ServiceEndpoint="${baseUrl}" ContainerName="item1"><Prefix/><Marker/><MaxResults>1</MaxResults><Blobs><Blob><Name>myblob1</Name><Properties><Creation-Time>Wed, 22 Jan 2025 18:53:15 GMT</Creation-Time><Last-Modified>Wed, 22 Jan 2025 18:53:15 GMT</Last-Modified><Etag>0x1F8268B228AA730</Etag><Content-Length>37</Content-Length><Content-Type>application/json</Content-Type><Content-MD5>aWQGHD8kGQd5ZtEN/S1/aw==</Content-MD5><BlobType>BlockBlob</BlobType><LeaseStatus>unlocked</LeaseStatus><LeaseState>available</LeaseState><ServerEncrypted>true</ServerEncrypted><AccessTier>Hot</AccessTier><AccessTierInferred>true</AccessTierInferred><AccessTierChangeTime>Wed, 22 Jan 2025 18:53:15 GMT</AccessTierChangeTime></Properties></Blob></Blobs><NextMarker>myblob2</NextMarker></EnumerationResults>`,
},
],
},
});
});
@@ -0,0 +1,54 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"operation": "create",
"containerCreate": "mycontainer",
"options": {
"accessLevel": "blob",
"metadata": { "metadataValues": [{ "fieldName": "key1", "fieldValue": "value1" }] }
},
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"etag": "\"0x22769D26D3F3740\"",
"lastModified": "Thu, 23 Jan 2025 17:53:23 GMT",
"requestId": "75b87ee3-a7f7-468d-b7d1-e7e7b3173dab",
"version": "2025-01-05",
"date": "Thu, 23 Jan 2025 17:53:23 GMT",
"clientRequestId": "client-request-id-123",
"requestServerEncrypted": true
}
}
]
}
}
@@ -0,0 +1,48 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"operation": "delete",
"container": { "__rl": true, "mode": "list", "value": "mycontainer" },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"contentLength": 0,
"requestId": "ca3a8907-601e-0050-1929-723410000000",
"server": "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"version": "2020-10-02",
"date": "Wed, 29 Jan 2025 08:38:21 GMT"
}
}
]
}
}
@@ -0,0 +1,61 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"operation": "get",
"container": { "__rl": true, "mode": "list", "value": "mycontainer" },
"options": { "simplify": false },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "mycontainer",
"properties": {
"lastModified": "Tue, 28 Jan 2025 16:40:21 GMT",
"etag": "\"0x8DD3FBA74CF3620\"",
"leaseStatus": "unlocked",
"leaseState": "available",
"hasImmutabilityPolicy": false,
"hasLegalHold": false,
"leaseDuration": "infinite",
"blobPublicAccess": "blob",
"contentLength": 0,
"date": "Wed, 29 Jan 2025 08:43:08 GMT",
"requestId": "49edb268-b01e-0053-6e29-72d574000000",
"server": "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"version": "2020-10-02"
},
"metadata": { "key1": "field1" }
}
}
]
}
}
@@ -0,0 +1,73 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": { "operation": "getAll", "returnAll": true, "requestOptions": {} },
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "mycontainer1",
"deleted": true,
"version": "01DB7228F6BEE6E7",
"properties": {
"lastModified": "Wed, 29 Jan 2025 08:37:00 GMT",
"etag": "\"0x8DD40401935032C\"",
"leaseStatus": "unlocked",
"leaseState": "expired",
"hasImmutabilityPolicy": false,
"hasLegalHold": false,
"immutableStorageWithVersioningEnabled": "false",
"deletedTime": "Wed, 29 Jan 2025 08:38:21 GMT",
"remainingRetentionDays": 7
},
"metadata": { "key1": "value1" }
}
},
{
"json": {
"name": "mycontainer1",
"deleted": true,
"version": "01DB7228F6BEE6E7",
"properties": {
"lastModified": "Wed, 29 Jan 2025 08:37:00 GMT",
"etag": "\"0x8DD40401935032C\"",
"leaseStatus": "unlocked",
"leaseState": "expired",
"hasImmutabilityPolicy": false,
"hasLegalHold": false,
"immutableStorageWithVersioningEnabled": "false",
"deletedTime": "Wed, 29 Jan 2025 08:38:21 GMT",
"remainingRetentionDays": 7
},
"metadata": { "key1": "value1" }
}
}
]
}
}
@@ -0,0 +1,59 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "99f866fa-f63c-477d-a0d0-48fbdb8a344a",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"operation": "getAll",
"limit": 1,
"options": { "fields": ["metadata", "deleted", "system"], "filter": "mycontainer" },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "ab1b6258-5c75-4893-90bf-ef591264420c",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "mycontainer1",
"deleted": true,
"version": "01DB7228F6BEE6E7",
"properties": {
"lastModified": "Wed, 29 Jan 2025 08:37:00 GMT",
"etag": "\"0x8DD40401935032C\"",
"leaseStatus": "unlocked",
"leaseState": "expired",
"hasImmutabilityPolicy": false,
"hasLegalHold": false,
"immutableStorageWithVersioningEnabled": "false",
"deletedTime": "Wed, 29 Jan 2025 08:38:21 GMT",
"remainingRetentionDays": 7
},
"metadata": { "key1": "value1" }
}
}
]
}
}
@@ -0,0 +1,32 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['container_create.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'put',
path: '/mycontainer?restype=container',
statusCode: 201,
requestHeaders: { 'x-ms-blob-public-access': 'blob', 'x-ms-meta-key1': 'value1' },
responseBody: '',
responseHeaders: {
etag: '"0x22769D26D3F3740"',
'last-modified': 'Thu, 23 Jan 2025 17:53:23 GMT',
'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab',
'x-ms-version': '2025-01-05',
date: 'Thu, 23 Jan 2025 17:53:23 GMT',
'x-ms-request-server-encrypted': 'true',
'x-ms-client-request-id': 'client-request-id-123',
},
},
],
},
});
});
@@ -0,0 +1,29 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['container_delete.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'delete',
path: '/mycontainer?restype=container',
statusCode: 202,
responseBody: '',
responseHeaders: {
'content-length': '0',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-request-id': 'ca3a8907-601e-0050-1929-723410000000',
'x-ms-version': '2020-10-02',
date: 'Wed, 29 Jan 2025 08:38:21 GMT',
},
},
],
},
});
});
@@ -0,0 +1,38 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['container_get.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/mycontainer?restype=container',
statusCode: 200,
responseBody: '',
responseHeaders: {
'content-length': '0',
'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT',
etag: '"0x8DD3FBA74CF3620"',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000',
'x-ms-version': '2020-10-02',
'x-ms-lease-status': 'unlocked',
'x-ms-lease-state': 'available',
'x-ms-has-immutability-policy': 'false',
'x-ms-has-legal-hold': 'false',
date: 'Wed, 29 Jan 2025 08:43:08 GMT',
'x-ms-meta-key1': 'field1',
'x-ms-blob-public-access': 'blob',
'x-ms-lease-duration': 'infinite',
},
},
],
},
});
});
@@ -0,0 +1,28 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['container_getAll.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/?comp=list',
statusCode: 200,
responseBody: `<?xml version="1.0" encoding="utf-8"?><EnumerationResults ServiceEndpoint="${baseUrl}/"><Prefix>mycontainer</Prefix><MaxResults>1</MaxResults><Containers><Container><Name>mycontainer1</Name><Deleted>true</Deleted><Version>01DB7228F6BEE6E7</Version><Properties><Last-Modified>Wed, 29 Jan 2025 08:37:00 GMT</Last-Modified><Etag>"0x8DD40401935032C"</Etag><LeaseStatus>unlocked</LeaseStatus><LeaseState>expired</LeaseState><HasImmutabilityPolicy>false</HasImmutabilityPolicy><HasLegalHold>false</HasLegalHold><ImmutableStorageWithVersioningEnabled>false</ImmutableStorageWithVersioningEnabled><DeletedTime>Wed, 29 Jan 2025 08:38:21 GMT</DeletedTime><RemainingRetentionDays>7</RemainingRetentionDays></Properties><Metadata><key1>value1</key1></Metadata></Container></Containers><NextMarker>mycontainer2</NextMarker></EnumerationResults>`,
},
{
method: 'get',
path: '/?comp=list&marker=mycontainer2',
statusCode: 200,
responseBody: `<?xml version="1.0" encoding="utf-8"?><EnumerationResults ServiceEndpoint="${baseUrl}/"><Prefix>mycontainer</Prefix><MaxResults>1</MaxResults><Containers><Container><Name>mycontainer1</Name><Deleted>true</Deleted><Version>01DB7228F6BEE6E7</Version><Properties><Last-Modified>Wed, 29 Jan 2025 08:37:00 GMT</Last-Modified><Etag>"0x8DD40401935032C"</Etag><LeaseStatus>unlocked</LeaseStatus><LeaseState>expired</LeaseState><HasImmutabilityPolicy>false</HasImmutabilityPolicy><HasLegalHold>false</HasLegalHold><ImmutableStorageWithVersioningEnabled>false</ImmutableStorageWithVersioningEnabled><DeletedTime>Wed, 29 Jan 2025 08:38:21 GMT</DeletedTime><RemainingRetentionDays>7</RemainingRetentionDays></Properties><Metadata><key1>value1</key1></Metadata></Container></Containers><NextMarker></NextMarker></EnumerationResults>`,
},
],
},
});
});
@@ -0,0 +1,22 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['container_getAllLimitOptions.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/?comp=list&maxresults=1&include=metadata%2Cdeleted%2Csystem&prefix=mycontainer',
statusCode: 200,
responseBody: `<?xml version="1.0" encoding="utf-8"?><EnumerationResults ServiceEndpoint="${baseUrl}/"><Prefix>mycontainer</Prefix><MaxResults>1</MaxResults><Containers><Container><Name>mycontainer1</Name><Deleted>true</Deleted><Version>01DB7228F6BEE6E7</Version><Properties><Last-Modified>Wed, 29 Jan 2025 08:37:00 GMT</Last-Modified><Etag>"0x8DD40401935032C"</Etag><LeaseStatus>unlocked</LeaseStatus><LeaseState>expired</LeaseState><HasImmutabilityPolicy>false</HasImmutabilityPolicy><HasLegalHold>false</HasLegalHold><ImmutableStorageWithVersioningEnabled>false</ImmutableStorageWithVersioningEnabled><DeletedTime>Wed, 29 Jan 2025 08:38:21 GMT</DeletedTime><RemainingRetentionDays>7</RemainingRetentionDays></Properties><Metadata><key1>value1</key1></Metadata></Container></Containers><NextMarker>mycontainer2</NextMarker></EnumerationResults>`,
},
],
},
});
});
@@ -0,0 +1,29 @@
export const credentials = {
azureStorageOAuth2Api: {
grantType: 'authorizationCode',
authUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
accessTokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
clientId: 'CLIENTID',
clientSecret: 'CLIENTSECRET',
scope: 'https://storage.azure.com/user_impersonation',
authQueryParameters: 'response_mode=query',
authentication: 'body',
oauthTokenData: {
token_type: 'Bearer',
scope: 'https://storage.azure.com/user_impersonation',
expires_in: 4730,
ext_expires_in: 4730,
access_token: 'ACCESSTOKEN',
callbackQueryString: {
session_state: 'SESSIONSTATE',
},
},
account: 'myaccount',
baseUrl: 'https://myaccount.blob.core.windows.net',
},
azureStorageSharedKeyApi: {
account: 'devstoreaccount1',
key: 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==',
baseUrl: 'https://myaccount.blob.core.windows.net',
},
};
@@ -0,0 +1,65 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "1307e408-a8a5-464e-b858-494953e2f43b",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"authentication": "oAuth2",
"resource": "container",
"operation": "get",
"container": { "__rl": true, "value": "mycontainer", "mode": "id" },
"options": { "simplify": false },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "3429f7f2-dfca-4b72-8913-43a582e96e66",
"name": "Azure Storage",
"credentials": {
"azureStorageOAuth2Api": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage OAuth2 account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "mycontainer",
"properties": {
"lastModified": "Tue, 28 Jan 2025 16:40:21 GMT",
"etag": "\"0x8DD3FBA74CF3620\"",
"leaseStatus": "unlocked",
"leaseState": "available",
"hasImmutabilityPolicy": false,
"hasLegalHold": false,
"leaseDuration": "infinite",
"blobPublicAccess": "blob",
"contentLength": 0,
"date": "Wed, 29 Jan 2025 08:43:08 GMT",
"requestId": "49edb268-b01e-0053-6e29-72d574000000",
"server": "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"version": "2020-10-02"
},
"metadata": {
"key1": "field1"
}
}
}
]
}
}
@@ -0,0 +1,62 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "1307e408-a8a5-464e-b858-494953e2f43b",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"resource": "container",
"operation": "get",
"container": { "__rl": true, "value": "mycontainer", "mode": "id" },
"options": { "simplify": false },
"requestOptions": {}
},
"type": "n8n-nodes-base.azureStorage",
"typeVersion": 1,
"position": [220, 0],
"id": "3429f7f2-dfca-4b72-8913-43a582e96e66",
"name": "Azure Storage",
"credentials": {
"azureStorageSharedKeyApi": {
"id": "VPmcFM58eDDexWQL",
"name": "Azure Storage Shared Key account"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [[{ "node": "Azure Storage", "type": "main", "index": 0 }]]
}
},
"pinData": {
"Azure Storage": [
{
"json": {
"name": "mycontainer",
"properties": {
"lastModified": "Tue, 28 Jan 2025 16:40:21 GMT",
"etag": "\"0x8DD3FBA74CF3620\"",
"leaseStatus": "unlocked",
"leaseState": "available",
"hasImmutabilityPolicy": false,
"hasLegalHold": false,
"leaseDuration": "infinite",
"blobPublicAccess": "blob",
"contentLength": 0,
"date": "Wed, 29 Jan 2025 08:43:08 GMT",
"requestId": "49edb268-b01e-0053-6e29-72d574000000",
"server": "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"version": "2020-10-02"
},
"metadata": { "key1": "field1" }
}
}
]
}
}
@@ -0,0 +1,38 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['credentials_oauth2.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/mycontainer?restype=container',
statusCode: 200,
responseBody: '',
responseHeaders: {
'content-length': '0',
'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT',
etag: '"0x8DD3FBA74CF3620"',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000',
'x-ms-version': '2020-10-02',
'x-ms-lease-status': 'unlocked',
'x-ms-lease-state': 'available',
'x-ms-has-immutability-policy': 'false',
'x-ms-has-legal-hold': 'false',
date: 'Wed, 29 Jan 2025 08:43:08 GMT',
'x-ms-meta-key1': 'field1',
'x-ms-blob-public-access': 'blob',
'x-ms-lease-duration': 'infinite',
},
},
],
},
});
});
@@ -0,0 +1,110 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import type { ICredentialDataDecryptedObject, IHttpRequestOptions } from 'n8n-workflow';
import { AzureStorageSharedKeyApi } from '@credentials/AzureStorageSharedKeyApi.credentials';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { account, baseUrl, key } = credentials.azureStorageSharedKeyApi;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['credentials_sharedKey.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/mycontainer?restype=container',
statusCode: 200,
responseBody: '',
responseHeaders: {
'content-length': '0',
'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT',
etag: '"0x8DD3FBA74CF3620"',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000',
'x-ms-version': '2020-10-02',
'x-ms-lease-status': 'unlocked',
'x-ms-lease-state': 'available',
'x-ms-has-immutability-policy': 'false',
'x-ms-has-legal-hold': 'false',
date: 'Wed, 29 Jan 2025 08:43:08 GMT',
'x-ms-meta-key1': 'field1',
'x-ms-blob-public-access': 'blob',
'x-ms-lease-duration': 'infinite',
},
},
],
},
});
describe('authenticate', () => {
const azureStorageSharedKeyApi = new AzureStorageSharedKeyApi();
it('should remove undefined query parameters and headers', async () => {
const authCredentials: ICredentialDataDecryptedObject = {
account,
key,
};
const requestOptions: IHttpRequestOptions = {
url: `${baseUrl}/mycontainer`,
qs: { restype: 'container', query1: undefined },
headers: {
'Content-Length': undefined,
},
method: 'GET',
};
const result = await azureStorageSharedKeyApi.authenticate(authCredentials, requestOptions);
expect(result.qs).toEqual({ restype: 'container' });
expect(result.headers).not.toHaveProperty('Content-Length');
});
it('should default method to GET if not provided', async () => {
const authCredentials: ICredentialDataDecryptedObject = {
account,
key,
};
const requestOptions: IHttpRequestOptions = {
url: `${baseUrl}/mycontainer`,
qs: { restype: 'container' },
headers: {
'Content-Length': undefined,
},
};
const result = await azureStorageSharedKeyApi.authenticate(authCredentials, requestOptions);
expect(result.method).toBe('GET');
});
it('should generate a valid authorization header', async () => {
const authCredentials: ICredentialDataDecryptedObject = {
account,
key,
};
const requestOptions: IHttpRequestOptions = {
url: `${baseUrl}/mycontainer/myblob`,
qs: { param1: 'value1' },
headers: {
'x-ms-date': 'Thu, 27 Feb 2025 11:05:49 GMT',
'x-ms-version': '2021-12-02',
'x-ms-blob-content-language': 'en-EN',
'x-ms-blob-content-type': 'image/jpeg',
'x-ms-expiry-option': 'Absolute',
'x-ms-blob-type': 'BlockBlob',
'x-ms-blob-content-disposition': 'attachment; filename="image.jpg"',
'x-ms-meta-key1': 'value1',
'x-ms-tags': 'tag1=value1',
},
method: 'PUT',
};
const result = await azureStorageSharedKeyApi.authenticate(authCredentials, requestOptions);
expect(result.headers?.authorization).toBe(
'SharedKey devstoreaccount1:6sSQ3N4yNFQynBs/iLptIRPS5DQeaFBocW+dyYbAdOI=',
);
});
});
});
@@ -0,0 +1,115 @@
import type { ILoadOptionsFunctions, INodeParameterResourceLocator } from 'n8n-workflow';
import { AzureStorage } from '../../AzureStorage.node';
import { XMsVersion } from '../../GenericFunctions';
import { credentials } from '../credentials';
describe('Azure Storage Node', () => {
const { baseUrl } = credentials.azureStorageOAuth2Api;
describe('List search', () => {
it('should list search blobs', async () => {
const mockResponse = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><EnumerationResults ServiceEndpoint="${baseUrl}" ContainerName="item1"><Prefix/><Marker/><MaxResults>1</MaxResults><Blobs><Blob><Name>myblob1</Name><Properties><Creation-Time>Wed, 22 Jan 2025 18:53:15 GMT</Creation-Time><Last-Modified>Wed, 22 Jan 2025 18:53:15 GMT</Last-Modified><Etag>0x1F8268B228AA730</Etag><Content-Length>37</Content-Length><Content-Type>application/json</Content-Type><Content-MD5>aWQGHD8kGQd5ZtEN/S1/aw==</Content-MD5><BlobType>BlockBlob</BlobType><LeaseStatus>unlocked</LeaseStatus><LeaseState>available</LeaseState><ServerEncrypted>true</ServerEncrypted><AccessTier>Hot</AccessTier><AccessTierInferred>true</AccessTierInferred><AccessTierChangeTime>Wed, 22 Jan 2025 18:53:15 GMT</AccessTierChangeTime></Properties></Blob></Blobs><NextMarker>myblob2</NextMarker></EnumerationResults>`;
const mockRequestWithAuthentication = jest.fn().mockReturnValue(mockResponse);
const mockGetNodeParameter = jest.fn((parameterName, _fallbackValue, _options) => {
if (parameterName === 'authentication') {
return 'sharedKey';
}
if (parameterName === 'container') {
return {
value: 'mycontainer',
} as INodeParameterResourceLocator;
}
throw new Error('Unknown parameter');
});
const mockGetCredentials = jest.fn(async (type: string, _itemIndex?: number) => {
if (type === 'azureStorageSharedKeyApi') {
return credentials.azureStorageSharedKeyApi;
}
throw new Error('Unknown credentials');
});
const mockContext = {
getCredentials: mockGetCredentials,
getNodeParameter: mockGetNodeParameter,
helpers: {
requestWithAuthentication: mockRequestWithAuthentication,
},
} as unknown as ILoadOptionsFunctions;
jest.useFakeTimers().setSystemTime(new Date('2025-01-01T00:00:00Z'));
const node = new AzureStorage();
const listSearchResult = await node.methods.listSearch.getBlobs.call(mockContext);
expect(mockRequestWithAuthentication).toHaveBeenCalledWith('azureStorageSharedKeyApi', {
method: 'GET',
url: `${baseUrl}/mycontainer`,
headers: {
'x-ms-date': 'Wed, 01 Jan 2025 00:00:00 GMT',
'x-ms-version': XMsVersion,
},
qs: {
comp: 'list',
maxresults: 5000,
restype: 'container',
},
body: {},
});
expect(listSearchResult).toEqual({
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
results: [{ name: 'myblob1', value: 'myblob1' }],
paginationToken: 'myblob2',
});
});
it('should list search containers', async () => {
const mockResponse = `<?xml version="1.0" encoding="utf-8"?><EnumerationResults ServiceEndpoint="${baseUrl}/"><Prefix>mycontainer</Prefix><MaxResults>1</MaxResults><Containers><Container><Name>mycontainer1</Name><Deleted>true</Deleted><Version>01DB7228F6BEE6E7</Version><Properties><Last-Modified>Wed, 29 Jan 2025 08:37:00 GMT</Last-Modified><Etag>"0x8DD40401935032C"</Etag><LeaseStatus>unlocked</LeaseStatus><LeaseState>expired</LeaseState><HasImmutabilityPolicy>false</HasImmutabilityPolicy><HasLegalHold>false</HasLegalHold><ImmutableStorageWithVersioningEnabled>false</ImmutableStorageWithVersioningEnabled><DeletedTime>Wed, 29 Jan 2025 08:38:21 GMT</DeletedTime><RemainingRetentionDays>7</RemainingRetentionDays></Properties><Metadata><key1>value1</key1></Metadata></Container></Containers><NextMarker>mycontainer2</NextMarker></EnumerationResults>`;
const mockRequestWithAuthentication = jest.fn().mockReturnValue(mockResponse);
const mockGetNodeParameter = jest.fn((parameterName, _fallbackValue, _options) => {
if (parameterName === 'authentication') {
return 'sharedKey';
}
throw new Error('Unknown parameter');
});
const mockGetCredentials = jest.fn(async (type: string, _itemIndex?: number) => {
if (type === 'azureStorageSharedKeyApi') {
return credentials.azureStorageSharedKeyApi;
}
throw new Error('Unknown credentials');
});
const mockContext = {
getCredentials: mockGetCredentials,
getNodeParameter: mockGetNodeParameter,
helpers: {
requestWithAuthentication: mockRequestWithAuthentication,
},
} as unknown as ILoadOptionsFunctions;
jest.useFakeTimers().setSystemTime(new Date('2025-01-01T00:00:00Z'));
const node = new AzureStorage();
const listSearchResult = await node.methods.listSearch.getContainers.call(mockContext);
expect(mockRequestWithAuthentication).toHaveBeenCalledWith('azureStorageSharedKeyApi', {
method: 'GET',
url: `${baseUrl}/`,
headers: {
'x-ms-date': 'Wed, 01 Jan 2025 00:00:00 GMT',
'x-ms-version': XMsVersion,
},
qs: {
comp: 'list',
maxresults: 5000,
},
body: {},
});
expect(listSearchResult).toEqual({
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
results: [{ name: 'mycontainer1', value: 'mycontainer1' }],
paginationToken: 'mycontainer2',
});
});
});
});