Skip to content

Commit

Permalink
SharedId & PubcommonId: CCPA and COPPA support (prebid#6632)
Browse files Browse the repository at this point in the history
* SharedId & PubcommonId: CCPA and COPPA support

* Updating to check consent within the submodule

* Fixing review comments and adding tests

* Cleaning whitespace

Co-authored-by: skocheri <[email protected]>
  • Loading branch information
SKOCHERI and skocheri authored May 3, 2021
1 parent 1778504 commit cf5b060
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 10 deletions.
26 changes: 23 additions & 3 deletions modules/pubCommonIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as utils from '../src/utils.js';
import {submodule} from '../src/hook.js';
import {getStorageManager} from '../src/storageManager.js';
import {ajax} from '../src/ajax.js';
import { uspDataHandler, coppaDataHandler } from '../src/adapterManager.js';

const PUB_COMMON_ID = 'PublisherCommonId';
const MODULE_NAME = 'pubCommonId';
Expand Down Expand Up @@ -142,9 +143,18 @@ function handleResponse(pubcid, callback, config) {
* @return {string}
*/
function sharedIdUrl(consentData) {
if (!consentData || typeof consentData.gdprApplies !== 'boolean' || !consentData.gdprApplies) return SHAREDID_URL;

return `${SHAREDID_URL}?gdpr=1&gdpr_consent=${consentData.consentString}`
const usPrivacyString = uspDataHandler.getConsentData();
let sharedIdUrl = SHAREDID_URL;
if (usPrivacyString && typeof usPrivacyString === 'string') {
sharedIdUrl = `${SHAREDID_URL}?us_privacy=${usPrivacyString}`;
}
if (!consentData || typeof consentData.gdprApplies !== 'boolean' || !consentData.gdprApplies) return sharedIdUrl;
if (usPrivacyString) {
sharedIdUrl = `${sharedIdUrl}&gdpr=1&gdpr_consent=${consentData.consentString}`
return sharedIdUrl;
}
sharedIdUrl = `${SHAREDID_URL}?gdpr=1&gdpr_consent=${consentData.consentString}`;
return sharedIdUrl
}

/**
Expand Down Expand Up @@ -223,6 +233,11 @@ export const pubCommonIdSubmodule = {
* @returns {IdResponse}
*/
getId: function (config = {}, consentData, storedId) {
const coppa = coppaDataHandler.getCoppa();
if (coppa) {
utils.logInfo('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId');
return;
}
const {params: {create = true, pixelUrl, enableSharedId = SHAREDID_DEFAULT_STATE} = {}} = config;
let newId = storedId;
if (!newId) {
Expand Down Expand Up @@ -263,6 +278,11 @@ export const pubCommonIdSubmodule = {
* @returns {IdResponse|undefined}
*/
extendId: function(config = {}, consentData, storedId) {
const coppa = coppaDataHandler.getCoppa();
if (coppa) {
utils.logInfo('PubCommonId: IDs not provided for coppa requests, exiting PubCommonId');
return;
}
const {params: {extend = false, pixelUrl, enableSharedId = SHAREDID_DEFAULT_STATE} = {}} = config;

if (extend) {
Expand Down
26 changes: 23 additions & 3 deletions modules/sharedIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import * as utils from '../src/utils.js'
import {ajax} from '../src/ajax.js';
import {submodule} from '../src/hook.js';
import { uspDataHandler, coppaDataHandler } from '../src/adapterManager.js';

const MODULE_NAME = 'sharedId';
const ID_SVC = 'https://id.sharedid.org/id';
Expand Down Expand Up @@ -282,9 +283,18 @@ function detectPrng(root) {
* @return {string}
*/
function sharedIdUrl(consentData) {
if (!consentData || typeof consentData.gdprApplies !== 'boolean' || !consentData.gdprApplies) return ID_SVC;

return `${ID_SVC}?gdpr=1&gdpr_consent=${consentData.consentString}`
const usPrivacyString = uspDataHandler.getConsentData();
let sharedIdUrl = ID_SVC;
if (usPrivacyString) {
sharedIdUrl = `${ID_SVC}?us_privacy=${usPrivacyString}`;
}
if (!consentData || typeof consentData.gdprApplies !== 'boolean' || !consentData.gdprApplies) return sharedIdUrl;
if (usPrivacyString) {
sharedIdUrl = `${sharedIdUrl}&gdpr=1&gdpr_consent=${consentData.consentString}`
return sharedIdUrl;
}
sharedIdUrl = `${ID_SVC}?gdpr=1&gdpr_consent=${consentData.consentString}`;
return sharedIdUrl
}

/** @type {Submodule} */
Expand Down Expand Up @@ -318,6 +328,11 @@ export const sharedIdSubmodule = {
* @returns {sharedId}
*/
getId(config, consentData) {
const coppa = coppaDataHandler.getCoppa();
if (coppa) {
utils.logInfo('SharedId: IDs not provided for coppa requests, exiting SharedId');
return;
}
const resp = function (callback) {
utils.logInfo('SharedId: Sharedid doesnt exists, new cookie creation');
ajax(sharedIdUrl(consentData), idGenerationCallback(callback), undefined, {method: 'GET', withCredentials: true});
Expand All @@ -333,6 +348,11 @@ export const sharedIdSubmodule = {
* @returns {{callback: *}}
*/
extendId(config, consentData, storedId) {
const coppa = coppaDataHandler.getCoppa();
if (coppa) {
utils.logInfo('SharedId: IDs not provided for coppa requests, exiting SharedId');
return;
}
const configParams = (config && config.params) || {};
utils.logInfo('SharedId: Existing shared id ' + storedId.id);
const resp = function (callback) {
Expand Down
6 changes: 6 additions & 0 deletions src/adapterManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ export let uspDataHandler = {
}
};

export let coppaDataHandler = {
getCoppa: function() {
return !!(config.getConfig('coppa'))
}
};

// export for testing
export let clientTestAdapters = [];
export const allS2SBidders = [];
Expand Down
26 changes: 24 additions & 2 deletions test/spec/modules/sharedIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ import {
sharedIdSubmodule,
} from 'modules/sharedIdSystem.js';
import { server } from 'test/mocks/xhr.js';
import {uspDataHandler} from 'src/adapterManager';

let expect = require('chai').expect;

describe('SharedId System', function() {
const SHAREDID_RESPONSE = {sharedId: 'testsharedid'};

let uspConsentDataStub;
describe('Xhr Requests from getId()', function() {
let callbackSpy = sinon.spy();

beforeEach(function() {
callbackSpy.resetHistory();
uspConsentDataStub = sinon.stub(uspDataHandler, 'getConsentData');
});

afterEach(function () {

uspConsentDataStub.restore();
});

it('should call shared id endpoint without consent data and handle a valid response', function () {
Expand Down Expand Up @@ -51,5 +53,25 @@ describe('SharedId System', function() {
expect(callbackSpy.calledOnce).to.be.true;
expect(callbackSpy.lastCall.lastArg.id).to.equal(SHAREDID_RESPONSE.sharedId);
});

it('should call shared id endpoint with usp consent data and handle a valid response', function () {
uspConsentDataStub.returns('1YYY');
let consentData = {
gdprApplies: true,
consentString: 'abc12345234',
};

let submoduleCallback = sharedIdSubmodule.getId(undefined, consentData).callback;
submoduleCallback(callbackSpy);

let request = server.requests[0];
expect(request.url).to.equal('https://id.sharedid.org/id?us_privacy=1YYY&gdpr=1&gdpr_consent=abc12345234');
expect(request.withCredentials).to.be.true;

request.respond(200, {}, JSON.stringify(SHAREDID_RESPONSE));

expect(callbackSpy.calledOnce).to.be.true;
expect(callbackSpy.lastCall.lastArg.id).to.equal(SHAREDID_RESPONSE.sharedId);
});
});
});
22 changes: 20 additions & 2 deletions test/spec/unit/core/adapterManager_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import adapterManager, { allS2SBidders, clientTestAdapters, gdprDataHandler } from 'src/adapterManager.js';
import adapterManager, { allS2SBidders, clientTestAdapters, gdprDataHandler, coppaDataHandler } from 'src/adapterManager.js';
import {
getAdUnits,
getServerTestingConfig,
Expand Down Expand Up @@ -1904,7 +1904,25 @@ describe('adapterManager tests', function () {
expect(bidRequests[0].gdprConsent).to.be.undefined;
});
});

describe('coppa consent module', function () {
afterEach(() => {
config.resetConfig();
});
it('test coppa configuration with value false', function () {
config.setConfig({ coppa: 0 });
const coppa = coppaDataHandler.getCoppa();
expect(coppa).to.be.false;
});
it('test coppa configuration with value true', function () {
config.setConfig({ coppa: 1 });
const coppa = coppaDataHandler.getCoppa();
expect(coppa).to.be.true;
});
it('test coppa configuration', function () {
const coppa = coppaDataHandler.getCoppa();
expect(coppa).to.be.false;
});
});
describe('s2sTesting - testServerOnly', () => {
beforeEach(() => {
config.setConfig({ s2sConfig: getServerTestingConfig(CONFIG) });
Expand Down

0 comments on commit cf5b060

Please sign in to comment.