From 701bc5752bef5659ba36ed97fbd7ce0350961505 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Mon, 4 Nov 2024 15:33:17 +0300 Subject: [PATCH 1/9] feat: set id to the node --- CHANGELOG.md | 3 +++ lib/countly.js | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f3de83..3b3c6be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## XX.XX.XX +- Added a new method `set_id(newDeviceId)` for managing device ID changes according to the device ID Type + ## 24.10.0 - Default max segmentation value count changed from 30 to 100 - Mitigated an issue where SDK could create an unintended dump file diff --git a/lib/countly.js b/lib/countly.js index 761ca7a..6cbed26 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -627,6 +627,25 @@ Countly.Bulk = Bulk; return Countly.device_id; }; + /** + * Changes the current device ID according to the device ID type (the preffered method) + * @param {string} newId - new user/device ID to use. Must be a non-empty string value. Invalid values (like null, empty string or undefined) will be rejected + * */ + Countly.set_id = function (newId) { + cc.log(cc.logLevelEnums.INFO, "set_id, Changing the device ID to:[" + newId + "]"); + if (newId == null || newId === "") { + cc.log(cc.logLevelEnums.WARNING, "set_id, The provided device is not a valid ID"); + return; + } + if (Countly.deviceIdType === cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED) { + /*change ID without merge as current ID is Dev supplied, so not first login*/ + Countly.change_id(newId, false); + } else { + /*change ID with merge as current ID is not Dev supplied*/ + Countly.change_id(newId, true); + } + }; + /** * Change current user/device id * @param {string} newId - new user/device ID to use From 4a087cb37eb2ed8e19bfd70cc821339783dfeed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Mon, 4 Nov 2024 16:14:27 +0300 Subject: [PATCH 2/9] Lint fixes --- lib/countly.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/countly.js b/lib/countly.js index 6cbed26..485d8b1 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -631,17 +631,18 @@ Countly.Bulk = Bulk; * Changes the current device ID according to the device ID type (the preffered method) * @param {string} newId - new user/device ID to use. Must be a non-empty string value. Invalid values (like null, empty string or undefined) will be rejected * */ - Countly.set_id = function (newId) { - cc.log(cc.logLevelEnums.INFO, "set_id, Changing the device ID to:[" + newId + "]"); - if (newId == null || newId === "") { + Countly.set_id = function(newId) { + cc.log(cc.logLevelEnums.INFO, `set_id, Changing the device ID to: [${newId}]`); + if (newId === null || newId === "") { cc.log(cc.logLevelEnums.WARNING, "set_id, The provided device is not a valid ID"); return; } if (Countly.deviceIdType === cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED) { - /*change ID without merge as current ID is Dev supplied, so not first login*/ + // change ID without merge as current ID is Dev supplied, so not first login Countly.change_id(newId, false); - } else { - /*change ID with merge as current ID is not Dev supplied*/ + } + else { + // change ID with merge as current ID is not Dev supplied*/ Countly.change_id(newId, true); } }; From c2bce3552e7c9f63c970281243995d18bc030cb5 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Tue, 5 Nov 2024 09:56:24 +0300 Subject: [PATCH 3/9] feat: added device id types --- CHANGELOG.md | 1 + lib/countly.js | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b3c6be..27d09e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## XX.XX.XX - Added a new method `set_id(newDeviceId)` for managing device ID changes according to the device ID Type +- Added `DeviceIdType` enums to be used to evaluate the device ID type. ## 24.10.0 - Default max segmentation value count changed from 30 to 100 diff --git a/lib/countly.js b/lib/countly.js index 485d8b1..c095c03 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -30,6 +30,7 @@ var CountlyStorage = require("./countly-storage"); var Countly = {}; Countly.StorageTypes = cc.storageTypeEnums; +Countly.DeviceIdType = cc.deviceIdTypeEnums; Countly.Bulk = Bulk; (function() { var SDK_VERSION = "24.10.0"; From 3f84fb22da3bba7c4f97093361b992e3ca250d7d Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Tue, 5 Nov 2024 11:06:23 +0300 Subject: [PATCH 4/9] feat: add tests for the set_id and new device id type --- lib/countly.js | 4 +- test/helpers/helper_functions.js | 1 + test/tests_device_id.js | 97 ++++++++++++++++++++++++++++++++ test/tests_device_id_type.js | 7 +++ 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 test/tests_device_id.js diff --git a/lib/countly.js b/lib/countly.js index c095c03..3a38aa4 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -634,11 +634,11 @@ Countly.Bulk = Bulk; * */ Countly.set_id = function(newId) { cc.log(cc.logLevelEnums.INFO, `set_id, Changing the device ID to: [${newId}]`); - if (newId === null || newId === "") { + if (newId === null || newId === "" || newId === undefined) { cc.log(cc.logLevelEnums.WARNING, "set_id, The provided device is not a valid ID"); return; } - if (Countly.deviceIdType === cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED) { + if (Countly.get_device_id_type() === cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED) { // change ID without merge as current ID is Dev supplied, so not first login Countly.change_id(newId, false); } diff --git a/test/helpers/helper_functions.js b/test/helpers/helper_functions.js index d8340f6..996f971 100644 --- a/test/helpers/helper_functions.js +++ b/test/helpers/helper_functions.js @@ -284,4 +284,5 @@ module.exports = { validateUserDetails, viewEventValidator, doesFileStoragePathsExist, + requestBaseParamValidator, }; \ No newline at end of file diff --git a/test/tests_device_id.js b/test/tests_device_id.js new file mode 100644 index 0000000..30abd5f --- /dev/null +++ b/test/tests_device_id.js @@ -0,0 +1,97 @@ +/* eslint-disable no-console */ +var assert = require("assert"); +var Countly = require("../lib/countly"); +var cc = require("../lib/countly-common"); +var hp = require("./helpers/helper_functions"); + +function initMain(deviceId, eraseID) { + Countly.init({ + app_key: "YOUR_APP_KEY", + url: "https://try.count.ly", + device_id: deviceId, + max_events: -1, + // debug: true, + clear_stored_device_id: eraseID, + }); +} +function validateSdkGeneratedId(providedDeviceId) { + assert.ok(providedDeviceId); + assert.equal(providedDeviceId.length, 36); + assert.ok(cc.isUUID(providedDeviceId)); + assert.equal(Countly.get_device_id(), providedDeviceId); + assert.equal(Countly.get_device_id_type(), Countly.DeviceIdType.SDK_GENERATED); +} + +function validateDeveloperSuppliedId(providedDeviceId) { + assert.equal(Countly.get_device_id_type(), Countly.DeviceIdType.DEVELOPER_SUPPLIED); + assert.equal(Countly.get_device_id(), providedDeviceId); +} + +describe("Device ID tests", () => { + beforeEach(async() => { + await hp.clearStorage(); + }); + it("1.set_id with SDK generated to developer supplied", (done) => { + // initialize SDK + initMain(undefined); + validateSdkGeneratedId(Countly.get_device_id()); + var oldId = Countly.get_device_id(); + Countly.set_id("ID"); + validateDeveloperSuppliedId("ID"); + setTimeout(() => { + // validate that merge request is generated + var RQ = hp.readRequestQueue(); + assert.equal(RQ.length, 1); + hp.requestBaseParamValidator(RQ[0]); + assert.equal(RQ[0].old_device_id, oldId); + done(); + }, hp.sWait); + }); + it("2.set_id with developer supplied to developer supplied", (done) => { + // initialize SDK + initMain("ID2"); + validateDeveloperSuppliedId("ID2"); + Countly.set_id("ID"); + validateDeveloperSuppliedId("ID"); + setTimeout(() => { + // validate that no merge request is generated and the existing request is begin session + var RQ = hp.readRequestQueue(); + assert.equal(RQ.length, 1); + hp.sessionRequestValidator(RQ[0]); + done(); + }, hp.sWait); + }); + it("3.set_id with same custom id", (done) => { + // initialize SDK + initMain("ID"); + validateDeveloperSuppliedId("ID"); + Countly.set_id("ID"); + validateDeveloperSuppliedId("ID"); + done(); + }); + it("4.set_id with same sdk generated id", (done) => { + // initialize SDK + initMain(undefined); + var id = Countly.get_device_id(); + validateSdkGeneratedId(id); + Countly.set_id(id); + // so that the type is not converted to developer_supplied + validateSdkGeneratedId(id); + done(); + }); + it("5.set_id with invalid ids", (done) => { + // initialize SDK + initMain(undefined); + var id = Countly.get_device_id(); + validateSdkGeneratedId(id); + Countly.set_id(undefined); + validateSdkGeneratedId(id); + + Countly.set_id(null); + validateSdkGeneratedId(id); + + Countly.set_id(""); + validateSdkGeneratedId(id); + done(); + }); +}); diff --git a/test/tests_device_id_type.js b/test/tests_device_id_type.js index 650f1b5..70336a5 100644 --- a/test/tests_device_id_type.js +++ b/test/tests_device_id_type.js @@ -296,4 +296,11 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); + it("13.Check new DeviceIdType interface is equal to common interface", (done) => { + setTimeout(() => { + assert.equal(Countly.DeviceIdType.DEVELOPER_SUPPLIED, cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); + assert.equal(Countly.DeviceIdType.SDK_GENERATED, cc.deviceIdTypeEnums.SDK_GENERATED); + done(); + }); + }); }); From 544aec51fc17604c827eb944a6f1c7cae2754d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Tue, 5 Nov 2024 13:26:24 +0300 Subject: [PATCH 5/9] Cosmetic Updates --- test/tests_device_id.js | 15 ++++++++++----- test/tests_device_id_type.js | 36 +++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/test/tests_device_id.js b/test/tests_device_id.js index 30abd5f..db719e8 100644 --- a/test/tests_device_id.js +++ b/test/tests_device_id.js @@ -31,7 +31,8 @@ describe("Device ID tests", () => { beforeEach(async() => { await hp.clearStorage(); }); - it("1.set_id with SDK generated to developer supplied", (done) => { + + it("1- set_id with SDK generated to developer supplied", (done) => { // initialize SDK initMain(undefined); validateSdkGeneratedId(Countly.get_device_id()); @@ -47,7 +48,8 @@ describe("Device ID tests", () => { done(); }, hp.sWait); }); - it("2.set_id with developer supplied to developer supplied", (done) => { + + it("2- set_id with developer supplied to developer supplied", (done) => { // initialize SDK initMain("ID2"); validateDeveloperSuppliedId("ID2"); @@ -61,7 +63,8 @@ describe("Device ID tests", () => { done(); }, hp.sWait); }); - it("3.set_id with same custom id", (done) => { + + it("3- set_id with same custom id", (done) => { // initialize SDK initMain("ID"); validateDeveloperSuppliedId("ID"); @@ -69,7 +72,8 @@ describe("Device ID tests", () => { validateDeveloperSuppliedId("ID"); done(); }); - it("4.set_id with same sdk generated id", (done) => { + + it("4- set_id with same sdk generated id", (done) => { // initialize SDK initMain(undefined); var id = Countly.get_device_id(); @@ -79,7 +83,8 @@ describe("Device ID tests", () => { validateSdkGeneratedId(id); done(); }); - it("5.set_id with invalid ids", (done) => { + + it("5- set_id with invalid ids", (done) => { // initialize SDK initMain(undefined); var id = Countly.get_device_id(); diff --git a/test/tests_device_id_type.js b/test/tests_device_id_type.js index 70336a5..4e7c683 100644 --- a/test/tests_device_id_type.js +++ b/test/tests_device_id_type.js @@ -58,7 +58,7 @@ describe("Device ID type tests", () => { beforeEach(async() => { await hp.clearStorage(); }); - it("1.Generated device ID", (done) => { + it("1- Generated device ID", (done) => { // initialize SDK initMain(undefined); Countly.begin_session(); @@ -71,7 +71,8 @@ describe("Device ID type tests", () => { done(); }, hp.sWait); }); - it("2.Developer supplied device ID", (done) => { + + it("2- Developer supplied device ID", (done) => { // initialize SDK initMain("ID"); Countly.begin_session(); @@ -84,7 +85,8 @@ describe("Device ID type tests", () => { done(); }, hp.sWait); }); - it("3.With stored dev ID and no new ID", (done) => { + + it("3- With stored dev ID and no new ID", (done) => { // initialize SDK initMain("ID"); Countly.begin_session(); @@ -105,7 +107,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("4.With stored dev ID and with new ID", (done) => { + + it("4- With stored dev ID and with new ID", (done) => { // initialize SDK initMain("ID"); Countly.begin_session(); @@ -126,7 +129,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("5.With stored generated ID and no new ID", (done) => { + + it("5- With stored generated ID and no new ID", (done) => { // initialize SDK initMain(undefined); Countly.begin_session(); @@ -149,7 +153,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("6.With stored generated ID and with new ID", (done) => { + + it("6- With stored generated ID and with new ID", (done) => { // initialize SDK initMain(undefined); Countly.begin_session(); @@ -172,7 +177,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("7.With stored dev ID and no new ID, flag set", (done) => { + + it("7- With stored dev ID and no new ID, flag set", (done) => { // initialize SDK initMain("ID"); Countly.begin_session(); @@ -194,7 +200,7 @@ describe("Device ID type tests", () => { }, hp.sWait); }); - it("8.With stored dev ID and with new ID, flag set", (done) => { + it("8- With stored dev ID and with new ID, flag set", (done) => { setTimeout(() => { // initialize SDK initMain("ID"); @@ -217,7 +223,8 @@ describe("Device ID type tests", () => { }, hp.lWait); }, hp.lWait); }); - it("9.With stored sdk ID and no new ID, flag set", (done) => { + + it("9- With stored sdk ID and no new ID, flag set", (done) => { // initialize SDK initMain(undefined); Countly.begin_session(); @@ -241,7 +248,7 @@ describe("Device ID type tests", () => { }, hp.sWait); }); - it("10.With stored sdk ID and with new ID, flag set", (done) => { + it("10- With stored sdk ID and with new ID, flag set", (done) => { // initialize SDK initMain(undefined); Countly.begin_session(); @@ -264,7 +271,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("11.Change generated device ID", (done) => { + + it("11- Change generated device ID", (done) => { // initialize SDK initMain(undefined); Countly.change_id("changedID"); @@ -280,7 +288,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("12.Change developer supplied device ID", (done) => { + + it("12- Change developer supplied device ID", (done) => { // initialize SDK initMain("ID"); Countly.change_id("changedID"); @@ -296,7 +305,8 @@ describe("Device ID type tests", () => { }, hp.sWait); }, hp.sWait); }); - it("13.Check new DeviceIdType interface is equal to common interface", (done) => { + + it("13- Check new DeviceIdType interface is equal to common interface", (done) => { setTimeout(() => { assert.equal(Countly.DeviceIdType.DEVELOPER_SUPPLIED, cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED); assert.equal(Countly.DeviceIdType.SDK_GENERATED, cc.deviceIdTypeEnums.SDK_GENERATED); From 2861fc591f58b367f0dc4dafec0d24811bb38983 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray <57103426+arifBurakDemiray@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:28:35 +0300 Subject: [PATCH 6/9] fix: add type checks to the set_id --- lib/countly.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/countly.js b/lib/countly.js index 3a38aa4..43f22ee 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -634,7 +634,7 @@ Countly.Bulk = Bulk; * */ Countly.set_id = function(newId) { cc.log(cc.logLevelEnums.INFO, `set_id, Changing the device ID to: [${newId}]`); - if (newId === null || newId === "" || newId === undefined) { + if (newId === null || newId === undefined || typeof newId === "string" || newId === "") { cc.log(cc.logLevelEnums.WARNING, "set_id, The provided device is not a valid ID"); return; } From 9d031268d6dcd94454a3d3645de2807cef05cf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Fri, 8 Nov 2024 14:11:29 +0300 Subject: [PATCH 7/9] Error Fix my brother forgot to add '!' in the check, lint was fine all tests are working --- lib/countly.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/countly.js b/lib/countly.js index 43f22ee..495faad 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -634,8 +634,8 @@ Countly.Bulk = Bulk; * */ Countly.set_id = function(newId) { cc.log(cc.logLevelEnums.INFO, `set_id, Changing the device ID to: [${newId}]`); - if (newId === null || newId === undefined || typeof newId === "string" || newId === "") { - cc.log(cc.logLevelEnums.WARNING, "set_id, The provided device is not a valid ID"); + if (newId === null || newId === undefined || newId === "" || typeof newId !== "string") { + cc.log(cc.logLevelEnums.WARNING, "set_id, The provided id is not a valid ID"); return; } if (Countly.get_device_id_type() === cc.deviceIdTypeEnums.DEVELOPER_SUPPLIED) { From e0ecbb82dc6beeefd22a504d6f3dfc8949b6012c Mon Sep 17 00:00:00 2001 From: turtledreams <62231246+turtledreams@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:11:29 +0900 Subject: [PATCH 8/9] Proto pollution fix --- lib/countly-bulk-user.js | 5 ++++- lib/countly.js | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/countly-bulk-user.js b/lib/countly-bulk-user.js index 0f45a42..45e3d37 100644 --- a/lib/countly-bulk-user.js +++ b/lib/countly-bulk-user.js @@ -602,7 +602,10 @@ function CountlyBulkUser(conf) { var change_custom_property = function(key, value, mod) { key = cc.truncateSingleValue(key, conf.maxKeyLength, "change_custom_property"); value = cc.truncateSingleValue(value, conf.maxValueSize, "change_custom_property"); - + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + cc.log(cc.logLevelEnums.ERROR, "change_custom_property, Provided key is not allowed."); + return; + } if (!customData[key]) { customData[key] = {}; } diff --git a/lib/countly.js b/lib/countly.js index 495faad..6f8d1cf 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -865,6 +865,10 @@ Countly.Bulk = Bulk; var change_custom_property = function(key, value, mod) { key = cc.truncateSingleValue(key, Countly.maxKeyLength, "change_custom_property", Countly.debug); value = cc.truncateSingleValue(value, Countly.maxValueSize, "change_custom_property", Countly.debug); + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + cc.log(cc.logLevelEnums.ERROR, "change_custom_property, Provided key is not allowed."); + return; + } if (Countly.check_consent("users")) { if (!customData[key]) { From 6ddfd1a0028d667f373407a0c6b143ccfde866c6 Mon Sep 17 00:00:00 2001 From: turtledreams <62231246+turtledreams@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:19:35 +0900 Subject: [PATCH 9/9] Changlog --- CHANGELOG.md | 3 ++- lib/countly-bulk.js | 2 +- lib/countly.js | 2 +- package.json | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27d09e8..d62c898 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ -## XX.XX.XX +## 24.10.1 - Added a new method `set_id(newDeviceId)` for managing device ID changes according to the device ID Type - Added `DeviceIdType` enums to be used to evaluate the device ID type. +- Added reserved keys for user properties ## 24.10.0 - Default max segmentation value count changed from 30 to 100 diff --git a/lib/countly-bulk.js b/lib/countly-bulk.js index a7ecc0e..2670127 100644 --- a/lib/countly-bulk.js +++ b/lib/countly-bulk.js @@ -59,7 +59,7 @@ CountlyBulk.StorageTypes = cc.storageTypeEnums; * }); */ function CountlyBulk(conf) { - var SDK_VERSION = "24.10.0"; + var SDK_VERSION = "24.10.1"; var SDK_NAME = "javascript_native_nodejs_bulk"; var empty_queue_callback = null; diff --git a/lib/countly.js b/lib/countly.js index 6f8d1cf..50d7ad6 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -33,7 +33,7 @@ Countly.StorageTypes = cc.storageTypeEnums; Countly.DeviceIdType = cc.deviceIdTypeEnums; Countly.Bulk = Bulk; (function() { - var SDK_VERSION = "24.10.0"; + var SDK_VERSION = "24.10.1"; var SDK_NAME = "javascript_native_nodejs"; var inited = false; diff --git a/package.json b/package.json index c35b9f7..4b2b870 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "countly-sdk-nodejs", - "version": "24.10.0", + "version": "24.10.1", "description": "Countly NodeJS SDK", "main": "lib/countly.js", "directories": {