Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set ID method #501

Merged
merged 1 commit into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 24.4.1
- Added types for the SDK
- Added a new method `set_id(newDeviceId)` for managing device id changes according to the device ID Type

## 24.4.0
! Minor breaking change ! For implementations using `salt` the browser compatability is tied to SubtleCrypto's `digest` method support
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/bridge_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function initMain(name, version) {
}

const SDK_NAME = "javascript_native_web";
const SDK_VERSION = "24.4.0";
const SDK_VERSION = "24.4.1";

// tests
describe("Bridged SDK Utilities Tests", () => {
Expand Down
66 changes: 65 additions & 1 deletion cypress/integration/device_id_change.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ describe("Device ID change tests ", ()=>{
});
});
});
it("Check init time temp mode with set_id", () => {
hp.haltAndClearStorage(() => {
initMain(true); // init in offline mode
testDeviceIdInReqs(() => {
Countly.set_id("new ID");
});
});
});

// ========================================
// default init configuration tests
Expand Down Expand Up @@ -209,4 +217,60 @@ describe("Device ID change tests ", ()=>{
});
});
});
});
});

describe("Set ID change tests ", () => {
it("set_id should be non merge as there was dev provided id", () => {
hp.haltAndClearStorage(() => {
Countly.init({
app_key: "YOUR_APP_KEY",
url: "https://your.domain.count.ly",
test_mode: true,
debug: true,
device_id: "old ID"
});
Countly.add_event(eventObj("1")); // record an event.
cy.wait(500); // wait for the request to be sent
cy.fetch_local_request_queue().then((eq) => {
expect(eq[0].device_id).to.equal("old ID");
Countly.set_id("new ID");
Countly.add_event(eventObj("2")); // record another event
cy.wait(500); // wait for the request to be sent
cy.fetch_local_request_queue().then((eq2) => {
expect(eq2.length).to.equal(3); // no merge request
expect(eq2[0].device_id).to.equal("old ID");
expect(eq2[0].events).to.contains("\"key\":\"1\"");
expect(eq2[1].device_id).to.equal("new ID");
expect(eq2[1].begin_session).to.equal(1);
expect(eq2[2].device_id).to.equal("new ID");
expect(eq2[2].events).to.contains("\"key\":\"2\"");
});
});
});
});
it("set_id should be merge as there was sdk generated id", () => {
hp.haltAndClearStorage(() => {
initMain(false); // init normally
Countly.add_event(eventObj("1")); // record an event.
cy.wait(500); // wait for the request to be sent
let generatedID;
cy.fetch_local_request_queue().then((eq) => {
cy.log(eq);
generatedID = eq[0].device_id; // get the new id from first item in the queue
Countly.set_id("new ID");
Countly.add_event(eventObj("2")); // record another event
cy.wait(500); // wait for the request to be sent
cy.fetch_local_request_queue().then((eq2) => {
cy.log(eq2);
expect(eq2.length).to.equal(3); // merge request
expect(eq2[0].device_id).to.equal(generatedID);
expect(eq2[0].events).to.contains("\"key\":\"1\"");
expect(eq2[1].device_id).to.equal("new ID");
expect(eq2[1].old_device_id).to.equal(generatedID);
expect(eq2[2].device_id).to.equal("new ID");
expect(eq2[2].events).to.contains("\"key\":\"2\"");
});
});
});
});
});
8 changes: 7 additions & 1 deletion lib/countly.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,18 @@ declare module "countly-sdk-web" {
function end_session(sec: number, force: boolean): void;

/**
* Change current user/device id
* Change current user/device id (use set_id instead if you are not sure about the merge operation)
* @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
* @param {boolean} merge - move data from old ID to new ID on server
*/
function change_id(newId: string, merge: boolean): void;

/**
* 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
*/
function set_id(newId: string): void;

/**
* Report custom event
* @param {Object} event - Countly {@link Event} object
Expand Down
104 changes: 61 additions & 43 deletions lib/countly.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@
statusCode: "cly_hc_status_code",
errorMessage: "cly_hc_error_message"
});
var SDK_VERSION = "24.4.0";
var SDK_VERSION = "24.4.1";
var SDK_NAME = "javascript_native_web";

// Using this on document.referrer would return an array with 17 elements in it. The 12th element (array[11]) would be the path we are looking for. Others would be things like password and such (use https://regex101.com/ to check more)
Expand Down Expand Up @@ -1752,17 +1752,33 @@
};

/**
* Change current user/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
* */
this.set_id = function (newId) {
log(logLevelEnums.INFO, "set_id, Changing the device ID to:[" + newId + "]");
if (newId == null || newId === "") {
log(logLevelEnums.WARNING, "set_id, The provided device is not a valid ID");
return;
}
if (deviceIdType === DeviceIdTypeInternalEnums.DEVELOPER_SUPPLIED) {
/*change ID without merge as current ID is Dev supplied, so not first login*/
this.change_id(newId, false);
} else {
/*change ID with merge as current ID is not Dev supplied*/
this.change_id(newId, true);
}
};

/**
* Change current user/device id (use set_id instead if you are not sure about the merge operation)
* @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
* @param {boolean} merge - move data from old ID to new ID on server
* */
this.change_id = function (newId, merge) {
log(logLevelEnums.INFO, "change_id, Changing the ID");
if (merge) {
log(logLevelEnums.INFO, "change_id, Will merge the IDs");
}
log(logLevelEnums.INFO, "change_id, Changing the device ID to: [" + newId + "] with merge:[" + merge + "]");
if (!newId || typeof newId !== "string" || newId.length === 0) {
log(logLevelEnums.ERROR, "change_id, The provided ID: [" + newId + "] is not a valid ID");
log(logLevelEnums.WARNING, "change_id, The provided device ID is not a valid ID");
return;
}
if (offlineMode) {
Expand All @@ -1772,41 +1788,43 @@
}
// eqeq is used here since we want to catch number to string checks too. type conversion might happen at a new init
// eslint-disable-next-line eqeqeq
if (this.device_id != newId) {
if (!merge) {
// process async queue before sending events
processAsyncQueue();
// empty event queue
sendEventsForced();
// end current session
this.end_session(null, true);
// clear timed events
timedEvents = {};
// clear all consents
this.remove_consent_internal(Countly.features, false);
}
var oldId = this.device_id;
this.device_id = newId;
self.device_id = this.device_id;
deviceIdType = DeviceIdTypeInternalEnums.DEVELOPER_SUPPLIED;
setValueInStorage("cly_id", this.device_id);
setValueInStorage("cly_id_type", DeviceIdTypeInternalEnums.DEVELOPER_SUPPLIED);
log(logLevelEnums.INFO, "change_id, Changing ID from:[" + oldId + "] to [" + newId + "]");
if (merge) {
// no consent check here since 21.11.0
toRequestQueue({
old_device_id: oldId
});
} else {
// start new session for new ID
this.begin_session(!autoExtend, true);
}
// if init time remote config was enabled with a callback function, remove currently stored remote configs and fetch remote config again
if (this.remote_config) {
remoteConfigs = {};
setValueInStorage("cly_remote_configs", remoteConfigs);
this.fetch_remote_config(this.remote_config);
}
if (this.device_id == newId) {
log(logLevelEnums.DEBUG, "change_id, Provided device ID is equal to the current device ID. Aborting.");
return;
}
if (!merge) {
// process async queue before sending events
processAsyncQueue();
// empty event queue
sendEventsForced();
// end current session
this.end_session(null, true);
// clear timed events
timedEvents = {};
// clear all consents
this.remove_consent_internal(Countly.features, false);
}
var oldId = this.device_id;
this.device_id = newId;
self.device_id = this.device_id;
deviceIdType = DeviceIdTypeInternalEnums.DEVELOPER_SUPPLIED;
setValueInStorage("cly_id", this.device_id);
setValueInStorage("cly_id_type", DeviceIdTypeInternalEnums.DEVELOPER_SUPPLIED);
log(logLevelEnums.INFO, "change_id, Changing ID from:[" + oldId + "] to [" + newId + "]");
if (merge) {
// no consent check here since 21.11.0
toRequestQueue({
old_device_id: oldId
});
} else {
// start new session for new ID TODO: check this when no session tracking is enabled
this.begin_session(!autoExtend, true);
}
// if init time remote config was enabled with a callback function, remove currently stored remote configs and fetch remote config again
if (this.remote_config) {
remoteConfigs = {};
setValueInStorage("cly_remote_configs", remoteConfigs);
this.fetch_remote_config(this.remote_config);
}
};

Expand Down Expand Up @@ -5254,14 +5272,14 @@
isResponseValidBroad: isResponseValidBroad,
secureRandom: secureRandom,
log: log,
calculateChecksum: calculateChecksum,
checkIfLoggingIsOn: checkIfLoggingIsOn,
getMetrics: getMetrics,
getUA: getUA,
prepareRequest: prepareRequest,
generateUUID: generateUUID,
sendEventsForced: sendEventsForced,
isUUID: isUUID,
calculateChecksum: calculateChecksum,
isReferrerUsable: isReferrerUsable,
getId: getStoredIdOrGenerateId,
heartBeat: heartBeat,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "countly-sdk-web",
"version": "24.4.0",
"version": "24.4.1",
"description": "Countly Web SDK",
"main": "lib/countly.js",
"types": "lib/countly.d.ts",
Expand Down
Loading