@prosopo/database 4.2.6 → 4.2.8
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 +13 -12
- package/.turbo/turbo-build$colon$tsc.log +16 -16
- package/.turbo/turbo-build.log +14 -13
- package/CHANGELOG.md +72 -0
- package/dist/base/mongo.d.ts.map +1 -1
- package/dist/base/mongo.js +6 -4
- package/dist/base/mongo.js.map +1 -1
- package/dist/cjs/base/mongo.cjs +5 -3
- package/dist/cjs/databases/captcha.cjs +10 -7
- package/dist/cjs/databases/client.cjs +5 -3
- package/dist/cjs/databases/clientRecordCache.cjs +43 -0
- package/dist/cjs/databases/provider.cjs +338 -185
- package/dist/cjs/redisCache.cjs +1 -1
- package/dist/databases/captcha.d.ts.map +1 -1
- package/dist/databases/captcha.js +11 -8
- package/dist/databases/captcha.js.map +1 -1
- package/dist/databases/client.d.ts.map +1 -1
- package/dist/databases/client.js +6 -4
- package/dist/databases/client.js.map +1 -1
- package/dist/databases/clientRecordCache.d.ts +11 -0
- package/dist/databases/clientRecordCache.d.ts.map +1 -0
- package/dist/databases/clientRecordCache.js +42 -0
- package/dist/databases/clientRecordCache.js.map +1 -0
- package/dist/databases/provider.d.ts.map +1 -1
- package/dist/databases/provider.js +339 -186
- package/dist/databases/provider.js.map +1 -1
- package/dist/errorSites.d.ts +57 -0
- package/dist/errorSites.d.ts.map +1 -0
- package/dist/errorSites.js +2 -0
- package/dist/errorSites.js.map +1 -0
- package/dist/redisCache.js +1 -1
- package/dist/tests/integration/clientRecordCache.integration.test.d.ts +2 -0
- package/dist/tests/integration/clientRecordCache.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/clientRecordCache.integration.test.js +87 -0
- package/dist/tests/integration/clientRecordCache.integration.test.js.map +1 -0
- package/package.json +13 -13
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MongoDatabase } from "../base/mongo.js";
|
|
2
|
-
import {
|
|
2
|
+
import { clientRecordCache } from "./clientRecordCache.js";
|
|
3
|
+
import { ProsopoError } from "@prosopo/common";
|
|
3
4
|
import { CaptchaStates, CaptchaStatus, CaptchaType, DatasetWithIdsAndTreeSchema, DecisionMachineKind, StoredStatusNames, UserCommitmentSchema, isBlockingCaptchaResult } from "@prosopo/types";
|
|
4
5
|
import { AudioCaptchaRecordSchema, CaptchaRecordSchema, ClientRecordSchema, DatasetRecordSchema, DecisionMachineArtifactRecordSchema, IconOrderCaptchaRecordSchema, PoWCaptchaRecordSchema, PuzzleCaptchaRecordSchema, SESSION_PROJECTION, ScheduledTaskRecordSchema, ScheduledTaskSchema, SessionRecordSchema, SolutionRecordSchema, SpamEmailDomainRecordSchema, UserCommitmentRecordSchema, UserSolutionRecordSchema } from "@prosopo/types-database";
|
|
5
6
|
import { isHex } from "@polkadot/util/is";
|
|
@@ -121,18 +122,28 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
121
122
|
this.tables = tables;
|
|
122
123
|
}
|
|
123
124
|
getTables() {
|
|
124
|
-
if (!this.tables) throw new
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
if (!this.tables) throw new ProsopoError({
|
|
126
|
+
code: "DB_UNAVAILABLE",
|
|
127
|
+
errorSite: "DBSE-5",
|
|
128
|
+
message: "Tables undefined",
|
|
129
|
+
context: { failedFuncName: this.getTables.name }
|
|
127
130
|
});
|
|
128
131
|
return this.tables;
|
|
129
132
|
}
|
|
130
133
|
getRedisAccessRulesConnection() {
|
|
131
|
-
if (null === this.redisAccessRulesConnection) throw new
|
|
134
|
+
if (null === this.redisAccessRulesConnection) throw new ProsopoError({
|
|
135
|
+
code: "DB_UNAVAILABLE",
|
|
136
|
+
errorSite: "DBSE-6",
|
|
137
|
+
message: "Redis access rules connection undefined"
|
|
138
|
+
});
|
|
132
139
|
return this.redisAccessRulesConnection;
|
|
133
140
|
}
|
|
134
141
|
getRedisConnection() {
|
|
135
|
-
if (null === this.redisConnection) throw new
|
|
142
|
+
if (null === this.redisConnection) throw new ProsopoError({
|
|
143
|
+
code: "DB_UNAVAILABLE",
|
|
144
|
+
errorSite: "DBSE-7",
|
|
145
|
+
message: "Redis access rules connection undefined"
|
|
146
|
+
});
|
|
136
147
|
return this.redisConnection;
|
|
137
148
|
}
|
|
138
149
|
async ensureIndexes() {
|
|
@@ -161,7 +172,11 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
161
172
|
this.indexesEnsured = true;
|
|
162
173
|
}
|
|
163
174
|
getUserAccessRulesStorage() {
|
|
164
|
-
if (null === this.userAccessRulesStorage) throw new
|
|
175
|
+
if (null === this.userAccessRulesStorage) throw new ProsopoError({
|
|
176
|
+
code: "DB_UNAVAILABLE",
|
|
177
|
+
errorSite: "DBSE-8",
|
|
178
|
+
message: "User access rules storage undefined"
|
|
179
|
+
});
|
|
165
180
|
return this.userAccessRulesStorage;
|
|
166
181
|
}
|
|
167
182
|
/**
|
|
@@ -216,12 +231,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
216
231
|
} })));
|
|
217
232
|
this.logger.debug(() => ({ msg: "Dataset stored in database" }));
|
|
218
233
|
} catch (err) {
|
|
219
|
-
throw new
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
234
|
+
throw new ProsopoError({
|
|
235
|
+
code: "DB_QUERY_FAILED",
|
|
236
|
+
errorSite: "DBSE-9",
|
|
237
|
+
message: "Data set load failed",
|
|
238
|
+
cause: err,
|
|
239
|
+
context: { failedFuncName: this.storeDataset.name }
|
|
225
240
|
});
|
|
226
241
|
}
|
|
227
242
|
}
|
|
@@ -273,10 +288,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
273
288
|
})
|
|
274
289
|
};
|
|
275
290
|
}
|
|
276
|
-
throw new
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
291
|
+
throw new ProsopoError({
|
|
292
|
+
code: "DB_QUERY_FAILED",
|
|
293
|
+
errorSite: "DBSE-10",
|
|
294
|
+
message: "Failed to get dataset",
|
|
295
|
+
context: {
|
|
296
|
+
failedFuncName: this.getDataset.name,
|
|
297
|
+
datasetId
|
|
298
|
+
}
|
|
299
|
+
});
|
|
280
300
|
}
|
|
281
301
|
/**
|
|
282
302
|
* @description Get random captchas that are solved or not solved
|
|
@@ -285,10 +305,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
285
305
|
* @param {number} size the number of records to be returned
|
|
286
306
|
*/
|
|
287
307
|
async getRandomCaptcha(solved, datasetId, size) {
|
|
288
|
-
if (!isHex(datasetId)) throw new
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
308
|
+
if (!isHex(datasetId)) throw new ProsopoError({
|
|
309
|
+
code: "INVALID_DATA",
|
|
310
|
+
errorSite: "DBSE-11",
|
|
311
|
+
message: "Invalid hash",
|
|
312
|
+
context: {
|
|
313
|
+
failedFuncName: this.getRandomCaptcha.name,
|
|
314
|
+
datasetId
|
|
315
|
+
}
|
|
316
|
+
});
|
|
292
317
|
const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
|
|
293
318
|
const projection = {
|
|
294
319
|
_id: 0,
|
|
@@ -324,12 +349,17 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
324
349
|
if (fallback.length > 0) return fallback.map(({ _id, ...keep }) => keep);
|
|
325
350
|
}
|
|
326
351
|
if (docs.length > 0) return docs;
|
|
327
|
-
throw new
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
352
|
+
throw new ProsopoError({
|
|
353
|
+
code: "DB_QUERY_FAILED",
|
|
354
|
+
errorSite: "DBSE-12",
|
|
355
|
+
message: "Failed to get captcha",
|
|
356
|
+
context: {
|
|
357
|
+
failedFuncName: this.getRandomCaptcha.name,
|
|
358
|
+
solved,
|
|
359
|
+
datasetId,
|
|
360
|
+
size
|
|
361
|
+
}
|
|
362
|
+
});
|
|
333
363
|
}
|
|
334
364
|
/**
|
|
335
365
|
* @description Get captchas by id
|
|
@@ -344,10 +374,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
344
374
|
items: 1
|
|
345
375
|
}).lean();
|
|
346
376
|
if (docs?.length) return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
|
|
347
|
-
throw new
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
377
|
+
throw new ProsopoError({
|
|
378
|
+
code: "DB_QUERY_FAILED",
|
|
379
|
+
errorSite: "DBSE-13",
|
|
380
|
+
message: "Failed to get captcha",
|
|
381
|
+
context: {
|
|
382
|
+
failedFuncName: this.getCaptchaById.name,
|
|
383
|
+
captchaId
|
|
384
|
+
}
|
|
385
|
+
});
|
|
351
386
|
}
|
|
352
387
|
/**
|
|
353
388
|
* @description Update a captcha
|
|
@@ -355,18 +390,26 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
355
390
|
* @param {string} datasetId the id of the data set
|
|
356
391
|
*/
|
|
357
392
|
async updateCaptcha(captcha, datasetId) {
|
|
358
|
-
if (!isHex(datasetId)) throw new
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
393
|
+
if (!isHex(datasetId)) throw new ProsopoError({
|
|
394
|
+
code: "INVALID_DATA",
|
|
395
|
+
errorSite: "DBSE-14",
|
|
396
|
+
message: "Invalid hash",
|
|
397
|
+
context: {
|
|
398
|
+
failedFuncName: this.updateCaptcha.name,
|
|
399
|
+
datasetId
|
|
400
|
+
}
|
|
401
|
+
});
|
|
362
402
|
try {
|
|
363
403
|
const filter = { datasetId };
|
|
364
404
|
await this.tables?.captcha.updateOne(filter, { $set: captcha }, { upsert: false });
|
|
365
405
|
} catch (err) {
|
|
366
|
-
throw new
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
406
|
+
throw new ProsopoError({
|
|
407
|
+
code: "DB_QUERY_FAILED",
|
|
408
|
+
errorSite: "DBSE-15",
|
|
409
|
+
message: "Failed to update captcha",
|
|
410
|
+
cause: err,
|
|
411
|
+
context: { failedFuncName: this.getDatasetDetails.name }
|
|
412
|
+
});
|
|
370
413
|
}
|
|
371
414
|
}
|
|
372
415
|
/**
|
|
@@ -389,17 +432,27 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
389
432
|
return typeof datasetId === "string" ? datasetId : void 0;
|
|
390
433
|
}
|
|
391
434
|
async getDatasetDetails(datasetId) {
|
|
392
|
-
if (!isHex(datasetId)) throw new
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
435
|
+
if (!isHex(datasetId)) throw new ProsopoError({
|
|
436
|
+
code: "INVALID_DATA",
|
|
437
|
+
errorSite: "DBSE-16",
|
|
438
|
+
message: "Invalid hash",
|
|
439
|
+
context: {
|
|
440
|
+
failedFuncName: this.getDatasetDetails.name,
|
|
441
|
+
datasetId
|
|
442
|
+
}
|
|
443
|
+
});
|
|
396
444
|
const filter = { datasetId };
|
|
397
445
|
const doc = await this.tables?.dataset.findOne(filter).lean();
|
|
398
446
|
if (doc) return doc;
|
|
399
|
-
throw new
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
447
|
+
throw new ProsopoError({
|
|
448
|
+
code: "DB_QUERY_FAILED",
|
|
449
|
+
errorSite: "DBSE-17",
|
|
450
|
+
message: "Failed to get dataset",
|
|
451
|
+
context: {
|
|
452
|
+
failedFuncName: this.getDatasetDetails.name,
|
|
453
|
+
datasetId
|
|
454
|
+
}
|
|
455
|
+
});
|
|
403
456
|
}
|
|
404
457
|
/**
|
|
405
458
|
* @description Store a Dapp User's captcha solution commitment
|
|
@@ -488,15 +541,17 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
488
541
|
$unset: { pendingStage: 1 }
|
|
489
542
|
}).then(() => {}));
|
|
490
543
|
} catch (error) {
|
|
491
|
-
const err = new
|
|
544
|
+
const err = new ProsopoError({
|
|
545
|
+
code: "DB_QUERY_FAILED",
|
|
546
|
+
errorSite: "DBSE-18",
|
|
547
|
+
message: "Failed to update captcha",
|
|
548
|
+
cause: error,
|
|
492
549
|
context: {
|
|
493
|
-
error,
|
|
494
550
|
challenge,
|
|
495
551
|
userSubmitted,
|
|
496
552
|
serverChecked,
|
|
497
553
|
ipInfo
|
|
498
|
-
}
|
|
499
|
-
logger: this.logger
|
|
554
|
+
}
|
|
500
555
|
});
|
|
501
556
|
this.logger.error(() => ({
|
|
502
557
|
err: error,
|
|
@@ -511,9 +566,11 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
511
566
|
* @returns {Promise<PoWCaptchaRecord | null>} A promise that resolves with the found record or null if not found.
|
|
512
567
|
*/
|
|
513
568
|
async getPowCaptchaRecordByChallenge(challenge) {
|
|
514
|
-
if (!this.tables) throw new
|
|
515
|
-
|
|
516
|
-
|
|
569
|
+
if (!this.tables) throw new ProsopoError({
|
|
570
|
+
code: "DB_QUERY_FAILED",
|
|
571
|
+
errorSite: "DBSE-19",
|
|
572
|
+
message: "Database client is not connected",
|
|
573
|
+
context: { failedFuncName: this.getPowCaptchaRecordByChallenge.name }
|
|
517
574
|
});
|
|
518
575
|
try {
|
|
519
576
|
const filter = { challenge };
|
|
@@ -552,12 +609,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
552
609
|
}));
|
|
553
610
|
return null;
|
|
554
611
|
} catch (error) {
|
|
555
|
-
const err = new
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
612
|
+
const err = new ProsopoError({
|
|
613
|
+
code: "DB_QUERY_FAILED",
|
|
614
|
+
errorSite: "DBSE-20",
|
|
615
|
+
message: "Failed to get captcha",
|
|
616
|
+
cause: error,
|
|
617
|
+
context: { challenge }
|
|
561
618
|
});
|
|
562
619
|
this.logger.error(() => ({
|
|
563
620
|
err,
|
|
@@ -594,12 +651,14 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
594
651
|
if (isDisapproved) setStage.failedAtTimestamp = { $ifNull: ["$failedAtTimestamp", timestamp] };
|
|
595
652
|
try {
|
|
596
653
|
if ((await tables.powcaptcha.updateOne({ challenge }, [{ $set: setStage }], { updatePipeline: true })).matchedCount === 0) {
|
|
597
|
-
const err = new
|
|
654
|
+
const err = new ProsopoError({
|
|
655
|
+
code: "DB_QUERY_FAILED",
|
|
656
|
+
errorSite: "DBSE-21",
|
|
657
|
+
message: "Failed to get captcha",
|
|
598
658
|
context: {
|
|
599
659
|
challenge,
|
|
600
660
|
...setStage
|
|
601
|
-
}
|
|
602
|
-
logger: this.logger
|
|
661
|
+
}
|
|
603
662
|
});
|
|
604
663
|
this.logger.info(() => ({
|
|
605
664
|
err,
|
|
@@ -622,13 +681,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
622
681
|
$unset: { pendingStage: 1 }
|
|
623
682
|
}).then(() => {}));
|
|
624
683
|
} catch (error) {
|
|
625
|
-
const err = new
|
|
684
|
+
const err = new ProsopoError({
|
|
685
|
+
code: "DB_QUERY_FAILED",
|
|
686
|
+
errorSite: "DBSE-22",
|
|
687
|
+
message: "Failed to update captcha",
|
|
688
|
+
cause: error,
|
|
626
689
|
context: {
|
|
627
|
-
error,
|
|
628
690
|
challenge,
|
|
629
691
|
...setStage
|
|
630
|
-
}
|
|
631
|
-
logger: this.logger
|
|
692
|
+
}
|
|
632
693
|
});
|
|
633
694
|
this.logger.error(() => ({
|
|
634
695
|
err,
|
|
@@ -721,13 +782,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
721
782
|
}));
|
|
722
783
|
collection.streamRecord(record, this.markInteractiveRecordStored(collection, challenge));
|
|
723
784
|
} catch (error) {
|
|
724
|
-
const err = new
|
|
785
|
+
const err = new ProsopoError({
|
|
786
|
+
code: "DB_QUERY_FAILED",
|
|
787
|
+
errorSite: "DBSE-23",
|
|
788
|
+
message: "Failed to update captcha",
|
|
789
|
+
cause: error,
|
|
725
790
|
context: {
|
|
726
|
-
error,
|
|
727
791
|
challenge,
|
|
728
792
|
ipInfo
|
|
729
|
-
}
|
|
730
|
-
logger: this.logger
|
|
793
|
+
}
|
|
731
794
|
});
|
|
732
795
|
this.logger.error(() => ({
|
|
733
796
|
err: error,
|
|
@@ -779,9 +842,11 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
779
842
|
});
|
|
780
843
|
}
|
|
781
844
|
async getInteractiveCaptchaRecordByChallenge(collection, challenge, failedFuncName) {
|
|
782
|
-
if (!this.tables) throw new
|
|
783
|
-
|
|
784
|
-
|
|
845
|
+
if (!this.tables) throw new ProsopoError({
|
|
846
|
+
code: "DB_QUERY_FAILED",
|
|
847
|
+
errorSite: "DBSE-24",
|
|
848
|
+
message: "Database client is not connected",
|
|
849
|
+
context: { failedFuncName }
|
|
785
850
|
});
|
|
786
851
|
try {
|
|
787
852
|
const record = await this.tables[collection.table].findOne({ challenge }, {
|
|
@@ -817,12 +882,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
817
882
|
}));
|
|
818
883
|
return null;
|
|
819
884
|
} catch (error) {
|
|
820
|
-
const err = new
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
885
|
+
const err = new ProsopoError({
|
|
886
|
+
code: "DB_QUERY_FAILED",
|
|
887
|
+
errorSite: "DBSE-25",
|
|
888
|
+
message: "Failed to get captcha",
|
|
889
|
+
cause: error,
|
|
890
|
+
context: { challenge }
|
|
826
891
|
});
|
|
827
892
|
this.logger.error(() => ({
|
|
828
893
|
err,
|
|
@@ -870,12 +935,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
870
935
|
}));
|
|
871
936
|
return won;
|
|
872
937
|
} catch (error) {
|
|
873
|
-
const err = new
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
938
|
+
const err = new ProsopoError({
|
|
939
|
+
code: "DB_QUERY_FAILED",
|
|
940
|
+
errorSite: "DBSE-26",
|
|
941
|
+
message: "Failed to update captcha",
|
|
942
|
+
cause: error,
|
|
943
|
+
context: { challenge }
|
|
879
944
|
});
|
|
880
945
|
this.logger.error(() => ({
|
|
881
946
|
err,
|
|
@@ -909,12 +974,14 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
909
974
|
};
|
|
910
975
|
try {
|
|
911
976
|
if ((await tables[collection.table].updateOne({ challenge }, { $set: setStage })).matchedCount === 0) {
|
|
912
|
-
const err = new
|
|
977
|
+
const err = new ProsopoError({
|
|
978
|
+
code: "DB_QUERY_FAILED",
|
|
979
|
+
errorSite: "DBSE-27",
|
|
980
|
+
message: "Failed to get captcha",
|
|
913
981
|
context: {
|
|
914
982
|
challenge,
|
|
915
983
|
...setStage
|
|
916
|
-
}
|
|
917
|
-
logger: this.logger
|
|
984
|
+
}
|
|
918
985
|
});
|
|
919
986
|
this.logger.info(() => ({
|
|
920
987
|
err,
|
|
@@ -931,13 +998,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
931
998
|
}));
|
|
932
999
|
this.streamInteractiveUpdate(collection, challenge);
|
|
933
1000
|
} catch (error) {
|
|
934
|
-
const err = new
|
|
1001
|
+
const err = new ProsopoError({
|
|
1002
|
+
code: "DB_QUERY_FAILED",
|
|
1003
|
+
errorSite: "DBSE-28",
|
|
1004
|
+
message: "Failed to update captcha",
|
|
1005
|
+
cause: error,
|
|
935
1006
|
context: {
|
|
936
|
-
error,
|
|
937
1007
|
challenge,
|
|
938
1008
|
...setStage
|
|
939
|
-
}
|
|
940
|
-
logger: this.logger
|
|
1009
|
+
}
|
|
941
1010
|
});
|
|
942
1011
|
this.logger.error(() => ({
|
|
943
1012
|
err,
|
|
@@ -1195,12 +1264,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1195
1264
|
$unset: { pendingStage: 1 }
|
|
1196
1265
|
}).then(() => {}));
|
|
1197
1266
|
} catch (err) {
|
|
1198
|
-
throw new
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1267
|
+
throw new ProsopoError({
|
|
1268
|
+
code: "DB_QUERY_FAILED",
|
|
1269
|
+
errorSite: "DBSE-29",
|
|
1270
|
+
message: "Failed to store session",
|
|
1271
|
+
cause: err,
|
|
1272
|
+
context: { sessionId: sessionRecord.sessionId }
|
|
1204
1273
|
});
|
|
1205
1274
|
}
|
|
1206
1275
|
}
|
|
@@ -1281,12 +1350,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1281
1350
|
pendingStage: true
|
|
1282
1351
|
}).lean() || void 0;
|
|
1283
1352
|
} catch (err) {
|
|
1284
|
-
throw new
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1353
|
+
throw new ProsopoError({
|
|
1354
|
+
code: "DB_QUERY_FAILED",
|
|
1355
|
+
errorSite: "DBSE-30",
|
|
1356
|
+
message: "Failed to check and remove session",
|
|
1357
|
+
cause: err,
|
|
1358
|
+
context: { sessionId }
|
|
1290
1359
|
});
|
|
1291
1360
|
}
|
|
1292
1361
|
}
|
|
@@ -1301,12 +1370,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1301
1370
|
pendingStage: true
|
|
1302
1371
|
} })).modifiedCount > 0;
|
|
1303
1372
|
} catch (err) {
|
|
1304
|
-
throw new
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1373
|
+
throw new ProsopoError({
|
|
1374
|
+
code: "DB_QUERY_FAILED",
|
|
1375
|
+
errorSite: "DBSE-31",
|
|
1376
|
+
message: "Failed to get session",
|
|
1377
|
+
cause: err,
|
|
1378
|
+
context: { sessionId }
|
|
1310
1379
|
});
|
|
1311
1380
|
}
|
|
1312
1381
|
}
|
|
@@ -1337,12 +1406,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1337
1406
|
}).catch(() => {});
|
|
1338
1407
|
}
|
|
1339
1408
|
} catch (err) {
|
|
1340
|
-
throw new
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1409
|
+
throw new ProsopoError({
|
|
1410
|
+
code: "DB_QUERY_FAILED",
|
|
1411
|
+
errorSite: "DBSE-32",
|
|
1412
|
+
message: "Failed to get session",
|
|
1413
|
+
cause: err,
|
|
1414
|
+
context: { sessionId }
|
|
1346
1415
|
});
|
|
1347
1416
|
}
|
|
1348
1417
|
}
|
|
@@ -1362,13 +1431,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1362
1431
|
pendingStage: true
|
|
1363
1432
|
} }], { updatePipeline: true });
|
|
1364
1433
|
} catch (err) {
|
|
1365
|
-
throw new
|
|
1434
|
+
throw new ProsopoError({
|
|
1435
|
+
code: "DB_QUERY_FAILED",
|
|
1436
|
+
errorSite: "DBSE-33",
|
|
1437
|
+
message: "Failed to get session",
|
|
1438
|
+
cause: err,
|
|
1366
1439
|
context: {
|
|
1367
|
-
error: err,
|
|
1368
1440
|
sessionId,
|
|
1369
1441
|
stage
|
|
1370
|
-
}
|
|
1371
|
-
logger: this.logger
|
|
1442
|
+
}
|
|
1372
1443
|
});
|
|
1373
1444
|
}
|
|
1374
1445
|
}
|
|
@@ -1395,12 +1466,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1395
1466
|
try {
|
|
1396
1467
|
return (await this.tables.session.updateOne({ sessionId }, [{ $set: setStage }], { updatePipeline: true })).matchedCount > 0;
|
|
1397
1468
|
} catch (err) {
|
|
1398
|
-
throw new
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1469
|
+
throw new ProsopoError({
|
|
1470
|
+
code: "DB_QUERY_FAILED",
|
|
1471
|
+
errorSite: "DBSE-34",
|
|
1472
|
+
message: "Failed to get session",
|
|
1473
|
+
cause: err,
|
|
1474
|
+
context: { sessionId }
|
|
1404
1475
|
});
|
|
1405
1476
|
}
|
|
1406
1477
|
}
|
|
@@ -1421,12 +1492,12 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1421
1492
|
try {
|
|
1422
1493
|
return await this.tables.session.findOne(filter).lean() || void 0;
|
|
1423
1494
|
} catch (err) {
|
|
1424
|
-
throw new
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1495
|
+
throw new ProsopoError({
|
|
1496
|
+
code: "DB_QUERY_FAILED",
|
|
1497
|
+
errorSite: "DBSE-35",
|
|
1498
|
+
message: "Failed to get session",
|
|
1499
|
+
cause: err,
|
|
1500
|
+
context: { userSitekeyIpHash }
|
|
1430
1501
|
});
|
|
1431
1502
|
}
|
|
1432
1503
|
}
|
|
@@ -1463,10 +1534,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1463
1534
|
* @description Store a Dapp User's pending record
|
|
1464
1535
|
*/
|
|
1465
1536
|
async storePendingImageCommitment(userAccount, requestHash, salt, deadlineTimestamp, requestedAtTimestamp, ipAddress, threshold, sessionId, ipInfo) {
|
|
1466
|
-
if (!isHex(requestHash)) throw new
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1537
|
+
if (!isHex(requestHash)) throw new ProsopoError({
|
|
1538
|
+
code: "INVALID_DATA",
|
|
1539
|
+
errorSite: "DBSE-36",
|
|
1540
|
+
message: "Invalid hash",
|
|
1541
|
+
context: {
|
|
1542
|
+
failedFuncName: this.storePendingImageCommitment.name,
|
|
1543
|
+
requestHash
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1470
1546
|
const pendingRecord = {
|
|
1471
1547
|
userAccount,
|
|
1472
1548
|
pending: true,
|
|
@@ -1495,10 +1571,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1495
1571
|
* @description Get a user's pending record
|
|
1496
1572
|
*/
|
|
1497
1573
|
async getPendingImageCommitment(requestHash) {
|
|
1498
|
-
if (!isHex(requestHash)) throw new
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1574
|
+
if (!isHex(requestHash)) throw new ProsopoError({
|
|
1575
|
+
code: "INVALID_DATA",
|
|
1576
|
+
errorSite: "DBSE-37",
|
|
1577
|
+
message: "Invalid hash",
|
|
1578
|
+
context: {
|
|
1579
|
+
failedFuncName: this.getPendingImageCommitment.name,
|
|
1580
|
+
requestHash
|
|
1581
|
+
}
|
|
1582
|
+
});
|
|
1502
1583
|
const doc = await this.tables?.commitment.findOne({
|
|
1503
1584
|
requestHash,
|
|
1504
1585
|
pending: true
|
|
@@ -1514,19 +1595,29 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1514
1595
|
sessionId: doc.sessionId,
|
|
1515
1596
|
threshold: doc.threshold
|
|
1516
1597
|
};
|
|
1517
|
-
throw new
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1598
|
+
throw new ProsopoError({
|
|
1599
|
+
code: "RECORD_NOT_FOUND",
|
|
1600
|
+
errorSite: "DBSE-38",
|
|
1601
|
+
message: "No pending record found",
|
|
1602
|
+
context: {
|
|
1603
|
+
failedFuncName: this.getPendingImageCommitment.name,
|
|
1604
|
+
requestHash
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1521
1607
|
}
|
|
1522
1608
|
/**
|
|
1523
1609
|
* @description Mark a pending request as used
|
|
1524
1610
|
*/
|
|
1525
1611
|
async updatePendingImageCommitmentStatus(requestHash) {
|
|
1526
|
-
if (!isHex(requestHash)) throw new
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1612
|
+
if (!isHex(requestHash)) throw new ProsopoError({
|
|
1613
|
+
code: "INVALID_DATA",
|
|
1614
|
+
errorSite: "DBSE-39",
|
|
1615
|
+
message: "Invalid hash",
|
|
1616
|
+
context: {
|
|
1617
|
+
failedFuncName: this.updatePendingImageCommitmentStatus.name,
|
|
1618
|
+
requestHash
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1530
1621
|
return (await this.getTables().commitment.updateOne({
|
|
1531
1622
|
requestHash,
|
|
1532
1623
|
pending: true
|
|
@@ -1542,7 +1633,11 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1542
1633
|
};
|
|
1543
1634
|
const docs = await this.tables?.captcha.find(filter).lean();
|
|
1544
1635
|
if (docs) return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
|
|
1545
|
-
throw new
|
|
1636
|
+
throw new ProsopoError({
|
|
1637
|
+
code: "DB_QUERY_FAILED",
|
|
1638
|
+
errorSite: "DBSE-40",
|
|
1639
|
+
message: "Failed to get captcha"
|
|
1640
|
+
});
|
|
1546
1641
|
}
|
|
1547
1642
|
/**
|
|
1548
1643
|
* @description Get all dapp user solutions by captchaIds
|
|
@@ -1551,7 +1646,11 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1551
1646
|
const filter = { captchaId: { $in: captchaId } };
|
|
1552
1647
|
const docs = await this.tables?.usersolution?.find(filter).lean();
|
|
1553
1648
|
if (docs) return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
|
|
1554
|
-
throw new
|
|
1649
|
+
throw new ProsopoError({
|
|
1650
|
+
code: "DB_QUERY_FAILED",
|
|
1651
|
+
errorSite: "DBSE-41",
|
|
1652
|
+
message: "Failed to get solution"
|
|
1653
|
+
});
|
|
1555
1654
|
}
|
|
1556
1655
|
async getDatasetIdWithSolvedCaptchasOfSizeN(solvedCaptchaCount) {
|
|
1557
1656
|
const docs = await this.tables?.solution.aggregate([
|
|
@@ -1564,13 +1663,22 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1564
1663
|
{ $sample: { size: 1 } }
|
|
1565
1664
|
]);
|
|
1566
1665
|
if (docs?.length) return docs[0]._id;
|
|
1567
|
-
throw new
|
|
1666
|
+
throw new ProsopoError({
|
|
1667
|
+
code: "DATASET_INVALID",
|
|
1668
|
+
errorSite: "DBSE-42",
|
|
1669
|
+
message: "No datasets found with required number of solutions"
|
|
1670
|
+
});
|
|
1568
1671
|
}
|
|
1569
1672
|
async getRandomSolvedCaptchasFromSingleDataset(datasetId, size) {
|
|
1570
|
-
if (!isHex(datasetId)) throw new
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1673
|
+
if (!isHex(datasetId)) throw new ProsopoError({
|
|
1674
|
+
code: "INVALID_DATA",
|
|
1675
|
+
errorSite: "DBSE-43",
|
|
1676
|
+
message: "Invalid hash",
|
|
1677
|
+
context: {
|
|
1678
|
+
failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
|
|
1679
|
+
datasetId
|
|
1680
|
+
}
|
|
1681
|
+
});
|
|
1574
1682
|
const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
|
|
1575
1683
|
const docs = await this.tables?.solution.aggregate([
|
|
1576
1684
|
{ $match: { datasetId } },
|
|
@@ -1582,11 +1690,16 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1582
1690
|
} }
|
|
1583
1691
|
]);
|
|
1584
1692
|
if (docs?.length) return docs;
|
|
1585
|
-
throw new
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1693
|
+
throw new ProsopoError({
|
|
1694
|
+
code: "DB_QUERY_FAILED",
|
|
1695
|
+
errorSite: "DBSE-44",
|
|
1696
|
+
message: "Failed to get solution",
|
|
1697
|
+
context: {
|
|
1698
|
+
failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
|
|
1699
|
+
datasetId,
|
|
1700
|
+
size
|
|
1701
|
+
}
|
|
1702
|
+
});
|
|
1590
1703
|
}
|
|
1591
1704
|
/**
|
|
1592
1705
|
* @description Get dapp user solution by ID
|
|
@@ -1596,10 +1709,15 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1596
1709
|
const filter = { commitmentId };
|
|
1597
1710
|
const doc = await this.tables?.usersolution?.findOne(filter, { _id: 0 }).lean();
|
|
1598
1711
|
if (doc) return doc;
|
|
1599
|
-
throw new
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1712
|
+
throw new ProsopoError({
|
|
1713
|
+
code: "DB_QUERY_FAILED",
|
|
1714
|
+
errorSite: "DBSE-45",
|
|
1715
|
+
message: "Failed to get solution",
|
|
1716
|
+
context: {
|
|
1717
|
+
failedFuncName: this.getCaptchaById.name,
|
|
1718
|
+
commitmentId
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1603
1721
|
}
|
|
1604
1722
|
static {
|
|
1605
1723
|
this.DAPP_USER_COMMITMENT_PROJECTION = {
|
|
@@ -1669,10 +1787,13 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1669
1787
|
$unset: { pendingStage: 1 }
|
|
1670
1788
|
}).then(() => {}));
|
|
1671
1789
|
} catch (err) {
|
|
1672
|
-
throw new
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1790
|
+
throw new ProsopoError({
|
|
1791
|
+
code: "DB_QUERY_FAILED",
|
|
1792
|
+
errorSite: "DBSE-46",
|
|
1793
|
+
message: "Failed to approve solution",
|
|
1794
|
+
cause: err,
|
|
1795
|
+
context: { commitmentId }
|
|
1796
|
+
});
|
|
1676
1797
|
}
|
|
1677
1798
|
}
|
|
1678
1799
|
/**
|
|
@@ -1704,10 +1825,13 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1704
1825
|
$unset: { pendingStage: 1 }
|
|
1705
1826
|
}).then(() => {}));
|
|
1706
1827
|
} catch (err) {
|
|
1707
|
-
throw new
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1828
|
+
throw new ProsopoError({
|
|
1829
|
+
code: "DB_QUERY_FAILED",
|
|
1830
|
+
errorSite: "DBSE-47",
|
|
1831
|
+
message: "Failed to approve solution",
|
|
1832
|
+
cause: err,
|
|
1833
|
+
context: { commitmentId }
|
|
1834
|
+
});
|
|
1711
1835
|
}
|
|
1712
1836
|
}
|
|
1713
1837
|
/**
|
|
@@ -1718,10 +1842,13 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1718
1842
|
try {
|
|
1719
1843
|
await this.tables?.usersolution?.updateMany({ captchaId: { $in: captchaIds } }, { $set: { processed: true } }, { upsert: false }).lean();
|
|
1720
1844
|
} catch (err) {
|
|
1721
|
-
throw new
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1845
|
+
throw new ProsopoError({
|
|
1846
|
+
code: "DB_QUERY_FAILED",
|
|
1847
|
+
errorSite: "DBSE-48",
|
|
1848
|
+
message: "Failed to flag solution as processed",
|
|
1849
|
+
cause: err,
|
|
1850
|
+
context: { captchaIds }
|
|
1851
|
+
});
|
|
1725
1852
|
}
|
|
1726
1853
|
}
|
|
1727
1854
|
/**
|
|
@@ -1733,10 +1860,13 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1733
1860
|
const distinctCommitmentIds = [...new Set(commitmentIds)];
|
|
1734
1861
|
await this.tables?.commitment?.updateMany({ id: { $in: distinctCommitmentIds } }, { $set: { processed: true } }, { upsert: false }).lean();
|
|
1735
1862
|
} catch (err) {
|
|
1736
|
-
throw new
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1863
|
+
throw new ProsopoError({
|
|
1864
|
+
code: "DB_QUERY_FAILED",
|
|
1865
|
+
errorSite: "DBSE-49",
|
|
1866
|
+
message: "Failed to flag commitment as processed",
|
|
1867
|
+
cause: err,
|
|
1868
|
+
context: { commitmentIds }
|
|
1869
|
+
});
|
|
1740
1870
|
}
|
|
1741
1871
|
}
|
|
1742
1872
|
/**
|
|
@@ -1819,14 +1949,22 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1819
1949
|
await this.logger.debug(() => ({ msg: "No client updates to apply" }));
|
|
1820
1950
|
return;
|
|
1821
1951
|
}
|
|
1822
|
-
|
|
1952
|
+
try {
|
|
1953
|
+
await this.tables?.client.bulkWrite(ops);
|
|
1954
|
+
} finally {
|
|
1955
|
+
clientRecordCache.clear();
|
|
1956
|
+
}
|
|
1823
1957
|
}
|
|
1824
1958
|
/**
|
|
1825
1959
|
* @description Remove client records by account
|
|
1826
1960
|
*/
|
|
1827
1961
|
async removeClientRecords(accounts) {
|
|
1828
1962
|
if (!accounts || accounts.length === 0) return;
|
|
1829
|
-
|
|
1963
|
+
try {
|
|
1964
|
+
await this.tables?.client.deleteMany({ account: { $in: accounts } });
|
|
1965
|
+
} finally {
|
|
1966
|
+
clientRecordCache.clear();
|
|
1967
|
+
}
|
|
1830
1968
|
}
|
|
1831
1969
|
/**
|
|
1832
1970
|
* @description Get all client records
|
|
@@ -1838,13 +1976,18 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1838
1976
|
* @description Get a client record
|
|
1839
1977
|
*/
|
|
1840
1978
|
async getClientRecord(account) {
|
|
1979
|
+
const cacheKey = `${this.url}|${account}`;
|
|
1980
|
+
const cached = clientRecordCache.get(cacheKey);
|
|
1981
|
+
if (cached) return cached;
|
|
1841
1982
|
const filter = { account };
|
|
1842
1983
|
const doc = await this.tables?.client.findOne(filter, {
|
|
1843
1984
|
account: 1,
|
|
1844
1985
|
settings: 1,
|
|
1845
1986
|
tier: 1
|
|
1846
1987
|
}).lean();
|
|
1847
|
-
|
|
1988
|
+
if (!doc) return void 0;
|
|
1989
|
+
clientRecordCache.set(cacheKey, doc);
|
|
1990
|
+
return doc;
|
|
1848
1991
|
}
|
|
1849
1992
|
/**
|
|
1850
1993
|
* Stores a decision machine artifact with a unique scope identifier.
|
|
@@ -1930,13 +2073,23 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
|
|
|
1930
2073
|
return (await this.tables?.decisionMachine.deleteMany({}))?.deletedCount ?? 0;
|
|
1931
2074
|
}
|
|
1932
2075
|
async getSpamEmailDomain(domain) {
|
|
1933
|
-
if (!this.tables?.spamEmailDomain) throw new
|
|
2076
|
+
if (!this.tables?.spamEmailDomain) throw new ProsopoError({
|
|
2077
|
+
code: "DB_QUERY_FAILED",
|
|
2078
|
+
errorSite: "DBSE-50",
|
|
2079
|
+
message: "Failed to import database engine",
|
|
2080
|
+
context: { failedFuncName: this.getSpamEmailDomain.name }
|
|
2081
|
+
});
|
|
1934
2082
|
const suffixCandidates = buildDomainSuffixCandidates(domain).slice(0, MAX_DOMAIN_SUFFIX_CANDIDATES);
|
|
1935
2083
|
const query = suffixCandidates.length > 0 ? { domain: { $in: suffixCandidates } } : { domain };
|
|
1936
2084
|
return await this.tables.spamEmailDomain.findOne(query).exec();
|
|
1937
2085
|
}
|
|
1938
2086
|
async bulkUpdateSpamEmailDomains(domains, upsert) {
|
|
1939
|
-
if (!this.tables?.spamEmailDomain) throw new
|
|
2087
|
+
if (!this.tables?.spamEmailDomain) throw new ProsopoError({
|
|
2088
|
+
code: "DB_QUERY_FAILED",
|
|
2089
|
+
errorSite: "DBSE-51",
|
|
2090
|
+
message: "Failed to import database engine",
|
|
2091
|
+
context: { failedFuncName: this.bulkUpdateSpamEmailDomains.name }
|
|
2092
|
+
});
|
|
1940
2093
|
const bulkOps = domains.map((op) => ({ updateOne: {
|
|
1941
2094
|
filter: op.filter,
|
|
1942
2095
|
update: { $set: op.update },
|