@prosopo/provider 4.15.14 → 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.
Files changed (232) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +106 -106
  2. package/.turbo/turbo-build$colon$tsc.log +24 -24
  3. package/.turbo/turbo-build.log +107 -104
  4. package/CHANGELOG.md +49 -0
  5. package/dist/_virtual/_rolldown/runtime.js +3 -0
  6. package/dist/api/admin/apiAdminRoutesProvider.js +27 -46
  7. package/dist/api/admin/apiClearAllCountersEndpoint.js +62 -57
  8. package/dist/api/admin/apiDnsEventEndpoint.js +79 -92
  9. package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js +43 -45
  10. package/dist/api/admin/apiGetDecisionMachineEndpoint.js +40 -40
  11. package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +23 -22
  12. package/dist/api/admin/apiRegisterSiteKeysEndpoint.js +26 -30
  13. package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js +35 -37
  14. package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js +40 -40
  15. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +1 -1
  16. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +29 -31
  17. package/dist/api/admin/apiRemoveSiteKeyEndpoint.js +33 -29
  18. package/dist/api/admin/apiRemoveSiteKeysEndpoint.js +32 -31
  19. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +43 -35
  20. package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js +43 -63
  21. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +36 -35
  22. package/dist/api/admin/createApiAdminRoutesProvider.js +6 -8
  23. package/dist/api/blacklistRequestInspector.js +285 -377
  24. package/dist/api/block.js +17 -30
  25. package/dist/api/captcha/checkSpamEmail.js +88 -98
  26. package/dist/api/captcha/contextAwareValidation.js +21 -15
  27. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +126 -140
  28. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -12
  29. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +236 -299
  30. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.js +10 -13
  31. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +336 -462
  32. package/dist/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.js +17 -14
  33. package/dist/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.js +27 -27
  34. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +42 -63
  35. package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +2 -4
  36. package/dist/api/captcha/getImageCaptchaChallenge.js +136 -207
  37. package/dist/api/captcha/getPoWCaptchaChallenge.js +128 -198
  38. package/dist/api/captcha/getPuzzleCaptchaChallenge.js +132 -201
  39. package/dist/api/captcha/maintenanceModeResponses.js +38 -47
  40. package/dist/api/captcha/submitImageCaptchaSolution.js +75 -101
  41. package/dist/api/captcha/submitPoWCaptchaSolution.js +137 -207
  42. package/dist/api/captcha/submitPuzzleCaptchaSolution.js +73 -105
  43. package/dist/api/captcha.js +76 -58
  44. package/dist/api/dnsEventUrl.js +20 -22
  45. package/dist/api/domainMiddleware.js +104 -115
  46. package/dist/api/forwardVerify.js +62 -48
  47. package/dist/api/handshakeTimingMiddleware.js +43 -62
  48. package/dist/api/hardBlockVerdictCache.js +114 -117
  49. package/dist/api/headerCheckMiddleware.js +34 -34
  50. package/dist/api/ignoreMiddleware.js +13 -15
  51. package/dist/api/ipInfoMiddleware.js +17 -19
  52. package/dist/api/ja4.js +149 -188
  53. package/dist/api/ja4Middleware.js +39 -54
  54. package/dist/api/metrics.js +245 -257
  55. package/dist/api/public.js +52 -54
  56. package/dist/api/robotsMiddleware.js +10 -10
  57. package/dist/api/startProviderApi.js +205 -232
  58. package/dist/api/testSiteKey.js +16 -16
  59. package/dist/api/validateAddress.js +23 -21
  60. package/dist/api/verify.js +334 -377
  61. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  62. package/dist/cjs/api/admin/apiAdminRoutesProvider.cjs +40 -59
  63. package/dist/cjs/api/admin/apiClearAllCountersEndpoint.cjs +63 -58
  64. package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +82 -93
  65. package/dist/cjs/api/admin/apiGetAllDecisionMachinesEndpoint.cjs +46 -48
  66. package/dist/cjs/api/admin/apiGetDecisionMachineEndpoint.cjs +41 -41
  67. package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +25 -24
  68. package/dist/cjs/api/admin/apiRegisterSiteKeysEndpoint.cjs +28 -32
  69. package/dist/cjs/api/admin/apiRemoveAllDecisionMachinesEndpoint.cjs +38 -40
  70. package/dist/cjs/api/admin/apiRemoveDecisionMachineEndpoint.cjs +41 -41
  71. package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +31 -33
  72. package/dist/cjs/api/admin/apiRemoveSiteKeyEndpoint.cjs +35 -31
  73. package/dist/cjs/api/admin/apiRemoveSiteKeysEndpoint.cjs +34 -33
  74. package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +45 -35
  75. package/dist/cjs/api/admin/apiUpdateDecisionMachineEndpoint.cjs +45 -65
  76. package/dist/cjs/api/admin/apiUpdateDetectorKeyEndpoint.cjs +38 -37
  77. package/dist/cjs/api/admin/createApiAdminRoutesProvider.cjs +7 -8
  78. package/dist/cjs/api/blacklistRequestInspector.cjs +288 -376
  79. package/dist/cjs/api/block.cjs +18 -30
  80. package/dist/cjs/api/captcha/checkSpamEmail.cjs +90 -100
  81. package/dist/cjs/api/captcha/contextAwareValidation.cjs +21 -14
  82. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +125 -140
  83. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -10
  84. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +238 -301
  85. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.cjs +9 -12
  86. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +349 -473
  87. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.cjs +18 -14
  88. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.cjs +26 -26
  89. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +42 -63
  90. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +2 -3
  91. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +138 -208
  92. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +131 -200
  93. package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +135 -203
  94. package/dist/cjs/api/captcha/maintenanceModeResponses.cjs +38 -44
  95. package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +77 -102
  96. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +140 -209
  97. package/dist/cjs/api/captcha/submitPuzzleCaptchaSolution.cjs +76 -107
  98. package/dist/cjs/api/captcha.cjs +79 -58
  99. package/dist/cjs/api/dnsEventUrl.cjs +20 -21
  100. package/dist/cjs/api/domainMiddleware.cjs +106 -117
  101. package/dist/cjs/api/forwardVerify.cjs +63 -49
  102. package/dist/cjs/api/handshakeTimingMiddleware.cjs +43 -61
  103. package/dist/cjs/api/hardBlockVerdictCache.cjs +114 -114
  104. package/dist/cjs/api/headerCheckMiddleware.cjs +34 -34
  105. package/dist/cjs/api/ignoreMiddleware.cjs +12 -14
  106. package/dist/cjs/api/ipInfoMiddleware.cjs +16 -18
  107. package/dist/cjs/api/ja4.cjs +149 -187
  108. package/dist/cjs/api/ja4Middleware.cjs +40 -53
  109. package/dist/cjs/api/metrics.cjs +229 -228
  110. package/dist/cjs/api/public.cjs +57 -57
  111. package/dist/cjs/api/robotsMiddleware.cjs +9 -9
  112. package/dist/cjs/api/startProviderApi.cjs +219 -237
  113. package/dist/cjs/api/testSiteKey.cjs +15 -14
  114. package/dist/cjs/api/validateAddress.cjs +24 -21
  115. package/dist/cjs/api/verify.cjs +338 -379
  116. package/dist/cjs/compositeIpAddress.cjs +40 -47
  117. package/dist/cjs/index.cjs +65 -71
  118. package/dist/cjs/pairs.cjs +31 -35
  119. package/dist/cjs/rules/lang.cjs +10 -14
  120. package/dist/cjs/schedulers/captchaScheduler.cjs +26 -32
  121. package/dist/cjs/schedulers/getClientList.cjs +35 -33
  122. package/dist/cjs/schedulers/setClientEntropy.cjs +35 -33
  123. package/dist/cjs/schedulers/updateSpamEmailDomains.cjs +39 -43
  124. package/dist/cjs/services/ipComparison.cjs +122 -119
  125. package/dist/cjs/tasks/captchaManager.cjs +407 -486
  126. package/dist/cjs/tasks/client/clientTasks.cjs +347 -470
  127. package/dist/cjs/tasks/dataset/datasetTasks.cjs +25 -29
  128. package/dist/cjs/tasks/dataset/datasetTasksUtils.cjs +16 -32
  129. package/dist/cjs/tasks/decisionMachine/decisionMachineRunner.cjs +220 -307
  130. package/dist/cjs/tasks/detection/decodeBehavior.cjs +408 -317
  131. package/dist/cjs/tasks/detection/decodePayload.cjs +686 -468
  132. package/dist/cjs/tasks/detection/decodeSimd.cjs +462 -304
  133. package/dist/cjs/tasks/detection/getBotScore.cjs +37 -43
  134. package/dist/cjs/tasks/dnsEvent/enrichDnsEvent.cjs +88 -71
  135. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +348 -486
  136. package/dist/cjs/tasks/frictionless/frictionlessTasksUtils.cjs +13 -30
  137. package/dist/cjs/tasks/frictionless/routingMachine.cjs +71 -55
  138. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +555 -806
  139. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasksUtils.cjs +22 -23
  140. package/dist/cjs/tasks/index.cjs +2 -4
  141. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +491 -687
  142. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +17 -29
  143. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +422 -591
  144. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasksUtils.cjs +8 -5
  145. package/dist/cjs/tasks/spam/checkSpamEmail.cjs +133 -141
  146. package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +118 -76
  147. package/dist/cjs/tasks/spam/evaluateEmailSpamRules.cjs +75 -84
  148. package/dist/cjs/tasks/spam/updateSpamEmailDomains.cjs +40 -56
  149. package/dist/cjs/tasks/tasks.cjs +107 -158
  150. package/dist/cjs/util/usageCounters.cjs +220 -211
  151. package/dist/cjs/util.cjs +329 -359
  152. package/dist/cjs/utils/devicePlatform.cjs +14 -8
  153. package/dist/cjs/utils/dns.cjs +68 -93
  154. package/dist/cjs/utils/hashUserAgent.cjs +14 -7
  155. package/dist/cjs/utils/hashUserIp.cjs +14 -6
  156. package/dist/cjs/utils/honeypot/encoders.cjs +74 -80
  157. package/dist/cjs/utils/honeypot/phraseBank.cjs +51 -44
  158. package/dist/cjs/utils/normalizeRequestIp.cjs +33 -25
  159. package/dist/compositeIpAddress.js +38 -46
  160. package/dist/index.js +12 -56
  161. package/dist/pairs.js +31 -37
  162. package/dist/rules/lang.js +11 -15
  163. package/dist/schedulers/captchaScheduler.js +25 -31
  164. package/dist/schedulers/getClientList.js +34 -32
  165. package/dist/schedulers/setClientEntropy.js +34 -32
  166. package/dist/schedulers/updateSpamEmailDomains.js +38 -42
  167. package/dist/services/ipComparison.js +122 -119
  168. package/dist/tasks/captchaManager.js +403 -483
  169. package/dist/tasks/client/clientTasks.js +343 -467
  170. package/dist/tasks/dataset/datasetTasks.js +24 -28
  171. package/dist/tasks/dataset/datasetTasksUtils.js +15 -31
  172. package/dist/tasks/decisionMachine/decisionMachineRunner.js +217 -306
  173. package/dist/tasks/detection/getBotScore.js +37 -43
  174. package/dist/tasks/dnsEvent/enrichDnsEvent.d.ts.map +1 -1
  175. package/dist/tasks/dnsEvent/enrichDnsEvent.js +88 -74
  176. package/dist/tasks/dnsEvent/enrichDnsEvent.js.map +1 -1
  177. package/dist/tasks/frictionless/frictionlessTasks.js +342 -479
  178. package/dist/tasks/frictionless/frictionlessTasksUtils.js +14 -32
  179. package/dist/tasks/frictionless/routingMachine.js +72 -56
  180. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +550 -801
  181. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +21 -22
  182. package/dist/tasks/index.js +1 -3
  183. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  184. package/dist/tasks/powCaptcha/powTasks.js +486 -682
  185. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  186. package/dist/tasks/powCaptcha/powTasksUtils.js +15 -28
  187. package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
  188. package/dist/tasks/puzzleCaptcha/puzzleTasks.js +417 -586
  189. package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
  190. package/dist/tasks/puzzleCaptcha/puzzleTasksUtils.js +9 -6
  191. package/dist/tasks/spam/checkSpamEmail.js +133 -141
  192. package/dist/tasks/spam/checkTrafficFilter.d.ts +1 -0
  193. package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
  194. package/dist/tasks/spam/checkTrafficFilter.js +117 -77
  195. package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
  196. package/dist/tasks/spam/evaluateEmailSpamRules.js +75 -86
  197. package/dist/tasks/spam/updateSpamEmailDomains.js +36 -54
  198. package/dist/tasks/tasks.js +98 -150
  199. package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js +4 -1
  200. package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js.map +1 -1
  201. package/dist/tests/unit/api/block.unit.test.js +8 -4
  202. package/dist/tests/unit/api/block.unit.test.js.map +1 -1
  203. package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js +8 -6
  204. package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js.map +1 -1
  205. package/dist/tests/unit/api/forwardVerify.unit.test.js +3 -1
  206. package/dist/tests/unit/api/forwardVerify.unit.test.js.map +1 -1
  207. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +15 -7
  208. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  209. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +24 -18
  210. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -1
  211. package/dist/tests/unit/schedulers/getClientList.unit.test.js +19 -13
  212. package/dist/tests/unit/schedulers/getClientList.unit.test.js.map +1 -1
  213. package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js +19 -13
  214. package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js.map +1 -1
  215. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
  216. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +22 -16
  217. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
  218. package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js +140 -0
  219. package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js.map +1 -1
  220. package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +7 -7
  221. package/dist/util/usageCounters.js +220 -212
  222. package/dist/util.d.ts.map +1 -1
  223. package/dist/util.js +327 -364
  224. package/dist/util.js.map +1 -1
  225. package/dist/utils/devicePlatform.js +15 -9
  226. package/dist/utils/dns.js +64 -77
  227. package/dist/utils/hashUserAgent.js +14 -7
  228. package/dist/utils/hashUserIp.js +14 -6
  229. package/dist/utils/honeypot/encoders.js +74 -80
  230. package/dist/utils/honeypot/phraseBank.js +49 -44
  231. package/dist/utils/normalizeRequestIp.js +34 -26
  232. package/package.json +24 -24
@@ -1,384 +1,341 @@
1
- import { VERIFY_FORWARDED_HEADER } from "@prosopo/api";
2
- import { verifySignature, handleErrors } from "@prosopo/api-express-router";
3
- import { ProsopoApiError } from "@prosopo/common";
4
- import { decodeProcaptchaOutput, ClientApiPaths, CaptchaType, VerifySolutionBody, ApiParams, ServerPowCaptchaVerifyRequestBody, ServerPuzzleCaptchaVerifyRequestBody } from "@prosopo/types";
5
- import { validateAddress } from "@prosopo/util-crypto";
6
- import express from "express";
1
+ import { metricsEnabled, recordCaptchaVerify } from "./metrics.js";
7
2
  import { Tasks } from "../tasks/tasks.js";
8
3
  import { getMaintenanceMode } from "./admin/apiToggleMaintenanceModeEndpoint.js";
9
- import { forwardVerifyIfNotIssuer } from "./forwardVerify.js";
10
- import { metricsEnabled, recordCaptchaVerify } from "./metrics.js";
11
4
  import { isReservedTestSiteKey, resolveTestSiteKeyVerdict } from "./testSiteKey.js";
12
- const deriveVerifySource = (body) => {
13
- if (getMaintenanceMode()) return "maintenance";
14
- try {
15
- const token = body?.token;
16
- if (token) {
17
- const { dapp } = decodeProcaptchaOutput(token);
18
- if (isReservedTestSiteKey(dapp)) return "test_key";
19
- }
20
- } catch {
21
- }
22
- return "real";
5
+ import { forwardVerifyIfNotIssuer } from "./forwardVerify.js";
6
+ import { ProsopoApiError } from "@prosopo/common";
7
+ import { ApiParams, CaptchaType, ClientApiPaths, ServerPowCaptchaVerifyRequestBody, ServerPuzzleCaptchaVerifyRequestBody, VerifySolutionBody, decodeProcaptchaOutput } from "@prosopo/types";
8
+ import { validateAddress } from "@prosopo/util-crypto";
9
+ import { handleErrors, verifySignature } from "@prosopo/api-express-router";
10
+ import express from "express";
11
+ import { VERIFY_FORWARDED_HEADER } from "@prosopo/api";
12
+ //#region src/api/verify.ts
13
+ var deriveVerifySource = (body) => {
14
+ if (getMaintenanceMode()) return "maintenance";
15
+ try {
16
+ const token = body?.token;
17
+ if (token) {
18
+ const { dapp } = decodeProcaptchaOutput(token);
19
+ if (isReservedTestSiteKey(dapp)) return "test_key";
20
+ }
21
+ } catch {}
22
+ return "real";
23
23
  };
24
- const VERIFY_PATH_TYPE = {
25
- [ClientApiPaths.VerifyImageCaptchaSolutionDapp]: CaptchaType.image,
26
- [ClientApiPaths.VerifyPowCaptchaSolution]: CaptchaType.pow,
27
- [ClientApiPaths.VerifyPuzzleCaptchaSolution]: CaptchaType.puzzle
24
+ var VERIFY_PATH_TYPE = {
25
+ [ClientApiPaths.VerifyImageCaptchaSolutionDapp]: CaptchaType.image,
26
+ [ClientApiPaths.VerifyPowCaptchaSolution]: CaptchaType.pow,
27
+ [ClientApiPaths.VerifyPuzzleCaptchaSolution]: CaptchaType.puzzle
28
28
  };
29
+ /**
30
+ * Returns a router connected to the database which can interact with the Proposo protocol
31
+ *
32
+ * @return {Router} - A middleware router that can interact with the Prosopo protocol
33
+ * @param {Environment} env - The Prosopo environment
34
+ */
29
35
  function prosopoVerifyRouter(env) {
30
- const router = express.Router();
31
- let userAccessRulesStorage;
32
- try {
33
- userAccessRulesStorage = env.getDb().getUserAccessRulesStorage();
34
- } catch (err) {
35
- env.logger.warn(() => ({
36
- msg: "User access rules storage unavailable; verify endpoints will skip access-policy checks",
37
- err
38
- }));
39
- userAccessRulesStorage = void 0;
40
- }
41
- router.use((req, res, next) => {
42
- if (!metricsEnabled()) return next();
43
- const type = VERIFY_PATH_TYPE[req.path];
44
- if (!type) return next();
45
- const originalJson = res.json.bind(res);
46
- res.json = (body) => {
47
- if (res.statusCode < 300) {
48
- const verified = !!(body && typeof body === "object" && body.verified);
49
- recordCaptchaVerify({
50
- type,
51
- verified,
52
- source: deriveVerifySource(req.body)
53
- });
54
- }
55
- return originalJson(body);
56
- };
57
- next();
58
- });
59
- router.post(
60
- ClientApiPaths.VerifyImageCaptchaSolutionDapp,
61
- async (req, res, next) => {
62
- if (getMaintenanceMode()) {
63
- req.logger.info(() => ({
64
- msg: "Maintenance mode active - returning verified for image captcha verification"
65
- }));
66
- const verificationResponse = {
67
- status: "ok",
68
- verified: true
69
- };
70
- return res.json(verificationResponse);
71
- }
72
- let parsed;
73
- try {
74
- parsed = VerifySolutionBody.parse(req.body);
75
- } catch (err) {
76
- return next(
77
- new ProsopoApiError("CAPTCHA.PARSE_ERROR", {
78
- context: { code: 400, error: err, body: req.body },
79
- i18n: req.i18n,
80
- logger: req.logger
81
- })
82
- );
83
- }
84
- const { dappSignature, token, ip, maxVerifiedTime, email } = parsed;
85
- try {
86
- const { user, dapp, timestamp, commitmentId, providerUrl } = decodeProcaptchaOutput(token);
87
- const testVerdict = resolveTestSiteKeyVerdict(dapp, req.logger);
88
- if (testVerdict !== null) {
89
- const verificationResponse2 = {
90
- status: "ok",
91
- verified: testVerdict
92
- };
93
- return res.json(verificationResponse2);
94
- }
95
- const forwarded = await forwardVerifyIfNotIssuer({
96
- env,
97
- logger: req.logger,
98
- path: ClientApiPaths.VerifyImageCaptchaSolutionDapp,
99
- providerUrl,
100
- dapp,
101
- user,
102
- body: parsed,
103
- alreadyForwarded: req.headers[VERIFY_FORWARDED_HEADER] !== void 0
104
- });
105
- if (forwarded) {
106
- return res.json(forwarded);
107
- }
108
- const tasks = new Tasks(env, req.logger);
109
- validateAddress(dapp, false, 42);
110
- validateAddress(user, false, 42);
111
- const clientRecord = await tasks.db.getClientRecord(dapp);
112
- if (!clientRecord) {
113
- return next(
114
- new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
115
- context: { code: 400, siteKey: dapp, user },
116
- i18n: req.i18n,
117
- logger: req.logger
118
- })
119
- );
120
- }
121
- const keyPair = env.keyring.addFromAddress(dapp);
122
- verifySignature(dappSignature, timestamp.toString(), keyPair);
123
- const response = await tasks.imgCaptchaManager.verifyImageCaptchaSolution(
124
- user,
125
- dapp,
126
- commitmentId,
127
- env,
128
- maxVerifiedTime,
129
- ip,
130
- clientRecord.settings.disallowWebView,
131
- clientRecord.settings.contextAware?.enabled,
132
- userAccessRulesStorage,
133
- email,
134
- clientRecord.settings.spamEmailDomainCheckEnabled,
135
- clientRecord.settings.spamFilter,
136
- clientRecord.settings.trafficFilter,
137
- clientRecord.settings.storeMetadata
138
- );
139
- req.logger.debug(() => ({ data: { response } }));
140
- const verificationResponse = tasks.imgCaptchaManager.getVerificationResponse(
141
- response[ApiParams.verified],
142
- clientRecord,
143
- req.i18n.t,
144
- response[ApiParams.score],
145
- response[ApiParams.commitmentId],
146
- response[ApiParams.status]
147
- );
148
- res.json(verificationResponse);
149
- } catch (err) {
150
- req.logger.error(() => ({
151
- err,
152
- msg: "Error in verifyImageCaptchaSolution",
153
- data: { body: req.body }
154
- }));
155
- return next(
156
- new ProsopoApiError("API.BAD_REQUEST", {
157
- context: { code: 500, siteKey: req.body.dapp, user: req.body.user },
158
- i18n: req.i18n,
159
- logger: req.logger
160
- })
161
- );
162
- }
163
- }
164
- );
165
- router.post(
166
- ClientApiPaths.VerifyPowCaptchaSolution,
167
- async (req, res, next) => {
168
- if (getMaintenanceMode()) {
169
- req.logger.info(() => ({
170
- msg: "Maintenance mode active - returning verified for PoW captcha verification"
171
- }));
172
- const verificationResponse = {
173
- status: "ok",
174
- verified: true
175
- };
176
- return res.json(verificationResponse);
177
- }
178
- let parsed;
179
- try {
180
- parsed = ServerPowCaptchaVerifyRequestBody.parse(req.body);
181
- } catch (err) {
182
- return next(
183
- new ProsopoApiError("CAPTCHA.PARSE_ERROR", {
184
- context: { code: 400, error: err, body: req.body },
185
- i18n: req.i18n,
186
- logger: req.logger
187
- })
188
- );
189
- }
190
- try {
191
- const { token, dappSignature, ip, email } = parsed;
192
- const { dapp, user, timestamp, challenge, providerUrl } = decodeProcaptchaOutput(token);
193
- const testVerdict = resolveTestSiteKeyVerdict(dapp, req.logger);
194
- if (testVerdict !== null) {
195
- const verificationResponse2 = {
196
- status: "ok",
197
- verified: testVerdict
198
- };
199
- return res.json(verificationResponse2);
200
- }
201
- const forwarded = await forwardVerifyIfNotIssuer({
202
- env,
203
- logger: req.logger,
204
- path: ClientApiPaths.VerifyPowCaptchaSolution,
205
- providerUrl,
206
- dapp,
207
- user,
208
- body: parsed,
209
- alreadyForwarded: req.headers[VERIFY_FORWARDED_HEADER] !== void 0
210
- });
211
- if (forwarded) {
212
- return res.json(forwarded);
213
- }
214
- const tasks = new Tasks(env, req.logger);
215
- validateAddress(dapp, false, 42);
216
- validateAddress(user, false, 42);
217
- const clientRecord = await tasks.db.getClientRecord(dapp);
218
- if (!clientRecord) {
219
- return next(
220
- new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
221
- context: { code: 400, siteKey: dapp },
222
- i18n: req.i18n,
223
- logger: req.logger
224
- })
225
- );
226
- }
227
- if (!challenge) {
228
- const unverifiedResponse = {
229
- status: req.i18n.t("API.USER_NOT_VERIFIED"),
230
- [ApiParams.verified]: false
231
- };
232
- return res.json(unverifiedResponse);
233
- }
234
- const dappPair = env.keyring.addFromAddress(dapp);
235
- verifySignature(dappSignature, timestamp.toString(), dappPair);
236
- const { verified, score, reason } = await tasks.powCaptchaManager.serverVerifyPowCaptchaSolution(
237
- dapp,
238
- challenge,
239
- clientRecord.settings.verifiedTimeout,
240
- env,
241
- ip,
242
- userAccessRulesStorage,
243
- email,
244
- clientRecord.settings.spamEmailDomainCheckEnabled,
245
- clientRecord.settings.spamFilter,
246
- clientRecord.settings.trafficFilter,
247
- clientRecord.settings.storeMetadata
248
- );
249
- const verificationResponse = tasks.powCaptchaManager.getVerificationResponse(
250
- verified,
251
- clientRecord,
252
- req.i18n.t,
253
- score,
254
- reason
255
- );
256
- return res.json(verificationResponse);
257
- } catch (err) {
258
- req.logger.error(() => ({
259
- msg: "Error in verifyPowCaptchaSolution",
260
- err,
261
- data: { body: req.body }
262
- }));
263
- return next(
264
- new ProsopoApiError("API.BAD_REQUEST", {
265
- context: { code: 500, error: err },
266
- i18n: req.i18n,
267
- logger: req.logger
268
- })
269
- );
270
- }
271
- }
272
- );
273
- router.post(
274
- ClientApiPaths.VerifyPuzzleCaptchaSolution,
275
- async (req, res, next) => {
276
- if (getMaintenanceMode()) {
277
- req.logger.info(() => ({
278
- msg: "Maintenance mode active - returning verified for puzzle captcha verification"
279
- }));
280
- const verificationResponse = {
281
- status: "ok",
282
- verified: true
283
- };
284
- return res.json(verificationResponse);
285
- }
286
- let parsed;
287
- try {
288
- parsed = ServerPuzzleCaptchaVerifyRequestBody.parse(req.body);
289
- } catch (err) {
290
- return next(
291
- new ProsopoApiError("CAPTCHA.PARSE_ERROR", {
292
- context: { code: 400, error: err, body: req.body },
293
- i18n: req.i18n,
294
- logger: req.logger
295
- })
296
- );
297
- }
298
- try {
299
- const { token, dappSignature, ip, email } = parsed;
300
- const { dapp, user, timestamp, challenge, providerUrl } = decodeProcaptchaOutput(token);
301
- const testVerdict = resolveTestSiteKeyVerdict(dapp, req.logger);
302
- if (testVerdict !== null) {
303
- const verificationResponse2 = {
304
- status: "ok",
305
- verified: testVerdict
306
- };
307
- return res.json(verificationResponse2);
308
- }
309
- const forwarded = await forwardVerifyIfNotIssuer({
310
- env,
311
- logger: req.logger,
312
- path: ClientApiPaths.VerifyPuzzleCaptchaSolution,
313
- providerUrl,
314
- dapp,
315
- user,
316
- body: parsed,
317
- alreadyForwarded: req.headers[VERIFY_FORWARDED_HEADER] !== void 0
318
- });
319
- if (forwarded) {
320
- return res.json(forwarded);
321
- }
322
- const tasks = new Tasks(env, req.logger);
323
- validateAddress(dapp, false, 42);
324
- validateAddress(user, false, 42);
325
- const clientRecord = await tasks.db.getClientRecord(dapp);
326
- if (!clientRecord) {
327
- return next(
328
- new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
329
- context: { code: 400, siteKey: dapp },
330
- i18n: req.i18n,
331
- logger: req.logger
332
- })
333
- );
334
- }
335
- if (!challenge) {
336
- const unverifiedResponse = {
337
- status: req.i18n.t("API.USER_NOT_VERIFIED"),
338
- [ApiParams.verified]: false
339
- };
340
- return res.json(unverifiedResponse);
341
- }
342
- const dappPair = env.keyring.addFromAddress(dapp);
343
- verifySignature(dappSignature, timestamp.toString(), dappPair);
344
- const { verified, score } = await tasks.puzzleCaptchaManager.serverVerifyPuzzleCaptchaSolution(
345
- dapp,
346
- challenge,
347
- clientRecord.settings.verifiedTimeout,
348
- env,
349
- ip,
350
- userAccessRulesStorage,
351
- email,
352
- clientRecord.settings.spamEmailDomainCheckEnabled,
353
- clientRecord.settings.trafficFilter,
354
- clientRecord.settings.storeMetadata
355
- );
356
- const verificationResponse = tasks.puzzleCaptchaManager.getVerificationResponse(
357
- verified,
358
- clientRecord,
359
- req.i18n.t,
360
- score
361
- );
362
- return res.json(verificationResponse);
363
- } catch (err) {
364
- req.logger.error(() => ({
365
- msg: "Error in verifyPuzzleCaptchaSolution",
366
- err,
367
- data: { body: req.body }
368
- }));
369
- return next(
370
- new ProsopoApiError("API.BAD_REQUEST", {
371
- context: { code: 500, error: err },
372
- i18n: req.i18n,
373
- logger: req.logger
374
- })
375
- );
376
- }
377
- }
378
- );
379
- router.use(handleErrors);
380
- return router;
36
+ const router = express.Router();
37
+ let userAccessRulesStorage;
38
+ try {
39
+ userAccessRulesStorage = env.getDb().getUserAccessRulesStorage();
40
+ } catch (err) {
41
+ env.logger.warn(() => ({
42
+ msg: "User access rules storage unavailable; verify endpoints will skip access-policy checks",
43
+ err
44
+ }));
45
+ userAccessRulesStorage = void 0;
46
+ }
47
+ router.use((req, res, next) => {
48
+ if (!metricsEnabled()) return next();
49
+ const type = VERIFY_PATH_TYPE[req.path];
50
+ if (!type) return next();
51
+ const originalJson = res.json.bind(res);
52
+ res.json = (body) => {
53
+ if (res.statusCode < 300) {
54
+ const verified = !!(body && typeof body === "object" && body.verified);
55
+ recordCaptchaVerify({
56
+ type,
57
+ verified,
58
+ source: deriveVerifySource(req.body)
59
+ });
60
+ }
61
+ return originalJson(body);
62
+ };
63
+ next();
64
+ });
65
+ /**
66
+ * Verifies a dapp's solution as being approved or not
67
+ *
68
+ * @param {string} user - Dapp User AccountId
69
+ * @param {string} dapp - Dapp Contract AccountId
70
+ * @param {string} blockNumber - The block number at which the captcha was requested
71
+ * @param {string} dappUserSignature - The signature fo dapp user
72
+ * @param {string} commitmentId - The captcha solution to look up
73
+ * @param {number} maxVerifiedTime - The maximum time in milliseconds since the blockNumber
74
+ */
75
+ router.post(ClientApiPaths.VerifyImageCaptchaSolutionDapp, async (req, res, next) => {
76
+ if (getMaintenanceMode()) {
77
+ req.logger.info(() => ({ msg: "Maintenance mode active - returning verified for image captcha verification" }));
78
+ return res.json({
79
+ status: "ok",
80
+ verified: true
81
+ });
82
+ }
83
+ let parsed;
84
+ try {
85
+ parsed = VerifySolutionBody.parse(req.body);
86
+ } catch (err) {
87
+ return next(new ProsopoApiError("CAPTCHA.PARSE_ERROR", {
88
+ context: {
89
+ code: 400,
90
+ error: err,
91
+ body: req.body
92
+ },
93
+ i18n: req.i18n,
94
+ logger: req.logger
95
+ }));
96
+ }
97
+ const { dappSignature, token, ip, maxVerifiedTime, email } = parsed;
98
+ try {
99
+ const { user, dapp, timestamp, commitmentId, providerUrl } = decodeProcaptchaOutput(token);
100
+ const testVerdict = resolveTestSiteKeyVerdict(dapp, req.logger);
101
+ if (testVerdict !== null) {
102
+ const verificationResponse = {
103
+ status: "ok",
104
+ verified: testVerdict
105
+ };
106
+ return res.json(verificationResponse);
107
+ }
108
+ const forwarded = await forwardVerifyIfNotIssuer({
109
+ env,
110
+ logger: req.logger,
111
+ path: ClientApiPaths.VerifyImageCaptchaSolutionDapp,
112
+ providerUrl,
113
+ dapp,
114
+ user,
115
+ body: parsed,
116
+ alreadyForwarded: req.headers[VERIFY_FORWARDED_HEADER] !== void 0
117
+ });
118
+ if (forwarded) return res.json(forwarded);
119
+ const tasks = new Tasks(env, req.logger);
120
+ validateAddress(dapp, false, 42);
121
+ validateAddress(user, false, 42);
122
+ const clientRecord = await tasks.db.getClientRecord(dapp);
123
+ if (!clientRecord) return next(new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
124
+ context: {
125
+ code: 400,
126
+ siteKey: dapp,
127
+ user
128
+ },
129
+ i18n: req.i18n,
130
+ logger: req.logger
131
+ }));
132
+ const keyPair = env.keyring.addFromAddress(dapp);
133
+ verifySignature(dappSignature, timestamp.toString(), keyPair);
134
+ const response = await tasks.imgCaptchaManager.verifyImageCaptchaSolution(user, dapp, commitmentId, env, maxVerifiedTime, ip, clientRecord.settings.disallowWebView, clientRecord.settings.contextAware?.enabled, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.spamFilter, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata);
135
+ req.logger.debug(() => ({ data: { response } }));
136
+ const verificationResponse = tasks.imgCaptchaManager.getVerificationResponse(response[ApiParams.verified], clientRecord, req.i18n.t, response[ApiParams.score], response[ApiParams.commitmentId], response[ApiParams.status]);
137
+ res.json(verificationResponse);
138
+ } catch (err) {
139
+ req.logger.error(() => ({
140
+ err,
141
+ msg: "Error in verifyImageCaptchaSolution",
142
+ data: { body: req.body }
143
+ }));
144
+ return next(new ProsopoApiError("API.BAD_REQUEST", {
145
+ context: {
146
+ code: 500,
147
+ siteKey: req.body.dapp,
148
+ user: req.body.user
149
+ },
150
+ i18n: req.i18n,
151
+ logger: req.logger
152
+ }));
153
+ }
154
+ });
155
+ /**
156
+ * Verifies a dapp's solution as being approved or not
157
+ *
158
+ * @param {string} token - Token containing dapp, blockNumber and challenge
159
+ * @param {string} dappSignature - Signed token
160
+ * @param {number} verifiedTimeout - The maximum time in milliseconds to be valid
161
+ */
162
+ router.post(ClientApiPaths.VerifyPowCaptchaSolution, async (req, res, next) => {
163
+ if (getMaintenanceMode()) {
164
+ req.logger.info(() => ({ msg: "Maintenance mode active - returning verified for PoW captcha verification" }));
165
+ return res.json({
166
+ status: "ok",
167
+ verified: true
168
+ });
169
+ }
170
+ let parsed;
171
+ try {
172
+ parsed = ServerPowCaptchaVerifyRequestBody.parse(req.body);
173
+ } catch (err) {
174
+ return next(new ProsopoApiError("CAPTCHA.PARSE_ERROR", {
175
+ context: {
176
+ code: 400,
177
+ error: err,
178
+ body: req.body
179
+ },
180
+ i18n: req.i18n,
181
+ logger: req.logger
182
+ }));
183
+ }
184
+ try {
185
+ const { token, dappSignature, ip, email } = parsed;
186
+ const { dapp, user, timestamp, challenge, providerUrl } = decodeProcaptchaOutput(token);
187
+ const testVerdict = resolveTestSiteKeyVerdict(dapp, req.logger);
188
+ if (testVerdict !== null) {
189
+ const verificationResponse = {
190
+ status: "ok",
191
+ verified: testVerdict
192
+ };
193
+ return res.json(verificationResponse);
194
+ }
195
+ const forwarded = await forwardVerifyIfNotIssuer({
196
+ env,
197
+ logger: req.logger,
198
+ path: ClientApiPaths.VerifyPowCaptchaSolution,
199
+ providerUrl,
200
+ dapp,
201
+ user,
202
+ body: parsed,
203
+ alreadyForwarded: req.headers[VERIFY_FORWARDED_HEADER] !== void 0
204
+ });
205
+ if (forwarded) return res.json(forwarded);
206
+ const tasks = new Tasks(env, req.logger);
207
+ validateAddress(dapp, false, 42);
208
+ validateAddress(user, false, 42);
209
+ const clientRecord = await tasks.db.getClientRecord(dapp);
210
+ if (!clientRecord) return next(new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
211
+ context: {
212
+ code: 400,
213
+ siteKey: dapp
214
+ },
215
+ i18n: req.i18n,
216
+ logger: req.logger
217
+ }));
218
+ if (!challenge) {
219
+ const unverifiedResponse = {
220
+ status: req.i18n.t("API.USER_NOT_VERIFIED"),
221
+ [ApiParams.verified]: false
222
+ };
223
+ return res.json(unverifiedResponse);
224
+ }
225
+ const dappPair = env.keyring.addFromAddress(dapp);
226
+ verifySignature(dappSignature, timestamp.toString(), dappPair);
227
+ const { verified, score, reason } = await tasks.powCaptchaManager.serverVerifyPowCaptchaSolution(dapp, challenge, clientRecord.settings.verifiedTimeout, env, ip, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.spamFilter, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata);
228
+ const verificationResponse = tasks.powCaptchaManager.getVerificationResponse(verified, clientRecord, req.i18n.t, score, reason);
229
+ return res.json(verificationResponse);
230
+ } catch (err) {
231
+ req.logger.error(() => ({
232
+ msg: "Error in verifyPowCaptchaSolution",
233
+ err,
234
+ data: { body: req.body }
235
+ }));
236
+ return next(new ProsopoApiError("API.BAD_REQUEST", {
237
+ context: {
238
+ code: 500,
239
+ error: err
240
+ },
241
+ i18n: req.i18n,
242
+ logger: req.logger
243
+ }));
244
+ }
245
+ });
246
+ /**
247
+ * Verifies a dapp's puzzle captcha solution as being approved or not
248
+ *
249
+ * @param {string} token - Token containing dapp, blockNumber and challenge
250
+ * @param {string} dappSignature - Signed token
251
+ * @param {number} verifiedTimeout - The maximum time in milliseconds to be valid
252
+ */
253
+ router.post(ClientApiPaths.VerifyPuzzleCaptchaSolution, async (req, res, next) => {
254
+ if (getMaintenanceMode()) {
255
+ req.logger.info(() => ({ msg: "Maintenance mode active - returning verified for puzzle captcha verification" }));
256
+ return res.json({
257
+ status: "ok",
258
+ verified: true
259
+ });
260
+ }
261
+ let parsed;
262
+ try {
263
+ parsed = ServerPuzzleCaptchaVerifyRequestBody.parse(req.body);
264
+ } catch (err) {
265
+ return next(new ProsopoApiError("CAPTCHA.PARSE_ERROR", {
266
+ context: {
267
+ code: 400,
268
+ error: err,
269
+ body: req.body
270
+ },
271
+ i18n: req.i18n,
272
+ logger: req.logger
273
+ }));
274
+ }
275
+ try {
276
+ const { token, dappSignature, ip, email } = parsed;
277
+ const { dapp, user, timestamp, challenge, providerUrl } = decodeProcaptchaOutput(token);
278
+ const testVerdict = resolveTestSiteKeyVerdict(dapp, req.logger);
279
+ if (testVerdict !== null) {
280
+ const verificationResponse = {
281
+ status: "ok",
282
+ verified: testVerdict
283
+ };
284
+ return res.json(verificationResponse);
285
+ }
286
+ const forwarded = await forwardVerifyIfNotIssuer({
287
+ env,
288
+ logger: req.logger,
289
+ path: ClientApiPaths.VerifyPuzzleCaptchaSolution,
290
+ providerUrl,
291
+ dapp,
292
+ user,
293
+ body: parsed,
294
+ alreadyForwarded: req.headers[VERIFY_FORWARDED_HEADER] !== void 0
295
+ });
296
+ if (forwarded) return res.json(forwarded);
297
+ const tasks = new Tasks(env, req.logger);
298
+ validateAddress(dapp, false, 42);
299
+ validateAddress(user, false, 42);
300
+ const clientRecord = await tasks.db.getClientRecord(dapp);
301
+ if (!clientRecord) return next(new ProsopoApiError("API.SITE_KEY_NOT_REGISTERED", {
302
+ context: {
303
+ code: 400,
304
+ siteKey: dapp
305
+ },
306
+ i18n: req.i18n,
307
+ logger: req.logger
308
+ }));
309
+ if (!challenge) {
310
+ const unverifiedResponse = {
311
+ status: req.i18n.t("API.USER_NOT_VERIFIED"),
312
+ [ApiParams.verified]: false
313
+ };
314
+ return res.json(unverifiedResponse);
315
+ }
316
+ const dappPair = env.keyring.addFromAddress(dapp);
317
+ verifySignature(dappSignature, timestamp.toString(), dappPair);
318
+ const { verified, score } = await tasks.puzzleCaptchaManager.serverVerifyPuzzleCaptchaSolution(dapp, challenge, clientRecord.settings.verifiedTimeout, env, ip, userAccessRulesStorage, email, clientRecord.settings.spamEmailDomainCheckEnabled, clientRecord.settings.trafficFilter, clientRecord.settings.storeMetadata);
319
+ const verificationResponse = tasks.puzzleCaptchaManager.getVerificationResponse(verified, clientRecord, req.i18n.t, score);
320
+ return res.json(verificationResponse);
321
+ } catch (err) {
322
+ req.logger.error(() => ({
323
+ msg: "Error in verifyPuzzleCaptchaSolution",
324
+ err,
325
+ data: { body: req.body }
326
+ }));
327
+ return next(new ProsopoApiError("API.BAD_REQUEST", {
328
+ context: {
329
+ code: 500,
330
+ error: err
331
+ },
332
+ i18n: req.i18n,
333
+ logger: req.logger
334
+ }));
335
+ }
336
+ });
337
+ router.use(handleErrors);
338
+ return router;
381
339
  }
382
- export {
383
- prosopoVerifyRouter
384
- };
340
+ //#endregion
341
+ export { prosopoVerifyRouter };