@prosopo/user-access-policy 3.5.19 → 3.5.28
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/CHANGELOG.md +84 -0
- package/dist/.export.js +21 -0
- package/dist/api/.export.js +11 -0
- package/dist/api/delete/.export.js +1 -0
- package/dist/api/{deleteAllRulesEndpoint.js → delete/deleteAllRules.js} +10 -9
- package/dist/api/delete/deleteRuleGroups.js +52 -0
- package/dist/api/delete/deleteRules.js +43 -0
- package/dist/api/read/.export.js +1 -0
- package/dist/api/read/fetchRules.js +43 -0
- package/dist/api/read/findRuleIds.js +50 -0
- package/dist/api/read/getMissingIds.js +41 -0
- package/dist/api/ruleApiRoutes.js +131 -0
- package/dist/api/rulesApiClient.js +93 -0
- package/dist/api/write/.export.js +1 -0
- package/dist/api/write/insertRules.js +102 -0
- package/dist/api/write/rehashRules.js +57 -0
- package/dist/cjs/.export.cjs +21 -0
- package/dist/cjs/api/.export.cjs +11 -0
- package/dist/cjs/api/delete/.export.cjs +1 -0
- package/dist/cjs/api/{deleteAllRulesEndpoint.cjs → delete/deleteAllRules.cjs} +9 -8
- package/dist/cjs/api/delete/deleteRuleGroups.cjs +52 -0
- package/dist/cjs/api/delete/deleteRules.cjs +43 -0
- package/dist/cjs/api/read/.export.cjs +1 -0
- package/dist/cjs/api/read/fetchRules.cjs +43 -0
- package/dist/cjs/api/read/findRuleIds.cjs +50 -0
- package/dist/cjs/api/read/getMissingIds.cjs +41 -0
- package/dist/cjs/api/ruleApiRoutes.cjs +131 -0
- package/dist/cjs/api/rulesApiClient.cjs +93 -0
- package/dist/cjs/api/write/.export.cjs +1 -0
- package/dist/cjs/api/write/insertRules.cjs +102 -0
- package/dist/cjs/api/write/rehashRules.cjs +57 -0
- package/dist/cjs/mongoose/.export.cjs +4 -0
- package/dist/cjs/mongoose/mongooseRuleSchema.cjs +36 -0
- package/dist/cjs/redis/.export.cjs +6 -0
- package/dist/cjs/redis/reader/redisAggregate.cjs +60 -0
- package/dist/cjs/redis/reader/redisRulesQuery.cjs +99 -0
- package/dist/cjs/redis/reader/redisRulesReader.cjs +230 -0
- package/dist/cjs/redis/redisClient.cjs +67 -0
- package/dist/cjs/redis/redisRuleIndex.cjs +50 -0
- package/dist/cjs/redis/redisRulesStorage.cjs +22 -9
- package/dist/cjs/redis/redisRulesWriter.cjs +91 -64
- package/dist/cjs/rule.cjs +8 -0
- package/dist/cjs/ruleInput/.export.cjs +9 -0
- package/dist/cjs/ruleInput/policyInput.cjs +25 -0
- package/dist/cjs/ruleInput/ruleInput.cjs +50 -0
- package/dist/cjs/ruleInput/userScopeInput.cjs +55 -0
- package/dist/cjs/ruleRecord.cjs +23 -0
- package/dist/cjs/rulesStorage.cjs +8 -0
- package/dist/cjs/transformRule.cjs +77 -0
- package/dist/mongoose/.export.js +4 -0
- package/dist/mongoose/mongooseRuleSchema.js +36 -0
- package/dist/redis/.export.js +6 -0
- package/dist/redis/reader/redisAggregate.js +60 -0
- package/dist/redis/reader/redisRulesQuery.js +99 -0
- package/dist/redis/reader/redisRulesReader.js +213 -0
- package/dist/redis/redisClient.js +67 -0
- package/dist/redis/redisRuleIndex.js +50 -0
- package/dist/redis/redisRulesStorage.js +23 -10
- package/dist/redis/redisRulesWriter.js +91 -64
- package/dist/rule.js +8 -0
- package/dist/ruleInput/.export.js +9 -0
- package/dist/ruleInput/policyInput.js +25 -0
- package/dist/ruleInput/ruleInput.js +50 -0
- package/dist/ruleInput/userScopeInput.js +55 -0
- package/dist/ruleRecord.js +23 -0
- package/dist/rulesStorage.js +8 -0
- package/dist/transformRule.js +77 -0
- package/entries.ts +20 -0
- package/package.json +34 -18
- package/vite.cjs.config.ts +4 -1
- package/vite.esm.config.ts +6 -1
- package/dist/accessPolicy.js +0 -80
- package/dist/accessPolicyResolver.js +0 -31
- package/dist/accessRules.js +0 -11
- package/dist/api/accessRuleApiRoutes.js +0 -79
- package/dist/api/accessRulesApiClient.js +0 -38
- package/dist/api/deleteRulesEndpoint.js +0 -34
- package/dist/api/insertRulesEndpoint.js +0 -62
- package/dist/cjs/accessPolicy.cjs +0 -80
- package/dist/cjs/accessPolicyResolver.cjs +0 -31
- package/dist/cjs/accessRules.cjs +0 -11
- package/dist/cjs/api/accessRuleApiRoutes.cjs +0 -79
- package/dist/cjs/api/accessRulesApiClient.cjs +0 -38
- package/dist/cjs/api/deleteRulesEndpoint.cjs +0 -34
- package/dist/cjs/api/insertRulesEndpoint.cjs +0 -62
- package/dist/cjs/index.cjs +0 -31
- package/dist/cjs/redis/redisRulesIndex.cjs +0 -138
- package/dist/cjs/redis/redisRulesReader.cjs +0 -142
- package/dist/cjs/util.cjs +0 -5
- package/dist/index.js +0 -32
- package/dist/redis/redisRulesIndex.js +0 -138
- package/dist/redis/redisRulesReader.js +0 -125
- package/dist/util.js +0 -5
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const util = require("node:util");
|
|
4
|
-
const accessRules = require("../accessRules.cjs");
|
|
5
|
-
const redisRulesIndex = require("./redisRulesIndex.cjs");
|
|
6
|
-
function _interopNamespaceDefault(e) {
|
|
7
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
8
|
-
if (e) {
|
|
9
|
-
for (const k in e) {
|
|
10
|
-
if (k !== "default") {
|
|
11
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: () => e[k]
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
n.default = e;
|
|
20
|
-
return Object.freeze(n);
|
|
21
|
-
}
|
|
22
|
-
const util__namespace = /* @__PURE__ */ _interopNamespaceDefault(util);
|
|
23
|
-
const createRedisRulesReader = (client, logger) => {
|
|
24
|
-
return {
|
|
25
|
-
findRules: async (filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) => {
|
|
26
|
-
const query = redisRulesIndex.getRedisRulesQuery(filter, matchingFieldsOnly);
|
|
27
|
-
if (skipEmptyUserScopes && query === "ismissing(@clientId)") {
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
|
-
let searchReply;
|
|
31
|
-
try {
|
|
32
|
-
searchReply = await client.ft.search(
|
|
33
|
-
redisRulesIndex.redisRulesIndexName,
|
|
34
|
-
query,
|
|
35
|
-
redisRulesIndex.redisRulesSearchOptions
|
|
36
|
-
);
|
|
37
|
-
if (searchReply.total > 0) {
|
|
38
|
-
logger.debug(() => ({
|
|
39
|
-
msg: "Executed search query",
|
|
40
|
-
data: {
|
|
41
|
-
inspect: util__namespace.inspect(
|
|
42
|
-
{
|
|
43
|
-
filter,
|
|
44
|
-
searchReply,
|
|
45
|
-
query
|
|
46
|
-
},
|
|
47
|
-
{ depth: null }
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
}));
|
|
51
|
-
}
|
|
52
|
-
} catch (e) {
|
|
53
|
-
logger.error(() => ({
|
|
54
|
-
err: e,
|
|
55
|
-
data: {
|
|
56
|
-
inspect: util__namespace.inspect(
|
|
57
|
-
{
|
|
58
|
-
query,
|
|
59
|
-
filter
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
depth: null
|
|
63
|
-
}
|
|
64
|
-
)
|
|
65
|
-
},
|
|
66
|
-
msg: "failed to execute search query"
|
|
67
|
-
}));
|
|
68
|
-
return [];
|
|
69
|
-
}
|
|
70
|
-
return extractRulesFromSearchReply(searchReply, logger);
|
|
71
|
-
},
|
|
72
|
-
findRuleIds: async (filter, matchingFieldsOnly = false) => {
|
|
73
|
-
const query = redisRulesIndex.getRedisRulesQuery(filter, matchingFieldsOnly);
|
|
74
|
-
let searchReply;
|
|
75
|
-
try {
|
|
76
|
-
searchReply = await client.ft.searchNoContent(
|
|
77
|
-
redisRulesIndex.redisRulesIndexName,
|
|
78
|
-
query,
|
|
79
|
-
redisRulesIndex.redisRulesSearchOptions
|
|
80
|
-
);
|
|
81
|
-
} catch (e) {
|
|
82
|
-
logger.error(() => ({
|
|
83
|
-
err: e,
|
|
84
|
-
data: {
|
|
85
|
-
inspect: util__namespace.inspect(
|
|
86
|
-
{
|
|
87
|
-
query,
|
|
88
|
-
filter
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
depth: null
|
|
92
|
-
}
|
|
93
|
-
)
|
|
94
|
-
},
|
|
95
|
-
msg: "Failed to execute search query for rule IDs"
|
|
96
|
-
}));
|
|
97
|
-
return [];
|
|
98
|
-
}
|
|
99
|
-
return searchReply.documents;
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
const getDummyRedisRulesReader = (logger) => {
|
|
104
|
-
return {
|
|
105
|
-
findRules: async (filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) => {
|
|
106
|
-
logger.info(() => ({
|
|
107
|
-
msg: "Dummy findRules() has no effect (redis is not ready)",
|
|
108
|
-
data: {
|
|
109
|
-
filter
|
|
110
|
-
}
|
|
111
|
-
}));
|
|
112
|
-
return [];
|
|
113
|
-
},
|
|
114
|
-
findRuleIds: async (filter, matchingFieldsOnly = false) => {
|
|
115
|
-
logger.info(() => ({
|
|
116
|
-
msg: "Dummy findRuleIds() has no effect (redis is not ready)",
|
|
117
|
-
data: {
|
|
118
|
-
filter
|
|
119
|
-
}
|
|
120
|
-
}));
|
|
121
|
-
return [];
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
const extractRulesFromSearchReply = (searchReply, logger) => {
|
|
126
|
-
const accessRules$1 = [];
|
|
127
|
-
searchReply.documents.map(({ id, value: document }) => {
|
|
128
|
-
const parsedDocument = accessRules.accessRuleSchema.safeParse(document);
|
|
129
|
-
if (parsedDocument.success) {
|
|
130
|
-
accessRules$1.push(parsedDocument.data);
|
|
131
|
-
} else {
|
|
132
|
-
logger.debug(() => ({
|
|
133
|
-
msg: "Failed to parse access rule from search reply",
|
|
134
|
-
id,
|
|
135
|
-
error: parsedDocument.error
|
|
136
|
-
}));
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
return accessRules$1;
|
|
140
|
-
};
|
|
141
|
-
exports.createRedisRulesReader = createRedisRulesReader;
|
|
142
|
-
exports.getDummyRedisRulesReader = getDummyRedisRulesReader;
|
package/dist/cjs/util.cjs
DELETED
package/dist/index.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { AccessPolicyType, accessPolicySchema, accessRuleSchemaExtended, policyScopeSchema, userScopeInputSchema } from "./accessPolicy.js";
|
|
2
|
-
import { ScopeMatch } from "./accessPolicyResolver.js";
|
|
3
|
-
import { accessRuleSchema } from "./accessRules.js";
|
|
4
|
-
import { AccessRuleApiRoutes } from "./api/accessRuleApiRoutes.js";
|
|
5
|
-
import { accessRuleApiPaths, getExpressApiRuleRateLimits } from "./api/accessRuleApiRoutes.js";
|
|
6
|
-
import { deleteAllRulesEndpointSchema } from "./api/deleteAllRulesEndpoint.js";
|
|
7
|
-
import { deleteRulesEndpointSchema } from "./api/deleteRulesEndpoint.js";
|
|
8
|
-
import { insertRulesEndpointSchema } from "./api/insertRulesEndpoint.js";
|
|
9
|
-
import { createRedisAccessRulesStorage } from "./redis/redisRulesStorage.js";
|
|
10
|
-
import { redisAccessRulesIndex } from "./redis/redisRulesIndex.js";
|
|
11
|
-
import { AccessRulesApiClient } from "./api/accessRulesApiClient.js";
|
|
12
|
-
const createApiRuleRoutesProvider = (rulesStorage) => {
|
|
13
|
-
return new AccessRuleApiRoutes(rulesStorage);
|
|
14
|
-
};
|
|
15
|
-
export {
|
|
16
|
-
AccessPolicyType,
|
|
17
|
-
AccessRulesApiClient,
|
|
18
|
-
ScopeMatch,
|
|
19
|
-
accessPolicySchema,
|
|
20
|
-
accessRuleApiPaths,
|
|
21
|
-
accessRuleSchema,
|
|
22
|
-
accessRuleSchemaExtended,
|
|
23
|
-
createApiRuleRoutesProvider,
|
|
24
|
-
createRedisAccessRulesStorage,
|
|
25
|
-
deleteAllRulesEndpointSchema,
|
|
26
|
-
deleteRulesEndpointSchema,
|
|
27
|
-
getExpressApiRuleRateLimits,
|
|
28
|
-
insertRulesEndpointSchema,
|
|
29
|
-
policyScopeSchema,
|
|
30
|
-
redisAccessRulesIndex,
|
|
31
|
-
userScopeInputSchema
|
|
32
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { SCHEMA_FIELD_TYPE } from "@redis/search";
|
|
2
|
-
import { userScopeSchema } from "../accessPolicy.js";
|
|
3
|
-
import { ScopeMatch } from "../accessPolicyResolver.js";
|
|
4
|
-
const redisRulesIndexName = "index:user-access-rules";
|
|
5
|
-
const redisRuleKeyPrefix = "uar:";
|
|
6
|
-
const redisAccessRulesIndex = {
|
|
7
|
-
name: redisRulesIndexName,
|
|
8
|
-
/**
|
|
9
|
-
* Note on the field type decision
|
|
10
|
-
*
|
|
11
|
-
* TAG is designed for the exact value matching
|
|
12
|
-
* TEXT is designed for the word-based and pattern matching
|
|
13
|
-
*
|
|
14
|
-
* For our goal TAG fits perfectly and, more performant
|
|
15
|
-
*/
|
|
16
|
-
schema: {
|
|
17
|
-
clientId: {
|
|
18
|
-
type: SCHEMA_FIELD_TYPE.TAG,
|
|
19
|
-
// necessary to make possible use of the ismissing() function on this field in the search
|
|
20
|
-
INDEXMISSING: true
|
|
21
|
-
},
|
|
22
|
-
numericIpMaskMin: { type: SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
|
|
23
|
-
numericIpMaskMax: { type: SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
|
|
24
|
-
userId: { type: SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
|
|
25
|
-
numericIp: { type: SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
|
|
26
|
-
ja4Hash: { type: SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
|
|
27
|
-
headersHash: { type: SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
|
|
28
|
-
userAgentHash: { type: SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true }
|
|
29
|
-
},
|
|
30
|
-
// the satisfy statement is to guarantee that the keys are right
|
|
31
|
-
options: {
|
|
32
|
-
ON: "HASH",
|
|
33
|
-
PREFIX: [redisRuleKeyPrefix]
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
const numericIndexFields = [
|
|
37
|
-
"numericIp",
|
|
38
|
-
"numericIpMaskMin",
|
|
39
|
-
"numericIpMaskMax"
|
|
40
|
-
];
|
|
41
|
-
const greedyFieldComparisons = {
|
|
42
|
-
numericIp: (value, scope) => {
|
|
43
|
-
if (value !== void 0) {
|
|
44
|
-
return `( @numericIp:[${value}] | ( @numericIpMaskMin:[-inf ${value}] @numericIpMaskMax:[${value} +inf] ) )`;
|
|
45
|
-
}
|
|
46
|
-
if (scope.numericIpMaskMin === void 0 && scope.numericIpMaskMax === void 0) {
|
|
47
|
-
return "ismissing(@numericIp) ismissing(@numericIpMaskMin) ismissing(@numericIpMaskMax)";
|
|
48
|
-
}
|
|
49
|
-
return "";
|
|
50
|
-
},
|
|
51
|
-
numericIpMaskMin: (value, scope) => {
|
|
52
|
-
if (scope.numericIp !== void 0) {
|
|
53
|
-
return "";
|
|
54
|
-
}
|
|
55
|
-
return value !== void 0 ? `@numericIpMaskMin:[-inf ${value}]` : "ismissing(@numericIpMaskMin)";
|
|
56
|
-
},
|
|
57
|
-
numericIpMaskMax: (value, scope) => {
|
|
58
|
-
if (scope.numericIp !== void 0) {
|
|
59
|
-
return "";
|
|
60
|
-
}
|
|
61
|
-
return value !== void 0 ? `@numericIpMaskMax:[${value} +inf]` : "ismissing(@numericIpMaskMax)";
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
const redisRulesSearchOptions = {
|
|
65
|
-
// #2 is a required option when the 'ismissing()' function is in the query body
|
|
66
|
-
DIALECT: 2
|
|
67
|
-
};
|
|
68
|
-
const getRedisRulesQuery = (filter, matchingFieldsOnly) => {
|
|
69
|
-
const { policyScope, userScope } = filter;
|
|
70
|
-
const policyScopeFilter = getPolicyScopeQuery(
|
|
71
|
-
policyScope,
|
|
72
|
-
filter.policyScopeMatch
|
|
73
|
-
);
|
|
74
|
-
if (userScope && Object.keys(userScope).length > 0) {
|
|
75
|
-
const userScopeFilter = getUserScopeQuery(
|
|
76
|
-
userScope,
|
|
77
|
-
filter.userScopeMatch,
|
|
78
|
-
matchingFieldsOnly
|
|
79
|
-
);
|
|
80
|
-
return `${policyScopeFilter} ( ${userScopeFilter} )`;
|
|
81
|
-
}
|
|
82
|
-
return policyScopeFilter ? policyScopeFilter : "*";
|
|
83
|
-
};
|
|
84
|
-
const getPolicyScopeQuery = (policyScope, scopeMatchType) => {
|
|
85
|
-
const clientId = policyScope?.clientId;
|
|
86
|
-
if ("string" === typeof clientId) {
|
|
87
|
-
return ScopeMatch.Exact === scopeMatchType ? `@clientId:{${clientId}}` : `( @clientId:{${clientId}} | ismissing(@clientId) )`;
|
|
88
|
-
}
|
|
89
|
-
return ScopeMatch.Exact === scopeMatchType ? "ismissing(@clientId)" : "";
|
|
90
|
-
};
|
|
91
|
-
const getUserScopeQuery = (userScope, scopeMatchType, matchingFieldsOnly) => {
|
|
92
|
-
let scopeEntries = Object.entries(userScope);
|
|
93
|
-
let scopeJoinType = " ";
|
|
94
|
-
if (scopeMatchType === ScopeMatch.Greedy) {
|
|
95
|
-
scopeEntries = scopeEntries.filter(
|
|
96
|
-
([_, value]) => value !== void 0
|
|
97
|
-
);
|
|
98
|
-
scopeJoinType = " | ";
|
|
99
|
-
}
|
|
100
|
-
if (matchingFieldsOnly) {
|
|
101
|
-
const scopeMap = new Map(scopeEntries);
|
|
102
|
-
if (scopeMap.has("numericIp") && scopeMap.get("numericIp") === void 0) {
|
|
103
|
-
scopeMap.set("numericIpMaskMin", void 0);
|
|
104
|
-
scopeMap.set("numericIpMaskMax", void 0);
|
|
105
|
-
}
|
|
106
|
-
for (const name of Object.keys(userScopeSchema.shape)) {
|
|
107
|
-
if (!scopeMap.has(name)) {
|
|
108
|
-
scopeMap.set(name, void 0);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
scopeEntries = [...scopeMap.entries()];
|
|
112
|
-
}
|
|
113
|
-
const scopeObj = Object.fromEntries(scopeEntries);
|
|
114
|
-
return scopeEntries.map(
|
|
115
|
-
([scopeFieldName, scopeFieldValue]) => getUserScopeFieldQuery(
|
|
116
|
-
scopeFieldName,
|
|
117
|
-
scopeFieldValue,
|
|
118
|
-
scopeMatchType,
|
|
119
|
-
scopeObj
|
|
120
|
-
)
|
|
121
|
-
).filter(Boolean).join(scopeJoinType);
|
|
122
|
-
};
|
|
123
|
-
const getUserScopeFieldQuery = (fieldName, fieldValue, matchType, fullScope) => {
|
|
124
|
-
if ("function" === typeof greedyFieldComparisons[fieldName]) {
|
|
125
|
-
return greedyFieldComparisons[fieldName](fieldValue, fullScope);
|
|
126
|
-
}
|
|
127
|
-
if (fieldValue === void 0) {
|
|
128
|
-
return `ismissing(@${fieldName})`;
|
|
129
|
-
}
|
|
130
|
-
return numericIndexFields.includes(fieldName) ? `@${fieldName}:[${fieldValue}]` : `@${fieldName}:{${fieldValue}}`;
|
|
131
|
-
};
|
|
132
|
-
export {
|
|
133
|
-
getRedisRulesQuery,
|
|
134
|
-
redisAccessRulesIndex,
|
|
135
|
-
redisRuleKeyPrefix,
|
|
136
|
-
redisRulesIndexName,
|
|
137
|
-
redisRulesSearchOptions
|
|
138
|
-
};
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import * as util from "node:util";
|
|
2
|
-
import { accessRuleSchema } from "../accessRules.js";
|
|
3
|
-
import { getRedisRulesQuery, redisRulesIndexName, redisRulesSearchOptions } from "./redisRulesIndex.js";
|
|
4
|
-
const createRedisRulesReader = (client, logger) => {
|
|
5
|
-
return {
|
|
6
|
-
findRules: async (filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) => {
|
|
7
|
-
const query = getRedisRulesQuery(filter, matchingFieldsOnly);
|
|
8
|
-
if (skipEmptyUserScopes && query === "ismissing(@clientId)") {
|
|
9
|
-
return [];
|
|
10
|
-
}
|
|
11
|
-
let searchReply;
|
|
12
|
-
try {
|
|
13
|
-
searchReply = await client.ft.search(
|
|
14
|
-
redisRulesIndexName,
|
|
15
|
-
query,
|
|
16
|
-
redisRulesSearchOptions
|
|
17
|
-
);
|
|
18
|
-
if (searchReply.total > 0) {
|
|
19
|
-
logger.debug(() => ({
|
|
20
|
-
msg: "Executed search query",
|
|
21
|
-
data: {
|
|
22
|
-
inspect: util.inspect(
|
|
23
|
-
{
|
|
24
|
-
filter,
|
|
25
|
-
searchReply,
|
|
26
|
-
query
|
|
27
|
-
},
|
|
28
|
-
{ depth: null }
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
}));
|
|
32
|
-
}
|
|
33
|
-
} catch (e) {
|
|
34
|
-
logger.error(() => ({
|
|
35
|
-
err: e,
|
|
36
|
-
data: {
|
|
37
|
-
inspect: util.inspect(
|
|
38
|
-
{
|
|
39
|
-
query,
|
|
40
|
-
filter
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
depth: null
|
|
44
|
-
}
|
|
45
|
-
)
|
|
46
|
-
},
|
|
47
|
-
msg: "failed to execute search query"
|
|
48
|
-
}));
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
return extractRulesFromSearchReply(searchReply, logger);
|
|
52
|
-
},
|
|
53
|
-
findRuleIds: async (filter, matchingFieldsOnly = false) => {
|
|
54
|
-
const query = getRedisRulesQuery(filter, matchingFieldsOnly);
|
|
55
|
-
let searchReply;
|
|
56
|
-
try {
|
|
57
|
-
searchReply = await client.ft.searchNoContent(
|
|
58
|
-
redisRulesIndexName,
|
|
59
|
-
query,
|
|
60
|
-
redisRulesSearchOptions
|
|
61
|
-
);
|
|
62
|
-
} catch (e) {
|
|
63
|
-
logger.error(() => ({
|
|
64
|
-
err: e,
|
|
65
|
-
data: {
|
|
66
|
-
inspect: util.inspect(
|
|
67
|
-
{
|
|
68
|
-
query,
|
|
69
|
-
filter
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
depth: null
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
},
|
|
76
|
-
msg: "Failed to execute search query for rule IDs"
|
|
77
|
-
}));
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
return searchReply.documents;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
const getDummyRedisRulesReader = (logger) => {
|
|
85
|
-
return {
|
|
86
|
-
findRules: async (filter, matchingFieldsOnly = false, skipEmptyUserScopes = true) => {
|
|
87
|
-
logger.info(() => ({
|
|
88
|
-
msg: "Dummy findRules() has no effect (redis is not ready)",
|
|
89
|
-
data: {
|
|
90
|
-
filter
|
|
91
|
-
}
|
|
92
|
-
}));
|
|
93
|
-
return [];
|
|
94
|
-
},
|
|
95
|
-
findRuleIds: async (filter, matchingFieldsOnly = false) => {
|
|
96
|
-
logger.info(() => ({
|
|
97
|
-
msg: "Dummy findRuleIds() has no effect (redis is not ready)",
|
|
98
|
-
data: {
|
|
99
|
-
filter
|
|
100
|
-
}
|
|
101
|
-
}));
|
|
102
|
-
return [];
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
const extractRulesFromSearchReply = (searchReply, logger) => {
|
|
107
|
-
const accessRules = [];
|
|
108
|
-
searchReply.documents.map(({ id, value: document }) => {
|
|
109
|
-
const parsedDocument = accessRuleSchema.safeParse(document);
|
|
110
|
-
if (parsedDocument.success) {
|
|
111
|
-
accessRules.push(parsedDocument.data);
|
|
112
|
-
} else {
|
|
113
|
-
logger.debug(() => ({
|
|
114
|
-
msg: "Failed to parse access rule from search reply",
|
|
115
|
-
id,
|
|
116
|
-
error: parsedDocument.error
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
return accessRules;
|
|
121
|
-
};
|
|
122
|
-
export {
|
|
123
|
-
createRedisRulesReader,
|
|
124
|
-
getDummyRedisRulesReader
|
|
125
|
-
};
|