• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

prebid / Prebid.js / 19176070562

07 Nov 2025 05:26PM UTC coverage: 96.231% (+0.003%) from 96.228%
19176070562

push

github

web-flow
Adagio Bid Adapter: enable gzip compression (#14110)

* AdagioBidAdapter: add endpoint "orgid" query param

* AdagioBidAdapter: enable gzip compression

52862 of 64751 branches covered (81.64%)

9 of 9 new or added lines in 1 file covered. (100.0%)

11 existing lines in 7 files now uncovered.

202066 of 209980 relevant lines covered (96.23%)

124.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.85
/libraries/objectGuard/objectGuard.js
1
import {isData, sessionedApplies} from '../../src/activities/redactor.js';
2
import {deepEqual, logWarn} from '../../src/utils.js';
3

4
/**
5
 * @typedef {import('../src/activities/redactor.js').TransformationRuleDef} TransformationRuleDef
6
 * @typedef {import('../src/adapters/bidderFactory.js').TransformationRule} TransformationRule
7
 * @typedef {Object} ObjectGuard
8
 * @property {*} obj a view on the guarded object
9
 * @property {function(): void} verify a function that checks for and rolls back disallowed changes to the guarded object
10
 */
11

12
/**
13
 * Create a factory function for object guards using the given rules.
14
 *
15
 * An object guard is a view on the guarded object that applies "redact" rules (the same rules used in activites/redactor.js),
16
 * and prevents writes (including deltes) that violate "write protect" rules.
17
 *
18
 * This is meant to provide sandboxed version of a privacy-sensitive object, where reads
19
 * are filtered through redaction rules and writes are checked against write protect rules.
20
 *
21
 */
22
export function objectGuard(rules) {
23
  const root = {};
80✔
24

25
  // rules are associated with specific portions of the object, e.g. "user.eids"
26
  // build a tree representation of them, where the root is the object itself,
27
  // and each node's children are properties of the corresponding (nested) object.
28

29
  rules.forEach(rule => {
80✔
30
    rule.paths.forEach(path => {
446✔
31
      let node = root;
1,749✔
32
      path.split('.').forEach(el => {
1,749✔
33
        node.children = node.children ?? {};
4,063✔
34
        node.children[el] = node.children[el] ?? { parent: node, path: node.path ? `${node.path}.${el}` : el };
4,063✔
35
        node = node.children[el];
4,063✔
36
        node.wpRules = node.wpRules ?? [];
4,063✔
37
        node.redactRules = node.redactRules ?? [];
4,063✔
38
      });
39
      (rule.wp ? node.wpRules : node.redactRules).push(rule);
1,749✔
40
      if (rule.wp) {
1,749✔
41
        // mark the whole path as write protected, so that write operations
42
        // on parents do not need to walk down the tree
43
        let parent = node;
692✔
44
        while (parent && !parent.hasWP) {
692✔
45
          parent.hasWP = true;
1,004✔
46
          parent = parent.parent;
1,004✔
47
        }
48
      }
49
    });
50
  });
51

52
  function getRedactRule(node) {
53
    if (node.redactRule == null) {
12✔
54
      node.redactRule = node.redactRules.length === 0 ? false : {
12✔
55
        check: (applies) => node.redactRules.some(applies),
8✔
56
        get(val) {
57
          for (const rule of node.redactRules) {
7✔
58
            val = rule.get(val);
8✔
59
            if (!isData(val)) break;
8!
60
          }
61
          return val;
7✔
62
        }
63
      }
64
    }
65
    return node.redactRule;
12✔
66
  }
67

68
  function getWPRule(node) {
69
    if (node.wpRule == null) {
131✔
70
      node.wpRule = node.wpRules.length === 0 ? false : {
75✔
71
        check: (applies) => node.wpRules.some(applies),
124✔
72
      }
73
    }
74
    return node.wpRule;
131✔
75
  }
76

77
  /**
78
   * clean up `newValue` so that it doesn't violate any write protect rules
79
   * when set onto the property represented by 'node'.
80
   *
81
   * This is done substituting (portions of) `curValue` when some rule is violated.
82
   */
83
  function cleanup(node, curValue, newValue, applies) {
84
    if (
74✔
85
      !node.hasWP ||
231✔
86
      (!isData(curValue) && !isData(newValue)) ||
87
      deepEqual(curValue, newValue)
88
    ) {
89
      return newValue;
59✔
90
    }
91
    const rule = getWPRule(node);
15✔
92
    if (rule && rule.check(applies)) {
15✔
93
      return curValue;
9✔
94
    }
95
    if (node.children) {
6✔
96
      for (const [prop, child] of Object.entries(node.children)) {
6✔
97
        const propValue = cleanup(child, curValue?.[prop], newValue?.[prop], applies);
8✔
98
        if (newValue != null && typeof newValue === 'object') {
8✔
99
          if (!isData(propValue) && !curValue?.hasOwnProperty(prop)) {
7✔
100
            delete newValue[prop];
4✔
101
          } else {
102
            newValue[prop] = propValue;
3✔
103
          }
104
        } else {
105
          logWarn(`Invalid value set for '${node.path}', expected an object`, newValue);
1✔
106
          return curValue;
1✔
107
        }
108
      }
109
    }
110
    return newValue;
5✔
111
  }
112

113
  function isDeleteAllowed(node, curValue, applies) {
114
    if (!node.hasWP || !isData(curValue)) {
5✔
115
      return true;
1✔
116
    }
117
    const rule = getWPRule(node);
4✔
118
    if (rule && rule.check(applies)) {
4✔
119
      return false;
3✔
120
    }
121
    if (node.children) {
1✔
122
      for (const [prop, child] of Object.entries(node.children)) {
1✔
123
        if (!isDeleteAllowed(child, curValue?.[prop], applies)) {
2!
124
          return false;
1✔
125
        }
126
      }
127
    }
UNCOV
128
    return true;
×
129
  }
130

131
  function mkGuard(obj, tree, final, applies) {
132
    return new Proxy(obj, {
543✔
133
      get(target, prop, receiver) {
134
        const val = Reflect.get(target, prop, receiver);
1,084✔
135
        if (final && val != null && typeof val === 'object') {
1,084✔
136
          // a parent property has write protect rules, keep guarding
137
          return mkGuard(val, tree, final, applies)
159✔
138
        } else if (tree.children?.hasOwnProperty(prop)) {
925✔
139
          const {children, hasWP} = tree.children[prop];
314✔
140
          if ((children || hasWP) && val != null && typeof val === 'object') {
314✔
141
            // some nested properties have rules, return a guard for the branch
142
            return mkGuard(val, tree.children?.[prop] || tree, final || children == null, applies);
300!
143
          } else if (isData(val)) {
14✔
144
            // if this property has redact rules, apply them
145
            const rule = getRedactRule(tree.children[prop]);
12✔
146
            if (rule && rule.check(applies)) {
12✔
147
              return rule.get(val);
7✔
148
            }
149
          }
150
        }
151
        return val;
618✔
152
      },
153
      set(target, prop, newValue, receiver) {
154
        if (final) {
176✔
155
          // a parent property has rules, apply them
156
          const rule = getWPRule(tree);
107✔
157
          if (rule && rule.check(applies)) {
107✔
158
            return true;
56✔
159
          }
160
        }
161
        if (tree.children?.hasOwnProperty(prop)) {
120✔
162
          // apply all (possibly nested) write protect rules
163
          const curValue = Reflect.get(target, prop, receiver);
66✔
164
          newValue = cleanup(tree.children[prop], curValue, newValue, applies);
66✔
165
          if (!isData(newValue) && !target.hasOwnProperty(prop)) {
66✔
166
            return true;
3✔
167
          }
168
        }
169
        return Reflect.set(target, prop, newValue, receiver);
117✔
170
      },
171
      deleteProperty(target, prop) {
172
        if (final) {
8✔
173
          // a parent property has rules, apply them
174
          const rule = getWPRule(tree);
5✔
175
          if (rule && rule.check(applies)) {
5✔
176
            return true;
4✔
177
          }
178
        }
179
        if (tree.children?.hasOwnProperty(prop) && !isDeleteAllowed(tree.children[prop], target[prop], applies)) {
4✔
180
          // some nested properties should not be deleted
181
          return true;
3✔
182
        }
183
        return Reflect.deleteProperty(target, prop);
1✔
184
      }
185
    });
186
  }
187

188
  return function guard(obj, ...args) {
170✔
189
    const session = {};
84✔
190
    return mkGuard(obj, root, false, sessionedApplies(session, ...args))
84✔
191
  };
192
}
193

194
/**
195
 * @param {TransformationRuleDef} ruleDef
196
 * @return {TransformationRule}
197
 */
198
export function writeProtectRule(ruleDef) {
199
  return Object.assign({
124✔
200
    wp: true,
201
  }, ruleDef)
202
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc