From e1e9e6cedfef69995a49b2e279a445252330ec00 Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 9 Apr 2020 21:01:01 -0700 Subject: [PATCH 01/34] Adding sharedid submodule --- allowedModules.js | 1 + integrationExamples/gpt/userId_example.html | 9 ++++- modules/sharedIdSystem.js | 45 +++++++++++++++++++++ package.json | 3 +- 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 modules/sharedIdSystem.js diff --git a/allowedModules.js b/allowedModules.js index 4f8b8039d97..9db95fc07f0 100644 --- a/allowedModules.js +++ b/allowedModules.js @@ -14,6 +14,7 @@ module.exports = { 'criteo-direct-rsa-validate', 'jsencrypt', 'crypto-js', + 'ulid', 'live-connect' // Maintained by LiveIntent : https://github.com/liveintent-berlin/live-connect/ ], 'src': [ diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 6d2c2ce677a..9c29d9a4ed5 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -184,9 +184,16 @@ name: 'idl_env', expires: 30 } + }, { + name: "sharedId", + storage: { + type: "cookie", + name: "sharedId", + expires: 30 + }, }], syncDelay: 5000, - auctionDelay: 1000 + auctionDelay: 1000 } }); pbjs.addAdUnits(adUnits); diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js new file mode 100644 index 00000000000..8a527b89d14 --- /dev/null +++ b/modules/sharedIdSystem.js @@ -0,0 +1,45 @@ +/** + * This module adds Shared ID support to the User ID module + * The {@link module:modules/userId} module is required. + * @module modules/sharedIdSystem + * @requires module:modules/userId + */ + +import { submodule } from '../src/hook.js'; +// eslint-disable-next-line prebid/validate-imports +import { ulid } from 'ulid' + +const MODULE_NAME = 'sharedId'; + +/** @type {Submodule} */ +export const sharedIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: MODULE_NAME, + + /** + * decode the stored id value for passing to bid requests + * @function + * @param {string} value + * @returns {{sharedId:string}} + */ + decode(value) { + return { 'sharedId': value } + }, + + /** + * performs action to obtain id and return a value. + * @function + * @param {SubmoduleParams} [configParams] + * @returns {sharedId} + */ + getId(configParams) { + let sharedId = ulid(); + return { + id: sharedId } + } +}; + +submodule('userId', sharedIdSubmodule); diff --git a/package.json b/package.json index 66cfd10b357..61fe875e690 100755 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "fun-hooks": "^0.9.8", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2", - "live-connect-js": "1.1.1" + "live-connect-js": "1.1.1", + "ulid": "^2.3.0" } } From 0010b2094f959b756ec6fedf675ec47da840bae9 Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 13 Apr 2020 09:25:59 -0700 Subject: [PATCH 02/34] Updating with Shared ID Module --- integrationExamples/gpt/userId_example.html | 4 +- modules/.submodules.json | 3 +- modules/sharedIdSystem.js | 94 +++++++++++++++++++-- 3 files changed, 92 insertions(+), 9 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 9c29d9a4ed5..d0f55beb137 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -187,9 +187,9 @@ }, { name: "sharedId", storage: { - type: "cookie", + type: "html5", name: "sharedId", - expires: 30 + expires: 28 }, }], syncDelay: 5000, diff --git a/modules/.submodules.json b/modules/.submodules.json index ce3eb8fa137..25ae3c3884b 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -9,7 +9,8 @@ "liveIntentIdSystem", "criteoIdSystem", "netIdSystem", - "identityLinkIdSystem" + "identityLinkIdSystem", + "sharedIdSystem" ], "adpod": [ "freeWheelAdserverVideo", diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 8a527b89d14..4eaec68325e 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -4,11 +4,15 @@ * @module modules/sharedIdSystem * @requires module:modules/userId */ - import { submodule } from '../src/hook.js'; -// eslint-disable-next-line prebid/validate-imports -import { ulid } from 'ulid' - +import * as utils from '../src/utils.js'; +// These values should NEVER change. If +// they do, we're no longer making ulids! +const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 +const ENCODING_LEN = ENCODING.length; +const TIME_MAX = Math.pow(2, 48) - 1; +const TIME_LEN = 10; +const RANDOM_LEN = 16; const MODULE_NAME = 'sharedId'; /** @type {Submodule} */ @@ -19,6 +23,8 @@ export const sharedIdSubmodule = { */ name: MODULE_NAME, + sharedIdFactory: undefined, + /** * decode the stored id value for passing to bid requests * @function @@ -35,10 +41,86 @@ export const sharedIdSubmodule = { * @param {SubmoduleParams} [configParams] * @returns {sharedId} */ - getId(configParams) { - let sharedId = ulid(); + getId: function(configParams) { + let sharedId = this.sharedIdGenerator(); return { id: sharedId } + }, + + sharedIdGenerator: function () { + if (!this.sharedIdFactory) { + this.sharedIdFactory = this.factory(); + } + + return this.sharedIdFactory(); + }, + + factory: function (currPrng) { + if (!currPrng) { + currPrng = this.detectPrng(); + } + return function ulid(seedTime) { + if (isNaN(seedTime)) { + seedTime = Date.now(); + } + return this.encodeTime(seedTime, TIME_LEN) + this.encodeRandom(RANDOM_LEN, currPrng); + }; + }, + createError: function(message) { + utils.logError(message); + const err = new Error(message); + err.source = 'sharedId'; + return err; + }, + randomChar: function(prng) { + let rand = Math.floor(prng() * ENCODING_LEN); + if (rand === ENCODING_LEN) { + rand = ENCODING_LEN - 1; + } + return ENCODING.charAt(rand); + }, + encodeTime: function (now, len) { + if (isNaN(now)) { + throw new Error(now + ' must be a number'); + } + if (now > TIME_MAX) { + throw this.createError('cannot encode time greater than ' + TIME_MAX); + } + if (now < 0) { + throw this.createError('time must be positive'); + } + if (Number.isInteger(now) === false) { + throw this.createError('time must be an integer'); + } + let mod; + let str = ''; + for (; len > 0; len--) { + mod = now % ENCODING_LEN; + str = ENCODING.charAt(mod) + str; + now = (now - mod) / ENCODING_LEN; + } + return str; + }, + encodeRandom: function (len, prng) { + let str = ''; + for (; len > 0; len--) { + str = this.randomChar(prng) + str; + } + return str; + }, + detectPrng: function (root) { + if (!root) { + root = typeof window !== 'undefined' ? window : null; + } + const browserCrypto = root && (root.crypto || root.msCrypto); + if (browserCrypto) { + return () => { + const buffer = new Uint8Array(1); + browserCrypto.getRandomValues(buffer); + return buffer[0] / 0xff; + }; + } + return () => Math.random(); } }; From 06ede75b882f56347abd2b22281ee20b7b6b0df9 Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 13 Apr 2020 18:05:39 -0700 Subject: [PATCH 03/34] SharedID test and sharedid eids --- integrationExamples/gpt/userId_example.html | 2 +- modules/sharedIdSystem.js | 2 +- modules/userId/eids.js | 5 + modules/userId/userId.md | 14 +++ test/spec/modules/eids_spec.js | 11 ++ test/spec/modules/userId_spec.js | 115 ++++++++++++++++---- 6 files changed, 124 insertions(+), 25 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index d0f55beb137..0042a5557fb 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -187,7 +187,7 @@ }, { name: "sharedId", storage: { - type: "html5", + type: "cookie", name: "sharedId", expires: 28 }, diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 4eaec68325e..ee3b5f66d9d 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -32,7 +32,7 @@ export const sharedIdSubmodule = { * @returns {{sharedId:string}} */ decode(value) { - return { 'sharedId': value } + return (value && typeof value['sharedId'] === 'string') ? { 'sharedId': value['sharedId'] } : undefined; }, /** diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 5ca9e40866b..837fb6fd250 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -81,6 +81,11 @@ const USER_IDS_CONFIG = { 'netId': { source: 'netid.de', atype: 1 + }, + // sharedId + 'sharedId': { + source: 'rubiconproject.com', + atype: 1 } }; diff --git a/modules/userId/userId.md b/modules/userId/userId.md index e6da02a6811..3ca188a45cb 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -64,6 +64,13 @@ pbjs.setConfig({ name: '_li_pbid', expires: 60 } + }, { + name: 'sharedId', + storage: { + type: 'cookie', + name: 'sharedId', + expires: 28 + } }], syncDelay: 5000, auctionDelay: 1000 @@ -113,6 +120,13 @@ pbjs.setConfig({ name: '_li_pbid', expires: 60 } + }, { + name: 'sharedId', + storage: { + type: 'cookie', + name: 'sharedId', + expires: 28 + } }], syncDelay: 5000 } diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js index ed32ecc51d2..6c68b9ee151 100644 --- a/test/spec/modules/eids_spec.js +++ b/test/spec/modules/eids_spec.js @@ -146,6 +146,17 @@ describe('eids array generation for known sub-modules', function() { uids: [{id: 'some-random-id-value', atype: 1}] }); }); + it('SharedId', function() { + const userId = { + sharedId: 'test_sharedId' + }; + const newEids = createEidsArray(userId); + expect(newEids.length).to.equal(1); + expect(newEids[0]).to.deep.equal({ + source: 'rubiconproject.com', + uids: [{id: 'test_sharedId', atype: 1}] + }); + }); }); describe('Negative case', function() { diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 41c4841926a..a2efa822c62 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -18,6 +18,7 @@ import {id5IdSubmodule} from 'modules/id5IdSystem.js'; import {identityLinkSubmodule} from 'modules/identityLinkIdSystem.js'; import {liveIntentIdSubmodule} from 'modules/liveIntentIdSystem.js'; import {netIdSubmodule} from 'modules/netIdSystem.js'; +import {sharedIdSubmodule} from 'modules/sharedIdSystem.js'; import {server} from 'test/mocks/xhr.js'; let assert = require('chai').assert; @@ -25,7 +26,7 @@ let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; describe('User ID', function() { - function getConfigMock(configArr1, configArr2, configArr3, configArr4, configArr5, configArr6) { + function getConfigMock(configArr1, configArr2, configArr3, configArr4, configArr5, configArr6, configArr7) { return { userSync: { syncDelay: 0, @@ -35,7 +36,8 @@ describe('User ID', function() { (configArr3 && configArr3.length >= 3) ? getStorageMock.apply(null, configArr3) : null, (configArr4 && configArr4.length >= 3) ? getStorageMock.apply(null, configArr4) : null, (configArr5 && configArr5.length >= 3) ? getStorageMock.apply(null, configArr5) : null, - (configArr6 && configArr6.length >= 3) ? getStorageMock.apply(null, configArr6) : null + (configArr6 && configArr6.length >= 3) ? getStorageMock.apply(null, configArr6) : null, + (configArr7 && configArr7.length >= 3) ? getStorageMock.apply(null, configArr7) : null ].filter(i => i)} } } @@ -283,7 +285,7 @@ describe('User ID', function() { }); it('handles config with no usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({}); // usersync is undefined, and no logInfo message for 'User ID - usersync config updated' @@ -291,14 +293,14 @@ describe('User ID', function() { }); it('handles config with empty usersync object', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: {} }); expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); it('handles config with usersync and userIds that are empty objs', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: { @@ -309,7 +311,7 @@ describe('User ID', function() { }); it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: { @@ -326,15 +328,15 @@ describe('User ID', function() { }); it('config with 1 configurations should create 1 submodules', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); - it('config with 7 configurations should result in 7 submodules add', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule]); + it('config with 8 configurations should result in 8 submodules add', function () { + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: { @@ -359,14 +361,17 @@ describe('User ID', function() { }, { name: 'netId', storage: { name: 'netId', type: 'cookie' } - }] + }, { + name: 'sharedId', + storage: { name: 'sharedId', type: 'cookie' } + } ] } }); - expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 7 submodules'); + expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 8 submodules'); }); it('config syncDelay updates module correctly', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: { @@ -381,7 +386,7 @@ describe('User ID', function() { }); it('config auctionDelay updates module correctly', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: { @@ -396,7 +401,7 @@ describe('User ID', function() { }); it('config auctionDelay defaults to 0 if not a number', function () { - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ userSync: { @@ -786,6 +791,52 @@ describe('User ID', function() { }, {adUnits}); }); + it('test hook from sharedId html5', function(done) { + // simulate existing browser local storage values + localStorage.setItem('sharedId', JSON.stringify({'sharedId': 'test_sharedId'})); + localStorage.setItem('sharedId_exp', ''); + + setSubmoduleRegistry([sharedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['sharedId', 'sharedId', 'html5'])); + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.sharedId'); + expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'rubiconproject.com', + uids: [{id: 'test_sharedId', atype: 1}] + }); + }); + }); + localStorage.removeItem('sharedId'); + localStorage.removeItem('sharedId_exp'); + done(); + }, {adUnits}); + }); + it('test hook from sharedId cookie', function(done) { + coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), (new Date(Date.now() + 100000).toUTCString())); + + setSubmoduleRegistry([sharedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['sharedId', 'sharedId', 'cookie'])); + + requestBidsHook(function() { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.sharedId'); + expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'rubiconproject.com', + uids: [{id: 'test_sharedId', atype: 1}] + }); + }); + }); + coreStorage.setCookie('_li_pbid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); it('test hook from id5id cookies when refresh needed', function(done) { // simulate existing browser local storage values coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -935,22 +986,24 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId and netId have data to pass', function(done) { + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId have data to pass', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'], ['id5Id', 'id5id', 'cookie'], ['identityLink', 'idl_env', 'cookie'], ['britepoolId', 'britepoolid', 'cookie'], - ['netId', 'netId', 'cookie'])); + ['netId', 'netId', 'cookie'], + ['sharedId', 'sharedId', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -973,7 +1026,9 @@ describe('User ID', function() { // also check that netId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); - expect(bid.userIdAsEids.length).to.equal(6); + expect(bid).to.have.deep.nested.property('userId.sharedId'); + expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid.userIdAsEids.length).to.equal(7); }); }); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -982,17 +1037,19 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedId', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, britepoolId and netId have their modules added before and after init', function(done) { + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId have their modules added before and after init', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -1007,13 +1064,15 @@ describe('User ID', function() { attachIdSystem(identityLinkSubmodule); attachIdSystem(britepoolIdSubmodule); attachIdSystem(netIdSubmodule); + attachIdSystem(sharedIdSubmodule); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], ['unifiedId', 'unifiedid', 'cookie'], ['id5Id', 'id5id', 'cookie'], ['identityLink', 'idl_env', 'cookie'], ['britepoolId', 'britepoolid', 'cookie'], - ['netId', 'netId', 'cookie'])); + ['netId', 'netId', 'cookie'], + ['sharedId', 'sharedId', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -1036,7 +1095,9 @@ describe('User ID', function() { // also check that britepoolId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); - expect(bid.userIdAsEids.length).to.equal(6); + expect(bid).to.have.deep.nested.property('userId.sharedId'); + expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid.userIdAsEids.length).to.equal(7); }); }); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -1045,6 +1106,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedId', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -1056,9 +1118,10 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule]); + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -1076,6 +1139,8 @@ describe('User ID', function() { name: 'britepoolId', storage: { name: 'britepoolid', type: 'cookie' } }, { name: 'netId', storage: { name: 'netId', type: 'cookie' } + }, { + name: 'sharedId', storage: {name: 'sharedId', type: 'cookie'} }, { name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } }] @@ -1117,10 +1182,13 @@ describe('User ID', function() { // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); + // also check that sharedId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.sharedId'); + expect(bid.userId.sharedId).to.equal('test_sharedId') // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.mid'); expect(bid.userId.mid).to.equal('123456778'); - expect(bid.userIdAsEids.length).to.equal(6);// mid is unknown for eids.js + expect(bid.userIdAsEids.length).to.equal(7);// mid is unknown for eids.js }); }); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -1129,6 +1197,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); From 16db9be122e6c3b905cbe0b5a05121689659efaf Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 13 Apr 2020 21:41:26 -0700 Subject: [PATCH 04/34] Shared ID md changes --- modules/sharedIdSystem.md | 39 +++++++++++++++++++++++++++++++++++++++ modules/userId/eids.md | 9 ++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 modules/sharedIdSystem.md diff --git a/modules/sharedIdSystem.md b/modules/sharedIdSystem.md new file mode 100644 index 00000000000..755e8ef055c --- /dev/null +++ b/modules/sharedIdSystem.md @@ -0,0 +1,39 @@ +## Shared ID User ID Submodule + +Shared ID User ID Module generates a simple UUID that can be utilized to improve user matching. +This module does not require any registration. + +### Building Prebid with Shared Id Support +Your Prebid build must include the modules for both **userId** and **sharedId** submodule. Follow the build instructions for Prebid as +explained in the top level README.md file of the Prebid source tree. + +ex: $ gulp build --modules=userId,sharedIdSystem + +### Prebid Params + +Individual params may be set for the Shared ID User ID Submodule. +``` +pbjs.setConfig({ + usersync: { + userIds: [{ + name: 'sharedId', + storage: { + name: 'sharedId', + type: 'cookie', + expires: 28 + }, + }] + } +}); +``` + +### Parameter Descriptions for the `usersync` Configuration Section +The below parameters apply only to the Shared ID User ID Module integration. + +| Params under usersync.userIds[]| Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the Shared ID module - `"sharedId"` | `"sharedId"` | +| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | +| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | +| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedId"` | +| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `28` | diff --git a/modules/userId/eids.md b/modules/userId/eids.md index baface1ab6f..c888f57a04d 100644 --- a/modules/userId/eids.md +++ b/modules/userId/eids.md @@ -85,6 +85,13 @@ userIdAsEids = [ id: 'some-random-id-value', atype: 1 }] + }, + { + source: 'rubiconproject.com', + uids: [{ + id: 'some-random-id-value', + atype: 1 + }] } ] -``` \ No newline at end of file +``` From 2d1d4730371028f153fedcc189695fd975c9b62c Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 13 Apr 2020 21:49:34 -0700 Subject: [PATCH 05/34] Shared ID md changes --- allowedModules.js | 1 - 1 file changed, 1 deletion(-) diff --git a/allowedModules.js b/allowedModules.js index 9db95fc07f0..4f8b8039d97 100644 --- a/allowedModules.js +++ b/allowedModules.js @@ -14,7 +14,6 @@ module.exports = { 'criteo-direct-rsa-validate', 'jsencrypt', 'crypto-js', - 'ulid', 'live-connect' // Maintained by LiveIntent : https://github.com/liveintent-berlin/live-connect/ ], 'src': [ From 81efb7d3d609c726303db2aa679df42a549e18b6 Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 13 Apr 2020 21:59:40 -0700 Subject: [PATCH 06/34] Shared ID changes --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 61fe875e690..66cfd10b357 100755 --- a/package.json +++ b/package.json @@ -106,7 +106,6 @@ "fun-hooks": "^0.9.8", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2", - "live-connect-js": "1.1.1", - "ulid": "^2.3.0" + "live-connect-js": "1.1.1" } } From c3777ba37a18d710709167060085404890265513 Mon Sep 17 00:00:00 2001 From: SKOCHERI <37454420+SKOCHERI@users.noreply.github.com> Date: Tue, 14 Apr 2020 09:03:24 -0700 Subject: [PATCH 07/34] Apply suggestions from code review Co-Authored-By: Brad Rodriguez --- integrationExamples/gpt/userId_example.html | 2 +- modules/sharedIdSystem.js | 3 ++- modules/sharedIdSystem.md | 4 ++-- modules/userId/eids.js | 2 +- modules/userId/eids.md | 2 +- modules/userId/userId.md | 4 ++-- test/spec/modules/eids_spec.js | 2 +- test/spec/modules/userId_spec.js | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 0042a5557fb..8f0be9adecc 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -188,7 +188,7 @@ name: "sharedId", storage: { type: "cookie", - name: "sharedId", + name: "sharedid", expires: 28 }, }], diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index ee3b5f66d9d..bd6c1c7c3ce 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -44,7 +44,8 @@ export const sharedIdSubmodule = { getId: function(configParams) { let sharedId = this.sharedIdGenerator(); return { - id: sharedId } + id: sharedId + } }, sharedIdGenerator: function () { diff --git a/modules/sharedIdSystem.md b/modules/sharedIdSystem.md index 755e8ef055c..77c48e03311 100644 --- a/modules/sharedIdSystem.md +++ b/modules/sharedIdSystem.md @@ -18,7 +18,7 @@ pbjs.setConfig({ userIds: [{ name: 'sharedId', storage: { - name: 'sharedId', + name: 'sharedid', type: 'cookie', expires: 28 }, @@ -35,5 +35,5 @@ The below parameters apply only to the Shared ID User ID Module integration. | name | Required | String | ID value for the Shared ID module - `"sharedId"` | `"sharedId"` | | storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | | storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | -| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedId"` | +| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedid"` | | storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `28` | diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 837fb6fd250..6e429494a2b 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -84,7 +84,7 @@ const USER_IDS_CONFIG = { }, // sharedId 'sharedId': { - source: 'rubiconproject.com', + source: 'sharedid.org', atype: 1 } }; diff --git a/modules/userId/eids.md b/modules/userId/eids.md index c888f57a04d..0ca03c90cb7 100644 --- a/modules/userId/eids.md +++ b/modules/userId/eids.md @@ -87,7 +87,7 @@ userIdAsEids = [ }] }, { - source: 'rubiconproject.com', + source: 'sharedid.org', uids: [{ id: 'some-random-id-value', atype: 1 diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 3ca188a45cb..1bf3db92703 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -68,7 +68,7 @@ pbjs.setConfig({ name: 'sharedId', storage: { type: 'cookie', - name: 'sharedId', + name: 'sharedid', expires: 28 } }], @@ -124,7 +124,7 @@ pbjs.setConfig({ name: 'sharedId', storage: { type: 'cookie', - name: 'sharedId', + name: 'sharedid', expires: 28 } }], diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js index 6c68b9ee151..bdcaede9761 100644 --- a/test/spec/modules/eids_spec.js +++ b/test/spec/modules/eids_spec.js @@ -153,7 +153,7 @@ describe('eids array generation for known sub-modules', function() { const newEids = createEidsArray(userId); expect(newEids.length).to.equal(1); expect(newEids[0]).to.deep.equal({ - source: 'rubiconproject.com', + source: 'sharedid.org', uids: [{id: 'test_sharedId', atype: 1}] }); }); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index a2efa822c62..2053ce06d66 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -363,7 +363,7 @@ describe('User ID', function() { storage: { name: 'netId', type: 'cookie' } }, { name: 'sharedId', - storage: { name: 'sharedId', type: 'cookie' } + storage: { name: 'sharedid', type: 'cookie' } } ] } }); From 5f58cebbc76d091b51fbb6ab5992ecda2bf40f48 Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 14 Apr 2020 12:26:23 -0700 Subject: [PATCH 08/34] Applying review suggestions --- modules/sharedIdSystem.js | 58 +++++++++++++++++++++++++++++--- modules/userId/eids.js | 4 +-- test/spec/modules/eids_spec.js | 4 +-- test/spec/modules/userId_spec.js | 58 ++++++++++++++++---------------- 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index bd6c1c7c3ce..622dd13af3d 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -29,10 +29,10 @@ export const sharedIdSubmodule = { * decode the stored id value for passing to bid requests * @function * @param {string} value - * @returns {{sharedId:string}} + * @returns {{sharedid:string}} or undefined if value doesn't exists */ decode(value) { - return (value && typeof value['sharedId'] === 'string') ? { 'sharedId': value['sharedId'] } : undefined; + return (value && typeof value['sharedid'] === 'string') ? { 'sharedid': value['sharedid'] } : undefined; }, /** @@ -47,7 +47,10 @@ export const sharedIdSubmodule = { id: sharedId } }, - + /** + * the shared id generator factory. + * @returns {*} + */ sharedIdGenerator: function () { if (!this.sharedIdFactory) { this.sharedIdFactory = this.factory(); @@ -56,6 +59,11 @@ export const sharedIdSubmodule = { return this.sharedIdFactory(); }, + /** + * the factory to generate unique identifier based on time and current pseudorandom number + * @param {string} the current pseudorandom number + * @returns {function(*=): *} + */ factory: function (currPrng) { if (!currPrng) { currPrng = this.detectPrng(); @@ -67,12 +75,23 @@ export const sharedIdSubmodule = { return this.encodeTime(seedTime, TIME_LEN) + this.encodeRandom(RANDOM_LEN, currPrng); }; }, + /** + * creates and logs the error message + * @function + * @param {string} error message + * @returns {Error} + */ createError: function(message) { utils.logError(message); const err = new Error(message); err.source = 'sharedId'; return err; }, + /** + * gets a a random charcter from generated pseudorandom number + * @param {string} the generated pseudorandom number + * @returns {string} + */ randomChar: function(prng) { let rand = Math.floor(prng() * ENCODING_LEN); if (rand === ENCODING_LEN) { @@ -80,19 +99,35 @@ export const sharedIdSubmodule = { } return ENCODING.charAt(rand); }, + /** + * encodes the time based on the length + * @param now + * @param len + * @returns {string} encoded time. + */ encodeTime: function (now, len) { if (isNaN(now)) { throw new Error(now + ' must be a number'); } + + if (Number.isInteger(now) === false) { + throw this.createError('time must be an integer'); + } + if (now > TIME_MAX) { throw this.createError('cannot encode time greater than ' + TIME_MAX); } if (now < 0) { throw this.createError('time must be positive'); } - if (Number.isInteger(now) === false) { - throw this.createError('time must be an integer'); + + if (Number.isInteger(len) === false) { + throw this.createError('length must be an integer'); + } + if (len < 0) { + throw this.createError('length must be positive'); } + let mod; let str = ''; for (; len > 0; len--) { @@ -102,6 +137,13 @@ export const sharedIdSubmodule = { } return str; }, + + /** + * encodes random character + * @param len + * @param prng + * @returns {string} + */ encodeRandom: function (len, prng) { let str = ''; for (; len > 0; len--) { @@ -109,6 +151,12 @@ export const sharedIdSubmodule = { } return str; }, + /** + * detects the pseudorandom number generator and generates the random number + * @function + * @param {string} error message + * @returns {string} a random number + */ detectPrng: function (root) { if (!root) { root = typeof window !== 'undefined' ? window : null; diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 6e429494a2b..15caf52d4e7 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -82,8 +82,8 @@ const USER_IDS_CONFIG = { source: 'netid.de', atype: 1 }, - // sharedId - 'sharedId': { + // sharedid + 'sharedid': { source: 'sharedid.org', atype: 1 } diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js index bdcaede9761..e7d1785232a 100644 --- a/test/spec/modules/eids_spec.js +++ b/test/spec/modules/eids_spec.js @@ -146,9 +146,9 @@ describe('eids array generation for known sub-modules', function() { uids: [{id: 'some-random-id-value', atype: 1}] }); }); - it('SharedId', function() { + it('Sharedid', function() { const userId = { - sharedId: 'test_sharedId' + sharedid: 'test_sharedId' }; const newEids = createEidsArray(userId); expect(newEids.length).to.equal(1); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 2053ce06d66..d319b1d81c2 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -793,47 +793,47 @@ describe('User ID', function() { it('test hook from sharedId html5', function(done) { // simulate existing browser local storage values - localStorage.setItem('sharedId', JSON.stringify({'sharedId': 'test_sharedId'})); - localStorage.setItem('sharedId_exp', ''); + localStorage.setItem('sharedid', JSON.stringify({'sharedid': 'test_sharedId'})); + localStorage.setItem('sharedid_exp', ''); setSubmoduleRegistry([sharedIdSubmodule]); init(config); - config.setConfig(getConfigMock(['sharedId', 'sharedId', 'html5'])); + config.setConfig(getConfigMock(['sharedId', 'sharedid', 'html5'])); requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.sharedId'); - expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.equal('test_sharedId'); expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'rubiconproject.com', + source: 'sharedid.org', uids: [{id: 'test_sharedId', atype: 1}] }); }); }); - localStorage.removeItem('sharedId'); - localStorage.removeItem('sharedId_exp'); + localStorage.removeItem('sharedid'); + localStorage.removeItem('sharedid_exp'); done(); }, {adUnits}); }); it('test hook from sharedId cookie', function(done) { - coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([sharedIdSubmodule]); init(config); - config.setConfig(getConfigMock(['sharedId', 'sharedId', 'cookie'])); + config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.sharedId'); - expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.equal('test_sharedId'); expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'rubiconproject.com', + source: 'sharedid.org', uids: [{id: 'test_sharedId', atype: 1}] }); }); }); - coreStorage.setCookie('_li_pbid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -993,7 +993,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); @@ -1003,7 +1003,7 @@ describe('User ID', function() { ['identityLink', 'idl_env', 'cookie'], ['britepoolId', 'britepoolid', 'cookie'], ['netId', 'netId', 'cookie'], - ['sharedId', 'sharedId', 'cookie'])); + ['sharedId', 'sharedid', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -1026,8 +1026,8 @@ describe('User ID', function() { // also check that netId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); - expect(bid).to.have.deep.nested.property('userId.sharedId'); - expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.equal('test_sharedId'); expect(bid.userIdAsEids.length).to.equal(7); }); }); @@ -1037,7 +1037,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('sharedId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -1049,7 +1049,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -1072,7 +1072,7 @@ describe('User ID', function() { ['identityLink', 'idl_env', 'cookie'], ['britepoolId', 'britepoolid', 'cookie'], ['netId', 'netId', 'cookie'], - ['sharedId', 'sharedId', 'cookie'])); + ['sharedId', 'sharedid', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { @@ -1095,8 +1095,8 @@ describe('User ID', function() { // also check that britepoolId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); - expect(bid).to.have.deep.nested.property('userId.sharedId'); - expect(bid.userId.sharedId).to.equal('test_sharedId'); + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.equal('test_sharedId'); expect(bid.userIdAsEids.length).to.equal(7); }); }); @@ -1106,7 +1106,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('sharedId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); }); @@ -1118,7 +1118,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); - coreStorage.setCookie('sharedId', JSON.stringify({'sharedId': 'test_sharedId'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); @@ -1140,7 +1140,7 @@ describe('User ID', function() { }, { name: 'netId', storage: { name: 'netId', type: 'cookie' } }, { - name: 'sharedId', storage: {name: 'sharedId', type: 'cookie'} + name: 'sharedId', storage: {name: 'sharedid', type: 'cookie'} }, { name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } }] @@ -1183,8 +1183,8 @@ describe('User ID', function() { expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); // also check that sharedId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.sharedId'); - expect(bid.userId.sharedId).to.equal('test_sharedId') + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.equal('test_sharedId') // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.mid'); expect(bid.userId.mid).to.equal('123456778'); @@ -1197,7 +1197,7 @@ describe('User ID', function() { coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('sharedId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('MOCKID', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); From 9a70c2e07a211dae7da35a03ded951c00584163b Mon Sep 17 00:00:00 2001 From: SKOCHERI <37454420+SKOCHERI@users.noreply.github.com> Date: Tue, 14 Apr 2020 12:41:28 -0700 Subject: [PATCH 09/34] Apply suggestions from code review Co-Authored-By: Brad Rodriguez --- modules/sharedIdSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 622dd13af3d..38bff0d7814 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -61,7 +61,7 @@ export const sharedIdSubmodule = { /** * the factory to generate unique identifier based on time and current pseudorandom number - * @param {string} the current pseudorandom number + * @param {string} the current pseudorandom number generator * @returns {function(*=): *} */ factory: function (currPrng) { From 120f1c316a3d58d2f71329b2162f14f471526170 Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 15 Apr 2020 13:25:20 -0700 Subject: [PATCH 10/34] Reformatting and reorganizing sharedId submodule --- modules/sharedIdSystem.js | 75 +++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 622dd13af3d..485bf410b95 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -4,8 +4,10 @@ * @module modules/sharedIdSystem * @requires module:modules/userId */ + import { submodule } from '../src/hook.js'; import * as utils from '../src/utils.js'; + // These values should NEVER change. If // they do, we're no longer making ulids! const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 @@ -15,43 +17,17 @@ const TIME_LEN = 10; const RANDOM_LEN = 16; const MODULE_NAME = 'sharedId'; -/** @type {Submodule} */ -export const sharedIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - +/** + * Primary module for generating ulid. + */ +const UlidGenerator = { sharedIdFactory: undefined, - /** - * decode the stored id value for passing to bid requests - * @function - * @param {string} value - * @returns {{sharedid:string}} or undefined if value doesn't exists - */ - decode(value) { - return (value && typeof value['sharedid'] === 'string') ? { 'sharedid': value['sharedid'] } : undefined; - }, - - /** - * performs action to obtain id and return a value. - * @function - * @param {SubmoduleParams} [configParams] - * @returns {sharedId} - */ - getId: function(configParams) { - let sharedId = this.sharedIdGenerator(); - return { - id: sharedId - } - }, /** * the shared id generator factory. * @returns {*} */ - sharedIdGenerator: function () { + generateId: function () { if (!this.sharedIdFactory) { this.sharedIdFactory = this.factory(); } @@ -75,6 +51,7 @@ export const sharedIdSubmodule = { return this.encodeTime(seedTime, TIME_LEN) + this.encodeRandom(RANDOM_LEN, currPrng); }; }, + /** * creates and logs the error message * @function @@ -87,6 +64,7 @@ export const sharedIdSubmodule = { err.source = 'sharedId'; return err; }, + /** * gets a a random charcter from generated pseudorandom number * @param {string} the generated pseudorandom number @@ -99,6 +77,7 @@ export const sharedIdSubmodule = { } return ENCODING.charAt(rand); }, + /** * encodes the time based on the length * @param now @@ -151,6 +130,7 @@ export const sharedIdSubmodule = { } return str; }, + /** * detects the pseudorandom number generator and generates the random number * @function @@ -173,4 +153,37 @@ export const sharedIdSubmodule = { } }; +/** @type {Submodule} */ +export const sharedIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: MODULE_NAME, + + /** + * decode the stored id value for passing to bid requests + * @function + * @param {string} value + * @returns {{sharedid:string}} or undefined if value doesn't exists + */ + decode(value) { + return (value && typeof value['sharedid'] === 'string') ? { 'sharedid': value['sharedid'] } : undefined; + }, + + /** + * performs action to obtain id and return a value. + * @function + * @param {SubmoduleParams} [configParams] + * @returns {sharedId} + */ + getId: function(configParams) { + let sharedId = UlidGenerator.generateId(); + return { + id: sharedId + } + }, +}; + +// Register submodule for userId submodule('userId', sharedIdSubmodule); From 16fa25c6465f061adc16991f4546773eef102bf8 Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 15 Apr 2020 16:13:33 -0700 Subject: [PATCH 11/34] Reformatting and reorganizing sharedId submodule --- modules/sharedIdSystem.js | 147 +------------------------------------- src/sharedIdGenerator.js | 132 ++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 145 deletions(-) create mode 100644 src/sharedIdGenerator.js diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 8a3f47e2f36..8967c52b90a 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -6,153 +6,10 @@ */ import { submodule } from '../src/hook.js'; -import * as utils from '../src/utils.js'; +import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; -// These values should NEVER change. If -// they do, we're no longer making ulids! -const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 -const ENCODING_LEN = ENCODING.length; -const TIME_MAX = Math.pow(2, 48) - 1; -const TIME_LEN = 10; -const RANDOM_LEN = 16; const MODULE_NAME = 'sharedId'; -/** - * Primary module for generating ulid. - */ -const UlidGenerator = { - sharedIdFactory: undefined, - - /** - * the shared id generator factory. - * @returns {*} - */ - generateId: function () { - if (!this.sharedIdFactory) { - this.sharedIdFactory = this.factory(); - } - - return this.sharedIdFactory(); - }, - - /** - * the factory to generate unique identifier based on time and current pseudorandom number - * @param {string} the current pseudorandom number generator - * @returns {function(*=): *} - */ - factory: function (currPrng) { - if (!currPrng) { - currPrng = this.detectPrng(); - } - return function ulid(seedTime) { - if (isNaN(seedTime)) { - seedTime = Date.now(); - } - return this.encodeTime(seedTime, TIME_LEN) + this.encodeRandom(RANDOM_LEN, currPrng); - }; - }, - - /** - * creates and logs the error message - * @function - * @param {string} error message - * @returns {Error} - */ - createError: function(message) { - utils.logError(message); - const err = new Error(message); - err.source = 'sharedId'; - return err; - }, - - /** - * gets a a random charcter from generated pseudorandom number - * @param {string} the generated pseudorandom number - * @returns {string} - */ - randomChar: function(prng) { - let rand = Math.floor(prng() * ENCODING_LEN); - if (rand === ENCODING_LEN) { - rand = ENCODING_LEN - 1; - } - return ENCODING.charAt(rand); - }, - - /** - * encodes the time based on the length - * @param now - * @param len - * @returns {string} encoded time. - */ - encodeTime: function (now, len) { - if (isNaN(now)) { - throw new Error(now + ' must be a number'); - } - - if (Number.isInteger(now) === false) { - throw this.createError('time must be an integer'); - } - - if (now > TIME_MAX) { - throw this.createError('cannot encode time greater than ' + TIME_MAX); - } - if (now < 0) { - throw this.createError('time must be positive'); - } - - if (Number.isInteger(len) === false) { - throw this.createError('length must be an integer'); - } - if (len < 0) { - throw this.createError('length must be positive'); - } - - let mod; - let str = ''; - for (; len > 0; len--) { - mod = now % ENCODING_LEN; - str = ENCODING.charAt(mod) + str; - now = (now - mod) / ENCODING_LEN; - } - return str; - }, - - /** - * encodes random character - * @param len - * @param prng - * @returns {string} - */ - encodeRandom: function (len, prng) { - let str = ''; - for (; len > 0; len--) { - str = this.randomChar(prng) + str; - } - return str; - }, - - /** - * detects the pseudorandom number generator and generates the random number - * @function - * @param {string} error message - * @returns {string} a random number - */ - detectPrng: function (root) { - if (!root) { - root = typeof window !== 'undefined' ? window : null; - } - const browserCrypto = root && (root.crypto || root.msCrypto); - if (browserCrypto) { - return () => { - const buffer = new Uint8Array(1); - browserCrypto.getRandomValues(buffer); - return buffer[0] / 0xff; - }; - } - return () => Math.random(); - } -}; - /** @type {Submodule} */ export const sharedIdSubmodule = { /** @@ -178,7 +35,7 @@ export const sharedIdSubmodule = { * @returns {sharedId} */ getId: function(configParams) { - let sharedId = UlidGenerator.generateId(); + let sharedId = sharedIdGenerator.id(); return { id: sharedId } diff --git a/src/sharedIdGenerator.js b/src/sharedIdGenerator.js new file mode 100644 index 00000000000..65db67f9435 --- /dev/null +++ b/src/sharedIdGenerator.js @@ -0,0 +1,132 @@ +/** + * Generates the shared Id/Ulid. Id generated is 128 bits with first 48 bits of timestamp followed by 80 bit of randomness. + * Spec is available in https://github.com/ulid/spec + */ +import * as utils from '../src/utils.js'; + +// These values should NEVER change. If +// they do, we're no longer making ulids! +const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 +const ENCODING_LEN = ENCODING.length; +const TIME_MAX = Math.pow(2, 48) - 1; +const TIME_LEN = 10; +const RANDOM_LEN = 16; + +/** + * the factory to generate unique identifier based on time and current pseudorandom number + * @param {string} the current pseudorandom number generator + * @returns {function(*=): *} + */ +function factory(currPrng) { + if (!currPrng) { + currPrng = detectPrng(); + } + return function ulid(seedTime) { + if (isNaN(seedTime)) { + seedTime = Date.now(); + } + return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN, currPrng); + }; +} + +/** + * creates and logs the error message + * @function + * @param {string} error message + * @returns {Error} + */ +function createError(message) { + utils.logError(message); + const err = new Error(message); + err.source = 'sharedId'; + return err; +} + +/** + * gets a a random charcter from generated pseudorandom number + * @param {string} the generated pseudorandom number + * @returns {string} + */ +function randomChar(prng) { + let rand = Math.floor(prng() * ENCODING_LEN); + if (rand === ENCODING_LEN) { + rand = ENCODING_LEN - 1; + } + return ENCODING.charAt(rand); +} + +/** + * encodes the time based on the length + * @param now + * @param len + * @returns {string} encoded time. + */ +function encodeTime (now, len) { + if (isNaN(now)) { + throw new Error(now + ' must be a number'); + } + + if (Number.isInteger(now) === false) { + throw createError('time must be an integer'); + } + + if (now > TIME_MAX) { + throw createError('cannot encode time greater than ' + TIME_MAX); + } + if (now < 0) { + throw createError('time must be positive'); + } + + if (Number.isInteger(len) === false) { + throw createError('length must be an integer'); + } + if (len < 0) { + throw createError('length must be positive'); + } + + let mod; + let str = ''; + for (; len > 0; len--) { + mod = now % ENCODING_LEN; + str = ENCODING.charAt(mod) + str; + now = (now - mod) / ENCODING_LEN; + } + return str; +} + +/** + * encodes random character + * @param len + * @param prng + * @returns {string} + */ +function encodeRandom (len, prng) { + let str = ''; + for (; len > 0; len--) { + str = randomChar(prng) + str; + } + return str; +} + +/** + * detects the pseudorandom number generator and generates the random number + * @function + * @param {string} error message + * @returns {string} a random number + */ +function detectPrng(root) { + if (!root) { + root = typeof window !== 'undefined' ? window : null; + } + const browserCrypto = root && (root.crypto || root.msCrypto); + if (browserCrypto) { + return () => { + const buffer = new Uint8Array(1); + browserCrypto.getRandomValues(buffer); + return buffer[0] / 0xff; + }; + } + return () => Math.random(); +} + +export const id = factory(); From e175a2965ada6bc738e4d1caa60294a475ceb8ed Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 20 Apr 2020 09:36:44 -0700 Subject: [PATCH 12/34] Shared Id generation changes --- modules/sharedIdSystem.js | 48 +++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 8967c52b90a..1c736e95e1a 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -5,10 +5,42 @@ * @requires module:modules/userId */ +import * as utils from '../src/utils.js' +import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; const MODULE_NAME = 'sharedId'; +const ID_SVC = 'http://qa.sharedid.org/id'; + +/** + * id generation call back + * @param result + * @param callback + * @returns {{success: success, error: error}} + */ +function idGenerationCallback(result, callback) { + return { + success: function (responseBody) { + let responseObj; + if (responseBody) { + try { + responseObj = JSON.parse(responseBody); + result.id = responseObj.sharedId; + utils.logInfo('SharedId: Generated SharedId: ' + result.id); + } catch (error) { + utils.logError(error); + } + } + callback(result.id); + }, + error: function (statusText, responseBody) { + result.id = sharedIdGenerator.id(); + utils.logInfo('SharedId: Ulid Generated SharedId: ' + result.id); + callback(result.id); + } + } +} /** @type {Submodule} */ export const sharedIdSubmodule = { @@ -34,12 +66,18 @@ export const sharedIdSubmodule = { * @param {SubmoduleParams} [configParams] * @returns {sharedId} */ - getId: function(configParams) { - let sharedId = sharedIdGenerator.id(); - return { - id: sharedId + getId(configParams) { + var result = { + id: null } - }, + + const resp = function (callback) { + utils.logInfo('sharedId doesnt exists'); + + ajax(ID_SVC, idGenerationCallback(result, callback), undefined, {method: 'GET', withCredentials: true}); + }; + return {callback: resp}; + } }; // Register submodule for userId From 76d5424a7da883def5a880e0fb2b2a22af69a9a3 Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 23 Apr 2020 11:37:36 -0700 Subject: [PATCH 13/34] Adding cookie Sync --- modules/sharedIdSystem.js | 94 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 6 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 1c736e95e1a..86d59d1bbb2 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -6,12 +6,16 @@ */ import * as utils from '../src/utils.js' -import { ajax } from '../src/ajax.js'; -import { submodule } from '../src/hook.js'; +import {ajax} from '../src/ajax.js'; +import {submodule} from '../src/hook.js'; import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; +import {getStorageManager} from '../src/storageManager.js'; const MODULE_NAME = 'sharedId'; -const ID_SVC = 'http://qa.sharedid.org/id'; +const ID_SVC = 'https://id-qa.sharedid.org/id'; +const storage = getStorageManager(null, MODULE_NAME); +const EXP_28_DAYS = 40320 +const SHARED_ID_ULID_TRACKER = 'sharedid_ns' /** * id generation call back @@ -37,11 +41,67 @@ function idGenerationCallback(result, callback) { error: function (statusText, responseBody) { result.id = sharedIdGenerator.id(); utils.logInfo('SharedId: Ulid Generated SharedId: ' + result.id); + setSharedIdTrackerCookie(result.id); callback(result.id); } } } +/** + * existing id generation call back + * @param result + * @param callback + * @returns {{success: success, error: error}} + */ +function existingIdCallback(result, callback) { + return { + success: function () { + try { + utils.logInfo('SharedId: Synced: ' + result.id); + clearSharedIdTracker(); + } catch (error) { + utils.logError(error); + } + callback(result.id); + }, + error: function () { + utils.logInfo('SharedId: Sync error for id : ' + result.id); + callback(result.id); + } + } +} + +/** + * Write a value to cookies + * @param {string} value Value to be store + */ +function setSharedIdTrackerCookie(value) { + if (value) { + utils.logInfo('SharedId: Writing to the ' + SHARED_ID_ULID_TRACKER + ' cookies '); + let expTime = new Date(); + expTime.setTime(expTime.getTime() + EXP_28_DAYS * 1000 * 60); + storage.setCookie(SHARED_ID_ULID_TRACKER, value, expTime); + } +} + +function clearSharedIdTracker() { + let existingCookie = readValue(SHARED_ID_ULID_TRACKER); + if (existingCookie != undefined) { + utils.logInfo('SharedId: Clearing ' + SHARED_ID_ULID_TRACKER + ' cookies '); + storage.setCookie(SHARED_ID_ULID_TRACKER, ''); + } +} + +function readValue(name) { + let value = storage.getCookie(name); + if (value === 'undefined' || value === 'null' || value === '') { + utils.logInfo(SHARED_ID_ULID_TRACKER + ' cookies is empty/undefined/null '); + return undefined; + } + utils.logInfo('SharedId: Reading the ' + SHARED_ID_ULID_TRACKER + ' cookies ' + value); + return value; +} + /** @type {Submodule} */ export const sharedIdSubmodule = { /** @@ -57,7 +117,7 @@ export const sharedIdSubmodule = { * @returns {{sharedid:string}} or undefined if value doesn't exists */ decode(value) { - return (value && typeof value['sharedid'] === 'string') ? { 'sharedid': value['sharedid'] } : undefined; + return (value && typeof value['sharedid'] === 'string') ? {'sharedid': value['sharedid']} : undefined; }, /** @@ -70,13 +130,35 @@ export const sharedIdSubmodule = { var result = { id: null } - const resp = function (callback) { - utils.logInfo('sharedId doesnt exists'); + utils.logInfo('SharedId: Sharedid doesnt exists, new cookie creation'); ajax(ID_SVC, idGenerationCallback(result, callback), undefined, {method: 'GET', withCredentials: true}); }; return {callback: resp}; + }, + + /** + * performs actions even if the id exists and returns a value + * @param configParams + * @param storedId + * @returns {{callback: *}} + */ + extendId(configParams, storedId) { + utils.logInfo('SharedId: Existing shared id ' + storedId); + var result = { + id: storedId + } + const resp = function (callback) { + let existingCookie = readValue(SHARED_ID_ULID_TRACKER); + if (existingCookie) { + let sharedIdPayload = {}; + sharedIdPayload.sharedId = storedId; + let payloadString = JSON.stringify(sharedIdPayload); + ajax(ID_SVC, existingIdCallback(result, callback), payloadString, {method: 'POST', withCredentials: true}); + } + }; + return {callback: resp}; } }; From 7d43ecc8b47c4708bbf374ba661ea7bb99ada6d7 Mon Sep 17 00:00:00 2001 From: skocheri Date: Fri, 1 May 2020 17:38:02 -0700 Subject: [PATCH 14/34] Decode and sync cookie --- integrationExamples/gpt/testrunner.html | 20 ++ modules/sharedIdSystem.js | 133 +++++---- modules/userId/eids.js | 20 +- test/spec/modules/eids_spec.js | 29 +- test/spec/modules/userId_spec.js | 361 ++++++++++++++++-------- 5 files changed, 375 insertions(+), 188 deletions(-) create mode 100644 integrationExamples/gpt/testrunner.html diff --git a/integrationExamples/gpt/testrunner.html b/integrationExamples/gpt/testrunner.html new file mode 100644 index 00000000000..47d9f157153 --- /dev/null +++ b/integrationExamples/gpt/testrunner.html @@ -0,0 +1,20 @@ + + + + Mocha Tests + + + +
+ + + + + + + + + + + + diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 86d59d1bbb2..26d97558762 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -9,13 +9,25 @@ import * as utils from '../src/utils.js' import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js'; import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; -import {getStorageManager} from '../src/storageManager.js'; const MODULE_NAME = 'sharedId'; const ID_SVC = 'https://id-qa.sharedid.org/id'; -const storage = getStorageManager(null, MODULE_NAME); -const EXP_28_DAYS = 40320 -const SHARED_ID_ULID_TRACKER = 'sharedid_ns' + +/** + * Constructs cookie value + * @param value + * @param needSync + * @returns {string} + */ +function constructCookieValue(value, needSync) { + let cookieValue = {}; + cookieValue.id = value; + if (needSync) { + cookieValue.ns = true; + } + utils.logInfo('SharedId: cookie Value: ' + cookieValue); + return cookieValue; +} /** * id generation call back @@ -23,26 +35,25 @@ const SHARED_ID_ULID_TRACKER = 'sharedid_ns' * @param callback * @returns {{success: success, error: error}} */ -function idGenerationCallback(result, callback) { +function idGenerationCallback(callback) { return { success: function (responseBody) { - let responseObj; + var value = {}; if (responseBody) { try { - responseObj = JSON.parse(responseBody); - result.id = responseObj.sharedId; - utils.logInfo('SharedId: Generated SharedId: ' + result.id); + let responseObj = JSON.parse(responseBody); + utils.logInfo('SharedId: Generated SharedId: ' + responseObj.sharedId); + value = constructCookieValue(responseObj.sharedId, false); } catch (error) { utils.logError(error); } } - callback(result.id); + callback(value); }, error: function (statusText, responseBody) { - result.id = sharedIdGenerator.id(); - utils.logInfo('SharedId: Ulid Generated SharedId: ' + result.id); - setSharedIdTrackerCookie(result.id); - callback(result.id); + var value = constructCookieValue(sharedIdGenerator.id(), true); + utils.logInfo('SharedId: Ulid Generated SharedId: ' + value.id); + callback(value); } } } @@ -53,53 +64,57 @@ function idGenerationCallback(result, callback) { * @param callback * @returns {{success: success, error: error}} */ -function existingIdCallback(result, callback) { +function existingIdCallback(storedId, callback) { return { - success: function () { + success: function (responseBody) { try { - utils.logInfo('SharedId: Synced: ' + result.id); - clearSharedIdTracker(); + utils.logInfo('SharedId: id to be synced: ' + storedId.id); + if (responseBody) { + try { + let responseObj = JSON.parse(responseBody); + storedId = constructCookieValue(responseObj.sharedId, false); + utils.logInfo('SharedId: Older SharedId: ' + storedId.id); + } catch (error) { + utils.logError(error); + } + } } catch (error) { utils.logError(error); } - callback(result.id); + callback(storedId); }, error: function () { - utils.logInfo('SharedId: Sync error for id : ' + result.id); - callback(result.id); + utils.logInfo('SharedId: Sync error for id : ' + storedId.id); + callback(storedId); } } } /** - * Write a value to cookies - * @param {string} value Value to be store + * Encode the id + * @param value + * @returns {string|*} */ -function setSharedIdTrackerCookie(value) { - if (value) { - utils.logInfo('SharedId: Writing to the ' + SHARED_ID_ULID_TRACKER + ' cookies '); - let expTime = new Date(); - expTime.setTime(expTime.getTime() + EXP_28_DAYS * 1000 * 60); - storage.setCookie(SHARED_ID_ULID_TRACKER, value, expTime); - } -} - -function clearSharedIdTracker() { - let existingCookie = readValue(SHARED_ID_ULID_TRACKER); - if (existingCookie != undefined) { - utils.logInfo('SharedId: Clearing ' + SHARED_ID_ULID_TRACKER + ' cookies '); - storage.setCookie(SHARED_ID_ULID_TRACKER, ''); - } -} - -function readValue(name) { - let value = storage.getCookie(name); - if (value === 'undefined' || value === 'null' || value === '') { - utils.logInfo(SHARED_ID_ULID_TRACKER + ' cookies is empty/undefined/null '); - return undefined; +function encodeId(value) { + try { + let result = {}; + let sharedId = (value && typeof value['id'] === 'string') ? value['id'] : undefined; + if (sharedId) { + var bidIds = { + first: sharedId, + } + let ns = (value && typeof value['ns'] === 'boolean') ? value['ns'] : undefined; + if (ns == undefined) { + bidIds.third = sharedId; + } + result.sharedid = bidIds; + utils.logInfo('SharedId: Decoded value ' + JSON.stringify(result)); + return result; + } + return sharedId; + } catch (ex) { + return value; } - utils.logInfo('SharedId: Reading the ' + SHARED_ID_ULID_TRACKER + ' cookies ' + value); - return value; } /** @type {Submodule} */ @@ -114,10 +129,10 @@ export const sharedIdSubmodule = { * decode the stored id value for passing to bid requests * @function * @param {string} value - * @returns {{sharedid:string}} or undefined if value doesn't exists + * @returns {{sharedid:{ 1: string, 3:string}} or undefined if value doesn't exists */ decode(value) { - return (value && typeof value['sharedid'] === 'string') ? {'sharedid': value['sharedid']} : undefined; + return ((value) ? encodeId(value) : undefined); }, /** @@ -127,13 +142,9 @@ export const sharedIdSubmodule = { * @returns {sharedId} */ getId(configParams) { - var result = { - id: null - } const resp = function (callback) { utils.logInfo('SharedId: Sharedid doesnt exists, new cookie creation'); - - ajax(ID_SVC, idGenerationCallback(result, callback), undefined, {method: 'GET', withCredentials: true}); + ajax(ID_SVC, idGenerationCallback(callback), undefined, {method: 'GET', withCredentials: true}); }; return {callback: resp}; }, @@ -145,17 +156,15 @@ export const sharedIdSubmodule = { * @returns {{callback: *}} */ extendId(configParams, storedId) { - utils.logInfo('SharedId: Existing shared id ' + storedId); - var result = { - id: storedId - } + utils.logInfo('SharedId: Existing shared id ' + storedId.id); const resp = function (callback) { - let existingCookie = readValue(SHARED_ID_ULID_TRACKER); - if (existingCookie) { + let needSync = storedId.ns; + if (needSync) { + utils.logInfo('SharedId: Existing shared id ' + storedId + ' is not synced'); let sharedIdPayload = {}; - sharedIdPayload.sharedId = storedId; + sharedIdPayload.sharedId = storedId.id; let payloadString = JSON.stringify(sharedIdPayload); - ajax(ID_SVC, existingIdCallback(result, callback), payloadString, {method: 'POST', withCredentials: true}); + ajax(ID_SVC, existingIdCallback(storedId, callback), payloadString, {method: 'POST', withCredentials: true}); } }; return {callback: resp}; diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 15caf52d4e7..79116e33aa7 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -15,7 +15,7 @@ const USER_IDS_CONFIG = { 'tdid': { source: 'adserver.org', atype: 1, - getUidExt: function() { + getUidExt: function () { return { rtiPartner: 'TDID' }; @@ -42,12 +42,12 @@ const USER_IDS_CONFIG = { // liveIntentId 'lipb': { - getValue: function(data) { + getValue: function (data) { return data.lipbid; }, source: 'liveintent.com', atype: 1, - getEidExt: function(data) { + getEidExt: function (data) { if (Array.isArray(data.segments) && data.segments.length) { return { segments: data.segments @@ -64,7 +64,7 @@ const USER_IDS_CONFIG = { // DigiTrust 'digitrustid': { - getValue: function(data) { + getValue: function (data) { return data.data.id; }, source: 'digitru.st', @@ -85,7 +85,15 @@ const USER_IDS_CONFIG = { // sharedid 'sharedid': { source: 'sharedid.org', - atype: 1 + atype: 1, + getValue: function (data) { + return data.first; + }, + getUidExt: function (data) { + return (data && data.third) ? { + third: data.third + } : undefined; + } } }; @@ -97,7 +105,7 @@ function createEidObject(userIdData, subModuleKey) { eid.source = conf['source']; const value = utils.isFn(conf['getValue']) ? conf['getValue'](userIdData) : userIdData; if (utils.isStr(value)) { - const uid = { id: value, atype: conf['atype'] }; + const uid = {id: value, atype: conf['atype']}; // getUidExt if (utils.isFn(conf['getUidExt'])) { const uidExt = conf['getUidExt'](userIdData); diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js index e7d1785232a..88bc9beb505 100644 --- a/test/spec/modules/eids_spec.js +++ b/test/spec/modules/eids_spec.js @@ -148,13 +148,38 @@ describe('eids array generation for known sub-modules', function() { }); it('Sharedid', function() { const userId = { - sharedid: 'test_sharedId' + sharedid: { + first: 'test_sharedId', + third: 'test_sharedId' + } + }; + const newEids = createEidsArray(userId); + expect(newEids.length).to.equal(1); + expect(newEids[0]).to.deep.equal({ + source: 'sharedid.org', + uids: [{ + id: 'test_sharedId', + atype: 1, + ext: { + third: 'test_sharedId' + } + }] + }); + }); + it('Sharedid: Not Synched', function() { + const userId = { + sharedid: { + first: 'test_sharedId' + } }; const newEids = createEidsArray(userId); expect(newEids.length).to.equal(1); expect(newEids[0]).to.deep.equal({ source: 'sharedid.org', - uids: [{id: 'test_sharedId', atype: 1}] + uids: [{ + id: 'test_sharedId', + atype: 1 + }] }); }); }); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index d319b1d81c2..7ca992e1762 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -25,7 +25,7 @@ let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; -describe('User ID', function() { +describe('User ID', function () { function getConfigMock(configArr1, configArr2, configArr3, configArr4, configArr5, configArr6, configArr7) { return { userSync: { @@ -38,15 +38,18 @@ describe('User ID', function() { (configArr5 && configArr5.length >= 3) ? getStorageMock.apply(null, configArr5) : null, (configArr6 && configArr6.length >= 3) ? getStorageMock.apply(null, configArr6) : null, (configArr7 && configArr7.length >= 3) ? getStorageMock.apply(null, configArr7) : null - ].filter(i => i)} + ].filter(i => i) + } } } + function getStorageMock(name = 'pubCommonId', key = 'pubcid', type = 'cookie', expires = 30, refreshInSeconds) { - return { name: name, storage: { name: key, type: type, expires: expires, refreshInSeconds: refreshInSeconds } } + return {name: name, storage: {name: key, type: type, expires: expires, refreshInSeconds: refreshInSeconds}} } + function getConfigValueMock(name, value) { return { - userSync: { syncDelay: 0, userIds: [{ name: name, value: value }] } + userSync: {syncDelay: 0, userIds: [{name: name, value: value}]} } } @@ -62,21 +65,25 @@ describe('User ID', function() { function addConfig(cfg, name, value) { if (cfg && cfg.userSync && cfg.userSync.userIds) { cfg.userSync.userIds.forEach(element => { - if (element[name] !== undefined) { element[name] = Object.assign(element[name], value); } else { element[name] = value; } + if (element[name] !== undefined) { + element[name] = Object.assign(element[name], value); + } else { + element[name] = value; + } }); } return cfg; } - before(function() { + before(function () { coreStorage.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); localStorage.removeItem('_pbjs_id_optout'); localStorage.removeItem('_pubcid_optout'); }); - describe('Decorate Ad Units', function() { - beforeEach(function() { + describe('Decorate Ad Units', function () { + beforeEach(function () { coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); sinon.spy(coreStorage, 'setCookie'); @@ -88,7 +95,7 @@ describe('User ID', function() { coreStorage.setCookie.restore(); }); - after(function() { + after(function () { coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('pubcid_alt', '', EXPIRED_COOKIE_DATE); }); @@ -106,7 +113,9 @@ describe('User ID', function() { init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - requestBidsHook(config => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); + requestBidsHook(config => { + innerAdUnits1 = config.adUnits + }, {adUnits: adUnits1}); pubcid = coreStorage.getCookie('pubcid'); // cookies is created after requestbidHook innerAdUnits1.forEach(unit => { @@ -120,7 +129,9 @@ describe('User ID', function() { }); }); - requestBidsHook(config => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); + requestBidsHook(config => { + innerAdUnits2 = config.adUnits + }, {adUnits: adUnits2}); assert.deepEqual(innerAdUnits1, innerAdUnits2); }); @@ -135,7 +146,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - requestBidsHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); + requestBidsHook((config) => { + innerAdUnits1 = config.adUnits + }, {adUnits: adUnits1}); pubcid1 = coreStorage.getCookie('pubcid'); // get first cookie coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); // erase cookie @@ -153,7 +166,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - requestBidsHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); + requestBidsHook((config) => { + innerAdUnits2 = config.adUnits + }, {adUnits: adUnits2}); pubcid2 = coreStorage.getCookie('pubcid'); // get second cookie @@ -178,7 +193,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie'])); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { expect(bid).to.have.deep.nested.property('userId.pubcid'); @@ -202,7 +219,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); init(config); config.setConfig(customConfig); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { expect(bid).to.have.deep.nested.property('userId.pubcid'); @@ -226,7 +245,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); init(config); config.setConfig(customConfig); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); innerAdUnits.forEach((unit) => { unit.bids.forEach((bid) => { expect(bid).to.not.have.deep.nested.property('userId.pubcid'); @@ -295,7 +316,7 @@ describe('User ID', function() { it('handles config with empty usersync object', function () { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); - config.setConfig({ userSync: {} }); + config.setConfig({userSync: {}}); expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); @@ -317,10 +338,10 @@ describe('User ID', function() { userSync: { userIds: [{ name: '', - value: { test: '1' } + value: {test: '1'} }, { name: 'foo', - value: { test: '1' } + value: {test: '1'} }] } }); @@ -345,26 +366,26 @@ describe('User ID', function() { name: 'pubCommonId', value: {'pubcid': '11111'} }, { name: 'unifiedId', - storage: { name: 'unifiedid', type: 'cookie' } + storage: {name: 'unifiedid', type: 'cookie'} }, { name: 'id5Id', - storage: { name: 'id5id', type: 'cookie' } + storage: {name: 'id5id', type: 'cookie'} }, { name: 'identityLink', - storage: { name: 'idl_env', type: 'cookie' } + storage: {name: 'idl_env', type: 'cookie'} }, { name: 'liveIntentId', - storage: { name: '_li_pbid', type: 'cookie' } + storage: {name: '_li_pbid', type: 'cookie'} }, { name: 'britepoolId', - value: { 'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd' } + value: {'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd'} }, { name: 'netId', - storage: { name: 'netId', type: 'cookie' } + storage: {name: 'netId', type: 'cookie'} }, { name: 'sharedId', - storage: { name: 'sharedid', type: 'cookie' } - } ] + storage: {name: 'sharedid', type: 'cookie'} + }] } }); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 8 submodules'); @@ -378,7 +399,7 @@ describe('User ID', function() { syncDelay: 99, userIds: [{ name: 'unifiedId', - storage: { name: 'unifiedid', type: 'cookie' } + storage: {name: 'unifiedid', type: 'cookie'} }] } }); @@ -393,7 +414,7 @@ describe('User ID', function() { auctionDelay: 100, userIds: [{ name: 'unifiedId', - storage: { name: 'unifiedid', type: 'cookie' } + storage: {name: 'unifiedid', type: 'cookie'} }] } }); @@ -408,7 +429,7 @@ describe('User ID', function() { auctionDelay: '', userIds: [{ name: 'unifiedId', - storage: { name: 'unifiedid', type: 'cookie' } + storage: {name: 'unifiedid', type: 'cookie'} }] } }); @@ -416,13 +437,13 @@ describe('User ID', function() { }); }); - describe('auction and user sync delays', function() { + describe('auction and user sync delays', function () { let sandbox; let adUnits; let mockIdCallback; let auctionSpy; - beforeEach(function() { + beforeEach(function () { sandbox = sinon.createSandbox(); sandbox.stub(global, 'setTimeout').returns(2); sandbox.stub(events, 'on'); @@ -436,12 +457,12 @@ describe('User ID', function() { mockIdCallback = sandbox.stub(); const mockIdSystem = { name: 'mockId', - decode: function(value) { + decode: function (value) { return { 'mid': value['MOCKID'] }; }, - getId: function() { + getId: function () { const storedId = coreStorage.getCookie('MOCKID'); if (storedId) { return {id: {'MOCKID': storedId}}; @@ -461,13 +482,13 @@ describe('User ID', function() { sandbox.restore(); }); - it('delays auction if auctionDelay is set, timing out at auction delay', function() { + it('delays auction if auctionDelay is set, timing out at auction delay', function () { config.setConfig({ userSync: { auctionDelay: 33, syncDelay: 77, userIds: [{ - name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + name: 'mockId', storage: {name: 'MOCKID', type: 'cookie'} }] } }); @@ -494,13 +515,13 @@ describe('User ID', function() { events.on.called.should.equal(false); }); - it('delays auction if auctionDelay is set, continuing auction if ids are fetched before timing out', function(done) { + it('delays auction if auctionDelay is set, continuing auction if ids are fetched before timing out', function (done) { config.setConfig({ userSync: { auctionDelay: 33, syncDelay: 77, userIds: [{ - name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + name: 'mockId', storage: {name: 'MOCKID', type: 'cookie'} }] } }); @@ -533,12 +554,12 @@ describe('User ID', function() { events.on.called.should.equal(false); }); - it('does not delay auction if not set, delays id fetch after auction ends with syncDelay', function() { + it('does not delay auction if not set, delays id fetch after auction ends with syncDelay', function () { config.setConfig({ userSync: { syncDelay: 77, userIds: [{ - name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + name: 'mockId', storage: {name: 'MOCKID', type: 'cookie'} }] } }); @@ -569,12 +590,12 @@ describe('User ID', function() { mockIdCallback.calledOnce.should.equal(true); }); - it('does not delay user id sync after auction ends if set to 0', function() { + it('does not delay user id sync after auction ends if set to 0', function () { config.setConfig({ userSync: { syncDelay: 0, userIds: [{ - name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + name: 'mockId', storage: {name: 'MOCKID', type: 'cookie'} }] } }); @@ -598,7 +619,7 @@ describe('User ID', function() { mockIdCallback.calledOnce.should.equal(true); }); - it('does not delay auction if there are no ids to fetch', function() { + it('does not delay auction if there are no ids to fetch', function () { coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); config.setConfig({ @@ -606,7 +627,7 @@ describe('User ID', function() { auctionDelay: 200, syncDelay: 77, userIds: [{ - name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + name: 'mockId', storage: {name: 'MOCKID', type: 'cookie'} }] } }); @@ -622,21 +643,21 @@ describe('User ID', function() { }); }); - describe('Request bids hook appends userId to bid objs in adapters', function() { + describe('Request bids hook appends userId to bid objs in adapters', function () { let adUnits; - beforeEach(function() { + beforeEach(function () { adUnits = [getAdUnitMock()]; }); - it('test hook from pubcommonid cookie', function(done) { + it('test hook from pubcommonid cookie', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.pubcid'); @@ -652,12 +673,12 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from pubcommonid config value object', function(done) { + it('test hook from pubcommonid config value object', function (done) { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigValueMock('pubCommonId', {'pubcidvalue': 'testpubcidvalue'})); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.pubcidvalue'); @@ -669,7 +690,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from pubcommonid html5', function(done) { + it('test hook from pubcommonid html5', function (done) { // simulate existing browser local storage values localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); @@ -678,14 +699,14 @@ describe('User ID', function() { init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid_alt', 'html5'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.tdid'); expect(bid.userId.tdid).to.equal('testunifiedid_alt'); expect(bid.userIdAsEids[0]).to.deep.equal({ source: 'adserver.org', - uids: [{id: 'testunifiedid_alt', atype: 1, ext: { rtiPartner: 'TDID' }}] + uids: [{id: 'testunifiedid_alt', atype: 1, ext: {rtiPartner: 'TDID'}}] }); }); }); @@ -695,7 +716,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from identityLink html5', function(done) { + it('test hook from identityLink html5', function (done) { // simulate existing browser local storage values localStorage.setItem('idl_env', 'AiGNC8Z5ONyZKSpIPf'); localStorage.setItem('idl_env_exp', ''); @@ -703,7 +724,7 @@ describe('User ID', function() { setSubmoduleRegistry([identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['identityLink', 'idl_env', 'html5'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.idl_env'); @@ -720,14 +741,14 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from identityLink cookie', function(done) { + it('test hook from identityLink cookie', function (done) { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['identityLink', 'idl_env', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.idl_env'); @@ -743,7 +764,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from liveIntentId html5', function(done) { + it('test hook from liveIntentId html5', function (done) { // simulate existing browser local storage values localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier'})); localStorage.setItem('_li_pbid_exp', ''); @@ -751,7 +772,7 @@ describe('User ID', function() { setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'html5'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -768,14 +789,14 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from liveIntentId cookie', function(done) { + it('test hook from liveIntentId cookie', function (done) { coreStorage.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier'}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -791,22 +812,64 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from sharedId html5', function(done) { + it('test hook from sharedId html5', function (done) { + // simulate existing browser local storage values + localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId'})); + localStorage.setItem('sharedid_exp', ''); + + setSubmoduleRegistry([sharedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['sharedId', 'sharedid', 'html5'])); + requestBidsHook(function () { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.have.deep.nested.property('third'); + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId', + third: 'test_sharedId' + }); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'sharedid.org', + uids: [{ + id: 'test_sharedId', + atype: 1, + ext: { + third: 'test_sharedId' + } + }] + }); + }); + }); + localStorage.removeItem('sharedid'); + localStorage.removeItem('sharedid_exp'); + done(); + }, {adUnits}); + }); + + it('test hook from sharedId html5 (id not synced)', function (done) { // simulate existing browser local storage values - localStorage.setItem('sharedid', JSON.stringify({'sharedid': 'test_sharedId'})); + localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true})); localStorage.setItem('sharedid_exp', ''); setSubmoduleRegistry([sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['sharedId', 'sharedid', 'html5'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.equal('test_sharedId'); + expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId' + }); expect(bid.userIdAsEids[0]).to.deep.equal({ source: 'sharedid.org', - uids: [{id: 'test_sharedId', atype: 1}] + uids: [{ + id: 'test_sharedId', + atype: 1 + }] }); }); }); @@ -815,21 +878,33 @@ describe('User ID', function() { done(); }, {adUnits}); }); - it('test hook from sharedId cookie', function(done) { - coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), (new Date(Date.now() + 100000).toUTCString())); + + it('test hook from sharedId cookie', function (done) { + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.equal('test_sharedId'); + expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.have.deep.nested.property('third'); + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId', + third: 'test_sharedId' + }); expect(bid.userIdAsEids[0]).to.deep.equal({ source: 'sharedid.org', - uids: [{id: 'test_sharedId', atype: 1}] + uids: [{ + id: 'test_sharedId', + atype: 1, + ext: { + third: 'test_sharedId' + } + }] }); }); }); @@ -837,7 +912,35 @@ describe('User ID', function() { done(); }, {adUnits}); }); - it('test hook from id5id cookies when refresh needed', function(done) { + it('test hook from sharedId cookie (id not synced) ', function (done) { + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true}), (new Date(Date.now() + 100000).toUTCString())); + + setSubmoduleRegistry([sharedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); + + requestBidsHook(function () { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + expect(bid).to.have.deep.nested.property('userId.sharedid'); + expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId' + }); + expect(bid.userIdAsEids[0]).to.deep.equal({ + source: 'sharedid.org', + uids: [{ + id: 'test_sharedId', + atype: 1 + }] + }); + }); + }); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + it('test hook from id5id cookies when refresh needed', function (done) { // simulate existing browser local storage values coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id_last', (new Date(Date.now() - 7200 * 1000)).toUTCString(), (new Date(Date.now() + 5000).toUTCString())); @@ -848,7 +951,7 @@ describe('User ID', function() { init(config); config.setConfig(getConfigMock(['id5Id', 'id5id', 'cookie', 10, 3600])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.id5id'); @@ -866,12 +969,12 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from id5id value-based config', function(done) { + it('test hook from id5id value-based config', function (done) { setSubmoduleRegistry([id5IdSubmodule]); init(config); config.setConfig(getConfigValueMock('id5Id', {'id5id': 'testid5id'})); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.id5id'); @@ -886,7 +989,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from liveIntentId html5', function(done) { + it('test hook from liveIntentId html5', function (done) { // simulate existing browser local storage values localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier', 'segments': ['123']})); localStorage.setItem('_li_pbid_exp', ''); @@ -894,7 +997,7 @@ describe('User ID', function() { setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'html5'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -913,14 +1016,17 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from liveIntentId cookie', function(done) { - coreStorage.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier', 'segments': ['123']}), (new Date(Date.now() + 100000).toUTCString())); + it('test hook from liveIntentId cookie', function (done) { + coreStorage.setCookie('_li_pbid', JSON.stringify({ + 'unifiedId': 'random-cookie-identifier', + 'segments': ['123'] + }), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -938,7 +1044,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from britepoolid cookies', function(done) { + it('test hook from britepoolid cookies', function (done) { // simulate existing browser local storage values coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd'}), (new Date(Date.now() + 5000).toUTCString())); @@ -946,7 +1052,7 @@ describe('User ID', function() { init(config); config.setConfig(getConfigMock(['britepoolId', 'britepoolid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.britepoolid'); @@ -962,7 +1068,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook from netId cookies', function(done) { + it('test hook from netId cookies', function (done) { // simulate existing browser local storage values coreStorage.setCookie('netId', JSON.stringify({'netId': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg'}), (new Date(Date.now() + 5000).toUTCString())); @@ -970,7 +1076,7 @@ describe('User ID', function() { init(config); config.setConfig(getConfigMock(['netId', 'netId', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.netId'); @@ -986,14 +1092,14 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId have data to pass', function(done) { + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId have data to pass', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); @@ -1005,7 +1111,7 @@ describe('User ID', function() { ['netId', 'netId', 'cookie'], ['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { // verify that the PubCommonId id data was copied to bid @@ -1027,7 +1133,10 @@ describe('User ID', function() { expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.equal('test_sharedId'); + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId', + third: 'test_sharedId' + }); expect(bid.userIdAsEids.length).to.equal(7); }); }); @@ -1042,14 +1151,14 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId have their modules added before and after init', function(done) { + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId have their modules added before and after init', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -1074,7 +1183,7 @@ describe('User ID', function() { ['netId', 'netId', 'cookie'], ['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { // verify that the PubCommonId id data was copied to bid @@ -1096,7 +1205,10 @@ describe('User ID', function() { expect(bid).to.have.deep.nested.property('userId.netId'); expect(bid.userId.netId).to.equal('testnetId'); expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.equal('test_sharedId'); + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId', + third: 'test_sharedId' + }); expect(bid.userIdAsEids.length).to.equal(7); }); }); @@ -1111,14 +1223,14 @@ describe('User ID', function() { }, {adUnits}); }); - it('should add new id system ', function(done) { + it('should add new id system ', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); - coreStorage.setCookie('sharedid', JSON.stringify({'sharedid': 'test_sharedId'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); @@ -1128,21 +1240,21 @@ describe('User ID', function() { userSync: { syncDelay: 0, userIds: [{ - name: 'pubCommonId', storage: { name: 'pubcid', type: 'cookie' } + name: 'pubCommonId', storage: {name: 'pubcid', type: 'cookie'} }, { - name: 'unifiedId', storage: { name: 'unifiedid', type: 'cookie' } + name: 'unifiedId', storage: {name: 'unifiedid', type: 'cookie'} }, { - name: 'id5Id', storage: { name: 'id5id', type: 'cookie' } + name: 'id5Id', storage: {name: 'id5id', type: 'cookie'} }, { - name: 'identityLink', storage: { name: 'idl_env', type: 'cookie' } + name: 'identityLink', storage: {name: 'idl_env', type: 'cookie'} }, { - name: 'britepoolId', storage: { name: 'britepoolid', type: 'cookie' } + name: 'britepoolId', storage: {name: 'britepoolid', type: 'cookie'} }, { - name: 'netId', storage: { name: 'netId', type: 'cookie' } + name: 'netId', storage: {name: 'netId', type: 'cookie'} }, { name: 'sharedId', storage: {name: 'sharedid', type: 'cookie'} }, { - name: 'mockId', storage: { name: 'MOCKID', type: 'cookie' } + name: 'mockId', storage: {name: 'MOCKID', type: 'cookie'} }] } }); @@ -1150,18 +1262,18 @@ describe('User ID', function() { // Add new submodule named 'mockId' attachIdSystem({ name: 'mockId', - decode: function(value) { + decode: function (value) { return { 'mid': value['MOCKID'] }; }, - getId: function(params, storedId) { + getId: function (params, storedId) { if (storedId) return {}; return {id: {'MOCKID': '1234'}}; } }); - requestBidsHook(function() { + requestBidsHook(function () { adUnits.forEach(unit => { unit.bids.forEach(bid => { // check PubCommonId id data was copied to bid @@ -1184,7 +1296,10 @@ describe('User ID', function() { expect(bid.userId.netId).to.equal('testnetId'); // also check that sharedId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.equal('test_sharedId') + expect(bid.userId.sharedid).to.deep.equal({ + first: 'test_sharedId', + third: 'test_sharedId' + }); // check MockId data was copied to bid expect(bid).to.have.deep.nested.property('userId.mid'); expect(bid.userId.mid).to.equal('123456778'); @@ -1204,8 +1319,8 @@ describe('User ID', function() { }); }); - describe('callbacks at the end of auction', function() { - beforeEach(function() { + describe('callbacks at the end of auction', function () { + beforeEach(function () { sinon.stub(events, 'getEvents').returns([]); sinon.stub(utils, 'triggerPixel'); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -1213,7 +1328,7 @@ describe('User ID', function() { coreStorage.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); - afterEach(function() { + afterEach(function () { events.getEvents.restore(); utils.triggerPixel.restore(); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -1230,7 +1345,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); init(config); config.setConfig(customCfg); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); expect(utils.triggerPixel.called).to.be.false; events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); @@ -1246,7 +1363,9 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); init(config); config.setConfig(customCfg); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); expect(server.requests).to.be.empty; events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); @@ -1262,14 +1381,16 @@ describe('User ID', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule]); init(config); config.setConfig(customCfg); - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); expect(server.requests).to.be.empty; events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); expect(server.requests[0].url).to.equal('https://match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); }); - it('callback for submodules that always need to refresh stored id', function(done) { + it('callback for submodules that always need to refresh stored id', function (done) { let adUnits = [getAdUnitMock()]; let innerAdUnits; const parrableStoredId = '01.1111111111.test-eid'; @@ -1278,12 +1399,12 @@ describe('User ID', function() { const parrableIdSubmoduleMock = { name: 'parrableId', - decode: function(value) { - return { 'parrableid': value }; + decode: function (value) { + return {'parrableid': value}; }, - getId: function() { + getId: function () { return { - callback: function(cb) { + callback: function (cb) { cb(parrableRefreshedId); } }; @@ -1309,7 +1430,9 @@ describe('User ID', function() { config.setConfig(parrableConfigMock); // make first bid request, should use stored id value - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); innerAdUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.parrableid'); @@ -1325,7 +1448,9 @@ describe('User ID', function() { events.on(CONSTANTS.EVENTS.AUCTION_END, function handler(submodule) { if (submodule === 'parrableIdSubmoduleMock') { // make the second bid request, id should have been refreshed - requestBidsHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); + requestBidsHook((config) => { + innerAdUnits = config.adUnits + }, {adUnits}); innerAdUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.parrableid'); From ba08669d5096ceba8205b94b7e7394a8b1819351 Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 4 May 2020 11:36:54 -0700 Subject: [PATCH 15/34] Updating endpoint --- integrationExamples/gpt/testrunner.html | 20 -------------------- modules/sharedIdSystem.js | 4 ++-- 2 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 integrationExamples/gpt/testrunner.html diff --git a/integrationExamples/gpt/testrunner.html b/integrationExamples/gpt/testrunner.html deleted file mode 100644 index 47d9f157153..00000000000 --- a/integrationExamples/gpt/testrunner.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Mocha Tests - - - -
- - - - - - - - - - - - diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 26d97558762..d8f7d269937 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -11,7 +11,7 @@ import {submodule} from '../src/hook.js'; import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; const MODULE_NAME = 'sharedId'; -const ID_SVC = 'https://id-qa.sharedid.org/id'; +const ID_SVC = 'https://id.sharedid.org/id'; /** * Constructs cookie value @@ -25,7 +25,7 @@ function constructCookieValue(value, needSync) { if (needSync) { cookieValue.ns = true; } - utils.logInfo('SharedId: cookie Value: ' + cookieValue); + utils.logInfo('SharedId: cookie Value: ' + JSON.stringify(cookieValue)); return cookieValue; } From 21dea574ae93ef7ff22b36a88c52d010350bbaf9 Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 4 May 2020 12:19:48 -0700 Subject: [PATCH 16/34] Updaitng eids.md --- modules/userId/eids.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/userId/eids.md b/modules/userId/eids.md index 0ca03c90cb7..60f450e9328 100644 --- a/modules/userId/eids.md +++ b/modules/userId/eids.md @@ -90,8 +90,11 @@ userIdAsEids = [ source: 'sharedid.org', uids: [{ id: 'some-random-id-value', - atype: 1 - }] + atype: 1, + ext: { + third: 'some-random-id-value' + } + }] } ] ``` From 649b593a780e6b8b566bec06896ae2128abcaf05 Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 26 May 2020 15:36:10 -0700 Subject: [PATCH 17/34] Configured sync --- integrationExamples/gpt/userId_example.html | 3 + modules/sharedIdSystem.js | 32 ++++- test/spec/modules/userId_spec.js | 137 ++++++++++++++++++-- 3 files changed, 163 insertions(+), 9 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 8f0be9adecc..515519c5e16 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -186,6 +186,9 @@ } }, { name: "sharedId", + params: { + sycTime: 1 // in hours, default is 24 hours + }, storage: { type: "cookie", name: "sharedid", diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index d8f7d269937..7785ffb251f 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -12,6 +12,8 @@ import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; const MODULE_NAME = 'sharedId'; const ID_SVC = 'https://id.sharedid.org/id'; +const DEFAULT_SYNC_TIME_IN_HOURS = 24; +const OPT_OUT_VALUE = '00000000000000000000000000'; /** * Constructs cookie value @@ -22,6 +24,7 @@ const ID_SVC = 'https://id.sharedid.org/id'; function constructCookieValue(value, needSync) { let cookieValue = {}; cookieValue.id = value; + cookieValue.ts = utils.timestamp(); if (needSync) { cookieValue.ns = true; } @@ -29,6 +32,30 @@ function constructCookieValue(value, needSync) { return cookieValue; } +/** + * Checks if id needs to be synced + * @param configParams + * @param storedId + * @returns {boolean} + */ +function isIdSynced(configParams, storedId) { + var needSync = storedId.ns; + if (needSync) { + return true; + } + if (!configParams || typeof configParams.sycTime !== 'number') { + utils.logInfo('SharedId: Sync time is not configured or is not a number'); + } + var syncTime = (!configParams || typeof configParams.sycTime !== 'number') ? DEFAULT_SYNC_TIME_IN_HOURS : configParams.sycTime; + var timestamp = storedId.ts; + if (timestamp) { + var date = new Date(timestamp); + var hoursago = Date.now() - syncTime * 1000 * 60 * 60; + return date < hoursago; + } + return false; +} + /** * id generation call back * @param result @@ -99,6 +126,9 @@ function encodeId(value) { try { let result = {}; let sharedId = (value && typeof value['id'] === 'string') ? value['id'] : undefined; + if (sharedId == OPT_OUT_VALUE) { + return undefined; + } if (sharedId) { var bidIds = { first: sharedId, @@ -158,7 +188,7 @@ export const sharedIdSubmodule = { extendId(configParams, storedId) { utils.logInfo('SharedId: Existing shared id ' + storedId.id); const resp = function (callback) { - let needSync = storedId.ns; + let needSync = isIdSynced(configParams, storedId); if (needSync) { utils.logInfo('SharedId: Existing shared id ' + storedId + ' is not synced'); let sharedIdPayload = {}; diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 7ca992e1762..29e06c6d467 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -814,7 +814,7 @@ describe('User ID', function () { it('test hook from sharedId html5', function (done) { // simulate existing browser local storage values - localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId'})); + localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611})); localStorage.setItem('sharedid_exp', ''); setSubmoduleRegistry([sharedIdSubmodule]); @@ -850,7 +850,7 @@ describe('User ID', function () { it('test hook from sharedId html5 (id not synced)', function (done) { // simulate existing browser local storage values - localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true})); + localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true, 'ts': 1590525289611})); localStorage.setItem('sharedid_exp', ''); setSubmoduleRegistry([sharedIdSubmodule]); @@ -878,9 +878,8 @@ describe('User ID', function () { done(); }, {adUnits}); }); - it('test hook from sharedId cookie', function (done) { - coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([sharedIdSubmodule]); init(config); @@ -913,7 +912,7 @@ describe('User ID', function () { }, {adUnits}); }); it('test hook from sharedId cookie (id not synced) ', function (done) { - coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true}), (new Date(Date.now() + 100000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true, 'ts': 1590525289611}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([sharedIdSubmodule]); init(config); @@ -1099,7 +1098,7 @@ describe('User ID', function () { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); @@ -1151,6 +1150,60 @@ describe('User ID', function () { }, {adUnits}); }); + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId (opted out) have data to pass', function (done) { + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': '00000000000000000000000000', 'ts': 1590525289611}), (new Date(Date.now() + 5000).toUTCString())); + + setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); + init(config); + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'], + ['identityLink', 'idl_env', 'cookie'], + ['britepoolId', 'britepoolid', 'cookie'], + ['netId', 'netId', 'cookie'], + ['sharedId', 'sharedid', 'cookie'])); + + requestBidsHook(function () { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + // verify that the PubCommonId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('testpubcid'); + // also check that UnifiedId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.tdid'); + expect(bid.userId.tdid).to.equal('testunifiedid'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); + // check that identityLink id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.idl_env'); + expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); + // also check that britepoolId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.britepoolid'); + expect(bid.userId.britepoolid).to.equal('testbritepoolid'); + // also check that netId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.netId'); + expect(bid.userId.netId).to.equal('testnetId'); + expect(bid.userIdAsEids.length).to.equal(6); + }); + }); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId have their modules added before and after init', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); @@ -1158,7 +1211,7 @@ describe('User ID', function () { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); @@ -1223,6 +1276,74 @@ describe('User ID', function () { }, {adUnits}); }); + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId(opted out) have their modules added before and after init', function (done) { + coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + coreStorage.setCookie('sharedid', JSON.stringify({'id': '00000000000000000000000000', 'ts': 1590525289611}), (new Date(Date.now() + 5000).toUTCString())); + + setSubmoduleRegistry([]); + + // attaching before init + attachIdSystem(pubCommonIdSubmodule); + + init(config); + + // attaching after init + attachIdSystem(unifiedIdSubmodule); + attachIdSystem(id5IdSubmodule); + attachIdSystem(identityLinkSubmodule); + attachIdSystem(britepoolIdSubmodule); + attachIdSystem(netIdSubmodule); + attachIdSystem(sharedIdSubmodule); + + config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], + ['unifiedId', 'unifiedid', 'cookie'], + ['id5Id', 'id5id', 'cookie'], + ['identityLink', 'idl_env', 'cookie'], + ['britepoolId', 'britepoolid', 'cookie'], + ['netId', 'netId', 'cookie'], + ['sharedId', 'sharedid', 'cookie'])); + + requestBidsHook(function () { + adUnits.forEach(unit => { + unit.bids.forEach(bid => { + // verify that the PubCommonId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.pubcid'); + expect(bid.userId.pubcid).to.equal('testpubcid'); + // also check that UnifiedId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.tdid'); + expect(bid.userId.tdid).to.equal('cookie-value-add-module-variations'); + // also check that Id5Id id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.id5id'); + expect(bid.userId.id5id).to.equal('testid5id'); + // also check that identityLink id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.idl_env'); + expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); + // also check that britepoolId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.britepoolid'); + expect(bid.userId.britepoolid).to.equal('testbritepoolid'); + // also check that britepoolId id data was copied to bid + expect(bid).to.have.deep.nested.property('userId.netId'); + expect(bid.userId.netId).to.equal('testnetId'); + + expect(bid.userIdAsEids.length).to.equal(6); + }); + }); + coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); + coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); + done(); + }, {adUnits}); + }); + it('should add new id system ', function (done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); @@ -1230,7 +1351,7 @@ describe('User ID', function () { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), new Date(Date.now() + 5000).toUTCString()); - coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId'}), new Date(Date.now() + 5000).toUTCString()); + coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); From 584abb5d0dd8d161c2b0a2ece8c3b98ff71a9ae5 Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 26 May 2020 15:47:51 -0700 Subject: [PATCH 18/34] Refactor and md update --- integrationExamples/gpt/userId_example.html | 2 +- modules/sharedIdSystem.js | 4 ++-- modules/sharedIdSystem.md | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 515519c5e16..4be478f3c54 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -187,7 +187,7 @@ }, { name: "sharedId", params: { - sycTime: 1 // in hours, default is 24 hours + syncTime: 1 // in hours, default is 24 hours }, storage: { type: "cookie", diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 7785ffb251f..11b01e08e77 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -43,10 +43,10 @@ function isIdSynced(configParams, storedId) { if (needSync) { return true; } - if (!configParams || typeof configParams.sycTime !== 'number') { + if (!configParams || typeof configParams.syncTime !== 'number') { utils.logInfo('SharedId: Sync time is not configured or is not a number'); } - var syncTime = (!configParams || typeof configParams.sycTime !== 'number') ? DEFAULT_SYNC_TIME_IN_HOURS : configParams.sycTime; + var syncTime = (!configParams || typeof configParams.syncTime !== 'number') ? DEFAULT_SYNC_TIME_IN_HOURS : configParams.syncTime; var timestamp = storedId.ts; if (timestamp) { var date = new Date(timestamp); diff --git a/modules/sharedIdSystem.md b/modules/sharedIdSystem.md index 77c48e03311..849761d601f 100644 --- a/modules/sharedIdSystem.md +++ b/modules/sharedIdSystem.md @@ -17,6 +17,9 @@ pbjs.setConfig({ usersync: { userIds: [{ name: 'sharedId', + params: { + syncTime: 1 // in hours, default is 24 hours + }, storage: { name: 'sharedid', type: 'cookie', @@ -33,6 +36,8 @@ The below parameters apply only to the Shared ID User ID Module integration. | Params under usersync.userIds[]| Scope | Type | Description | Example | | --- | --- | --- | --- | --- | | name | Required | String | ID value for the Shared ID module - `"sharedId"` | `"sharedId"` | +| params | Optional | Object | Details for sharedId syncing. | | +| params.syncTime | Required | Object | Configuration to define the frequency(in hours) of id synchronization. By default id is synchronized every 24 hours | 24 | | storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | | storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | | storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedid"` | From 6729c1045252151cbd8089fdf4baca343d2ec476 Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 27 May 2020 09:28:42 -0700 Subject: [PATCH 19/34] Refactoring --- modules/sharedIdSystem.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 11b01e08e77..0f9cc145a56 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -18,14 +18,14 @@ const OPT_OUT_VALUE = '00000000000000000000000000'; /** * Constructs cookie value * @param value - * @param needSync + * @param needsSync * @returns {string} */ -function constructCookieValue(value, needSync) { +function constructCookieValue(value, needsSync) { let cookieValue = {}; cookieValue.id = value; cookieValue.ts = utils.timestamp(); - if (needSync) { + if (needsSync) { cookieValue.ns = true; } utils.logInfo('SharedId: cookie Value: ' + JSON.stringify(cookieValue)); From 46e9efaae108b476e2bd041846736b1f2a9af5ed Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 27 May 2020 10:30:39 -0700 Subject: [PATCH 20/34] Refactoring --- modules/sharedIdSystem.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 0f9cc145a56..e2ac725e764 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -49,9 +49,8 @@ function isIdSynced(configParams, storedId) { var syncTime = (!configParams || typeof configParams.syncTime !== 'number') ? DEFAULT_SYNC_TIME_IN_HOURS : configParams.syncTime; var timestamp = storedId.ts; if (timestamp) { - var date = new Date(timestamp); - var hoursago = Date.now() - syncTime * 1000 * 60 * 60; - return date < hoursago; + var hoursago = utils.timestamp() - syncTime * 1000 * 60 * 60; + return timestamp < hoursago; } return false; } From 91255b00d85371f1940032a83c2acb4079c5040d Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 27 May 2020 14:36:10 -0700 Subject: [PATCH 21/34] Updating sync to seconds --- integrationExamples/gpt/userId_example.html | 2 +- modules/sharedIdSystem.js | 26 ++++++++++++++++----- modules/sharedIdSystem.md | 4 ++-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 4be478f3c54..f1465c32e29 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -187,7 +187,7 @@ }, { name: "sharedId", params: { - syncTime: 1 // in hours, default is 24 hours + syncTime: 1 // in seconds, default is 24 hours }, storage: { type: "cookie", diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index e2ac725e764..3733f25d769 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -12,7 +12,7 @@ import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; const MODULE_NAME = 'sharedId'; const ID_SVC = 'https://id.sharedid.org/id'; -const DEFAULT_SYNC_TIME_IN_HOURS = 24; +const DEFAULT_24_HOURS = 86400; const OPT_OUT_VALUE = '00000000000000000000000000'; /** @@ -46,15 +46,29 @@ function isIdSynced(configParams, storedId) { if (!configParams || typeof configParams.syncTime !== 'number') { utils.logInfo('SharedId: Sync time is not configured or is not a number'); } - var syncTime = (!configParams || typeof configParams.syncTime !== 'number') ? DEFAULT_SYNC_TIME_IN_HOURS : configParams.syncTime; - var timestamp = storedId.ts; - if (timestamp) { - var hoursago = utils.timestamp() - syncTime * 1000 * 60 * 60; - return timestamp < hoursago; + var syncTime = (!configParams || typeof configParams.syncTime !== 'number') ? DEFAULT_24_HOURS : configParams.syncTime; + if (syncTime > DEFAULT_24_HOURS) { + syncTime = DEFAULT_24_HOURS; + } + var cookieTimestamp = storedId.ts; + if (cookieTimestamp) { + var secondBetweenTwoDate = timeDifferenceInSeconds(utils.timestamp(), cookieTimestamp); + return secondBetweenTwoDate >= syncTime; } return false; } +/** + * Gets time difference in secounds + * @param date1 + * @param date2 + * @returns {number} + */ +function timeDifferenceInSeconds(date1, date2) { + var diff = (date1 - date2) / 1000; + return Math.abs(Math.round(diff)); +} + /** * id generation call back * @param result diff --git a/modules/sharedIdSystem.md b/modules/sharedIdSystem.md index 849761d601f..c5e42e8dafa 100644 --- a/modules/sharedIdSystem.md +++ b/modules/sharedIdSystem.md @@ -18,7 +18,7 @@ pbjs.setConfig({ userIds: [{ name: 'sharedId', params: { - syncTime: 1 // in hours, default is 24 hours + syncTime: 1 // in seconds, default is 24 hours }, storage: { name: 'sharedid', @@ -37,7 +37,7 @@ The below parameters apply only to the Shared ID User ID Module integration. | --- | --- | --- | --- | --- | | name | Required | String | ID value for the Shared ID module - `"sharedId"` | `"sharedId"` | | params | Optional | Object | Details for sharedId syncing. | | -| params.syncTime | Required | Object | Configuration to define the frequency(in hours) of id synchronization. By default id is synchronized every 24 hours | 24 | +| params.syncTime | Optional | Object | Configuration to define the frequency(in seconds) of id synchronization. By default id is synchronized every 24 hours | 24 | | storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | | storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | | storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedid"` | From b6721a32f8b6e345b1e487f81328296070f33237 Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 27 May 2020 16:07:54 -0700 Subject: [PATCH 22/34] Updating configuration --- integrationExamples/gpt/userId_example.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index f1465c32e29..b3f293580ff 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -187,7 +187,7 @@ }, { name: "sharedId", params: { - syncTime: 1 // in seconds, default is 24 hours + syncTime: 60 // in seconds, default is 24 hours }, storage: { type: "cookie", From 4e16a0f29bc62a4f3e8880ff00b6dd134311c923 Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 28 May 2020 09:31:26 -0700 Subject: [PATCH 23/34] Reformatting --- modules/userId/eids.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 79116e33aa7..21a3ef6e984 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -15,7 +15,7 @@ const USER_IDS_CONFIG = { 'tdid': { source: 'adserver.org', atype: 1, - getUidExt: function () { + getUidExt: function() { return { rtiPartner: 'TDID' }; @@ -42,12 +42,12 @@ const USER_IDS_CONFIG = { // liveIntentId 'lipb': { - getValue: function (data) { + getValue: function(data) { return data.lipbid; }, source: 'liveintent.com', atype: 1, - getEidExt: function (data) { + getEidExt: function(data) { if (Array.isArray(data.segments) && data.segments.length) { return { segments: data.segments @@ -64,7 +64,7 @@ const USER_IDS_CONFIG = { // DigiTrust 'digitrustid': { - getValue: function (data) { + getValue: function(data) { return data.data.id; }, source: 'digitru.st', @@ -86,7 +86,7 @@ const USER_IDS_CONFIG = { 'sharedid': { source: 'sharedid.org', atype: 1, - getValue: function (data) { + getValue: function(data) { return data.first; }, getUidExt: function (data) { @@ -105,7 +105,7 @@ function createEidObject(userIdData, subModuleKey) { eid.source = conf['source']; const value = utils.isFn(conf['getValue']) ? conf['getValue'](userIdData) : userIdData; if (utils.isStr(value)) { - const uid = {id: value, atype: conf['atype']}; + const uid = { id: value, atype: conf['atype'] }; // getUidExt if (utils.isFn(conf['getUidExt'])) { const uidExt = conf['getUidExt'](userIdData); From d832997df87e17882442aec85ea2363b5038a5fb Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 28 May 2020 09:35:59 -0700 Subject: [PATCH 24/34] Reformatting --- modules/userId/eids.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 21a3ef6e984..23817f92b4b 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -89,7 +89,7 @@ const USER_IDS_CONFIG = { getValue: function(data) { return data.first; }, - getUidExt: function (data) { + getUidExt: function(data) { return (data && data.third) ? { third: data.third } : undefined; From 26d694b172fd23f8e1aff4f1cb738dbb792f1d92 Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 28 May 2020 09:58:34 -0700 Subject: [PATCH 25/34] Reformatting --- modules/userId/userId.md | 5 +- test/spec/modules/userId_spec.js | 196 +++++++++++++++---------------- 2 files changed, 102 insertions(+), 99 deletions(-) diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 1bf3db92703..17c0b5fef7f 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -66,11 +66,14 @@ pbjs.setConfig({ } }, { name: 'sharedId', + params: { + syncTime: 3600 // in seconds, default is 24 hours + }, storage: { type: 'cookie', name: 'sharedid', expires: 28 - } + } }], syncDelay: 5000, auctionDelay: 1000 diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 29e06c6d467..ef7253047be 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -25,7 +25,7 @@ let assert = require('chai').assert; let expect = require('chai').expect; const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; -describe('User ID', function () { +describe('User ID', function() { function getConfigMock(configArr1, configArr2, configArr3, configArr4, configArr5, configArr6, configArr7) { return { userSync: { @@ -76,31 +76,31 @@ describe('User ID', function () { return cfg; } - before(function () { + before(function() { coreStorage.setCookie('_pubcid_optout', '', EXPIRED_COOKIE_DATE); localStorage.removeItem('_pbjs_id_optout'); localStorage.removeItem('_pubcid_optout'); }); - describe('Decorate Ad Units', function () { - beforeEach(function () { + describe('Decorate Ad Units', function() { + beforeEach(function() { coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('pubcid_alt', 'altpubcid200000', (new Date(Date.now() + 5000).toUTCString())); sinon.spy(coreStorage, 'setCookie'); }); - afterEach(function () { + afterEach(function() { $$PREBID_GLOBAL$$.requestBids.removeAll(); config.resetConfig(); coreStorage.setCookie.restore(); }); - after(function () { + after(function() { coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('pubcid_alt', '', EXPIRED_COOKIE_DATE); }); - it('Check same cookie behavior', function () { + it('Check same cookie behavior', function() { let adUnits1 = [getAdUnitMock()]; let adUnits2 = [getAdUnitMock()]; let innerAdUnits1; @@ -135,7 +135,7 @@ describe('User ID', function () { assert.deepEqual(innerAdUnits1, innerAdUnits2); }); - it('Check different cookies', function () { + it('Check different cookies', function() { let adUnits1 = [getAdUnitMock()]; let adUnits2 = [getAdUnitMock()]; let innerAdUnits1; @@ -186,7 +186,7 @@ describe('User ID', function () { expect(pubcid1).to.not.equal(pubcid2); }); - it('Use existing cookie', function () { + it('Use existing cookie', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; @@ -210,7 +210,7 @@ describe('User ID', function () { expect(coreStorage.setCookie.callCount).to.equal(0); }); - it('Extend cookie', function () { + it('Extend cookie', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; let customConfig = getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie']); @@ -236,7 +236,7 @@ describe('User ID', function () { expect(coreStorage.setCookie.callCount).to.equal(1); }); - it('Disable auto create', function () { + it('Disable auto create', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; let customConfig = getConfigMock(['pubCommonId', 'pubcid', 'cookie']); @@ -258,16 +258,16 @@ describe('User ID', function () { }); }); - describe('Opt out', function () { - before(function () { + describe('Opt out', function() { + before(function() { coreStorage.setCookie('_pbjs_id_optout', '1', (new Date(Date.now() + 5000).toUTCString())); }); - beforeEach(function () { + beforeEach(function() { sinon.stub(utils, 'logInfo'); }); - afterEach(function () { + afterEach(function() { // removed cookie coreStorage.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); $$PREBID_GLOBAL$$.requestBids.removeAll(); @@ -275,18 +275,18 @@ describe('User ID', function () { config.resetConfig(); }); - after(function () { + after(function() { coreStorage.setCookie('_pbjs_id_optout', '', EXPIRED_COOKIE_DATE); }); - it('fails initialization if opt out cookie exists', function () { + it('fails initialization if opt out cookie exists', function() { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - opt-out cookie found, exit module'); }); - it('initializes if no opt out cookie exists', function () { + it('initializes if no opt out cookie exists', function() { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); @@ -294,18 +294,18 @@ describe('User ID', function () { }); }); - describe('Handle variations of config values', function () { - beforeEach(function () { + describe('Handle variations of config values', function() { + beforeEach(function() { sinon.stub(utils, 'logInfo'); }); - afterEach(function () { + afterEach(function() { $$PREBID_GLOBAL$$.requestBids.removeAll(); utils.logInfo.restore(); config.resetConfig(); }); - it('handles config with no usersync object', function () { + it('handles config with no usersync object', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({}); @@ -313,14 +313,14 @@ describe('User ID', function () { expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); - it('handles config with empty usersync object', function () { + it('handles config with empty usersync object', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({userSync: {}}); expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); - it('handles config with usersync and userIds that are empty objs', function () { + it('handles config with usersync and userIds that are empty objs', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -331,7 +331,7 @@ describe('User ID', function () { expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); - it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () { + it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -348,7 +348,7 @@ describe('User ID', function () { expect(typeof utils.logInfo.args[0]).to.equal('undefined'); }); - it('config with 1 configurations should create 1 submodules', function () { + it('config with 1 configurations should create 1 submodules', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie'])); @@ -356,7 +356,7 @@ describe('User ID', function () { expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 1 submodules'); }); - it('config with 8 configurations should result in 8 submodules add', function () { + it('config with 8 configurations should result in 8 submodules add', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -391,7 +391,7 @@ describe('User ID', function () { expect(utils.logInfo.args[0][0]).to.exist.and.to.equal('User ID - usersync config updated for 8 submodules'); }); - it('config syncDelay updates module correctly', function () { + it('config syncDelay updates module correctly', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -406,7 +406,7 @@ describe('User ID', function () { expect(syncDelay).to.equal(99); }); - it('config auctionDelay updates module correctly', function () { + it('config auctionDelay updates module correctly', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -421,7 +421,7 @@ describe('User ID', function () { expect(auctionDelay).to.equal(100); }); - it('config auctionDelay defaults to 0 if not a number', function () { + it('config auctionDelay defaults to 0 if not a number', function() { setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule]); init(config); config.setConfig({ @@ -437,13 +437,13 @@ describe('User ID', function () { }); }); - describe('auction and user sync delays', function () { + describe('auction and user sync delays', function() { let sandbox; let adUnits; let mockIdCallback; let auctionSpy; - beforeEach(function () { + beforeEach(function() { sandbox = sinon.createSandbox(); sandbox.stub(global, 'setTimeout').returns(2); sandbox.stub(events, 'on'); @@ -457,12 +457,12 @@ describe('User ID', function () { mockIdCallback = sandbox.stub(); const mockIdSystem = { name: 'mockId', - decode: function (value) { + decode: function(value) { return { 'mid': value['MOCKID'] }; }, - getId: function () { + getId: function() { const storedId = coreStorage.getCookie('MOCKID'); if (storedId) { return {id: {'MOCKID': storedId}}; @@ -476,13 +476,13 @@ describe('User ID', function () { attachIdSystem(mockIdSystem, true); }); - afterEach(function () { + afterEach(function() { $$PREBID_GLOBAL$$.requestBids.removeAll(); config.resetConfig(); sandbox.restore(); }); - it('delays auction if auctionDelay is set, timing out at auction delay', function () { + it('delays auction if auctionDelay is set, timing out at auction delay', function() { config.setConfig({ userSync: { auctionDelay: 33, @@ -515,7 +515,7 @@ describe('User ID', function () { events.on.called.should.equal(false); }); - it('delays auction if auctionDelay is set, continuing auction if ids are fetched before timing out', function (done) { + it('delays auction if auctionDelay is set, continuing auction if ids are fetched before timing out', function(done) { config.setConfig({ userSync: { auctionDelay: 33, @@ -554,7 +554,7 @@ describe('User ID', function () { events.on.called.should.equal(false); }); - it('does not delay auction if not set, delays id fetch after auction ends with syncDelay', function () { + it('does not delay auction if not set, delays id fetch after auction ends with syncDelay', function() { config.setConfig({ userSync: { syncDelay: 77, @@ -590,7 +590,7 @@ describe('User ID', function () { mockIdCallback.calledOnce.should.equal(true); }); - it('does not delay user id sync after auction ends if set to 0', function () { + it('does not delay user id sync after auction ends if set to 0', function() { config.setConfig({ userSync: { syncDelay: 0, @@ -619,7 +619,7 @@ describe('User ID', function () { mockIdCallback.calledOnce.should.equal(true); }); - it('does not delay auction if there are no ids to fetch', function () { + it('does not delay auction if there are no ids to fetch', function() { coreStorage.setCookie('MOCKID', JSON.stringify({'MOCKID': '123456778'}), new Date(Date.now() + 5000).toUTCString()); config.setConfig({ @@ -643,21 +643,21 @@ describe('User ID', function () { }); }); - describe('Request bids hook appends userId to bid objs in adapters', function () { + describe('Request bids hook appends userId to bid objs in adapters', function() { let adUnits; - beforeEach(function () { + beforeEach(function() { adUnits = [getAdUnitMock()]; }); - it('test hook from pubcommonid cookie', function (done) { + it('test hook from pubcommonid cookie', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.pubcid'); @@ -673,12 +673,12 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from pubcommonid config value object', function (done) { + it('test hook from pubcommonid config value object', function(done) { setSubmoduleRegistry([pubCommonIdSubmodule]); init(config); config.setConfig(getConfigValueMock('pubCommonId', {'pubcidvalue': 'testpubcidvalue'})); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.pubcidvalue'); @@ -690,7 +690,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from pubcommonid html5', function (done) { + it('test hook from pubcommonid html5', function(done) { // simulate existing browser local storage values localStorage.setItem('unifiedid_alt', JSON.stringify({'TDID': 'testunifiedid_alt'})); localStorage.setItem('unifiedid_alt_exp', ''); @@ -699,7 +699,7 @@ describe('User ID', function () { init(config); config.setConfig(getConfigMock(['unifiedId', 'unifiedid_alt', 'html5'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.tdid'); @@ -716,7 +716,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from identityLink html5', function (done) { + it('test hook from identityLink html5', function(done) { // simulate existing browser local storage values localStorage.setItem('idl_env', 'AiGNC8Z5ONyZKSpIPf'); localStorage.setItem('idl_env_exp', ''); @@ -724,7 +724,7 @@ describe('User ID', function () { setSubmoduleRegistry([identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['identityLink', 'idl_env', 'html5'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.idl_env'); @@ -741,14 +741,14 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from identityLink cookie', function (done) { + it('test hook from identityLink cookie', function(done) { coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([identityLinkSubmodule]); init(config); config.setConfig(getConfigMock(['identityLink', 'idl_env', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.idl_env'); @@ -764,7 +764,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from liveIntentId html5', function (done) { + it('test hook from liveIntentId html5', function(done) { // simulate existing browser local storage values localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier'})); localStorage.setItem('_li_pbid_exp', ''); @@ -772,7 +772,7 @@ describe('User ID', function () { setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'html5'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -789,14 +789,14 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from liveIntentId cookie', function (done) { + it('test hook from liveIntentId cookie', function(done) { coreStorage.setCookie('_li_pbid', JSON.stringify({'unifiedId': 'random-cookie-identifier'}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -812,7 +812,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from sharedId html5', function (done) { + it('test hook from sharedId html5', function(done) { // simulate existing browser local storage values localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611})); localStorage.setItem('sharedid_exp', ''); @@ -820,7 +820,7 @@ describe('User ID', function () { setSubmoduleRegistry([sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['sharedId', 'sharedid', 'html5'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); @@ -848,7 +848,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from sharedId html5 (id not synced)', function (done) { + it('test hook from sharedId html5 (id not synced)', function(done) { // simulate existing browser local storage values localStorage.setItem('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true, 'ts': 1590525289611})); localStorage.setItem('sharedid_exp', ''); @@ -856,7 +856,7 @@ describe('User ID', function () { setSubmoduleRegistry([sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['sharedId', 'sharedid', 'html5'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); @@ -878,14 +878,14 @@ describe('User ID', function () { done(); }, {adUnits}); }); - it('test hook from sharedId cookie', function (done) { + it('test hook from sharedId cookie', function(done) { coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ts': 1590525289611}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); @@ -911,14 +911,14 @@ describe('User ID', function () { done(); }, {adUnits}); }); - it('test hook from sharedId cookie (id not synced) ', function (done) { + it('test hook from sharedId cookie (id not synced) ', function(done) { coreStorage.setCookie('sharedid', JSON.stringify({'id': 'test_sharedId', 'ns': true, 'ts': 1590525289611}), (new Date(Date.now() + 100000).toUTCString())); setSubmoduleRegistry([sharedIdSubmodule]); init(config); config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); @@ -939,7 +939,7 @@ describe('User ID', function () { done(); }, {adUnits}); }); - it('test hook from id5id cookies when refresh needed', function (done) { + it('test hook from id5id cookies when refresh needed', function(done) { // simulate existing browser local storage values coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id_last', (new Date(Date.now() - 7200 * 1000)).toUTCString(), (new Date(Date.now() + 5000).toUTCString())); @@ -950,7 +950,7 @@ describe('User ID', function () { init(config); config.setConfig(getConfigMock(['id5Id', 'id5id', 'cookie', 10, 3600])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.id5id'); @@ -968,12 +968,12 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from id5id value-based config', function (done) { + it('test hook from id5id value-based config', function(done) { setSubmoduleRegistry([id5IdSubmodule]); init(config); config.setConfig(getConfigValueMock('id5Id', {'id5id': 'testid5id'})); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.id5id'); @@ -988,7 +988,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from liveIntentId html5', function (done) { + it('test hook from liveIntentId html5', function(done) { // simulate existing browser local storage values localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier', 'segments': ['123']})); localStorage.setItem('_li_pbid_exp', ''); @@ -996,7 +996,7 @@ describe('User ID', function () { setSubmoduleRegistry([liveIntentIdSubmodule]); init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'html5'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -1015,7 +1015,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from liveIntentId cookie', function (done) { + it('test hook from liveIntentId cookie', function(done) { coreStorage.setCookie('_li_pbid', JSON.stringify({ 'unifiedId': 'random-cookie-identifier', 'segments': ['123'] @@ -1025,7 +1025,7 @@ describe('User ID', function () { init(config); config.setConfig(getConfigMock(['liveIntentId', '_li_pbid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.lipb'); @@ -1043,7 +1043,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from britepoolid cookies', function (done) { + it('test hook from britepoolid cookies', function(done) { // simulate existing browser local storage values coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': '279c0161-5152-487f-809e-05d7f7e653fd'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1051,7 +1051,7 @@ describe('User ID', function () { init(config); config.setConfig(getConfigMock(['britepoolId', 'britepoolid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.britepoolid'); @@ -1067,7 +1067,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook from netId cookies', function (done) { + it('test hook from netId cookies', function(done) { // simulate existing browser local storage values coreStorage.setCookie('netId', JSON.stringify({'netId': 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1075,7 +1075,7 @@ describe('User ID', function () { init(config); config.setConfig(getConfigMock(['netId', 'netId', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.netId'); @@ -1091,7 +1091,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId have data to pass', function (done) { + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId have data to pass', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1110,7 +1110,7 @@ describe('User ID', function () { ['netId', 'netId', 'cookie'], ['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { // verify that the PubCommonId id data was copied to bid @@ -1150,7 +1150,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId (opted out) have data to pass', function (done) { + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId (opted out) have data to pass', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1169,7 +1169,7 @@ describe('User ID', function () { ['netId', 'netId', 'cookie'], ['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { // verify that the PubCommonId id data was copied to bid @@ -1204,7 +1204,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId have their modules added before and after init', function (done) { + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId have their modules added before and after init', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1236,7 +1236,7 @@ describe('User ID', function () { ['netId', 'netId', 'cookie'], ['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { // verify that the PubCommonId id data was copied to bid @@ -1276,7 +1276,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId(opted out) have their modules added before and after init', function (done) { + it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId(opted out) have their modules added before and after init', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1308,7 +1308,7 @@ describe('User ID', function () { ['netId', 'netId', 'cookie'], ['sharedId', 'sharedid', 'cookie'])); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { // verify that the PubCommonId id data was copied to bid @@ -1344,7 +1344,7 @@ describe('User ID', function () { }, {adUnits}); }); - it('should add new id system ', function (done) { + it('should add new id system ', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1383,18 +1383,18 @@ describe('User ID', function () { // Add new submodule named 'mockId' attachIdSystem({ name: 'mockId', - decode: function (value) { + decode: function(value) { return { 'mid': value['MOCKID'] }; }, - getId: function (params, storedId) { + getId: function(params, storedId) { if (storedId) return {}; return {id: {'MOCKID': '1234'}}; } }); - requestBidsHook(function () { + requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { // check PubCommonId id data was copied to bid @@ -1440,8 +1440,8 @@ describe('User ID', function () { }); }); - describe('callbacks at the end of auction', function () { - beforeEach(function () { + describe('callbacks at the end of auction', function() { + beforeEach(function() { sinon.stub(events, 'getEvents').returns([]); sinon.stub(utils, 'triggerPixel'); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -1449,7 +1449,7 @@ describe('User ID', function () { coreStorage.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); - afterEach(function () { + afterEach(function() { events.getEvents.restore(); utils.triggerPixel.restore(); coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); @@ -1457,7 +1457,7 @@ describe('User ID', function () { coreStorage.setCookie('_parrable_eid', '', EXPIRED_COOKIE_DATE); }); - it('pubcid callback with url', function () { + it('pubcid callback with url', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; let customCfg = getConfigMock(['pubCommonId', 'pubcid_alt', 'cookie']); @@ -1475,7 +1475,7 @@ describe('User ID', function () { expect(utils.triggerPixel.getCall(0).args[0]).to.include('/any/pubcid/url'); }); - it('unifiedid callback with url', function () { + it('unifiedid callback with url', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; let customCfg = getConfigMock(['unifiedId', 'unifiedid', 'cookie']); @@ -1493,7 +1493,7 @@ describe('User ID', function () { expect(server.requests[0].url).to.equal('/any/unifiedid/url'); }); - it('unifiedid callback with partner', function () { + it('unifiedid callback with partner', function() { let adUnits = [getAdUnitMock()]; let innerAdUnits; let customCfg = getConfigMock(['unifiedId', 'unifiedid', 'cookie']); @@ -1511,7 +1511,7 @@ describe('User ID', function () { expect(server.requests[0].url).to.equal('https://match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); }); - it('callback for submodules that always need to refresh stored id', function (done) { + it('callback for submodules that always need to refresh stored id', function(done) { let adUnits = [getAdUnitMock()]; let innerAdUnits; const parrableStoredId = '01.1111111111.test-eid'; @@ -1520,12 +1520,12 @@ describe('User ID', function () { const parrableIdSubmoduleMock = { name: 'parrableId', - decode: function (value) { + decode: function(value) { return {'parrableid': value}; }, - getId: function () { + getId: function() { return { - callback: function (cb) { + callback: function(cb) { cb(parrableRefreshedId); } }; From b4f2f1fb3b1279d4e0f476fb23c58b57da5b090d Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 28 May 2020 10:22:26 -0700 Subject: [PATCH 26/34] Fixing review comments --- modules/sharedIdSystem.js | 58 +++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 3733f25d769..c4da50169eb 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -39,7 +39,7 @@ function constructCookieValue(value, needsSync) { * @returns {boolean} */ function isIdSynced(configParams, storedId) { - var needSync = storedId.ns; + const needSync = storedId.ns; if (needSync) { return true; } @@ -107,19 +107,15 @@ function idGenerationCallback(callback) { function existingIdCallback(storedId, callback) { return { success: function (responseBody) { - try { - utils.logInfo('SharedId: id to be synced: ' + storedId.id); - if (responseBody) { - try { - let responseObj = JSON.parse(responseBody); - storedId = constructCookieValue(responseObj.sharedId, false); - utils.logInfo('SharedId: Older SharedId: ' + storedId.id); - } catch (error) { - utils.logError(error); - } + utils.logInfo('SharedId: id to be synced: ' + storedId.id); + if (responseBody) { + try { + let responseObj = JSON.parse(responseBody); + storedId = constructCookieValue(responseObj.sharedId, false); + utils.logInfo('SharedId: Older SharedId: ' + storedId.id); + } catch (error) { + utils.logError(error); } - } catch (error) { - utils.logError(error); } callback(storedId); }, @@ -136,28 +132,24 @@ function existingIdCallback(storedId, callback) { * @returns {string|*} */ function encodeId(value) { - try { - let result = {}; - let sharedId = (value && typeof value['id'] === 'string') ? value['id'] : undefined; - if (sharedId == OPT_OUT_VALUE) { - return undefined; + let result = {}; + let sharedId = (value && typeof value['id'] === 'string') ? value['id'] : undefined; + if (sharedId == OPT_OUT_VALUE) { + return undefined; + } + if (sharedId) { + var bidIds = { + first: sharedId, } - if (sharedId) { - var bidIds = { - first: sharedId, - } - let ns = (value && typeof value['ns'] === 'boolean') ? value['ns'] : undefined; - if (ns == undefined) { - bidIds.third = sharedId; - } - result.sharedid = bidIds; - utils.logInfo('SharedId: Decoded value ' + JSON.stringify(result)); - return result; + let ns = (value && typeof value['ns'] === 'boolean') ? value['ns'] : undefined; + if (ns == undefined) { + bidIds.third = sharedId; } - return sharedId; - } catch (ex) { - return value; + result.sharedid = bidIds; + utils.logInfo('SharedId: Decoded value ' + JSON.stringify(result)); + return result; } + return sharedId; } /** @type {Submodule} */ @@ -175,7 +167,7 @@ export const sharedIdSubmodule = { * @returns {{sharedid:{ 1: string, 3:string}} or undefined if value doesn't exists */ decode(value) { - return ((value) ? encodeId(value) : undefined); + return (value) ? encodeId(value) : undefined; }, /** From f58abbbd08156e22f294fa3aec5891c122598fef Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 28 May 2020 12:26:20 -0700 Subject: [PATCH 27/34] Changes to id value --- modules/sharedIdSystem.js | 30 +++++++++++++++--------------- modules/userId/eids.js | 2 +- test/spec/modules/eids_spec.js | 4 ++-- test/spec/modules/userId_spec.js | 22 +++++++++++----------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index c4da50169eb..9665e6e3adc 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -22,7 +22,7 @@ const OPT_OUT_VALUE = '00000000000000000000000000'; * @returns {string} */ function constructCookieValue(value, needsSync) { - let cookieValue = {}; + const cookieValue = {}; cookieValue.id = value; cookieValue.ts = utils.timestamp(); if (needsSync) { @@ -46,11 +46,11 @@ function isIdSynced(configParams, storedId) { if (!configParams || typeof configParams.syncTime !== 'number') { utils.logInfo('SharedId: Sync time is not configured or is not a number'); } - var syncTime = (!configParams || typeof configParams.syncTime !== 'number') ? DEFAULT_24_HOURS : configParams.syncTime; + let syncTime = (!configParams || typeof configParams.syncTime !== 'number') ? DEFAULT_24_HOURS : configParams.syncTime; if (syncTime > DEFAULT_24_HOURS) { syncTime = DEFAULT_24_HOURS; } - var cookieTimestamp = storedId.ts; + const cookieTimestamp = storedId.ts; if (cookieTimestamp) { var secondBetweenTwoDate = timeDifferenceInSeconds(utils.timestamp(), cookieTimestamp); return secondBetweenTwoDate >= syncTime; @@ -65,7 +65,7 @@ function isIdSynced(configParams, storedId) { * @returns {number} */ function timeDifferenceInSeconds(date1, date2) { - var diff = (date1 - date2) / 1000; + const diff = (date1 - date2) / 1000; return Math.abs(Math.round(diff)); } @@ -78,7 +78,7 @@ function timeDifferenceInSeconds(date1, date2) { function idGenerationCallback(callback) { return { success: function (responseBody) { - var value = {}; + let value = {}; if (responseBody) { try { let responseObj = JSON.parse(responseBody); @@ -91,7 +91,7 @@ function idGenerationCallback(callback) { callback(value); }, error: function (statusText, responseBody) { - var value = constructCookieValue(sharedIdGenerator.id(), true); + const value = constructCookieValue(sharedIdGenerator.id(), true); utils.logInfo('SharedId: Ulid Generated SharedId: ' + value.id); callback(value); } @@ -132,16 +132,16 @@ function existingIdCallback(storedId, callback) { * @returns {string|*} */ function encodeId(value) { - let result = {}; - let sharedId = (value && typeof value['id'] === 'string') ? value['id'] : undefined; + const result = {}; + const sharedId = (value && typeof value['id'] === 'string') ? value['id'] : undefined; if (sharedId == OPT_OUT_VALUE) { return undefined; } if (sharedId) { - var bidIds = { - first: sharedId, + const bidIds = { + id: sharedId, } - let ns = (value && typeof value['ns'] === 'boolean') ? value['ns'] : undefined; + const ns = (value && typeof value['ns'] === 'boolean') ? value['ns'] : undefined; if (ns == undefined) { bidIds.third = sharedId; } @@ -164,7 +164,7 @@ export const sharedIdSubmodule = { * decode the stored id value for passing to bid requests * @function * @param {string} value - * @returns {{sharedid:{ 1: string, 3:string}} or undefined if value doesn't exists + * @returns {{sharedid:{ id: string, third:string}} or undefined if value doesn't exists */ decode(value) { return (value) ? encodeId(value) : undefined; @@ -193,12 +193,12 @@ export const sharedIdSubmodule = { extendId(configParams, storedId) { utils.logInfo('SharedId: Existing shared id ' + storedId.id); const resp = function (callback) { - let needSync = isIdSynced(configParams, storedId); + const needSync = isIdSynced(configParams, storedId); if (needSync) { utils.logInfo('SharedId: Existing shared id ' + storedId + ' is not synced'); - let sharedIdPayload = {}; + const sharedIdPayload = {}; sharedIdPayload.sharedId = storedId.id; - let payloadString = JSON.stringify(sharedIdPayload); + const payloadString = JSON.stringify(sharedIdPayload); ajax(ID_SVC, existingIdCallback(storedId, callback), payloadString, {method: 'POST', withCredentials: true}); } }; diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 23817f92b4b..478905025a6 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -87,7 +87,7 @@ const USER_IDS_CONFIG = { source: 'sharedid.org', atype: 1, getValue: function(data) { - return data.first; + return data.id; }, getUidExt: function(data) { return (data && data.third) ? { diff --git a/test/spec/modules/eids_spec.js b/test/spec/modules/eids_spec.js index 88bc9beb505..160277204df 100644 --- a/test/spec/modules/eids_spec.js +++ b/test/spec/modules/eids_spec.js @@ -149,7 +149,7 @@ describe('eids array generation for known sub-modules', function() { it('Sharedid', function() { const userId = { sharedid: { - first: 'test_sharedId', + id: 'test_sharedId', third: 'test_sharedId' } }; @@ -169,7 +169,7 @@ describe('eids array generation for known sub-modules', function() { it('Sharedid: Not Synched', function() { const userId = { sharedid: { - first: 'test_sharedId' + id: 'test_sharedId' } }; const newEids = createEidsArray(userId); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index ef7253047be..d75e3e183c8 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -824,10 +824,10 @@ describe('User ID', function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.have.deep.nested.property('id'); expect(bid.userId.sharedid).to.have.deep.nested.property('third'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId', + id: 'test_sharedId', third: 'test_sharedId' }); expect(bid.userIdAsEids[0]).to.deep.equal({ @@ -860,9 +860,9 @@ describe('User ID', function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.have.deep.nested.property('id'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId' + id: 'test_sharedId' }); expect(bid.userIdAsEids[0]).to.deep.equal({ source: 'sharedid.org', @@ -889,10 +889,10 @@ describe('User ID', function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.have.deep.nested.property('id'); expect(bid.userId.sharedid).to.have.deep.nested.property('third'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId', + id: 'test_sharedId', third: 'test_sharedId' }); expect(bid.userIdAsEids[0]).to.deep.equal({ @@ -922,9 +922,9 @@ describe('User ID', function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.sharedid'); - expect(bid.userId.sharedid).to.have.deep.nested.property('first'); + expect(bid.userId.sharedid).to.have.deep.nested.property('id'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId' + id: 'test_sharedId' }); expect(bid.userIdAsEids[0]).to.deep.equal({ source: 'sharedid.org', @@ -1133,7 +1133,7 @@ describe('User ID', function() { expect(bid.userId.netId).to.equal('testnetId'); expect(bid).to.have.deep.nested.property('userId.sharedid'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId', + id: 'test_sharedId', third: 'test_sharedId' }); expect(bid.userIdAsEids.length).to.equal(7); @@ -1259,7 +1259,7 @@ describe('User ID', function() { expect(bid.userId.netId).to.equal('testnetId'); expect(bid).to.have.deep.nested.property('userId.sharedid'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId', + id: 'test_sharedId', third: 'test_sharedId' }); expect(bid.userIdAsEids.length).to.equal(7); @@ -1418,7 +1418,7 @@ describe('User ID', function() { // also check that sharedId id data was copied to bid expect(bid).to.have.deep.nested.property('userId.sharedid'); expect(bid.userId.sharedid).to.deep.equal({ - first: 'test_sharedId', + id: 'test_sharedId', third: 'test_sharedId' }); // check MockId data was copied to bid From 4d05d33accd64867a9dd93f397753a5657afd5d7 Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 28 May 2020 12:30:29 -0700 Subject: [PATCH 28/34] Updating documentation --- modules/sharedIdSystem.md | 4 ++-- modules/userId/userId.md | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/sharedIdSystem.md b/modules/sharedIdSystem.md index c5e42e8dafa..4ed7a513920 100644 --- a/modules/sharedIdSystem.md +++ b/modules/sharedIdSystem.md @@ -18,7 +18,7 @@ pbjs.setConfig({ userIds: [{ name: 'sharedId', params: { - syncTime: 1 // in seconds, default is 24 hours + syncTime: 60 // in seconds, default is 24 hours }, storage: { name: 'sharedid', @@ -37,7 +37,7 @@ The below parameters apply only to the Shared ID User ID Module integration. | --- | --- | --- | --- | --- | | name | Required | String | ID value for the Shared ID module - `"sharedId"` | `"sharedId"` | | params | Optional | Object | Details for sharedId syncing. | | -| params.syncTime | Optional | Object | Configuration to define the frequency(in seconds) of id synchronization. By default id is synchronized every 24 hours | 24 | +| params.syncTime | Optional | Object | Configuration to define the frequency(in seconds) of id synchronization. By default id is synchronized every 24 hours | 60 | | storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | | | storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` | | storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedid"` | diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 17c0b5fef7f..d315edcd9f5 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -67,7 +67,7 @@ pbjs.setConfig({ }, { name: 'sharedId', params: { - syncTime: 3600 // in seconds, default is 24 hours + syncTime: 60 // in seconds, default is 24 hours }, storage: { type: 'cookie', @@ -125,6 +125,9 @@ pbjs.setConfig({ } }, { name: 'sharedId', + params: { + syncTime: 60 // in seconds, default is 24 hours + }, storage: { type: 'cookie', name: 'sharedid', From 40a849e2119b8b004e1de6da5cd102f8ba034ddf Mon Sep 17 00:00:00 2001 From: skocheri Date: Thu, 4 Jun 2020 15:33:24 -0700 Subject: [PATCH 29/34] Documentation update --- modules/sharedIdSystem.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/sharedIdSystem.md b/modules/sharedIdSystem.md index 4ed7a513920..acb076ed97f 100644 --- a/modules/sharedIdSystem.md +++ b/modules/sharedIdSystem.md @@ -1,7 +1,6 @@ ## Shared ID User ID Submodule -Shared ID User ID Module generates a simple UUID that can be utilized to improve user matching. -This module does not require any registration. +Shared ID User ID Module generates a UUID that can be utilized to improve user matching.This module enables timely synchronization which handles sharedId.org optout. This module does not require any registration. ### Building Prebid with Shared Id Support Your Prebid build must include the modules for both **userId** and **sharedId** submodule. Follow the build instructions for Prebid as From d864b64c00ab73dab2d258f195ebb4b310f412ba Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 9 Jun 2020 09:44:12 -0700 Subject: [PATCH 30/34] Resolving merge conflicts --- test/spec/modules/userId_spec.js | 80 -------------------------------- 1 file changed, 80 deletions(-) diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index d75e3e183c8..7f20d1f2bfb 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -1510,85 +1510,5 @@ describe('User ID', function() { events.emit(CONSTANTS.EVENTS.AUCTION_END, {}); expect(server.requests[0].url).to.equal('https://match.adsrvr.org/track/rid?ttd_pid=rubicon&fmt=json'); }); - - it('callback for submodules that always need to refresh stored id', function(done) { - let adUnits = [getAdUnitMock()]; - let innerAdUnits; - const parrableStoredId = '01.1111111111.test-eid'; - const parrableRefreshedId = '02.2222222222.test-eid'; - coreStorage.setCookie('_parrable_eid', parrableStoredId, (new Date(Date.now() + 5000).toUTCString())); - - const parrableIdSubmoduleMock = { - name: 'parrableId', - decode: function(value) { - return {'parrableid': value}; - }, - getId: function() { - return { - callback: function(cb) { - cb(parrableRefreshedId); - } - }; - } - }; - - const parrableConfigMock = { - userSync: { - syncDelay: 0, - userIds: [{ - name: 'parrableId', - storage: { - type: 'cookie', - name: '_parrable_eid' - } - }] - } - }; - - setSubmoduleRegistry([parrableIdSubmoduleMock]); - attachIdSystem(parrableIdSubmoduleMock); - init(config); - config.setConfig(parrableConfigMock); - - // make first bid request, should use stored id value - requestBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}); - innerAdUnits.forEach(unit => { - unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.parrableid'); - expect(bid.userId.parrableid).to.equal(parrableStoredId); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'parrable.com', - uids: [{id: parrableStoredId, atype: 1}] - }); - }); - }); - - // attach a handler for auction end event to run the second bid request - events.on(CONSTANTS.EVENTS.AUCTION_END, function handler(submodule) { - if (submodule === 'parrableIdSubmoduleMock') { - // make the second bid request, id should have been refreshed - requestBidsHook((config) => { - innerAdUnits = config.adUnits - }, {adUnits}); - innerAdUnits.forEach(unit => { - unit.bids.forEach(bid => { - expect(bid).to.have.deep.nested.property('userId.parrableid'); - expect(bid.userId.parrableid).to.equal(parrableRefreshedId); - expect(bid.userIdAsEids[0]).to.deep.equal({ - source: 'parrable.com', - uids: [{id: parrableRefreshedId, atype: 1}] - }); - }); - }); - events.off(CONSTANTS.EVENTS.AUCTION_END, handler); - done(); - } - }); - - // emit an auction end event to run the submodule callback - events.emit(CONSTANTS.EVENTS.AUCTION_END, 'parrableIdSubmoduleMock'); - }); }); }); From 73c693d3e68fcee36b5710f4a70f9182217a7893 Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 9 Jun 2020 11:48:28 -0700 Subject: [PATCH 31/34] updating userid_example.html --- integrationExamples/gpt/userId_example.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index b3f293580ff..1b68882a01a 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -193,7 +193,7 @@ type: "cookie", name: "sharedid", expires: 28 - }, + } }], syncDelay: 5000, auctionDelay: 1000 From 6cb4d98187d94ae9e4df6ba46f772e5400fa4bf2 Mon Sep 17 00:00:00 2001 From: skocheri Date: Wed, 10 Jun 2020 11:08:16 -0700 Subject: [PATCH 32/34] Fixing review comments on test to separate sharedid opt out tests --- test/spec/modules/userId_spec.js | 99 +++----------------------------- 1 file changed, 8 insertions(+), 91 deletions(-) diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 7f20d1f2bfb..68f33ac4444 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -1091,7 +1091,7 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId have data to pass', function(done) { + it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId, netId and sharedId have data to pass', function(done) { coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); @@ -1150,55 +1150,19 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, identityLink, britepoolId , netId and sharedId (opted out) have data to pass', function(done) { - coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'testunifiedid'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + it('test hook when sharedId (opted out) have data to pass', function(done) { coreStorage.setCookie('sharedid', JSON.stringify({'id': '00000000000000000000000000', 'ts': 1590525289611}), (new Date(Date.now() + 5000).toUTCString())); - setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule]); + setSubmoduleRegistry([sharedIdSubmodule]); init(config); - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], - ['unifiedId', 'unifiedid', 'cookie'], - ['id5Id', 'id5id', 'cookie'], - ['identityLink', 'idl_env', 'cookie'], - ['britepoolId', 'britepoolid', 'cookie'], - ['netId', 'netId', 'cookie'], - ['sharedId', 'sharedid', 'cookie'])); + config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { - // verify that the PubCommonId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal('testpubcid'); - // also check that UnifiedId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.tdid'); - expect(bid.userId.tdid).to.equal('testunifiedid'); - // also check that Id5Id id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.id5id'); - expect(bid.userId.id5id).to.equal('testid5id'); - // check that identityLink id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.idl_env'); - expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); - // also check that britepoolId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.britepoolid'); - expect(bid.userId.britepoolid).to.equal('testbritepoolid'); - // also check that netId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.netId'); - expect(bid.userId.netId).to.equal('testnetId'); - expect(bid.userIdAsEids.length).to.equal(6); + expect(bid.userIdAsEids).to.be.undefined; }); }); - coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); @@ -1276,69 +1240,22 @@ describe('User ID', function() { }, {adUnits}); }); - it('test hook when pubCommonId, unifiedId, id5Id, britepoolId, netId and sharedId(opted out) have their modules added before and after init', function(done) { - coreStorage.setCookie('pubcid', 'testpubcid', (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('unifiedid', JSON.stringify({'TDID': 'cookie-value-add-module-variations'}), new Date(Date.now() + 5000).toUTCString()); - coreStorage.setCookie('id5id', JSON.stringify({'ID5ID': 'testid5id'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('idl_env', 'AiGNC8Z5ONyZKSpIPf', new Date(Date.now() + 5000).toUTCString()); - coreStorage.setCookie('britepoolid', JSON.stringify({'primaryBPID': 'testbritepoolid'}), (new Date(Date.now() + 5000).toUTCString())); - coreStorage.setCookie('netId', JSON.stringify({'netId': 'testnetId'}), (new Date(Date.now() + 5000).toUTCString())); + it('test hook when sharedId(opted out) have their modules added before and after init', function(done) { coreStorage.setCookie('sharedid', JSON.stringify({'id': '00000000000000000000000000', 'ts': 1590525289611}), (new Date(Date.now() + 5000).toUTCString())); setSubmoduleRegistry([]); - - // attaching before init - attachIdSystem(pubCommonIdSubmodule); - init(config); - // attaching after init - attachIdSystem(unifiedIdSubmodule); - attachIdSystem(id5IdSubmodule); - attachIdSystem(identityLinkSubmodule); - attachIdSystem(britepoolIdSubmodule); - attachIdSystem(netIdSubmodule); attachIdSystem(sharedIdSubmodule); - config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'], - ['unifiedId', 'unifiedid', 'cookie'], - ['id5Id', 'id5id', 'cookie'], - ['identityLink', 'idl_env', 'cookie'], - ['britepoolId', 'britepoolid', 'cookie'], - ['netId', 'netId', 'cookie'], - ['sharedId', 'sharedid', 'cookie'])); + config.setConfig(getConfigMock(['sharedId', 'sharedid', 'cookie'])); requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { - // verify that the PubCommonId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.pubcid'); - expect(bid.userId.pubcid).to.equal('testpubcid'); - // also check that UnifiedId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.tdid'); - expect(bid.userId.tdid).to.equal('cookie-value-add-module-variations'); - // also check that Id5Id id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.id5id'); - expect(bid.userId.id5id).to.equal('testid5id'); - // also check that identityLink id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.idl_env'); - expect(bid.userId.idl_env).to.equal('AiGNC8Z5ONyZKSpIPf'); - // also check that britepoolId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.britepoolid'); - expect(bid.userId.britepoolid).to.equal('testbritepoolid'); - // also check that britepoolId id data was copied to bid - expect(bid).to.have.deep.nested.property('userId.netId'); - expect(bid.userId.netId).to.equal('testnetId'); - - expect(bid.userIdAsEids.length).to.equal(6); + expect(bid.userIdAsEids).to.be.undefined; }); }); - coreStorage.setCookie('pubcid', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('unifiedid', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('id5id', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('idl_env', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('britepoolid', '', EXPIRED_COOKIE_DATE); - coreStorage.setCookie('netId', '', EXPIRED_COOKIE_DATE); coreStorage.setCookie('sharedid', '', EXPIRED_COOKIE_DATE); done(); }, {adUnits}); From 7b7847e6eded69f7764c9a26697492fb89f11b1a Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 15 Jun 2020 13:21:21 -0700 Subject: [PATCH 33/34] Moving sharedID generation within sharedId module --- modules/sharedIdSystem.js | 130 ++++++++++++++++++++++++++++++++++++- src/sharedIdGenerator.js | 132 -------------------------------------- 2 files changed, 127 insertions(+), 135 deletions(-) delete mode 100644 src/sharedIdGenerator.js diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 9665e6e3adc..9c973f13991 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -8,13 +8,12 @@ import * as utils from '../src/utils.js' import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js'; -import * as sharedIdGenerator from '../src/sharedIdGenerator.js'; const MODULE_NAME = 'sharedId'; const ID_SVC = 'https://id.sharedid.org/id'; const DEFAULT_24_HOURS = 86400; const OPT_OUT_VALUE = '00000000000000000000000000'; - +const id = factory(); /** * Constructs cookie value * @param value @@ -91,7 +90,7 @@ function idGenerationCallback(callback) { callback(value); }, error: function (statusText, responseBody) { - const value = constructCookieValue(sharedIdGenerator.id(), true); + const value = constructCookieValue(id(), true); utils.logInfo('SharedId: Ulid Generated SharedId: ' + value.id); callback(value); } @@ -152,6 +151,131 @@ function encodeId(value) { return sharedId; } +// These values should NEVER change. If +// they do, we're no longer making ulids! +const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 +const ENCODING_LEN = ENCODING.length; +const TIME_MAX = Math.pow(2, 48) - 1; +const TIME_LEN = 10; +const RANDOM_LEN = 16; + +/** + * the factory to generate unique identifier based on time and current pseudorandom number + * @param {string} the current pseudorandom number generator + * @returns {function(*=): *} + */ +function factory(currPrng) { + if (!currPrng) { + currPrng = detectPrng(); + } + return function ulid(seedTime) { + if (isNaN(seedTime)) { + seedTime = Date.now(); + } + return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN, currPrng); + }; +} + +/** + * creates and logs the error message + * @function + * @param {string} error message + * @returns {Error} + */ +function createError(message) { + utils.logError(message); + const err = new Error(message); + err.source = 'sharedId'; + return err; +} + +/** + * gets a a random charcter from generated pseudorandom number + * @param {string} the generated pseudorandom number + * @returns {string} + */ +function randomChar(prng) { + let rand = Math.floor(prng() * ENCODING_LEN); + if (rand === ENCODING_LEN) { + rand = ENCODING_LEN - 1; + } + return ENCODING.charAt(rand); +} + +/** + * encodes the time based on the length + * @param now + * @param len + * @returns {string} encoded time. + */ +function encodeTime (now, len) { + if (isNaN(now)) { + throw new Error(now + ' must be a number'); + } + + if (Number.isInteger(now) === false) { + throw createError('time must be an integer'); + } + + if (now > TIME_MAX) { + throw createError('cannot encode time greater than ' + TIME_MAX); + } + if (now < 0) { + throw createError('time must be positive'); + } + + if (Number.isInteger(len) === false) { + throw createError('length must be an integer'); + } + if (len < 0) { + throw createError('length must be positive'); + } + + let mod; + let str = ''; + for (; len > 0; len--) { + mod = now % ENCODING_LEN; + str = ENCODING.charAt(mod) + str; + now = (now - mod) / ENCODING_LEN; + } + return str; +} + +/** + * encodes random character + * @param len + * @param prng + * @returns {string} + */ +function encodeRandom (len, prng) { + let str = ''; + for (; len > 0; len--) { + str = randomChar(prng) + str; + } + return str; +} + +/** + * detects the pseudorandom number generator and generates the random number + * @function + * @param {string} error message + * @returns {string} a random number + */ +function detectPrng(root) { + if (!root) { + root = typeof window !== 'undefined' ? window : null; + } + const browserCrypto = root && (root.crypto || root.msCrypto); + if (browserCrypto) { + return () => { + const buffer = new Uint8Array(1); + browserCrypto.getRandomValues(buffer); + return buffer[0] / 0xff; + }; + } + return () => Math.random(); +} + /** @type {Submodule} */ export const sharedIdSubmodule = { /** diff --git a/src/sharedIdGenerator.js b/src/sharedIdGenerator.js deleted file mode 100644 index 65db67f9435..00000000000 --- a/src/sharedIdGenerator.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Generates the shared Id/Ulid. Id generated is 128 bits with first 48 bits of timestamp followed by 80 bit of randomness. - * Spec is available in https://github.com/ulid/spec - */ -import * as utils from '../src/utils.js'; - -// These values should NEVER change. If -// they do, we're no longer making ulids! -const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 -const ENCODING_LEN = ENCODING.length; -const TIME_MAX = Math.pow(2, 48) - 1; -const TIME_LEN = 10; -const RANDOM_LEN = 16; - -/** - * the factory to generate unique identifier based on time and current pseudorandom number - * @param {string} the current pseudorandom number generator - * @returns {function(*=): *} - */ -function factory(currPrng) { - if (!currPrng) { - currPrng = detectPrng(); - } - return function ulid(seedTime) { - if (isNaN(seedTime)) { - seedTime = Date.now(); - } - return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN, currPrng); - }; -} - -/** - * creates and logs the error message - * @function - * @param {string} error message - * @returns {Error} - */ -function createError(message) { - utils.logError(message); - const err = new Error(message); - err.source = 'sharedId'; - return err; -} - -/** - * gets a a random charcter from generated pseudorandom number - * @param {string} the generated pseudorandom number - * @returns {string} - */ -function randomChar(prng) { - let rand = Math.floor(prng() * ENCODING_LEN); - if (rand === ENCODING_LEN) { - rand = ENCODING_LEN - 1; - } - return ENCODING.charAt(rand); -} - -/** - * encodes the time based on the length - * @param now - * @param len - * @returns {string} encoded time. - */ -function encodeTime (now, len) { - if (isNaN(now)) { - throw new Error(now + ' must be a number'); - } - - if (Number.isInteger(now) === false) { - throw createError('time must be an integer'); - } - - if (now > TIME_MAX) { - throw createError('cannot encode time greater than ' + TIME_MAX); - } - if (now < 0) { - throw createError('time must be positive'); - } - - if (Number.isInteger(len) === false) { - throw createError('length must be an integer'); - } - if (len < 0) { - throw createError('length must be positive'); - } - - let mod; - let str = ''; - for (; len > 0; len--) { - mod = now % ENCODING_LEN; - str = ENCODING.charAt(mod) + str; - now = (now - mod) / ENCODING_LEN; - } - return str; -} - -/** - * encodes random character - * @param len - * @param prng - * @returns {string} - */ -function encodeRandom (len, prng) { - let str = ''; - for (; len > 0; len--) { - str = randomChar(prng) + str; - } - return str; -} - -/** - * detects the pseudorandom number generator and generates the random number - * @function - * @param {string} error message - * @returns {string} a random number - */ -function detectPrng(root) { - if (!root) { - root = typeof window !== 'undefined' ? window : null; - } - const browserCrypto = root && (root.crypto || root.msCrypto); - if (browserCrypto) { - return () => { - const buffer = new Uint8Array(1); - browserCrypto.getRandomValues(buffer); - return buffer[0] / 0xff; - }; - } - return () => Math.random(); -} - -export const id = factory(); From 520470380654f1ff37180898c59bca31641d7b4a Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 15 Jun 2020 13:24:07 -0700 Subject: [PATCH 34/34] Moving sharedID generation within sharedId module --- modules/sharedIdSystem.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 9c973f13991..5c2a3df0595 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -13,6 +13,13 @@ const MODULE_NAME = 'sharedId'; const ID_SVC = 'https://id.sharedid.org/id'; const DEFAULT_24_HOURS = 86400; const OPT_OUT_VALUE = '00000000000000000000000000'; +// These values should NEVER change. If +// they do, we're no longer making ulids! +const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 +const ENCODING_LEN = ENCODING.length; +const TIME_MAX = Math.pow(2, 48) - 1; +const TIME_LEN = 10; +const RANDOM_LEN = 16; const id = factory(); /** * Constructs cookie value @@ -151,14 +158,6 @@ function encodeId(value) { return sharedId; } -// These values should NEVER change. If -// they do, we're no longer making ulids! -const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32 -const ENCODING_LEN = ENCODING.length; -const TIME_MAX = Math.pow(2, 48) - 1; -const TIME_LEN = 10; -const RANDOM_LEN = 16; - /** * the factory to generate unique identifier based on time and current pseudorandom number * @param {string} the current pseudorandom number generator