From ded9bb4ac73cb4d6d9a275ec6e8cc3d6b1df2c9b Mon Sep 17 00:00:00 2001 From: AASHISH MALIK Date: Sat, 16 Dec 2023 12:51:17 +0530 Subject: [PATCH 1/2] fix: email validation for braze --- src/v0/destinations/braze/transform.js | 4 +- test/__tests__/data/braze_input.json | 77 ++++++++++++++++++++++++++ test/__tests__/data/braze_output.json | 73 +++++++++++++++++++++++- 3 files changed, 151 insertions(+), 3 deletions(-) diff --git a/src/v0/destinations/braze/transform.js b/src/v0/destinations/braze/transform.js index 38c4b348db..2ac13d9969 100644 --- a/src/v0/destinations/braze/transform.js +++ b/src/v0/destinations/braze/transform.js @@ -155,8 +155,8 @@ function getUserAttributesObject(message, mappingJson, destination) { let value = get(traits, mappingJson[destKey]); if (value || (value === null && reservedKeys.includes(destKey))) { // if email is not string remove it from attributes - if (destKey === 'email' && typeof value !== 'string') { - throw new InstrumentationError('Invalid email, email must be a valid string'); + if (destKey === 'email' && Number.isInteger(value)) { + throw new InstrumentationError('Invalid email, email must be a valid string or null'); } // handle gender special case diff --git a/test/__tests__/data/braze_input.json b/test/__tests__/data/braze_input.json index fb4e41b189..3fc1dbb905 100644 --- a/test/__tests__/data/braze_input.json +++ b/test/__tests__/data/braze_input.json @@ -1955,5 +1955,82 @@ "type": "identify", "userId": "" } + }, + { + "destination": { + "Config": { + "restApiKey": "dummyApiKey", + "prefixProperties": true, + "useNativeSDK": false, + "sendPurchaseEventWithExtraProperties": true + }, + "DestinationDefinition": { + "DisplayName": "Braze", + "ID": "1WhbSZ6uA3H5ChVifHpfL2H6sie", + "Name": "BRAZE" + }, + "Enabled": true, + "ID": "1WhcOCGgj9asZu850HvugU2C3Aq", + "Name": "Braze", + "Transformations": [] + }, + "message": { + "anonymousId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "channel": "web", + "context": { + "traits": { + "city": "Disney", + "country": "USA", + "email": null, + "firstname": "Mickey" + }, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" + }, + "event": "Order Completed", + "integrations": { + "All": true + }, + "messageId": "aa5f5e44-8756-40ad-ad1e-b0d3b9fa710a", + "originalTimestamp": "2020-01-24T06:29:02.367Z", + "properties": { + "affiliation": "Google Store", + "checkout_id": "fksdjfsdjfisjf9sdfjsd9f", + "coupon": "hasbros", + "currency": "USD", + "discount": 2.5, + "order_id": "50314b8e9bcf000000000000", + "products": [ + { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "price": 0, + "product_id": "507f1f77bcf86cd799439023", + "quantity": 1, + "sku": "45790-32", + "url": "https://www.example.com/product/path" + }, + { + "category": "Games", + "name": "Uno Card Game", + "price": 0, + "product_id": "505bd76785ebb509fc183724", + "quantity": 2, + "sku": "46493-32" + } + ], + "revenue": 25, + "shipping": 3, + "subtotal": 22.5, + "tax": 2, + "total": 27.5 + }, + "receivedAt": "2020-01-24T11:59:02.403+05:30", + "request_ip": "[::1]:53712", + "sentAt": "2020-01-24T06:29:02.368Z", + "timestamp": "2020-01-24T11:59:02.402+05:30", + "type": "track", + "userId": "" + } } ] diff --git a/test/__tests__/data/braze_output.json b/test/__tests__/data/braze_output.json index ed39930569..a7d8c6fb5a 100644 --- a/test/__tests__/data/braze_output.json +++ b/test/__tests__/data/braze_output.json @@ -1037,6 +1037,77 @@ }, { "statusCode": 400, - "message": "Invalid email, email must be a valid string" + "message": "Invalid email, email must be a valid string or null" + }, + { + "body": { + "FORM": {}, + "JSON": { + "attributes": [ + { + "_update_existing_only": false, + "city": "Disney", + "country": "USA", + "email": null, + "firstname": "Mickey", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + } + ], + "partner": "RudderStack", + "purchases": [ + { + "_update_existing_only": false, + "currency": "USD", + "price": 0, + "product_id": "507f1f77bcf86cd799439023", + "properties": { + "category": "Games", + "image_url": "https:///www.example.com/product/path.jpg", + "name": "Monopoly: 3rd Edition", + "url": "https://www.example.com/product/path" + }, + "quantity": 1, + "time": "2020-01-24T11:59:02.402+05:30", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + }, + { + "_update_existing_only": false, + "currency": "USD", + "price": 0, + "product_id": "505bd76785ebb509fc183724", + "properties": { + "category": "Games", + "name": "Uno Card Game" + }, + "quantity": 2, + "time": "2020-01-24T11:59:02.402+05:30", + "user_alias": { + "alias_label": "rudder_id", + "alias_name": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca" + } + } + ] + }, + "JSON_ARRAY": {}, + "XML": {} + }, + "endpoint": "https://rest.fra-01.braze.eu/users/track", + "files": {}, + "headers": { + "Accept": "application/json", + "Authorization": "Bearer dummyApiKey", + "Content-Type": "application/json" + }, + "method": "POST", + "params": {}, + "type": "REST", + "userId": "e6ab2c5e-2cda-44a9-a962-e2f67df78bca", + "version": "1" } ] From cc47c15ddcabc507c59873a7f118495dfa5935fb Mon Sep 17 00:00:00 2001 From: AASHISH MALIK Date: Mon, 18 Dec 2023 11:12:10 +0530 Subject: [PATCH 2/2] fix: addressed comments --- src/v0/destinations/braze/transform.js | 23 +++++++++++++---------- test/__tests__/data/braze_output.json | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/v0/destinations/braze/transform.js b/src/v0/destinations/braze/transform.js index 2ac13d9969..6549f5658f 100644 --- a/src/v0/destinations/braze/transform.js +++ b/src/v0/destinations/braze/transform.js @@ -154,16 +154,19 @@ function getUserAttributesObject(message, mappingJson, destination) { Object.keys(mappingJson).forEach((destKey) => { let value = get(traits, mappingJson[destKey]); if (value || (value === null && reservedKeys.includes(destKey))) { - // if email is not string remove it from attributes - if (destKey === 'email' && Number.isInteger(value)) { - throw new InstrumentationError('Invalid email, email must be a valid string or null'); - } - - // handle gender special case - if (destKey === 'gender') { - value = formatGender(value); - } else if (destKey === 'email' && isDefinedAndNotNull(value)) { - value = value.toString().toLowerCase(); + switch (destKey) { + case 'gender': + value = formatGender(value); + break; + case 'email': + if (typeof value === 'string') { + value = value.toLowerCase(); + } else if (isDefinedAndNotNull(value)) { + throw new InstrumentationError('Invalid email, email must be a valid string'); + } + break; + default: + break; } data[destKey] = value; } diff --git a/test/__tests__/data/braze_output.json b/test/__tests__/data/braze_output.json index a7d8c6fb5a..7e0715f057 100644 --- a/test/__tests__/data/braze_output.json +++ b/test/__tests__/data/braze_output.json @@ -1037,7 +1037,7 @@ }, { "statusCode": 400, - "message": "Invalid email, email must be a valid string or null" + "message": "Invalid email, email must be a valid string" }, { "body": {