@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.
Files changed (84) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +45 -41
  2. package/.turbo/turbo-build$colon$tsc.log +14 -14
  3. package/.turbo/turbo-build.log +46 -42
  4. package/CHANGELOG.md +24 -0
  5. package/dist/.export.js +7 -21
  6. package/dist/_virtual/_rolldown/runtime.js +3 -0
  7. package/dist/api/.export.js +2 -9
  8. package/dist/api/accessRulesApiClient.js +1 -1
  9. package/dist/api/delete/.export.js +2 -1
  10. package/dist/api/delete/deleteAllRules.js +22 -24
  11. package/dist/api/delete/deleteRuleGroups.js +39 -51
  12. package/dist/api/delete/deleteRules.js +37 -41
  13. package/dist/api/read/.export.js +2 -1
  14. package/dist/api/read/fetchRules.js +34 -42
  15. package/dist/api/read/findRuleIds.js +35 -48
  16. package/dist/api/read/getMissingIds.js +36 -40
  17. package/dist/api/ruleApiRoutes.js +62 -120
  18. package/dist/api/rulesApiClient.js +51 -87
  19. package/dist/api/write/.export.js +2 -1
  20. package/dist/api/write/insertRules.js +84 -102
  21. package/dist/api/write/rehashRules.js +48 -56
  22. package/dist/cjs/.export.cjs +21 -23
  23. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  24. package/dist/cjs/api/.export.cjs +6 -10
  25. package/dist/cjs/api/accessRulesApiClient.cjs +0 -0
  26. package/dist/cjs/api/delete/.export.cjs +0 -1
  27. package/dist/cjs/api/delete/deleteAllRules.cjs +22 -24
  28. package/dist/cjs/api/delete/deleteRuleGroups.cjs +39 -51
  29. package/dist/cjs/api/delete/deleteRules.cjs +41 -42
  30. package/dist/cjs/api/read/.export.cjs +0 -1
  31. package/dist/cjs/api/read/fetchRules.cjs +34 -41
  32. package/dist/cjs/api/read/findRuleIds.cjs +37 -48
  33. package/dist/cjs/api/read/getMissingIds.cjs +36 -39
  34. package/dist/cjs/api/ruleApiRoutes.cjs +69 -125
  35. package/dist/cjs/api/rulesApiClient.cjs +54 -90
  36. package/dist/cjs/api/write/.export.cjs +0 -1
  37. package/dist/cjs/api/write/insertRules.cjs +85 -103
  38. package/dist/cjs/api/write/rehashRules.cjs +48 -56
  39. package/dist/cjs/classifyOs.cjs +46 -26
  40. package/dist/cjs/mongoose/.export.cjs +2 -3
  41. package/dist/cjs/mongoose/mongooseRuleSchema.cjs +97 -36
  42. package/dist/cjs/redis/.export.cjs +4 -5
  43. package/dist/cjs/redis/reader/redisAggregate.cjs +59 -84
  44. package/dist/cjs/redis/reader/redisRulesQuery.cjs +74 -116
  45. package/dist/cjs/redis/reader/redisRulesReader.cjs +322 -503
  46. package/dist/cjs/redis/reader/redisRulesSplitQuery.cjs +94 -72
  47. package/dist/cjs/redis/redisClient.cjs +53 -58
  48. package/dist/cjs/redis/redisRuleIndex.cjs +93 -49
  49. package/dist/cjs/redis/redisRulesStorage.cjs +21 -30
  50. package/dist/cjs/redis/redisRulesWriter.cjs +86 -112
  51. package/dist/cjs/rule.cjs +8 -7
  52. package/dist/cjs/ruleInput/.export.cjs +7 -8
  53. package/dist/cjs/ruleInput/policyInput.cjs +35 -58
  54. package/dist/cjs/ruleInput/ruleInput.cjs +37 -42
  55. package/dist/cjs/ruleInput/userScopeInput.cjs +47 -55
  56. package/dist/cjs/ruleRecord.cjs +15 -22
  57. package/dist/cjs/rulesStorage.cjs +7 -6
  58. package/dist/cjs/transformRule.cjs +36 -70
  59. package/dist/classifyOs.js +48 -29
  60. package/dist/mongoose/.export.js +2 -3
  61. package/dist/mongoose/mongooseRuleSchema.js +99 -38
  62. package/dist/redis/.export.js +3 -5
  63. package/dist/redis/reader/redisAggregate.js +60 -86
  64. package/dist/redis/reader/redisRulesQuery.js +75 -118
  65. package/dist/redis/reader/redisRulesReader.js +312 -487
  66. package/dist/redis/reader/redisRulesSplitQuery.js +96 -75
  67. package/dist/redis/redisClient.js +54 -62
  68. package/dist/redis/redisRuleIndex.js +93 -58
  69. package/dist/redis/redisRulesStorage.js +21 -30
  70. package/dist/redis/redisRulesWriter.js +82 -113
  71. package/dist/rule.js +10 -10
  72. package/dist/ruleInput/.export.js +3 -7
  73. package/dist/ruleInput/policyInput.js +35 -61
  74. package/dist/ruleInput/ruleInput.js +36 -44
  75. package/dist/ruleInput/userScopeInput.js +44 -55
  76. package/dist/ruleRecord.js +17 -27
  77. package/dist/rulesStorage.js +9 -8
  78. package/dist/tests/redis/redisRulesStorage.integration.test.js +1 -3
  79. package/dist/tests/redis/redisRulesStorage.integration.test.js.map +1 -1
  80. package/dist/transformRule.js +34 -73
  81. package/entries.ts +25 -6
  82. package/package.json +13 -12
  83. package/src/tests/redis/redisRulesStorage.integration.test.ts +191 -195
  84. package/tsconfig.tsbuildinfo +1 -1
@@ -1,80 +1,102 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const rule = require("../../rule.cjs");
4
- const escapeTagValue = (value) => value.replace(/([,.<>{}\[\]"':;!@#$%^&*()\-+=~|/\\])/g, "\\$1");
5
- const FIELDS_REQUIRING_ESCAPE = /* @__PURE__ */ new Set([
6
- "coords"
7
- ]);
8
- const NUMERIC_FIELDS = /* @__PURE__ */ new Set(["asn"]);
9
- const SCALAR_USER_SCOPE_FIELDS = [
10
- "userId",
11
- "ja4Hash",
12
- "headersHash",
13
- "userAgentHash",
14
- "headHash",
15
- "coords",
16
- "countryCode",
17
- "asn"
2
+ const require_rule = require("../../rule.cjs");
3
+ //#region src/redis/reader/redisRulesSplitQuery.ts
4
+ var escapeTagValue = (value) => value.replace(/([,.<>{}\[\]"':;!@#$%^&*()\-+=~|/\\])/g, "\\$1");
5
+ var FIELDS_REQUIRING_ESCAPE = /* @__PURE__ */ new Set(["coords"]);
6
+ var NUMERIC_FIELDS = /* @__PURE__ */ new Set(["asn"]);
7
+ var SCALAR_USER_SCOPE_FIELDS = [
8
+ "userId",
9
+ "ja4Hash",
10
+ "headersHash",
11
+ "userAgentHash",
12
+ "headHash",
13
+ "coords",
14
+ "countryCode",
15
+ "asn"
18
16
  ];
19
- const ALL_USER_SCOPE_FIELDS = [
20
- ...SCALAR_USER_SCOPE_FIELDS,
21
- "numericIp",
22
- "numericIpMaskMin",
23
- "numericIpMaskMax"
17
+ var ALL_USER_SCOPE_FIELDS = [
18
+ ...SCALAR_USER_SCOPE_FIELDS,
19
+ "numericIp",
20
+ "numericIpMaskMin",
21
+ "numericIpMaskMax"
24
22
  ];
25
- const GLOBAL_SCOPE_INNER = `@clientId:{${rule.GLOBAL_CLIENT_SCOPE_SENTINEL}} | ismissing(@clientId)`;
26
- const buildScopeClause = (clientId) => {
27
- if (clientId === void 0) {
28
- return `( ${GLOBAL_SCOPE_INNER} )`;
29
- }
30
- return `( @clientId:{${clientId}} | ${GLOBAL_SCOPE_INNER} )`;
23
+ var GLOBAL_SCOPE_INNER = `@clientId:{${require_rule.GLOBAL_CLIENT_SCOPE_SENTINEL}} | ismissing(@clientId)`;
24
+ var buildScopeClause = (clientId) => {
25
+ if (clientId === void 0) return `( ${GLOBAL_SCOPE_INNER} )`;
26
+ return `( @clientId:{${clientId}} | ${GLOBAL_SCOPE_INNER} )`;
31
27
  };
32
- const buildFieldClause = (field, value) => {
33
- if (value === void 0) {
34
- return null;
35
- }
36
- const stringValue = String(value);
37
- if (NUMERIC_FIELDS.has(field)) {
38
- return `@${field}:[${stringValue} ${stringValue}]`;
39
- }
40
- const queryValue = FIELDS_REQUIRING_ESCAPE.has(field) ? escapeTagValue(stringValue) : stringValue;
41
- return `@${field}:{${queryValue}}`;
28
+ var buildFieldClause = (field, value) => {
29
+ if (value === void 0) return null;
30
+ const stringValue = String(value);
31
+ if (NUMERIC_FIELDS.has(field)) return `@${field}:[${stringValue} ${stringValue}]`;
32
+ return `@${field}:{${FIELDS_REQUIRING_ESCAPE.has(field) ? escapeTagValue(stringValue) : stringValue}}`;
42
33
  };
43
- const buildScopedRulesSubQueries = (userScope, clientId, options = {}) => {
44
- const typeClause = options.blockOnly ? `@type:{${rule.AccessPolicyType.Block}} ` : "";
45
- const scopeClause = buildScopeClause(clientId);
46
- const prefix = `${typeClause}${scopeClause}`;
47
- const subQueries = [];
48
- for (const field of SCALAR_USER_SCOPE_FIELDS) {
49
- const clause = buildFieldClause(field, userScope[field]);
50
- if (clause === null) {
51
- continue;
52
- }
53
- subQueries.push({
54
- kind: `field:${field}`,
55
- query: `${prefix} ${clause}`
56
- });
57
- }
58
- const requestIp = userScope.numericIp;
59
- if (requestIp !== void 0) {
60
- subQueries.push({
61
- kind: "ip:exact",
62
- query: `${prefix} @numericIp:[${requestIp} ${requestIp}]`
63
- });
64
- subQueries.push({
65
- kind: "ip:mask",
66
- query: `${prefix} @numericIpMaskMin:[-inf ${requestIp}] @numericIpMaskMax:[${requestIp} +inf]`
67
- });
68
- }
69
- const noScopeIsmissing = ALL_USER_SCOPE_FIELDS.map(
70
- (field) => `ismissing(@${field})`
71
- ).join(" ");
72
- subQueries.push({
73
- kind: "no-user-scope",
74
- query: `${prefix} ${noScopeIsmissing}`
75
- });
76
- return subQueries;
34
+ /**
35
+ * Build the set of FT sub-queries that together cover every rule that
36
+ * could apply to a request.
37
+ *
38
+ * The single-query design this replaces produced one FT.AGGREGATE whose
39
+ * candidate set was the entire scope's rule pool — the APPLY / SORTBY
40
+ * pipeline then walked every rule per request, which degrades sharply
41
+ * once rule populations reach the 10k+ range. The split approach fires
42
+ * one probe per populated request field. Each probe uses the field's
43
+ * own index posting list, so a 17k IP-ban population collapses to 1
44
+ * result (exact IP) plus a handful (CIDR ranges containing the IP)
45
+ * instead of forcing a full-set scan.
46
+ *
47
+ * A single fall-through probe covers rules with no user-scope constraint
48
+ * (client-wide restriction); those are rare so the ismissing()-heavy
49
+ * query is cheap in practice.
50
+ *
51
+ * Rank + strict-match filtering happens in JS via `rankCandidateRules`
52
+ * after the union — the FT layer is used purely as a candidate fetcher.
53
+ *
54
+ * `blockOnly` narrows the candidate set to rules with `type:{block}` —
55
+ * used by the hard-block middleware which never needs Restrict rules.
56
+ * Every other caller passes false so both Block and Restrict rules are
57
+ * fetched; the JS-side ranker picks the right one via specificity +
58
+ * severity. Merging the block and restrict paths behind one split-query
59
+ * fixed the Twickets IP-rule regression: the previous FT.AGGREGATE ranker
60
+ * used for non-block lookups was truncating specific-IP restrict rules
61
+ * out of the top-N when many higher-specificity irrelevant rules matched
62
+ * the greedy `ismissing()` disjunction.
63
+ */
64
+ var buildScopedRulesSubQueries = (userScope, clientId, options = {}) => {
65
+ const prefix = `${options.blockOnly ? `@type:{${require_rule.AccessPolicyType.Block}} ` : ""}${buildScopeClause(clientId)}`;
66
+ const subQueries = [];
67
+ for (const field of SCALAR_USER_SCOPE_FIELDS) {
68
+ const clause = buildFieldClause(field, userScope[field]);
69
+ if (clause === null) continue;
70
+ subQueries.push({
71
+ kind: `field:${field}`,
72
+ query: `${prefix} ${clause}`
73
+ });
74
+ }
75
+ const requestIp = userScope.numericIp;
76
+ if (requestIp !== void 0) {
77
+ subQueries.push({
78
+ kind: "ip:exact",
79
+ query: `${prefix} @numericIp:[${requestIp} ${requestIp}]`
80
+ });
81
+ subQueries.push({
82
+ kind: "ip:mask",
83
+ query: `${prefix} @numericIpMaskMin:[-inf ${requestIp}] @numericIpMaskMax:[${requestIp} +inf]`
84
+ });
85
+ }
86
+ const noScopeIsmissing = ALL_USER_SCOPE_FIELDS.map((field) => `ismissing(@${field})`).join(" ");
87
+ subQueries.push({
88
+ kind: "no-user-scope",
89
+ query: `${prefix} ${noScopeIsmissing}`
90
+ });
91
+ return subQueries;
77
92
  };
78
- const buildScopedBlockSubQueries = (userScope, clientId) => buildScopedRulesSubQueries(userScope, clientId, { blockOnly: true });
93
+ /**
94
+ * Backwards-compatible alias for the previous block-only builder. New
95
+ * callers should use `buildScopedRulesSubQueries` directly.
96
+ *
97
+ * @deprecated use `buildScopedRulesSubQueries(..., { blockOnly: true })`
98
+ */
99
+ var buildScopedBlockSubQueries = (userScope, clientId) => buildScopedRulesSubQueries(userScope, clientId, { blockOnly: true });
100
+ //#endregion
79
101
  exports.buildScopedBlockSubQueries = buildScopedBlockSubQueries;
80
102
  exports.buildScopedRulesSubQueries = buildScopedRulesSubQueries;
@@ -1,66 +1,61 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const zod = require("zod");
4
- const REDIS_BATCH_SIZE = 1e3;
5
- const getMissingRedisKeys = async (client, keys) => {
6
- const queries = client.multi();
7
- keys.map((key) => {
8
- queries.exists(key);
9
- });
10
- const records = await queries.exec();
11
- const missingKeys = [];
12
- records.map((exists, recordIndex) => {
13
- if ("0" === String(exists)) {
14
- const key = keys[recordIndex];
15
- if (key) {
16
- missingKeys.push(key);
17
- }
18
- }
19
- });
20
- return missingKeys;
2
+ let zod = require("zod");
3
+ //#region src/redis/redisClient.ts
4
+ var REDIS_BATCH_SIZE = 1e3;
5
+ var getMissingRedisKeys = async (client, keys) => {
6
+ const queries = client.multi();
7
+ keys.map((key) => {
8
+ queries.exists(key);
9
+ });
10
+ const records = await queries.exec();
11
+ const missingKeys = [];
12
+ records.map((exists, recordIndex) => {
13
+ if ("0" === String(exists)) {
14
+ const key = keys[recordIndex];
15
+ if (key) missingKeys.push(key);
16
+ }
17
+ });
18
+ return missingKeys;
21
19
  };
22
- const fetchRedisHashRecords = async (client, keys, logger) => {
23
- const rulesPipe = client.multi();
24
- const expirationPipe = client.multi();
25
- for (const key of keys) {
26
- rulesPipe.hGetAll(key);
27
- expirationPipe.expireTime(key);
28
- }
29
- const records = await rulesPipe.exec();
30
- const expirationRecords = await expirationPipe.exec();
31
- return {
32
- records,
33
- expirations: parseExpirationRecords(expirationRecords, logger)
34
- };
20
+ var fetchRedisHashRecords = async (client, keys, logger) => {
21
+ const rulesPipe = client.multi();
22
+ const expirationPipe = client.multi();
23
+ for (const key of keys) {
24
+ rulesPipe.hGetAll(key);
25
+ expirationPipe.expireTime(key);
26
+ }
27
+ return {
28
+ records: await rulesPipe.exec(),
29
+ expirations: parseExpirationRecords(await expirationPipe.exec(), logger)
30
+ };
35
31
  };
36
- const parseRedisRecords = (records, recordSchema, logger) => records.flatMap((record) => {
37
- const parseResult = recordSchema.safeParse(record);
38
- if (parseResult.success) {
39
- return [parseResult.data];
40
- }
41
- logger.error(() => ({
42
- msg: "Failed to parse Redis record",
43
- data: { record, error: parseResult.error }
44
- }));
45
- return [];
32
+ var parseRedisRecords = (records, recordSchema, logger) => records.flatMap((record) => {
33
+ const parseResult = recordSchema.safeParse(record);
34
+ if (parseResult.success) return [parseResult.data];
35
+ logger.error(() => ({
36
+ msg: "Failed to parse Redis record",
37
+ data: {
38
+ record,
39
+ error: parseResult.error
40
+ }
41
+ }));
42
+ return [];
46
43
  });
47
- const expirationRecordSchema = zod.z.coerce.number();
48
- const UNSET_EXPIRATION_VALUE = -1;
49
- const parseExpirationRecords = (records, logger) => records.flatMap((record) => {
50
- const parseResult = expirationRecordSchema.safeParse(record);
51
- if (parseResult.success) {
52
- const expiration = UNSET_EXPIRATION_VALUE === parseResult.data ? void 0 : parseResult.data;
53
- return [expiration];
54
- }
55
- logger.error(() => ({
56
- msg: "Failed to parse Redis expiration record",
57
- data: {
58
- record,
59
- error: parseResult.error
60
- }
61
- }));
62
- return [void 0];
44
+ var expirationRecordSchema = zod.z.coerce.number();
45
+ var UNSET_EXPIRATION_VALUE = -1;
46
+ var parseExpirationRecords = (records, logger) => records.flatMap((record) => {
47
+ const parseResult = expirationRecordSchema.safeParse(record);
48
+ if (parseResult.success) return [UNSET_EXPIRATION_VALUE === parseResult.data ? void 0 : parseResult.data];
49
+ logger.error(() => ({
50
+ msg: "Failed to parse Redis expiration record",
51
+ data: {
52
+ record,
53
+ error: parseResult.error
54
+ }
55
+ }));
56
+ return [void 0];
63
57
  });
58
+ //#endregion
64
59
  exports.REDIS_BATCH_SIZE = REDIS_BATCH_SIZE;
65
60
  exports.fetchRedisHashRecords = fetchRedisHashRecords;
66
61
  exports.getMissingRedisKeys = getMissingRedisKeys;
@@ -1,60 +1,104 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const search = require("@redis/search");
4
- const transformRule = require("../transformRule.cjs");
5
- const rule = require("../rule.cjs");
6
- const userIpRedisSchema = {
7
- numericIpMaskMin: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
8
- numericIpMaskMax: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
9
- numericIp: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true }
2
+ const require_rule = require("../rule.cjs");
3
+ const require_transformRule = require("../transformRule.cjs");
4
+ let _redis_search = require("@redis/search");
5
+ //#region src/redis/redisRuleIndex.ts
6
+ var userIpRedisSchema = {
7
+ numericIpMaskMin: {
8
+ type: _redis_search.SCHEMA_FIELD_TYPE.NUMERIC,
9
+ INDEXMISSING: true
10
+ },
11
+ numericIpMaskMax: {
12
+ type: _redis_search.SCHEMA_FIELD_TYPE.NUMERIC,
13
+ INDEXMISSING: true
14
+ },
15
+ numericIp: {
16
+ type: _redis_search.SCHEMA_FIELD_TYPE.NUMERIC,
17
+ INDEXMISSING: true
18
+ }
10
19
  };
11
- const userAttributesRedisSchema = {
12
- userId: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
13
- ja4Hash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
14
- headersHash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
15
- userAgentHash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
16
- headHash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
17
- // Use pipe separator for coords since JSON strings contain commas
18
- coords: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true, SEPARATOR: "|" },
19
- countryCode: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
20
- asn: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
21
- os: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true }
20
+ var userAttributesRedisSchema = {
21
+ userId: {
22
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
23
+ INDEXMISSING: true
24
+ },
25
+ ja4Hash: {
26
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
27
+ INDEXMISSING: true
28
+ },
29
+ headersHash: {
30
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
31
+ INDEXMISSING: true
32
+ },
33
+ userAgentHash: {
34
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
35
+ INDEXMISSING: true
36
+ },
37
+ headHash: {
38
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
39
+ INDEXMISSING: true
40
+ },
41
+ coords: {
42
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
43
+ INDEXMISSING: true,
44
+ SEPARATOR: "|"
45
+ },
46
+ countryCode: {
47
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
48
+ INDEXMISSING: true
49
+ },
50
+ asn: {
51
+ type: _redis_search.SCHEMA_FIELD_TYPE.NUMERIC,
52
+ INDEXMISSING: true
53
+ },
54
+ os: {
55
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
56
+ INDEXMISSING: true
57
+ }
22
58
  };
23
- const userScopeRedisSchema = {
24
- ...userAttributesRedisSchema,
25
- ...userIpRedisSchema
59
+ var userScopeRedisSchema = {
60
+ ...userAttributesRedisSchema,
61
+ ...userIpRedisSchema
26
62
  };
27
- const policyScopeRedisSchema = {
28
- clientId: {
29
- type: search.SCHEMA_FIELD_TYPE.TAG,
30
- INDEXMISSING: true
31
- }
63
+ var policyScopeRedisSchema = { clientId: {
64
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
65
+ INDEXMISSING: true
66
+ } };
67
+ /**
68
+ * Note on the field type decision
69
+ *
70
+ * TAG is designed for the exact value matching
71
+ * TEXT is designed for the word-based and pattern matching
72
+ *
73
+ * For our goal TAG fits perfectly and, more performant
74
+ */
75
+ var accessRuleRedisSchema = {
76
+ ...policyScopeRedisSchema,
77
+ ...userScopeRedisSchema,
78
+ groupId: {
79
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
80
+ INDEXMISSING: true
81
+ },
82
+ type: {
83
+ type: _redis_search.SCHEMA_FIELD_TYPE.TAG,
84
+ INDEXMISSING: true
85
+ }
32
86
  };
33
- const accessRuleRedisSchema = {
34
- ...policyScopeRedisSchema,
35
- ...userScopeRedisSchema,
36
- groupId: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
37
- // Indexed so request-time callers that only care about Block policies
38
- // (checkForHardBlock, blockMiddleware) can pre-filter via @type:{block}
39
- // before the SERVER_SIDE_RANK_TOP_N cap kicks in. Without this, dense
40
- // Restrict / routing-Block populations push the hard-block rules out
41
- // of the top-N candidate set and the lookup silently misses them.
42
- type: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true }
87
+ var ACCESS_RULES_REDIS_INDEX_NAME = "index:user-access-rules";
88
+ var ACCESS_RULE_REDIS_KEY_PREFIX = "uar:";
89
+ var accessRulesRedisIndex = {
90
+ name: ACCESS_RULES_REDIS_INDEX_NAME,
91
+ schema: accessRuleRedisSchema,
92
+ options: {
93
+ ON: "HASH",
94
+ PREFIX: [ACCESS_RULE_REDIS_KEY_PREFIX]
95
+ }
43
96
  };
44
- const ACCESS_RULES_REDIS_INDEX_NAME = "index:user-access-rules";
45
- const ACCESS_RULE_REDIS_KEY_PREFIX = "uar:";
46
- const accessRulesRedisIndex = {
47
- name: ACCESS_RULES_REDIS_INDEX_NAME,
48
- schema: accessRuleRedisSchema,
49
- options: {
50
- ON: "HASH",
51
- PREFIX: [ACCESS_RULE_REDIS_KEY_PREFIX]
52
- }
53
- };
54
- const getAccessRuleRedisKey = (rule2) => ACCESS_RULE_REDIS_KEY_PREFIX + transformRule.makeAccessRuleHash(rule2);
55
- exports.GLOBAL_CLIENT_SCOPE_SENTINEL = rule.GLOBAL_CLIENT_SCOPE_SENTINEL;
97
+ var getAccessRuleRedisKey = (rule) => ACCESS_RULE_REDIS_KEY_PREFIX + require_transformRule.makeAccessRuleHash(rule);
98
+ //#endregion
56
99
  exports.ACCESS_RULES_REDIS_INDEX_NAME = ACCESS_RULES_REDIS_INDEX_NAME;
57
100
  exports.ACCESS_RULE_REDIS_KEY_PREFIX = ACCESS_RULE_REDIS_KEY_PREFIX;
101
+ exports.GLOBAL_CLIENT_SCOPE_SENTINEL = require_rule.GLOBAL_CLIENT_SCOPE_SENTINEL;
58
102
  exports.accessRuleRedisSchema = accessRuleRedisSchema;
59
103
  exports.accessRulesRedisIndex = accessRulesRedisIndex;
60
104
  exports.getAccessRuleRedisKey = getAccessRuleRedisKey;
@@ -1,34 +1,25 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const redisRulesReader = require("./reader/redisRulesReader.cjs");
4
- const redisRulesWriter = require("./redisRulesWriter.cjs");
5
- const createRedisAccessRulesStorage = (connection, logger) => {
6
- const storage = composeStorage(
7
- new redisRulesReader.DummyRedisRulesReader(logger),
8
- new redisRulesWriter.DummyRedisRulesWriter(logger)
9
- );
10
- connection.getClient().then((client) => {
11
- const realStorage = composeStorage(
12
- new redisRulesReader.RedisRulesReader(client, logger),
13
- new redisRulesWriter.RedisRulesWriter(client, logger)
14
- );
15
- Object.assign(storage, realStorage);
16
- logger.info(() => ({
17
- msg: "RedisAccessRules storage got a ready Redis client"
18
- }));
19
- });
20
- return storage;
2
+ const require_redis_reader_redisRulesReader = require("./reader/redisRulesReader.cjs");
3
+ const require_redis_redisRulesWriter = require("./redisRulesWriter.cjs");
4
+ //#region src/redis/redisRulesStorage.ts
5
+ var createRedisAccessRulesStorage = (connection, logger) => {
6
+ const storage = composeStorage(new require_redis_reader_redisRulesReader.DummyRedisRulesReader(logger), new require_redis_redisRulesWriter.DummyRedisRulesWriter(logger));
7
+ connection.getClient().then((client) => {
8
+ const realStorage = composeStorage(new require_redis_reader_redisRulesReader.RedisRulesReader(client, logger), new require_redis_redisRulesWriter.RedisRulesWriter(client, logger));
9
+ Object.assign(storage, realStorage);
10
+ logger.info(() => ({ msg: "RedisAccessRules storage got a ready Redis client" }));
11
+ });
12
+ return storage;
21
13
  };
22
- const composeStorage = (reader, writer) => ({
23
- // reader
24
- fetchRules: reader.fetchRules.bind(reader),
25
- getMissingRuleIds: reader.getMissingRuleIds.bind(reader),
26
- findRules: reader.findRules.bind(reader),
27
- findRuleIds: reader.findRuleIds.bind(reader),
28
- fetchAllRuleIds: reader.fetchAllRuleIds.bind(reader),
29
- // writer
30
- insertRules: writer.insertRules.bind(writer),
31
- deleteRules: writer.deleteRules.bind(writer),
32
- deleteAllRules: writer.deleteAllRules.bind(writer)
14
+ var composeStorage = (reader, writer) => ({
15
+ fetchRules: reader.fetchRules.bind(reader),
16
+ getMissingRuleIds: reader.getMissingRuleIds.bind(reader),
17
+ findRules: reader.findRules.bind(reader),
18
+ findRuleIds: reader.findRuleIds.bind(reader),
19
+ fetchAllRuleIds: reader.fetchAllRuleIds.bind(reader),
20
+ insertRules: writer.insertRules.bind(writer),
21
+ deleteRules: writer.deleteRules.bind(writer),
22
+ deleteAllRules: writer.deleteAllRules.bind(writer)
33
23
  });
24
+ //#endregion
34
25
  exports.createRedisAccessRulesStorage = createRedisAccessRulesStorage;