Skip to content

Commit c477466

Browse files
committed
feat: added DisabledVault to disable id-cache when noFunctional is set
1 parent 645f46a commit c477466

4 files changed

Lines changed: 152 additions & 5 deletions

File tree

src/mp-instance.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import KitBlocker from './kitBlocking';
3737
import ConfigAPIClient, { IKitConfigs } from './configAPIClient';
3838
import IdentityAPIClient from './identityApiClient';
3939
import { isFunction, parseConfig } from './utils';
40-
import { LocalStorageVault } from './vault';
40+
import { DisabledVault, LocalStorageVault } from './vault';
4141
import { removeExpiredIdentityCacheDates } from './identity-utils';
4242
import IntegrationCapture from './integrationCapture';
4343
import { IPreInit, processReadyQueue } from './pre-init-utils';
@@ -1523,9 +1523,12 @@ function createKitBlocker(config, mpInstance) {
15231523
}
15241524

15251525
function createIdentityCache(mpInstance) {
1526-
return new LocalStorageVault(`${mpInstance._Store.storageName}-id-cache`, {
1527-
logger: mpInstance.Logger,
1528-
});
1526+
const cacheKey = `${mpInstance._Store.storageName}-id-cache`;
1527+
if (mpInstance._Store.getNoFunctional()) {
1528+
console.log('createIdentityCache: noFunctional is true');
1529+
return new DisabledVault(cacheKey, { logger: mpInstance.Logger });
1530+
}
1531+
return new LocalStorageVault(cacheKey, { logger: mpInstance.Logger });
15291532
}
15301533

15311534
function runPreConfigFetchInitialization(mpInstance, apiKey, config) {

src/vault.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,20 @@ export class SessionStorageVault<StorableItem> extends BaseVault<StorableItem> {
102102
constructor(storageKey: string, options?: IVaultOptions) {
103103
super(storageKey, window.sessionStorage, options);
104104
}
105+
}
106+
107+
// DisabledVault is used when persistence is disabled by privacy flags.
108+
export class DisabledVault<StorableItem> extends BaseVault<StorableItem> {
109+
constructor(storageKey: string, options?: IVaultOptions) {
110+
super(storageKey, window.localStorage, options);
111+
this.contents = null;
112+
}
113+
114+
public store(_item: StorableItem): void {
115+
this.contents = null;
116+
}
117+
118+
public retrieve(): StorableItem | null {
119+
return this.contents;
120+
}
105121
}

test/src/tests-identity.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,36 @@ describe('identity', function() {
642642
});
643643
});
644644

645+
describe('privacy flags', function() {
646+
beforeEach(function() {
647+
mParticle._resetForTests(MPConfig);
648+
mParticle.config.flags.cacheIdentity = 'True';
649+
localStorage.clear();
650+
});
651+
652+
describe('#createIdentityCache', function() {
653+
it('should use LocalStorageVault when noFunctional is false by default', async () => {
654+
mParticle.init(apiKey, window.mParticle.config);
655+
await waitForCondition(hasIdentifyReturned);
656+
expect(localStorage.getItem('mprtcl-v4_abcdef-id-cache')).to.be.ok;
657+
});
658+
659+
it('should use DisabledVault when noFunctional is true', async () => {
660+
mParticle.config.noFunctional = true;
661+
mParticle.init(apiKey, window.mParticle.config);
662+
await waitForCondition(hasIdentifyReturned);
663+
expect(localStorage.getItem('mprtcl-v4_abcdef-id-cache')).not.to.be.ok;
664+
});
665+
666+
it('should use LocalStorageVault when noFunctional is false', async () => {
667+
mParticle.config.noFunctional = false;
668+
mParticle.init(apiKey, window.mParticle.config);
669+
await waitForCondition(hasIdentifyReturned);
670+
expect(localStorage.getItem('mprtcl-v4_abcdef-id-cache')).to.be.ok;
671+
});
672+
});
673+
});
674+
645675
// https://go.mparticle.com/work/SQDSDKS-6849
646676
// This test passes with no issue when it is run on its own, but fails when tests-forwarders.js are also ran.
647677
it('should respect consent rules on consent-change', async () => {

test/src/vault.spec.ts

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Batch } from '@mparticle/event-models';
22
import { expect } from 'chai';
33
import { Dictionary } from '../../src/utils';
4-
import { SessionStorageVault, LocalStorageVault } from '../../src/vault';
4+
import { SessionStorageVault, LocalStorageVault, DisabledVault } from '../../src/vault';
55

66
const testObject: Dictionary<Dictionary<string>> = {
77
foo: { foo: 'bar', buzz: 'bazz' },
@@ -419,4 +419,102 @@ describe('Vault', () => {
419419
);
420420
});
421421
});
422+
423+
describe('DisabledVault', () => {
424+
afterEach(() => {
425+
window.localStorage.clear();
426+
});
427+
428+
describe('#store', () => {
429+
it('should NOT write to localStorage', () => {
430+
const storageKey = 'test-disabled-store-empty';
431+
const vault = new DisabledVault<Dictionary<Dictionary<string>>>(
432+
storageKey,
433+
);
434+
435+
vault.store(testObject);
436+
437+
expect(vault.contents).to.equal(null);
438+
expect(window.localStorage.getItem(storageKey)).to.equal(null);
439+
});
440+
441+
it('should NOT overwrite existing localStorage value and keep contents null', () => {
442+
const storageKey = 'test-disabled-store-existing';
443+
window.localStorage.setItem(
444+
storageKey,
445+
JSON.stringify(testObject),
446+
);
447+
448+
const vault = new DisabledVault<Dictionary<Dictionary<string>>>(
449+
storageKey,
450+
);
451+
452+
vault.store({ pinky: { narf: 'poit' } });
453+
454+
expect(vault.contents).to.equal(null);
455+
expect(window.localStorage.getItem(storageKey)).to.equal(
456+
JSON.stringify(testObject),
457+
);
458+
});
459+
});
460+
461+
describe('#retrieve', () => {
462+
it('should return null when nothing is stored', () => {
463+
const storageKey = 'test-disabled-retrieve-empty';
464+
const vault = new DisabledVault<Dictionary<Dictionary<string>>>(
465+
storageKey,
466+
);
467+
const retrievedItem = vault.retrieve();
468+
expect(retrievedItem).to.equal(null);
469+
});
470+
471+
it('should return null even if localStorage has a value', () => {
472+
const storageKey = 'test-disabled-retrieve-existing';
473+
window.localStorage.setItem(
474+
storageKey,
475+
JSON.stringify(testObject),
476+
);
477+
478+
const vault = new DisabledVault<Dictionary<Dictionary<string>>>(
479+
storageKey,
480+
);
481+
const retrievedItem = vault.retrieve();
482+
expect(retrievedItem).to.equal(null);
483+
expect(window.localStorage.getItem(storageKey)).to.equal(
484+
JSON.stringify(testObject),
485+
);
486+
});
487+
});
488+
489+
describe('#purge', () => {
490+
it('should keep contents null when purging', () => {
491+
const storageKey = 'test-disabled-purge-existing';
492+
window.localStorage.setItem(
493+
storageKey,
494+
JSON.stringify(testObject),
495+
);
496+
497+
const vault = new DisabledVault<Dictionary<Dictionary<string>>>(
498+
storageKey,
499+
);
500+
501+
vault.purge();
502+
503+
expect(vault.contents).to.equal(null);
504+
expect(window.localStorage.getItem(storageKey)).to.equal(null);
505+
});
506+
507+
it('should keep contents null when purging an empty key', () => {
508+
const storageKey = 'test-disabled-purge-empty';
509+
const vault = new DisabledVault<Dictionary<Dictionary<string>>>(
510+
storageKey,
511+
);
512+
513+
vault.purge();
514+
console.log(window.localStorage.getItem(storageKey));
515+
expect(vault.contents).to.equal(null);
516+
expect(window.localStorage.getItem(storageKey)).to.equal(null);
517+
});
518+
});
519+
});
422520
});

0 commit comments

Comments
 (0)