@prosopo/user-access-policy 3.12.7 → 3.12.9
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 +40 -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 +36 -39
- 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.d.ts +52 -1
- package/dist/ruleInput/policyInput.d.ts.map +1 -1
- package/dist/ruleInput/policyInput.js +35 -41
- package/dist/ruleInput/policyInput.js.map +1 -1
- package/dist/ruleInput/ruleInput.d.ts.map +1 -1
- package/dist/ruleInput/ruleInput.js +36 -44
- package/dist/ruleInput/ruleInput.js.map +1 -1
- package/dist/ruleInput/userScopeInput.js +44 -55
- package/dist/ruleRecord.js +17 -27
- package/dist/rulesStorage.js +9 -8
- package/dist/tests/policyInput.unit.test.js +50 -1
- package/dist/tests/policyInput.unit.test.js.map +1 -1
- package/dist/tests/redis/redisRulesStorage.integration.test.js +22 -3
- package/dist/tests/redis/redisRulesStorage.integration.test.js.map +1 -1
- package/dist/transformRule.js +34 -73
- package/dist/transformRule.js.map +1 -1
- package/entries.ts +25 -6
- package/package.json +13 -12
- package/src/ruleInput/policyInput.ts +45 -2
- package/src/ruleInput/ruleInput.ts +10 -3
- package/src/tests/policyInput.unit.test.ts +69 -1
- package/src/tests/redis/redisRulesStorage.integration.test.ts +191 -148
- package/src/transformRule.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,80 +1,102 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
]);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
var ALL_USER_SCOPE_FIELDS = [
|
|
18
|
+
...SCALAR_USER_SCOPE_FIELDS,
|
|
19
|
+
"numericIp",
|
|
20
|
+
"numericIpMaskMin",
|
|
21
|
+
"numericIpMaskMax"
|
|
24
22
|
];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
59
|
+
var userScopeRedisSchema = {
|
|
60
|
+
...userAttributesRedisSchema,
|
|
61
|
+
...userIpRedisSchema
|
|
26
62
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
45
|
-
|
|
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
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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;
|