Worked on requests

This commit is contained in:
Adina Totorean 2025-02-03 19:12:37 +02:00
parent 0a57678acc
commit e488e6c0bb
5 changed files with 68 additions and 25 deletions

View file

@ -55,8 +55,7 @@ export class MicrosoftCosmosDbSharedKeyApi implements ICredentialType {
credentials: ICredentialDataDecryptedObject, credentials: ICredentialDataDecryptedObject,
requestOptions: IHttpRequestOptions, requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> { ): Promise<IHttpRequestOptions> {
console.log('Authenticate invoked with requestOptions:', requestOptions); // Remove undefined query parameters?
if (requestOptions.qs) { if (requestOptions.qs) {
for (const [key, value] of Object.entries(requestOptions.qs)) { for (const [key, value] of Object.entries(requestOptions.qs)) {
if (value === undefined) { if (value === undefined) {
@ -65,38 +64,54 @@ export class MicrosoftCosmosDbSharedKeyApi implements ICredentialType {
} }
} }
// Add headers for date and version
requestOptions.headers ??= {}; requestOptions.headers ??= {};
const date = new Date().toUTCString(); const date = new Date().toUTCString().toLowerCase();
requestOptions.headers = { requestOptions.headers = {
...requestOptions.headers, ...requestOptions.headers,
'x-ms-date': date, 'x-ms-date': date,
'x-ms-version': '2018-12-31', 'x-ms-version': '2018-12-31',
'x-ms-partitionkey': '[]',
}; };
if (credentials.sessionToken) { if (credentials.sessionToken) {
requestOptions.headers['x-ms-session-token'] = credentials.sessionToken; requestOptions.headers['x-ms-session-token'] = credentials.sessionToken;
} }
let resourceType = ''; // This shouldn't be the full url
const resourceLink = '/dbs/first_database_1' + requestOptions.url; // Refer to https://stackoverflow.com/questions/45645389/documentdb-rest-api-authorization-token-error
console.log('Link', resourceLink); const url = new URL(requestOptions.baseURL + requestOptions.url);
if (resourceLink.includes('/colls')) { const pathSegments = url.pathname.split('/').filter((segment) => segment);
resourceType = 'colls'; console.log('Filtered Path Segments:', pathSegments);
} else if (resourceLink.includes('/docs')) {
let resourceType = '';
let resourceId = '';
if (pathSegments.includes('docs')) {
const docsIndex = pathSegments.lastIndexOf('docs');
resourceType = 'docs'; resourceType = 'docs';
} else if (resourceLink.includes('/dbs')) { resourceId = pathSegments.slice(0, docsIndex).join('/');
} else if (pathSegments.includes('colls')) {
const collsIndex = pathSegments.lastIndexOf('colls');
resourceType = 'colls';
resourceId = pathSegments.slice(0, collsIndex).join('/');
} else if (pathSegments.includes('dbs')) {
const dbsIndex = pathSegments.lastIndexOf('dbs');
resourceType = 'dbs'; resourceType = 'dbs';
resourceId = pathSegments.slice(0, dbsIndex + 2).join('/');
} else { } else {
throw new ApplicationError('Unable to determine resourceType'); throw new ApplicationError('Unable to determine resourceType and resourceId from the URL.');
} }
console.log('Type', resourceType);
console.log('resourceId', resourceId);
console.log('resourceType', resourceType);
if (requestOptions.method) { if (requestOptions.method) {
const authToken = getAuthorizationTokenUsingMasterKey( const authToken = getAuthorizationTokenUsingMasterKey(
requestOptions.method, requestOptions.method,
resourceType, resourceType,
resourceLink, resourceId,
date, date,
credentials.key as string, credentials.key as string,
); );

View file

@ -3,9 +3,9 @@ import { NodeConnectionType } from 'n8n-workflow';
import { containerFields, containerOperations } from './descriptions/ContainerDescription'; import { containerFields, containerOperations } from './descriptions/ContainerDescription';
import { itemFields, itemOperations } from './descriptions/ItemDescription'; import { itemFields, itemOperations } from './descriptions/ItemDescription';
import { searchCollections } from './GenericFunctions'; import { presendStringifyBody, searchCollections } from './GenericFunctions';
export class AzureCosmosDb implements INodeType { export class CosmosDb implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
displayName: 'Cosmos DB', displayName: 'Cosmos DB',
name: 'cosmosDb', name: 'cosmosDb',
@ -58,6 +58,11 @@ export class AzureCosmosDb implements INodeType {
name: 'resource', name: 'resource',
type: 'options', type: 'options',
noDataExpression: true, noDataExpression: true,
routing: {
send: {
preSend: [presendStringifyBody],
},
},
options: [ options: [
{ {
name: 'Container', name: 'Container',

View file

@ -3,6 +3,7 @@ import type {
DeclarativeRestApiSettings, DeclarativeRestApiSettings,
IDataObject, IDataObject,
IExecutePaginationFunctions, IExecutePaginationFunctions,
IExecuteSingleFunctions,
IHttpRequestOptions, IHttpRequestOptions,
ILoadOptionsFunctions, ILoadOptionsFunctions,
INodeExecutionData, INodeExecutionData,
@ -43,7 +44,7 @@ export const HeaderConstants = {
export function getAuthorizationTokenUsingMasterKey( export function getAuthorizationTokenUsingMasterKey(
verb: string, verb: string,
resourceType: string, resourceType: string,
resourceLink: string, resourceId: string,
date: string, date: string,
masterKey: string, masterKey: string,
): string { ): string {
@ -51,14 +52,24 @@ export function getAuthorizationTokenUsingMasterKey(
const payload = const payload =
`${verb.toLowerCase()}\n` + `${verb.toLowerCase()}\n` +
`${resourceType.toLowerCase()}\n` + `${resourceType.toLowerCase()}\n` +
`${resourceLink}\n` + `${resourceId}\n` +
`${date}\n` + `${date.toLowerCase()}\n` +
'\n'; '\n';
const hmacSha256 = crypto.createHmac('sha256', key); const hmacSha256 = crypto.createHmac('sha256', key);
const hashPayload = hmacSha256.update(payload, 'utf8').digest('base64'); const signature = hmacSha256.update(payload, 'utf8').digest('base64');
return encodeURIComponent('type=master&ver=1.0&sig=' + hashPayload); return `type=master&ver=1.0&sig=${signature}`;
}
export async function presendStringifyBody(
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
if (requestOptions.body) {
requestOptions.body = JSON.stringify(requestOptions.body);
}
return requestOptions;
} }
export async function handlePagination( export async function handlePagination(
@ -207,10 +218,12 @@ export async function searchCollections(
} }
const results: INodeListSearchItems[] = collections const results: INodeListSearchItems[] = collections
.map((collection) => ({ .map((collection) => {
name: String(collection.id), return {
value: String(collection.id), name: String(collection.id),
})) value: String(collection.id),
};
})
.filter((collection) => !filter || collection.name.includes(filter)) .filter((collection) => !filter || collection.name.includes(filter))
.sort((a, b) => a.name.localeCompare(b.name)); .sort((a, b) => a.name.localeCompare(b.name));

View file

@ -21,6 +21,9 @@ export const containerOperations: INodeProperties[] = [
ignoreHttpStatusErrors: true, ignoreHttpStatusErrors: true,
method: 'POST', method: 'POST',
url: '/colls', url: '/colls',
headers: {
headers: {},
},
}, },
}, },
action: 'Create container', action: 'Create container',

View file

@ -23,6 +23,9 @@ export const itemOperations: INodeProperties[] = [
ignoreHttpStatusErrors: true, ignoreHttpStatusErrors: true,
method: 'POST', method: 'POST',
url: '=/colls/{{ $parameter["collId"] }}/docs', url: '=/colls/{{ $parameter["collId"] }}/docs',
headers: {
// 'x-ms-documentdb-partitionkey': '={{$parameter["partitionKey"]}}',
},
}, },
}, },
action: 'Create item', action: 'Create item',
@ -108,6 +111,9 @@ export const itemOperations: INodeProperties[] = [
ignoreHttpStatusErrors: true, ignoreHttpStatusErrors: true,
method: 'PATCH', method: 'PATCH',
url: '=/colls/{{ $parameter["collId"] }}/docs/{{ $parameter["id"] }}', url: '=/colls/{{ $parameter["collId"] }}/docs/{{ $parameter["id"] }}',
headers: {
'Content-Type': 'application/json-patch+json',
},
}, },
}, },
action: 'Update item', action: 'Update item',
@ -198,10 +204,11 @@ export const createFields: INodeProperties[] = [
operation: ['create'], operation: ['create'],
}, },
}, },
//To-Do-add preSend function
routing: { routing: {
send: { send: {
type: 'body', type: 'body',
value: '={{ $json["id"] ? Object.assign({ id: $json["id"] }, $value) : $value }}', value: '={{$value}}',
}, },
}, },
}, },