Skip to content

Commit 8302d87

Browse files
committed
move v3 decoding into main lib
1 parent 43af42d commit 8302d87

File tree

3 files changed

+46
-79
lines changed

3 files changed

+46
-79
lines changed

src/index.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@ import { setCookie, getCookie, getAnalyticsCookie, generateId } from './cookie.j
33
import { sendEvent } from './http.js';
44
import { version } from '../package.json';
55

6+
function decodeV3Cookie(value) {
7+
if (value && value.startsWith('RS_ENC_v3_')) {
8+
const encoded = value.replace('RS_ENC_v3_', '');
9+
try {
10+
return JSON.parse(atob(encoded));
11+
} catch (e) {
12+
return null;
13+
}
14+
}
15+
return value;
16+
}
17+
618
// Define TinyTag class
719
function TinyTag() {
820
this.queue = new EventQueue();
@@ -135,7 +147,7 @@ TinyTag.prototype.group = function (groupId, traits = {}) {
135147
};
136148

137149
TinyTag.prototype.getAnonymousId = function () {
138-
let anonId = getAnalyticsCookie('anonymous_id', 'anonymousId');
150+
let anonId = decodeV3Cookie(getAnalyticsCookie('anonymous_id', 'anonymousId'));
139151
if (!anonId) {
140152
anonId = generateId();
141153
setCookie('anonymousId', anonId);
@@ -144,11 +156,11 @@ TinyTag.prototype.getAnonymousId = function () {
144156
};
145157

146158
TinyTag.prototype.getUserId = function () {
147-
return getAnalyticsCookie('user_id', 'userId');
159+
return decodeV3Cookie(getAnalyticsCookie('user_id', 'userId'));
148160
};
149161

150162
TinyTag.prototype.getTraits = function () {
151-
const traitsCookie = getAnalyticsCookie('trait', 'traits');
163+
const traitsCookie = decodeV3Cookie(getAnalyticsCookie('trait', 'traits'));
152164
return traitsCookie ? JSON.parse(traitsCookie) : {};
153165
};
154166

src/rudder-compat.js

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,36 @@ import { getCookie } from './cookie.js'; // Reuse TinyTag's getCookie
66
// RudderStack v1 decryption key (placeholder, needs actual key)
77
const V1_ENCRYPTION_KEY = 'Rudder'; // Replace with real key from RudderStack
88

9-
// Decode v3 encoded cookie (base64 JSON)
10-
function decodeV3Cookie(value) {
11-
if (value && value.startsWith('RS_ENC_v3_')) {
12-
const encoded = value.replace('RS_ENC_v3_', '');
13-
try {
14-
return JSON.parse(atob(encoded));
15-
} catch (e) {
16-
return null; // Invalid encoding
17-
}
18-
}
19-
return value; // Not v3, return as-is
20-
}
21-
22-
// Decrypt v1 encrypted cookie
239
function decryptV1Cookie(value) {
2410
if (value && !value.startsWith('RS_ENC_v3_')) {
2511
try {
2612
const bytes = AES.decrypt(value, V1_ENCRYPTION_KEY);
2713
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
28-
return decrypted || value; // Return original if decryption fails or is empty
14+
return decrypted || value;
2915
} catch (e) {
30-
return value; // Return original on exception
16+
return value;
3117
}
3218
}
33-
return value; // Not v3 or encrypted, return as-is
19+
return value;
3420
}
35-
36-
// Enhance window.tt methods with RudderStack compatibility
37-
const originalGetUserId = window.tt.getUserId;
38-
window.tt.getUserId = function () {
39-
const value = getCookie('rl_user_id');
40-
return decodeV3Cookie(decryptV1Cookie(value)) || originalGetUserId();
41-
};
42-
43-
const originalGetAnonymousId = window.tt.getAnonymousId;
44-
window.tt.getAnonymousId = function () {
45-
const value = getCookie('rl_anonymous_id');
46-
return decodeV3Cookie(decryptV1Cookie(value)) || originalGetAnonymousId();
47-
};
48-
49-
const originalGetTraits = window.tt.getTraits;
50-
window.tt.getTraits = function () {
51-
const value = getCookie('rl_trait');
52-
const decoded = decodeV3Cookie(decryptV1Cookie(value));
53-
return decoded ? JSON.parse(decoded) : originalGetTraits();
54-
};
55-
56-
// Export for testing (optional, not used in IIFE)
57-
export { decodeV3Cookie, decryptV1Cookie };
21+
22+
const originalGetUserId = window.tt.getUserId;
23+
window.tt.getUserId = function () {
24+
const value = getCookie('rl_user_id');
25+
return decryptV1Cookie(value) || originalGetUserId();
26+
};
27+
28+
const originalGetAnonymousId = window.tt.getAnonymousId;
29+
window.tt.getAnonymousId = function () {
30+
const value = getCookie('rl_anonymous_id');
31+
return decryptV1Cookie(value) || originalGetAnonymousId();
32+
};
33+
34+
const originalGetTraits = window.tt.getTraits;
35+
window.tt.getTraits = function () {
36+
const value = getCookie('rl_trait');
37+
const decoded = decryptV1Cookie(value);
38+
return decoded ? JSON.parse(decoded) : originalGetTraits();
39+
};
40+
41+
export { decryptV1Cookie };

tests/rudder-compat.test.js

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,11 @@ describe('RudderStack Compatibility', () => {
1313
});
1414
});
1515

16-
test('decodeV3Cookie decodes base64 v3 RudderStack cookie', () => {
17-
const v3Value = 'RS_ENC_v3_' + btoa(JSON.stringify('user123'));
18-
setCookie('rl_user_id', v3Value);
19-
expect(decodeV3Cookie(getCookie('rl_user_id'))).toBe('user123');
20-
});
21-
22-
test('decodeV3Cookie returns original value if not v3 format', () => {
23-
setCookie('rl_user_id', 'plain-value');
24-
expect(decodeV3Cookie(getCookie('rl_user_id'))).toBe('plain-value');
25-
});
26-
27-
test('decryptV1Cookie decrypts v1 RudderStack cookie', () => {
28-
const plainValue = 'anon123asdasdasdlskdjasdlkajdalskdjasldsdl';
16+
test('window.tt.getUserId reads v1 encrypted cookie', () => {
17+
const plainValue = 'user123';
2918
const encrypted = CryptoJS.AES.encrypt(plainValue, 'Rudder').toString();
30-
expect(decryptV1Cookie(encrypted)).toBe(plainValue); // Direct test
31-
});
32-
33-
test('decryptV1Cookie returns original value if not encrypted', () => {
34-
setCookie('rl_anonymous_id', 'plain-value');
35-
expect(decryptV1Cookie(getCookie('rl_anonymous_id'))).toBe('plain-value');
36-
});
37-
38-
test('window.tt.getUserId reads v3 encoded cookie', () => {
39-
const v3Value = 'RS_ENC_v3_' + btoa(JSON.stringify('user123'));
40-
setCookie('rl_user_id', v3Value);
41-
expect(window.tt.getUserId()).toBe('user123');
19+
setCookie('rl_user_id', encrypted);
20+
expect(window.tt.getUserId()).toBe(plainValue);
4221
});
4322

4423
test('window.tt.getAnonymousId reads v1 encrypted cookie', () => {
@@ -48,18 +27,10 @@ describe('RudderStack Compatibility', () => {
4827
expect(window.tt.getAnonymousId()).toBe(plainValue);
4928
});
5029

51-
test('window.tt.getTraits reads v3 encoded traits', () => {
30+
test('window.tt.getTraits reads v1 encrypted traits', () => {
5231
const traits = { email: '[email protected]' };
53-
const v3Value = 'RS_ENC_v3_' + btoa(JSON.stringify(JSON.stringify(traits)));
54-
setCookie('rl_trait', v3Value);
32+
const encrypted = CryptoJS.AES.encrypt(JSON.stringify(traits), 'Rudder').toString();
33+
setCookie('rl_trait', encrypted);
5534
expect(window.tt.getTraits()).toEqual(traits);
5635
});
57-
58-
test('decryptV1Cookie decrypts v1 RudderStack cookie', () => {
59-
const plainValue = 'anon123asdasdasdlskdjasdlkajdalskdjasldsdl';
60-
const encrypted = CryptoJS.AES.encrypt(plainValue, 'Rudder').toString();
61-
const decrypted = decryptV1Cookie(encrypted);
62-
console.log('Encrypted:', encrypted, 'Decrypted:', decrypted);
63-
expect(decrypted).toBe(plainValue);
64-
});
6536
});

0 commit comments

Comments
 (0)