@prosopo/provider 3.1.3 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/dist/api/admin/apiAdminRoutesProvider.js +26 -21
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +21 -20
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +27 -27
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +33 -33
- package/dist/api/admin/createApiAdminRoutesProvider.js +8 -5
- package/dist/api/blacklistRequestInspector.js +116 -98
- package/dist/api/block.js +13 -8
- package/dist/api/captcha.js +519 -356
- package/dist/api/domainMiddleware.js +75 -68
- package/dist/api/headerCheckMiddleware.js +26 -25
- package/dist/api/ignoreMiddleware.js +12 -10
- package/dist/api/ja4Middleware.js +75 -80
- package/dist/api/public.js +26 -23
- package/dist/api/robotsMiddleware.js +11 -9
- package/dist/api/validateAddress.js +20 -18
- package/dist/api/verify.js +133 -95
- package/dist/cjs/api/blacklistRequestInspector.cjs +4 -6
- package/dist/cjs/api/captcha.cjs +45 -36
- package/dist/cjs/api/ja4Middleware.cjs +4 -1
- package/dist/cjs/tasks/captchaManager.cjs +24 -10
- package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +0 -3
- package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +1 -1
- package/dist/index.js +38 -15
- package/dist/rules/lang.js +14 -14
- package/dist/schedulers/captchaScheduler.js +28 -23
- package/dist/schedulers/getClientList.js +29 -24
- package/dist/tasks/captchaManager.js +109 -85
- package/dist/tasks/client/clientTasks.js +265 -204
- package/dist/tasks/dataset/datasetTasks.js +27 -16
- package/dist/tasks/dataset/datasetTasksUtils.js +31 -31
- package/dist/tasks/detection/decodePayload.js +378 -208
- package/dist/tasks/detection/getBotScore.js +12 -10
- package/dist/tasks/frictionless/frictionlessTasks.js +117 -119
- package/dist/tasks/frictionless/frictionlessTasksUtils.js +10 -5
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +360 -271
- package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +23 -16
- package/dist/tasks/index.js +4 -2
- package/dist/tasks/powCaptcha/powTasks.js +157 -97
- package/dist/tasks/powCaptcha/powTasksUtils.js +24 -20
- package/dist/tasks/tasks.js +53 -29
- package/dist/util.js +98 -88
- package/package.json +31 -27
- package/vite.cjs.config.ts +4 -1
- package/vite.esm.config.ts +20 -0
- package/vite.test.config.ts +15 -3
- package/dist/api/admin/apiAdminRoutesProvider.d.ts +0 -9
- package/dist/api/admin/apiAdminRoutesProvider.d.ts.map +0 -1
- package/dist/api/admin/apiAdminRoutesProvider.js.map +0 -1
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.d.ts +0 -14
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.d.ts.map +0 -1
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.js.map +0 -1
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts +0 -14
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +0 -1
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js.map +0 -1
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.d.ts +0 -14
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.d.ts.map +0 -1
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js.map +0 -1
- package/dist/api/admin/createApiAdminRoutesProvider.d.ts +0 -4
- package/dist/api/admin/createApiAdminRoutesProvider.d.ts.map +0 -1
- package/dist/api/admin/createApiAdminRoutesProvider.js.map +0 -1
- package/dist/api/blacklistRequestInspector.d.ts +0 -44
- package/dist/api/blacklistRequestInspector.d.ts.map +0 -1
- package/dist/api/blacklistRequestInspector.js.map +0 -1
- package/dist/api/block.d.ts +0 -3
- package/dist/api/block.d.ts.map +0 -1
- package/dist/api/block.js.map +0 -1
- package/dist/api/captcha.d.ts +0 -4
- package/dist/api/captcha.d.ts.map +0 -1
- package/dist/api/captcha.js.map +0 -1
- package/dist/api/domainMiddleware.d.ts +0 -4
- package/dist/api/domainMiddleware.d.ts.map +0 -1
- package/dist/api/domainMiddleware.js.map +0 -1
- package/dist/api/headerCheckMiddleware.d.ts +0 -4
- package/dist/api/headerCheckMiddleware.d.ts.map +0 -1
- package/dist/api/headerCheckMiddleware.js.map +0 -1
- package/dist/api/ignoreMiddleware.d.ts +0 -3
- package/dist/api/ignoreMiddleware.d.ts.map +0 -1
- package/dist/api/ignoreMiddleware.js.map +0 -1
- package/dist/api/ja4Middleware.d.ts +0 -10
- package/dist/api/ja4Middleware.d.ts.map +0 -1
- package/dist/api/ja4Middleware.js.map +0 -1
- package/dist/api/public.d.ts +0 -3
- package/dist/api/public.d.ts.map +0 -1
- package/dist/api/public.js.map +0 -1
- package/dist/api/robotsMiddleware.d.ts +0 -3
- package/dist/api/robotsMiddleware.d.ts.map +0 -1
- package/dist/api/robotsMiddleware.js.map +0 -1
- package/dist/api/validateAddress.d.ts +0 -5
- package/dist/api/validateAddress.d.ts.map +0 -1
- package/dist/api/validateAddress.js.map +0 -1
- package/dist/api/verify.d.ts +0 -4
- package/dist/api/verify.d.ts.map +0 -1
- package/dist/api/verify.js.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/rules/lang.d.ts +0 -3
- package/dist/rules/lang.d.ts.map +0 -1
- package/dist/rules/lang.js.map +0 -1
- package/dist/schedulers/captchaScheduler.d.ts +0 -4
- package/dist/schedulers/captchaScheduler.d.ts.map +0 -1
- package/dist/schedulers/captchaScheduler.js.map +0 -1
- package/dist/schedulers/getClientList.d.ts +0 -4
- package/dist/schedulers/getClientList.d.ts.map +0 -1
- package/dist/schedulers/getClientList.js.map +0 -1
- package/dist/tasks/captchaManager.d.ts +0 -48
- package/dist/tasks/captchaManager.d.ts.map +0 -1
- package/dist/tasks/captchaManager.js.map +0 -1
- package/dist/tasks/client/clientTasks.d.ts +0 -21
- package/dist/tasks/client/clientTasks.d.ts.map +0 -1
- package/dist/tasks/client/clientTasks.js.map +0 -1
- package/dist/tasks/dataset/datasetTasks.d.ts +0 -13
- package/dist/tasks/dataset/datasetTasks.d.ts.map +0 -1
- package/dist/tasks/dataset/datasetTasks.js.map +0 -1
- package/dist/tasks/dataset/datasetTasksUtils.d.ts +0 -3
- package/dist/tasks/dataset/datasetTasksUtils.d.ts.map +0 -1
- package/dist/tasks/dataset/datasetTasksUtils.js.map +0 -1
- package/dist/tasks/detection/decodePayload.d.ts +0 -5
- package/dist/tasks/detection/decodePayload.d.ts.map +0 -1
- package/dist/tasks/detection/decodePayload.js.map +0 -1
- package/dist/tasks/detection/getBotScore.d.ts +0 -5
- package/dist/tasks/detection/getBotScore.d.ts.map +0 -1
- package/dist/tasks/detection/getBotScore.js.map +0 -1
- package/dist/tasks/frictionless/frictionlessTasks.d.ts +0 -23
- package/dist/tasks/frictionless/frictionlessTasks.d.ts.map +0 -1
- package/dist/tasks/frictionless/frictionlessTasks.js.map +0 -1
- package/dist/tasks/frictionless/frictionlessTasksUtils.d.ts +0 -5
- package/dist/tasks/frictionless/frictionlessTasksUtils.d.ts.map +0 -1
- package/dist/tasks/frictionless/frictionlessTasksUtils.js.map +0 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts +0 -29
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +0 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +0 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.d.ts +0 -7
- package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.d.ts.map +0 -1
- package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js.map +0 -1
- package/dist/tasks/index.d.ts +0 -2
- package/dist/tasks/index.d.ts.map +0 -1
- package/dist/tasks/index.js.map +0 -1
- package/dist/tasks/powCaptcha/powTasks.d.ts +0 -16
- package/dist/tasks/powCaptcha/powTasks.d.ts.map +0 -1
- package/dist/tasks/powCaptcha/powTasks.js.map +0 -1
- package/dist/tasks/powCaptcha/powTasksUtils.d.ts +0 -3
- package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +0 -1
- package/dist/tasks/powCaptcha/powTasksUtils.js.map +0 -1
- package/dist/tasks/tasks.d.ts +0 -25
- package/dist/tasks/tasks.d.ts.map +0 -1
- package/dist/tasks/tasks.js.map +0 -1
- package/dist/tests/index.d.ts +0 -2
- package/dist/tests/index.d.ts.map +0 -1
- package/dist/tests/index.js +0 -2
- package/dist/tests/index.js.map +0 -1
- package/dist/tests/integration/imgCaptcha.integration.test.d.ts +0 -2
- package/dist/tests/integration/imgCaptcha.integration.test.d.ts.map +0 -1
- package/dist/tests/integration/imgCaptcha.integration.test.js +0 -261
- package/dist/tests/integration/imgCaptcha.integration.test.js.map +0 -1
- package/dist/tests/integration/mocks/solvedTestCaptchas.d.ts +0 -32
- package/dist/tests/integration/mocks/solvedTestCaptchas.d.ts.map +0 -1
- package/dist/tests/integration/mocks/solvedTestCaptchas.js +0 -1046
- package/dist/tests/integration/mocks/solvedTestCaptchas.js.map +0 -1
- package/dist/tests/integration/powCaptcha.integration.test.d.ts +0 -2
- package/dist/tests/integration/powCaptcha.integration.test.d.ts.map +0 -1
- package/dist/tests/integration/powCaptcha.integration.test.js +0 -299
- package/dist/tests/integration/powCaptcha.integration.test.js.map +0 -1
- package/dist/tests/integration/registerSitekey.d.ts +0 -3
- package/dist/tests/integration/registerSitekey.d.ts.map +0 -1
- package/dist/tests/integration/registerSitekey.js +0 -39
- package/dist/tests/integration/registerSitekey.js.map +0 -1
- package/dist/tests/unit/api/ignoreMiddleware.unit.test.d.ts +0 -2
- package/dist/tests/unit/api/ignoreMiddleware.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/api/ignoreMiddleware.unit.test.js +0 -43
- package/dist/tests/unit/api/ignoreMiddleware.unit.test.js.map +0 -1
- package/dist/tests/unit/api/ja4Middleware.unit.test.d.ts +0 -2
- package/dist/tests/unit/api/ja4Middleware.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/api/ja4Middleware.unit.test.js +0 -71
- package/dist/tests/unit/api/ja4Middleware.unit.test.js.map +0 -1
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.d.ts +0 -2
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +0 -75
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/captchaManager.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/captchaManager.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/captchaManager.unit.test.js +0 -236
- package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +0 -277
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js +0 -93
- package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js +0 -75
- package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js +0 -68
- package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.js +0 -37
- package/dist/tests/unit/tasks/frictionless/frictionlessTasksUtils.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +0 -402
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +0 -46
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js +0 -228
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +0 -1
- package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.d.ts +0 -2
- package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +0 -68
- package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +0 -1
- package/dist/tests/unit/util.unit.test.d.ts +0 -2
- package/dist/tests/unit/util.unit.test.d.ts.map +0 -1
- package/dist/tests/unit/util.unit.test.js +0 -148
- package/dist/tests/unit/util.unit.test.js.map +0 -1
- package/dist/util.d.ts +0 -13
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js.map +0 -1
|
@@ -1,228 +1,289 @@
|
|
|
1
1
|
import { createPrivateKey } from "node:crypto";
|
|
2
2
|
import { ProsopoApiError } from "@prosopo/common";
|
|
3
3
|
import { CaptchaDatabase, ClientDatabase } from "@prosopo/database";
|
|
4
|
-
import { ScheduledTaskNames, ScheduledTaskStatus
|
|
4
|
+
import { ScheduledTaskNames, ScheduledTaskStatus } from "@prosopo/types";
|
|
5
5
|
import { parseUrl } from "@prosopo/util";
|
|
6
6
|
import { validateSiteKey } from "../../api/validateAddress.js";
|
|
7
7
|
const isValidPrivateKey = (privateKeyString) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
const privateKey = Buffer.from(privateKeyString, "base64").toString("ascii");
|
|
9
|
+
try {
|
|
10
|
+
createPrivateKey({
|
|
11
|
+
key: privateKey,
|
|
12
|
+
format: "pem",
|
|
13
|
+
type: "pkcs8"
|
|
14
|
+
});
|
|
15
|
+
return true;
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
class ClientTaskManager {
|
|
21
|
+
constructor(config, logger, db) {
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
this.providerDB = db;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @description Get the captcha database connection or create a new one
|
|
28
|
+
* @returns CaptchaDatabase
|
|
29
|
+
*/
|
|
30
|
+
getCaptchaDB(mongoCaptchaUri) {
|
|
31
|
+
if (this.captchaDB) {
|
|
32
|
+
return this.captchaDB;
|
|
16
33
|
}
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
if (!this.captchaDB) {
|
|
35
|
+
this.captchaDB = new CaptchaDatabase(
|
|
36
|
+
mongoCaptchaUri,
|
|
37
|
+
void 0,
|
|
38
|
+
void 0,
|
|
39
|
+
this.logger
|
|
40
|
+
);
|
|
19
41
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
42
|
+
return this.captchaDB;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @description Store commitments externally in the database (Sends image captcha data to the big Mongo Cloud DB)
|
|
46
|
+
* @returns Promise<void>
|
|
47
|
+
*/
|
|
48
|
+
async storeCommitmentsExternal() {
|
|
49
|
+
if (!this.config.mongoCaptchaUri) {
|
|
50
|
+
this.logger.info(() => ({ msg: "Mongo env not set" }));
|
|
51
|
+
return;
|
|
26
52
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
53
|
+
const lastTask = await this.providerDB.getLastScheduledTaskStatus(
|
|
54
|
+
ScheduledTaskNames.StoreCommitmentsExternal,
|
|
55
|
+
ScheduledTaskStatus.Completed
|
|
56
|
+
);
|
|
57
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(
|
|
58
|
+
ScheduledTaskNames.StoreCommitmentsExternal,
|
|
59
|
+
ScheduledTaskStatus.Running
|
|
60
|
+
);
|
|
61
|
+
try {
|
|
62
|
+
const BATCH_SIZE = 1e3;
|
|
63
|
+
const captchaDB = this.getCaptchaDB(this.config.mongoCaptchaUri);
|
|
64
|
+
let processedCommitments = 0;
|
|
65
|
+
await this.processBatchesWithCursor(
|
|
66
|
+
async (skip) => await this.providerDB.getUnstoredDappUserCommitments(
|
|
67
|
+
BATCH_SIZE,
|
|
68
|
+
skip
|
|
69
|
+
),
|
|
70
|
+
async (batch) => {
|
|
71
|
+
const filteredBatch = lastTask?.updated ? batch.filter((commitment) => this.isRecordUpdated(commitment)) : batch;
|
|
72
|
+
if (filteredBatch.length > 0) {
|
|
73
|
+
await captchaDB.saveCaptchas([], filteredBatch, []);
|
|
74
|
+
await this.providerDB.markDappUserCommitmentsStored(
|
|
75
|
+
filteredBatch.map((commitment) => commitment.id)
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
processedCommitments += filteredBatch.length;
|
|
30
79
|
}
|
|
31
|
-
|
|
32
|
-
|
|
80
|
+
);
|
|
81
|
+
let processedPowRecords = 0;
|
|
82
|
+
await this.processBatchesWithCursor(
|
|
83
|
+
async (skip) => await this.providerDB.getUnstoredDappUserPoWCommitments(
|
|
84
|
+
BATCH_SIZE,
|
|
85
|
+
skip
|
|
86
|
+
),
|
|
87
|
+
async (batch) => {
|
|
88
|
+
const filteredBatch = lastTask?.updated ? batch.filter((record) => this.isRecordUpdated(record)) : batch;
|
|
89
|
+
if (filteredBatch.length > 0) {
|
|
90
|
+
await captchaDB.saveCaptchas([], [], filteredBatch);
|
|
91
|
+
await this.providerDB.markDappUserPoWCommitmentsStored(
|
|
92
|
+
filteredBatch.map((record) => record.challenge)
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
processedPowRecords += filteredBatch.length;
|
|
33
96
|
}
|
|
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
|
-
? batch.filter((record) => this.isRecordUpdated(record))
|
|
61
|
-
: batch;
|
|
62
|
-
if (filteredBatch.length > 0) {
|
|
63
|
-
await captchaDB.saveCaptchas([], [], filteredBatch);
|
|
64
|
-
await this.providerDB.markDappUserPoWCommitmentsStored(filteredBatch.map((record) => record.challenge));
|
|
65
|
-
}
|
|
66
|
-
processedPowRecords += filteredBatch.length;
|
|
67
|
-
});
|
|
68
|
-
let processedSessionRecords = 0;
|
|
69
|
-
await this.processBatchesWithCursor(async (skip) => await this.providerDB.getUnstoredSessionRecords(BATCH_SIZE, skip), async (batch) => {
|
|
70
|
-
const filteredBatch = lastTask?.updated
|
|
71
|
-
? batch.filter((record) => this.isRecordUpdated(record))
|
|
72
|
-
: batch;
|
|
73
|
-
const frictionlessTokenRecords = await this.providerDB.getFrictionlessTokenRecordsByTokenIds(filteredBatch.map((record) => record.tokenId));
|
|
74
|
-
this.logger.info(() => ({
|
|
75
|
-
msg: `Frictionless token records: ${frictionlessTokenRecords.length}`,
|
|
76
|
-
}));
|
|
77
|
-
const filteredBatchWithScores = filteredBatch.map((record) => {
|
|
78
|
-
const tokenRecord = frictionlessTokenRecords.find((tokenRecord) => tokenRecord._id?.toString() === record.tokenId.toString());
|
|
79
|
-
if (!tokenRecord) {
|
|
80
|
-
this.logger.error(() => ({
|
|
81
|
-
msg: "No token record found",
|
|
82
|
-
data: { tokenId: record.tokenId },
|
|
83
|
-
}));
|
|
84
|
-
return {
|
|
85
|
-
...record,
|
|
86
|
-
score: 0,
|
|
87
|
-
scoreComponents: {
|
|
88
|
-
baseScore: 0,
|
|
89
|
-
},
|
|
90
|
-
threshold: 0,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
return {
|
|
94
|
-
...record,
|
|
95
|
-
score: tokenRecord?.score || 0,
|
|
96
|
-
scoreComponents: tokenRecord?.scoreComponents,
|
|
97
|
-
threshold: tokenRecord?.threshold || 0,
|
|
98
|
-
};
|
|
99
|
-
});
|
|
100
|
-
if (filteredBatch.length > 0) {
|
|
101
|
-
await captchaDB.saveCaptchas(filteredBatchWithScores, [], []);
|
|
102
|
-
await this.providerDB.markSessionRecordsStored(filteredBatch.map((record) => record.sessionId));
|
|
103
|
-
}
|
|
104
|
-
processedSessionRecords += filteredBatch.length;
|
|
105
|
-
});
|
|
106
|
-
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Completed, {
|
|
107
|
-
data: {
|
|
108
|
-
processedSessionRecords,
|
|
109
|
-
processedCommitments,
|
|
110
|
-
processedPowRecords,
|
|
97
|
+
);
|
|
98
|
+
let processedSessionRecords = 0;
|
|
99
|
+
await this.processBatchesWithCursor(
|
|
100
|
+
async (skip) => await this.providerDB.getUnstoredSessionRecords(BATCH_SIZE, skip),
|
|
101
|
+
async (batch) => {
|
|
102
|
+
const filteredBatch = lastTask?.updated ? batch.filter((record) => this.isRecordUpdated(record)) : batch;
|
|
103
|
+
const frictionlessTokenRecords = await this.providerDB.getFrictionlessTokenRecordsByTokenIds(
|
|
104
|
+
filteredBatch.map((record) => record.tokenId)
|
|
105
|
+
);
|
|
106
|
+
this.logger.info(() => ({
|
|
107
|
+
msg: `Frictionless token records: ${frictionlessTokenRecords.length}`
|
|
108
|
+
}));
|
|
109
|
+
const filteredBatchWithScores = filteredBatch.map((record) => {
|
|
110
|
+
const tokenRecord = frictionlessTokenRecords.find(
|
|
111
|
+
(tokenRecord2) => tokenRecord2._id?.toString() === record.tokenId.toString()
|
|
112
|
+
);
|
|
113
|
+
if (!tokenRecord) {
|
|
114
|
+
this.logger.error(() => ({
|
|
115
|
+
msg: "No token record found",
|
|
116
|
+
data: { tokenId: record.tokenId }
|
|
117
|
+
}));
|
|
118
|
+
return {
|
|
119
|
+
...record,
|
|
120
|
+
score: 0,
|
|
121
|
+
scoreComponents: {
|
|
122
|
+
baseScore: 0
|
|
111
123
|
},
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
116
|
-
this.logger.error(() => ({
|
|
117
|
-
err: e,
|
|
118
|
-
msg: "Error processing client tasks",
|
|
119
|
-
}));
|
|
120
|
-
this.captchaDB?.close();
|
|
121
|
-
await this.providerDB.updateScheduledTaskStatus(taskID, ScheduledTaskStatus.Failed, { error: String(e) });
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
async getClientList() {
|
|
125
|
-
if (!this.config.mongoClientUri) {
|
|
126
|
-
this.logger.info(() => ({ msg: "Mongo env not set" }));
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
const lastTask = await this.providerDB.getLastScheduledTaskStatus(ScheduledTaskNames.GetClientList, ScheduledTaskStatus.Completed);
|
|
130
|
-
const taskID = await this.providerDB.createScheduledTaskStatus(ScheduledTaskNames.GetClientList, ScheduledTaskStatus.Running);
|
|
131
|
-
try {
|
|
132
|
-
const clientDB = new ClientDatabase(this.config.mongoClientUri, undefined, undefined, this.logger);
|
|
133
|
-
const tenMinuteWindow = 10 * 60 * 1000;
|
|
134
|
-
const updatedAtTimestamp = lastTask?.updated
|
|
135
|
-
? lastTask.updated - tenMinuteWindow || 0
|
|
136
|
-
: 0;
|
|
137
|
-
this.logger.info(() => ({
|
|
138
|
-
msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}`,
|
|
139
|
-
}));
|
|
140
|
-
const newClientRecords = await clientDB.getUpdatedClients(updatedAtTimestamp);
|
|
141
|
-
if (newClientRecords) {
|
|
142
|
-
await this.providerDB.updateClientRecords(newClientRecords);
|
|
124
|
+
threshold: 0
|
|
125
|
+
};
|
|
143
126
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
127
|
+
return {
|
|
128
|
+
...record,
|
|
129
|
+
score: tokenRecord?.score || 0,
|
|
130
|
+
scoreComponents: tokenRecord?.scoreComponents,
|
|
131
|
+
threshold: tokenRecord?.threshold || 0
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
if (filteredBatch.length > 0) {
|
|
135
|
+
await captchaDB.saveCaptchas(filteredBatchWithScores, [], []);
|
|
136
|
+
await this.providerDB.markSessionRecordsStored(
|
|
137
|
+
filteredBatch.map((record) => record.sessionId)
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
processedSessionRecords += filteredBatch.length;
|
|
149
141
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
);
|
|
143
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
144
|
+
taskID,
|
|
145
|
+
ScheduledTaskStatus.Completed,
|
|
146
|
+
{
|
|
147
|
+
data: {
|
|
148
|
+
processedSessionRecords,
|
|
149
|
+
processedCommitments,
|
|
150
|
+
processedPowRecords
|
|
151
|
+
}
|
|
160
152
|
}
|
|
153
|
+
);
|
|
154
|
+
this.captchaDB?.close();
|
|
155
|
+
} catch (e) {
|
|
156
|
+
this.logger.error(() => ({
|
|
157
|
+
err: e,
|
|
158
|
+
msg: "Error processing client tasks"
|
|
159
|
+
}));
|
|
160
|
+
this.captchaDB?.close();
|
|
161
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
162
|
+
taskID,
|
|
163
|
+
ScheduledTaskStatus.Failed,
|
|
164
|
+
{ error: String(e) }
|
|
165
|
+
);
|
|
161
166
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* @description Get a list of client accounts and their settings from the client database
|
|
170
|
+
* @returns Promise<void>
|
|
171
|
+
*/
|
|
172
|
+
async getClientList() {
|
|
173
|
+
if (!this.config.mongoClientUri) {
|
|
174
|
+
this.logger.info(() => ({ msg: "Mongo env not set" }));
|
|
175
|
+
return;
|
|
171
176
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
const lastTask = await this.providerDB.getLastScheduledTaskStatus(
|
|
178
|
+
ScheduledTaskNames.GetClientList,
|
|
179
|
+
ScheduledTaskStatus.Completed
|
|
180
|
+
);
|
|
181
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(
|
|
182
|
+
ScheduledTaskNames.GetClientList,
|
|
183
|
+
ScheduledTaskStatus.Running
|
|
184
|
+
);
|
|
185
|
+
try {
|
|
186
|
+
const clientDB = new ClientDatabase(
|
|
187
|
+
this.config.mongoClientUri,
|
|
188
|
+
void 0,
|
|
189
|
+
// expected to come from URI
|
|
190
|
+
void 0,
|
|
191
|
+
// expected to come from URI
|
|
192
|
+
this.logger
|
|
193
|
+
);
|
|
194
|
+
const tenMinuteWindow = 10 * 60 * 1e3;
|
|
195
|
+
const updatedAtTimestamp = lastTask?.updated ? lastTask.updated - tenMinuteWindow || 0 : 0;
|
|
196
|
+
this.logger.info(() => ({
|
|
197
|
+
msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}`
|
|
198
|
+
}));
|
|
199
|
+
const newClientRecords = await clientDB.getUpdatedClients(updatedAtTimestamp);
|
|
200
|
+
if (newClientRecords) {
|
|
201
|
+
await this.providerDB.updateClientRecords(newClientRecords);
|
|
202
|
+
}
|
|
203
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
204
|
+
taskID,
|
|
205
|
+
ScheduledTaskStatus.Completed,
|
|
206
|
+
{
|
|
207
|
+
data: {
|
|
208
|
+
clientRecords: newClientRecords.length
|
|
209
|
+
}
|
|
178
210
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
211
|
+
);
|
|
212
|
+
} catch (e) {
|
|
213
|
+
const getClientListError = new ProsopoApiError("DATABASE.UNKNOWN", {
|
|
214
|
+
context: { error: e },
|
|
215
|
+
logger: this.logger
|
|
216
|
+
});
|
|
217
|
+
this.logger.error(() => ({
|
|
218
|
+
err: getClientListError,
|
|
219
|
+
msg: "Error getting client list"
|
|
220
|
+
}));
|
|
221
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
222
|
+
taskID,
|
|
223
|
+
ScheduledTaskStatus.Failed,
|
|
224
|
+
{ error: String(e) }
|
|
225
|
+
);
|
|
182
226
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
227
|
+
}
|
|
228
|
+
async registerSiteKey(siteKey, tier, settings) {
|
|
229
|
+
validateSiteKey(siteKey);
|
|
230
|
+
await this.providerDB.updateClientRecords([
|
|
231
|
+
{
|
|
232
|
+
account: siteKey,
|
|
233
|
+
tier,
|
|
234
|
+
settings
|
|
235
|
+
}
|
|
236
|
+
]);
|
|
237
|
+
}
|
|
238
|
+
async updateDetectorKey(detectorKey) {
|
|
239
|
+
if (!isValidPrivateKey(detectorKey)) {
|
|
240
|
+
throw new ProsopoApiError("INVALID_DETECTOR_KEY", {
|
|
241
|
+
context: { detectorKey },
|
|
242
|
+
logger: this.logger
|
|
243
|
+
});
|
|
191
244
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
catch {
|
|
204
|
-
this.logger.error(() => ({
|
|
205
|
-
msg: "Error in isSubdomainOrExactMatch",
|
|
206
|
-
data: { referrer, clientDomain },
|
|
207
|
-
}));
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
245
|
+
await this.providerDB.storeDetectorKey(detectorKey);
|
|
246
|
+
const activeDetectorKeys = await this.providerDB.getDetectorKeys();
|
|
247
|
+
return activeDetectorKeys;
|
|
248
|
+
}
|
|
249
|
+
async removeDetectorKey(detectorKey) {
|
|
250
|
+
if (!isValidPrivateKey(detectorKey)) {
|
|
251
|
+
throw new ProsopoApiError("INVALID_DETECTOR_KEY", {
|
|
252
|
+
context: { detectorKey },
|
|
253
|
+
logger: this.logger
|
|
254
|
+
});
|
|
210
255
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
256
|
+
await this.providerDB.removeDetectorKey(detectorKey);
|
|
257
|
+
}
|
|
258
|
+
isSubdomainOrExactMatch(referrer, clientDomain) {
|
|
259
|
+
if (!referrer || !clientDomain) return false;
|
|
260
|
+
if (clientDomain === "*") return true;
|
|
261
|
+
try {
|
|
262
|
+
const referrerDomain = parseUrl(referrer).hostname.replace(/\.$/, "");
|
|
263
|
+
const allowedDomain = parseUrl(clientDomain).hostname.replace(/\.$/, "");
|
|
264
|
+
return referrerDomain === allowedDomain || referrerDomain.endsWith(`.${allowedDomain}`);
|
|
265
|
+
} catch {
|
|
266
|
+
this.logger.error(() => ({
|
|
267
|
+
msg: "Error in isSubdomainOrExactMatch",
|
|
268
|
+
data: { referrer, clientDomain }
|
|
269
|
+
}));
|
|
270
|
+
return false;
|
|
216
271
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
272
|
+
}
|
|
273
|
+
isRecordUpdated(record) {
|
|
274
|
+
const { lastUpdatedTimestamp, storedAtTimestamp } = record;
|
|
275
|
+
return !lastUpdatedTimestamp || !storedAtTimestamp || lastUpdatedTimestamp > storedAtTimestamp;
|
|
276
|
+
}
|
|
277
|
+
async processBatchesWithCursor(fetchBatch, processBatch) {
|
|
278
|
+
let skip = 0;
|
|
279
|
+
while (true) {
|
|
280
|
+
const batch = await fetchBatch(skip);
|
|
281
|
+
if (!batch.length) break;
|
|
282
|
+
await processBatch(batch);
|
|
283
|
+
skip += batch.length;
|
|
226
284
|
}
|
|
285
|
+
}
|
|
227
286
|
}
|
|
228
|
-
|
|
287
|
+
export {
|
|
288
|
+
ClientTaskManager
|
|
289
|
+
};
|
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
import { parseCaptchaDataset } from "@prosopo/datasets";
|
|
2
2
|
import { providerValidateDataset } from "./datasetTasksUtils.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
class DatasetManager {
|
|
4
|
+
constructor(config, logger, captchaConfig, db) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.logger = logger;
|
|
7
|
+
this.captchaConfig = captchaConfig;
|
|
8
|
+
this.db = db;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @description Set the provider dataset from a file
|
|
12
|
+
*
|
|
13
|
+
* @param file JSON of the captcha dataset
|
|
14
|
+
*/
|
|
15
|
+
async providerSetDatasetFromFile(file) {
|
|
16
|
+
const datasetRaw = parseCaptchaDataset(file);
|
|
17
|
+
return await this.providerSetDataset(datasetRaw);
|
|
18
|
+
}
|
|
19
|
+
async providerSetDataset(datasetRaw) {
|
|
20
|
+
const dataset = await providerValidateDataset(
|
|
21
|
+
datasetRaw,
|
|
22
|
+
this.captchaConfig.solved.count,
|
|
23
|
+
this.captchaConfig.unsolved.count
|
|
24
|
+
);
|
|
25
|
+
await this.db?.storeDataset(dataset);
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
|
-
|
|
28
|
+
export {
|
|
29
|
+
DatasetManager
|
|
30
|
+
};
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import { ProsopoEnvError } from "@prosopo/common";
|
|
2
2
|
import { buildDataset } from "@prosopo/datasets";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
3
|
+
const providerValidateDataset = async (datasetRaw, minSolvedCaptchas, minUnsolvedCaptchas) => {
|
|
4
|
+
if (datasetRaw.captchas.length < minSolvedCaptchas + minUnsolvedCaptchas) {
|
|
5
|
+
throw new ProsopoEnvError("DATASET.CAPTCHAS_COUNT_LESS_THAN_CONFIGURED", {
|
|
6
|
+
context: { failedFuncName: providerValidateDataset.name }
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
const solutions = datasetRaw.captchas.map((captcha) => captcha.solution ? 1 : 0).reduce((partialSum, b) => partialSum + b, 0);
|
|
10
|
+
if (solutions < minSolvedCaptchas) {
|
|
11
|
+
throw new ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", {
|
|
12
|
+
context: { failedFuncName: providerValidateDataset.name }
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (solutions < minUnsolvedCaptchas) {
|
|
16
|
+
throw new ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", {
|
|
17
|
+
context: { failedFuncName: providerValidateDataset.name }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const dataset = await buildDataset(datasetRaw);
|
|
21
|
+
if (!dataset.datasetId || !dataset.datasetContentId) {
|
|
22
|
+
throw new ProsopoEnvError("DATASET.DATASET_ID_UNDEFINED", {
|
|
23
|
+
context: {
|
|
24
|
+
failedFuncName: providerValidateDataset.name,
|
|
25
|
+
datasetId: dataset.datasetId,
|
|
26
|
+
datasetContentId: dataset.datasetContentId
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return dataset;
|
|
31
|
+
};
|
|
32
|
+
export {
|
|
33
|
+
providerValidateDataset
|
|
33
34
|
};
|
|
34
|
-
//# sourceMappingURL=datasetTasksUtils.js.map
|