prebid.js 7.50.0 → 7.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adhashBidAdapter.js +1 -1
  7. package/dist/adkernelBidAdapter.js +1 -1
  8. package/dist/admanBidAdapter.js +1 -1
  9. package/dist/adnuntiusBidAdapter.js +1 -1
  10. package/dist/adqueryBidAdapter.js +1 -1
  11. package/dist/adrelevantisBidAdapter.js +1 -1
  12. package/dist/adrinoBidAdapter.js +1 -1
  13. package/dist/adriverIdSystem.js +1 -1
  14. package/dist/adtelligentBidAdapter.js +1 -1
  15. package/dist/adtrgtmeBidAdapter.js +1 -1
  16. package/dist/adxcgBidAdapter.js +1 -1
  17. package/dist/adyoulikeBidAdapter.js +1 -1
  18. package/dist/ajaBidAdapter.js +1 -1
  19. package/dist/allowActivities.js +1 -0
  20. package/dist/amxBidAdapter.js +1 -1
  21. package/dist/amxIdSystem.js +1 -1
  22. package/dist/appierAnalyticsAdapter.js +1 -1
  23. package/dist/appnexusBidAdapter.js +1 -1
  24. package/dist/asoBidAdapter.js +1 -1
  25. package/dist/axonixBidAdapter.js +1 -1
  26. package/dist/bidglassBidAdapter.js +1 -1
  27. package/dist/big-richmediaBidAdapter.js +1 -1
  28. package/dist/bridgewellBidAdapter.js +1 -1
  29. package/dist/brightMountainMediaBidAdapter.js +1 -1
  30. package/dist/carodaBidAdapter.js +1 -1
  31. package/dist/chtnwBidAdapter.js +1 -1
  32. package/dist/cleanioRtdProvider.js +1 -1
  33. package/dist/concertBidAdapter.js +1 -1
  34. package/dist/connectIdSystem.js +1 -1
  35. package/dist/connectadBidAdapter.js +1 -1
  36. package/dist/consumableBidAdapter.js +1 -1
  37. package/dist/conversantAnalyticsAdapter.js +1 -1
  38. package/dist/conversantBidAdapter.js +1 -1
  39. package/dist/craftBidAdapter.js +1 -1
  40. package/dist/criteoBidAdapter.js +1 -1
  41. package/dist/cwireBidAdapter.js +1 -1
  42. package/dist/dependencies.json +6 -0
  43. package/dist/dspxBidAdapter.js +1 -1
  44. package/dist/eplanningBidAdapter.js +1 -1
  45. package/dist/feedadBidAdapter.js +1 -1
  46. package/dist/finativeBidAdapter.js +1 -1
  47. package/dist/freewheel-sspBidAdapter.js +1 -1
  48. package/dist/gdprEnforcement.js +1 -1
  49. package/dist/glimpseBidAdapter.js +1 -1
  50. package/dist/gmosspBidAdapter.js +1 -1
  51. package/dist/goldbachBidAdapter.js +1 -1
  52. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  53. package/dist/greenbidsRtdProvider.js +1 -1
  54. package/dist/gridBidAdapter.js +1 -1
  55. package/dist/growthCodeRtdProvider.js +1 -0
  56. package/dist/gumgumBidAdapter.js +1 -1
  57. package/dist/h12mediaBidAdapter.js +1 -1
  58. package/dist/id5IdSystem.js +1 -1
  59. package/dist/improvedigitalBidAdapter.js +1 -1
  60. package/dist/inmarBidAdapter.js +1 -1
  61. package/dist/insticatorBidAdapter.js +1 -1
  62. package/dist/ixBidAdapter.js +1 -1
  63. package/dist/justpremiumBidAdapter.js +1 -1
  64. package/dist/kargoBidAdapter.js +1 -1
  65. package/dist/konduitAnalyticsAdapter.js +1 -1
  66. package/dist/kueezBidAdapter.js +1 -1
  67. package/dist/kueezRtbBidAdapter.js +1 -1
  68. package/dist/kulturemediaBidAdapter.js +1 -1
  69. package/dist/lassoBidAdapter.js +1 -1
  70. package/dist/lifestreetBidAdapter.js +1 -1
  71. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  72. package/dist/logicadBidAdapter.js +1 -1
  73. package/dist/loglyliftBidAdapter.js +1 -1
  74. package/dist/magniteAnalyticsAdapter.js +1 -1
  75. package/dist/malltvAnalyticsAdapter.js +1 -1
  76. package/dist/marsmediaBidAdapter.js +1 -1
  77. package/dist/mediafuseBidAdapter.js +1 -1
  78. package/dist/mediasquareBidAdapter.js +1 -1
  79. package/dist/mgidBidAdapter.js +1 -1
  80. package/dist/minutemediaBidAdapter.js +1 -1
  81. package/dist/minutemediaplusBidAdapter.js +1 -1
  82. package/dist/nexx360BidAdapter.js +1 -1
  83. package/dist/not-for-prod/prebid.js +144 -140
  84. package/dist/objectGuard.js +1 -0
  85. package/dist/oguryBidAdapter.js +1 -1
  86. package/dist/onetagBidAdapter.js +1 -1
  87. package/dist/ooloAnalyticsAdapter.js +1 -1
  88. package/dist/optidigitalBidAdapter.js +1 -1
  89. package/dist/outbrainBidAdapter.js +1 -1
  90. package/dist/oxxionAnalyticsAdapter.js +1 -0
  91. package/dist/pairIdSystem.js +1 -1
  92. package/dist/parrableIdSystem.js +1 -1
  93. package/dist/pixfutureBidAdapter.js +1 -1
  94. package/dist/prebid-core.js +1 -1
  95. package/dist/prebidServerBidAdapter.js +1 -1
  96. package/dist/publinkIdSystem.js +1 -1
  97. package/dist/pubmaticBidAdapter.js +1 -1
  98. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  99. package/dist/pxyzBidAdapter.js +1 -1
  100. package/dist/quantcastBidAdapter.js +1 -1
  101. package/dist/readpeakBidAdapter.js +1 -1
  102. package/dist/relaidoBidAdapter.js +1 -1
  103. package/dist/retailspotBidAdapter.js +1 -1
  104. package/dist/rhythmoneBidAdapter.js +1 -1
  105. package/dist/riseBidAdapter.js +1 -1
  106. package/dist/rtdModule.js +1 -1
  107. package/dist/rubiconAnalyticsAdapter.js +1 -1
  108. package/dist/rubiconBidAdapter.js +1 -1
  109. package/dist/seedingAllianceBidAdapter.js +1 -1
  110. package/dist/seedtagBidAdapter.js +1 -1
  111. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  112. package/dist/sharethroughBidAdapter.js +1 -1
  113. package/dist/shinezBidAdapter.js +1 -1
  114. package/dist/smaatoBidAdapter.js +1 -1
  115. package/dist/smartadserverBidAdapter.js +1 -1
  116. package/dist/smartxBidAdapter.js +1 -1
  117. package/dist/smilewantedBidAdapter.js +1 -1
  118. package/dist/sonobiBidAdapter.js +1 -1
  119. package/dist/sovrnAnalyticsAdapter.js +1 -1
  120. package/dist/sovrnBidAdapter.js +1 -1
  121. package/dist/sspBCBidAdapter.js +1 -1
  122. package/dist/stvBidAdapter.js +1 -1
  123. package/dist/sublimeBidAdapter.js +1 -1
  124. package/dist/synacormediaBidAdapter.js +1 -1
  125. package/dist/targetVideoBidAdapter.js +1 -1
  126. package/dist/teadsBidAdapter.js +1 -1
  127. package/dist/trionBidAdapter.js +1 -1
  128. package/dist/tripleliftBidAdapter.js +1 -1
  129. package/dist/ttdBidAdapter.js +1 -1
  130. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  131. package/dist/uid2IdSystem.js +1 -1
  132. package/dist/underdogmediaBidAdapter.js +1 -1
  133. package/dist/undertoneBidAdapter.js +1 -1
  134. package/dist/userId.js +1 -1
  135. package/dist/vidazooBidAdapter.js +1 -1
  136. package/dist/videobyteBidAdapter.js +1 -1
  137. package/dist/visxBidAdapter.js +1 -1
  138. package/dist/vuukleBidAdapter.js +1 -1
  139. package/dist/widespaceBidAdapter.js +1 -1
  140. package/dist/winrBidAdapter.js +1 -1
  141. package/dist/yahoosspBidAdapter.js +1 -1
  142. package/dist/yieldmoBidAdapter.js +1 -1
  143. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  144. package/dist/zeta_global_sspBidAdapter.js +1 -1
  145. package/integrationExamples/gpt/growthcode.html +20 -9
  146. package/libraries/objectGuard/objectGuard.js +108 -0
  147. package/libraries/objectGuard/ortbGuard.js +88 -0
  148. package/modules/adgenerationBidAdapter.js +14 -5
  149. package/modules/adhashBidAdapter.js +28 -17
  150. package/modules/adkernelBidAdapter.js +2 -1
  151. package/modules/admanBidAdapter.js +30 -22
  152. package/modules/adnuntiusBidAdapter.js +98 -79
  153. package/modules/adnuntiusBidAdapter.md +2 -1
  154. package/modules/adqueryBidAdapter.js +7 -1
  155. package/modules/adrinoBidAdapter.js +1 -0
  156. package/modules/adriverIdSystem.js +1 -1
  157. package/modules/adtelligentBidAdapter.js +4 -2
  158. package/modules/allowActivities.js +74 -0
  159. package/modules/appnexusBidAdapter.js +1 -0
  160. package/modules/cleanioRtdProvider.js +2 -4
  161. package/modules/connectIdSystem.js +89 -13
  162. package/modules/connectIdSystem.md +4 -7
  163. package/modules/criteoBidAdapter.js +50 -3
  164. package/modules/freewheel-sspBidAdapter.js +10 -2
  165. package/modules/gdprEnforcement.js +98 -169
  166. package/modules/growthCodeRtdProvider.js +131 -0
  167. package/modules/growthCodeRtdProvider.md +55 -0
  168. package/modules/gumgumBidAdapter.js +5 -0
  169. package/modules/ixBidAdapter.js +5 -2
  170. package/modules/minutemediaBidAdapter.js +13 -3
  171. package/modules/oxxionAnalyticsAdapter.js +212 -0
  172. package/modules/oxxionAnalyticsAdapter.md +33 -0
  173. package/modules/pairIdSystem.js +6 -6
  174. package/modules/prebidServerBidAdapter/index.js +7 -8
  175. package/modules/pubmaticBidAdapter.js +1 -0
  176. package/modules/riseBidAdapter.js +13 -3
  177. package/modules/rtbhouseBidAdapter.md +24 -0
  178. package/modules/rtdModule/index.js +12 -1
  179. package/modules/sharethroughBidAdapter.js +2 -2
  180. package/modules/smartadserverBidAdapter.js +5 -0
  181. package/modules/stvBidAdapter.js +34 -1
  182. package/modules/undertoneBidAdapter.js +9 -1
  183. package/modules/userId/index.js +69 -41
  184. package/modules/yahoosspBidAdapter.js +45 -3
  185. package/modules/yahoosspBidAdapter.md +1 -1
  186. package/modules/zeta_global_sspBidAdapter.js +1 -0
  187. package/package.json +1 -1
  188. package/src/activities/activities.js +47 -0
  189. package/src/activities/activityParams.js +8 -0
  190. package/src/activities/modules.js +1 -1
  191. package/src/activities/params.js +59 -0
  192. package/src/activities/redactor.js +157 -0
  193. package/src/activities/rules.js +95 -0
  194. package/src/adapterManager.js +45 -8
  195. package/src/adloader.js +2 -1
  196. package/src/fpd/rootDomain.js +1 -1
  197. package/src/native.js +20 -4
  198. package/src/prebid.js +1 -1
  199. package/src/storageManager.js +57 -44
  200. package/src/userSync.js +35 -18
  201. package/test/spec/activities/allowActivites_spec.js +138 -0
  202. package/test/spec/activities/objectGuard_spec.js +144 -0
  203. package/test/spec/activities/ortbGuard_spec.js +140 -0
  204. package/test/spec/activities/params_spec.js +25 -0
  205. package/test/spec/activities/redactor_spec.js +296 -0
  206. package/test/spec/activities/rules_spec.js +135 -0
  207. package/test/spec/modules/adgenerationBidAdapter_spec.js +52 -12
  208. package/test/spec/modules/adhashBidAdapter_spec.js +51 -1
  209. package/test/spec/modules/admanBidAdapter_spec.js +1 -2
  210. package/test/spec/modules/adnuntiusBidAdapter_spec.js +535 -264
  211. package/test/spec/modules/adqueryBidAdapter_spec.js +9 -0
  212. package/test/spec/modules/adrinoBidAdapter_spec.js +4 -0
  213. package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
  214. package/test/spec/modules/cleanioRtdProvider_spec.js +7 -8
  215. package/test/spec/modules/connectIdSystem_spec.js +291 -23
  216. package/test/spec/modules/criteoBidAdapter_spec.js +134 -2
  217. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +5 -2
  218. package/test/spec/modules/gdprEnforcement_spec.js +127 -414
  219. package/test/spec/modules/growthCodeRtdProvider_spec.js +127 -0
  220. package/test/spec/modules/gumgumBidAdapter_spec.js +14 -0
  221. package/test/spec/modules/ixBidAdapter_spec.js +2 -1
  222. package/test/spec/modules/minutemediaBidAdapter_spec.js +69 -1
  223. package/test/spec/modules/oxxionAnalyticsAdapter_spec.js +324 -0
  224. package/test/spec/modules/pairIdSystem_spec.js +16 -3
  225. package/test/spec/modules/prebidServerBidAdapter_spec.js +3 -1
  226. package/test/spec/modules/pubmaticBidAdapter_spec.js +7 -0
  227. package/test/spec/modules/realTimeDataModule_spec.js +1 -1
  228. package/test/spec/modules/riseBidAdapter_spec.js +69 -1
  229. package/test/spec/modules/sharethroughBidAdapter_spec.js +1 -1
  230. package/test/spec/modules/smartadserverBidAdapter_spec.js +42 -0
  231. package/test/spec/modules/stvBidAdapter_spec.js +13 -1
  232. package/test/spec/modules/undertoneBidAdapter_spec.js +57 -1
  233. package/test/spec/modules/userId_spec.js +80 -21
  234. package/test/spec/modules/yahoosspBidAdapter_spec.js +103 -51
  235. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +4 -0
  236. package/test/spec/native_spec.js +12 -12
  237. package/test/spec/unit/core/adapterManager_spec.js +181 -1
  238. package/test/spec/unit/core/storageManager_spec.js +76 -68
  239. package/test/spec/unit/pbjs_api_spec.js +15 -25
  240. package/test/spec/userSync_spec.js +45 -16
@@ -1,16 +1,17 @@
1
1
  import {
2
+ accessDeviceRule,
2
3
  deviceAccessHook,
3
- enableAnalyticsHook,
4
4
  enforcementRules,
5
+ enrichEidsRule,
6
+ fetchBidsRule,
5
7
  getGvlid,
6
8
  getGvlidFromAnalyticsAdapter,
7
- makeBidRequestsHook,
8
9
  purpose1Rule,
9
10
  purpose2Rule,
11
+ reportAnalyticsRule,
10
12
  setEnforcementConfig,
11
13
  STRICT_STORAGE_ENFORCEMENT,
12
- userIdHook,
13
- userSyncHook,
14
+ syncUserRule,
14
15
  validateRules
15
16
  } from 'modules/gdprEnforcement.js';
16
17
  import {config} from 'src/config.js';
@@ -19,7 +20,7 @@ import * as utils from 'src/utils.js';
19
20
  import {
20
21
  MODULE_TYPE_ANALYTICS,
21
22
  MODULE_TYPE_BIDDER,
22
- MODULE_TYPE_CORE,
23
+ MODULE_TYPE_PREBID,
23
24
  MODULE_TYPE_UID
24
25
  } from '../../../src/activities/modules.js';
25
26
  import * as events from 'src/events.js';
@@ -28,6 +29,7 @@ import 'src/prebid.js';
28
29
  import {hook} from '../../../src/hook.js';
29
30
  import {GDPR_GVLIDS, VENDORLESS_GVLID} from '../../../src/consentHandler.js';
30
31
  import {validateStorageEnforcement} from '../../../src/storageManager.js';
32
+ import {activityParams} from '../../../src/activities/activityParams.js';
31
33
 
32
34
  describe('gdpr enforcement', function () {
33
35
  let nextFnSpy;
@@ -107,65 +109,47 @@ describe('gdpr enforcement', function () {
107
109
  }
108
110
  }
109
111
  };
110
- let gvlids;
112
+ let gvlids, sandbox;
113
+
114
+ function setupConsentData({gdprApplies = true, apiVersion = 2} = {}) {
115
+ const cd = utils.deepClone(staticConfig);
116
+ const consent = {
117
+ vendorData: cd.consentData.getTCData,
118
+ gdprApplies,
119
+ apiVersion
120
+ };
121
+ sandbox.stub(gdprDataHandler, 'getConsentData').callsFake(() => consent)
122
+ return consent;
123
+ }
111
124
 
112
125
  before(() => {
113
126
  hook.ready();
114
127
  });
115
128
 
116
129
  after(function () {
117
- validateStorageEnforcement.getHooks({ hook: deviceAccessHook }).remove();
118
130
  $$PREBID_GLOBAL$$.requestBids.getHooks().remove();
119
- adapterManager.makeBidRequests.getHooks({ hook: makeBidRequestsHook }).remove();
120
131
  })
121
132
 
133
+ function expectAllow(allow, ruleResult) {
134
+ allow ? expect(ruleResult).to.not.exist : sinon.assert.match(ruleResult, {allow: false});
135
+ }
136
+
122
137
  beforeEach(() => {
138
+ sandbox = sinon.sandbox.create();
123
139
  gvlids = {};
124
- sinon.stub(GDPR_GVLIDS, 'get').callsFake((name) => ({gvlid: gvlids[name], modules: {}}));
140
+ sandbox.stub(GDPR_GVLIDS, 'get').callsFake((name) => ({gvlid: gvlids[name], modules: {}}));
125
141
  });
126
142
 
127
143
  afterEach(() => {
128
- GDPR_GVLIDS.get.restore();
129
- });
130
-
131
- describe('deviceAccessHook', function () {
132
- beforeEach(function () {
133
- nextFnSpy = sinon.spy();
134
- gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData');
135
- logWarnSpy = sinon.spy(utils, 'logWarn');
136
- });
144
+ sandbox.restore();
145
+ })
137
146
 
138
- afterEach(function () {
147
+ describe('deviceAccessRule', () => {
148
+ afterEach(() => {
139
149
  config.resetConfig();
140
- gdprDataHandler.getConsentData.restore();
141
- logWarnSpy.restore();
142
- });
143
-
144
- it('should not allow device access when device access flag is set to false', function () {
145
- config.setConfig({
146
- deviceAccess: false,
147
- consentManagement: {
148
- gdpr: {
149
- rules: [{
150
- purpose: 'storage',
151
- enforcePurpose: false,
152
- enforceVendor: false,
153
- vendorExceptions: ['appnexus', 'rubicon']
154
- }]
155
- }
156
- }
157
- });
158
-
159
- deviceAccessHook(nextFnSpy);
160
- expect(nextFnSpy.calledOnce).to.equal(true);
161
- let result = {
162
- hasEnforcementHook: true,
163
- valid: false
164
- }
165
- sinon.assert.calledWith(nextFnSpy, undefined, undefined, result);
166
150
  });
167
151
 
168
- it('should only check for consent for vendor exceptions when enforcePurpose and enforceVendor are false', function () {
152
+ it('should not check for consent when enforcePurpose and enforceVendor are false', function () {
169
153
  Object.assign(gvlids, {
170
154
  appnexus: 1,
171
155
  rubicon: 5
@@ -180,15 +164,8 @@ describe('gdpr enforcement', function () {
180
164
  }]
181
165
  }
182
166
  });
183
- let consentData = {}
184
- consentData.vendorData = staticConfig.consentData.getTCData;
185
- consentData.gdprApplies = true;
186
- consentData.apiVersion = 2;
187
- gdprDataHandlerStub.returns(consentData);
188
-
189
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus');
190
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'rubicon');
191
- expect(logWarnSpy.callCount).to.equal(0);
167
+ setupConsentData();
168
+ ['appnexus', 'rubicon'].forEach(bidder => expectAllow(true, accessDeviceRule(activityParams(MODULE_TYPE_BIDDER, bidder))));
192
169
  });
193
170
 
194
171
  it('should check consent for all vendors when enforcePurpose and enforceVendor are true', function () {
@@ -205,15 +182,13 @@ describe('gdpr enforcement', function () {
205
182
  }]
206
183
  }
207
184
  });
208
- let consentData = {}
209
- consentData.vendorData = staticConfig.consentData.getTCData;
210
- consentData.gdprApplies = true;
211
- consentData.apiVersion = 2;
212
- gdprDataHandlerStub.returns(consentData);
213
-
214
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus');
215
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'rubicon');
216
- expect(logWarnSpy.callCount).to.equal(1);
185
+ setupConsentData();
186
+ Object.entries({
187
+ appnexus: true,
188
+ rubicon: false
189
+ }).forEach(([bidder, isAllowed]) => {
190
+ expectAllow(isAllowed, accessDeviceRule(activityParams(MODULE_TYPE_BIDDER, bidder)));
191
+ })
217
192
  });
218
193
 
219
194
  it('should allow device access when gdprApplies is false and hasDeviceAccess flag is true', function () {
@@ -228,19 +203,8 @@ describe('gdpr enforcement', function () {
228
203
  }]
229
204
  }
230
205
  });
231
- let consentData = {}
232
- consentData.vendorData = staticConfig.consentData.getTCData;
233
- consentData.gdprApplies = false;
234
- consentData.apiVersion = 2;
235
- gdprDataHandlerStub.returns(consentData);
236
-
237
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus');
238
- expect(nextFnSpy.calledOnce).to.equal(true);
239
- let result = {
240
- hasEnforcementHook: true,
241
- valid: true
242
- }
243
- sinon.assert.calledWith(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus', result);
206
+ setupConsentData();
207
+ expectAllow(true, accessDeviceRule(activityParams(MODULE_TYPE_BIDDER, 'appnexus')));
244
208
  });
245
209
 
246
210
  it('should use gvlMapping set by publisher', function() {
@@ -259,92 +223,18 @@ describe('gdpr enforcement', function () {
259
223
  }]
260
224
  }
261
225
  });
262
- let consentData = {}
263
- consentData.vendorData = staticConfig.consentData.getTCData;
264
- consentData.gdprApplies = true;
265
- consentData.apiVersion = 2;
266
- gdprDataHandlerStub.returns(consentData);
267
-
268
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus');
269
- expect(nextFnSpy.calledOnce).to.equal(true);
270
- let result = {
271
- hasEnforcementHook: true,
272
- valid: true
273
- }
274
- sinon.assert.calledWith(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus', result);
275
- config.resetConfig();
276
- });
277
-
278
- it('should use gvl id of alias and not of parent', function() {
279
- let curBidderStub = sinon.stub(config, 'getCurrentBidder');
280
- curBidderStub.returns('appnexus-alias');
281
- adapterManager.aliasBidAdapter('appnexus', 'appnexus-alias');
282
- config.setConfig({
283
- 'gvlMapping': {
284
- 'appnexus-alias': 4
285
- }
286
- });
287
- setEnforcementConfig({
288
- gdpr: {
289
- rules: [{
290
- purpose: 'storage',
291
- enforcePurpose: true,
292
- enforceVendor: true,
293
- vendorExceptions: []
294
- }]
295
- }
296
- });
297
- let consentData = {}
298
- consentData.vendorData = staticConfig.consentData.getTCData;
299
- consentData.gdprApplies = true;
300
- consentData.apiVersion = 2;
301
- gdprDataHandlerStub.returns(consentData);
302
-
303
- deviceAccessHook(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus');
304
- expect(nextFnSpy.calledOnce).to.equal(true);
305
- let result = {
306
- hasEnforcementHook: true,
307
- valid: true
308
- }
309
- sinon.assert.calledWith(nextFnSpy, MODULE_TYPE_BIDDER, 'appnexus', result);
310
- config.resetConfig();
311
- curBidderStub.restore();
226
+ setupConsentData();
227
+ expectAllow(true, accessDeviceRule(activityParams(MODULE_TYPE_BIDDER, 'appnexus')));
312
228
  });
313
229
 
314
230
  it(`should not enforce consent for vendorless modules if ${STRICT_STORAGE_ENFORCEMENT} is not set`, () => {
315
231
  setEnforcementConfig({});
316
- let consentData = {
317
- vendorData: staticConfig.consentData.getTCData,
318
- gdprApplies: true
319
- }
320
- gdprDataHandlerStub.returns(consentData);
321
- const validate = sinon.stub().callsFake(() => false);
322
- deviceAccessHook(nextFnSpy, MODULE_TYPE_CORE, 'mockModule', undefined, {validate});
323
- sinon.assert.callCount(validate, 0);
324
- sinon.assert.calledWith(nextFnSpy, MODULE_TYPE_CORE, 'mockModule', {hasEnforcementHook: true, valid: true});
232
+ setupConsentData();
233
+ expectAllow(true, accessDeviceRule(activityParams(MODULE_TYPE_PREBID, 'mockCoreModule')));
325
234
  })
326
235
  });
327
236
 
328
- describe('userSyncHook', function () {
329
- let curBidderStub;
330
- let adapterManagerStub;
331
-
332
- beforeEach(function () {
333
- gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData');
334
- logWarnSpy = sinon.spy(utils, 'logWarn');
335
- curBidderStub = sinon.stub(config, 'getCurrentBidder');
336
- adapterManagerStub = sinon.stub(adapterManager, 'getBidAdapter');
337
- nextFnSpy = sinon.spy();
338
- });
339
-
340
- afterEach(function () {
341
- config.getCurrentBidder.restore();
342
- config.resetConfig();
343
- gdprDataHandler.getConsentData.restore();
344
- adapterManager.getBidAdapter.restore();
345
- logWarnSpy.restore();
346
- });
347
-
237
+ describe('syncUserRule', () => {
348
238
  it('should allow bidder to do user sync if consent is true', function () {
349
239
  setEnforcementConfig({
350
240
  gdpr: {
@@ -356,20 +246,12 @@ describe('gdpr enforcement', function () {
356
246
  }]
357
247
  }
358
248
  });
359
- let consentData = {}
360
- consentData.vendorData = staticConfig.consentData.getTCData;
361
- consentData.gdprApplies = true;
362
- consentData.apiVersion = 2;
363
- gdprDataHandlerStub.returns(consentData);
364
-
365
- curBidderStub.returns('sampleBidder1');
366
- gvlids.sampleBidder1 = 1;
367
- userSyncHook(nextFnSpy);
368
-
369
- curBidderStub.returns('sampleBidder2');
370
- gvlids.sampleBidder2 = 3;
371
- userSyncHook(nextFnSpy);
372
- expect(nextFnSpy.calledTwice).to.equal(true);
249
+ setupConsentData();
250
+ Object.assign(gvlids, {
251
+ sampleBidder1: 1,
252
+ sampleBidder2: 2
253
+ })
254
+ Object.keys(gvlids).forEach(bidder => expect(syncUserRule(activityParams(MODULE_TYPE_BIDDER, bidder))).to.not.exist);
373
255
  });
374
256
 
375
257
  it('should not allow bidder to do user sync if user has denied consent', function () {
@@ -383,21 +265,18 @@ describe('gdpr enforcement', function () {
383
265
  }]
384
266
  }
385
267
  });
386
- let consentData = {}
387
- consentData.vendorData = staticConfig.consentData.getTCData;
388
- consentData.apiVersion = 2;
389
- consentData.gdprApplies = true;
390
- gdprDataHandlerStub.returns(consentData);
391
-
392
- curBidderStub.returns('sampleBidder1');
393
- gvlids.sampleBidder1 = 1;
394
- userSyncHook(nextFnSpy);
395
-
396
- curBidderStub.returns('sampleBidder2');
397
- gvlids.sampleBidder2 = 3;
398
- userSyncHook(nextFnSpy);
399
- expect(nextFnSpy.calledOnce).to.equal(true);
400
- expect(logWarnSpy.callCount).to.equal(1);
268
+ setupConsentData();
269
+ Object.assign(gvlids, {
270
+ sampleBidder1: 1,
271
+ sampleBidder2: 3
272
+ })
273
+
274
+ Object.entries({
275
+ sampleBidder1: true,
276
+ sampleBidder2: false
277
+ }).forEach(([bidder, isAllowed]) => {
278
+ expectAllow(isAllowed, syncUserRule(activityParams(MODULE_TYPE_BIDDER, bidder)));
279
+ })
401
280
  });
402
281
 
403
282
  it('should not check vendor consent when enforceVendor is false', function () {
@@ -411,33 +290,15 @@ describe('gdpr enforcement', function () {
411
290
  }]
412
291
  }
413
292
  });
414
- let consentData = {}
415
- consentData.vendorData = staticConfig.consentData.getTCData;
416
- consentData.apiVersion = 2;
417
- consentData.gdprApplies = true;
418
- gdprDataHandlerStub.returns(consentData);
419
-
420
- curBidderStub.returns('sampleBidder1');
421
- gvlids.sampleBidder1 = 1;
422
- userSyncHook(nextFnSpy);
423
-
424
- curBidderStub.returns('sampleBidder2');
425
- gvlids.sampleBidder2 = 3;
426
- userSyncHook(nextFnSpy);
427
- expect(nextFnSpy.calledTwice).to.equal(true);
428
- expect(logWarnSpy.callCount).to.equal(0);
293
+ setupConsentData();
294
+ Object.assign(gvlids, {
295
+ sampleBidder1: 1,
296
+ sampleBidder2: 3
297
+ })
298
+ Object.keys(gvlids).forEach(bidder => expect(syncUserRule(activityParams(MODULE_TYPE_BIDDER, bidder))).to.not.exist);
429
299
  });
430
300
  });
431
-
432
- describe('userIdHook', function () {
433
- beforeEach(function () {
434
- logWarnSpy = sinon.spy(utils, 'logWarn');
435
- nextFnSpy = sinon.spy();
436
- });
437
- afterEach(function () {
438
- config.resetConfig();
439
- logWarnSpy.restore();
440
- });
301
+ describe('enrichEidsRule', () => {
441
302
  it('should allow user id module if consent is given', function () {
442
303
  setEnforcementConfig({
443
304
  gdpr: {
@@ -449,40 +310,16 @@ describe('gdpr enforcement', function () {
449
310
  }]
450
311
  }
451
312
  });
452
- let consentData = {}
453
- consentData.vendorData = staticConfig.consentData.getTCData;
454
- consentData.apiVersion = 2;
455
- consentData.gdprApplies = true;
456
- let submodules = [{
457
- submodule: {
458
- gvlid: 1,
459
- name: 'sampleUserId'
460
- }
461
- }]
313
+ setupConsentData();
462
314
  gvlids.sampleUserId = 1;
463
- userIdHook(nextFnSpy, submodules, consentData);
464
- // Should pass back hasValidated flag since version 2
465
- const args = nextFnSpy.getCalls()[0].args;
466
- expect(args[1].hasValidated).to.be.true;
467
- expect(nextFnSpy.calledOnce).to.equal(true);
468
- sinon.assert.calledWith(nextFnSpy, submodules, { ...consentData, hasValidated: true });
315
+ expect(enrichEidsRule(activityParams(MODULE_TYPE_UID, 'sampleUserId'))).to.not.exist;
469
316
  });
470
317
 
471
318
  it('should allow userId module if gdpr not in scope', function () {
472
- let submodules = [{
473
- submodule: {
474
- gvlid: 1,
475
- name: 'sampleUserId'
476
- }
477
- }];
478
319
  gvlids.sampleUserId = 1;
479
- let consentData = null;
480
- userIdHook(nextFnSpy, submodules, consentData);
481
- // Should not pass back hasValidated flag since version 2
482
- const args = nextFnSpy.getCalls()[0].args;
483
- expect(args[1]).to.be.null;
484
- expect(nextFnSpy.calledOnce).to.equal(true);
485
- sinon.assert.calledWith(nextFnSpy, submodules, consentData);
320
+ const consent = setupConsentData({gdprApplies: false});
321
+ consent.vendorData.purpose.consents['1'] = false;
322
+ expect(enrichEidsRule(activityParams(MODULE_TYPE_UID, 'sampleUserId'))).to.not.exist;
486
323
  });
487
324
 
488
325
  it('should not allow user id module if user denied consent', function () {
@@ -496,72 +333,23 @@ describe('gdpr enforcement', function () {
496
333
  }]
497
334
  }
498
335
  });
499
- let consentData = {}
500
- consentData.vendorData = staticConfig.consentData.getTCData;
501
- consentData.apiVersion = 2;
502
- consentData.gdprApplies = true;
503
-
504
- let submodules = [{
505
- submodule: {
506
- gvlid: 1,
507
- name: 'sampleUserId'
508
- }
509
- }, {
510
- submodule: {
511
- gvlid: 3,
512
- name: 'sampleUserId1'
513
- }
514
- }]
336
+ setupConsentData();
515
337
  Object.assign(gvlids, {
516
338
  sampleUserId: 1,
517
339
  sampleUserId1: 3
518
340
  });
519
- userIdHook(nextFnSpy, submodules, consentData);
520
- expect(logWarnSpy.callCount).to.equal(1);
521
- let expectedSubmodules = [{
522
- submodule: {
523
- gvlid: 1,
524
- name: 'sampleUserId'
525
- }
526
- }]
527
- sinon.assert.calledWith(nextFnSpy, expectedSubmodules, { ...consentData, hasValidated: true });
341
+ Object.entries({
342
+ sampleUserId: true,
343
+ sampleUserId1: false
344
+ }).forEach(([name, allow]) => {
345
+ expectAllow(allow, enrichEidsRule(activityParams(MODULE_TYPE_UID, name)))
346
+ });
528
347
  });
529
348
  });
530
349
 
531
- describe('makeBidRequestsHook', function () {
532
- let sandbox;
533
- let adapterManagerStub;
534
- let emitEventSpy;
535
-
536
- const MOCK_AD_UNITS = [{
537
- code: 'ad-unit-1',
538
- mediaTypes: {},
539
- bids: [{
540
- bidder: 'bidder_1' // has consent
541
- }, {
542
- bidder: 'bidder_2' // doesn't have consent, but liTransparency is true. Bidder remains active.
543
- }]
544
- }, {
545
- code: 'ad-unit-2',
546
- mediaTypes: {},
547
- bids: [{
548
- bidder: 'bidder_2'
549
- }, {
550
- bidder: 'bidder_3'
551
- }]
552
- }];
553
-
554
- beforeEach(function () {
555
- sandbox = sinon.createSandbox();
556
- gdprDataHandlerStub = sandbox.stub(gdprDataHandler, 'getConsentData');
557
- adapterManagerStub = sandbox.stub(adapterManager, 'getBidAdapter');
558
- logWarnSpy = sandbox.spy(utils, 'logWarn');
559
- nextFnSpy = sandbox.spy();
560
- emitEventSpy = sandbox.spy(events, 'emit');
561
- });
350
+ describe('fetchBidsRule', () => {
562
351
  afterEach(function () {
563
352
  config.resetConfig();
564
- sandbox.restore();
565
353
  });
566
354
 
567
355
  it('should block bidder which does not have consent and allow bidder which has consent (liTransparency is established)', function () {
@@ -575,35 +363,12 @@ describe('gdpr enforcement', function () {
575
363
  }]
576
364
  }
577
365
  });
578
- const consentData = {};
579
- consentData.vendorData = staticConfig.consentData.getTCData;
580
- consentData.apiVersion = 2;
581
- consentData.gdprApplies = true;
582
-
583
- gdprDataHandlerStub.returns(consentData);
366
+ setupConsentData()
584
367
  Object.assign(gvlids, {
585
368
  bidder_1: 4,
586
369
  bidder_2: 5,
587
370
  });
588
- makeBidRequestsHook(nextFnSpy, MOCK_AD_UNITS, []);
589
-
590
- // Assertions
591
- expect(nextFnSpy.calledOnce).to.equal(true);
592
- sinon.assert.calledWith(nextFnSpy, [{
593
- code: 'ad-unit-1',
594
- mediaTypes: {},
595
- bids: [
596
- sinon.match({ bidder: 'bidder_1' }),
597
- sinon.match({ bidder: 'bidder_2' })
598
- ]
599
- }, {
600
- code: 'ad-unit-2',
601
- mediaTypes: {},
602
- bids: [
603
- sinon.match({ bidder: 'bidder_2' }),
604
- sinon.match({ bidder: 'bidder_3' }) // should be allowed even though it's doesn't have a gvlId because liTransparency is established.
605
- ]
606
- }], []);
371
+ ['bidder_1', 'bidder_2', 'bidder_3'].forEach(bidder => expect(fetchBidsRule(activityParams(MODULE_TYPE_BIDDER, bidder))).to.not.exist);
607
372
  });
608
373
 
609
374
  it('should block bidder which does not have consent and allow bidder which has consent (liTransparency is NOT established)', function() {
@@ -617,41 +382,19 @@ describe('gdpr enforcement', function () {
617
382
  }]
618
383
  }
619
384
  });
620
- const consentData = {};
621
-
622
- // set li for purpose 2 to false
623
- const newConsentData = utils.deepClone(staticConfig);
624
- newConsentData.consentData.getTCData.purpose.legitimateInterests['2'] = false;
625
-
626
- consentData.vendorData = newConsentData.consentData.getTCData;
627
- consentData.apiVersion = 2;
628
- consentData.gdprApplies = true;
629
-
630
- gdprDataHandlerStub.returns(consentData);
385
+ const consent = setupConsentData();
386
+ consent.vendorData.purpose.legitimateInterests['2'] = false;
631
387
  Object.assign(gvlids, {
632
388
  bidder_1: 4,
633
389
  bidder_2: 5,
634
390
  })
635
-
636
- makeBidRequestsHook(nextFnSpy, MOCK_AD_UNITS, []);
637
-
638
- // Assertions
639
- expect(nextFnSpy.calledOnce).to.equal(true);
640
- sinon.assert.calledWith(nextFnSpy, [{
641
- code: 'ad-unit-1',
642
- mediaTypes: {},
643
- bids: [
644
- sinon.match({ bidder: 'bidder_1' }), // 'bidder_2' is not present because it doesn't have vendorConsent
645
- ]
646
- }, {
647
- code: 'ad-unit-2',
648
- mediaTypes: {},
649
- bids: [
650
- sinon.match({ bidder: 'bidder_3' }), // 'bidder_3' is allowed despite gvlId being undefined because it's part of vendorExceptions
651
- ]
652
- }], []);
653
-
654
- expect(logWarnSpy.calledOnce).to.equal(true);
391
+ Object.entries({
392
+ bidder_1: true,
393
+ bidder_2: false,
394
+ bidder_3: true
395
+ }).forEach(([bidder, allowed]) => {
396
+ expectAllow(allowed, fetchBidsRule(activityParams(MODULE_TYPE_BIDDER, bidder)));
397
+ })
655
398
  });
656
399
 
657
400
  it('should skip validation checks if GDPR version is not equal to "2"', function () {
@@ -659,57 +402,36 @@ describe('gdpr enforcement', function () {
659
402
  gdpr: {
660
403
  rules: [{
661
404
  purpose: 'storage',
662
- enforePurpose: false,
663
- enforceVendor: false,
405
+ enforcePurpose: true,
406
+ enforceVendor: true,
664
407
  vendorExceptions: []
665
408
  }]
666
409
  }
667
410
  });
668
-
669
- const consentData = {};
670
- consentData.vendorData = staticConfig.consentData.getTCData;
671
- consentData.apiVersion = 1;
672
- consentData.gdprApplies = true;
673
- gdprDataHandlerStub.returns(consentData);
674
-
675
- makeBidRequestsHook(nextFnSpy, MOCK_AD_UNITS, []);
676
-
677
- // Assertions
678
- expect(nextFnSpy.calledOnce).to.equal(true);
679
- sinon.assert.calledWith(nextFnSpy, sinon.match.array.deepEquals(MOCK_AD_UNITS), []);
680
- expect(emitEventSpy.notCalled).to.equal(true);
681
- expect(logWarnSpy.notCalled).to.equal(true);
682
- });
683
- });
684
-
685
- describe('enableAnalyticsHook', function () {
686
- let sandbox;
687
- let adapterManagerStub;
688
-
689
- const MOCK_ANALYTICS_ADAPTER_CONFIG = [{
690
- provider: 'analyticsAdapter_A',
691
- options: {}
692
- }, {
693
- provider: 'analyticsAdapter_B',
694
- options: {}
695
- }, {
696
- provider: 'analyticsAdapter_C',
697
- options: {}
698
- }];
699
-
700
- beforeEach(function () {
701
- sandbox = sinon.createSandbox();
702
- gdprDataHandlerStub = sandbox.stub(gdprDataHandler, 'getConsentData');
703
- adapterManagerStub = sandbox.stub(adapterManager, 'getAnalyticsAdapter');
704
- logWarnSpy = sandbox.spy(utils, 'logWarn');
705
- nextFnSpy = sandbox.spy();
411
+ const consent = setupConsentData();
412
+ consent.vendorData.purpose.consents['2'] = false;
413
+ consent.apiVersion = 1;
414
+ ['bidder_1', 'bidder_2', 'bidder_3'].forEach(bidder => expect(fetchBidsRule(activityParams(MODULE_TYPE_BIDDER, bidder))).to.not.exist);
706
415
  });
707
416
 
708
- afterEach(function() {
709
- config.resetConfig();
710
- sandbox.restore();
711
- });
417
+ it('should skip validation if enforcePurpose is false', () => {
418
+ setEnforcementConfig({
419
+ gdpr: {
420
+ rules: [{
421
+ purpose: 'storage',
422
+ enforcePurpose: false,
423
+ enforceVendor: true,
424
+ vendorExceptions: []
425
+ }]
426
+ }
427
+ });
428
+ const consent = setupConsentData();
429
+ consent.vendorData.purpose.consents['2'] = false;
430
+ ['bidder_1', 'bidder_2', 'bidder_3'].forEach(bidder => expect(fetchBidsRule(activityParams(MODULE_TYPE_BIDDER, bidder))).to.not.exist);
431
+ })
432
+ });
712
433
 
434
+ describe('reportAnalyticsRule', () => {
713
435
  it('should block analytics adapter which does not have consent and allow the one(s) which have consent', function() {
714
436
  setEnforcementConfig({
715
437
  gdpr: {
@@ -722,30 +444,21 @@ describe('gdpr enforcement', function () {
722
444
  }
723
445
  });
724
446
 
725
- const consentData = {};
726
- consentData.vendorData = staticConfig.consentData.getTCData;
727
- consentData.apiVersion = 2;
728
- consentData.gdprApplies = true;
729
-
730
- gdprDataHandlerStub.returns(consentData);
731
447
  Object.assign(gvlids, {
732
448
  analyticsAdapter_A: 3,
733
449
  analyticsAdapter_B: 5,
734
450
  analyticsAdapter_C: 1
735
451
  });
736
452
 
737
- enableAnalyticsHook(nextFnSpy, MOCK_ANALYTICS_ADAPTER_CONFIG);
453
+ setupConsentData()
738
454
 
739
- // Assertions
740
- expect(nextFnSpy.calledOnce).to.equal(true);
741
- sinon.assert.calledWith(nextFnSpy, [{
742
- provider: 'analyticsAdapter_B',
743
- options: {}
744
- }, {
745
- provider: 'analyticsAdapter_C',
746
- options: {}
747
- }]);
748
- expect(logWarnSpy.calledOnce).to.equal(true);
455
+ Object.entries({
456
+ analyticsAdapter_A: false,
457
+ analyticsAdapter_B: true,
458
+ analyticsAdapter_C: true
459
+ }).forEach(([adapter, allow]) => {
460
+ expectAllow(allow, reportAnalyticsRule(activityParams(MODULE_TYPE_ANALYTICS, adapter)))
461
+ })
749
462
  });
750
463
  });
751
464
 
@@ -1150,7 +863,7 @@ describe('gdpr enforcement', function () {
1150
863
 
1151
864
  it('should return VENDORLESS_GVLID for core modules', () => {
1152
865
  entry = {gvlid: 123};
1153
- expect(getGvlid(MODULE_TYPE_CORE, MOCK_MODULE, fallbackFn)).to.equal(VENDORLESS_GVLID);
866
+ expect(getGvlid(MODULE_TYPE_PREBID, MOCK_MODULE, fallbackFn)).to.equal(VENDORLESS_GVLID);
1154
867
  });
1155
868
 
1156
869
  describe('multiple GVL IDs are found', () => {