From d64c4637d9e24a56c4dc6ff9c7e5490f43d417f0 Mon Sep 17 00:00:00 2001 From: BrightMountainMedia <69471268+BrightMountainMediaInc@users.noreply.github.com> Date: Mon, 14 Sep 2020 14:58:33 +0530 Subject: [PATCH] Revert "user id module refresh ids when consent changes (#5451)" This reverts commit a904bbd7125b443d9dce4addc21e8985613ad721. --- modules/userId/index.js | 82 +---------- test/spec/modules/userId_spec.js | 234 ++----------------------------- 2 files changed, 16 insertions(+), 300 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index afdd93a57bad..2a37723e3a08 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -124,10 +124,6 @@ const COOKIE = 'cookie'; const LOCAL_STORAGE = 'html5'; const DEFAULT_SYNC_DELAY = 500; const NO_AUCTION_DELAY = 0; -const CONSENT_DATA_COOKIE_STORAGE_CONFIG = { - name: '_pbjs_userid_consent_data', - expires: 30 // 30 days expiration, which should match how often consent is refreshed by CMPs -}; export const coreStorage = getCoreStorageManager('userid'); /** @type {string[]} */ @@ -225,72 +221,6 @@ function getStoredValue(storage, key = undefined) { return storedValue; } -/** - * makes an object that can be stored with only the keys we need to check. - * excluding the vendorConsents object since the consentString is enough to know - * if consent has changed without needing to have all the details in an object - * @param consentData - * @returns {{apiVersion: number, gdprApplies: boolean, consentString: string}} - */ -function makeStoredConsentDataObject(consentData) { - const storedConsentData = { - consentString: '', - gdprApplies: false, - apiVersion: 0 - }; - - if (consentData) { - storedConsentData.consentString = consentData.consentString; - storedConsentData.gdprApplies = consentData.gdprApplies; - storedConsentData.apiVersion = consentData.apiVersion; - } - - return storedConsentData; -} - -/** - * puts the current consent data into cookie storage - * @param consentData - */ -export function setStoredConsentData(consentData) { - try { - const expiresStr = (new Date(Date.now() + (CONSENT_DATA_COOKIE_STORAGE_CONFIG.expires * (60 * 60 * 24 * 1000)))).toUTCString(); - coreStorage.setCookie(CONSENT_DATA_COOKIE_STORAGE_CONFIG.name, JSON.stringify(makeStoredConsentDataObject(consentData)), expiresStr, 'Lax'); - } catch (error) { - utils.logError(error); - } -} - -/** - * get the stored consent data from local storage, if any - * @returns {string} - */ -function getStoredConsentData() { - let storedValue; - try { - storedValue = JSON.parse(coreStorage.getCookie(CONSENT_DATA_COOKIE_STORAGE_CONFIG.name)); - } catch (e) { - utils.logError(e); - } - return storedValue; -} - -/** - * test if the consent object stored locally matches the current consent data. - * if there is nothing in storage, return true and we'll do an actual comparison next time. - * this way, we don't force a refresh for every user when this code rolls out - * @param storedConsentData - * @param consentData - * @returns {boolean} - */ -function storedConsentDataMatchesConsentData(storedConsentData, consentData) { - return ( - typeof storedConsentData === 'undefined' || - storedConsentData === null || - utils.deepEqual(storedConsentData, makeStoredConsentDataObject(consentData)) - ); -} - /** * test if consent module is present, applies, and is valid for local storage or cookies (purpose 1) * @param {ConsentData} consentData @@ -378,7 +308,7 @@ function addIdDataToAdUnitBids(adUnits, submodules) { } /** - * This is a common function that will initialize subModules if not already done and it will also execute subModule callbacks + * This is a common function that will initalize subModules if not already done and it will also execute subModule callbacks */ function initializeSubmodulesAndExecuteCallbacks(continueAuction) { let delayed = false; @@ -481,10 +411,6 @@ export const validateGdprEnforcement = hook('sync', function (submodules, consen * @returns {SubmoduleContainer[]} initialized submodules */ function initSubmodules(submodules, consentData) { - // we always want the latest consentData stored, even if we don't execute any submodules - const storedConsentData = getStoredConsentData(); - setStoredConsentData(consentData); - // gdpr consent with purpose one is required, otherwise exit immediately let {userIdModules, hasValidated} = validateGdprEnforcement(submodules, consentData); if (!hasValidated && !hasGDPRConsent(consentData)) { @@ -506,8 +432,8 @@ function initSubmodules(submodules, consentData) { refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > submodule.config.storage.refreshInSeconds * 1000); } - if (!storedId || refreshNeeded || !storedConsentDataMatchesConsentData(storedConsentData, consentData)) { - // No id previously saved, or a refresh is needed, or consent has changed. Request a new id from the submodule. + if (!storedId || refreshNeeded) { + // No previously saved id. Request one from submodule. response = submodule.submodule.getId(submodule.config.params, consentData, storedId); } else if (typeof submodule.submodule.extendId === 'function') { // If the id exists already, give submodule a chance to decide additional actions that need to be taken @@ -643,7 +569,7 @@ export function init(config) { utils.logInfo(`${MODULE_NAME} - opt-out cookie found, exit module`); return; } - // _pubcid_optout is checked for compatibility with pubCommonId + // _pubcid_optout is checked for compatiblility with pubCommonId if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (coreStorage.getDataFromLocalStorage('_pbjs_id_optout') || coreStorage.getDataFromLocalStorage('_pubcid_optout'))) { utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`); return; diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index d9671aabc846..a0b7d68bcce3 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -6,8 +6,7 @@ import { setSubmoduleRegistry, syncDelay, coreStorage, - setStoredValue, - setStoredConsentData + setStoredValue } from 'modules/userId/index.js'; import {createEidsArray} from 'modules/userId/eids.js'; import {config} from 'src/config.js'; @@ -15,8 +14,6 @@ import * as utils from 'src/utils.js'; import events from 'src/events.js'; import CONSTANTS from 'src/constants.json'; import {getGlobal} from 'src/prebidGlobal.js'; -import {setConsentConfig, requestBidsHook as consentManagementRequestBidsHook, resetConsentData} from 'modules/consentManagement.js'; -import {gdprDataHandler} from 'src/adapterManager.js'; import {unifiedIdSubmodule} from 'modules/unifiedIdSystem.js'; import {pubCommonIdSubmodule} from 'modules/pubCommonIdSystem.js'; import {britepoolIdSubmodule} from 'modules/britepoolIdSystem.js'; @@ -31,7 +28,6 @@ import {server} from 'test/mocks/xhr.js'; let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; -const CONSENT_LOCAL_STORAGE_NAME = '_pbjs_userid_consent_data'; describe('User ID', function() { function getConfigMock(configArr1, configArr2, configArr3, configArr4, configArr5, configArr6, configArr7, configArr8) { @@ -91,10 +87,6 @@ describe('User ID', function() { localStorage.removeItem('_pubcid_optout'); }); - beforeEach(function() { - coreStorage.setCookie(CONSENT_LOCAL_STORAGE_NAME, '', EXPIRED_COOKIE_DATE); - }); - describe('Decorate Ad Units', function() { beforeEach(function() { coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -219,9 +211,8 @@ describe('User ID', function() { }); }); }); - // Because the cookie exists already, there should be no setCookie call by default; the only setCookie call is - // to store consent data - expect(coreStorage.setCookie.callCount).to.equal(1); + // Because the cookie exists already, there should be no setCookie call by default + expect(coreStorage.setCookie.callCount).to.equal(0); }); it('Extend cookie', function() { @@ -246,9 +237,8 @@ describe('User ID', function() { }); }); }); - // Because extend is true, the cookie will be updated even if it exists already. The second setCookie call - // is for storing consentData - expect(coreStorage.setCookie.callCount).to.equal(2); + // Because extend is true, the cookie will be updated even if it exists already + expect(coreStorage.setCookie.callCount).to.equal(1); }); it('Disable auto create', function() { @@ -269,8 +259,7 @@ describe('User ID', function() { expect(bid).to.not.have.deep.nested.property('userIdAsEids'); }); }); - // setCookie is called once in order to store consentData - expect(coreStorage.setCookie.callCount).to.equal(1); + expect(coreStorage.setCookie.callCount).to.equal(0); }); it('pbjs.getUserIds', function() { @@ -1458,16 +1447,16 @@ describe('User ID', function() { describe('Set cookie behavior', function() { let coreStorageSpy; - beforeEach(function () { + beforeEach(function() { coreStorageSpy = sinon.spy(coreStorage, 'setCookie'); }); - afterEach(function () { + afterEach(function() { coreStorageSpy.restore(); }); it('should allow submodules to override the domain', function () { const submodule = { submodule: { - domainOverride: function () { + domainOverride: function() { return 'foo.com' } }, @@ -1483,7 +1472,9 @@ describe('User ID', function() { it('should pass null for domain if submodule does not override the domain', function () { const submodule = { - submodule: {}, + submodule: { + + }, config: { storage: { type: 'cookie' @@ -1494,205 +1485,4 @@ describe('User ID', function() { expect(coreStorage.setCookie.getCall(0).args[4]).to.equal(null); }); }); - - describe('Consent changes determine getId refreshes', function() { - let expStr; - let adUnits; - - const mockIdCookieName = 'MOCKID'; - let mockGetId = sinon.stub(); - let mockDecode = sinon.stub(); - let mockExtendId = sinon.stub(); - const mockIdSystem = { - name: 'mockId', - getId: mockGetId, - decode: mockDecode, - extendId: mockExtendId - }; - const userIdConfig = { - userSync: { - userIds: [{ - name: 'mockId', - storage: { - name: 'MOCKID', - type: 'cookie', - refreshInSeconds: 30 - } - }], - auctionDelay: 5 - } - }; - - let cmpStub; - let testConsentData; - const consentConfig = { - cmpApi: 'iab', - timeout: 7500, - allowAuctionWithoutConsent: false - }; - - const sharedBeforeFunction = function() { - // clear cookies - expStr = (new Date(Date.now() + 25000).toUTCString()); - coreStorage.setCookie(mockIdCookieName, '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie(`${mockIdCookieName}_last`, '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie(CONSENT_LOCAL_STORAGE_NAME, '', EXPIRED_COOKIE_DATE); - - // init - adUnits = [getAdUnitMock()]; - init(config); - - // init id system - attachIdSystem(mockIdSystem); - config.setConfig(userIdConfig); - } - const sharedAfterFunction = function () { - config.resetConfig(); - mockGetId.reset(); - mockDecode.reset(); - mockExtendId.reset(); - cmpStub.restore(); - resetConsentData(); - delete window.__cmp; - delete window.__tcfapi; - }; - - describe('TCF v1', function() { - testConsentData = { - gdprApplies: true, - consentData: 'xyz', - apiVersion: 1 - }; - - beforeEach(function () { - sharedBeforeFunction(); - - // init v1 consent management - window.__cmp = function () { }; - delete window.__tcfapi; - cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { - args[2](testConsentData); - }); - setConsentConfig(consentConfig); - }); - - afterEach(function() { - sharedAfterFunction(); - }); - - it('does not call getId if no stored consent data and refresh is not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({ id: '1234' }), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - - let innerAdUnits; - consentManagementRequestBidsHook(() => { }, {}); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, { adUnits }); - - sinon.assert.notCalled(mockGetId); - sinon.assert.calledOnce(mockDecode); - sinon.assert.calledOnce(mockExtendId); - - let consent = gdprDataHandler.getConsentData(); - let userIdStoredConsent = JSON.parse(coreStorage.getCookie(CONSENT_LOCAL_STORAGE_NAME)); - expect(userIdStoredConsent.gdprApplies).to.equal(consent.gdprApplies); - expect(userIdStoredConsent.gdprApplies).to.equal(testConsentData.gdprApplies); - expect(userIdStoredConsent.consentString).to.equal(consent.consentString); - expect(userIdStoredConsent.consentString).to.equal(testConsentData.consentData); - }); - - it('calls getId if no stored consent data but refresh is needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({ id: '1234' }), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 60 * 1000).toUTCString()), expStr); - - let innerAdUnits; - consentManagementRequestBidsHook(() => { }, {}); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, { adUnits }); - - sinon.assert.calledOnce(mockGetId); - sinon.assert.calledOnce(mockDecode); - sinon.assert.notCalled(mockExtendId); - - let consent = gdprDataHandler.getConsentData(); - let userIdStoredConsent = JSON.parse(coreStorage.getCookie(CONSENT_LOCAL_STORAGE_NAME)); - expect(userIdStoredConsent.gdprApplies).to.equal(consent.gdprApplies); - expect(userIdStoredConsent.gdprApplies).to.equal(testConsentData.gdprApplies); - expect(userIdStoredConsent.consentString).to.equal(consent.consentString); - expect(userIdStoredConsent.consentString).to.equal(testConsentData.consentData); - }); - - it('calls getId if empty stored consent and refresh not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({ id: '1234' }), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - - setStoredConsentData(); - - let innerAdUnits; - consentManagementRequestBidsHook(() => { }, {}); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, { adUnits }); - - sinon.assert.calledOnce(mockGetId); - sinon.assert.calledOnce(mockDecode); - sinon.assert.notCalled(mockExtendId); - - let consent = gdprDataHandler.getConsentData(); - let userIdStoredConsent = JSON.parse(coreStorage.getCookie(CONSENT_LOCAL_STORAGE_NAME)); - expect(userIdStoredConsent.gdprApplies).to.equal(consent.gdprApplies); - expect(userIdStoredConsent.gdprApplies).to.equal(testConsentData.gdprApplies); - expect(userIdStoredConsent.consentString).to.equal(consent.consentString); - expect(userIdStoredConsent.consentString).to.equal(testConsentData.consentData); - }); - - it('calls getId if stored consent does not match current consent and refresh not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({ id: '1234' }), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - - setStoredConsentData({ - gdprApplies: testConsentData.gdprApplies, - consentString: 'abc', - apiVersion: testConsentData.apiVersion - }); - - let innerAdUnits; - consentManagementRequestBidsHook(() => { }, {}); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, { adUnits }); - - sinon.assert.calledOnce(mockGetId); - sinon.assert.calledOnce(mockDecode); - sinon.assert.notCalled(mockExtendId); - - let consent = gdprDataHandler.getConsentData(); - let userIdStoredConsent = JSON.parse(coreStorage.getCookie(CONSENT_LOCAL_STORAGE_NAME)); - expect(userIdStoredConsent.gdprApplies).to.equal(consent.gdprApplies); - expect(userIdStoredConsent.gdprApplies).to.equal(testConsentData.gdprApplies); - expect(userIdStoredConsent.consentString).to.equal(consent.consentString); - expect(userIdStoredConsent.consentString).to.equal(testConsentData.consentData); - }); - - it('does not call getId if stored consent matches current consent and refresh not needed', function () { - coreStorage.setCookie(mockIdCookieName, JSON.stringify({ id: '1234' }), expStr); - coreStorage.setCookie(`${mockIdCookieName}_last`, (new Date(Date.now() - 1 * 1000).toUTCString()), expStr); - - setStoredConsentData({ - gdprApplies: testConsentData.gdprApplies, - consentString: testConsentData.consentData, - apiVersion: testConsentData.apiVersion - }); - - let innerAdUnits; - consentManagementRequestBidsHook(() => { }, {}); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, { adUnits }); - - sinon.assert.notCalled(mockGetId); - sinon.assert.calledOnce(mockDecode); - sinon.assert.calledOnce(mockExtendId); - - let consent = gdprDataHandler.getConsentData(); - let userIdStoredConsent = JSON.parse(coreStorage.getCookie(CONSENT_LOCAL_STORAGE_NAME)); - expect(userIdStoredConsent.gdprApplies).to.equal(consent.gdprApplies); - expect(userIdStoredConsent.gdprApplies).to.equal(testConsentData.gdprApplies); - expect(userIdStoredConsent.consentString).to.equal(consent.consentString); - expect(userIdStoredConsent.consentString).to.equal(testConsentData.consentData); - }); - }); - }); });