@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,62 +0,0 @@
|
|
|
1
|
-
import { ApiEndpointResponseStatus } from "@prosopo/api-route";
|
|
2
|
-
import { getLogger, LogLevel } from "@prosopo/common";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
import { userScopeInputSchema, policyScopeSchema, accessPolicySchema } from "../accessPolicy.js";
|
|
5
|
-
const insertRulesEndpointSchema = z.object({
|
|
6
|
-
accessPolicy: accessPolicySchema,
|
|
7
|
-
policyScope: policyScopeSchema.optional(),
|
|
8
|
-
userScopes: z.array(userScopeInputSchema),
|
|
9
|
-
expirationTimestamp: z.number().optional().transform((val) => val !== void 0 ? Math.floor(val) : val)
|
|
10
|
-
});
|
|
11
|
-
class InsertRulesEndpoint {
|
|
12
|
-
constructor(accessRulesWriter) {
|
|
13
|
-
this.accessRulesWriter = accessRulesWriter;
|
|
14
|
-
}
|
|
15
|
-
async processRequest(args, logger) {
|
|
16
|
-
logger = logger || getLogger(LogLevel.enum.info, "InsertRulesEndpoint");
|
|
17
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
18
|
-
setTimeout(() => {
|
|
19
|
-
resolve({
|
|
20
|
-
status: ApiEndpointResponseStatus.PROCESSING
|
|
21
|
-
});
|
|
22
|
-
}, 5e3);
|
|
23
|
-
});
|
|
24
|
-
const createRulesPromise = this.createRules(args).then(() => ({
|
|
25
|
-
status: ApiEndpointResponseStatus.SUCCESS
|
|
26
|
-
})).catch((error) => {
|
|
27
|
-
if (logger?.getLogLevel() === LogLevel.enum.debug) {
|
|
28
|
-
logger.error(() => ({
|
|
29
|
-
err: error,
|
|
30
|
-
data: { args },
|
|
31
|
-
msg: "Failed to insert access rules"
|
|
32
|
-
}));
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
status: ApiEndpointResponseStatus.FAIL
|
|
36
|
-
};
|
|
37
|
-
});
|
|
38
|
-
return Promise.race([timeoutPromise, createRulesPromise]);
|
|
39
|
-
}
|
|
40
|
-
getRequestArgsSchema() {
|
|
41
|
-
return insertRulesEndpointSchema;
|
|
42
|
-
}
|
|
43
|
-
async createRules(args) {
|
|
44
|
-
const policyScope = args.policyScope || {};
|
|
45
|
-
const createPromises = [];
|
|
46
|
-
for (const userScope of args.userScopes) {
|
|
47
|
-
const rule = {
|
|
48
|
-
...args.accessPolicy,
|
|
49
|
-
...policyScope,
|
|
50
|
-
...userScope
|
|
51
|
-
};
|
|
52
|
-
createPromises.push(
|
|
53
|
-
this.accessRulesWriter.insertRule(rule, args.expirationTimestamp)
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
return Promise.all(createPromises);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
export {
|
|
60
|
-
InsertRulesEndpoint,
|
|
61
|
-
insertRulesEndpointSchema
|
|
62
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const types = require("@prosopo/types");
|
|
4
|
-
const util = require("@prosopo/util");
|
|
5
|
-
const ipAddress = require("ip-address");
|
|
6
|
-
const zod = require("zod");
|
|
7
|
-
const util$1 = require("./util.cjs");
|
|
8
|
-
var AccessPolicyType = /* @__PURE__ */ ((AccessPolicyType2) => {
|
|
9
|
-
AccessPolicyType2["Block"] = "block";
|
|
10
|
-
AccessPolicyType2["Restrict"] = "restrict";
|
|
11
|
-
return AccessPolicyType2;
|
|
12
|
-
})(AccessPolicyType || {});
|
|
13
|
-
const accessPolicySchema = zod.z.object({
|
|
14
|
-
type: zod.z.nativeEnum(AccessPolicyType),
|
|
15
|
-
captchaType: types.CaptchaTypeSchema.optional(),
|
|
16
|
-
description: zod.z.coerce.string().optional(),
|
|
17
|
-
// Redis stores values as strings, so coerce is needed to parse properly
|
|
18
|
-
solvedImagesCount: zod.z.coerce.number().optional(),
|
|
19
|
-
// the percentage of image panels that must be solved per image CAPTCHA
|
|
20
|
-
imageThreshold: zod.z.coerce.number().optional(),
|
|
21
|
-
// the Proof-of-Work difficulty level
|
|
22
|
-
powDifficulty: zod.z.coerce.number().optional(),
|
|
23
|
-
// the number of unsolved image CAPTCHA challenges to serve
|
|
24
|
-
unsolvedImagesCount: zod.z.coerce.number().optional(),
|
|
25
|
-
// used to increase the user's score
|
|
26
|
-
frictionlessScore: zod.z.coerce.number().optional()
|
|
27
|
-
});
|
|
28
|
-
const policyScopeSchema = zod.z.object({
|
|
29
|
-
clientId: zod.z.coerce.string().optional(),
|
|
30
|
-
ruleGroupId: zod.z.coerce.string().optional()
|
|
31
|
-
});
|
|
32
|
-
const userScopeSchema = zod.z.object({
|
|
33
|
-
// coerce is used for safety, as e.g., incoming userId can be digital
|
|
34
|
-
userId: zod.z.coerce.string().optional(),
|
|
35
|
-
numericIp: zod.z.coerce.bigint().optional(),
|
|
36
|
-
numericIpMaskMin: zod.z.coerce.bigint().optional(),
|
|
37
|
-
numericIpMaskMax: zod.z.coerce.bigint().optional(),
|
|
38
|
-
ja4Hash: zod.z.coerce.string().optional(),
|
|
39
|
-
headersHash: zod.z.coerce.string().optional(),
|
|
40
|
-
userAgentHash: zod.z.coerce.string().optional()
|
|
41
|
-
});
|
|
42
|
-
const userScopeInputSchema = userScopeSchema.extend({
|
|
43
|
-
// human-friendly ip versions. If present, then converted to numeric and removed from the object
|
|
44
|
-
// 127.0.0.1
|
|
45
|
-
ip: zod.z.string().optional(),
|
|
46
|
-
// 127.0.0.1/24
|
|
47
|
-
ipMask: zod.z.string().optional(),
|
|
48
|
-
// human friendly user agent
|
|
49
|
-
userAgent: zod.z.string().optional()
|
|
50
|
-
}).transform((inputUserScope) => {
|
|
51
|
-
const { ip, ipMask, userAgent, ...userScope } = inputUserScope;
|
|
52
|
-
if ("string" === typeof ip) {
|
|
53
|
-
userScope.numericIp = util.getIPAddress(ip).bigInt();
|
|
54
|
-
}
|
|
55
|
-
if ("string" === typeof ipMask) {
|
|
56
|
-
const ipObject = new ipAddress.Address4(ipMask);
|
|
57
|
-
userScope.numericIpMaskMin = ipObject.startAddress().bigInt();
|
|
58
|
-
userScope.numericIpMaskMax = ipObject.endAddress().bigInt();
|
|
59
|
-
}
|
|
60
|
-
if ("string" === typeof userAgent) {
|
|
61
|
-
userScope.userAgentHash = util$1.hashUserAgent(userAgent);
|
|
62
|
-
}
|
|
63
|
-
return userScope;
|
|
64
|
-
});
|
|
65
|
-
const accessRuleSchemaExtended = zod.z.object({
|
|
66
|
-
// flat structure is used to fit the Redis requirements
|
|
67
|
-
...accessPolicySchema.shape,
|
|
68
|
-
...policyScopeSchema.shape,
|
|
69
|
-
...userScopeInputSchema._def.schema.shape
|
|
70
|
-
}).omit({
|
|
71
|
-
numericIp: true,
|
|
72
|
-
numericIpMaskMin: true,
|
|
73
|
-
numericIpMaskMax: true
|
|
74
|
-
});
|
|
75
|
-
exports.AccessPolicyType = AccessPolicyType;
|
|
76
|
-
exports.accessPolicySchema = accessPolicySchema;
|
|
77
|
-
exports.accessRuleSchemaExtended = accessRuleSchemaExtended;
|
|
78
|
-
exports.policyScopeSchema = policyScopeSchema;
|
|
79
|
-
exports.userScopeInputSchema = userScopeInputSchema;
|
|
80
|
-
exports.userScopeSchema = userScopeSchema;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const zod = require("zod");
|
|
4
|
-
const accessPolicy = require("./accessPolicy.cjs");
|
|
5
|
-
var ScopeMatch = /* @__PURE__ */ ((ScopeMatch2) => {
|
|
6
|
-
ScopeMatch2["Exact"] = "exact";
|
|
7
|
-
ScopeMatch2["Greedy"] = "greedy";
|
|
8
|
-
return ScopeMatch2;
|
|
9
|
-
})(ScopeMatch || {});
|
|
10
|
-
const policyFilterSchema = zod.z.object({
|
|
11
|
-
policyScope: accessPolicy.policyScopeSchema.optional(),
|
|
12
|
-
/**
|
|
13
|
-
* Exact: "clientId" => client rules, "undefined" => global rules. Used by the API
|
|
14
|
-
* Greedy: "clientId" => client + global rules, "undefined" => any rules. Used by the Express middleware
|
|
15
|
-
*/
|
|
16
|
-
policyScopeMatch: zod.z.nativeEnum(ScopeMatch).default(
|
|
17
|
-
"exact"
|
|
18
|
-
/* Exact */
|
|
19
|
-
),
|
|
20
|
-
userScope: accessPolicy.userScopeInputSchema.optional(),
|
|
21
|
-
/**
|
|
22
|
-
* Exact: finds rules where all the given fields matches and doesn't check IP against masks. Used by the API
|
|
23
|
-
* Greedy: finds rules where any of the given fields match and checks IP against masks. Used by the Express middleware
|
|
24
|
-
*/
|
|
25
|
-
userScopeMatch: zod.z.nativeEnum(ScopeMatch).default(
|
|
26
|
-
"exact"
|
|
27
|
-
/* Exact */
|
|
28
|
-
)
|
|
29
|
-
});
|
|
30
|
-
exports.ScopeMatch = ScopeMatch;
|
|
31
|
-
exports.policyFilterSchema = policyFilterSchema;
|
package/dist/cjs/accessRules.cjs
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const zod = require("zod");
|
|
4
|
-
const accessPolicy = require("./accessPolicy.cjs");
|
|
5
|
-
const accessRuleSchema = zod.z.object({
|
|
6
|
-
// flat structure is used to fit the Redis requirements
|
|
7
|
-
...accessPolicy.accessPolicySchema.shape,
|
|
8
|
-
...accessPolicy.policyScopeSchema.shape,
|
|
9
|
-
...accessPolicy.userScopeSchema.shape
|
|
10
|
-
});
|
|
11
|
-
exports.accessRuleSchema = accessRuleSchema;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const deleteAllRulesEndpoint = require("./deleteAllRulesEndpoint.cjs");
|
|
4
|
-
const deleteRulesEndpoint = require("./deleteRulesEndpoint.cjs");
|
|
5
|
-
const insertRulesEndpoint = require("./insertRulesEndpoint.cjs");
|
|
6
|
-
var accessRuleApiPaths = /* @__PURE__ */ ((accessRuleApiPaths2) => {
|
|
7
|
-
accessRuleApiPaths2["INSERT_MANY"] = "/v1/prosopo/user-access-policy/rules/insert-many";
|
|
8
|
-
accessRuleApiPaths2["DELETE_MANY"] = "/v1/prosopo/user-access-policy/rules/delete-many";
|
|
9
|
-
accessRuleApiPaths2["DELETE_ALL"] = "/v1/prosopo/user-access-policy/rules/delete-all";
|
|
10
|
-
return accessRuleApiPaths2;
|
|
11
|
-
})(accessRuleApiPaths || {});
|
|
12
|
-
class AccessRuleApiRoutes {
|
|
13
|
-
constructor(accessRulesStorage) {
|
|
14
|
-
this.accessRulesStorage = accessRulesStorage;
|
|
15
|
-
}
|
|
16
|
-
getRoutes() {
|
|
17
|
-
return [
|
|
18
|
-
{
|
|
19
|
-
path: "/v1/prosopo/user-access-policy/rules/insert-many",
|
|
20
|
-
endpoint: new insertRulesEndpoint.InsertRulesEndpoint(this.accessRulesStorage)
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
path: "/v1/prosopo/user-access-policy/rules/delete-many",
|
|
24
|
-
endpoint: new deleteRulesEndpoint.DeleteRulesEndpoint(this.accessRulesStorage)
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
path: "/v1/prosopo/user-access-policy/rules/delete-all",
|
|
28
|
-
endpoint: new deleteAllRulesEndpoint.DeleteAllRulesEndpoint(this.accessRulesStorage)
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const getExpressApiRuleRateLimits = () => {
|
|
34
|
-
const defaultWindowsMs = 6e4;
|
|
35
|
-
const defaultLimit = 5;
|
|
36
|
-
return {
|
|
37
|
-
[
|
|
38
|
-
"/v1/prosopo/user-access-policy/rules/insert-many"
|
|
39
|
-
/* INSERT_MANY */
|
|
40
|
-
]: {
|
|
41
|
-
windowMs: getIntEnvironmentVariable(
|
|
42
|
-
"PROSOPO_USER_ACCESS_POLICY_RULE_INSERT_MANY_WINDOW"
|
|
43
|
-
) || defaultWindowsMs,
|
|
44
|
-
limit: getIntEnvironmentVariable(
|
|
45
|
-
"PROSOPO_USER_ACCESS_POLICY_RULE_INSERT_MANY_LIMIT"
|
|
46
|
-
) || defaultLimit
|
|
47
|
-
},
|
|
48
|
-
[
|
|
49
|
-
"/v1/prosopo/user-access-policy/rules/delete-many"
|
|
50
|
-
/* DELETE_MANY */
|
|
51
|
-
]: {
|
|
52
|
-
windowMs: getIntEnvironmentVariable(
|
|
53
|
-
"PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_MANY_WINDOW"
|
|
54
|
-
) || defaultWindowsMs,
|
|
55
|
-
limit: getIntEnvironmentVariable(
|
|
56
|
-
"PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_MANY_LIMIT"
|
|
57
|
-
) || defaultLimit
|
|
58
|
-
},
|
|
59
|
-
[
|
|
60
|
-
"/v1/prosopo/user-access-policy/rules/delete-all"
|
|
61
|
-
/* DELETE_ALL */
|
|
62
|
-
]: {
|
|
63
|
-
windowMs: getIntEnvironmentVariable(
|
|
64
|
-
"PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_ALL_WINDOW"
|
|
65
|
-
) || defaultWindowsMs,
|
|
66
|
-
limit: getIntEnvironmentVariable(
|
|
67
|
-
"PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_ALL_LIMIT"
|
|
68
|
-
) || defaultLimit
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
const getIntEnvironmentVariable = (variableName) => {
|
|
73
|
-
const variableValue = process.env[variableName];
|
|
74
|
-
const numericValue = variableValue ? Number.parseInt(variableValue) : Number.NaN;
|
|
75
|
-
return Number.isInteger(numericValue) ? numericValue : void 0;
|
|
76
|
-
};
|
|
77
|
-
exports.AccessRuleApiRoutes = AccessRuleApiRoutes;
|
|
78
|
-
exports.accessRuleApiPaths = accessRuleApiPaths;
|
|
79
|
-
exports.getExpressApiRuleRateLimits = getExpressApiRuleRateLimits;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const api = require("@prosopo/api");
|
|
4
|
-
const accessRuleApiRoutes = require("./accessRuleApiRoutes.cjs");
|
|
5
|
-
class AccessRulesApiClient extends api.ApiClient {
|
|
6
|
-
insertMany(toInsert, timestamp, signature) {
|
|
7
|
-
return this.post(accessRuleApiRoutes.accessRuleApiPaths.INSERT_MANY, toInsert, {
|
|
8
|
-
headers: {
|
|
9
|
-
"Prosopo-Site-Key": this.account,
|
|
10
|
-
timestamp,
|
|
11
|
-
signature
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
deleteMany(toDelete, timestamp, signature) {
|
|
16
|
-
return this.post(accessRuleApiRoutes.accessRuleApiPaths.DELETE_MANY, toDelete, {
|
|
17
|
-
headers: {
|
|
18
|
-
"Prosopo-Site-Key": this.account,
|
|
19
|
-
timestamp,
|
|
20
|
-
signature
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
deleteAll(timestamp, signature) {
|
|
25
|
-
return this.post(
|
|
26
|
-
accessRuleApiRoutes.accessRuleApiPaths.DELETE_ALL,
|
|
27
|
-
{},
|
|
28
|
-
{
|
|
29
|
-
headers: {
|
|
30
|
-
"Prosopo-Site-Key": this.account,
|
|
31
|
-
timestamp,
|
|
32
|
-
signature
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
exports.AccessRulesApiClient = AccessRulesApiClient;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const apiRoute = require("@prosopo/api-route");
|
|
4
|
-
const zod = require("zod");
|
|
5
|
-
const accessPolicyResolver = require("../accessPolicyResolver.cjs");
|
|
6
|
-
const deleteRulesEndpointSchema = zod.z.array(accessPolicyResolver.policyFilterSchema);
|
|
7
|
-
class DeleteRulesEndpoint {
|
|
8
|
-
constructor(accessRulesStorage) {
|
|
9
|
-
this.accessRulesStorage = accessRulesStorage;
|
|
10
|
-
}
|
|
11
|
-
async processRequest(args) {
|
|
12
|
-
const allRuleIds = [];
|
|
13
|
-
for (const accessRuleFilter of args) {
|
|
14
|
-
const parsedRules = accessPolicyResolver.policyFilterSchema.parse(accessRuleFilter);
|
|
15
|
-
const foundRuleIds = await this.accessRulesStorage.findRuleIds(parsedRules);
|
|
16
|
-
allRuleIds.push(...foundRuleIds);
|
|
17
|
-
}
|
|
18
|
-
const uniqueRuleIds = [...new Set(allRuleIds)];
|
|
19
|
-
if (uniqueRuleIds.length > 0) {
|
|
20
|
-
await this.accessRulesStorage.deleteRules(uniqueRuleIds);
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
status: apiRoute.ApiEndpointResponseStatus.SUCCESS,
|
|
24
|
-
data: {
|
|
25
|
-
deleted_count: uniqueRuleIds.length
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
getRequestArgsSchema() {
|
|
30
|
-
return deleteRulesEndpointSchema;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.DeleteRulesEndpoint = DeleteRulesEndpoint;
|
|
34
|
-
exports.deleteRulesEndpointSchema = deleteRulesEndpointSchema;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const apiRoute = require("@prosopo/api-route");
|
|
4
|
-
const common = require("@prosopo/common");
|
|
5
|
-
const zod = require("zod");
|
|
6
|
-
const accessPolicy = require("../accessPolicy.cjs");
|
|
7
|
-
const insertRulesEndpointSchema = zod.z.object({
|
|
8
|
-
accessPolicy: accessPolicy.accessPolicySchema,
|
|
9
|
-
policyScope: accessPolicy.policyScopeSchema.optional(),
|
|
10
|
-
userScopes: zod.z.array(accessPolicy.userScopeInputSchema),
|
|
11
|
-
expirationTimestamp: zod.z.number().optional().transform((val) => val !== void 0 ? Math.floor(val) : val)
|
|
12
|
-
});
|
|
13
|
-
class InsertRulesEndpoint {
|
|
14
|
-
constructor(accessRulesWriter) {
|
|
15
|
-
this.accessRulesWriter = accessRulesWriter;
|
|
16
|
-
}
|
|
17
|
-
async processRequest(args, logger) {
|
|
18
|
-
logger = logger || common.getLogger(common.LogLevel.enum.info, "InsertRulesEndpoint");
|
|
19
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
20
|
-
setTimeout(() => {
|
|
21
|
-
resolve({
|
|
22
|
-
status: apiRoute.ApiEndpointResponseStatus.PROCESSING
|
|
23
|
-
});
|
|
24
|
-
}, 5e3);
|
|
25
|
-
});
|
|
26
|
-
const createRulesPromise = this.createRules(args).then(() => ({
|
|
27
|
-
status: apiRoute.ApiEndpointResponseStatus.SUCCESS
|
|
28
|
-
})).catch((error) => {
|
|
29
|
-
if (logger?.getLogLevel() === common.LogLevel.enum.debug) {
|
|
30
|
-
logger.error(() => ({
|
|
31
|
-
err: error,
|
|
32
|
-
data: { args },
|
|
33
|
-
msg: "Failed to insert access rules"
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
status: apiRoute.ApiEndpointResponseStatus.FAIL
|
|
38
|
-
};
|
|
39
|
-
});
|
|
40
|
-
return Promise.race([timeoutPromise, createRulesPromise]);
|
|
41
|
-
}
|
|
42
|
-
getRequestArgsSchema() {
|
|
43
|
-
return insertRulesEndpointSchema;
|
|
44
|
-
}
|
|
45
|
-
async createRules(args) {
|
|
46
|
-
const policyScope = args.policyScope || {};
|
|
47
|
-
const createPromises = [];
|
|
48
|
-
for (const userScope of args.userScopes) {
|
|
49
|
-
const rule = {
|
|
50
|
-
...args.accessPolicy,
|
|
51
|
-
...policyScope,
|
|
52
|
-
...userScope
|
|
53
|
-
};
|
|
54
|
-
createPromises.push(
|
|
55
|
-
this.accessRulesWriter.insertRule(rule, args.expirationTimestamp)
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
return Promise.all(createPromises);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
exports.InsertRulesEndpoint = InsertRulesEndpoint;
|
|
62
|
-
exports.insertRulesEndpointSchema = insertRulesEndpointSchema;
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const accessPolicy = require("./accessPolicy.cjs");
|
|
4
|
-
const accessPolicyResolver = require("./accessPolicyResolver.cjs");
|
|
5
|
-
const accessRules = require("./accessRules.cjs");
|
|
6
|
-
const accessRuleApiRoutes = require("./api/accessRuleApiRoutes.cjs");
|
|
7
|
-
const deleteAllRulesEndpoint = require("./api/deleteAllRulesEndpoint.cjs");
|
|
8
|
-
const deleteRulesEndpoint = require("./api/deleteRulesEndpoint.cjs");
|
|
9
|
-
const insertRulesEndpoint = require("./api/insertRulesEndpoint.cjs");
|
|
10
|
-
const redisRulesStorage = require("./redis/redisRulesStorage.cjs");
|
|
11
|
-
const redisRulesIndex = require("./redis/redisRulesIndex.cjs");
|
|
12
|
-
const accessRulesApiClient = require("./api/accessRulesApiClient.cjs");
|
|
13
|
-
const createApiRuleRoutesProvider = (rulesStorage) => {
|
|
14
|
-
return new accessRuleApiRoutes.AccessRuleApiRoutes(rulesStorage);
|
|
15
|
-
};
|
|
16
|
-
exports.AccessPolicyType = accessPolicy.AccessPolicyType;
|
|
17
|
-
exports.accessPolicySchema = accessPolicy.accessPolicySchema;
|
|
18
|
-
exports.accessRuleSchemaExtended = accessPolicy.accessRuleSchemaExtended;
|
|
19
|
-
exports.policyScopeSchema = accessPolicy.policyScopeSchema;
|
|
20
|
-
exports.userScopeInputSchema = accessPolicy.userScopeInputSchema;
|
|
21
|
-
exports.ScopeMatch = accessPolicyResolver.ScopeMatch;
|
|
22
|
-
exports.accessRuleSchema = accessRules.accessRuleSchema;
|
|
23
|
-
exports.accessRuleApiPaths = accessRuleApiRoutes.accessRuleApiPaths;
|
|
24
|
-
exports.getExpressApiRuleRateLimits = accessRuleApiRoutes.getExpressApiRuleRateLimits;
|
|
25
|
-
exports.deleteAllRulesEndpointSchema = deleteAllRulesEndpoint.deleteAllRulesEndpointSchema;
|
|
26
|
-
exports.deleteRulesEndpointSchema = deleteRulesEndpoint.deleteRulesEndpointSchema;
|
|
27
|
-
exports.insertRulesEndpointSchema = insertRulesEndpoint.insertRulesEndpointSchema;
|
|
28
|
-
exports.createRedisAccessRulesStorage = redisRulesStorage.createRedisAccessRulesStorage;
|
|
29
|
-
exports.redisAccessRulesIndex = redisRulesIndex.redisAccessRulesIndex;
|
|
30
|
-
exports.AccessRulesApiClient = accessRulesApiClient.AccessRulesApiClient;
|
|
31
|
-
exports.createApiRuleRoutesProvider = createApiRuleRoutesProvider;
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const search = require("@redis/search");
|
|
4
|
-
const accessPolicy = require("../accessPolicy.cjs");
|
|
5
|
-
const accessPolicyResolver = require("../accessPolicyResolver.cjs");
|
|
6
|
-
const redisRulesIndexName = "index:user-access-rules";
|
|
7
|
-
const redisRuleKeyPrefix = "uar:";
|
|
8
|
-
const redisAccessRulesIndex = {
|
|
9
|
-
name: redisRulesIndexName,
|
|
10
|
-
/**
|
|
11
|
-
* Note on the field type decision
|
|
12
|
-
*
|
|
13
|
-
* TAG is designed for the exact value matching
|
|
14
|
-
* TEXT is designed for the word-based and pattern matching
|
|
15
|
-
*
|
|
16
|
-
* For our goal TAG fits perfectly and, more performant
|
|
17
|
-
*/
|
|
18
|
-
schema: {
|
|
19
|
-
clientId: {
|
|
20
|
-
type: search.SCHEMA_FIELD_TYPE.TAG,
|
|
21
|
-
// necessary to make possible use of the ismissing() function on this field in the search
|
|
22
|
-
INDEXMISSING: true
|
|
23
|
-
},
|
|
24
|
-
numericIpMaskMin: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
|
|
25
|
-
numericIpMaskMax: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
|
|
26
|
-
userId: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
|
|
27
|
-
numericIp: { type: search.SCHEMA_FIELD_TYPE.NUMERIC, INDEXMISSING: true },
|
|
28
|
-
ja4Hash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
|
|
29
|
-
headersHash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true },
|
|
30
|
-
userAgentHash: { type: search.SCHEMA_FIELD_TYPE.TAG, INDEXMISSING: true }
|
|
31
|
-
},
|
|
32
|
-
// the satisfy statement is to guarantee that the keys are right
|
|
33
|
-
options: {
|
|
34
|
-
ON: "HASH",
|
|
35
|
-
PREFIX: [redisRuleKeyPrefix]
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
const numericIndexFields = [
|
|
39
|
-
"numericIp",
|
|
40
|
-
"numericIpMaskMin",
|
|
41
|
-
"numericIpMaskMax"
|
|
42
|
-
];
|
|
43
|
-
const greedyFieldComparisons = {
|
|
44
|
-
numericIp: (value, scope) => {
|
|
45
|
-
if (value !== void 0) {
|
|
46
|
-
return `( @numericIp:[${value}] | ( @numericIpMaskMin:[-inf ${value}] @numericIpMaskMax:[${value} +inf] ) )`;
|
|
47
|
-
}
|
|
48
|
-
if (scope.numericIpMaskMin === void 0 && scope.numericIpMaskMax === void 0) {
|
|
49
|
-
return "ismissing(@numericIp) ismissing(@numericIpMaskMin) ismissing(@numericIpMaskMax)";
|
|
50
|
-
}
|
|
51
|
-
return "";
|
|
52
|
-
},
|
|
53
|
-
numericIpMaskMin: (value, scope) => {
|
|
54
|
-
if (scope.numericIp !== void 0) {
|
|
55
|
-
return "";
|
|
56
|
-
}
|
|
57
|
-
return value !== void 0 ? `@numericIpMaskMin:[-inf ${value}]` : "ismissing(@numericIpMaskMin)";
|
|
58
|
-
},
|
|
59
|
-
numericIpMaskMax: (value, scope) => {
|
|
60
|
-
if (scope.numericIp !== void 0) {
|
|
61
|
-
return "";
|
|
62
|
-
}
|
|
63
|
-
return value !== void 0 ? `@numericIpMaskMax:[${value} +inf]` : "ismissing(@numericIpMaskMax)";
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const redisRulesSearchOptions = {
|
|
67
|
-
// #2 is a required option when the 'ismissing()' function is in the query body
|
|
68
|
-
DIALECT: 2
|
|
69
|
-
};
|
|
70
|
-
const getRedisRulesQuery = (filter, matchingFieldsOnly) => {
|
|
71
|
-
const { policyScope, userScope } = filter;
|
|
72
|
-
const policyScopeFilter = getPolicyScopeQuery(
|
|
73
|
-
policyScope,
|
|
74
|
-
filter.policyScopeMatch
|
|
75
|
-
);
|
|
76
|
-
if (userScope && Object.keys(userScope).length > 0) {
|
|
77
|
-
const userScopeFilter = getUserScopeQuery(
|
|
78
|
-
userScope,
|
|
79
|
-
filter.userScopeMatch,
|
|
80
|
-
matchingFieldsOnly
|
|
81
|
-
);
|
|
82
|
-
return `${policyScopeFilter} ( ${userScopeFilter} )`;
|
|
83
|
-
}
|
|
84
|
-
return policyScopeFilter ? policyScopeFilter : "*";
|
|
85
|
-
};
|
|
86
|
-
const getPolicyScopeQuery = (policyScope, scopeMatchType) => {
|
|
87
|
-
const clientId = policyScope?.clientId;
|
|
88
|
-
if ("string" === typeof clientId) {
|
|
89
|
-
return accessPolicyResolver.ScopeMatch.Exact === scopeMatchType ? `@clientId:{${clientId}}` : `( @clientId:{${clientId}} | ismissing(@clientId) )`;
|
|
90
|
-
}
|
|
91
|
-
return accessPolicyResolver.ScopeMatch.Exact === scopeMatchType ? "ismissing(@clientId)" : "";
|
|
92
|
-
};
|
|
93
|
-
const getUserScopeQuery = (userScope, scopeMatchType, matchingFieldsOnly) => {
|
|
94
|
-
let scopeEntries = Object.entries(userScope);
|
|
95
|
-
let scopeJoinType = " ";
|
|
96
|
-
if (scopeMatchType === accessPolicyResolver.ScopeMatch.Greedy) {
|
|
97
|
-
scopeEntries = scopeEntries.filter(
|
|
98
|
-
([_, value]) => value !== void 0
|
|
99
|
-
);
|
|
100
|
-
scopeJoinType = " | ";
|
|
101
|
-
}
|
|
102
|
-
if (matchingFieldsOnly) {
|
|
103
|
-
const scopeMap = new Map(scopeEntries);
|
|
104
|
-
if (scopeMap.has("numericIp") && scopeMap.get("numericIp") === void 0) {
|
|
105
|
-
scopeMap.set("numericIpMaskMin", void 0);
|
|
106
|
-
scopeMap.set("numericIpMaskMax", void 0);
|
|
107
|
-
}
|
|
108
|
-
for (const name of Object.keys(accessPolicy.userScopeSchema.shape)) {
|
|
109
|
-
if (!scopeMap.has(name)) {
|
|
110
|
-
scopeMap.set(name, void 0);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
scopeEntries = [...scopeMap.entries()];
|
|
114
|
-
}
|
|
115
|
-
const scopeObj = Object.fromEntries(scopeEntries);
|
|
116
|
-
return scopeEntries.map(
|
|
117
|
-
([scopeFieldName, scopeFieldValue]) => getUserScopeFieldQuery(
|
|
118
|
-
scopeFieldName,
|
|
119
|
-
scopeFieldValue,
|
|
120
|
-
scopeMatchType,
|
|
121
|
-
scopeObj
|
|
122
|
-
)
|
|
123
|
-
).filter(Boolean).join(scopeJoinType);
|
|
124
|
-
};
|
|
125
|
-
const getUserScopeFieldQuery = (fieldName, fieldValue, matchType, fullScope) => {
|
|
126
|
-
if ("function" === typeof greedyFieldComparisons[fieldName]) {
|
|
127
|
-
return greedyFieldComparisons[fieldName](fieldValue, fullScope);
|
|
128
|
-
}
|
|
129
|
-
if (fieldValue === void 0) {
|
|
130
|
-
return `ismissing(@${fieldName})`;
|
|
131
|
-
}
|
|
132
|
-
return numericIndexFields.includes(fieldName) ? `@${fieldName}:[${fieldValue}]` : `@${fieldName}:{${fieldValue}}`;
|
|
133
|
-
};
|
|
134
|
-
exports.getRedisRulesQuery = getRedisRulesQuery;
|
|
135
|
-
exports.redisAccessRulesIndex = redisAccessRulesIndex;
|
|
136
|
-
exports.redisRuleKeyPrefix = redisRuleKeyPrefix;
|
|
137
|
-
exports.redisRulesIndexName = redisRulesIndexName;
|
|
138
|
-
exports.redisRulesSearchOptions = redisRulesSearchOptions;
|