From 511741ed356b365f52e0335ce6a1fc953ccbc465 Mon Sep 17 00:00:00 2001 From: Sandeep Digumarty Date: Wed, 27 Dec 2023 01:54:36 +0530 Subject: [PATCH 1/9] fix: send empty string instead of null when the schema data is undefined (#2955) --- .../destinations/fb_custom_audience/util.js | 10 +++++----- .../fb_custom_audience/processor/data.ts | 6 +++--- .../fb_custom_audience/router/data.ts | 20 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/v0/destinations/fb_custom_audience/util.js b/src/v0/destinations/fb_custom_audience/util.js index 47ccb9bf7d..6c53ed2814 100644 --- a/src/v0/destinations/fb_custom_audience/util.js +++ b/src/v0/destinations/fb_custom_audience/util.js @@ -131,21 +131,21 @@ const getUpdatedDataElement = (dataElement, isHashRequired, eachProperty, update /** * hash the original value for the properties apart from 'MADID' && 'EXTERN_ID as hashing is not required for them * ref: https://developers.facebook.com/docs/marketing-api/audiences/guides/custom-audiences#hash - * sending null values for the properties for which user hasn't provided any value + * sending empty string for the properties for which user hasn't provided any value */ if (isHashRequired && eachProperty !== 'MADID' && eachProperty !== 'EXTERN_ID') { if (tmpUpdatedProperty) { tmpUpdatedProperty = `${tmpUpdatedProperty}`; dataElement.push(sha256(tmpUpdatedProperty)); } else { - dataElement.push(null); + dataElement.push(''); } } - // if property name is MADID or EXTERN_ID if the value is undefined send null + // if property name is MADID or EXTERN_ID if the value is undefined send empty string else if (!tmpUpdatedProperty && (eachProperty === 'MADID' || eachProperty === 'EXTERN_ID')) { - dataElement.push(null); + dataElement.push(''); } else { - dataElement.push(tmpUpdatedProperty); + dataElement.push(tmpUpdatedProperty || ''); } return dataElement; }; diff --git a/test/integrations/destinations/fb_custom_audience/processor/data.ts b/test/integrations/destinations/fb_custom_audience/processor/data.ts index 4f892f6fef..267b966865 100644 --- a/test/integrations/destinations/fb_custom_audience/processor/data.ts +++ b/test/integrations/destinations/fb_custom_audience/processor/data.ts @@ -1987,7 +1987,7 @@ export const data = [ 'a953f09a1b6b6725b81956e9ad0b1eb49e3ad40004c04307ef8af6246a054116', '3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278', '7931aa2a1bed855457d1ddf6bc06ab4406a9fba0579045a4d6ff78f9c07c440f', - null, + '', '252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111', 'db0683221aebc02cc034b65ebcf7d1bddd1eb199e33fd23a31931947d13a11bc', 'abc', @@ -2123,7 +2123,7 @@ export const data = [ 'ST', 'COUNTRY', ], - data: [[null, null, null, null, null, null, null, null, null, null, null]], + data: [['', '', '', '', '', '', '', '', '', '', '']], }, }, body: { @@ -2256,7 +2256,7 @@ export const data = [ 'a953f09a1b6b6725b81956e9ad0b1eb49e3ad40004c04307ef8af6246a054116', '3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278', '7931aa2a1bed855457d1ddf6bc06ab4406a9fba0579045a4d6ff78f9c07c440f', - null, + '', '252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111', 'db0683221aebc02cc034b65ebcf7d1bddd1eb199e33fd23a31931947d13a11bc', 'abc', diff --git a/test/integrations/destinations/fb_custom_audience/router/data.ts b/test/integrations/destinations/fb_custom_audience/router/data.ts index efefb80a89..fd099fe33c 100644 --- a/test/integrations/destinations/fb_custom_audience/router/data.ts +++ b/test/integrations/destinations/fb_custom_audience/router/data.ts @@ -26757,16 +26757,16 @@ export const data = [ payload: { schema: ['EMAIL', 'FN'], data: [ - ['7625cab24612c37df6d2f724721bb38a25095d0295e29b807238ee188b8aca43', null], - ['b2b4abadd72190af54305c0d3abf1977fec4935016bb13ff28040d5712318dfd', null], - ['c4b007d1c3c9a5d31bd4082237a913e8e0db1767225c2a5ef33be2716df005fa', null], - ['94639be1bd9f17c05820164e9d71ef78558f117a9e8bfab43cf8015e08aa0b27', null], - ['39b456cfb4bb07f9e6bb18698aa173171ca49c731fccc4790e9ecea808d24ae6', null], - ['769f73387add781a481ca08300008a08fb2f1816aaed196137efc2e05976d711', null], - ['48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', null], - ['da2d431121cd10578fd81f8f80344b06db59ea2d05a7b5d27536c8789ddae8f0', null], - ['b100c2ec0718fe6b4805b623aeec6710719d042ceea55f5c8135b010ec1c7b36', null], - ['0c1d1b0ba547a742013366d6fbc8f71dd77f566d94e41ed9f828a74b96928161', null], + ['7625cab24612c37df6d2f724721bb38a25095d0295e29b807238ee188b8aca43', ''], + ['b2b4abadd72190af54305c0d3abf1977fec4935016bb13ff28040d5712318dfd', ''], + ['c4b007d1c3c9a5d31bd4082237a913e8e0db1767225c2a5ef33be2716df005fa', ''], + ['94639be1bd9f17c05820164e9d71ef78558f117a9e8bfab43cf8015e08aa0b27', ''], + ['39b456cfb4bb07f9e6bb18698aa173171ca49c731fccc4790e9ecea808d24ae6', ''], + ['769f73387add781a481ca08300008a08fb2f1816aaed196137efc2e05976d711', ''], + ['48ddb93f0b30c475423fe177832912c5bcdce3cc72872f8051627967ef278e08', ''], + ['da2d431121cd10578fd81f8f80344b06db59ea2d05a7b5d27536c8789ddae8f0', ''], + ['b100c2ec0718fe6b4805b623aeec6710719d042ceea55f5c8135b010ec1c7b36', ''], + ['0c1d1b0ba547a742013366d6fbc8f71dd77f566d94e41ed9f828a74b96928161', ''], ], }, }, From 551c44d14a646e1534cd12d3b5deef4d0c601cf2 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 27 Dec 2023 07:11:13 +0000 Subject: [PATCH 2/9] chore(release): 1.52.4 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6bca95652..8933728ccf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.52.4](https://github.com/rudderlabs/rudder-transformer/compare/v1.52.3...v1.52.4) (2023-12-27) + + +### Bug Fixes + +* send empty string instead of null when the schema data is undefined ([#2955](https://github.com/rudderlabs/rudder-transformer/issues/2955)) ([511741e](https://github.com/rudderlabs/rudder-transformer/commit/511741ed356b365f52e0335ce6a1fc953ccbc465)) + ### [1.52.3](https://github.com/rudderlabs/rudder-transformer/compare/v1.52.2...v1.52.3) (2023-12-18) diff --git a/package-lock.json b/package-lock.json index 573993a1a6..552802d3be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rudder-transformer", - "version": "1.52.3", + "version": "1.52.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rudder-transformer", - "version": "1.52.3", + "version": "1.52.4", "license": "ISC", "dependencies": { "@amplitude/ua-parser-js": "^0.7.24", diff --git a/package.json b/package.json index e8259c96e6..b80b5be2c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rudder-transformer", - "version": "1.52.3", + "version": "1.52.4", "description": "", "homepage": "https://github.com/rudderlabs/rudder-transformer#readme", "bugs": { From efca60cd0f337d261ae96e1f5c400f0ddb0d5bba Mon Sep 17 00:00:00 2001 From: Dilip Kola <33080863+koladilip@users.noreply.github.com> Date: Wed, 27 Dec 2023 13:16:39 +0530 Subject: [PATCH 3/9] chore: upgrade node to 18.19 (#2940) * chore: upgrade node to 18.19 * fix: image name --------- Co-authored-by: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> --- .nvmrc | 2 +- Dockerfile | 2 +- package-lock.json | 35 ----------------------------------- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/.nvmrc b/.nvmrc index 6d80269a4f..a9d087399d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.16.0 +18.19.0 diff --git a/Dockerfile b/Dockerfile index a568ce95c7..6bd03c9515 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1.4 -FROM node:18.17-alpine3.17 AS base +FROM node:18.19.0-alpine3.18 AS base ENV HUSKY 0 RUN apk update diff --git a/package-lock.json b/package-lock.json index 3fd630c9ec..76e90faf57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3710,41 +3710,6 @@ "tslib": "^2.6.2" } }, - "node_modules/@rudderstack/workflow-engine/node_modules/@smithy/is-array-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", - "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rudderstack/workflow-engine/node_modules/@smithy/util-buffer-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", - "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", - "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rudderstack/workflow-engine/node_modules/@smithy/util-utf8": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", - "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@sideway/address": { "version": "4.1.4", "license": "BSD-3-Clause", From 4e1a200516bd4b9ae42f2bea09ff196b4dede6f9 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Wed, 27 Dec 2023 21:32:43 +0530 Subject: [PATCH 4/9] chore: update pr template (#2956) * chore: update pr template * chore: address comments * Update .github/pull_request_template.md Co-authored-by: Krishna Chaitanya * Update .github/pull_request_template.md Co-authored-by: Krishna Chaitanya * chore: updated checklist * chore: fix linear, heading --------- Co-authored-by: Krishna Chaitanya --- .github/pull_request_template.md | 34 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 5b716b7e9f..fe308ce8b9 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,21 +2,15 @@ Write a brief explainer on your code changes. -## Please explain the objectives of your changes below - -Put down any required details on the broader aspect of your changes. If there are any dependent changes, **mandatorily** mention them here - -### Type of change +## What is the related Linear task? -If the pull request is a **bug-fix**, **enhancement** or a **refactor**, please fill in the details on the changes made. +Resolves INT-XXX -- Existing capabilities/behavior - -- New capabilities/behavior +## Please explain the objectives of your changes below -If the pull request is a **new feature**, +Put down any required details on the broader aspect of your changes. If there are any dependent changes, **mandatorily** mention them here -### Any technical or performance related pointers to consider with the change? +### Any changes to existing capabilities/behaviour, mention the reason & what are the changes ? N/A @@ -28,11 +22,7 @@ N/A N/A -### If the PR has changes in more than 10 files, please mention why the changes were not split into multiple PRs. - -N/A - -### If multiple linear tasks are associated with the PR changes, please elaborate on the reason: +### Any technical or performance related pointers to consider with the change? N/A @@ -40,13 +30,19 @@ N/A ### Developer checklist +- [ ] My code follows the style guidelines of this project + - [ ] **No breaking changes are being introduced.** -- [ ] Are all related docs linked with the PR? +- [ ] All related docs linked with the PR? + +- [ ] All changes manually tested? + +- [ ] Any documentation changes needed with this change? -- [ ] Are all changes manually tested? +- [ ] Is the PR limited to 10 file changes? -- [ ] Does this change require any documentation changes? +- [ ] Is the PR limited to one linear task? - [ ] Are relevant unit and component test-cases added? From 970d37d6a3e4196c284513dd56f5405b0f3f2821 Mon Sep 17 00:00:00 2001 From: AASHISH MALIK Date: Tue, 2 Jan 2024 19:34:09 +0530 Subject: [PATCH 5/9] feat: pass ip details for factorsAI (#2925) --- .../factorsai/data/FactorsAIGroupConfig.json | 5 + .../data/FactorsAIIdentifyConfig.json | 5 + .../factorsai/data/FactorsAITrackConfig.json | 5 + src/v0/destinations/factorsai/transform.js | 17 +- .../destinations/factorsai/data.ts | 270 ++++++++++++++++++ 5 files changed, 299 insertions(+), 3 deletions(-) diff --git a/src/v0/destinations/factorsai/data/FactorsAIGroupConfig.json b/src/v0/destinations/factorsai/data/FactorsAIGroupConfig.json index f5f78e71e4..d581f56070 100644 --- a/src/v0/destinations/factorsai/data/FactorsAIGroupConfig.json +++ b/src/v0/destinations/factorsai/data/FactorsAIGroupConfig.json @@ -34,5 +34,10 @@ "destKey": "email", "sourceKeys": "email", "required": false + }, + { + "sourceKeys": "context", + "destKey": "context", + "required": false } ] diff --git a/src/v0/destinations/factorsai/data/FactorsAIIdentifyConfig.json b/src/v0/destinations/factorsai/data/FactorsAIIdentifyConfig.json index 9a08c382d4..b34cd2147e 100644 --- a/src/v0/destinations/factorsai/data/FactorsAIIdentifyConfig.json +++ b/src/v0/destinations/factorsai/data/FactorsAIIdentifyConfig.json @@ -34,5 +34,10 @@ "destKey": "channel", "sourceKeys": "channel", "required": false + }, + { + "sourceKeys": "context", + "destKey": "context", + "required": false } ] diff --git a/src/v0/destinations/factorsai/data/FactorsAITrackConfig.json b/src/v0/destinations/factorsai/data/FactorsAITrackConfig.json index ccb9686c29..67df67fc76 100644 --- a/src/v0/destinations/factorsai/data/FactorsAITrackConfig.json +++ b/src/v0/destinations/factorsai/data/FactorsAITrackConfig.json @@ -44,5 +44,10 @@ "destKey": "channel", "sourceKeys": "channel", "required": false + }, + { + "sourceKeys": "context", + "destKey": "context", + "required": false } ] diff --git a/src/v0/destinations/factorsai/transform.js b/src/v0/destinations/factorsai/transform.js index 9824b73bbf..9fbfc926f7 100644 --- a/src/v0/destinations/factorsai/transform.js +++ b/src/v0/destinations/factorsai/transform.js @@ -13,6 +13,14 @@ const { JSON_MIME_TYPE } = require('../../util/constant'); const { ConfigCategories, mappingConfig, BASE_URL } = require('./config'); +function populateIpDetails(requestJson, message) { + const payload = requestJson; + if (message.context || message.request_ip) { + payload.context = { ...(payload.context || {}), ip: message.context?.ip || message.request_ip }; + } + return payload; +} + // build final response function buildResponse(payload, factorsAIApiKey) { const response = defaultRequestConfig(); @@ -29,13 +37,15 @@ function buildResponse(payload, factorsAIApiKey) { // process identify call function processIdentify(message, factorsAIApiKey) { - const requestJson = constructPayload(message, mappingConfig[ConfigCategories.IDENTIFY.name]); + let requestJson = constructPayload(message, mappingConfig[ConfigCategories.IDENTIFY.name]); + requestJson = populateIpDetails(requestJson, message); return buildResponse(requestJson, factorsAIApiKey); } // process track call function processTrack(message, factorsAIApiKey) { - const requestJson = constructPayload(message, mappingConfig[ConfigCategories.TRACK.name]); + let requestJson = constructPayload(message, mappingConfig[ConfigCategories.TRACK.name]); + requestJson = populateIpDetails(requestJson, message); // flatten json as factorsAi do not support nested properties requestJson.properties = flattenJson(requestJson.properties); return buildResponse(requestJson, factorsAIApiKey); @@ -43,7 +53,8 @@ function processTrack(message, factorsAIApiKey) { // process Page Call function processPageAndGroup(message, factorsAIApiKey, category) { - const requestJson = constructPayload(message, mappingConfig[category]); + let requestJson = constructPayload(message, mappingConfig[category]); + requestJson = populateIpDetails(requestJson, message); requestJson.type = message.type; return buildResponse(requestJson, factorsAIApiKey); } diff --git a/test/integrations/destinations/factorsai/data.ts b/test/integrations/destinations/factorsai/data.ts index fb0a76bf34..be13c291f4 100644 --- a/test/integrations/destinations/factorsai/data.ts +++ b/test/integrations/destinations/factorsai/data.ts @@ -308,6 +308,9 @@ export const data = [ XML: {}, FORM: {}, JSON: { + context: { + ip: '8.8.8.8', + }, type: 'identify', traits: { age: 27, @@ -540,4 +543,271 @@ export const data = [ }, }, }, + { + name: 'factorsai', + description: 'IP fetched from request_ip', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + factorsAIApiKey: 'sdgerghsdfhsdhsdh432141dfgdfsg', + }, + }, + message: { + context: { + page: { + url: 'myurl', + path: '/workspace/index.html', + title: 'test track', + search: '?s=ek8reb577tu65kfc2fv41fbm3j', + referrer: '$direct', + initial_referrer: '$direct', + referring_domain: '', + initial_referring_domain: '', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36', + }, + event: 'finalPageTest', + properties: { + title: 'Intro to Test final segemt context page added context last', + }, + userId: 'PageTestAnonymousUser', + type: 'track', + messageId: '3c0abc14-96a2-4aed-9dfc-ee463832cc24', + originalTimestamp: '2022-10-17T15:32:44.202+05:30', + request_ip: '104.205.211.60', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + type: 'track', + event: 'finalPageTest', + context: { + ip: '104.205.211.60', + page: { + url: 'myurl', + path: '/workspace/index.html', + title: 'test track', + search: '?s=ek8reb577tu65kfc2fv41fbm3j', + referrer: '$direct', + initial_referrer: '$direct', + referring_domain: '', + initial_referring_domain: '', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36', + }, + messageId: '3c0abc14-96a2-4aed-9dfc-ee463832cc24', + timestamp: '2022-10-17T15:32:44.202+05:30', + properties: { + title: 'Intro to Test final segemt context page added context last', + }, + userId: 'PageTestAnonymousUser', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + userId: '', + method: 'POST', + params: {}, + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic c2RnZXJnaHNkZmhzZGhzZGg0MzIxNDFkZmdkZnNnOg==', + }, + version: '1', + endpoint: 'https://api.factors.ai/integrations/rudderstack_platform', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'factorsai', + description: 'IP fetched from request_ip', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + factorsAIApiKey: 'sdgerghsdfhsdhsdh432141dfgdfsg', + }, + }, + message: { + context: { + locale: 'en-US', + screen: { + density: 2, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + }, + event: 'finalPageTest', + properties: { + title: 'Intro to Test final segemt context page added context last', + }, + userId: 'PageTestAnonymousUser', + type: 'track', + messageId: '3c0abc14-96a2-4aed-9dfc-ee463832cc24', + originalTimestamp: '2022-10-17T15:32:44.202+05:30', + request_ip: '0.0.0.0', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + type: 'track', + event: 'finalPageTest', + context: { + ip: '0.0.0.0', + locale: 'en-US', + screen: { + density: 2, + }, + library: { + name: 'RudderLabs JavaScript SDK', + version: '1.0.0', + }, + userAgent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + }, + messageId: '3c0abc14-96a2-4aed-9dfc-ee463832cc24', + timestamp: '2022-10-17T15:32:44.202+05:30', + properties: { + title: 'Intro to Test final segemt context page added context last', + }, + userId: 'PageTestAnonymousUser', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + userId: '', + method: 'POST', + params: {}, + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic c2RnZXJnaHNkZmhzZGhzZGg0MzIxNDFkZmdkZnNnOg==', + }, + version: '1', + endpoint: 'https://api.factors.ai/integrations/rudderstack_platform', + }, + statusCode: 200, + }, + ], + }, + }, + }, + { + name: 'factorsai', + description: 'IP fetched from request_ip withput context in payload', + feature: 'processor', + module: 'destination', + version: 'v0', + input: { + request: { + body: [ + { + destination: { + Config: { + factorsAIApiKey: 'sdgerghsdfhsdhsdh432141dfgdfsg', + }, + }, + message: { + event: 'finalPageTest', + properties: { + title: 'Intro to Test final segemt context page added context last', + }, + userId: 'PageTestAnonymousUser', + type: 'track', + messageId: '3c0abc14-96a2-4aed-9dfc-ee463832cc24', + originalTimestamp: '2022-10-17T15:32:44.202+05:30', + request_ip: '1.1.1.1', + }, + }, + ], + method: 'POST', + }, + }, + output: { + response: { + status: 200, + body: [ + { + output: { + body: { + XML: {}, + FORM: {}, + JSON: { + type: 'track', + event: 'finalPageTest', + context: { + ip: '1.1.1.1', + }, + messageId: '3c0abc14-96a2-4aed-9dfc-ee463832cc24', + timestamp: '2022-10-17T15:32:44.202+05:30', + properties: { + title: 'Intro to Test final segemt context page added context last', + }, + userId: 'PageTestAnonymousUser', + }, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + userId: '', + method: 'POST', + params: {}, + headers: { + 'Content-Type': 'application/json', + Authorization: 'Basic c2RnZXJnaHNkZmhzZGhzZGg0MzIxNDFkZmdkZnNnOg==', + }, + version: '1', + endpoint: 'https://api.factors.ai/integrations/rudderstack_platform', + }, + statusCode: 200, + }, + ], + }, + }, + }, ]; From 7d734f06df75d198f8440a953ce089631af15a8b Mon Sep 17 00:00:00 2001 From: Sandeep Digumarty Date: Wed, 3 Jan 2024 11:46:21 +0530 Subject: [PATCH 6/9] feat: handle improper type validation sync vulnerability (#2937) * feat: handle improper type validation sync vulnerability * feat: addressed review comments --- src/controllers/bulkUpload.ts | 10 +++++----- src/util/types.ts | 3 +++ .../networkHandler.js | 8 +++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/controllers/bulkUpload.ts b/src/controllers/bulkUpload.ts index 85c4fe6b4f..babb8b6db1 100644 --- a/src/controllers/bulkUpload.ts +++ b/src/controllers/bulkUpload.ts @@ -1,7 +1,7 @@ /* eslint-disable global-require, import/no-dynamic-require, @typescript-eslint/no-unused-vars */ import { client as errNotificationClient } from '../util/errorNotifier'; import logger from '../logger'; -import { CatchErr } from '../util/types'; +import { CatchErr, ContextBodySimple } from '../util/types'; // TODO: To be refactored and redisgned const getDestFileUploadHandler = (version, dest) => @@ -45,7 +45,7 @@ export const fileUpload = async (ctx) => { return {}; }; - const { destType } = ctx.request.body; + const { destType }: ContextBodySimple = ctx.request.body; const destFileUploadHandler = getDestFileUploadHandler('v0', destType.toLowerCase()); if (!destFileUploadHandler || !destFileUploadHandler.processFileData) { @@ -82,7 +82,7 @@ export const pollStatus = async (ctx) => { JSON.stringify(ctx.request.body), ); - const { destType } = ctx.request.body; + const { destType }: ContextBodySimple = ctx.request.body; const destFileUploadHandler = getPollStatusHandler('v0', destType.toLowerCase()); let response; if (!destFileUploadHandler || !destFileUploadHandler.processPolling) { @@ -117,7 +117,7 @@ export const getWarnJobStatus = async (ctx) => { JSON.stringify(ctx.request.body), ); - const { destType } = ctx.request.body; + const { destType }: ContextBodySimple = ctx.request.body; const destFileUploadHandler = getJobStatusHandler('v0', destType.toLowerCase()); if (!destFileUploadHandler || !destFileUploadHandler.processJobStatus) { @@ -153,7 +153,7 @@ export const getFailedJobStatus = async (ctx) => { JSON.stringify(ctx.request.body), ); - const { destType } = ctx.request.body; + const { destType }: ContextBodySimple = ctx.request.body; const destFileUploadHandler = getJobStatusHandler('v0', destType.toLowerCase()); if (!destFileUploadHandler || !destFileUploadHandler.processJobStatus) { diff --git a/src/util/types.ts b/src/util/types.ts index 579c35579c..bd2836d710 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -3,6 +3,9 @@ export type FixMe = any; export type CatchErr = any; +export type ContextBodySimple = { + destType: string; +}; export interface Config { cdkEnabled?: boolean; cdkV2Enabled?: boolean; diff --git a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js index a87a2431f2..cd891d9688 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js @@ -190,9 +190,11 @@ const ProxyRequest = async (request) => { const addPayload = body.JSON.addConversionPayload; // Mapping Conversion Action const conversionId = await getConversionActionId(headers, params); - addPayload.operations.forEach((operation) => { - set(operation, 'create.transaction_attribute.conversion_action', conversionId); - }); + if (Array.isArray(addPayload.operations)) { + addPayload.operations.forEach((operation) => { + set(operation, 'create.transaction_attribute.conversion_action', conversionId); + }); + } await addConversionToJob(endpoint, headers, firstResponse, addPayload); const thirdResponse = await runTheJob( endpoint, From 48e40365de6d45c40b25b0af3373504bfd5368bd Mon Sep 17 00:00:00 2001 From: Mihir Bhalala <77438541+mihir-4116@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:34:32 +0530 Subject: [PATCH 7/9] feat: move intercom to routerTransform (#2964) --- src/features.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features.json b/src/features.json index a3d29bb325..606590459c 100644 --- a/src/features.json +++ b/src/features.json @@ -63,7 +63,8 @@ "GLADLY": true, "ONE_SIGNAL": true, "TIKTOK_AUDIENCE": true, - "REDDIT": true + "REDDIT": true, + "INTERCOM": true }, "supportSourceTransformV1": true, "supportTransformerProxyV1": false From 8a245a21c450958595aa660b9051ed3b21bc986c Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:52:17 +0530 Subject: [PATCH 8/9] chore: add endpoint labels (#2944) * chore: add endpoint labelsx1 * chore: add endpoint labelsx2 * Update src/v0/destinations/active_campaign/transform.js Co-authored-by: Sudip Paul <67197965+ItsSudip@users.noreply.github.com> * Update src/v0/destinations/active_campaign/transform.js Co-authored-by: Sankeerth * chore: fix monday path --------- Co-authored-by: Sudip Paul <67197965+ItsSudip@users.noreply.github.com> Co-authored-by: Sankeerth --- .../destinations/active_campaign/transform.js | 28 +++++++++++-------- src/v0/destinations/af/deleteUsers.js | 1 + src/v0/destinations/am/deleteUsers.js | 2 ++ src/v0/destinations/ga/deleteUsers.js | 1 + .../networkHandler.js | 2 ++ .../networkHandler.js | 4 +++ .../utils.js | 1 + .../networkHandler.js | 3 ++ src/v0/destinations/intercom/deleteUsers.js | 1 + src/v0/destinations/marketo/util.js | 1 + src/v0/destinations/monday/util.js | 1 + 11 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/v0/destinations/active_campaign/transform.js b/src/v0/destinations/active_campaign/transform.js index 70caf47ea8..90e6b2080f 100644 --- a/src/v0/destinations/active_campaign/transform.js +++ b/src/v0/destinations/active_campaign/transform.js @@ -50,7 +50,8 @@ const responseBuilderSimple = (payload, category, destination) => { }; const syncContact = async (contactPayload, category, destination) => { - const endpoint = `${destination.Config.apiUrl}${category.endPoint}`; + const { endPoint } = category; + const endpoint = `${destination.Config.apiUrl}${endPoint}`; const requestData = { contact: contactPayload, }; @@ -60,6 +61,7 @@ const syncContact = async (contactPayload, category, destination) => { const res = await httpPOST(endpoint, requestData, requestOptions, { destType: 'active_campaign', feature: 'transformation', + endpointPath: endPoint, }); if (res.success === false) { errorHandler(res, 'Failed to create new contact'); @@ -78,6 +80,7 @@ const customTagProcessor = async (message, category, destination, contactId) => let endpoint; let requestOptions; let requestData; + const { tagEndPoint, mergeTagWithContactUrl } = category; // Here we extract the tags which are to be mapped to the created contact from the message const msgTags = get(message?.context?.traits, 'tags') || get(message?.traits, 'tags'); @@ -89,13 +92,14 @@ const customTagProcessor = async (message, category, destination, contactId) => // Step - 1 // Fetch already created tags from dest, so that we avoid duplicate tag creation request // Ref - https://developers.activecampaign.com/reference/retrieve-all-tags - endpoint = `${destination.Config.apiUrl}${`${category.tagEndPoint}?limit=100`}`; + endpoint = `${destination.Config.apiUrl}${`${tagEndPoint}?limit=100`}`; requestOptions = { headers: getHeader(destination), }; res = await httpGET(endpoint, requestOptions, { destType: 'active_campaign', feature: 'transformation', + tagEndPoint, }); if (res.success === false) { errorHandler(res, 'Failed to fetch already created tags'); @@ -117,9 +121,7 @@ const customTagProcessor = async (message, category, destination, contactId) => if (parseInt(get(res, TOTAL_RECORDS_KEY), 10) > 100) { const limit = Math.floor(parseInt(get(res, TOTAL_RECORDS_KEY), 10) / 100); for (let i = 0; i < limit; i += 1) { - endpoint = `${destination.Config.apiUrl}${category.tagEndPoint}?limit=100&offset=${ - 100 * (i + 1) - }`; + endpoint = `${destination.Config.apiUrl}${tagEndPoint}?limit=100&offset=${100 * (i + 1)}`; requestOptions = { headers: getHeader(destination), }; @@ -153,7 +155,7 @@ const customTagProcessor = async (message, category, destination, contactId) => if (tagsToBeCreated.length > 0) { await Promise.all( tagsToBeCreated.map(async (tag) => { - endpoint = `${destination.Config.apiUrl}${category.tagEndPoint}`; + endpoint = `${destination.Config.apiUrl}${tagEndPoint}`; requestData = { tag: { tag, @@ -182,7 +184,7 @@ const customTagProcessor = async (message, category, destination, contactId) => // Ref - https://developers.activecampaign.com/reference/create-contact-tag const responsesArr = await Promise.all( tagIds.map(async (tagId) => { - endpoint = `${destination.Config.apiUrl}${category.mergeTagWithContactUrl}`; + endpoint = `${destination.Config.apiUrl}${mergeTagWithContactUrl}`; requestData = { contactTag: { contact: contactId, @@ -207,6 +209,7 @@ const customTagProcessor = async (message, category, destination, contactId) => const customFieldProcessor = async (message, category, destination) => { const responseStaging = []; + const { fieldEndPoint } = category; // Step - 1 // Extract the custom field info from the message const fieldInfo = get(message?.context?.traits, 'fieldInfo') || get(message.traits, 'fieldInfo'); @@ -219,7 +222,7 @@ const customFieldProcessor = async (message, category, destination) => { // Step - 2 // Get the existing field data from dest and store it in responseStaging // Ref - https://developers.activecampaign.com/reference/retrieve-fields - let endpoint = `${destination.Config.apiUrl}${category.fieldEndPoint}?limit=100`; + let endpoint = `${destination.Config.apiUrl}${fieldEndPoint}?limit=100`; const requestOptions = { headers: { 'Api-Token': destination.Config.apiKey, @@ -228,6 +231,7 @@ const customFieldProcessor = async (message, category, destination) => { const res = await httpGET(endpoint, requestOptions, { destType: 'active_campaign', feature: 'transformation', + fieldEndPoint, }); if (res.success === false) { errorHandler(res, 'Failed to get existing field data'); @@ -238,9 +242,7 @@ const customFieldProcessor = async (message, category, destination) => { const limit = Math.floor(parseInt(get(res, TOTAL_RECORDS_KEY), 10) / 100); if (parseInt(get(res, TOTAL_RECORDS_KEY), 10) > 100) { for (let i = 0; i < limit; i += 1) { - endpoint = `${destination.Config.apiUrl}${category.fieldEndPoint}?limit=100&offset=${ - 100 * (i + 1) - }`; + endpoint = `${destination.Config.apiUrl}${fieldEndPoint}?limit=100&offset=${100 * (i + 1)}`; const requestOpt = { headers: { 'Api-Token': destination.Config.apiKey, @@ -308,6 +310,7 @@ const customFieldProcessor = async (message, category, destination) => { }; const customListProcessor = async (message, category, destination, contactId) => { + const { mergeListWithContactUrl } = category; // Here we extract the list info from the message const listInfo = get(message?.context?.traits, 'lists') ? get(message.context.traits, 'lists') @@ -331,7 +334,7 @@ const customListProcessor = async (message, category, destination, contactId) => // eslint-disable-next-line no-restricted-syntax for (const li of listArr) { if (li.status === 'subscribe' || li.status === 'unsubscribe') { - const endpoint = `${destination.Config.apiUrl}${category.mergeListWithContactUrl}`; + const endpoint = `${destination.Config.apiUrl}${mergeListWithContactUrl}`; const requestData = { contactList: { list: li.id, @@ -345,6 +348,7 @@ const customListProcessor = async (message, category, destination, contactId) => const res = httpPOST(endpoint, requestData, requestOptions, { destType: 'active_campaign', feature: 'transformation', + endpointPath: mergeListWithContactUrl, }); promises.push(res); } diff --git a/src/v0/destinations/af/deleteUsers.js b/src/v0/destinations/af/deleteUsers.js index 2d68549fcc..bb711292c0 100644 --- a/src/v0/destinations/af/deleteUsers.js +++ b/src/v0/destinations/af/deleteUsers.js @@ -38,6 +38,7 @@ const deleteUser = async (config, endpoint, body, identityType, identityValue) = { destType: 'af', feature: 'deleteUsers', + endpointPath: `appsflyer.com/api/gdpr/v1/opendsr_requests`, }, ); const handledDelResponse = processAxiosResponse(response); diff --git a/src/v0/destinations/am/deleteUsers.js b/src/v0/destinations/am/deleteUsers.js index 578c58fb5c..6de9cf64a1 100644 --- a/src/v0/destinations/am/deleteUsers.js +++ b/src/v0/destinations/am/deleteUsers.js @@ -28,6 +28,7 @@ const userDeletionHandler = async (userAttributes, config) => { // Ref : https://www.docs.developers.amplitude.com/analytics/apis/user-privacy-api/#response const batchEvents = getUserIdBatches(userAttributes, DELETE_MAX_BATCH_SIZE); const url = 'https://amplitude.com/api/2/deletions/users'; + const endpointPath = '/api/2/deletions/users'; await Promise.all( batchEvents.map(async (batch) => { const data = { @@ -41,6 +42,7 @@ const userDeletionHandler = async (userAttributes, config) => { const resp = await httpPOST(url, data, requestOptions, { destType: 'am', feature: 'deleteUsers', + endpointPath, }); const handledDelResponse = processAxiosResponse(resp); if (!isHttpStatusSuccess(handledDelResponse.status)) { diff --git a/src/v0/destinations/ga/deleteUsers.js b/src/v0/destinations/ga/deleteUsers.js index bb909a0053..06e674048a 100644 --- a/src/v0/destinations/ga/deleteUsers.js +++ b/src/v0/destinations/ga/deleteUsers.js @@ -80,6 +80,7 @@ const userDeletionHandler = async (userAttributes, config, rudderDestInfo) => { { destType: 'ga', feature: 'deleteUsers', + endpointPath: '/userDeletion/userDeletionRequests:upsert', }, ); // process the response to know about refreshing scenario diff --git a/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js b/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js index 8ac432935f..7266154a09 100644 --- a/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_enhanced_conversions/networkHandler.js @@ -44,6 +44,7 @@ const getConversionActionId = async (method, headers, params) => { { destType: 'google_adwords_enhanced_conversions', feature: 'proxy', + endpointPath: `/googleAds:searchStream`, }, ); if (!isHttpStatusSuccess(gaecConversionActionIdResponse.status)) { @@ -96,6 +97,7 @@ const ProxyRequest = async (request) => { const { httpResponse: response } = await handleHttpRequest('constructor', requestBody, { destType: 'google_adwords_enhanced_conversions', feature: 'proxy', + endpointPath: `/googleAds:uploadOfflineUserData`, }); return response; }; diff --git a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js index cd891d9688..e880f97d0d 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js @@ -33,6 +33,7 @@ const createJob = async (endpoint, headers, payload) => { { destType: 'google_adwords_offline_conversions', feature: 'proxy', + endpointPath: `/create`, }, ); createJobResponse = processAxiosResponse(createJobResponse); @@ -57,6 +58,7 @@ const addConversionToJob = async (endpoint, headers, jobId, payload) => { { destType: 'google_adwords_offline_conversions', feature: 'proxy', + endpointPath: `/addOperations`, }, ); addConversionToJobResponse = processAxiosResponse(addConversionToJobResponse); @@ -80,6 +82,7 @@ const runTheJob = async (endpoint, headers, payload, jobId) => { { destType: 'google_adwords_offline_conversions', feature: 'proxy', + endpointPath: `/run`, }, ); return executeJobResponse; @@ -106,6 +109,7 @@ const getConversionCustomVariable = async (headers, params) => { let searchStreamResponse = await httpPOST(endpoint, data, requestOptions, { destType: 'google_adwords_offline_conversions', feature: 'proxy', + endpointPath: `/searchStream`, }); searchStreamResponse = processAxiosResponse(searchStreamResponse); if (!isHttpStatusSuccess(searchStreamResponse.status)) { diff --git a/src/v0/destinations/google_adwords_offline_conversions/utils.js b/src/v0/destinations/google_adwords_offline_conversions/utils.js index c69c5a436f..599a163c54 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/utils.js +++ b/src/v0/destinations/google_adwords_offline_conversions/utils.js @@ -63,6 +63,7 @@ const getConversionActionId = async (headers, params) => { let searchStreamResponse = await httpPOST(endpoint, data, requestOptions, { destType: 'google_adwords_offline_conversions', feature: 'transformation', + endpointPath: `/googleAds:searchStream`, }); searchStreamResponse = processAxiosResponse(searchStreamResponse); if (!isHttpStatusSuccess(searchStreamResponse.status)) { diff --git a/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js b/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js index 5be8597bdb..aeb80216ff 100644 --- a/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js +++ b/src/v0/destinations/google_adwords_remarketing_lists/networkHandler.js @@ -34,6 +34,7 @@ const createJob = async (endpoint, customerId, listId, headers, method) => { const response = await httpSend(jobCreatingRequest, { destType: 'google_adwords_remarketing_lists', feature: 'proxy', + endpointPath: '/customers/create', }); return response; }; @@ -57,6 +58,7 @@ const addUserToJob = async (endpoint, headers, method, jobId, body) => { const response = await httpSend(secondRequest, { destType: 'google_adwords_remarketing_lists', feature: 'proxy', + endpointPath: '/addOperations', }); return response; }; @@ -78,6 +80,7 @@ const runTheJob = async (endpoint, headers, method, jobId) => { const response = await httpSend(thirdRequest, { destType: 'google_adwords_remarketing_lists', feature: 'proxy', + endpointPath: '/run', }); return response; }; diff --git a/src/v0/destinations/intercom/deleteUsers.js b/src/v0/destinations/intercom/deleteUsers.js index e11d352117..085e842458 100644 --- a/src/v0/destinations/intercom/deleteUsers.js +++ b/src/v0/destinations/intercom/deleteUsers.js @@ -38,6 +38,7 @@ const userDeletionHandler = async (userAttributes, config) => { const resp = await httpPOST(url, data, requestOptions, { destType: 'intercom', feature: 'deleteUsers', + endpointPath: '/user_delete_requests', }); const handledDelResponse = processAxiosResponse(resp); if (!isHttpStatusSuccess(handledDelResponse.status) && handledDelResponse.status !== 404) { diff --git a/src/v0/destinations/marketo/util.js b/src/v0/destinations/marketo/util.js index 203e0bf859..4dc576ec16 100644 --- a/src/v0/destinations/marketo/util.js +++ b/src/v0/destinations/marketo/util.js @@ -262,6 +262,7 @@ const sendPostRequest = async (url, data, options) => { const clientResponse = await httpPOST(url, data, options, { destType: 'marketo', feature: 'transformation', + endpointPath: `/v1/leads`, }); const processedResponse = processAxiosResponse(clientResponse); return processedResponse; diff --git a/src/v0/destinations/monday/util.js b/src/v0/destinations/monday/util.js index a66dd63dff..736f0133fd 100644 --- a/src/v0/destinations/monday/util.js +++ b/src/v0/destinations/monday/util.js @@ -194,6 +194,7 @@ const getBoardDetails = async (url, boardID, apiToken) => { { destType: 'monday', feature: 'transformation', + endpointPath: '/v2', }, ); const boardDetailsResponse = processAxiosResponse(clientResponse); From 5dade8942e3b59d3f0f36f5543f6e38d41f2aab5 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:52:40 +0530 Subject: [PATCH 9/9] chore: add endpoint labels (#2951) chore: add endpoint labelsx3 Co-authored-by: Sudip Paul <67197965+ItsSudip@users.noreply.github.com> --- src/v0/destinations/active_campaign/transform.js | 4 ++++ src/v0/destinations/canny/util.js | 1 + src/v0/destinations/custify/util.js | 1 + src/v0/destinations/freshmarketer/utils.js | 7 +++++++ src/v0/destinations/freshsales/utils.js | 5 +++++ .../google_adwords_offline_conversions/networkHandler.js | 1 + src/v0/destinations/hs/util.js | 2 ++ src/v0/destinations/marketo/util.js | 1 + src/v0/destinations/user/utils.js | 7 +++++++ src/v0/destinations/wootric/util.js | 2 ++ 10 files changed, 31 insertions(+) diff --git a/src/v0/destinations/active_campaign/transform.js b/src/v0/destinations/active_campaign/transform.js index 90e6b2080f..981dbd7520 100644 --- a/src/v0/destinations/active_campaign/transform.js +++ b/src/v0/destinations/active_campaign/transform.js @@ -128,6 +128,7 @@ const customTagProcessor = async (message, category, destination, contactId) => const resp = httpGET(endpoint, requestOptions, { destType: 'active_campaign', feature: 'transformation', + endpointPath: `/api/3/tags`, }); promises.push(resp); } @@ -251,6 +252,7 @@ const customFieldProcessor = async (message, category, destination) => { const resp = httpGET(endpoint, requestOpt, { destType: 'active_campaign', feature: 'transformation', + endpointPath: `/api/3/fields`, }); promises.push(resp); } @@ -406,6 +408,7 @@ const screenRequestHandler = async (message, category, destination) => { res = await httpGET(endpoint, requestOptions, { destType: 'active_campaign', feature: 'transformation', + endpointPath: `/api/3/eventTrackingEvents`, }); if (res.success === false) { errorHandler(res, 'Failed to retrieve events'); @@ -469,6 +472,7 @@ const trackRequestHandler = async (message, category, destination) => { let res = await httpGET(endpoint, requestOptions, { destType: 'active_campaign', feature: 'transformation', + endpointPath: `/api/3/eventTrackingEvents`, }); if (res.success === false) { diff --git a/src/v0/destinations/canny/util.js b/src/v0/destinations/canny/util.js index 59644bcd6b..f514a01e5c 100644 --- a/src/v0/destinations/canny/util.js +++ b/src/v0/destinations/canny/util.js @@ -45,6 +45,7 @@ const retrieveUserId = async (apiKey, message) => { { destType: 'canny', feature: 'transformation', + endpointPath: `/v1/users/retrieve`, }, ); logger.debug(response); diff --git a/src/v0/destinations/custify/util.js b/src/v0/destinations/custify/util.js index ae6f21fe20..8ecabccd2e 100644 --- a/src/v0/destinations/custify/util.js +++ b/src/v0/destinations/custify/util.js @@ -40,6 +40,7 @@ const createUpdateCompany = async (companyPayload, Config) => { { destType: 'custify', feature: 'transformation', + endpointPath: `/company`, }, ); const processedCompanyResponse = processAxiosResponse(companyResponse); diff --git a/src/v0/destinations/freshmarketer/utils.js b/src/v0/destinations/freshmarketer/utils.js index 6fa1fe9976..5e3ba6e67e 100644 --- a/src/v0/destinations/freshmarketer/utils.js +++ b/src/v0/destinations/freshmarketer/utils.js @@ -49,6 +49,7 @@ const createUpdateAccount = async (payload, Config) => { let accountResponse = await httpPOST(endPoint, payloadBody, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `/crm/sales/api/sales_accounts/upsert`, }); accountResponse = processAxiosResponse(accountResponse); if (accountResponse.status !== 200 && accountResponse.status !== 201) { @@ -93,6 +94,7 @@ const getUserAccountDetails = async (payload, userEmail, Config) => { let userSalesAccountResponse = await httpPOST(endPoint, userPayload, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `crm/sales/api/contacts/upsert?include=sales_accounts`, }); userSalesAccountResponse = processAxiosResponse(userSalesAccountResponse); if (userSalesAccountResponse.status !== 200 && userSalesAccountResponse.status !== 201) { @@ -142,6 +144,7 @@ const createOrUpdateListDetails = async (listName, Config) => { let listResponse = await httpGET(endPoint, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `/crm/sales/api/lists`, }); listResponse = processAxiosResponse(listResponse); if (listResponse.status !== 200) { @@ -161,6 +164,7 @@ const createOrUpdateListDetails = async (listName, Config) => { listResponse = await httpPOST(endPoint, { name: listName }, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `/crm/sales/api/lists`, }); listResponse = processAxiosResponse(listResponse); if (listResponse.status !== 200) { @@ -235,6 +239,7 @@ const getContactsDetails = async (userEmail, Config) => { let userResponse = await httpPOST(endPoint, userPayload, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `/crm/sales/api/contacts/upsert`, }); userResponse = processAxiosResponse(userResponse); if (userResponse.status !== 200 && userResponse.status !== 201) { @@ -308,6 +313,7 @@ const UpdateContactWithLifeCycleStage = async (message, Config) => { let lifeCycleStagesResponse = await httpGET(endPoint, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `/crm/sales/api/selector/lifecycle_stages`, }); lifeCycleStagesResponse = processAxiosResponse(lifeCycleStagesResponse); if (lifeCycleStagesResponse.status !== 200) { @@ -393,6 +399,7 @@ const UpdateContactWithSalesActivity = async (payload, message, Config) => { let salesActivityResponse = await httpGET(endPoint, requestOptions, { destType: 'freshmarketer', feature: 'transformation', + endpointPath: `/crm/sales/api/selector/sales_activity_types`, }); salesActivityResponse = processAxiosResponse(salesActivityResponse); if (salesActivityResponse.status !== 200) { diff --git a/src/v0/destinations/freshsales/utils.js b/src/v0/destinations/freshsales/utils.js index 96acabb037..5008fedc2d 100644 --- a/src/v0/destinations/freshsales/utils.js +++ b/src/v0/destinations/freshsales/utils.js @@ -47,6 +47,7 @@ const createUpdateAccount = async (payload, Config) => { let accountResponse = await httpPOST(endPoint, payloadBody, requestOptions, { destType: 'freshsales', feature: 'transformation', + endpointPath: `/crm/sales/api/sales_accounts/upsert`, }); accountResponse = processAxiosResponse(accountResponse); if (accountResponse.status !== 200 && accountResponse.status !== 201) { @@ -90,6 +91,7 @@ const getUserAccountDetails = async (payload, userEmail, Config) => { let userSalesAccountResponse = await httpPOST(endPoint, userPayload, requestOptions, { destType: 'freshsales', feature: 'transformation', + endpointPath: `/crm/sales/api/contacts/upsert?include=sales_accounts`, }); userSalesAccountResponse = processAxiosResponse(userSalesAccountResponse); if (userSalesAccountResponse.status !== 200 && userSalesAccountResponse.status !== 201) { @@ -145,6 +147,7 @@ const getContactsDetails = async (userEmail, Config) => { let userResponse = await httpPOST(endPoint, userPayload, requestOptions, { destType: 'freshsales', feature: 'transformation', + endpointPath: `/crm/sales/api/contacts/upsert`, }); userResponse = processAxiosResponse(userResponse); if (userResponse.status !== 200 && userResponse.status !== 201) { @@ -235,6 +238,7 @@ const UpdateContactWithSalesActivity = async (payload, message, Config) => { let salesActivityResponse = await httpGET(endPoint, requestOptions, { destType: 'freshsales', feature: 'transformation', + endpointPath: `/crm/sales/api/sales_activity_types`, }); salesActivityResponse = processAxiosResponse(salesActivityResponse); if (salesActivityResponse.status !== 200) { @@ -314,6 +318,7 @@ const UpdateContactWithLifeCycleStage = async (message, Config) => { let lifeCycleStagesResponse = await httpGET(endPoint, requestOptions, { destType: 'freshsales', feature: 'transformation', + endpointPath: `/crm/sales/api/lifecycle_stages`, }); lifeCycleStagesResponse = processAxiosResponse(lifeCycleStagesResponse); if (lifeCycleStagesResponse.status !== 200) { diff --git a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js index e880f97d0d..6922cde8c8 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js +++ b/src/v0/destinations/google_adwords_offline_conversions/networkHandler.js @@ -246,6 +246,7 @@ const ProxyRequest = async (request) => { const response = await httpSend(requestBody, { feature: 'proxy', destType: 'gogole_adwords_offline_conversions', + endpointPath: `/proxy`, }); return response; }; diff --git a/src/v0/destinations/hs/util.js b/src/v0/destinations/hs/util.js index f83ce0b6de..5c8f4a908a 100644 --- a/src/v0/destinations/hs/util.js +++ b/src/v0/destinations/hs/util.js @@ -100,6 +100,7 @@ const getProperties = async (destination) => { hubspotPropertyMapResponse = await httpGET(CONTACT_PROPERTY_MAP_ENDPOINT, requestOptions, { destType: 'hs', feature: 'transformation', + endpointPath: `/properties/v1/contacts/properties`, }); hubspotPropertyMapResponse = processAxiosResponse(hubspotPropertyMapResponse); } else { @@ -111,6 +112,7 @@ const getProperties = async (destination) => { { destType: 'hs', feature: 'transformation', + endpointPath: `/properties/v1/contacts/properties?hapikey`, }, ); hubspotPropertyMapResponse = processAxiosResponse(hubspotPropertyMapResponse); diff --git a/src/v0/destinations/marketo/util.js b/src/v0/destinations/marketo/util.js index 4dc576ec16..54ff70708a 100644 --- a/src/v0/destinations/marketo/util.js +++ b/src/v0/destinations/marketo/util.js @@ -247,6 +247,7 @@ const sendGetRequest = async (url, options) => { const clientResponse = await httpGET(url, options, { destType: 'marketo', feature: 'transformation', + endpointPath: `/v1/leads`, }); const processedResponse = processAxiosResponse(clientResponse); return processedResponse; diff --git a/src/v0/destinations/user/utils.js b/src/v0/destinations/user/utils.js index 41ad173583..52fba2167e 100644 --- a/src/v0/destinations/user/utils.js +++ b/src/v0/destinations/user/utils.js @@ -237,6 +237,7 @@ const createCompany = async (message, destination) => { const response = await httpPOST(endpoint, payload, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/companies/`, }); const data = processAxiosResponse(response); return data.response; @@ -277,6 +278,7 @@ const updateCompany = async (message, destination, company) => { const response = await httpPUT(endpoint, payload, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/companies/`, }); const data = processAxiosResponse(response); return data.response; @@ -303,6 +305,7 @@ const getUserByUserKey = async (apiKey, userKey, appSubdomain) => { const userResponse = await httpGET(endpoint, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/users/search`, }); const processedUserResponse = processAxiosResponse(userResponse); if (processedUserResponse.status === 200) { @@ -336,6 +339,7 @@ const getUserByEmail = async (apiKey, email, appSubdomain) => { const userResponse = await httpGET(endpoint, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/users/search/?email`, }); const processedUserResponse = processAxiosResponse(userResponse); @@ -374,6 +378,7 @@ const getUserByPhoneNumber = async (apiKey, phoneNumber, appSubdomain) => { const userResponse = await httpGET(endpoint, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/users/search/?phone_number`, }); const processedUserResponse = processAxiosResponse(userResponse); @@ -418,6 +423,7 @@ const getUserByCustomId = async (message, destination) => { const userResponse = await httpGET(endpoint, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/users-by-id/`, }); const processedUserResponse = processAxiosResponse(userResponse); @@ -453,6 +459,7 @@ const getCompanyByCustomId = async (message, destination) => { const response = await httpGET(endpoint, requestOptions, { destType: 'user', feature: 'transformation', + endpointPath: `/companies-by-id/`, }); const processedUserResponse = processAxiosResponse(response); if (processedUserResponse.status === 200) { diff --git a/src/v0/destinations/wootric/util.js b/src/v0/destinations/wootric/util.js index fce8a66586..eb61a472cf 100644 --- a/src/v0/destinations/wootric/util.js +++ b/src/v0/destinations/wootric/util.js @@ -46,6 +46,7 @@ const getAccessToken = async (destination) => { const wootricAuthResponse = await httpPOST(request.url, request.data, request.header, { destType: 'wootric', feature: 'transformation', + endpointPath: `/oauth/token`, }); const processedAuthResponse = processAxiosResponse(wootricAuthResponse); // If the request fails, throwing error. @@ -98,6 +99,7 @@ const retrieveUserDetails = async (endUserId, externalId, accessToken) => { const userResponse = await httpGET(endpoint, requestOptions, { destType: 'wootric', feature: 'transformation', + endpointPath: `/v1/end_users/`, }); const processedUserResponse = processAxiosResponse(userResponse);