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.
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adhashBidAdapter.js +1 -1
- package/dist/adkernelBidAdapter.js +1 -1
- package/dist/admanBidAdapter.js +1 -1
- package/dist/adnuntiusBidAdapter.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adrinoBidAdapter.js +1 -1
- package/dist/adriverIdSystem.js +1 -1
- package/dist/adtelligentBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/allowActivities.js +1 -0
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/cleanioRtdProvider.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectIdSystem.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dependencies.json +6 -0
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/gdprEnforcement.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/growthCodeRtdProvider.js +1 -0
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmarBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/kueezRtbBidAdapter.js +1 -1
- package/dist/kulturemediaBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/minutemediaplusBidAdapter.js +1 -1
- package/dist/nexx360BidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +144 -140
- package/dist/objectGuard.js +1 -0
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/oxxionAnalyticsAdapter.js +1 -0
- package/dist/pairIdSystem.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +1 -1
- package/dist/prebidServerBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rtdModule.js +1 -1
- package/dist/rubiconAnalyticsAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/shinezBidAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/uid2IdSystem.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooBidAdapter.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/dist/zeta_global_sspBidAdapter.js +1 -1
- package/integrationExamples/gpt/growthcode.html +20 -9
- package/libraries/objectGuard/objectGuard.js +108 -0
- package/libraries/objectGuard/ortbGuard.js +88 -0
- package/modules/adgenerationBidAdapter.js +14 -5
- package/modules/adhashBidAdapter.js +28 -17
- package/modules/adkernelBidAdapter.js +2 -1
- package/modules/admanBidAdapter.js +30 -22
- package/modules/adnuntiusBidAdapter.js +98 -79
- package/modules/adnuntiusBidAdapter.md +2 -1
- package/modules/adqueryBidAdapter.js +7 -1
- package/modules/adrinoBidAdapter.js +1 -0
- package/modules/adriverIdSystem.js +1 -1
- package/modules/adtelligentBidAdapter.js +4 -2
- package/modules/allowActivities.js +74 -0
- package/modules/appnexusBidAdapter.js +1 -0
- package/modules/cleanioRtdProvider.js +2 -4
- package/modules/connectIdSystem.js +89 -13
- package/modules/connectIdSystem.md +4 -7
- package/modules/criteoBidAdapter.js +50 -3
- package/modules/freewheel-sspBidAdapter.js +10 -2
- package/modules/gdprEnforcement.js +98 -169
- package/modules/growthCodeRtdProvider.js +131 -0
- package/modules/growthCodeRtdProvider.md +55 -0
- package/modules/gumgumBidAdapter.js +5 -0
- package/modules/ixBidAdapter.js +5 -2
- package/modules/minutemediaBidAdapter.js +13 -3
- package/modules/oxxionAnalyticsAdapter.js +212 -0
- package/modules/oxxionAnalyticsAdapter.md +33 -0
- package/modules/pairIdSystem.js +6 -6
- package/modules/prebidServerBidAdapter/index.js +7 -8
- package/modules/pubmaticBidAdapter.js +1 -0
- package/modules/riseBidAdapter.js +13 -3
- package/modules/rtbhouseBidAdapter.md +24 -0
- package/modules/rtdModule/index.js +12 -1
- package/modules/sharethroughBidAdapter.js +2 -2
- package/modules/smartadserverBidAdapter.js +5 -0
- package/modules/stvBidAdapter.js +34 -1
- package/modules/undertoneBidAdapter.js +9 -1
- package/modules/userId/index.js +69 -41
- package/modules/yahoosspBidAdapter.js +45 -3
- package/modules/yahoosspBidAdapter.md +1 -1
- package/modules/zeta_global_sspBidAdapter.js +1 -0
- package/package.json +1 -1
- package/src/activities/activities.js +47 -0
- package/src/activities/activityParams.js +8 -0
- package/src/activities/modules.js +1 -1
- package/src/activities/params.js +59 -0
- package/src/activities/redactor.js +157 -0
- package/src/activities/rules.js +95 -0
- package/src/adapterManager.js +45 -8
- package/src/adloader.js +2 -1
- package/src/fpd/rootDomain.js +1 -1
- package/src/native.js +20 -4
- package/src/prebid.js +1 -1
- package/src/storageManager.js +57 -44
- package/src/userSync.js +35 -18
- package/test/spec/activities/allowActivites_spec.js +138 -0
- package/test/spec/activities/objectGuard_spec.js +144 -0
- package/test/spec/activities/ortbGuard_spec.js +140 -0
- package/test/spec/activities/params_spec.js +25 -0
- package/test/spec/activities/redactor_spec.js +296 -0
- package/test/spec/activities/rules_spec.js +135 -0
- package/test/spec/modules/adgenerationBidAdapter_spec.js +52 -12
- package/test/spec/modules/adhashBidAdapter_spec.js +51 -1
- package/test/spec/modules/admanBidAdapter_spec.js +1 -2
- package/test/spec/modules/adnuntiusBidAdapter_spec.js +535 -264
- package/test/spec/modules/adqueryBidAdapter_spec.js +9 -0
- package/test/spec/modules/adrinoBidAdapter_spec.js +4 -0
- package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
- package/test/spec/modules/cleanioRtdProvider_spec.js +7 -8
- package/test/spec/modules/connectIdSystem_spec.js +291 -23
- package/test/spec/modules/criteoBidAdapter_spec.js +134 -2
- package/test/spec/modules/freewheel-sspBidAdapter_spec.js +5 -2
- package/test/spec/modules/gdprEnforcement_spec.js +127 -414
- package/test/spec/modules/growthCodeRtdProvider_spec.js +127 -0
- package/test/spec/modules/gumgumBidAdapter_spec.js +14 -0
- package/test/spec/modules/ixBidAdapter_spec.js +2 -1
- package/test/spec/modules/minutemediaBidAdapter_spec.js +69 -1
- package/test/spec/modules/oxxionAnalyticsAdapter_spec.js +324 -0
- package/test/spec/modules/pairIdSystem_spec.js +16 -3
- package/test/spec/modules/prebidServerBidAdapter_spec.js +3 -1
- package/test/spec/modules/pubmaticBidAdapter_spec.js +7 -0
- package/test/spec/modules/realTimeDataModule_spec.js +1 -1
- package/test/spec/modules/riseBidAdapter_spec.js +69 -1
- package/test/spec/modules/sharethroughBidAdapter_spec.js +1 -1
- package/test/spec/modules/smartadserverBidAdapter_spec.js +42 -0
- package/test/spec/modules/stvBidAdapter_spec.js +13 -1
- package/test/spec/modules/undertoneBidAdapter_spec.js +57 -1
- package/test/spec/modules/userId_spec.js +80 -21
- package/test/spec/modules/yahoosspBidAdapter_spec.js +103 -51
- package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +4 -0
- package/test/spec/native_spec.js +12 -12
- package/test/spec/unit/core/adapterManager_spec.js +181 -1
- package/test/spec/unit/core/storageManager_spec.js +76 -68
- package/test/spec/unit/pbjs_api_spec.js +15 -25
- package/test/spec/userSync_spec.js +45 -16
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {prefixLog} from '../utils.js';
|
|
2
|
+
import {ACTIVITY_PARAM_COMPONENT} from './params.js';
|
|
3
|
+
|
|
4
|
+
export function ruleRegistry(logger = prefixLog('Activity control:')) {
|
|
5
|
+
const registry = {};
|
|
6
|
+
|
|
7
|
+
function getRules(activity) {
|
|
8
|
+
return registry[activity] = registry[activity] || [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function runRule(activity, name, rule, params) {
|
|
12
|
+
let res;
|
|
13
|
+
try {
|
|
14
|
+
res = rule(params);
|
|
15
|
+
} catch (e) {
|
|
16
|
+
logger.logError(`Exception in rule ${name} for '${activity}'`, e);
|
|
17
|
+
res = {allow: false, reason: e};
|
|
18
|
+
}
|
|
19
|
+
return res && Object.assign({activity, name, component: params[ACTIVITY_PARAM_COMPONENT]}, res);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const dupes = {};
|
|
23
|
+
const DEDUPE_INTERVAL = 1000;
|
|
24
|
+
|
|
25
|
+
function logResult({activity, name, allow, reason, component}) {
|
|
26
|
+
const msg = `${name} ${allow ? 'allowed' : 'denied'} '${activity}' for '${component}'${reason ? ':' : ''}`;
|
|
27
|
+
const deduping = dupes.hasOwnProperty(msg);
|
|
28
|
+
if (deduping) {
|
|
29
|
+
clearTimeout(dupes[msg]);
|
|
30
|
+
}
|
|
31
|
+
dupes[msg] = setTimeout(() => delete dupes[msg], DEDUPE_INTERVAL);
|
|
32
|
+
if (!deduping) {
|
|
33
|
+
const parts = [msg];
|
|
34
|
+
reason && parts.push(reason);
|
|
35
|
+
(allow ? logger.logInfo : logger.logWarn).apply(logger, parts);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return [
|
|
40
|
+
/**
|
|
41
|
+
* Register an activity control rule.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} activity activity name - set is defined in `activities.js`
|
|
44
|
+
* @param {string} ruleName a name for this rule; used for logging.
|
|
45
|
+
* @param {function({}): {allow: boolean, reason?: string}} rule definition function. Takes in activity
|
|
46
|
+
* parameters as a single map; MAY return an object {allow, reason}, where allow is true/false,
|
|
47
|
+
* and reason is an optional message used for logging.
|
|
48
|
+
*
|
|
49
|
+
* {allow: true} will allow this activity AS LONG AS no other rules with same or higher priority return {allow: false};
|
|
50
|
+
* {allow: false} will deny this activity AS LONG AS no other rules with higher priority return {allow: true};
|
|
51
|
+
* returning null/undefined has no effect - the decision is left to other rules.
|
|
52
|
+
* If no rule returns an allow value, the default is to allow the activity.
|
|
53
|
+
*
|
|
54
|
+
* @param {number} priority rule priority; lower number means higher priority
|
|
55
|
+
* @returns {function(void): void} a function that unregisters the rule when called.
|
|
56
|
+
*/
|
|
57
|
+
function registerActivityControl(activity, ruleName, rule, priority = 10) {
|
|
58
|
+
const rules = getRules(activity);
|
|
59
|
+
const pos = rules.findIndex(([itemPriority]) => priority < itemPriority);
|
|
60
|
+
const entry = [priority, ruleName, rule];
|
|
61
|
+
rules.splice(pos < 0 ? rules.length : pos, 0, entry);
|
|
62
|
+
return function () {
|
|
63
|
+
const idx = rules.indexOf(entry);
|
|
64
|
+
if (idx >= 0) rules.splice(idx, 1);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Test whether an activity is allowed.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} activity activity name
|
|
71
|
+
* @param {{}} params activity parameters; should be generated through the `activityParams` utility.
|
|
72
|
+
* @return {boolean} true for allow, false for deny.
|
|
73
|
+
*/
|
|
74
|
+
function isActivityAllowed(activity, params) {
|
|
75
|
+
let lastPriority, foundAllow;
|
|
76
|
+
for (const [priority, name, rule] of getRules(activity)) {
|
|
77
|
+
if (lastPriority !== priority && foundAllow) break;
|
|
78
|
+
lastPriority = priority;
|
|
79
|
+
const ruleResult = runRule(activity, name, rule, params);
|
|
80
|
+
if (ruleResult) {
|
|
81
|
+
if (!ruleResult.allow) {
|
|
82
|
+
logResult(ruleResult);
|
|
83
|
+
return false;
|
|
84
|
+
} else {
|
|
85
|
+
foundAllow = ruleResult;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
foundAllow && logResult(foundAllow);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const [registerActivityControl, isActivityAllowed] = ruleRegistry();
|
package/src/adapterManager.js
CHANGED
|
@@ -31,18 +31,28 @@ import {hook} from './hook.js';
|
|
|
31
31
|
import {find, includes} from './polyfill.js';
|
|
32
32
|
import {adunitCounter} from './adUnits.js';
|
|
33
33
|
import {getRefererInfo} from './refererDetection.js';
|
|
34
|
-
import {
|
|
34
|
+
import {GDPR_GVLIDS, GdprConsentHandler, GppConsentHandler, UspConsentHandler} from './consentHandler.js';
|
|
35
35
|
import * as events from './events.js';
|
|
36
36
|
import CONSTANTS from './constants.json';
|
|
37
37
|
import {useMetrics} from './utils/perfMetrics.js';
|
|
38
38
|
import {auctionManager} from './auctionManager.js';
|
|
39
|
-
import {MODULE_TYPE_ANALYTICS, MODULE_TYPE_BIDDER} from './activities/modules.js';
|
|
39
|
+
import {MODULE_TYPE_ANALYTICS, MODULE_TYPE_BIDDER, MODULE_TYPE_PREBID} from './activities/modules.js';
|
|
40
|
+
import {isActivityAllowed} from './activities/rules.js';
|
|
41
|
+
import {ACTIVITY_FETCH_BIDS, ACTIVITY_REPORT_ANALYTICS} from './activities/activities.js';
|
|
42
|
+
import {ACTIVITY_PARAM_ANL_CONFIG, ACTIVITY_PARAM_S2S_NAME, activityParamsBuilder} from './activities/params.js';
|
|
43
|
+
import {redactor} from './activities/redactor.js';
|
|
40
44
|
|
|
45
|
+
const PBS_ADAPTER_NAME = 'pbsBidAdapter';
|
|
41
46
|
export const PARTITIONS = {
|
|
42
47
|
CLIENT: 'client',
|
|
43
48
|
SERVER: 'server'
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
export const dep = {
|
|
52
|
+
isAllowed: isActivityAllowed,
|
|
53
|
+
redact: redactor
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
let adapterManager = {};
|
|
47
57
|
|
|
48
58
|
let _bidderRegistry = adapterManager.bidderRegistry = {};
|
|
@@ -57,6 +67,8 @@ config.getConfig('s2sConfig', config => {
|
|
|
57
67
|
|
|
58
68
|
var _analyticsRegistry = {};
|
|
59
69
|
|
|
70
|
+
const activityParams = activityParamsBuilder((alias) => adapterManager.resolveAlias(alias));
|
|
71
|
+
|
|
60
72
|
/**
|
|
61
73
|
* @typedef {object} LabelDescriptor
|
|
62
74
|
* @property {boolean} labelAll describes whether or not this object expects all labels to match, or any label to match
|
|
@@ -139,7 +151,7 @@ function getAdUnitCopyForPrebidServer(adUnits, s2sConfig) {
|
|
|
139
151
|
|
|
140
152
|
adUnitsCopy.forEach((adUnit) => {
|
|
141
153
|
// filter out client side bids
|
|
142
|
-
const s2sBids = adUnit.bids.filter((b) => b.module ===
|
|
154
|
+
const s2sBids = adUnit.bids.filter((b) => b.module === PBS_ADAPTER_NAME && b.params?.configName === s2sConfig.configName);
|
|
143
155
|
if (s2sBids.length === 1) {
|
|
144
156
|
adUnit.s2sBid = s2sBids[0];
|
|
145
157
|
hasModuleBids = true;
|
|
@@ -237,6 +249,10 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a
|
|
|
237
249
|
if (FEATURES.NATIVE) {
|
|
238
250
|
decorateAdUnitsWithNativeParams(adUnits);
|
|
239
251
|
}
|
|
252
|
+
|
|
253
|
+
// filter out bidders that cannot participate in the auction
|
|
254
|
+
adUnits.forEach(au => au.bids = au.bids.filter((bid) => !bid.bidder || dep.isAllowed(ACTIVITY_FETCH_BIDS, activityParams(MODULE_TYPE_BIDDER, bid.bidder))))
|
|
255
|
+
|
|
240
256
|
adUnits = setupAdUnitMediaTypes(adUnits, labels);
|
|
241
257
|
|
|
242
258
|
let {[PARTITIONS.CLIENT]: clientBidders, [PARTITIONS.SERVER]: serverBidders} = partitionBidders(adUnits, _s2sConfigs);
|
|
@@ -252,14 +268,24 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a
|
|
|
252
268
|
const bidderOrtb2 = ortb2Fragments.bidder || {};
|
|
253
269
|
|
|
254
270
|
function addOrtb2(bidderRequest) {
|
|
255
|
-
const
|
|
271
|
+
const redact = dep.redact(activityParams(MODULE_TYPE_BIDDER, bidderRequest.bidderCode));
|
|
272
|
+
const fpd = Object.freeze(redact.ortb2(mergeDeep({}, ortb2, bidderOrtb2[bidderRequest.bidderCode])));
|
|
256
273
|
bidderRequest.ortb2 = fpd;
|
|
257
|
-
bidderRequest.bids.
|
|
274
|
+
bidderRequest.bids = bidderRequest.bids.map((bid) => {
|
|
275
|
+
bid.ortb2 = fpd;
|
|
276
|
+
return redact.bidRequest(bid);
|
|
277
|
+
})
|
|
258
278
|
return bidderRequest;
|
|
259
279
|
}
|
|
260
280
|
|
|
281
|
+
function isS2SAllowed(s2sConfig) {
|
|
282
|
+
return dep.isAllowed(ACTIVITY_FETCH_BIDS, activityParams(MODULE_TYPE_PREBID, PBS_ADAPTER_NAME, {
|
|
283
|
+
[ACTIVITY_PARAM_S2S_NAME]: s2sConfig.configName
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
286
|
+
|
|
261
287
|
_s2sConfigs.forEach(s2sConfig => {
|
|
262
|
-
if (s2sConfig && s2sConfig.enabled) {
|
|
288
|
+
if (s2sConfig && s2sConfig.enabled && isS2SAllowed(s2sConfig)) {
|
|
263
289
|
let {adUnits: adUnitsS2SCopy, hasModuleBids} = getAdUnitCopyForPrebidServer(adUnits, s2sConfig);
|
|
264
290
|
|
|
265
291
|
// uniquePbsTid is so we know which server to send which bids to during the callBids function
|
|
@@ -338,7 +364,6 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a
|
|
|
338
364
|
bidRequest['gppConsent'] = gppDataHandler.getConsentData();
|
|
339
365
|
}
|
|
340
366
|
});
|
|
341
|
-
|
|
342
367
|
return bidRequests;
|
|
343
368
|
}, 'makeBidRequests');
|
|
344
369
|
|
|
@@ -529,6 +554,16 @@ adapterManager.aliasBidAdapter = function (bidderCode, alias, options) {
|
|
|
529
554
|
}
|
|
530
555
|
};
|
|
531
556
|
|
|
557
|
+
adapterManager.resolveAlias = function (alias) {
|
|
558
|
+
let code = alias;
|
|
559
|
+
let visited;
|
|
560
|
+
while (_aliasRegistry[code] && (!visited || !visited.has(code))) {
|
|
561
|
+
code = _aliasRegistry[code];
|
|
562
|
+
(visited = visited || new Set()).add(code);
|
|
563
|
+
}
|
|
564
|
+
return code;
|
|
565
|
+
}
|
|
566
|
+
|
|
532
567
|
adapterManager.registerAnalyticsAdapter = function ({adapter, code, gvlid}) {
|
|
533
568
|
if (adapter && code) {
|
|
534
569
|
if (typeof adapter.enableAnalytics === 'function') {
|
|
@@ -552,7 +587,9 @@ adapterManager.enableAnalytics = function (config) {
|
|
|
552
587
|
_each(config, adapterConfig => {
|
|
553
588
|
const entry = _analyticsRegistry[adapterConfig.provider];
|
|
554
589
|
if (entry && entry.adapter) {
|
|
555
|
-
|
|
590
|
+
if (dep.isAllowed(ACTIVITY_REPORT_ANALYTICS, activityParams(MODULE_TYPE_ANALYTICS, adapterConfig.provider, {[ACTIVITY_PARAM_ANL_CONFIG]: adapterConfig}))) {
|
|
591
|
+
entry.adapter.enableAnalytics(adapterConfig);
|
|
592
|
+
}
|
|
556
593
|
} else {
|
|
557
594
|
logError(`Prebid Error: no analytics adapter found in registry for '${adapterConfig.provider}'.`);
|
|
558
595
|
}
|
package/src/adloader.js
CHANGED
package/src/fpd/rootDomain.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {memoize, timestamp} from '../utils.js';
|
|
2
2
|
import {getCoreStorageManager} from '../storageManager.js';
|
|
3
3
|
|
|
4
|
-
export const coreStorage = getCoreStorageManager();
|
|
4
|
+
export const coreStorage = getCoreStorageManager('fpdEnrichment');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Find the root domain by testing for the topmost domain that will allow setting cookies.
|
package/src/native.js
CHANGED
|
@@ -556,6 +556,21 @@ export function toOrtbNativeRequest(legacyNativeAssets) {
|
|
|
556
556
|
return ortb;
|
|
557
557
|
}
|
|
558
558
|
|
|
559
|
+
/**
|
|
560
|
+
* Greatest common divisor between two positive integers
|
|
561
|
+
* https://en.wikipedia.org/wiki/Euclidean_algorithm
|
|
562
|
+
*/
|
|
563
|
+
function gcd(a, b) {
|
|
564
|
+
while (a && b && a !== b) {
|
|
565
|
+
if (a > b) {
|
|
566
|
+
a = a - b;
|
|
567
|
+
} else {
|
|
568
|
+
b = b - a;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return a || b;
|
|
572
|
+
}
|
|
573
|
+
|
|
559
574
|
/**
|
|
560
575
|
* This function converts an OpenRTB native request object to Prebid proprietary
|
|
561
576
|
* format. The purpose of this function is to help adapters to handle the
|
|
@@ -584,12 +599,13 @@ export function fromOrtbNativeRequest(openRTBRequest) {
|
|
|
584
599
|
if (asset.img.w && asset.img.h) {
|
|
585
600
|
image.sizes = [asset.img.w, asset.img.h];
|
|
586
601
|
} else if (asset.img.wmin && asset.img.hmin) {
|
|
587
|
-
|
|
602
|
+
const scale = gcd(asset.img.wmin, asset.img.hmin)
|
|
603
|
+
image.aspect_ratios = [{
|
|
588
604
|
min_width: asset.img.wmin,
|
|
589
605
|
min_height: asset.img.hmin,
|
|
590
|
-
ratio_width: asset.img.wmin,
|
|
591
|
-
ratio_height: asset.img.hmin
|
|
592
|
-
}
|
|
606
|
+
ratio_width: asset.img.wmin / scale,
|
|
607
|
+
ratio_height: asset.img.hmin / scale
|
|
608
|
+
}]
|
|
593
609
|
}
|
|
594
610
|
|
|
595
611
|
if (asset.img.type === NATIVE_IMAGE_TYPES.MAIN) {
|
package/src/prebid.js
CHANGED
|
@@ -1004,7 +1004,7 @@ if (FEATURES.VIDEO) {
|
|
|
1004
1004
|
const bids = fetchReceivedBids(markBidRequest, 'Improper use of markWinningBidAsUsed. It needs an adUnitCode or an adId to function.');
|
|
1005
1005
|
|
|
1006
1006
|
if (bids.length > 0) {
|
|
1007
|
-
bids[0]
|
|
1007
|
+
auctionManager.addWinningBid(bids[0]);
|
|
1008
1008
|
}
|
|
1009
1009
|
}
|
|
1010
1010
|
}
|
package/src/storageManager.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import {checkCookieSupport, hasDeviceAccess, logError} from './utils.js';
|
|
2
|
+
import {bidderSettings} from './bidderSettings.js';
|
|
3
|
+
import {MODULE_TYPE_BIDDER, MODULE_TYPE_PREBID} from './activities/modules.js';
|
|
4
|
+
import {isActivityAllowed, registerActivityControl} from './activities/rules.js';
|
|
5
|
+
import {
|
|
6
|
+
ACTIVITY_PARAM_ADAPTER_CODE,
|
|
7
|
+
ACTIVITY_PARAM_COMPONENT_TYPE,
|
|
8
|
+
ACTIVITY_PARAM_STORAGE_TYPE
|
|
9
|
+
} from './activities/params.js';
|
|
10
|
+
|
|
11
|
+
import {ACTIVITY_ACCESS_DEVICE} from './activities/activities.js';
|
|
12
|
+
import {config} from './config.js';
|
|
13
|
+
import adapterManager from './adapterManager.js';
|
|
14
|
+
import {activityParams} from './activities/activityParams.js';
|
|
5
15
|
|
|
6
16
|
export const STORAGE_TYPE_LOCALSTORAGE = 'html5';
|
|
7
17
|
export const STORAGE_TYPE_COOKIES = 'cookie';
|
|
@@ -11,40 +21,19 @@ export let storageCallbacks = [];
|
|
|
11
21
|
/*
|
|
12
22
|
* Storage manager constructor. Consumers should prefer one of `getStorageManager` or `getCoreStorageManager`.
|
|
13
23
|
*/
|
|
14
|
-
export function newStorageManager({moduleName, moduleType} = {}, {
|
|
15
|
-
function isBidderAllowed(storageType) {
|
|
16
|
-
if (moduleType !== MODULE_TYPE_BIDDER) {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
const storageAllowed = bidderSettings.get(moduleName, 'storageAllowed');
|
|
20
|
-
if (!storageAllowed || storageAllowed === true) return !!storageAllowed;
|
|
21
|
-
if (Array.isArray(storageAllowed)) return storageAllowed.some((e) => e === storageType);
|
|
22
|
-
return storageAllowed === storageType;
|
|
23
|
-
}
|
|
24
|
-
|
|
24
|
+
export function newStorageManager({moduleName, moduleType} = {}, {isAllowed = isActivityAllowed} = {}) {
|
|
25
25
|
function isValid(cb, storageType) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} else {
|
|
31
|
-
let value;
|
|
32
|
-
let hookDetails = {
|
|
33
|
-
hasEnforcementHook: false
|
|
34
|
-
}
|
|
35
|
-
validateStorageEnforcement(moduleType, moduleName, hookDetails, function(result) {
|
|
36
|
-
if (result && result.hasEnforcementHook) {
|
|
37
|
-
value = cb(result);
|
|
38
|
-
} else {
|
|
39
|
-
let result = {
|
|
40
|
-
hasEnforcementHook: false,
|
|
41
|
-
valid: hasDeviceAccess()
|
|
42
|
-
}
|
|
43
|
-
value = cb(result);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
return value;
|
|
26
|
+
let mod = moduleName;
|
|
27
|
+
const curBidder = config.getCurrentBidder();
|
|
28
|
+
if (curBidder && moduleType === MODULE_TYPE_BIDDER && adapterManager.aliasRegistry[curBidder] === moduleName) {
|
|
29
|
+
mod = curBidder;
|
|
47
30
|
}
|
|
31
|
+
const result = {
|
|
32
|
+
valid: isAllowed(ACTIVITY_ACCESS_DEVICE, activityParams(moduleType, mod, {
|
|
33
|
+
[ACTIVITY_PARAM_STORAGE_TYPE]: storageType
|
|
34
|
+
}))
|
|
35
|
+
};
|
|
36
|
+
return cb(result);
|
|
48
37
|
}
|
|
49
38
|
|
|
50
39
|
function schedule(operation, storageType, done) {
|
|
@@ -228,13 +217,6 @@ export function newStorageManager({moduleName, moduleType} = {}, {bidderSettings
|
|
|
228
217
|
}
|
|
229
218
|
}
|
|
230
219
|
|
|
231
|
-
/**
|
|
232
|
-
* This hook validates the storage enforcement if gdprEnforcement module is included
|
|
233
|
-
*/
|
|
234
|
-
export const validateStorageEnforcement = hook('async', function(moduleType, moduleName, hookDetails, callback) {
|
|
235
|
-
callback(hookDetails);
|
|
236
|
-
}, 'validateStorageEnforcement');
|
|
237
|
-
|
|
238
220
|
/**
|
|
239
221
|
* Get a storage manager for a particular module.
|
|
240
222
|
*
|
|
@@ -262,9 +244,40 @@ export function getStorageManager({moduleType, moduleName, bidderCode} = {}) {
|
|
|
262
244
|
* @param {string} moduleName Module name
|
|
263
245
|
*/
|
|
264
246
|
export function getCoreStorageManager(moduleName) {
|
|
265
|
-
return newStorageManager({moduleName: moduleName, moduleType:
|
|
247
|
+
return newStorageManager({moduleName: moduleName, moduleType: MODULE_TYPE_PREBID});
|
|
266
248
|
}
|
|
267
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Block all access to storage when deviceAccess = false
|
|
252
|
+
*/
|
|
253
|
+
export function deviceAccessRule() {
|
|
254
|
+
if (!hasDeviceAccess()) {
|
|
255
|
+
return {allow: false}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
registerActivityControl(ACTIVITY_ACCESS_DEVICE, 'deviceAccess config', deviceAccessRule);
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* By default, deny bidders accessDevice unless they enable it through bidderSettings
|
|
262
|
+
*
|
|
263
|
+
* // TODO: for backwards compat, the check is done on the adapter - rather than bidder's code.
|
|
264
|
+
*/
|
|
265
|
+
export function storageAllowedRule(params, bs = bidderSettings) {
|
|
266
|
+
if (params[ACTIVITY_PARAM_COMPONENT_TYPE] !== MODULE_TYPE_BIDDER) return;
|
|
267
|
+
let allow = bs.get(params[ACTIVITY_PARAM_ADAPTER_CODE], 'storageAllowed');
|
|
268
|
+
if (!allow || allow === true) {
|
|
269
|
+
allow = !!allow
|
|
270
|
+
} else {
|
|
271
|
+
const storageType = params[ACTIVITY_PARAM_STORAGE_TYPE];
|
|
272
|
+
allow = Array.isArray(allow) ? allow.some((e) => e === storageType) : allow === storageType;
|
|
273
|
+
}
|
|
274
|
+
if (!allow) {
|
|
275
|
+
return {allow};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
registerActivityControl(ACTIVITY_ACCESS_DEVICE, 'bidderSettings.*.storageAllowed', storageAllowedRule);
|
|
280
|
+
|
|
268
281
|
export function resetData() {
|
|
269
282
|
storageCallbacks = [];
|
|
270
283
|
}
|
package/src/userSync.js
CHANGED
|
@@ -5,6 +5,15 @@ import {
|
|
|
5
5
|
import { config } from './config.js';
|
|
6
6
|
import {includes} from './polyfill.js';
|
|
7
7
|
import { getCoreStorageManager } from './storageManager.js';
|
|
8
|
+
import {isActivityAllowed, registerActivityControl} from './activities/rules.js';
|
|
9
|
+
import {ACTIVITY_SYNC_USER} from './activities/activities.js';
|
|
10
|
+
import {
|
|
11
|
+
ACTIVITY_PARAM_COMPONENT_NAME,
|
|
12
|
+
ACTIVITY_PARAM_COMPONENT_TYPE,
|
|
13
|
+
ACTIVITY_PARAM_SYNC_TYPE, ACTIVITY_PARAM_SYNC_URL
|
|
14
|
+
} from './activities/params.js';
|
|
15
|
+
import {MODULE_TYPE_BIDDER} from './activities/modules.js';
|
|
16
|
+
import {activityParams} from './activities/activityParams.js';
|
|
8
17
|
|
|
9
18
|
export const USERSYNC_DEFAULT_CONFIG = {
|
|
10
19
|
syncEnabled: true,
|
|
@@ -29,10 +38,10 @@ const storage = getCoreStorageManager('usersync');
|
|
|
29
38
|
/**
|
|
30
39
|
* Factory function which creates a new UserSyncPool.
|
|
31
40
|
*
|
|
32
|
-
* @param {
|
|
41
|
+
* @param {} deps Configuration options and dependencies which the
|
|
33
42
|
* UserSync object needs in order to behave properly.
|
|
34
43
|
*/
|
|
35
|
-
export function newUserSync(
|
|
44
|
+
export function newUserSync(deps) {
|
|
36
45
|
let publicApi = {};
|
|
37
46
|
// A queue of user syncs for each adapter
|
|
38
47
|
// Let getDefaultQueue() set the defaults
|
|
@@ -50,7 +59,7 @@ export function newUserSync(userSyncDependencies) {
|
|
|
50
59
|
};
|
|
51
60
|
|
|
52
61
|
// Use what is in config by default
|
|
53
|
-
let usConfig =
|
|
62
|
+
let usConfig = deps.config;
|
|
54
63
|
// Update if it's (re)set
|
|
55
64
|
config.getConfig('userSync', (conf) => {
|
|
56
65
|
// Added this logic for https://github.com/prebid/Prebid.js/issues/4864
|
|
@@ -70,6 +79,19 @@ export function newUserSync(userSyncDependencies) {
|
|
|
70
79
|
usConfig = Object.assign(usConfig, conf.userSync);
|
|
71
80
|
});
|
|
72
81
|
|
|
82
|
+
deps.regRule(ACTIVITY_SYNC_USER, 'userSync config', (params) => {
|
|
83
|
+
if (!usConfig.syncEnabled) {
|
|
84
|
+
return {allow: false, reason: 'syncs are disabled'}
|
|
85
|
+
}
|
|
86
|
+
if (params[ACTIVITY_PARAM_COMPONENT_TYPE] === MODULE_TYPE_BIDDER) {
|
|
87
|
+
const syncType = params[ACTIVITY_PARAM_SYNC_TYPE];
|
|
88
|
+
const bidder = params[ACTIVITY_PARAM_COMPONENT_NAME];
|
|
89
|
+
if (!publicApi.canBidderRegisterSync(syncType, bidder)) {
|
|
90
|
+
return {allow: false, reason: `${syncType} syncs are not enabled for ${bidder}`}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
73
95
|
/**
|
|
74
96
|
* @function getDefaultQueue
|
|
75
97
|
* @summary Returns the default empty queue
|
|
@@ -89,7 +111,7 @@ export function newUserSync(userSyncDependencies) {
|
|
|
89
111
|
* @private
|
|
90
112
|
*/
|
|
91
113
|
function fireSyncs() {
|
|
92
|
-
if (!usConfig.syncEnabled || !
|
|
114
|
+
if (!usConfig.syncEnabled || !deps.browserSupportsCookies) {
|
|
93
115
|
return;
|
|
94
116
|
}
|
|
95
117
|
|
|
@@ -199,14 +221,14 @@ export function newUserSync(userSyncDependencies) {
|
|
|
199
221
|
return logWarn(`Number of user syncs exceeded for "${bidder}"`);
|
|
200
222
|
}
|
|
201
223
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
224
|
+
if (deps.isAllowed(ACTIVITY_SYNC_USER, activityParams(MODULE_TYPE_BIDDER, bidder, {
|
|
225
|
+
[ACTIVITY_PARAM_SYNC_TYPE]: type,
|
|
226
|
+
[ACTIVITY_PARAM_SYNC_URL]: url
|
|
227
|
+
}))) {
|
|
228
|
+
// the bidder's pixel has passed all checks and is allowed to register
|
|
229
|
+
queue[type].push([bidder, url]);
|
|
230
|
+
numAdapterBids = incrementAdapterBids(numAdapterBids, bidder);
|
|
205
231
|
}
|
|
206
|
-
|
|
207
|
-
// the bidder's pixel has passed all checks and is allowed to register
|
|
208
|
-
queue[type].push([bidder, url]);
|
|
209
|
-
numAdapterBids = incrementAdapterBids(numAdapterBids, bidder);
|
|
210
232
|
};
|
|
211
233
|
|
|
212
234
|
/**
|
|
@@ -320,6 +342,8 @@ export function newUserSync(userSyncDependencies) {
|
|
|
320
342
|
|
|
321
343
|
export const userSync = newUserSync(Object.defineProperties({
|
|
322
344
|
config: config.getConfig('userSync'),
|
|
345
|
+
isAllowed: isActivityAllowed,
|
|
346
|
+
regRule: registerActivityControl,
|
|
323
347
|
}, {
|
|
324
348
|
browserSupportsCookies: {
|
|
325
349
|
get: function() {
|
|
@@ -329,13 +353,6 @@ export const userSync = newUserSync(Object.defineProperties({
|
|
|
329
353
|
}
|
|
330
354
|
}));
|
|
331
355
|
|
|
332
|
-
/**
|
|
333
|
-
* @typedef {Object} UserSyncDependencies
|
|
334
|
-
*
|
|
335
|
-
* @property {UserSyncConfig} config
|
|
336
|
-
* @property {boolean} browserSupportsCookies True if the current browser supports cookies, and false otherwise.
|
|
337
|
-
*/
|
|
338
|
-
|
|
339
356
|
/**
|
|
340
357
|
* @typedef {Object} UserSyncConfig
|
|
341
358
|
*
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {config} from 'src/config.js';
|
|
2
|
+
import {ruleRegistry} from '../../../src/activities/rules.js';
|
|
3
|
+
import {updateRulesFromConfig} from '../../../modules/allowActivities.js';
|
|
4
|
+
import {activityParams} from '../../../src/activities/activityParams.js';
|
|
5
|
+
|
|
6
|
+
describe('allowActivities config', () => {
|
|
7
|
+
const MODULE_TYPE = 'test'
|
|
8
|
+
const MODULE_NAME = 'testMod';
|
|
9
|
+
const ACTIVITY = 'testActivity';
|
|
10
|
+
|
|
11
|
+
let isAllowed, params;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
let registerRule;
|
|
15
|
+
[registerRule, isAllowed] = ruleRegistry();
|
|
16
|
+
updateRulesFromConfig(registerRule);
|
|
17
|
+
params = activityParams(MODULE_TYPE, MODULE_NAME)
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
config.resetConfig();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function setupActivityConfig(cfg) {
|
|
25
|
+
config.setConfig({
|
|
26
|
+
allowActivities: {
|
|
27
|
+
[ACTIVITY]: cfg
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('default = false', () => {
|
|
33
|
+
it('should deny activites with no other rules', () => {
|
|
34
|
+
setupActivityConfig({
|
|
35
|
+
default: false
|
|
36
|
+
})
|
|
37
|
+
expect(isAllowed(ACTIVITY, {})).to.be.false;
|
|
38
|
+
});
|
|
39
|
+
it('should not deny activities that are explicitly allowed', () => {
|
|
40
|
+
setupActivityConfig({
|
|
41
|
+
default: false,
|
|
42
|
+
rules: [
|
|
43
|
+
{
|
|
44
|
+
condition({componentName}) {
|
|
45
|
+
return componentName === MODULE_NAME
|
|
46
|
+
},
|
|
47
|
+
allow: true
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
})
|
|
51
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
52
|
+
});
|
|
53
|
+
it('should be removable by a config update', () => {
|
|
54
|
+
setupActivityConfig({
|
|
55
|
+
default: false
|
|
56
|
+
});
|
|
57
|
+
setupActivityConfig({});
|
|
58
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('rules', () => {
|
|
63
|
+
it('are tested for their condition', () => {
|
|
64
|
+
setupActivityConfig({
|
|
65
|
+
rules: [{
|
|
66
|
+
condition({flag}) { return flag },
|
|
67
|
+
allow: false
|
|
68
|
+
}]
|
|
69
|
+
});
|
|
70
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
71
|
+
params.flag = true;
|
|
72
|
+
expect(isAllowed(ACTIVITY, params)).to.be.false;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('always apply if they have no condition', () => {
|
|
76
|
+
setupActivityConfig({
|
|
77
|
+
rules: [{allow: false}]
|
|
78
|
+
});
|
|
79
|
+
expect(isAllowed(ACTIVITY, params)).to.be.false;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('do not choke when the condition throws', () => {
|
|
83
|
+
setupActivityConfig({
|
|
84
|
+
rules: [{
|
|
85
|
+
condition() {
|
|
86
|
+
throw new Error()
|
|
87
|
+
},
|
|
88
|
+
allow: true
|
|
89
|
+
}]
|
|
90
|
+
});
|
|
91
|
+
expect(isAllowed(ACTIVITY, params)).to.be.false;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('does not pass private (underscored) parameters to condition', () => {
|
|
95
|
+
setupActivityConfig({
|
|
96
|
+
rules: [{
|
|
97
|
+
condition({_priv}) { return _priv },
|
|
98
|
+
allow: false
|
|
99
|
+
}]
|
|
100
|
+
});
|
|
101
|
+
params._priv = true;
|
|
102
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('are evaluated in order of priority', () => {
|
|
106
|
+
setupActivityConfig({
|
|
107
|
+
rules: [{
|
|
108
|
+
priority: 1000,
|
|
109
|
+
allow: false
|
|
110
|
+
}, {
|
|
111
|
+
priority: 100,
|
|
112
|
+
allow: true
|
|
113
|
+
}]
|
|
114
|
+
});
|
|
115
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('can be set with priority 0', () => {
|
|
119
|
+
setupActivityConfig({
|
|
120
|
+
rules: [{
|
|
121
|
+
allow: false
|
|
122
|
+
}, {
|
|
123
|
+
priority: 0,
|
|
124
|
+
allow: true
|
|
125
|
+
}]
|
|
126
|
+
});
|
|
127
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('can be reset with a config update', () => {
|
|
131
|
+
setupActivityConfig({
|
|
132
|
+
allow: false
|
|
133
|
+
});
|
|
134
|
+
config.setConfig({allowActivities: {}});
|
|
135
|
+
expect(isAllowed(ACTIVITY, params)).to.be.true;
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|