@prosopo/user-access-policy 3.12.8 → 3.12.10
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/.turbo/turbo-build$colon$cjs.log +45 -41
- package/.turbo/turbo-build$colon$tsc.log +14 -14
- package/.turbo/turbo-build.log +46 -42
- package/CHANGELOG.md +24 -0
- package/dist/.export.js +7 -21
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/api/.export.js +2 -9
- package/dist/api/accessRulesApiClient.js +1 -1
- package/dist/api/delete/.export.js +2 -1
- package/dist/api/delete/deleteAllRules.js +22 -24
- package/dist/api/delete/deleteRuleGroups.js +39 -51
- package/dist/api/delete/deleteRules.js +37 -41
- package/dist/api/read/.export.js +2 -1
- package/dist/api/read/fetchRules.js +34 -42
- package/dist/api/read/findRuleIds.js +35 -48
- package/dist/api/read/getMissingIds.js +36 -40
- package/dist/api/ruleApiRoutes.js +62 -120
- package/dist/api/rulesApiClient.js +51 -87
- package/dist/api/write/.export.js +2 -1
- package/dist/api/write/insertRules.js +84 -102
- package/dist/api/write/rehashRules.js +48 -56
- package/dist/cjs/.export.cjs +21 -23
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cjs/api/.export.cjs +6 -10
- package/dist/cjs/api/accessRulesApiClient.cjs +0 -0
- package/dist/cjs/api/delete/.export.cjs +0 -1
- package/dist/cjs/api/delete/deleteAllRules.cjs +22 -24
- package/dist/cjs/api/delete/deleteRuleGroups.cjs +39 -51
- package/dist/cjs/api/delete/deleteRules.cjs +41 -42
- package/dist/cjs/api/read/.export.cjs +0 -1
- package/dist/cjs/api/read/fetchRules.cjs +34 -41
- package/dist/cjs/api/read/findRuleIds.cjs +37 -48
- package/dist/cjs/api/read/getMissingIds.cjs +36 -39
- package/dist/cjs/api/ruleApiRoutes.cjs +69 -125
- package/dist/cjs/api/rulesApiClient.cjs +54 -90
- package/dist/cjs/api/write/.export.cjs +0 -1
- package/dist/cjs/api/write/insertRules.cjs +85 -103
- package/dist/cjs/api/write/rehashRules.cjs +48 -56
- package/dist/cjs/classifyOs.cjs +46 -26
- package/dist/cjs/mongoose/.export.cjs +2 -3
- package/dist/cjs/mongoose/mongooseRuleSchema.cjs +97 -36
- package/dist/cjs/redis/.export.cjs +4 -5
- package/dist/cjs/redis/reader/redisAggregate.cjs +59 -84
- package/dist/cjs/redis/reader/redisRulesQuery.cjs +74 -116
- package/dist/cjs/redis/reader/redisRulesReader.cjs +322 -503
- package/dist/cjs/redis/reader/redisRulesSplitQuery.cjs +94 -72
- package/dist/cjs/redis/redisClient.cjs +53 -58
- package/dist/cjs/redis/redisRuleIndex.cjs +93 -49
- package/dist/cjs/redis/redisRulesStorage.cjs +21 -30
- package/dist/cjs/redis/redisRulesWriter.cjs +86 -112
- package/dist/cjs/rule.cjs +8 -7
- package/dist/cjs/ruleInput/.export.cjs +7 -8
- package/dist/cjs/ruleInput/policyInput.cjs +35 -58
- package/dist/cjs/ruleInput/ruleInput.cjs +37 -42
- package/dist/cjs/ruleInput/userScopeInput.cjs +47 -55
- package/dist/cjs/ruleRecord.cjs +15 -22
- package/dist/cjs/rulesStorage.cjs +7 -6
- package/dist/cjs/transformRule.cjs +36 -70
- package/dist/classifyOs.js +48 -29
- package/dist/mongoose/.export.js +2 -3
- package/dist/mongoose/mongooseRuleSchema.js +99 -38
- package/dist/redis/.export.js +3 -5
- package/dist/redis/reader/redisAggregate.js +60 -86
- package/dist/redis/reader/redisRulesQuery.js +75 -118
- package/dist/redis/reader/redisRulesReader.js +312 -487
- package/dist/redis/reader/redisRulesSplitQuery.js +96 -75
- package/dist/redis/redisClient.js +54 -62
- package/dist/redis/redisRuleIndex.js +93 -58
- package/dist/redis/redisRulesStorage.js +21 -30
- package/dist/redis/redisRulesWriter.js +82 -113
- package/dist/rule.js +10 -10
- package/dist/ruleInput/.export.js +3 -7
- package/dist/ruleInput/policyInput.js +35 -61
- package/dist/ruleInput/ruleInput.js +36 -44
- package/dist/ruleInput/userScopeInput.js +44 -55
- package/dist/ruleRecord.js +17 -27
- package/dist/rulesStorage.js +9 -8
- package/dist/tests/redis/redisRulesStorage.integration.test.js +1 -3
- package/dist/tests/redis/redisRulesStorage.integration.test.js.map +1 -1
- package/dist/transformRule.js +34 -73
- package/entries.ts +25 -6
- package/package.json +13 -12
- package/src/tests/redis/redisRulesStorage.integration.test.ts +191 -195
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,511 +1,330 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const SPLIT_MAX_CANDIDATES_PER_SUB = 500;
|
|
32
|
-
const SPECIFICITY_EXPR = [
|
|
33
|
-
"exists(@clientId)",
|
|
34
|
-
"exists(@userId)",
|
|
35
|
-
"exists(@ja4Hash)",
|
|
36
|
-
"exists(@headersHash)",
|
|
37
|
-
"exists(@userAgentHash)",
|
|
38
|
-
"exists(@headHash)",
|
|
39
|
-
"exists(@coords)",
|
|
40
|
-
"exists(@countryCode)",
|
|
41
|
-
"exists(@asn)",
|
|
42
|
-
"exists(@os)",
|
|
43
|
-
"exists(@numericIp)",
|
|
44
|
-
"exists(@numericIpMaskMin)"
|
|
2
|
+
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_rule = require("../../rule.cjs");
|
|
4
|
+
const require_ruleInput_ruleInput = require("../../ruleInput/ruleInput.cjs");
|
|
5
|
+
const require_redis_reader_redisRulesQuery = require("./redisRulesQuery.cjs");
|
|
6
|
+
const require_redis_reader_redisRulesSplitQuery = require("./redisRulesSplitQuery.cjs");
|
|
7
|
+
const require_redis_redisClient = require("../redisClient.cjs");
|
|
8
|
+
const require_redis_redisRuleIndex = require("../redisRuleIndex.cjs");
|
|
9
|
+
const require_redis_reader_redisAggregate = require("./redisAggregate.cjs");
|
|
10
|
+
let _prosopo_common = require("@prosopo/common");
|
|
11
|
+
let node_util = require("node:util");
|
|
12
|
+
node_util = require_runtime.__toESM(node_util, 1);
|
|
13
|
+
//#region src/redis/reader/redisRulesReader.ts
|
|
14
|
+
var SERVER_SIDE_RANK_TOP_N = 20;
|
|
15
|
+
var GREEDY_MAX_CANDIDATES = require_redis_redisClient.REDIS_BATCH_SIZE * 10;
|
|
16
|
+
var SPLIT_MAX_CANDIDATES_PER_SUB = 500;
|
|
17
|
+
var SPECIFICITY_EXPR = [
|
|
18
|
+
"exists(@clientId)",
|
|
19
|
+
"exists(@userId)",
|
|
20
|
+
"exists(@ja4Hash)",
|
|
21
|
+
"exists(@headersHash)",
|
|
22
|
+
"exists(@userAgentHash)",
|
|
23
|
+
"exists(@headHash)",
|
|
24
|
+
"exists(@coords)",
|
|
25
|
+
"exists(@countryCode)",
|
|
26
|
+
"exists(@asn)",
|
|
27
|
+
"exists(@os)",
|
|
28
|
+
"exists(@numericIp)",
|
|
29
|
+
"exists(@numericIpMaskMin)"
|
|
45
30
|
].join(" + ");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
31
|
+
var SEVERITY_EXPR = `(@type == "${require_rule.AccessPolicyType.Block}")`;
|
|
32
|
+
var RANK_EXPR = "(@_spec * 2) + @_sev";
|
|
33
|
+
var RULE_LOAD_FIELDS = [
|
|
34
|
+
"@__key",
|
|
35
|
+
"@type",
|
|
36
|
+
"@captchaType",
|
|
37
|
+
"@description",
|
|
38
|
+
"@solvedImagesCount",
|
|
39
|
+
"@imageThreshold",
|
|
40
|
+
"@powDifficulty",
|
|
41
|
+
"@unsolvedImagesCount",
|
|
42
|
+
"@frictionlessScore",
|
|
43
|
+
"@deferToVerify",
|
|
44
|
+
"@clientId",
|
|
45
|
+
"@groupId",
|
|
46
|
+
"@userId",
|
|
47
|
+
"@ja4Hash",
|
|
48
|
+
"@headersHash",
|
|
49
|
+
"@userAgentHash",
|
|
50
|
+
"@headHash",
|
|
51
|
+
"@coords",
|
|
52
|
+
"@countryCode",
|
|
53
|
+
"@asn",
|
|
54
|
+
"@os",
|
|
55
|
+
"@numericIp",
|
|
56
|
+
"@numericIpMaskMin",
|
|
57
|
+
"@numericIpMaskMax"
|
|
73
58
|
];
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
59
|
+
var readerSpecificity = (rule) => {
|
|
60
|
+
let score = 0;
|
|
61
|
+
if (rule.clientId !== void 0) score++;
|
|
62
|
+
if (rule.userId !== void 0) score++;
|
|
63
|
+
if (rule.ja4Hash !== void 0) score++;
|
|
64
|
+
if (rule.headersHash !== void 0) score++;
|
|
65
|
+
if (rule.userAgentHash !== void 0) score++;
|
|
66
|
+
if (rule.headHash !== void 0) score++;
|
|
67
|
+
if (rule.coords !== void 0) score++;
|
|
68
|
+
if (rule.countryCode !== void 0) score++;
|
|
69
|
+
if (rule.asn !== void 0) score++;
|
|
70
|
+
if (rule.os !== void 0) score++;
|
|
71
|
+
if (rule.numericIp !== void 0) score++;
|
|
72
|
+
if (rule.numericIpMaskMin !== void 0) score++;
|
|
73
|
+
return score;
|
|
89
74
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return bBlock - aBlock;
|
|
75
|
+
var sortByReaderRank = (rules) => [...rules].sort((a, b) => {
|
|
76
|
+
const specDelta = readerSpecificity(b) - readerSpecificity(a);
|
|
77
|
+
if (specDelta !== 0) return specDelta;
|
|
78
|
+
const aBlock = a.type === require_rule.AccessPolicyType.Block ? 1 : 0;
|
|
79
|
+
return (b.type === require_rule.AccessPolicyType.Block ? 1 : 0) - aBlock;
|
|
96
80
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
query,
|
|
345
|
-
this.logger,
|
|
346
|
-
void 0,
|
|
347
|
-
GREEDY_MAX_CANDIDATES
|
|
348
|
-
);
|
|
349
|
-
if (ruleKeys.length === 0) {
|
|
350
|
-
return [];
|
|
351
|
-
}
|
|
352
|
-
this.logger.debug(() => ({
|
|
353
|
-
msg: "Executed greedy search query",
|
|
354
|
-
data: {
|
|
355
|
-
inspect: util__namespace.inspect(
|
|
356
|
-
{
|
|
357
|
-
filter,
|
|
358
|
-
foundCount: ruleKeys.length,
|
|
359
|
-
query
|
|
360
|
-
},
|
|
361
|
-
{ depth: null }
|
|
362
|
-
)
|
|
363
|
-
}
|
|
364
|
-
}));
|
|
365
|
-
const { records } = await redisClient.fetchRedisHashRecords(
|
|
366
|
-
this.client,
|
|
367
|
-
ruleKeys,
|
|
368
|
-
this.logger
|
|
369
|
-
);
|
|
370
|
-
const nonEmptyRecords = records.filter(
|
|
371
|
-
(record) => Object.keys(record).length > 0
|
|
372
|
-
);
|
|
373
|
-
return redisClient.parseRedisRecords(nonEmptyRecords, ruleInput.accessRuleInput, this.logger);
|
|
374
|
-
} catch (e) {
|
|
375
|
-
this.logger.error(() => ({
|
|
376
|
-
err: e,
|
|
377
|
-
data: {
|
|
378
|
-
inspect: util__namespace.inspect({ query, filter }, { depth: null })
|
|
379
|
-
},
|
|
380
|
-
msg: "failed to execute greedy search query"
|
|
381
|
-
}));
|
|
382
|
-
return [];
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
async findRuleIds(filter, matchingFieldsOnly = false) {
|
|
386
|
-
const query = redisRulesQuery.getRulesRedisQuery(filter, matchingFieldsOnly);
|
|
387
|
-
let ruleIds = [];
|
|
388
|
-
try {
|
|
389
|
-
const ruleKeys = await redisAggregate.aggregateRedisKeys(
|
|
390
|
-
this.client,
|
|
391
|
-
query,
|
|
392
|
-
this.logger
|
|
393
|
-
);
|
|
394
|
-
ruleIds = ruleKeys.map(
|
|
395
|
-
(ruleKey) => ruleKey.slice(redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX.length)
|
|
396
|
-
);
|
|
397
|
-
} catch (e) {
|
|
398
|
-
this.logger.error(() => ({
|
|
399
|
-
err: e,
|
|
400
|
-
data: {
|
|
401
|
-
inspect: util__namespace.inspect(
|
|
402
|
-
{
|
|
403
|
-
query,
|
|
404
|
-
filter
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
depth: null
|
|
408
|
-
}
|
|
409
|
-
)
|
|
410
|
-
},
|
|
411
|
-
msg: "Failed to execute search query for rule IDs"
|
|
412
|
-
}));
|
|
413
|
-
return [];
|
|
414
|
-
}
|
|
415
|
-
this.logger.debug(() => ({
|
|
416
|
-
msg: "Executed search query for rule IDs",
|
|
417
|
-
data: {
|
|
418
|
-
query,
|
|
419
|
-
foundCount: ruleIds.length,
|
|
420
|
-
foundIds: ruleIds
|
|
421
|
-
}
|
|
422
|
-
}));
|
|
423
|
-
return ruleIds;
|
|
424
|
-
}
|
|
425
|
-
async fetchAllRuleIds(batchHandler) {
|
|
426
|
-
const keysBatchHandler = async (keys) => {
|
|
427
|
-
const ids = keys.map(
|
|
428
|
-
(ruleKey) => ruleKey.slice(redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX.length)
|
|
429
|
-
);
|
|
430
|
-
await batchHandler(ids);
|
|
431
|
-
};
|
|
432
|
-
await redisAggregate.aggregateRedisKeys(this.client, "*", this.logger, keysBatchHandler);
|
|
433
|
-
}
|
|
434
|
-
async fetchRuleEntries(keys) {
|
|
435
|
-
const { records, expirations } = await redisClient.fetchRedisHashRecords(
|
|
436
|
-
this.client,
|
|
437
|
-
keys,
|
|
438
|
-
this.logger
|
|
439
|
-
);
|
|
440
|
-
const entries = [];
|
|
441
|
-
for (const [index, ruleData] of records.entries()) {
|
|
442
|
-
const isRulePresent = Object.keys(ruleData).length > 0;
|
|
443
|
-
if (isRulePresent) {
|
|
444
|
-
const rule2 = redisClient.parseRedisRecords(
|
|
445
|
-
[ruleData],
|
|
446
|
-
ruleInput.accessRuleInput,
|
|
447
|
-
this.logger
|
|
448
|
-
)[0];
|
|
449
|
-
if (rule2) {
|
|
450
|
-
entries.push({
|
|
451
|
-
rule: rule2,
|
|
452
|
-
expiresUnixTimestamp: expirations[index]
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return entries;
|
|
458
|
-
}
|
|
459
|
-
getRuleKeys(ruleIds) {
|
|
460
|
-
return ruleIds.map((id) => `${redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX}${id}`);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
class DummyRedisRulesReader {
|
|
464
|
-
constructor(logger) {
|
|
465
|
-
this.logger = logger;
|
|
466
|
-
}
|
|
467
|
-
async getMissingRuleIds(ruleIds) {
|
|
468
|
-
this.logger.info(() => ({
|
|
469
|
-
msg: "Dummy getMissingRuleIds() has no effect (redis is not ready)",
|
|
470
|
-
data: {
|
|
471
|
-
ruleIds
|
|
472
|
-
}
|
|
473
|
-
}));
|
|
474
|
-
return [];
|
|
475
|
-
}
|
|
476
|
-
async fetchRules(ruleIds) {
|
|
477
|
-
this.logger.info(() => ({
|
|
478
|
-
msg: "Dummy fetchRule() has no effect (redis is not ready)",
|
|
479
|
-
data: {
|
|
480
|
-
ruleIds
|
|
481
|
-
}
|
|
482
|
-
}));
|
|
483
|
-
return [];
|
|
484
|
-
}
|
|
485
|
-
async findRules(filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) {
|
|
486
|
-
this.logger.info(() => ({
|
|
487
|
-
msg: "Dummy findRules() has no effect (redis is not ready)",
|
|
488
|
-
data: {
|
|
489
|
-
filter
|
|
490
|
-
}
|
|
491
|
-
}));
|
|
492
|
-
return [];
|
|
493
|
-
}
|
|
494
|
-
async findRuleIds(filter, matchingFieldsOnly = false) {
|
|
495
|
-
this.logger.info(() => ({
|
|
496
|
-
msg: "Dummy findRuleIds() has no effect (redis is not ready)",
|
|
497
|
-
data: {
|
|
498
|
-
filter
|
|
499
|
-
}
|
|
500
|
-
}));
|
|
501
|
-
return [];
|
|
502
|
-
}
|
|
503
|
-
async fetchAllRuleIds(batchHandler) {
|
|
504
|
-
this.logger.info(() => ({
|
|
505
|
-
msg: "Dummy fetchAllRuleIds() has no effect (redis is not ready)"
|
|
506
|
-
}));
|
|
507
|
-
}
|
|
508
|
-
}
|
|
81
|
+
var RedisRulesReader = class {
|
|
82
|
+
constructor(client, logger) {
|
|
83
|
+
this.client = client;
|
|
84
|
+
this.logger = logger;
|
|
85
|
+
}
|
|
86
|
+
async getMissingRuleIds(ruleIds) {
|
|
87
|
+
const ruleKeys = this.getRuleKeys(ruleIds);
|
|
88
|
+
const keyBatches = (0, _prosopo_common.chunkIntoBatches)(ruleKeys, require_redis_redisClient.REDIS_BATCH_SIZE);
|
|
89
|
+
return (await (0, _prosopo_common.executeBatchesSequentially)(keyBatches, async (keysBatch) => require_redis_redisClient.getMissingRedisKeys(this.client, keysBatch))).flat().map((ruleKey) => ruleKey.slice(require_redis_redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX.length));
|
|
90
|
+
}
|
|
91
|
+
async fetchRules(ruleIds) {
|
|
92
|
+
const ruleKeys = this.getRuleKeys(ruleIds);
|
|
93
|
+
const keyBatches = (0, _prosopo_common.chunkIntoBatches)(ruleKeys, require_redis_redisClient.REDIS_BATCH_SIZE);
|
|
94
|
+
return (await (0, _prosopo_common.executeBatchesSequentially)(keyBatches, (keysBatch) => this.fetchRuleEntries(keysBatch))).flat();
|
|
95
|
+
}
|
|
96
|
+
async findRules(filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) {
|
|
97
|
+
const query = require_redis_reader_redisRulesQuery.getRulesRedisQuery(filter, matchingFieldsOnly);
|
|
98
|
+
if (skipEmptyUserScopes && query === "( @clientId:{global} | ismissing(@clientId) )") return [];
|
|
99
|
+
if (matchingFieldsOnly && filter.userScope !== void 0) return this.findRulesSplit(filter);
|
|
100
|
+
return this.findRulesGreedy(filter, query);
|
|
101
|
+
}
|
|
102
|
+
async findRulesSplit(filter) {
|
|
103
|
+
const userScope = filter.userScope;
|
|
104
|
+
if (userScope === void 0) return [];
|
|
105
|
+
const clientId = filter.policyScope?.clientId;
|
|
106
|
+
const subQueries = require_redis_reader_redisRulesSplitQuery.buildScopedRulesSubQueries(userScope, clientId, { ...filter.blockOnly === true && { blockOnly: true } });
|
|
107
|
+
try {
|
|
108
|
+
const keyLists = await Promise.all(subQueries.map((sub) => require_redis_reader_redisAggregate.searchRedisKeysBounded(this.client, sub.query, SPLIT_MAX_CANDIDATES_PER_SUB).catch((err) => {
|
|
109
|
+
this.logger.error(() => ({
|
|
110
|
+
err,
|
|
111
|
+
data: { inspect: node_util.inspect({
|
|
112
|
+
subKind: sub.kind,
|
|
113
|
+
query: sub.query
|
|
114
|
+
}, { depth: null }) },
|
|
115
|
+
msg: "failed to execute split rule sub-query"
|
|
116
|
+
}));
|
|
117
|
+
return [];
|
|
118
|
+
})));
|
|
119
|
+
const uniqueKeys = /* @__PURE__ */ new Set();
|
|
120
|
+
for (const list of keyLists) for (const key of list) uniqueKeys.add(key);
|
|
121
|
+
if (uniqueKeys.size === 0) return [];
|
|
122
|
+
const ruleKeys = [...uniqueKeys];
|
|
123
|
+
this.logger.debug(() => ({
|
|
124
|
+
msg: "Executed split rule sub-queries",
|
|
125
|
+
data: { inspect: node_util.inspect({
|
|
126
|
+
subQueryCount: subQueries.length,
|
|
127
|
+
uniqueCandidates: ruleKeys.length,
|
|
128
|
+
perSubQueryCounts: keyLists.map((l, i) => ({
|
|
129
|
+
kind: subQueries[i]?.kind,
|
|
130
|
+
found: l.length
|
|
131
|
+
})),
|
|
132
|
+
filter
|
|
133
|
+
}, { depth: null }) }
|
|
134
|
+
}));
|
|
135
|
+
const { records } = await require_redis_redisClient.fetchRedisHashRecords(this.client, ruleKeys, this.logger);
|
|
136
|
+
const nonEmptyRecords = records.filter((record) => Object.keys(record).length > 0);
|
|
137
|
+
return sortByReaderRank(require_redis_redisClient.parseRedisRecords(nonEmptyRecords, require_ruleInput_ruleInput.accessRuleInput, this.logger));
|
|
138
|
+
} catch (e) {
|
|
139
|
+
this.logger.error(() => ({
|
|
140
|
+
err: e,
|
|
141
|
+
data: { inspect: node_util.inspect({ filter }, { depth: null }) },
|
|
142
|
+
msg: "failed to execute split rule query set"
|
|
143
|
+
}));
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async findRulesRanked(filter, query) {
|
|
148
|
+
try {
|
|
149
|
+
const reply = await this.client.ft.aggregate(require_redis_redisRuleIndex.ACCESS_RULES_REDIS_INDEX_NAME, query, {
|
|
150
|
+
DIALECT: 2,
|
|
151
|
+
LOAD: [...RULE_LOAD_FIELDS],
|
|
152
|
+
STEPS: [
|
|
153
|
+
{
|
|
154
|
+
type: "FILTER",
|
|
155
|
+
expression: "exists(@type)"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
type: "APPLY",
|
|
159
|
+
expression: SPECIFICITY_EXPR,
|
|
160
|
+
AS: "_spec"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: "APPLY",
|
|
164
|
+
expression: SEVERITY_EXPR,
|
|
165
|
+
AS: "_sev"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
type: "APPLY",
|
|
169
|
+
expression: RANK_EXPR,
|
|
170
|
+
AS: "_rank"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
type: "SORTBY",
|
|
174
|
+
BY: [{
|
|
175
|
+
BY: "@_rank",
|
|
176
|
+
DIRECTION: "DESC"
|
|
177
|
+
}]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
type: "LIMIT",
|
|
181
|
+
from: 0,
|
|
182
|
+
size: 20
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
});
|
|
186
|
+
if (reply.results.length === 0) return [];
|
|
187
|
+
this.logger.debug(() => ({
|
|
188
|
+
msg: "Executed ranked search query",
|
|
189
|
+
data: { inspect: node_util.inspect({
|
|
190
|
+
filter,
|
|
191
|
+
foundCount: reply.results.length,
|
|
192
|
+
query
|
|
193
|
+
}, { depth: null }) }
|
|
194
|
+
}));
|
|
195
|
+
const ruleKeys = [];
|
|
196
|
+
for (const result of reply.results) {
|
|
197
|
+
const key = result.__key;
|
|
198
|
+
if (typeof key === "string") ruleKeys.push(key);
|
|
199
|
+
}
|
|
200
|
+
if (ruleKeys.length === 0) return [];
|
|
201
|
+
const { records } = await require_redis_redisClient.fetchRedisHashRecords(this.client, ruleKeys, this.logger);
|
|
202
|
+
const nonEmptyRecords = records.filter((record) => Object.keys(record).length > 0);
|
|
203
|
+
return require_redis_redisClient.parseRedisRecords(nonEmptyRecords, require_ruleInput_ruleInput.accessRuleInput, this.logger);
|
|
204
|
+
} catch (e) {
|
|
205
|
+
this.logger.error(() => ({
|
|
206
|
+
err: e,
|
|
207
|
+
data: { inspect: node_util.inspect({
|
|
208
|
+
query,
|
|
209
|
+
filter
|
|
210
|
+
}, { depth: null }) },
|
|
211
|
+
msg: "failed to execute ranked search query"
|
|
212
|
+
}));
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async findRulesGreedy(filter, query) {
|
|
217
|
+
try {
|
|
218
|
+
const ruleKeys = await require_redis_reader_redisAggregate.aggregateRedisKeys(this.client, query, this.logger, void 0, GREEDY_MAX_CANDIDATES);
|
|
219
|
+
if (ruleKeys.length === 0) return [];
|
|
220
|
+
this.logger.debug(() => ({
|
|
221
|
+
msg: "Executed greedy search query",
|
|
222
|
+
data: { inspect: node_util.inspect({
|
|
223
|
+
filter,
|
|
224
|
+
foundCount: ruleKeys.length,
|
|
225
|
+
query
|
|
226
|
+
}, { depth: null }) }
|
|
227
|
+
}));
|
|
228
|
+
const { records } = await require_redis_redisClient.fetchRedisHashRecords(this.client, ruleKeys, this.logger);
|
|
229
|
+
const nonEmptyRecords = records.filter((record) => Object.keys(record).length > 0);
|
|
230
|
+
return require_redis_redisClient.parseRedisRecords(nonEmptyRecords, require_ruleInput_ruleInput.accessRuleInput, this.logger);
|
|
231
|
+
} catch (e) {
|
|
232
|
+
this.logger.error(() => ({
|
|
233
|
+
err: e,
|
|
234
|
+
data: { inspect: node_util.inspect({
|
|
235
|
+
query,
|
|
236
|
+
filter
|
|
237
|
+
}, { depth: null }) },
|
|
238
|
+
msg: "failed to execute greedy search query"
|
|
239
|
+
}));
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async findRuleIds(filter, matchingFieldsOnly = false) {
|
|
244
|
+
const query = require_redis_reader_redisRulesQuery.getRulesRedisQuery(filter, matchingFieldsOnly);
|
|
245
|
+
let ruleIds = [];
|
|
246
|
+
try {
|
|
247
|
+
ruleIds = (await require_redis_reader_redisAggregate.aggregateRedisKeys(this.client, query, this.logger)).map((ruleKey) => ruleKey.slice(require_redis_redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX.length));
|
|
248
|
+
} catch (e) {
|
|
249
|
+
this.logger.error(() => ({
|
|
250
|
+
err: e,
|
|
251
|
+
data: { inspect: node_util.inspect({
|
|
252
|
+
query,
|
|
253
|
+
filter
|
|
254
|
+
}, { depth: null }) },
|
|
255
|
+
msg: "Failed to execute search query for rule IDs"
|
|
256
|
+
}));
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
this.logger.debug(() => ({
|
|
260
|
+
msg: "Executed search query for rule IDs",
|
|
261
|
+
data: {
|
|
262
|
+
query,
|
|
263
|
+
foundCount: ruleIds.length,
|
|
264
|
+
foundIds: ruleIds
|
|
265
|
+
}
|
|
266
|
+
}));
|
|
267
|
+
return ruleIds;
|
|
268
|
+
}
|
|
269
|
+
async fetchAllRuleIds(batchHandler) {
|
|
270
|
+
const keysBatchHandler = async (keys) => {
|
|
271
|
+
await batchHandler(keys.map((ruleKey) => ruleKey.slice(require_redis_redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX.length)));
|
|
272
|
+
};
|
|
273
|
+
await require_redis_reader_redisAggregate.aggregateRedisKeys(this.client, "*", this.logger, keysBatchHandler);
|
|
274
|
+
}
|
|
275
|
+
async fetchRuleEntries(keys) {
|
|
276
|
+
const { records, expirations } = await require_redis_redisClient.fetchRedisHashRecords(this.client, keys, this.logger);
|
|
277
|
+
const entries = [];
|
|
278
|
+
for (const [index, ruleData] of records.entries()) if (Object.keys(ruleData).length > 0) {
|
|
279
|
+
const rule = require_redis_redisClient.parseRedisRecords([ruleData], require_ruleInput_ruleInput.accessRuleInput, this.logger)[0];
|
|
280
|
+
if (rule) entries.push({
|
|
281
|
+
rule,
|
|
282
|
+
expiresUnixTimestamp: expirations[index]
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
return entries;
|
|
286
|
+
}
|
|
287
|
+
getRuleKeys(ruleIds) {
|
|
288
|
+
return ruleIds.map((id) => `${require_redis_redisRuleIndex.ACCESS_RULE_REDIS_KEY_PREFIX}${id}`);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
var DummyRedisRulesReader = class {
|
|
292
|
+
constructor(logger) {
|
|
293
|
+
this.logger = logger;
|
|
294
|
+
}
|
|
295
|
+
async getMissingRuleIds(ruleIds) {
|
|
296
|
+
this.logger.info(() => ({
|
|
297
|
+
msg: "Dummy getMissingRuleIds() has no effect (redis is not ready)",
|
|
298
|
+
data: { ruleIds }
|
|
299
|
+
}));
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
async fetchRules(ruleIds) {
|
|
303
|
+
this.logger.info(() => ({
|
|
304
|
+
msg: "Dummy fetchRule() has no effect (redis is not ready)",
|
|
305
|
+
data: { ruleIds }
|
|
306
|
+
}));
|
|
307
|
+
return [];
|
|
308
|
+
}
|
|
309
|
+
async findRules(filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) {
|
|
310
|
+
this.logger.info(() => ({
|
|
311
|
+
msg: "Dummy findRules() has no effect (redis is not ready)",
|
|
312
|
+
data: { filter }
|
|
313
|
+
}));
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
async findRuleIds(filter, matchingFieldsOnly = false) {
|
|
317
|
+
this.logger.info(() => ({
|
|
318
|
+
msg: "Dummy findRuleIds() has no effect (redis is not ready)",
|
|
319
|
+
data: { filter }
|
|
320
|
+
}));
|
|
321
|
+
return [];
|
|
322
|
+
}
|
|
323
|
+
async fetchAllRuleIds(batchHandler) {
|
|
324
|
+
this.logger.info(() => ({ msg: "Dummy fetchAllRuleIds() has no effect (redis is not ready)" }));
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
//#endregion
|
|
509
328
|
exports.DummyRedisRulesReader = DummyRedisRulesReader;
|
|
510
329
|
exports.RedisRulesReader = RedisRulesReader;
|
|
511
330
|
exports.SERVER_SIDE_RANK_TOP_N = SERVER_SIDE_RANK_TOP_N;
|