Skip to content

Commit 8187d72

Browse files
authored
feat: added DisabledVault to disable id-cache when noFunctional is set (#1072)
1 parent 71c891c commit 8187d72

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed

src/mp-instance.ts

Lines changed: 6 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, valueof } 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';
@@ -1534,9 +1534,11 @@ function createKitBlocker(config, mpInstance) {
15341534
}
15351535

15361536
function createIdentityCache(mpInstance) {
1537-
return new LocalStorageVault(`${mpInstance._Store.storageName}-id-cache`, {
1538-
logger: mpInstance.Logger,
1539-
});
1537+
const cacheKey = `${mpInstance._Store.storageName}-id-cache`;
1538+
if (mpInstance._Store.getPrivacyFlag('IdentityCache')) {
1539+
return new DisabledVault(cacheKey, { logger: mpInstance.Logger });
1540+
}
1541+
return new LocalStorageVault(cacheKey, { logger: mpInstance.Logger });
15401542
}
15411543

15421544
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 save id cache to local storage 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 NOT save id cache to local storage when noFunctional is true', async () => {
660+
mParticle.config.launcherOptions = { 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 save id cache to local storage when noFunctional is false', async () => {
667+
mParticle.config.launcherOptions = { 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: 73 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,76 @@ 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<string>(storageKey);
432+
433+
vault.store('testString');
434+
435+
expect(vault.contents).to.equal(null);
436+
expect(window.localStorage.getItem(storageKey)).to.equal(null);
437+
});
438+
439+
it('should NOT overwrite existing localStorage value and keep contents null', () => {
440+
const storageKey = 'test-disabled-store-existing';
441+
window.localStorage.setItem(storageKey, 'existingItem');
442+
443+
const vault = new DisabledVault<string>(storageKey);
444+
445+
vault.store('newValue');
446+
447+
expect(vault.contents).to.equal(null);
448+
expect(window.localStorage.getItem(storageKey)).to.equal('existingItem');
449+
});
450+
});
451+
452+
describe('#retrieve', () => {
453+
it('should return null when nothing is stored', () => {
454+
const storageKey = 'test-disabled-retrieve-empty';
455+
const vault = new DisabledVault<string>(storageKey);
456+
const retrievedItem = vault.retrieve();
457+
expect(retrievedItem).to.equal(null);
458+
});
459+
460+
it('should return null even if localStorage has a value', () => {
461+
const storageKey = 'test-disabled-retrieve-existing';
462+
window.localStorage.setItem(storageKey, 'existingItem');
463+
464+
const vault = new DisabledVault<string>(storageKey);
465+
const retrievedItem = vault.retrieve();
466+
expect(retrievedItem).to.equal(null);
467+
expect(window.localStorage.getItem(storageKey)).to.equal('existingItem');
468+
});
469+
});
470+
471+
describe('#purge', () => {
472+
it('should keep contents null when purging', () => {
473+
const storageKey = 'test-disabled-purge-existing';
474+
window.localStorage.setItem(storageKey, 'existing');
475+
476+
const vault = new DisabledVault<string>(storageKey);
477+
478+
vault.purge();
479+
480+
expect(vault.contents).to.equal(null);
481+
expect(window.localStorage.getItem(storageKey)).to.equal(null);
482+
});
483+
484+
it('should keep contents null when purging an empty key', () => {
485+
const storageKey = 'test-disabled-purge-empty';
486+
const vault = new DisabledVault<string>(storageKey);
487+
488+
vault.purge();
489+
expect(vault.contents).to.equal(null);
490+
expect(window.localStorage.getItem(storageKey)).to.equal(null);
491+
});
492+
});
493+
});
422494
});

0 commit comments

Comments
 (0)