@prosopo/provider 4.15.13 → 4.15.15
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 +78 -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/powCaptcha/powTasks.unit.test.js +6 -0
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js +60 -1
- package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.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,688 +1,492 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
};
|
|
493
|
-
failReason = "API.SPAM_EMAIL_RULE";
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
const sessionRecord = challengeRecord.sessionId ? await this.db.getSessionRecordBySessionId(challengeRecord.sessionId) : void 0;
|
|
497
|
-
const enrichedDnsEvent = await enrichDnsEvent.enrichDnsEvent(
|
|
498
|
-
sessionRecord?.dnsEvent,
|
|
499
|
-
env.ipInfoService,
|
|
500
|
-
ip ?? challengeRecord.ipInfo?.ip
|
|
501
|
-
);
|
|
502
|
-
if (!failResult) {
|
|
503
|
-
const check = await this.resolveTrafficFilterCheck(
|
|
504
|
-
env,
|
|
505
|
-
challengeRecord.ipInfo,
|
|
506
|
-
trafficFilter,
|
|
507
|
-
ip,
|
|
508
|
-
enrichedDnsEvent
|
|
509
|
-
);
|
|
510
|
-
if (check.isBlocked) {
|
|
511
|
-
logger.info(() => ({
|
|
512
|
-
msg: "Traffic filter rejected request in PoW verification",
|
|
513
|
-
data: {
|
|
514
|
-
ip,
|
|
515
|
-
reason: check.reason,
|
|
516
|
-
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
517
|
-
dnsResolverIp: enrichedDnsEvent?.resolverIp,
|
|
518
|
-
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
519
|
-
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
|
|
520
|
-
dnsPathValid: enrichedDnsEvent?.pathValid
|
|
521
|
-
}
|
|
522
|
-
}));
|
|
523
|
-
failResult = {
|
|
524
|
-
status: types.CaptchaStatus.disapproved,
|
|
525
|
-
reason: check.reason
|
|
526
|
-
};
|
|
527
|
-
failReason = check.reason;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
if (storeMetadata && email) {
|
|
531
|
-
powRecordUpdates.metadata = { email };
|
|
532
|
-
}
|
|
533
|
-
if (!failResult && ip) {
|
|
534
|
-
const challengeIpAddress = compositeIpAddress.getIpAddressFromComposite(
|
|
535
|
-
challengeRecord.ipAddress
|
|
536
|
-
);
|
|
537
|
-
const clientRecord = await this.db.getClientRecord(dappAccount);
|
|
538
|
-
const ipValidationRules = clientRecord?.settings?.ipValidationRules;
|
|
539
|
-
powRecordUpdates.providedIp = compositeIpAddress.getCompositeIpAddress(ip);
|
|
540
|
-
if (ipValidationRules?.enabled === true) {
|
|
541
|
-
const ipValidation = await util$2.deepValidateIpAddress(
|
|
542
|
-
ip,
|
|
543
|
-
challengeIpAddress,
|
|
544
|
-
logger,
|
|
545
|
-
env.ipInfoService,
|
|
546
|
-
ipValidationRules,
|
|
547
|
-
enrichedDnsEvent?.peerIp
|
|
548
|
-
);
|
|
549
|
-
if (!ipValidation.isValid) {
|
|
550
|
-
logger.error(() => ({
|
|
551
|
-
msg: "IP validation failed for PoW captcha",
|
|
552
|
-
data: {
|
|
553
|
-
ip,
|
|
554
|
-
challengeIp: challengeIpAddress.address,
|
|
555
|
-
error: ipValidation.errorMessage,
|
|
556
|
-
distanceKm: ipValidation.distanceKm
|
|
557
|
-
}
|
|
558
|
-
}));
|
|
559
|
-
failResult = {
|
|
560
|
-
status: types.CaptchaStatus.disapproved,
|
|
561
|
-
reason: types.ResultReason.FAILED_IP_VALIDATION
|
|
562
|
-
};
|
|
563
|
-
failReason = "API.FAILED_IP_VALIDATION";
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
let score;
|
|
568
|
-
if (sessionRecord) {
|
|
569
|
-
const dnsAsymmetry = enrichDnsEvent.computeDnsAsymmetry(
|
|
570
|
-
enrichedDnsEvent,
|
|
571
|
-
challengeRecord.ipInfo,
|
|
572
|
-
trafficFilter
|
|
573
|
-
);
|
|
574
|
-
if (dnsAsymmetry > 0) {
|
|
575
|
-
sessionRecord.scoreComponents = {
|
|
576
|
-
...sessionRecord.scoreComponents,
|
|
577
|
-
dnsAsymmetry
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
|
-
score = frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
581
|
-
logger.info(() => ({
|
|
582
|
-
data: {
|
|
583
|
-
scoreComponents: { ...sessionRecord?.scoreComponents || {} },
|
|
584
|
-
score,
|
|
585
|
-
dnsPeerAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
586
|
-
dnsResolverAsn: enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
|
|
587
|
-
}
|
|
588
|
-
}));
|
|
589
|
-
}
|
|
590
|
-
if (!failResult) {
|
|
591
|
-
try {
|
|
592
|
-
const decisionInput = {
|
|
593
|
-
userAccount: challengeRecord.userAccount,
|
|
594
|
-
dappAccount: challengeRecord.dappAccount,
|
|
595
|
-
captchaResult: "passed",
|
|
596
|
-
headers: challengeRecord.headers,
|
|
597
|
-
captchaType: types.CaptchaType.pow,
|
|
598
|
-
behavioralDataPacked: challengeRecord.behavioralDataPacked,
|
|
599
|
-
deviceCapability: challengeRecord.deviceCapability,
|
|
600
|
-
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0,
|
|
601
|
-
ipInfo: challengeRecord.ipInfo,
|
|
602
|
-
dnsEvent: enrichedDnsEvent,
|
|
603
|
-
score,
|
|
604
|
-
threshold: sessionRecord?.threshold,
|
|
605
|
-
scoreComponents: sessionRecord?.scoreComponents,
|
|
606
|
-
decryptedHeadHash: sessionRecord?.decryptedHeadHash,
|
|
607
|
-
userSitekeyIpHash: sessionRecord?.userSitekeyIpHash,
|
|
608
|
-
simdReadings: sessionRecord?.simdReadings,
|
|
609
|
-
frictionlessReason: sessionRecord?.reason,
|
|
610
|
-
ruleType: sessionRecord?.ruleType,
|
|
611
|
-
webView: sessionRecord?.webView,
|
|
612
|
-
iFrame: sessionRecord?.iFrame,
|
|
613
|
-
coords: challengeRecord.coords
|
|
614
|
-
};
|
|
615
|
-
const decision = await this.decisionMachineRunner.decide(
|
|
616
|
-
decisionInput,
|
|
617
|
-
logger
|
|
618
|
-
);
|
|
619
|
-
if (decision.decision === types.DecisionMachineDecision.Deny) {
|
|
620
|
-
logger.info(() => ({
|
|
621
|
-
msg: "Decision machine denied PoW captcha in server verification",
|
|
622
|
-
data: {
|
|
623
|
-
userAccount: challengeRecord.userAccount,
|
|
624
|
-
reason: decision.reason,
|
|
625
|
-
score: decision.score,
|
|
626
|
-
tags: decision.tags
|
|
627
|
-
}
|
|
628
|
-
}));
|
|
629
|
-
const dmReason = decision.reason || types.ResultReason.CAPTCHA_DECISION_MACHINE_DENIED;
|
|
630
|
-
failResult = {
|
|
631
|
-
status: types.CaptchaStatus.disapproved,
|
|
632
|
-
reason: dmReason
|
|
633
|
-
};
|
|
634
|
-
failReason = dmReason;
|
|
635
|
-
} else {
|
|
636
|
-
logger.debug(() => ({
|
|
637
|
-
msg: "Decision machine allowed PoW captcha",
|
|
638
|
-
data: {
|
|
639
|
-
reason: decision.reason,
|
|
640
|
-
score: decision.score,
|
|
641
|
-
tags: decision.tags
|
|
642
|
-
}
|
|
643
|
-
}));
|
|
644
|
-
}
|
|
645
|
-
} catch (error) {
|
|
646
|
-
logger.error(() => ({
|
|
647
|
-
msg: "Failed to run decision machine in server PoW verification",
|
|
648
|
-
err: error
|
|
649
|
-
}));
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
const finalResult = failResult || {
|
|
653
|
-
status: types.CaptchaStatus.approved
|
|
654
|
-
};
|
|
655
|
-
if (failResult) {
|
|
656
|
-
powRecordUpdates.result = failResult;
|
|
657
|
-
}
|
|
658
|
-
const writePromises = [];
|
|
659
|
-
if (Object.keys(powRecordUpdates).length > 0) {
|
|
660
|
-
writePromises.push(
|
|
661
|
-
this.db.updatePowCaptchaRecord(
|
|
662
|
-
challengeRecord.challenge,
|
|
663
|
-
powRecordUpdates
|
|
664
|
-
)
|
|
665
|
-
);
|
|
666
|
-
}
|
|
667
|
-
if (challengeRecord.sessionId) {
|
|
668
|
-
writePromises.push(
|
|
669
|
-
this.updateSessionRecordWithCache(
|
|
670
|
-
challengeRecord.sessionId,
|
|
671
|
-
{
|
|
672
|
-
serverChecked: true,
|
|
673
|
-
result: finalResult
|
|
674
|
-
},
|
|
675
|
-
true
|
|
676
|
-
)
|
|
677
|
-
);
|
|
678
|
-
}
|
|
679
|
-
if (writePromises.length > 0) {
|
|
680
|
-
await Promise.all(writePromises);
|
|
681
|
-
}
|
|
682
|
-
if (failReason) {
|
|
683
|
-
return notVerified(failReason);
|
|
684
|
-
}
|
|
685
|
-
return { verified: true, ...score ? { score } : {} };
|
|
686
|
-
}
|
|
687
|
-
}
|
|
1
|
+
const require_usageCounters = require("../../util/usageCounters.cjs");
|
|
2
|
+
const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
|
|
3
|
+
const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
|
|
4
|
+
const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
|
|
5
|
+
const require_captchaManager = require("../captchaManager.cjs");
|
|
6
|
+
const require_routingMachine = require("../frictionless/routingMachine.cjs");
|
|
7
|
+
const require_util = require("../../util.cjs");
|
|
8
|
+
const require_frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
|
|
9
|
+
const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
|
|
10
|
+
const require_powTasksUtils = require("./powTasksUtils.cjs");
|
|
11
|
+
let _prosopo_common = require("@prosopo/common");
|
|
12
|
+
let _prosopo_types = require("@prosopo/types");
|
|
13
|
+
let _prosopo_util = require("@prosopo/util");
|
|
14
|
+
let _polkadot_util = require("@polkadot/util");
|
|
15
|
+
//#region src/tasks/powCaptcha/powTasks.ts
|
|
16
|
+
var DEFAULT_POW_DIFFICULTY = 4;
|
|
17
|
+
var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
|
|
18
|
+
constructor(db, pair, config, logger, writeQueue, usageCounters) {
|
|
19
|
+
super(db, pair, config, logger, writeQueue);
|
|
20
|
+
this.POW_SEPARATOR = _prosopo_types.POW_SEPARATOR;
|
|
21
|
+
this.decisionMachineRunner = new require_decisionMachineRunner.DecisionMachineRunner(db);
|
|
22
|
+
this.usageCounters = usageCounters ?? null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Provide the request-side data needed to run the post-pow routing pass
|
|
26
|
+
* inside `verifyPowCaptchaSolution`. When unset, the routing pass is
|
|
27
|
+
* skipped and verification behaves exactly as before.
|
|
28
|
+
*/
|
|
29
|
+
setPostPowContext(ctx) {
|
|
30
|
+
this.postPowContext = ctx;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @description Generates a PoW Captcha for a given user and dapp
|
|
34
|
+
*
|
|
35
|
+
* @param {string} userAccount - user that is solving the captcha
|
|
36
|
+
* @param {string} dappAccount - dapp that is requesting the captcha
|
|
37
|
+
* @param origin - not currently used
|
|
38
|
+
* @param powDifficulty
|
|
39
|
+
*/
|
|
40
|
+
async getPowCaptchaChallenge(userAccount, dappAccount, origin, powDifficulty) {
|
|
41
|
+
const difficulty = powDifficulty || DEFAULT_POW_DIFFICULTY;
|
|
42
|
+
const requestedAtTimestamp = Date.now();
|
|
43
|
+
const challenge = `${requestedAtTimestamp}___${userAccount}___${dappAccount}___${Math.floor(Math.random() * 1e6)}`;
|
|
44
|
+
return {
|
|
45
|
+
challenge,
|
|
46
|
+
difficulty,
|
|
47
|
+
providerSignature: (0, _polkadot_util.u8aToHex)(this.pair.sign((0, _polkadot_util.stringToHex)(challenge))),
|
|
48
|
+
requestedAtTimestamp
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @description Verifies a PoW Captcha for a given user and dapp
|
|
53
|
+
*
|
|
54
|
+
* @param {string} challenge - the starting string for the PoW challenge
|
|
55
|
+
* @param {string} providerChallengeSignature - proof that the Provider provided the challenge
|
|
56
|
+
* @param {string} nonce - the string that the user has found that satisfies the PoW challenge
|
|
57
|
+
* @param {number} timeout - the time in milliseconds since the Provider was selected to provide the PoW captcha
|
|
58
|
+
* @param {string} userTimestampSignature
|
|
59
|
+
* @param ipAddress
|
|
60
|
+
* @param headers
|
|
61
|
+
* @param behavioralData
|
|
62
|
+
* @param salt
|
|
63
|
+
*/
|
|
64
|
+
async verifyPowCaptchaSolution(challenge, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress, headers, behavioralData, salt, simdReadings, clientMetaData) {
|
|
65
|
+
require_powTasksUtils.checkPowSignature(challenge, providerChallengeSignature, this.pair.address, _prosopo_types.ApiParams.challenge);
|
|
66
|
+
const challengeSplit = challenge.split(this.POW_SEPARATOR);
|
|
67
|
+
const timestamp = Number.parseInt((0, _prosopo_util.at)(challengeSplit, 0));
|
|
68
|
+
const userAccount = (0, _prosopo_util.at)(challengeSplit, 1);
|
|
69
|
+
require_powTasksUtils.checkPowSignature(timestamp.toString(), userTimestampSignature, userAccount, _prosopo_types.ApiParams.timestamp);
|
|
70
|
+
const challengeRecord = await this.db.getPowCaptchaRecordByChallenge(challenge);
|
|
71
|
+
if (!challengeRecord) {
|
|
72
|
+
this.logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
|
|
73
|
+
return { verified: false };
|
|
74
|
+
}
|
|
75
|
+
const difficulty = challengeRecord.difficulty;
|
|
76
|
+
let coords;
|
|
77
|
+
let saltDecodeError;
|
|
78
|
+
if (salt) try {
|
|
79
|
+
const extractedData = (0, _prosopo_util.extractData)(salt);
|
|
80
|
+
if (extractedData.length >= 2) {
|
|
81
|
+
const built = [[[extractedData[0], extractedData[1]]]];
|
|
82
|
+
(0, _prosopo_util.assertCoordsSafe)(built, "coords");
|
|
83
|
+
coords = built;
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
saltDecodeError = error;
|
|
87
|
+
this.logger.warn(() => ({
|
|
88
|
+
msg: "Failed to extract coordinates from salt",
|
|
89
|
+
error,
|
|
90
|
+
salt
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
if (saltDecodeError) {
|
|
94
|
+
const badSaltResult = {
|
|
95
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
96
|
+
reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_SALT
|
|
97
|
+
};
|
|
98
|
+
const writePromises = [this.db.updatePowCaptchaRecordResult(challenge, badSaltResult, false, true, userTimestampSignature, void 0)];
|
|
99
|
+
if (challengeRecord.sessionId) writePromises.push(this.updateSessionRecordWithCache(challengeRecord.sessionId, {
|
|
100
|
+
userSubmitted: true,
|
|
101
|
+
result: badSaltResult
|
|
102
|
+
}));
|
|
103
|
+
await Promise.all(writePromises);
|
|
104
|
+
return { verified: false };
|
|
105
|
+
}
|
|
106
|
+
if (!(0, _prosopo_util.verifyRecency)(challenge, timeout)) {
|
|
107
|
+
const timeoutResult = {
|
|
108
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
109
|
+
reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_TIMESTAMP
|
|
110
|
+
};
|
|
111
|
+
const writePromises = [this.db.updatePowCaptchaRecordResult(challenge, timeoutResult, false, true, userTimestampSignature, coords)];
|
|
112
|
+
if (challengeRecord.sessionId) writePromises.push(this.updateSessionRecordWithCache(challengeRecord.sessionId, {
|
|
113
|
+
userSubmitted: true,
|
|
114
|
+
result: timeoutResult
|
|
115
|
+
}));
|
|
116
|
+
await Promise.all(writePromises);
|
|
117
|
+
return { verified: false };
|
|
118
|
+
}
|
|
119
|
+
const correct = require_powTasksUtils.validateSolution(nonce, challenge, difficulty);
|
|
120
|
+
let result = { status: _prosopo_types.CaptchaStatus.approved };
|
|
121
|
+
if (!correct) result = {
|
|
122
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
123
|
+
reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_SOLUTION
|
|
124
|
+
};
|
|
125
|
+
if (correct && this.usageCounters) {
|
|
126
|
+
const dappAccount = (0, _prosopo_util.at)(challengeSplit, 2);
|
|
127
|
+
this.usageCounters.incrManyAsync(dappAccount, require_usageCounters.buildAllWindowIncrements("solved", _prosopo_types.CaptchaType.pow, ipAddress.address, userAccount));
|
|
128
|
+
}
|
|
129
|
+
let behavioralUpdates = {};
|
|
130
|
+
let decryptedBehavioralDataPacked;
|
|
131
|
+
if (behavioralData) try {
|
|
132
|
+
const decryptKeys = [...await this.getDetectorKeys(), process.env.BOT_DECRYPTION_KEY];
|
|
133
|
+
const decryptedData = await this.decryptBehavioralData(behavioralData, decryptKeys);
|
|
134
|
+
if (decryptedData) {
|
|
135
|
+
const dappAccount = (0, _prosopo_util.at)(challengeSplit, 2);
|
|
136
|
+
this.logger?.info(() => ({
|
|
137
|
+
msg: "Behavioral analysis completed",
|
|
138
|
+
data: {
|
|
139
|
+
userAccount,
|
|
140
|
+
dappAccount,
|
|
141
|
+
challenge,
|
|
142
|
+
mouseEventsCount: decryptedData.collector1?.length || 0,
|
|
143
|
+
touchEventsCount: decryptedData.collector2?.length || 0,
|
|
144
|
+
clickEventsCount: decryptedData.collector3?.length || 0,
|
|
145
|
+
deviceCapability: decryptedData.deviceCapability,
|
|
146
|
+
captchaResult: correct ? "passed" : "failed"
|
|
147
|
+
}
|
|
148
|
+
}));
|
|
149
|
+
const packedData = {
|
|
150
|
+
c1: decryptedData.collector1 || [],
|
|
151
|
+
c2: decryptedData.collector2 || [],
|
|
152
|
+
c3: decryptedData.collector3 || [],
|
|
153
|
+
d: decryptedData.deviceCapability
|
|
154
|
+
};
|
|
155
|
+
behavioralUpdates = {
|
|
156
|
+
behavioralDataPacked: packedData,
|
|
157
|
+
deviceCapability: decryptedData.deviceCapability
|
|
158
|
+
};
|
|
159
|
+
decryptedBehavioralDataPacked = packedData;
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
this.logger?.error(() => ({
|
|
163
|
+
msg: "Failed to process behavioral data",
|
|
164
|
+
err: error
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
const recordUpdates = { ...behavioralUpdates };
|
|
168
|
+
if (clientMetaData?.hp) recordUpdates.clientMetaData = { hp: clientMetaData.hp };
|
|
169
|
+
if (Object.keys(recordUpdates).length > 0) await this.db.updatePowCaptchaRecord(challenge, recordUpdates);
|
|
170
|
+
const writePromises = [this.db.updatePowCaptchaRecordResult(challenge, result, false, true, userTimestampSignature, coords)];
|
|
171
|
+
if (challengeRecord.sessionId) {
|
|
172
|
+
const linkedSessionId = challengeRecord.sessionId;
|
|
173
|
+
writePromises.push(this.updateSessionRecordWithCache(linkedSessionId, {
|
|
174
|
+
userSubmitted: true,
|
|
175
|
+
result
|
|
176
|
+
}));
|
|
177
|
+
if (simdReadings) writePromises.push(this.decryptAndAttachSimdReadingsIfAbsent(linkedSessionId, simdReadings, _prosopo_types.SimdReadingsStage.submit));
|
|
178
|
+
}
|
|
179
|
+
await Promise.all(writePromises);
|
|
180
|
+
if (!correct) return { verified: correct };
|
|
181
|
+
const escalateForMissingCoords = !coords && Boolean(challengeRecord.sessionId);
|
|
182
|
+
let routingOutput = this.postPowContext ? await this.runPostPowRouting({
|
|
183
|
+
challengeRecord,
|
|
184
|
+
challengeSplit,
|
|
185
|
+
behavioralDataPacked: decryptedBehavioralDataPacked
|
|
186
|
+
}) : void 0;
|
|
187
|
+
if (escalateForMissingCoords && routingOutput?.captchaType !== _prosopo_types.CaptchaType.image && routingOutput?.captchaType !== _prosopo_types.CaptchaType.puzzle) routingOutput = {
|
|
188
|
+
captchaType: _prosopo_types.CaptchaType.image,
|
|
189
|
+
reason: _prosopo_types.FrictionlessReason.MISSING_COORDINATES
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
verified: correct,
|
|
193
|
+
routingOutput
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Resolve the originating session, build a full RoutingContext, and run the
|
|
198
|
+
* post-pow phase of the routing machine. Returns the machine's output, or
|
|
199
|
+
* undefined when prerequisites are missing (no session, no score) — in
|
|
200
|
+
* which case the caller treats the result as "no escalation".
|
|
201
|
+
*/
|
|
202
|
+
async runPostPowRouting(args) {
|
|
203
|
+
if (!this.postPowContext) return void 0;
|
|
204
|
+
const { challengeRecord, challengeSplit, behavioralDataPacked } = args;
|
|
205
|
+
if (!challengeRecord.sessionId) {
|
|
206
|
+
this.logger.debug(() => ({ msg: "Skipping post-pow routing: PoW record has no linked session" }));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const sessionRecord = await this.db.getSessionRecordBySessionId(challengeRecord.sessionId);
|
|
210
|
+
if (!sessionRecord) {
|
|
211
|
+
this.logger.debug(() => ({
|
|
212
|
+
msg: "Skipping post-pow routing: session record not found",
|
|
213
|
+
data: { sessionId: challengeRecord.sessionId }
|
|
214
|
+
}));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const score = require_frictionlessTasksUtils.computeFrictionlessScore(sessionRecord.scoreComponents);
|
|
218
|
+
const dappAccount = (0, _prosopo_util.at)(challengeSplit, 2);
|
|
219
|
+
const userAccount = (0, _prosopo_util.at)(challengeSplit, 1);
|
|
220
|
+
const platform = {
|
|
221
|
+
...this.postPowContext.platform,
|
|
222
|
+
isWebView: sessionRecord.webView
|
|
223
|
+
};
|
|
224
|
+
const ctx = {
|
|
225
|
+
dappAccount,
|
|
226
|
+
userAccount,
|
|
227
|
+
ip: this.postPowContext.ip,
|
|
228
|
+
countryCode: this.postPowContext.countryCode,
|
|
229
|
+
score,
|
|
230
|
+
platform,
|
|
231
|
+
raw: {
|
|
232
|
+
...this.postPowContext.raw,
|
|
233
|
+
...behavioralDataPacked && { behavioralDataPacked },
|
|
234
|
+
...sessionRecord.simdReadings && { simd: sessionRecord.simdReadings },
|
|
235
|
+
...sessionRecord.currentUrl && { currentUrl: sessionRecord.currentUrl },
|
|
236
|
+
...sessionRecord.iframeUrl && { iframeUrl: sessionRecord.iframeUrl }
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const baseline = {
|
|
240
|
+
captchaType: _prosopo_types.CaptchaType.pow,
|
|
241
|
+
powDifficulty: challengeRecord.difficulty
|
|
242
|
+
};
|
|
243
|
+
return require_routingMachine.applyRouter(this.decisionMachineRunner, this.usageCounters, baseline, ctx, this.logger, "postPow");
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* @description Verifies a PoW Captcha for a given user and dapp. This is called by the server to verify the user's solution
|
|
247
|
+
* and update the record in the database to show that the user has solved the captcha
|
|
248
|
+
*
|
|
249
|
+
* @param {string} dappAccount - the dapp that is requesting the captcha
|
|
250
|
+
* @param {string} challenge - the starting string for the PoW challenge
|
|
251
|
+
* @param {number} timeout - the time in milliseconds since the Provider was selected to provide the PoW captcha
|
|
252
|
+
* @param env - provider environment
|
|
253
|
+
* @param ip - optional IP address for validation
|
|
254
|
+
* @param userAccessRulesStorage - storage for querying user access policies
|
|
255
|
+
* @param email
|
|
256
|
+
* @param spamEmailDomainCheckingEnabled
|
|
257
|
+
* @param spamFilter
|
|
258
|
+
* @param trafficFilter
|
|
259
|
+
* @param storeMetadata - when true, persists the dapp-server-provided
|
|
260
|
+
* `email` (and any future metadata fields) on the captcha record so
|
|
261
|
+
* it can be inspected for spam-rate analysis.
|
|
262
|
+
*/
|
|
263
|
+
async serverVerifyPowCaptchaSolution(dappAccount, challenge, timeout, env, ip, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false) {
|
|
264
|
+
const notVerified = (reason) => ({
|
|
265
|
+
verified: false,
|
|
266
|
+
reason
|
|
267
|
+
});
|
|
268
|
+
const logger = this.logger.with({
|
|
269
|
+
challenge,
|
|
270
|
+
dappAccount
|
|
271
|
+
});
|
|
272
|
+
const challengeRecord = await this.db.getPowCaptchaRecordByChallenge(challenge);
|
|
273
|
+
if (!challengeRecord) {
|
|
274
|
+
logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
|
|
275
|
+
return notVerified("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND");
|
|
276
|
+
}
|
|
277
|
+
if (challengeRecord.result.status !== _prosopo_types.CaptchaStatus.approved) throw new _prosopo_common.ProsopoApiError("CAPTCHA.INVALID_SOLUTION", { context: {
|
|
278
|
+
code: 400,
|
|
279
|
+
failedFuncName: this.serverVerifyPowCaptchaSolution.name,
|
|
280
|
+
challenge
|
|
281
|
+
} });
|
|
282
|
+
if (challengeRecord.serverChecked) return notVerified("API.USER_ALREADY_VERIFIED");
|
|
283
|
+
const challengeDappAccount = challengeRecord.dappAccount;
|
|
284
|
+
if (dappAccount !== challengeDappAccount) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", { context: {
|
|
285
|
+
failedFuncName: this.serverVerifyPowCaptchaSolution.name,
|
|
286
|
+
dappAccount,
|
|
287
|
+
challengeDappAccount
|
|
288
|
+
} });
|
|
289
|
+
await this.db.markDappUserPoWCommitmentsChecked([challengeRecord.challenge]);
|
|
290
|
+
const powRecordUpdates = {};
|
|
291
|
+
let failResult;
|
|
292
|
+
let failReason;
|
|
293
|
+
const submittedAt = challengeRecord.submittedAtTimestamp;
|
|
294
|
+
if ((submittedAt instanceof Date ? Date.now() - submittedAt.getTime() : Number.POSITIVE_INFINITY) > timeout) {
|
|
295
|
+
failResult = {
|
|
296
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
297
|
+
reason: _prosopo_types.ResultReason.TIMESTAMP_TOO_OLD
|
|
298
|
+
};
|
|
299
|
+
failReason = "API.TIMESTAMP_TOO_OLD";
|
|
300
|
+
}
|
|
301
|
+
if (!failResult && userAccessRulesStorage) try {
|
|
302
|
+
const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, challengeRecord, challengeRecord.userAccount, challengeRecord.headers, challengeRecord.coords, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.asnNumber : void 0);
|
|
303
|
+
if (blockPolicy) {
|
|
304
|
+
logger.info(() => ({
|
|
305
|
+
msg: "User blocked by access policy in server PoW verification",
|
|
306
|
+
data: {
|
|
307
|
+
userAccount: challengeRecord.userAccount,
|
|
308
|
+
policy: blockPolicy
|
|
309
|
+
}
|
|
310
|
+
}));
|
|
311
|
+
failResult = {
|
|
312
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
313
|
+
reason: _prosopo_types.ResultReason.ACCESS_POLICY_BLOCK
|
|
314
|
+
};
|
|
315
|
+
failReason = "API.ACCESS_POLICY_BLOCK";
|
|
316
|
+
}
|
|
317
|
+
} catch (error) {
|
|
318
|
+
logger.warn(() => ({
|
|
319
|
+
msg: "Failed to check user access policies in server PoW verification",
|
|
320
|
+
error
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
323
|
+
if (!failResult && email && spamEmailDomainCheckingEnabled) try {
|
|
324
|
+
if (await this.checkSpamEmail(email)) {
|
|
325
|
+
const emailDomain = email.split("@")[1] || "unknown";
|
|
326
|
+
logger.info(() => ({
|
|
327
|
+
msg: "Spam email domain detected in server PoW verification",
|
|
328
|
+
data: { emailDomain }
|
|
329
|
+
}));
|
|
330
|
+
failResult = {
|
|
331
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
332
|
+
reason: _prosopo_types.ResultReason.SPAM_EMAIL_DOMAIN
|
|
333
|
+
};
|
|
334
|
+
failReason = "API.SPAM_EMAIL_DOMAIN";
|
|
335
|
+
}
|
|
336
|
+
} catch (error) {
|
|
337
|
+
logger.warn(() => ({
|
|
338
|
+
msg: "Failed to check spam email domain in server PoW verification",
|
|
339
|
+
error
|
|
340
|
+
}));
|
|
341
|
+
}
|
|
342
|
+
if (!failResult && spamFilter?.enabled && spamFilter.emailRules?.enabled && email) {
|
|
343
|
+
const result = require_evaluateEmailSpamRules.evaluateEmailSpamRules(email, spamFilter.emailRules);
|
|
344
|
+
if (result.isSpam) {
|
|
345
|
+
logger.info(() => ({
|
|
346
|
+
msg: "Spam filter rejected email in PoW verification",
|
|
347
|
+
data: { reason: result.reason }
|
|
348
|
+
}));
|
|
349
|
+
failResult = {
|
|
350
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
351
|
+
reason: _prosopo_types.ResultReason.SPAM_EMAIL_RULE
|
|
352
|
+
};
|
|
353
|
+
failReason = "API.SPAM_EMAIL_RULE";
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const sessionRecord = challengeRecord.sessionId ? await this.db.getSessionRecordBySessionId(challengeRecord.sessionId) : void 0;
|
|
357
|
+
const enrichedDnsEvent = await require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? challengeRecord.ipInfo?.ip);
|
|
358
|
+
if (!failResult) {
|
|
359
|
+
const check = await this.resolveTrafficFilterCheck(env, challengeRecord.ipInfo, trafficFilter, ip, enrichedDnsEvent);
|
|
360
|
+
if (check.isBlocked) {
|
|
361
|
+
logger.info(() => ({
|
|
362
|
+
msg: "Traffic filter rejected request in PoW verification",
|
|
363
|
+
data: {
|
|
364
|
+
ip,
|
|
365
|
+
reason: check.reason,
|
|
366
|
+
dnsPeerIp: enrichedDnsEvent?.peerIp,
|
|
367
|
+
dnsResolverIp: enrichedDnsEvent?.resolverIp,
|
|
368
|
+
dnsPeerAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
369
|
+
dnsResolverAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
|
|
370
|
+
dnsPathValid: enrichedDnsEvent?.pathValid
|
|
371
|
+
}
|
|
372
|
+
}));
|
|
373
|
+
failResult = {
|
|
374
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
375
|
+
reason: check.reason
|
|
376
|
+
};
|
|
377
|
+
failReason = check.reason;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (storeMetadata && email) powRecordUpdates.metadata = { email };
|
|
381
|
+
if (!failResult && ip) {
|
|
382
|
+
const challengeIpAddress = require_compositeIpAddress.getIpAddressFromComposite(challengeRecord.ipAddress);
|
|
383
|
+
const ipValidationRules = (await this.db.getClientRecord(dappAccount))?.settings?.ipValidationRules;
|
|
384
|
+
powRecordUpdates.providedIp = require_compositeIpAddress.getCompositeIpAddress(ip);
|
|
385
|
+
if (ipValidationRules?.enabled === true) {
|
|
386
|
+
const ipValidation = await require_util.deepValidateIpAddress(ip, challengeIpAddress, logger, env.ipInfoService, ipValidationRules, enrichedDnsEvent?.peerIp);
|
|
387
|
+
if (!ipValidation.isValid) {
|
|
388
|
+
logger.error(() => ({
|
|
389
|
+
msg: "IP validation failed for PoW captcha",
|
|
390
|
+
data: {
|
|
391
|
+
ip,
|
|
392
|
+
challengeIp: challengeIpAddress.address,
|
|
393
|
+
error: ipValidation.errorMessage,
|
|
394
|
+
distanceKm: ipValidation.distanceKm
|
|
395
|
+
}
|
|
396
|
+
}));
|
|
397
|
+
failResult = {
|
|
398
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
399
|
+
reason: _prosopo_types.ResultReason.FAILED_IP_VALIDATION
|
|
400
|
+
};
|
|
401
|
+
failReason = "API.FAILED_IP_VALIDATION";
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
let score;
|
|
406
|
+
if (sessionRecord) {
|
|
407
|
+
const dnsAsymmetry = require_enrichDnsEvent.computeDnsAsymmetry(enrichedDnsEvent, challengeRecord.ipInfo, trafficFilter);
|
|
408
|
+
if (dnsAsymmetry > 0) sessionRecord.scoreComponents = {
|
|
409
|
+
...sessionRecord.scoreComponents,
|
|
410
|
+
dnsAsymmetry
|
|
411
|
+
};
|
|
412
|
+
score = require_frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
|
|
413
|
+
logger.info(() => ({ data: {
|
|
414
|
+
scoreComponents: { ...sessionRecord?.scoreComponents || {} },
|
|
415
|
+
score,
|
|
416
|
+
dnsPeerAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
|
|
417
|
+
dnsResolverAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
|
|
418
|
+
} }));
|
|
419
|
+
}
|
|
420
|
+
if (!failResult) try {
|
|
421
|
+
const decisionInput = {
|
|
422
|
+
userAccount: challengeRecord.userAccount,
|
|
423
|
+
dappAccount: challengeRecord.dappAccount,
|
|
424
|
+
captchaResult: "passed",
|
|
425
|
+
headers: challengeRecord.headers,
|
|
426
|
+
captchaType: _prosopo_types.CaptchaType.pow,
|
|
427
|
+
behavioralDataPacked: challengeRecord.behavioralDataPacked,
|
|
428
|
+
deviceCapability: challengeRecord.deviceCapability,
|
|
429
|
+
countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0,
|
|
430
|
+
ipInfo: challengeRecord.ipInfo,
|
|
431
|
+
dnsEvent: enrichedDnsEvent,
|
|
432
|
+
score,
|
|
433
|
+
threshold: sessionRecord?.threshold,
|
|
434
|
+
scoreComponents: sessionRecord?.scoreComponents,
|
|
435
|
+
decryptedHeadHash: sessionRecord?.decryptedHeadHash,
|
|
436
|
+
userSitekeyIpHash: sessionRecord?.userSitekeyIpHash,
|
|
437
|
+
simdReadings: sessionRecord?.simdReadings,
|
|
438
|
+
frictionlessReason: sessionRecord?.reason,
|
|
439
|
+
ruleType: sessionRecord?.ruleType,
|
|
440
|
+
webView: sessionRecord?.webView,
|
|
441
|
+
iFrame: sessionRecord?.iFrame,
|
|
442
|
+
coords: challengeRecord.coords
|
|
443
|
+
};
|
|
444
|
+
const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
|
|
445
|
+
if (decision.decision === _prosopo_types.DecisionMachineDecision.Deny) {
|
|
446
|
+
logger.info(() => ({
|
|
447
|
+
msg: "Decision machine denied PoW captcha in server verification",
|
|
448
|
+
data: {
|
|
449
|
+
userAccount: challengeRecord.userAccount,
|
|
450
|
+
reason: decision.reason,
|
|
451
|
+
score: decision.score,
|
|
452
|
+
tags: decision.tags
|
|
453
|
+
}
|
|
454
|
+
}));
|
|
455
|
+
const dmReason = decision.reason || _prosopo_types.ResultReason.CAPTCHA_DECISION_MACHINE_DENIED;
|
|
456
|
+
failResult = {
|
|
457
|
+
status: _prosopo_types.CaptchaStatus.disapproved,
|
|
458
|
+
reason: dmReason
|
|
459
|
+
};
|
|
460
|
+
failReason = dmReason;
|
|
461
|
+
} else logger.debug(() => ({
|
|
462
|
+
msg: "Decision machine allowed PoW captcha",
|
|
463
|
+
data: {
|
|
464
|
+
reason: decision.reason,
|
|
465
|
+
score: decision.score,
|
|
466
|
+
tags: decision.tags
|
|
467
|
+
}
|
|
468
|
+
}));
|
|
469
|
+
} catch (error) {
|
|
470
|
+
logger.error(() => ({
|
|
471
|
+
msg: "Failed to run decision machine in server PoW verification",
|
|
472
|
+
err: error
|
|
473
|
+
}));
|
|
474
|
+
}
|
|
475
|
+
const finalResult = failResult || { status: _prosopo_types.CaptchaStatus.approved };
|
|
476
|
+
if (failResult) powRecordUpdates.result = failResult;
|
|
477
|
+
const writePromises = [];
|
|
478
|
+
if (Object.keys(powRecordUpdates).length > 0) writePromises.push(this.db.updatePowCaptchaRecord(challengeRecord.challenge, powRecordUpdates));
|
|
479
|
+
if (challengeRecord.sessionId) writePromises.push(this.updateSessionRecordWithCache(challengeRecord.sessionId, {
|
|
480
|
+
serverChecked: true,
|
|
481
|
+
result: finalResult
|
|
482
|
+
}, true));
|
|
483
|
+
if (writePromises.length > 0) await Promise.all(writePromises);
|
|
484
|
+
if (failReason) return notVerified(failReason);
|
|
485
|
+
return {
|
|
486
|
+
verified: true,
|
|
487
|
+
...score ? { score } : {}
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
//#endregion
|
|
688
492
|
exports.PowCaptchaManager = PowCaptchaManager;
|