@prosopo/provider 4.15.14 → 4.15.16
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 +106 -106
- package/.turbo/turbo-build$colon$tsc.log +24 -24
- package/.turbo/turbo-build.log +107 -104
- package/CHANGELOG.md +63 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/api/admin/apiAdminRoutesProvider.js +27 -46
- package/dist/api/admin/apiClearAllCountersEndpoint.js +62 -57
- package/dist/api/admin/apiDnsEventEndpoint.js +79 -92
- package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js +43 -45
- package/dist/api/admin/apiGetDecisionMachineEndpoint.js +40 -40
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +23 -22
- package/dist/api/admin/apiRegisterSiteKeysEndpoint.js +26 -30
- package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js +35 -37
- package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js +40 -40
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +29 -31
- package/dist/api/admin/apiRemoveSiteKeyEndpoint.js +33 -29
- package/dist/api/admin/apiRemoveSiteKeysEndpoint.js +32 -31
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +43 -35
- package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js +43 -63
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +36 -35
- package/dist/api/admin/createApiAdminRoutesProvider.js +6 -8
- package/dist/api/blacklistRequestInspector.js +285 -377
- package/dist/api/block.js +17 -30
- package/dist/api/captcha/checkSpamEmail.js +88 -98
- package/dist/api/captcha/contextAwareValidation.js +21 -15
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +126 -140
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -12
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +236 -299
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.js +10 -13
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +336 -462
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.js +17 -14
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.js +27 -27
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +42 -63
- package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +2 -4
- package/dist/api/captcha/getImageCaptchaChallenge.js +136 -207
- package/dist/api/captcha/getPoWCaptchaChallenge.js +128 -198
- package/dist/api/captcha/getPuzzleCaptchaChallenge.js +132 -201
- package/dist/api/captcha/maintenanceModeResponses.js +38 -47
- package/dist/api/captcha/submitImageCaptchaSolution.js +75 -101
- package/dist/api/captcha/submitPoWCaptchaSolution.js +137 -207
- package/dist/api/captcha/submitPuzzleCaptchaSolution.js +73 -105
- package/dist/api/captcha.js +76 -58
- package/dist/api/dnsEventUrl.js +20 -22
- package/dist/api/domainMiddleware.js +104 -115
- package/dist/api/forwardVerify.js +62 -48
- package/dist/api/handshakeTimingMiddleware.js +43 -62
- package/dist/api/hardBlockVerdictCache.js +114 -117
- package/dist/api/headerCheckMiddleware.js +34 -34
- package/dist/api/ignoreMiddleware.js +13 -15
- package/dist/api/ipInfoMiddleware.js +17 -19
- package/dist/api/ja4.js +149 -188
- package/dist/api/ja4Middleware.js +39 -54
- package/dist/api/metrics.js +245 -257
- package/dist/api/public.js +52 -54
- package/dist/api/robotsMiddleware.js +10 -10
- package/dist/api/startProviderApi.js +205 -232
- package/dist/api/testSiteKey.js +16 -16
- package/dist/api/validateAddress.js +23 -21
- package/dist/api/verify.js +334 -377
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cjs/api/admin/apiAdminRoutesProvider.cjs +40 -59
- package/dist/cjs/api/admin/apiClearAllCountersEndpoint.cjs +63 -58
- package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +82 -93
- package/dist/cjs/api/admin/apiGetAllDecisionMachinesEndpoint.cjs +46 -48
- package/dist/cjs/api/admin/apiGetDecisionMachineEndpoint.cjs +41 -41
- package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +25 -24
- package/dist/cjs/api/admin/apiRegisterSiteKeysEndpoint.cjs +28 -32
- package/dist/cjs/api/admin/apiRemoveAllDecisionMachinesEndpoint.cjs +38 -40
- package/dist/cjs/api/admin/apiRemoveDecisionMachineEndpoint.cjs +41 -41
- package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +31 -33
- package/dist/cjs/api/admin/apiRemoveSiteKeyEndpoint.cjs +35 -31
- package/dist/cjs/api/admin/apiRemoveSiteKeysEndpoint.cjs +34 -33
- package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +45 -35
- package/dist/cjs/api/admin/apiUpdateDecisionMachineEndpoint.cjs +45 -65
- package/dist/cjs/api/admin/apiUpdateDetectorKeyEndpoint.cjs +38 -37
- package/dist/cjs/api/admin/createApiAdminRoutesProvider.cjs +7 -8
- package/dist/cjs/api/blacklistRequestInspector.cjs +288 -376
- package/dist/cjs/api/block.cjs +18 -30
- package/dist/cjs/api/captcha/checkSpamEmail.cjs +90 -100
- package/dist/cjs/api/captcha/contextAwareValidation.cjs +21 -14
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +125 -140
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -10
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +238 -301
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.cjs +9 -12
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +349 -473
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.cjs +18 -14
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.cjs +26 -26
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +42 -63
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +2 -3
- package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +138 -208
- package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +131 -200
- package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +135 -203
- package/dist/cjs/api/captcha/maintenanceModeResponses.cjs +38 -44
- package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +77 -102
- package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +140 -209
- package/dist/cjs/api/captcha/submitPuzzleCaptchaSolution.cjs +76 -107
- package/dist/cjs/api/captcha.cjs +79 -58
- package/dist/cjs/api/dnsEventUrl.cjs +20 -21
- package/dist/cjs/api/domainMiddleware.cjs +106 -117
- package/dist/cjs/api/forwardVerify.cjs +63 -49
- package/dist/cjs/api/handshakeTimingMiddleware.cjs +43 -61
- package/dist/cjs/api/hardBlockVerdictCache.cjs +114 -114
- package/dist/cjs/api/headerCheckMiddleware.cjs +34 -34
- package/dist/cjs/api/ignoreMiddleware.cjs +12 -14
- package/dist/cjs/api/ipInfoMiddleware.cjs +16 -18
- package/dist/cjs/api/ja4.cjs +149 -187
- package/dist/cjs/api/ja4Middleware.cjs +40 -53
- package/dist/cjs/api/metrics.cjs +229 -228
- package/dist/cjs/api/public.cjs +57 -57
- package/dist/cjs/api/robotsMiddleware.cjs +9 -9
- package/dist/cjs/api/startProviderApi.cjs +219 -237
- package/dist/cjs/api/testSiteKey.cjs +15 -14
- package/dist/cjs/api/validateAddress.cjs +24 -21
- package/dist/cjs/api/verify.cjs +338 -379
- package/dist/cjs/compositeIpAddress.cjs +40 -47
- package/dist/cjs/index.cjs +65 -71
- package/dist/cjs/pairs.cjs +31 -35
- package/dist/cjs/rules/lang.cjs +10 -14
- package/dist/cjs/schedulers/captchaScheduler.cjs +26 -32
- package/dist/cjs/schedulers/getClientList.cjs +35 -33
- package/dist/cjs/schedulers/setClientEntropy.cjs +35 -33
- package/dist/cjs/schedulers/updateSpamEmailDomains.cjs +39 -43
- package/dist/cjs/services/ipComparison.cjs +122 -119
- package/dist/cjs/tasks/captchaManager.cjs +407 -486
- package/dist/cjs/tasks/client/clientTasks.cjs +347 -470
- package/dist/cjs/tasks/dataset/datasetTasks.cjs +25 -29
- package/dist/cjs/tasks/dataset/datasetTasksUtils.cjs +16 -32
- package/dist/cjs/tasks/decisionMachine/decisionMachineRunner.cjs +220 -307
- package/dist/cjs/tasks/detection/decodeBehavior.cjs +408 -317
- package/dist/cjs/tasks/detection/decodePayload.cjs +686 -468
- package/dist/cjs/tasks/detection/decodeSimd.cjs +462 -304
- package/dist/cjs/tasks/detection/getBotScore.cjs +37 -43
- package/dist/cjs/tasks/dnsEvent/enrichDnsEvent.cjs +88 -71
- package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +348 -486
- package/dist/cjs/tasks/frictionless/frictionlessTasksUtils.cjs +13 -30
- package/dist/cjs/tasks/frictionless/routingMachine.cjs +71 -55
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +555 -806
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasksUtils.cjs +22 -23
- package/dist/cjs/tasks/index.cjs +2 -4
- package/dist/cjs/tasks/powCaptcha/powTasks.cjs +491 -687
- package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +17 -29
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +422 -591
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasksUtils.cjs +8 -5
- package/dist/cjs/tasks/spam/checkSpamEmail.cjs +133 -141
- package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +118 -76
- package/dist/cjs/tasks/spam/evaluateEmailSpamRules.cjs +75 -84
- package/dist/cjs/tasks/spam/updateSpamEmailDomains.cjs +40 -56
- package/dist/cjs/tasks/tasks.cjs +107 -158
- package/dist/cjs/util/usageCounters.cjs +220 -211
- package/dist/cjs/util.cjs +329 -359
- package/dist/cjs/utils/devicePlatform.cjs +14 -8
- package/dist/cjs/utils/dns.cjs +68 -93
- package/dist/cjs/utils/hashUserAgent.cjs +14 -7
- package/dist/cjs/utils/hashUserIp.cjs +14 -6
- package/dist/cjs/utils/honeypot/encoders.cjs +74 -80
- package/dist/cjs/utils/honeypot/phraseBank.cjs +51 -44
- package/dist/cjs/utils/normalizeRequestIp.cjs +33 -25
- package/dist/compositeIpAddress.js +38 -46
- package/dist/index.js +12 -56
- package/dist/pairs.js +31 -37
- package/dist/rules/lang.js +11 -15
- package/dist/schedulers/captchaScheduler.js +25 -31
- package/dist/schedulers/getClientList.js +34 -32
- package/dist/schedulers/setClientEntropy.js +34 -32
- package/dist/schedulers/updateSpamEmailDomains.js +38 -42
- package/dist/services/ipComparison.js +122 -119
- package/dist/tasks/captchaManager.js +403 -483
- package/dist/tasks/client/clientTasks.js +343 -467
- package/dist/tasks/dataset/datasetTasks.js +24 -28
- package/dist/tasks/dataset/datasetTasksUtils.js +15 -31
- package/dist/tasks/decisionMachine/decisionMachineRunner.js +217 -306
- package/dist/tasks/detection/getBotScore.js +37 -43
- package/dist/tasks/dnsEvent/enrichDnsEvent.d.ts.map +1 -1
- package/dist/tasks/dnsEvent/enrichDnsEvent.js +88 -74
- package/dist/tasks/dnsEvent/enrichDnsEvent.js.map +1 -1
- package/dist/tasks/frictionless/frictionlessTasks.js +342 -479
- package/dist/tasks/frictionless/frictionlessTasksUtils.js +14 -32
- package/dist/tasks/frictionless/routingMachine.js +72 -56
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +550 -801
- package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +21 -22
- package/dist/tasks/index.js +1 -3
- package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.js +486 -682
- package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
- package/dist/tasks/powCaptcha/powTasksUtils.js +15 -28
- package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js +417 -586
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasksUtils.js +9 -6
- package/dist/tasks/spam/checkSpamEmail.js +133 -141
- package/dist/tasks/spam/checkTrafficFilter.d.ts +1 -0
- package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
- package/dist/tasks/spam/checkTrafficFilter.js +117 -77
- package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
- package/dist/tasks/spam/evaluateEmailSpamRules.js +75 -86
- package/dist/tasks/spam/updateSpamEmailDomains.js +36 -54
- package/dist/tasks/tasks.js +98 -150
- package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js +4 -1
- package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js.map +1 -1
- package/dist/tests/unit/api/block.unit.test.js +8 -4
- package/dist/tests/unit/api/block.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js +8 -6
- package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js.map +1 -1
- package/dist/tests/unit/api/forwardVerify.unit.test.js +3 -1
- package/dist/tests/unit/api/forwardVerify.unit.test.js.map +1 -1
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +15 -7
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +24 -18
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/getClientList.unit.test.js +19 -13
- package/dist/tests/unit/schedulers/getClientList.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js +19 -13
- package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +22 -16
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js +140 -0
- package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js.map +1 -1
- package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +7 -7
- package/dist/util/usageCounters.js +220 -212
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +327 -364
- package/dist/util.js.map +1 -1
- package/dist/utils/devicePlatform.js +15 -9
- package/dist/utils/dns.js +64 -77
- package/dist/utils/hashUserAgent.js +14 -7
- package/dist/utils/hashUserIp.js +14 -6
- package/dist/utils/honeypot/encoders.js +74 -80
- package/dist/utils/honeypot/phraseBank.js +49 -44
- package/dist/utils/normalizeRequestIp.js +34 -26
- package/package.json +24 -24
|
@@ -1,472 +1,348 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validateSiteKey } from "../../api/validateAddress.js";
|
|
2
2
|
import { ProsopoApiError } from "@prosopo/common";
|
|
3
3
|
import { CaptchaDatabase, ClientDatabase } from "@prosopo/database";
|
|
4
|
-
import { ScheduledTaskNames, ScheduledTaskStatus, Tier
|
|
4
|
+
import { DecisionMachineScope, ScheduledTaskNames, ScheduledTaskStatus, Tier } from "@prosopo/types";
|
|
5
|
+
import { createPrivateKey } from "node:crypto";
|
|
5
6
|
import { majorityAverage, parseUrl } from "@prosopo/util";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
//#region src/tasks/client/clientTasks.ts
|
|
8
|
+
var SAMPLE_SIZE = 75;
|
|
9
|
+
var isValidPrivateKey = (privateKeyString) => {
|
|
10
|
+
const privateKey = Buffer.from(privateKeyString, "base64").toString("ascii");
|
|
11
|
+
try {
|
|
12
|
+
createPrivateKey({
|
|
13
|
+
key: privateKey,
|
|
14
|
+
format: "pem",
|
|
15
|
+
type: "pkcs8"
|
|
16
|
+
});
|
|
17
|
+
return true;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
20
21
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
kind,
|
|
346
|
-
runtime,
|
|
347
|
-
language,
|
|
348
|
-
source,
|
|
349
|
-
name,
|
|
350
|
-
version,
|
|
351
|
-
captchaType,
|
|
352
|
-
createdAt: now,
|
|
353
|
-
updatedAt: now
|
|
354
|
-
});
|
|
355
|
-
return {
|
|
356
|
-
scope,
|
|
357
|
-
dappAccount,
|
|
358
|
-
kind,
|
|
359
|
-
updatedAt: now.toISOString()
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
async getAllDecisionMachines() {
|
|
363
|
-
const artifacts = await this.providerDB.getAllDecisionMachineArtifacts();
|
|
364
|
-
return artifacts.map((artifact) => ({
|
|
365
|
-
_id: artifact._id.toString(),
|
|
366
|
-
scope: artifact.scope,
|
|
367
|
-
dappAccount: artifact.dappAccount,
|
|
368
|
-
kind: artifact.kind,
|
|
369
|
-
runtime: artifact.runtime,
|
|
370
|
-
language: artifact.language,
|
|
371
|
-
name: artifact.name,
|
|
372
|
-
version: artifact.version,
|
|
373
|
-
captchaType: artifact.captchaType,
|
|
374
|
-
source: artifact.source,
|
|
375
|
-
createdAt: artifact.createdAt.toISOString(),
|
|
376
|
-
updatedAt: artifact.updatedAt.toISOString()
|
|
377
|
-
}));
|
|
378
|
-
}
|
|
379
|
-
async getDecisionMachine(id) {
|
|
380
|
-
const artifact = await this.providerDB.getDecisionMachineArtifactById(id);
|
|
381
|
-
if (!artifact) {
|
|
382
|
-
throw new ProsopoApiError("API.BAD_REQUEST", {
|
|
383
|
-
context: { id },
|
|
384
|
-
logger: this.logger
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
return {
|
|
388
|
-
_id: artifact._id.toString(),
|
|
389
|
-
scope: artifact.scope,
|
|
390
|
-
dappAccount: artifact.dappAccount,
|
|
391
|
-
kind: artifact.kind,
|
|
392
|
-
runtime: artifact.runtime,
|
|
393
|
-
language: artifact.language,
|
|
394
|
-
source: artifact.source,
|
|
395
|
-
name: artifact.name,
|
|
396
|
-
version: artifact.version,
|
|
397
|
-
captchaType: artifact.captchaType,
|
|
398
|
-
createdAt: artifact.createdAt.toISOString(),
|
|
399
|
-
updatedAt: artifact.updatedAt.toISOString()
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
async removeDecisionMachine(id) {
|
|
403
|
-
const success = await this.providerDB.removeDecisionMachineArtifact(id);
|
|
404
|
-
if (!success) {
|
|
405
|
-
throw new ProsopoApiError("API.BAD_REQUEST", {
|
|
406
|
-
context: { id, message: "Decision machine not found" },
|
|
407
|
-
logger: this.logger
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
return {
|
|
411
|
-
success,
|
|
412
|
-
deletedId: id
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
async removeAllDecisionMachines() {
|
|
416
|
-
const deletedCount = await this.providerDB.removeAllDecisionMachineArtifacts();
|
|
417
|
-
return {
|
|
418
|
-
success: true,
|
|
419
|
-
deletedCount
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Matches a request referrer against an allowed domain pattern.
|
|
424
|
-
* Supports global '*', subdomain '*.example.com', glob '*example*',
|
|
425
|
-
* plain domains (exact or subdomain), and 'localhost'.
|
|
426
|
-
*/
|
|
427
|
-
domainPatternMatcher(referrer, clientDomain) {
|
|
428
|
-
if (!referrer || !clientDomain) return false;
|
|
429
|
-
try {
|
|
430
|
-
const referrerHost = parseUrl(referrer).hostname.replace(/\.$/, "");
|
|
431
|
-
const pattern = clientDomain.trim().toLowerCase();
|
|
432
|
-
if (pattern === "*") return true;
|
|
433
|
-
if (pattern === "localhost") {
|
|
434
|
-
return referrerHost === "localhost" || referrerHost.startsWith("localhost:");
|
|
435
|
-
}
|
|
436
|
-
if (pattern.startsWith("*.")) {
|
|
437
|
-
const suffix = pattern.slice(2);
|
|
438
|
-
const allowed = parseUrl(suffix).hostname.replace(/\.$/, "");
|
|
439
|
-
return referrerHost.endsWith(`.${allowed}`) || referrerHost === allowed;
|
|
440
|
-
}
|
|
441
|
-
if (pattern.includes("*")) {
|
|
442
|
-
const escaped = pattern.replace(/[.+?^${}()|\[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
443
|
-
const regex = new RegExp(`^${escaped}$`, "i");
|
|
444
|
-
return regex.test(referrerHost);
|
|
445
|
-
}
|
|
446
|
-
const allowedHost = parseUrl(pattern).hostname.replace(/\.$/, "");
|
|
447
|
-
return referrerHost === allowedHost || referrerHost.endsWith(`.${allowedHost}`);
|
|
448
|
-
} catch (e) {
|
|
449
|
-
this.logger.error(() => ({
|
|
450
|
-
msg: "Error in domainPatternMatcher",
|
|
451
|
-
data: { referrer, clientDomain }
|
|
452
|
-
}));
|
|
453
|
-
return false;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
isRecordUpdated(record) {
|
|
457
|
-
const { lastUpdatedTimestamp, storedAtTimestamp } = record;
|
|
458
|
-
return !lastUpdatedTimestamp || !storedAtTimestamp || lastUpdatedTimestamp.getTime() > storedAtTimestamp.getTime();
|
|
459
|
-
}
|
|
460
|
-
async processBatchesWithCursor(fetchBatch, processBatch) {
|
|
461
|
-
let skip = 0;
|
|
462
|
-
while (true) {
|
|
463
|
-
const batch = await fetchBatch(skip);
|
|
464
|
-
if (!batch.length) break;
|
|
465
|
-
await processBatch(batch);
|
|
466
|
-
skip += batch.length;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
export {
|
|
471
|
-
ClientTaskManager
|
|
22
|
+
var ClientTaskManager = class {
|
|
23
|
+
constructor(config, logger, db) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.logger = logger;
|
|
26
|
+
this.providerDB = db;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @description Get the captcha database connection or create a new one
|
|
30
|
+
* @returns CaptchaDatabase
|
|
31
|
+
*/
|
|
32
|
+
getCaptchaDB(mongoCaptchaUri) {
|
|
33
|
+
if (this.captchaDB) return this.captchaDB;
|
|
34
|
+
if (!this.captchaDB) this.captchaDB = new CaptchaDatabase(mongoCaptchaUri, void 0, void 0, this.logger);
|
|
35
|
+
return this.captchaDB;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @description Store commitments externally in the database (Sends image captcha data to the big Mongo Cloud DB)
|
|
39
|
+
* @returns Promise<void>
|
|
40
|
+
*/
|
|
41
|
+
async storeCommitmentsExternal() {
|
|
42
|
+
if (!this.config.mongoCaptchaUri) {
|
|
43
|
+
this.logger.info(() => ({ msg: "Mongo env not set" }));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const lastTask = await this.providerDB.getLastScheduledTaskStatus(ScheduledTaskNames.StoreCommitmentsExternal, ScheduledTaskStatus.Completed);
|
|
47
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(ScheduledTaskNames.StoreCommitmentsExternal, ScheduledTaskStatus.Running);
|
|
48
|
+
try {
|
|
49
|
+
const BATCH_SIZE = 1e3;
|
|
50
|
+
const captchaDB = this.getCaptchaDB(this.config.mongoCaptchaUri);
|
|
51
|
+
const sweepStartedAt = /* @__PURE__ */ new Date();
|
|
52
|
+
let processedCommitments = 0;
|
|
53
|
+
await this.processBatchesWithCursor(async (skip) => await this.providerDB.getUnstoredDappUserCommitments(BATCH_SIZE, skip), async (batch) => {
|
|
54
|
+
const filteredBatch = (lastTask?.updated ? batch.filter((commitment) => this.isRecordUpdated(commitment)) : batch).filter((commitment) => commitment.id !== "");
|
|
55
|
+
if (filteredBatch.length > 0) {
|
|
56
|
+
await captchaDB.saveCaptchas([], filteredBatch, []);
|
|
57
|
+
await this.providerDB.markDappUserCommitmentsStored(filteredBatch.map((commitment) => commitment.id), sweepStartedAt);
|
|
58
|
+
}
|
|
59
|
+
processedCommitments += filteredBatch.length;
|
|
60
|
+
});
|
|
61
|
+
let processedPowRecords = 0;
|
|
62
|
+
await this.processBatchesWithCursor(async (skip) => await this.providerDB.getUnstoredDappUserPoWCommitments(BATCH_SIZE, skip), async (batch) => {
|
|
63
|
+
const filteredBatch = lastTask?.updated ? batch.filter((record) => this.isRecordUpdated(record)) : batch;
|
|
64
|
+
if (filteredBatch.length > 0) {
|
|
65
|
+
await captchaDB.saveCaptchas([], [], filteredBatch);
|
|
66
|
+
await this.providerDB.markDappUserPoWCommitmentsStored(filteredBatch.map((record) => record.challenge), sweepStartedAt);
|
|
67
|
+
}
|
|
68
|
+
processedPowRecords += filteredBatch.length;
|
|
69
|
+
});
|
|
70
|
+
let processedSessionRecords = 0;
|
|
71
|
+
await this.processBatchesWithCursor(async (skip) => await this.providerDB.getUnstoredSessionRecords(BATCH_SIZE, skip), async (batch) => {
|
|
72
|
+
const filteredBatch = lastTask?.updated ? batch.filter((record) => this.isRecordUpdated(record)) : batch;
|
|
73
|
+
if (filteredBatch.length > 0) {
|
|
74
|
+
await captchaDB.saveCaptchas(filteredBatch, [], []);
|
|
75
|
+
await this.providerDB.markSessionRecordsStored(filteredBatch.map((record) => record.sessionId), sweepStartedAt);
|
|
76
|
+
}
|
|
77
|
+
processedSessionRecords += filteredBatch.length;
|
|
78
|
+
});
|
|
79
|
+
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Completed, { data: {
|
|
80
|
+
processedSessionRecords,
|
|
81
|
+
processedCommitments,
|
|
82
|
+
processedPowRecords
|
|
83
|
+
} });
|
|
84
|
+
this.captchaDB?.close();
|
|
85
|
+
} catch (e) {
|
|
86
|
+
this.logger.error(() => ({
|
|
87
|
+
err: e,
|
|
88
|
+
msg: "Error processing client tasks"
|
|
89
|
+
}));
|
|
90
|
+
this.captchaDB?.close();
|
|
91
|
+
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Failed, { error: String(e) });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @description Get a list of client accounts and their settings from the client database
|
|
96
|
+
* @returns Promise<void>
|
|
97
|
+
*/
|
|
98
|
+
async getClientList() {
|
|
99
|
+
if (!this.config.mongoClientUri) {
|
|
100
|
+
this.logger.info(() => ({ msg: "Mongo env not set" }));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const lastTask = await this.providerDB.getLastScheduledTaskStatus(ScheduledTaskNames.GetClientList, ScheduledTaskStatus.Completed);
|
|
104
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(ScheduledTaskNames.GetClientList, ScheduledTaskStatus.Running);
|
|
105
|
+
try {
|
|
106
|
+
const clientDB = new ClientDatabase(this.config.mongoClientUri, void 0, void 0, this.logger);
|
|
107
|
+
const tenMinuteWindow = 600 * 1e3;
|
|
108
|
+
const updatedAtTimestamp = (() => {
|
|
109
|
+
const raw = lastTask?.updated;
|
|
110
|
+
if (!raw) return 0;
|
|
111
|
+
const ts = raw instanceof Date ? raw.getTime() : Date.parse(String(raw));
|
|
112
|
+
if (Number.isNaN(ts)) return 0;
|
|
113
|
+
return Math.max(ts - tenMinuteWindow, 0);
|
|
114
|
+
})();
|
|
115
|
+
this.logger.info(() => ({ msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}` }));
|
|
116
|
+
const newClientRecords = await clientDB.getUpdatedClients(updatedAtTimestamp);
|
|
117
|
+
if (newClientRecords) await this.providerDB.updateClientRecords(newClientRecords);
|
|
118
|
+
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Completed, { data: { clientRecords: newClientRecords.length } });
|
|
119
|
+
} catch (e) {
|
|
120
|
+
const getClientListError = new ProsopoApiError("DATABASE.UNKNOWN", {
|
|
121
|
+
context: { error: e },
|
|
122
|
+
logger: this.logger
|
|
123
|
+
});
|
|
124
|
+
this.logger.error(() => ({
|
|
125
|
+
err: getClientListError,
|
|
126
|
+
msg: "Error getting client list"
|
|
127
|
+
}));
|
|
128
|
+
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Failed, { error: String(e) });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* @description Calculate client entropy scores and update in db
|
|
133
|
+
* @returns Promise<void>
|
|
134
|
+
*/
|
|
135
|
+
async calculateClientEntropy() {
|
|
136
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(ScheduledTaskNames.SetClientEntropy, ScheduledTaskStatus.Running);
|
|
137
|
+
try {
|
|
138
|
+
let clients = await this.providerDB.getAllClientRecords();
|
|
139
|
+
clients = clients.filter((client) => client.tier !== Tier.Free);
|
|
140
|
+
this.logger.info(() => ({ msg: `Calculating entropies for ${clients.length} clients` }));
|
|
141
|
+
for (const client of clients) if (client.settings?.contextAware?.enabled) {
|
|
142
|
+
const contextTypes = Object.keys(client.settings.contextAware.contexts ?? {});
|
|
143
|
+
for (const contextType of contextTypes) {
|
|
144
|
+
const contextSamples = await this.providerDB.sampleContextEntropy(SAMPLE_SIZE, client.account, contextType);
|
|
145
|
+
if (contextSamples.length < SAMPLE_SIZE) {
|
|
146
|
+
this.logger.info(() => ({ msg: `Skipping ${contextType} entropy calculation for client ${client.account} due to insufficient samples (${contextSamples.length}/${SAMPLE_SIZE})` }));
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const contextAvgEntropy = majorityAverage(contextSamples);
|
|
150
|
+
this.logger.info(() => ({ msg: `Calculated ${contextType} entropy for client ${client.account}: ${contextAvgEntropy}` }));
|
|
151
|
+
await this.providerDB.setClientContextEntropy(client.account, contextType, contextAvgEntropy);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Completed, { data: { clientRecords: clients.length } });
|
|
155
|
+
} catch (e) {
|
|
156
|
+
const calculateClientEntropiesError = new ProsopoApiError("DATABASE.UNKNOWN", {
|
|
157
|
+
context: { error: e },
|
|
158
|
+
logger: this.logger
|
|
159
|
+
});
|
|
160
|
+
this.logger.error(() => ({
|
|
161
|
+
err: calculateClientEntropiesError,
|
|
162
|
+
msg: "Error calculating client entropy"
|
|
163
|
+
}));
|
|
164
|
+
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Failed, { error: String(e) });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async registerSiteKey(siteKey, tier, settings) {
|
|
168
|
+
validateSiteKey(siteKey);
|
|
169
|
+
await this.providerDB.updateClientRecords([{
|
|
170
|
+
account: siteKey,
|
|
171
|
+
tier,
|
|
172
|
+
settings
|
|
173
|
+
}]);
|
|
174
|
+
}
|
|
175
|
+
async registerSiteKeys(siteKeys) {
|
|
176
|
+
const records = [];
|
|
177
|
+
for (const { siteKey, tier, settings } of siteKeys) {
|
|
178
|
+
validateSiteKey(siteKey);
|
|
179
|
+
records.push({
|
|
180
|
+
account: siteKey,
|
|
181
|
+
tier,
|
|
182
|
+
settings
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
await this.providerDB.updateClientRecords(records);
|
|
186
|
+
}
|
|
187
|
+
async removeSiteKey(siteKey) {
|
|
188
|
+
validateSiteKey(siteKey);
|
|
189
|
+
await this.providerDB.removeClientRecords([siteKey]);
|
|
190
|
+
}
|
|
191
|
+
async removeSiteKeys(siteKeys) {
|
|
192
|
+
const accounts = [];
|
|
193
|
+
for (const { siteKey } of siteKeys) {
|
|
194
|
+
validateSiteKey(siteKey);
|
|
195
|
+
accounts.push(siteKey);
|
|
196
|
+
}
|
|
197
|
+
await this.providerDB.removeClientRecords(accounts);
|
|
198
|
+
}
|
|
199
|
+
async updateDetectorKey(detectorKey) {
|
|
200
|
+
if (!isValidPrivateKey(detectorKey)) throw new ProsopoApiError("INVALID_DETECTOR_KEY", {
|
|
201
|
+
context: { detectorKey },
|
|
202
|
+
logger: this.logger
|
|
203
|
+
});
|
|
204
|
+
await this.providerDB.storeDetectorKey(detectorKey);
|
|
205
|
+
return await this.providerDB.getDetectorKeys();
|
|
206
|
+
}
|
|
207
|
+
async removeDetectorKey(detectorKey, expirationInSeconds) {
|
|
208
|
+
if (!isValidPrivateKey(detectorKey)) throw new ProsopoApiError("INVALID_DETECTOR_KEY", {
|
|
209
|
+
context: { detectorKey },
|
|
210
|
+
logger: this.logger
|
|
211
|
+
});
|
|
212
|
+
await this.providerDB.removeDetectorKey(detectorKey, expirationInSeconds);
|
|
213
|
+
}
|
|
214
|
+
async updateDecisionMachine(scope, runtime, source, dappAccount, language, name, version, captchaType, kind) {
|
|
215
|
+
if (scope === DecisionMachineScope.Dapp && !dappAccount) throw new ProsopoApiError("API.BAD_REQUEST", {
|
|
216
|
+
context: {
|
|
217
|
+
scope,
|
|
218
|
+
dappAccount
|
|
219
|
+
},
|
|
220
|
+
logger: this.logger
|
|
221
|
+
});
|
|
222
|
+
const now = /* @__PURE__ */ new Date();
|
|
223
|
+
await this.providerDB.upsertDecisionMachineArtifact({
|
|
224
|
+
scope,
|
|
225
|
+
dappAccount,
|
|
226
|
+
kind,
|
|
227
|
+
runtime,
|
|
228
|
+
language,
|
|
229
|
+
source,
|
|
230
|
+
name,
|
|
231
|
+
version,
|
|
232
|
+
captchaType,
|
|
233
|
+
createdAt: now,
|
|
234
|
+
updatedAt: now
|
|
235
|
+
});
|
|
236
|
+
return {
|
|
237
|
+
scope,
|
|
238
|
+
dappAccount,
|
|
239
|
+
kind,
|
|
240
|
+
updatedAt: now.toISOString()
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
async getAllDecisionMachines() {
|
|
244
|
+
return (await this.providerDB.getAllDecisionMachineArtifacts()).map((artifact) => ({
|
|
245
|
+
_id: artifact._id.toString(),
|
|
246
|
+
scope: artifact.scope,
|
|
247
|
+
dappAccount: artifact.dappAccount,
|
|
248
|
+
kind: artifact.kind,
|
|
249
|
+
runtime: artifact.runtime,
|
|
250
|
+
language: artifact.language,
|
|
251
|
+
name: artifact.name,
|
|
252
|
+
version: artifact.version,
|
|
253
|
+
captchaType: artifact.captchaType,
|
|
254
|
+
source: artifact.source,
|
|
255
|
+
createdAt: artifact.createdAt.toISOString(),
|
|
256
|
+
updatedAt: artifact.updatedAt.toISOString()
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
async getDecisionMachine(id) {
|
|
260
|
+
const artifact = await this.providerDB.getDecisionMachineArtifactById(id);
|
|
261
|
+
if (!artifact) throw new ProsopoApiError("API.BAD_REQUEST", {
|
|
262
|
+
context: { id },
|
|
263
|
+
logger: this.logger
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
_id: artifact._id.toString(),
|
|
267
|
+
scope: artifact.scope,
|
|
268
|
+
dappAccount: artifact.dappAccount,
|
|
269
|
+
kind: artifact.kind,
|
|
270
|
+
runtime: artifact.runtime,
|
|
271
|
+
language: artifact.language,
|
|
272
|
+
source: artifact.source,
|
|
273
|
+
name: artifact.name,
|
|
274
|
+
version: artifact.version,
|
|
275
|
+
captchaType: artifact.captchaType,
|
|
276
|
+
createdAt: artifact.createdAt.toISOString(),
|
|
277
|
+
updatedAt: artifact.updatedAt.toISOString()
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
async removeDecisionMachine(id) {
|
|
281
|
+
const success = await this.providerDB.removeDecisionMachineArtifact(id);
|
|
282
|
+
if (!success) throw new ProsopoApiError("API.BAD_REQUEST", {
|
|
283
|
+
context: {
|
|
284
|
+
id,
|
|
285
|
+
message: "Decision machine not found"
|
|
286
|
+
},
|
|
287
|
+
logger: this.logger
|
|
288
|
+
});
|
|
289
|
+
return {
|
|
290
|
+
success,
|
|
291
|
+
deletedId: id
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
async removeAllDecisionMachines() {
|
|
295
|
+
return {
|
|
296
|
+
success: true,
|
|
297
|
+
deletedCount: await this.providerDB.removeAllDecisionMachineArtifacts()
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Matches a request referrer against an allowed domain pattern.
|
|
302
|
+
* Supports global '*', subdomain '*.example.com', glob '*example*',
|
|
303
|
+
* plain domains (exact or subdomain), and 'localhost'.
|
|
304
|
+
*/
|
|
305
|
+
domainPatternMatcher(referrer, clientDomain) {
|
|
306
|
+
if (!referrer || !clientDomain) return false;
|
|
307
|
+
try {
|
|
308
|
+
const referrerHost = parseUrl(referrer).hostname.replace(/\.$/, "");
|
|
309
|
+
const pattern = clientDomain.trim().toLowerCase();
|
|
310
|
+
if (pattern === "*") return true;
|
|
311
|
+
if (pattern === "localhost") return referrerHost === "localhost" || referrerHost.startsWith("localhost:");
|
|
312
|
+
if (pattern.startsWith("*.")) {
|
|
313
|
+
const allowed = parseUrl(pattern.slice(2)).hostname.replace(/\.$/, "");
|
|
314
|
+
return referrerHost.endsWith(`.${allowed}`) || referrerHost === allowed;
|
|
315
|
+
}
|
|
316
|
+
if (pattern.includes("*")) {
|
|
317
|
+
const escaped = pattern.replace(/[.+?^${}()|\[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
318
|
+
return new RegExp(`^${escaped}$`, "i").test(referrerHost);
|
|
319
|
+
}
|
|
320
|
+
const allowedHost = parseUrl(pattern).hostname.replace(/\.$/, "");
|
|
321
|
+
return referrerHost === allowedHost || referrerHost.endsWith(`.${allowedHost}`);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
this.logger.error(() => ({
|
|
324
|
+
msg: "Error in domainPatternMatcher",
|
|
325
|
+
data: {
|
|
326
|
+
referrer,
|
|
327
|
+
clientDomain
|
|
328
|
+
}
|
|
329
|
+
}));
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
isRecordUpdated(record) {
|
|
334
|
+
const { lastUpdatedTimestamp, storedAtTimestamp } = record;
|
|
335
|
+
return !lastUpdatedTimestamp || !storedAtTimestamp || lastUpdatedTimestamp.getTime() > storedAtTimestamp.getTime();
|
|
336
|
+
}
|
|
337
|
+
async processBatchesWithCursor(fetchBatch, processBatch) {
|
|
338
|
+
let skip = 0;
|
|
339
|
+
while (true) {
|
|
340
|
+
const batch = await fetchBatch(skip);
|
|
341
|
+
if (!batch.length) break;
|
|
342
|
+
await processBatch(batch);
|
|
343
|
+
skip += batch.length;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
472
346
|
};
|
|
347
|
+
//#endregion
|
|
348
|
+
export { ClientTaskManager };
|