Skip to content

Commit da0b778

Browse files
committed
fix: identity management, web push migration
1 parent 0cc05b4 commit da0b778

8 files changed

+75
-44
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@types/jest": "^25.2.1",
2020
"@types/jquery": "^3.3.38",
2121
"@types/node": "^13.13.4",
22+
"@types/sha.js": "^2.4.0",
2223
"@types/webpack": "^5",
2324
"@typescript-eslint/eslint-plugin": "^2.29.0",
2425
"@typescript-eslint/parser": "^2.29.0",
@@ -108,6 +109,7 @@
108109
"homepage": "https://github.com/Leanplum/Leanplum-JavaScript-SDK#readme",
109110
"dependencies": {
110111
"@qiwi/semrel-metabranch": "^3.1.2",
111-
"clevertap-web-sdk": "^1.3.3"
112+
"clevertap-web-sdk": "^1.3.3",
113+
"sha.js": "2.4.9"
112114
}
113115
}

src/LeanplumInternal.ts

+14-18
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export default class LeanplumInternal {
4949
this._events
5050
)
5151
private _pushManager: PushManager = new PushManager(
52-
this._events,
5352
this.createRequest.bind(this)
5453
)
5554
private _webPushOptions: WebPushOptions
@@ -86,19 +85,6 @@ export default class LeanplumInternal {
8685
(host: string) => this.setSocketHost(host))
8786
this._events.on('migrateStateReceived',
8887
(sha: string) => this._migration.verifyState(sha))
89-
90-
this._events.on('webPushSubscribed',
91-
() => {
92-
const serviceWorkerPath = this._webPushOptions?.serviceWorkerUrl
93-
const path = serviceWorkerPath ? { serviceWorkerPath } : {}
94-
this._ct && this._ct.notifications.push({
95-
titleText: '',
96-
bodyText: '',
97-
okButtonText: '',
98-
rejectButtonText: '',
99-
...path,
100-
})
101-
})
10288
}
10389

10490
setApiPath(apiPath: string): void {
@@ -302,15 +288,25 @@ export default class LeanplumInternal {
302288
this._migration.getState((state: MigrationState) => {
303289
if (state === MigrationState.DUPLICATE) {
304290
this._ct = this._migration.initCleverTap()
291+
} else if (state === MigrationState.CLEVERTAP) {
292+
this._ct = this._migration.initCleverTap()
305293

306-
// silently register subscription in CT
294+
// move subscription in CT
307295
this.isWebPushSubscribed().then((isSubscribed) => {
308296
if (isSubscribed) {
309-
this._events.emit('webPushSubscribed')
297+
this._pushManager.unsubscribeUser()
298+
299+
const serviceWorkerPath = this._webPushOptions?.serviceWorkerUrl
300+
const path = serviceWorkerPath ? { serviceWorkerPath } : {}
301+
this._ct && this._ct.notifications.push({
302+
titleText: '',
303+
bodyText: '',
304+
okButtonText: '',
305+
rejectButtonText: '',
306+
...path,
307+
})
310308
}
311309
})
312-
} else if (state === MigrationState.CLEVERTAP) {
313-
this._ct = this._migration.initCleverTap()
314310

315311
Object.values(Constants.DEFAULT_KEYS)
316312
.filter(key => ![

src/MigrationManager.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CreateRequestFunction, MigrationState } from './types/internal'
33
import StorageManager from './StorageManager'
44
import Constants from './Constants'
55
import ArgsBuilder from './ArgsBuilder'
6+
import shajs from 'sha.js'
67

78
type Region = 'eu1' | 'in1' | 'sg1' | 'us1' | 'sk1';
89

@@ -107,6 +108,11 @@ export default class MigrationManager {
107108

108109
const argsDict = args?.buildDict() || {}
109110

111+
const userId = argsDict[Constants.PARAMS.USER_ID]
112+
if (userId) {
113+
this.identity.setUserId(userId)
114+
}
115+
110116
switch (action) {
111117
case Constants.METHODS.START:
112118
if (!this.identity.isAnonymous) {
@@ -143,7 +149,8 @@ export default class MigrationManager {
143149
)
144150

145151
if (userId) {
146-
Object.assign(attrs, { Identity: userId })
152+
this.identity.setUserId(userId)
153+
Object.assign(attrs, this.identity.profile)
147154
clevertap.onUserLogin.push({ Site: attrs })
148155
} else {
149156
clevertap.profile.push({ Site: attrs })
@@ -271,7 +278,9 @@ export class IdentityManager {
271278

272279
public get cleverTapID(): string {
273280
if (this.userId !== this.anonymousLoginUserId && !this.isAnonymous) {
274-
return `${this.deviceId}_${this.userId}`
281+
const sha = this.sha256(this.userId)
282+
283+
return `${this.deviceId}_${sha}`
275284
}
276285

277286
return this.deviceId
@@ -284,4 +293,10 @@ export class IdentityManager {
284293
public get isAnonymous(): boolean {
285294
return this.userId === this.deviceId
286295
}
296+
297+
private sha256(s: string): string {
298+
const sha = new shajs.sha256().update(s).digest('hex')
299+
300+
return sha.substring(0, 10)
301+
}
287302
}

src/PushManager.ts

-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717

1818
import ArgsBuilder from './ArgsBuilder'
19-
import EventEmitter from './EventEmitter'
2019
import Constants from './Constants'
2120
import StorageManager from './StorageManager'
2221
import { CreateRequestFunction } from './types/internal'
@@ -35,7 +34,6 @@ export default class PushManager {
3534
}
3635

3736
public constructor(
38-
private events: EventEmitter,
3937
private createRequest: CreateRequestFunction
4038
) { }
4139

@@ -200,8 +198,6 @@ export default class PushManager {
200198
) as string
201199

202200
if (existingSubscriptionString !== preparedSubscriptionString) {
203-
this.events.emit('webPushSubscribed')
204-
205201
StorageManager.save(
206202
Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION,
207203
preparedSubscriptionString

test/specs/LeanplumIntegration.test.ts

+1-15
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,6 @@ describe('Integration Tests', () => {
9494
})
9595
})
9696

97-
it('pushes notification token when registering with LP', (done) => {
98-
mockNextResponse(migrationResponses.DUPLICATE)
99-
mockNextResponse(startResponse)
100-
101-
lp.start(async () => {
102-
await lp.registerForWebPush('/sw.test.js')
103-
104-
// expect ct push to be registered, too
105-
expect(clevertap.notifications.push).toHaveBeenCalled()
106-
107-
done()
108-
})
109-
})
110-
11197
it('pushes previously registered notification token', (done) => {
11298
mockNextResponse(migrationResponses.LP)
11399
mockNextResponse(startResponse)
@@ -129,7 +115,7 @@ describe('Integration Tests', () => {
129115
sha256: 'changed-sha' // triggers config refresh
130116
}
131117
})
132-
mockNextResponse(migrationResponses.DUPLICATE)
118+
mockNextResponse(migrationResponses.CLEVERTAP)
133119
mockNextResponse(startResponse)
134120
lp.track('some-event')
135121
lpRequestMock.events.emit('migrateStateReceived', 'changed-sha');

test/specs/MigrationManager.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,29 @@ describe(MigrationManager, () => {
351351
}
352352
})
353353
})
354+
355+
it(`sends onUserLogin on start with userId parameter`, () => {
356+
localStorage.setItem('__leanplum_device_id', 'anon1')
357+
localStorage.setItem('__leanplum_user_id', 'anon1')
358+
manager = new MigrationManager(createRequest)
359+
360+
setMigrationState(DUPLICATE)
361+
362+
jest.spyOn(clevertap.onUserLogin, 'push')
363+
364+
const args = new ArgsBuilder()
365+
args.add('userId', 'john')
366+
367+
manager.duplicateRequest('start', args, {})
368+
369+
expect(clevertap.onUserLogin.push).toHaveBeenCalledTimes(1)
370+
expect(clevertap.onUserLogin.push).toHaveBeenCalledWith({
371+
Site: {
372+
'Identity': 'john',
373+
'tz': expect.any(String)
374+
}
375+
})
376+
})
354377
})
355378

356379
function setMigrationState(state: Object): void {

test/specs/PushManager.test.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import Constants from '../../src/Constants'
2-
import EventEmitter from '../../src/EventEmitter'
32
import PushManager from '../../src/PushManager'
43

54
describe(PushManager, () => {
@@ -8,8 +7,7 @@ describe(PushManager, () => {
87
const createRequestSpy: jest.Mock<() => void> = jest.fn()
98

109
beforeEach(() => {
11-
const events = new EventEmitter()
12-
pushManager = new PushManager(events, createRequestSpy)
10+
pushManager = new PushManager(createRequestSpy)
1311
windowMock = jest.spyOn(globalThis, 'window', 'get')
1412
})
1513

yarn.lock

+16-1
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,13 @@
13891389
dependencies:
13901390
"@types/node" "*"
13911391

1392+
"@types/sha.js@^2.4.0":
1393+
version "2.4.0"
1394+
resolved "https://registry.yarnpkg.com/@types/sha.js/-/sha.js-2.4.0.tgz#bce682ef860b40f419d024fa08600c3b8d24bb01"
1395+
integrity sha512-amxKgPy6WJTKuw8mpUwjX2BSxuBtBmZfRwIUDIuPJKNwGN8CWDli8JTg5ONTWOtcTkHIstvT7oAhhYXqEjStHQ==
1396+
dependencies:
1397+
"@types/node" "*"
1398+
13921399
"@types/sizzle@*":
13931400
version "2.3.2"
13941401
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
@@ -6568,7 +6575,7 @@ rxjs@^6.5.3:
65686575
dependencies:
65696576
tslib "^1.9.0"
65706577

6571-
safe-buffer@^5.1.0:
6578+
safe-buffer@^5.0.1, safe-buffer@^5.1.0:
65726579
version "5.2.1"
65736580
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
65746581
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -6721,6 +6728,14 @@ set-value@^2.0.0, set-value@^2.0.1:
67216728
is-plain-object "^2.0.3"
67226729
split-string "^3.0.1"
67236730

6731+
6732+
version "2.4.9"
6733+
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d"
6734+
integrity sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==
6735+
dependencies:
6736+
inherits "^2.0.1"
6737+
safe-buffer "^5.0.1"
6738+
67246739
shallow-clone@^3.0.0:
67256740
version "3.0.1"
67266741
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"

0 commit comments

Comments
 (0)