@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.
Files changed (93) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/dist/.export.js +21 -0
  3. package/dist/api/.export.js +11 -0
  4. package/dist/api/delete/.export.js +1 -0
  5. package/dist/api/{deleteAllRulesEndpoint.js → delete/deleteAllRules.js} +10 -9
  6. package/dist/api/delete/deleteRuleGroups.js +52 -0
  7. package/dist/api/delete/deleteRules.js +43 -0
  8. package/dist/api/read/.export.js +1 -0
  9. package/dist/api/read/fetchRules.js +43 -0
  10. package/dist/api/read/findRuleIds.js +50 -0
  11. package/dist/api/read/getMissingIds.js +41 -0
  12. package/dist/api/ruleApiRoutes.js +131 -0
  13. package/dist/api/rulesApiClient.js +93 -0
  14. package/dist/api/write/.export.js +1 -0
  15. package/dist/api/write/insertRules.js +102 -0
  16. package/dist/api/write/rehashRules.js +57 -0
  17. package/dist/cjs/.export.cjs +21 -0
  18. package/dist/cjs/api/.export.cjs +11 -0
  19. package/dist/cjs/api/delete/.export.cjs +1 -0
  20. package/dist/cjs/api/{deleteAllRulesEndpoint.cjs → delete/deleteAllRules.cjs} +9 -8
  21. package/dist/cjs/api/delete/deleteRuleGroups.cjs +52 -0
  22. package/dist/cjs/api/delete/deleteRules.cjs +43 -0
  23. package/dist/cjs/api/read/.export.cjs +1 -0
  24. package/dist/cjs/api/read/fetchRules.cjs +43 -0
  25. package/dist/cjs/api/read/findRuleIds.cjs +50 -0
  26. package/dist/cjs/api/read/getMissingIds.cjs +41 -0
  27. package/dist/cjs/api/ruleApiRoutes.cjs +131 -0
  28. package/dist/cjs/api/rulesApiClient.cjs +93 -0
  29. package/dist/cjs/api/write/.export.cjs +1 -0
  30. package/dist/cjs/api/write/insertRules.cjs +102 -0
  31. package/dist/cjs/api/write/rehashRules.cjs +57 -0
  32. package/dist/cjs/mongoose/.export.cjs +4 -0
  33. package/dist/cjs/mongoose/mongooseRuleSchema.cjs +36 -0
  34. package/dist/cjs/redis/.export.cjs +6 -0
  35. package/dist/cjs/redis/reader/redisAggregate.cjs +60 -0
  36. package/dist/cjs/redis/reader/redisRulesQuery.cjs +99 -0
  37. package/dist/cjs/redis/reader/redisRulesReader.cjs +230 -0
  38. package/dist/cjs/redis/redisClient.cjs +67 -0
  39. package/dist/cjs/redis/redisRuleIndex.cjs +50 -0
  40. package/dist/cjs/redis/redisRulesStorage.cjs +22 -9
  41. package/dist/cjs/redis/redisRulesWriter.cjs +91 -64
  42. package/dist/cjs/rule.cjs +8 -0
  43. package/dist/cjs/ruleInput/.export.cjs +9 -0
  44. package/dist/cjs/ruleInput/policyInput.cjs +25 -0
  45. package/dist/cjs/ruleInput/ruleInput.cjs +50 -0
  46. package/dist/cjs/ruleInput/userScopeInput.cjs +55 -0
  47. package/dist/cjs/ruleRecord.cjs +23 -0
  48. package/dist/cjs/rulesStorage.cjs +8 -0
  49. package/dist/cjs/transformRule.cjs +77 -0
  50. package/dist/mongoose/.export.js +4 -0
  51. package/dist/mongoose/mongooseRuleSchema.js +36 -0
  52. package/dist/redis/.export.js +6 -0
  53. package/dist/redis/reader/redisAggregate.js +60 -0
  54. package/dist/redis/reader/redisRulesQuery.js +99 -0
  55. package/dist/redis/reader/redisRulesReader.js +213 -0
  56. package/dist/redis/redisClient.js +67 -0
  57. package/dist/redis/redisRuleIndex.js +50 -0
  58. package/dist/redis/redisRulesStorage.js +23 -10
  59. package/dist/redis/redisRulesWriter.js +91 -64
  60. package/dist/rule.js +8 -0
  61. package/dist/ruleInput/.export.js +9 -0
  62. package/dist/ruleInput/policyInput.js +25 -0
  63. package/dist/ruleInput/ruleInput.js +50 -0
  64. package/dist/ruleInput/userScopeInput.js +55 -0
  65. package/dist/ruleRecord.js +23 -0
  66. package/dist/rulesStorage.js +8 -0
  67. package/dist/transformRule.js +77 -0
  68. package/entries.ts +20 -0
  69. package/package.json +34 -18
  70. package/vite.cjs.config.ts +4 -1
  71. package/vite.esm.config.ts +6 -1
  72. package/dist/accessPolicy.js +0 -80
  73. package/dist/accessPolicyResolver.js +0 -31
  74. package/dist/accessRules.js +0 -11
  75. package/dist/api/accessRuleApiRoutes.js +0 -79
  76. package/dist/api/accessRulesApiClient.js +0 -38
  77. package/dist/api/deleteRulesEndpoint.js +0 -34
  78. package/dist/api/insertRulesEndpoint.js +0 -62
  79. package/dist/cjs/accessPolicy.cjs +0 -80
  80. package/dist/cjs/accessPolicyResolver.cjs +0 -31
  81. package/dist/cjs/accessRules.cjs +0 -11
  82. package/dist/cjs/api/accessRuleApiRoutes.cjs +0 -79
  83. package/dist/cjs/api/accessRulesApiClient.cjs +0 -38
  84. package/dist/cjs/api/deleteRulesEndpoint.cjs +0 -34
  85. package/dist/cjs/api/insertRulesEndpoint.cjs +0 -62
  86. package/dist/cjs/index.cjs +0 -31
  87. package/dist/cjs/redis/redisRulesIndex.cjs +0 -138
  88. package/dist/cjs/redis/redisRulesReader.cjs +0 -142
  89. package/dist/cjs/util.cjs +0 -5
  90. package/dist/index.js +0 -32
  91. package/dist/redis/redisRulesIndex.js +0 -138
  92. package/dist/redis/redisRulesReader.js +0 -125
  93. package/dist/util.js +0 -5
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { FilterScopeMatch } from "../rulesStorage.js";
3
+ import { policyScopeInput, accessPolicyInput } from "./policyInput.js";
4
+ import { userScopeInput } from "./userScopeInput.js";
5
+ const ruleGroupInput = z.object({
6
+ groupId: z.coerce.string().optional(),
7
+ ruleGroupId: z.coerce.string().optional()
8
+ }).transform((ruleGroupInput2) => {
9
+ const { ruleGroupId, ...ruleGroup } = ruleGroupInput2;
10
+ if ("string" === typeof ruleGroupId) {
11
+ ruleGroup.groupId = ruleGroupId;
12
+ }
13
+ return ruleGroup;
14
+ });
15
+ const accessRuleInput = z.object({
16
+ ...accessPolicyInput.shape,
17
+ ...policyScopeInput.shape
18
+ }).and(userScopeInput).and(ruleGroupInput).transform((ruleInput) => ruleInput);
19
+ const ruleEntryInput = z.object({
20
+ rule: accessRuleInput,
21
+ expiresUnixTimestamp: z.coerce.number().optional()
22
+ });
23
+ const accessRulesFilterInput = z.object({
24
+ policyScope: policyScopeInput.optional(),
25
+ policyScopes: z.array(policyScopeInput).optional(),
26
+ policyScopeMatch: z.nativeEnum(FilterScopeMatch).default(FilterScopeMatch.Exact),
27
+ userScope: userScopeInput.optional(),
28
+ userScopeMatch: z.nativeEnum(FilterScopeMatch).default(FilterScopeMatch.Exact),
29
+ groupId: z.string().optional()
30
+ });
31
+ const getAccessRuleFiltersFromInput = (filterInput) => {
32
+ const { policyScopes, policyScope, ...filterBase } = filterInput;
33
+ const allPolicyScopes = policyScopes || [];
34
+ if (policyScope) {
35
+ allPolicyScopes.push(policyScope);
36
+ }
37
+ if (allPolicyScopes.length > 0) {
38
+ return allPolicyScopes.map((policyScope2) => ({
39
+ ...filterBase,
40
+ policyScope: policyScope2
41
+ }));
42
+ }
43
+ return [filterBase];
44
+ };
45
+ export {
46
+ accessRuleInput,
47
+ accessRulesFilterInput,
48
+ getAccessRuleFiltersFromInput,
49
+ ruleEntryInput
50
+ };
@@ -0,0 +1,55 @@
1
+ import crypto from "node:crypto";
2
+ import { getIPAddress } from "@prosopo/util";
3
+ import { Address4 } from "ip-address";
4
+ import { z } from "zod";
5
+ const userAttributesSchema = z.object({
6
+ // coerce is used for safety, as e.g., incoming userId can be digital
7
+ userId: z.coerce.string().optional(),
8
+ ja4Hash: z.coerce.string().optional(),
9
+ headersHash: z.coerce.string().optional(),
10
+ userAgentHash: z.coerce.string().optional()
11
+ });
12
+ const userAttributesInput = z.object({
13
+ ...userAttributesSchema.shape,
14
+ userAgent: z.coerce.string().optional()
15
+ }).transform((userAttributesInput2) => {
16
+ const { userAgent, ...userScope } = userAttributesInput2;
17
+ if ("string" === typeof userAgent) {
18
+ userScope.userAgentHash = hashUserAgent(userAgent);
19
+ }
20
+ return userScope;
21
+ });
22
+ const hashUserAgent = (userAgent) => crypto.createHash("sha256").update(userAgent).digest("hex");
23
+ const userIpSchema = z.object({
24
+ numericIp: z.coerce.bigint().optional(),
25
+ numericIpMaskMin: z.coerce.bigint().optional(),
26
+ numericIpMaskMax: z.coerce.bigint().optional()
27
+ });
28
+ const userIpInput = z.object({
29
+ ...userIpSchema.shape,
30
+ ip: z.string().optional(),
31
+ ipMask: z.string().optional()
32
+ }).transform((userIpInput2) => {
33
+ const { ip, ipMask, ...numericUserIp } = userIpInput2;
34
+ if ("string" === typeof ip) {
35
+ numericUserIp.numericIp = getIPAddress(ip).bigInt();
36
+ }
37
+ if ("string" === typeof ipMask) {
38
+ const ipObject = new Address4(ipMask);
39
+ numericUserIp.numericIpMaskMin = ipObject.startAddress().bigInt();
40
+ numericUserIp.numericIpMaskMax = ipObject.endAddress().bigInt();
41
+ }
42
+ return numericUserIp;
43
+ });
44
+ const userScopeSchema = z.object({
45
+ ...userIpSchema.shape,
46
+ ...userAttributesSchema.shape
47
+ });
48
+ const userScopeInput = z.object({}).and(userIpInput).and(userAttributesInput).transform(
49
+ // transform is used for type safety only - plain "satisfies ZodType<x>" doesn't work after ".and()"
50
+ (userScopeInput2) => userScopeInput2
51
+ );
52
+ export {
53
+ userScopeInput,
54
+ userScopeSchema
55
+ };
@@ -0,0 +1,23 @@
1
+ const userAttributesRecordFields = [
2
+ "userId",
3
+ "ja4Hash",
4
+ "headersHash",
5
+ "userAgent"
6
+ ];
7
+ const userIpRecordFields = [
8
+ "ip",
9
+ "ipMask"
10
+ ];
11
+ const userScopeRecordFields = [
12
+ ...userAttributesRecordFields,
13
+ ...userIpRecordFields
14
+ ];
15
+ const getUserScopeRecordFromAccessRuleRecord = (ruleRecord) => Object.fromEntries(
16
+ userScopeRecordFields.map((field) => [field, ruleRecord[field]]).filter(([, value]) => value !== void 0)
17
+ );
18
+ export {
19
+ getUserScopeRecordFromAccessRuleRecord,
20
+ userAttributesRecordFields,
21
+ userIpRecordFields,
22
+ userScopeRecordFields
23
+ };
@@ -0,0 +1,8 @@
1
+ var FilterScopeMatch = /* @__PURE__ */ ((FilterScopeMatch2) => {
2
+ FilterScopeMatch2["Exact"] = "exact";
3
+ FilterScopeMatch2["Greedy"] = "greedy";
4
+ return FilterScopeMatch2;
5
+ })(FilterScopeMatch || {});
6
+ export {
7
+ FilterScopeMatch
8
+ };
@@ -0,0 +1,77 @@
1
+ import crypto from "node:crypto";
2
+ import { IpRange, IpAddress } from "cidr-calc";
3
+ import { Address4 } from "ip-address";
4
+ import { z } from "zod";
5
+ import { policyScopeInput, accessPolicyInput } from "./ruleInput/policyInput.js";
6
+ import { accessRuleInput } from "./ruleInput/ruleInput.js";
7
+ import { userScopeSchema } from "./ruleInput/userScopeInput.js";
8
+ const RULE_HASH_ALGORITHM = "md5";
9
+ const makeAccessRuleHash = (rule) => {
10
+ const valueProperties = Object.entries(rule).filter(
11
+ ([key, value]) => "undefined" !== typeof value
12
+ );
13
+ const orderedProperties = valueProperties.sort();
14
+ const objectToHash = Object.fromEntries(orderedProperties);
15
+ return hashObject(objectToHash, RULE_HASH_ALGORITHM);
16
+ };
17
+ const transformAccessRuleRecordIntoRule = (ruleRecord) => (
18
+ // accessRuleInput does all the record field transformations
19
+ accessRuleInput.parse(ruleRecord)
20
+ );
21
+ const transformAccessRuleIntoRecord = (rule) => accessRuleToRecordScheme.parse(rule);
22
+ const accessRuleToRecordScheme = z.object({
23
+ ...accessPolicyInput.shape,
24
+ ...policyScopeInput.shape,
25
+ ...userScopeSchema.shape,
26
+ groupId: z.coerce.string().optional()
27
+ }).transform((ruleInput) => {
28
+ const {
29
+ groupId,
30
+ numericIp,
31
+ numericIpMaskMin,
32
+ numericIpMaskMax,
33
+ userAgentHash,
34
+ ...rule
35
+ } = ruleInput;
36
+ const record = rule;
37
+ if ("string" === typeof groupId) {
38
+ record.ruleGroupId = groupId;
39
+ }
40
+ if ("string" === typeof userAgentHash) {
41
+ record.userAgent = userAgentHash;
42
+ }
43
+ if ("bigint" === typeof numericIp) {
44
+ record.ip = getStringIpFromNumeric(numericIp);
45
+ }
46
+ if ("bigint" === typeof numericIpMaskMin && "bigint" === typeof numericIpMaskMax) {
47
+ record.ipMask = getCidrFromNumericIpRange(
48
+ numericIpMaskMin,
49
+ numericIpMaskMax
50
+ );
51
+ }
52
+ return record;
53
+ });
54
+ const hashObject = (object, algorithm) => crypto.createHash(algorithm).update(
55
+ JSON.stringify(
56
+ object,
57
+ (key, value) => (
58
+ // JSON.stringify can't handle BigInt itself: throws "Do not know how to serialize a BigInt"
59
+ "bigint" === typeof value ? value.toString() : value
60
+ )
61
+ )
62
+ ).digest("hex");
63
+ const getStringIpFromNumeric = (numericIp) => Address4.fromInteger(Number(numericIp)).address;
64
+ const getCidrFromNumericIpRange = (startIp, endIp) => {
65
+ const ipRange = new IpRange(
66
+ IpAddress.of(getStringIpFromNumeric(startIp)),
67
+ IpAddress.of(getStringIpFromNumeric(endIp))
68
+ );
69
+ const cidr = ipRange.toCidrs()[0];
70
+ return cidr ? `${cidr.prefix.toString()}/${cidr.prefixLen}` : void 0;
71
+ };
72
+ export {
73
+ getCidrFromNumericIpRange,
74
+ makeAccessRuleHash,
75
+ transformAccessRuleIntoRecord,
76
+ transformAccessRuleRecordIntoRule
77
+ };
package/entries.ts ADDED
@@ -0,0 +1,20 @@
1
+ // Copyright 2021-2025 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ export const entries: Record<string, string> = {
16
+ ".export": "src/.export.ts",
17
+ "api/.export": "src/api/.export.ts",
18
+ "redis/.export": "src/redis/.export.ts",
19
+ "mongoose/.export": "src/mongoose/.export.ts",
20
+ };
package/package.json CHANGED
@@ -1,18 +1,31 @@
1
1
  {
2
2
  "name": "@prosopo/user-access-policy",
3
- "version": "3.5.19",
4
- "main": "dist/index.js",
5
- "types": "dist/index.d.ts",
3
+ "version": "3.5.28",
6
4
  "type": "module",
7
5
  "engines": {
8
- "node": "20",
9
- "npm": "10.8.2"
6
+ "node": ">=v20.0.0",
7
+ "npm": ">=10.6.0"
10
8
  },
11
9
  "exports": {
12
10
  ".": {
13
- "types": "./dist/index.d.ts",
14
- "import": "./dist/index.js",
15
- "require": "./dist/cjs/index.cjs"
11
+ "types": "./dist/.export.d.ts",
12
+ "import": "./dist/.export.js",
13
+ "require": "./dist/cjs/.export.cjs"
14
+ },
15
+ "./api": {
16
+ "types": "./dist/api/.export.d.ts",
17
+ "import": "./dist/api/.export.js",
18
+ "require": "./dist/cjs/api/.export.cjs"
19
+ },
20
+ "./redis": {
21
+ "types": "./dist/redis/.export.d.ts",
22
+ "import": "./dist/redis/.export.js",
23
+ "require": "./dist/cjs/redis/.export.cjs"
24
+ },
25
+ "./mongoose": {
26
+ "types": "./dist/mongoose/.export.d.ts",
27
+ "import": "./dist/mongoose/.export.js",
28
+ "require": "./dist/cjs/mongoose/.export.cjs"
16
29
  }
17
30
  },
18
31
  "imports": {
@@ -29,24 +42,27 @@
29
42
  "test": "npm run test:unit && npm run test:integration"
30
43
  },
31
44
  "dependencies": {
32
- "@prosopo/api": "3.1.24",
33
- "@prosopo/api-route": "2.6.28",
34
- "@prosopo/common": "3.1.20",
35
- "@prosopo/redis-client": "1.0.5",
36
- "@prosopo/types": "3.5.3",
37
- "@prosopo/util": "3.1.5",
45
+ "@prosopo/api": "3.1.33",
46
+ "@prosopo/api-route": "2.6.30",
47
+ "@prosopo/common": "3.1.22",
48
+ "@prosopo/redis-client": "1.0.7",
49
+ "@prosopo/types": "3.6.0",
50
+ "@prosopo/util": "3.2.0",
38
51
  "@redis/search": "5.0.0",
52
+ "@redis/client": "5.0.0",
53
+ "cidr-calc": "1.0.4",
39
54
  "dotenv": "16.4.5",
40
55
  "ip-address": "10.0.1",
41
56
  "redis": "5.0.0",
42
57
  "zod": "3.23.8"
43
58
  },
44
59
  "devDependencies": {
45
- "@prosopo/config": "3.1.20",
46
- "@prosopo/util-crypto": "13.5.22",
60
+ "@prosopo/config": "3.1.22",
61
+ "@prosopo/util-crypto": "13.5.24",
47
62
  "@types/node": "22.10.2",
48
- "vite": "6.3.5",
49
- "vitest": "3.0.9",
63
+ "mongoose": "8.13.0",
64
+ "vite": "6.4.1",
65
+ "vitest": "3.2.4",
50
66
  "yargs": "17.7.2"
51
67
  },
52
68
  "author": "PROSOPO LIMITED <info@prosopo.io>",
@@ -1,4 +1,3 @@
1
- import path from "node:path";
2
1
  // Copyright 2021-2025 Prosopo (UK) Ltd.
3
2
  //
4
3
  // Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,11 +11,15 @@ import path from "node:path";
12
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
12
  // See the License for the specific language governing permissions and
14
13
  // limitations under the License.
14
+
15
+ import path from "node:path";
15
16
  import { ViteCommonJSConfig } from "@prosopo/config";
17
+ import { entries } from "./entries.js";
16
18
 
17
19
  export default function () {
18
20
  return ViteCommonJSConfig(
19
21
  path.basename("."),
20
22
  path.resolve("./tsconfig.json"),
23
+ entries,
21
24
  );
22
25
  }
@@ -14,7 +14,12 @@
14
14
 
15
15
  import path from "node:path";
16
16
  import { ViteEsmConfig } from "@prosopo/config";
17
+ import { entries } from "./entries.js";
17
18
 
18
19
  export default function () {
19
- return ViteEsmConfig(path.basename("."), path.resolve("./tsconfig.json"));
20
+ return ViteEsmConfig(
21
+ path.basename("."),
22
+ path.resolve("./tsconfig.json"),
23
+ entries,
24
+ );
20
25
  }
@@ -1,80 +0,0 @@
1
- import { CaptchaTypeSchema } from "@prosopo/types";
2
- import { getIPAddress } from "@prosopo/util";
3
- import { Address4 } from "ip-address";
4
- import { z } from "zod";
5
- import { hashUserAgent } from "./util.js";
6
- var AccessPolicyType = /* @__PURE__ */ ((AccessPolicyType2) => {
7
- AccessPolicyType2["Block"] = "block";
8
- AccessPolicyType2["Restrict"] = "restrict";
9
- return AccessPolicyType2;
10
- })(AccessPolicyType || {});
11
- const accessPolicySchema = z.object({
12
- type: z.nativeEnum(AccessPolicyType),
13
- captchaType: CaptchaTypeSchema.optional(),
14
- description: z.coerce.string().optional(),
15
- // Redis stores values as strings, so coerce is needed to parse properly
16
- solvedImagesCount: z.coerce.number().optional(),
17
- // the percentage of image panels that must be solved per image CAPTCHA
18
- imageThreshold: z.coerce.number().optional(),
19
- // the Proof-of-Work difficulty level
20
- powDifficulty: z.coerce.number().optional(),
21
- // the number of unsolved image CAPTCHA challenges to serve
22
- unsolvedImagesCount: z.coerce.number().optional(),
23
- // used to increase the user's score
24
- frictionlessScore: z.coerce.number().optional()
25
- });
26
- const policyScopeSchema = z.object({
27
- clientId: z.coerce.string().optional(),
28
- ruleGroupId: z.coerce.string().optional()
29
- });
30
- const userScopeSchema = z.object({
31
- // coerce is used for safety, as e.g., incoming userId can be digital
32
- userId: z.coerce.string().optional(),
33
- numericIp: z.coerce.bigint().optional(),
34
- numericIpMaskMin: z.coerce.bigint().optional(),
35
- numericIpMaskMax: z.coerce.bigint().optional(),
36
- ja4Hash: z.coerce.string().optional(),
37
- headersHash: z.coerce.string().optional(),
38
- userAgentHash: z.coerce.string().optional()
39
- });
40
- const userScopeInputSchema = userScopeSchema.extend({
41
- // human-friendly ip versions. If present, then converted to numeric and removed from the object
42
- // 127.0.0.1
43
- ip: z.string().optional(),
44
- // 127.0.0.1/24
45
- ipMask: z.string().optional(),
46
- // human friendly user agent
47
- userAgent: z.string().optional()
48
- }).transform((inputUserScope) => {
49
- const { ip, ipMask, userAgent, ...userScope } = inputUserScope;
50
- if ("string" === typeof ip) {
51
- userScope.numericIp = getIPAddress(ip).bigInt();
52
- }
53
- if ("string" === typeof ipMask) {
54
- const ipObject = new Address4(ipMask);
55
- userScope.numericIpMaskMin = ipObject.startAddress().bigInt();
56
- userScope.numericIpMaskMax = ipObject.endAddress().bigInt();
57
- }
58
- if ("string" === typeof userAgent) {
59
- userScope.userAgentHash = hashUserAgent(userAgent);
60
- }
61
- return userScope;
62
- });
63
- const accessRuleSchemaExtended = z.object({
64
- // flat structure is used to fit the Redis requirements
65
- ...accessPolicySchema.shape,
66
- ...policyScopeSchema.shape,
67
- ...userScopeInputSchema._def.schema.shape
68
- }).omit({
69
- numericIp: true,
70
- numericIpMaskMin: true,
71
- numericIpMaskMax: true
72
- });
73
- export {
74
- AccessPolicyType,
75
- accessPolicySchema,
76
- accessRuleSchemaExtended,
77
- policyScopeSchema,
78
- userScopeInputSchema,
79
- userScopeSchema
80
- };
@@ -1,31 +0,0 @@
1
- import { z } from "zod";
2
- import { userScopeInputSchema, policyScopeSchema } from "./accessPolicy.js";
3
- var ScopeMatch = /* @__PURE__ */ ((ScopeMatch2) => {
4
- ScopeMatch2["Exact"] = "exact";
5
- ScopeMatch2["Greedy"] = "greedy";
6
- return ScopeMatch2;
7
- })(ScopeMatch || {});
8
- const policyFilterSchema = z.object({
9
- policyScope: policyScopeSchema.optional(),
10
- /**
11
- * Exact: "clientId" => client rules, "undefined" => global rules. Used by the API
12
- * Greedy: "clientId" => client + global rules, "undefined" => any rules. Used by the Express middleware
13
- */
14
- policyScopeMatch: z.nativeEnum(ScopeMatch).default(
15
- "exact"
16
- /* Exact */
17
- ),
18
- userScope: userScopeInputSchema.optional(),
19
- /**
20
- * Exact: finds rules where all the given fields matches and doesn't check IP against masks. Used by the API
21
- * Greedy: finds rules where any of the given fields match and checks IP against masks. Used by the Express middleware
22
- */
23
- userScopeMatch: z.nativeEnum(ScopeMatch).default(
24
- "exact"
25
- /* Exact */
26
- )
27
- });
28
- export {
29
- ScopeMatch,
30
- policyFilterSchema
31
- };
@@ -1,11 +0,0 @@
1
- import { z } from "zod";
2
- import { userScopeSchema, policyScopeSchema, accessPolicySchema } from "./accessPolicy.js";
3
- const accessRuleSchema = z.object({
4
- // flat structure is used to fit the Redis requirements
5
- ...accessPolicySchema.shape,
6
- ...policyScopeSchema.shape,
7
- ...userScopeSchema.shape
8
- });
9
- export {
10
- accessRuleSchema
11
- };
@@ -1,79 +0,0 @@
1
- import { DeleteAllRulesEndpoint } from "./deleteAllRulesEndpoint.js";
2
- import { DeleteRulesEndpoint } from "./deleteRulesEndpoint.js";
3
- import { InsertRulesEndpoint } from "./insertRulesEndpoint.js";
4
- var accessRuleApiPaths = /* @__PURE__ */ ((accessRuleApiPaths2) => {
5
- accessRuleApiPaths2["INSERT_MANY"] = "/v1/prosopo/user-access-policy/rules/insert-many";
6
- accessRuleApiPaths2["DELETE_MANY"] = "/v1/prosopo/user-access-policy/rules/delete-many";
7
- accessRuleApiPaths2["DELETE_ALL"] = "/v1/prosopo/user-access-policy/rules/delete-all";
8
- return accessRuleApiPaths2;
9
- })(accessRuleApiPaths || {});
10
- class AccessRuleApiRoutes {
11
- constructor(accessRulesStorage) {
12
- this.accessRulesStorage = accessRulesStorage;
13
- }
14
- getRoutes() {
15
- return [
16
- {
17
- path: "/v1/prosopo/user-access-policy/rules/insert-many",
18
- endpoint: new InsertRulesEndpoint(this.accessRulesStorage)
19
- },
20
- {
21
- path: "/v1/prosopo/user-access-policy/rules/delete-many",
22
- endpoint: new DeleteRulesEndpoint(this.accessRulesStorage)
23
- },
24
- {
25
- path: "/v1/prosopo/user-access-policy/rules/delete-all",
26
- endpoint: new DeleteAllRulesEndpoint(this.accessRulesStorage)
27
- }
28
- ];
29
- }
30
- }
31
- const getExpressApiRuleRateLimits = () => {
32
- const defaultWindowsMs = 6e4;
33
- const defaultLimit = 5;
34
- return {
35
- [
36
- "/v1/prosopo/user-access-policy/rules/insert-many"
37
- /* INSERT_MANY */
38
- ]: {
39
- windowMs: getIntEnvironmentVariable(
40
- "PROSOPO_USER_ACCESS_POLICY_RULE_INSERT_MANY_WINDOW"
41
- ) || defaultWindowsMs,
42
- limit: getIntEnvironmentVariable(
43
- "PROSOPO_USER_ACCESS_POLICY_RULE_INSERT_MANY_LIMIT"
44
- ) || defaultLimit
45
- },
46
- [
47
- "/v1/prosopo/user-access-policy/rules/delete-many"
48
- /* DELETE_MANY */
49
- ]: {
50
- windowMs: getIntEnvironmentVariable(
51
- "PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_MANY_WINDOW"
52
- ) || defaultWindowsMs,
53
- limit: getIntEnvironmentVariable(
54
- "PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_MANY_LIMIT"
55
- ) || defaultLimit
56
- },
57
- [
58
- "/v1/prosopo/user-access-policy/rules/delete-all"
59
- /* DELETE_ALL */
60
- ]: {
61
- windowMs: getIntEnvironmentVariable(
62
- "PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_ALL_WINDOW"
63
- ) || defaultWindowsMs,
64
- limit: getIntEnvironmentVariable(
65
- "PROSOPO_USER_ACCESS_POLICY_RULE_DELETE_ALL_LIMIT"
66
- ) || defaultLimit
67
- }
68
- };
69
- };
70
- const getIntEnvironmentVariable = (variableName) => {
71
- const variableValue = process.env[variableName];
72
- const numericValue = variableValue ? Number.parseInt(variableValue) : Number.NaN;
73
- return Number.isInteger(numericValue) ? numericValue : void 0;
74
- };
75
- export {
76
- AccessRuleApiRoutes,
77
- accessRuleApiPaths,
78
- getExpressApiRuleRateLimits
79
- };
@@ -1,38 +0,0 @@
1
- import { ApiClient } from "@prosopo/api";
2
- import { accessRuleApiPaths } from "./accessRuleApiRoutes.js";
3
- class AccessRulesApiClient extends ApiClient {
4
- insertMany(toInsert, timestamp, signature) {
5
- return this.post(accessRuleApiPaths.INSERT_MANY, toInsert, {
6
- headers: {
7
- "Prosopo-Site-Key": this.account,
8
- timestamp,
9
- signature
10
- }
11
- });
12
- }
13
- deleteMany(toDelete, timestamp, signature) {
14
- return this.post(accessRuleApiPaths.DELETE_MANY, toDelete, {
15
- headers: {
16
- "Prosopo-Site-Key": this.account,
17
- timestamp,
18
- signature
19
- }
20
- });
21
- }
22
- deleteAll(timestamp, signature) {
23
- return this.post(
24
- accessRuleApiPaths.DELETE_ALL,
25
- {},
26
- {
27
- headers: {
28
- "Prosopo-Site-Key": this.account,
29
- timestamp,
30
- signature
31
- }
32
- }
33
- );
34
- }
35
- }
36
- export {
37
- AccessRulesApiClient
38
- };
@@ -1,34 +0,0 @@
1
- import { ApiEndpointResponseStatus } from "@prosopo/api-route";
2
- import { z } from "zod";
3
- import { policyFilterSchema } from "../accessPolicyResolver.js";
4
- const deleteRulesEndpointSchema = z.array(policyFilterSchema);
5
- class DeleteRulesEndpoint {
6
- constructor(accessRulesStorage) {
7
- this.accessRulesStorage = accessRulesStorage;
8
- }
9
- async processRequest(args) {
10
- const allRuleIds = [];
11
- for (const accessRuleFilter of args) {
12
- const parsedRules = policyFilterSchema.parse(accessRuleFilter);
13
- const foundRuleIds = await this.accessRulesStorage.findRuleIds(parsedRules);
14
- allRuleIds.push(...foundRuleIds);
15
- }
16
- const uniqueRuleIds = [...new Set(allRuleIds)];
17
- if (uniqueRuleIds.length > 0) {
18
- await this.accessRulesStorage.deleteRules(uniqueRuleIds);
19
- }
20
- return {
21
- status: ApiEndpointResponseStatus.SUCCESS,
22
- data: {
23
- deleted_count: uniqueRuleIds.length
24
- }
25
- };
26
- }
27
- getRequestArgsSchema() {
28
- return deleteRulesEndpointSchema;
29
- }
30
- }
31
- export {
32
- DeleteRulesEndpoint,
33
- deleteRulesEndpointSchema
34
- };