@prosopo/database 2.1.0 → 2.1.2

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 (40) hide show
  1. package/package.json +5 -5
  2. package/dist/base/index.d.ts +0 -3
  3. package/dist/base/index.d.ts.map +0 -1
  4. package/dist/base/index.js +0 -3
  5. package/dist/base/index.js.map +0 -1
  6. package/dist/base/mongo.d.ts +0 -16
  7. package/dist/base/mongo.d.ts.map +0 -1
  8. package/dist/base/mongo.js +0 -89
  9. package/dist/base/mongo.js.map +0 -1
  10. package/dist/base/mongoMemory.d.ts +0 -11
  11. package/dist/base/mongoMemory.d.ts.map +0 -1
  12. package/dist/base/mongoMemory.js +0 -27
  13. package/dist/base/mongoMemory.js.map +0 -1
  14. package/dist/cjs/base/index.cjs +0 -6
  15. package/dist/cjs/base/mongo.cjs +0 -97
  16. package/dist/cjs/base/mongoMemory.cjs +0 -28
  17. package/dist/cjs/databases/captcha.cjs +0 -82
  18. package/dist/cjs/databases/client.cjs +0 -46
  19. package/dist/cjs/databases/index.cjs +0 -19
  20. package/dist/cjs/databases/provider.cjs +0 -942
  21. package/dist/cjs/index.cjs +0 -15
  22. package/dist/databases/captcha.d.ts +0 -16
  23. package/dist/databases/captcha.d.ts.map +0 -1
  24. package/dist/databases/captcha.js +0 -75
  25. package/dist/databases/captcha.js.map +0 -1
  26. package/dist/databases/client.d.ts +0 -12
  27. package/dist/databases/client.d.ts.map +0 -1
  28. package/dist/databases/client.js +0 -42
  29. package/dist/databases/client.js.map +0 -1
  30. package/dist/databases/index.d.ts +0 -16
  31. package/dist/databases/index.d.ts.map +0 -1
  32. package/dist/databases/index.js +0 -17
  33. package/dist/databases/index.js.map +0 -1
  34. package/dist/databases/provider.d.ts +0 -68
  35. package/dist/databases/provider.d.ts.map +0 -1
  36. package/dist/databases/provider.js +0 -786
  37. package/dist/databases/provider.js.map +0 -1
  38. package/dist/index.d.ts +0 -3
  39. package/dist/index.d.ts.map +0 -1
  40. package/dist/index.js.map +0 -1
@@ -1,786 +0,0 @@
1
- import { isHex } from "@polkadot/util/is";
2
- import { ProsopoDBError, ProsopoEnvError, } from "@prosopo/common";
3
- import { CaptchaStates, CaptchaStatus, DatasetWithIdsAndTreeSchema, } from "@prosopo/types";
4
- import { CaptchaRecordSchema, ClientRecordSchema, DatasetRecordSchema, PendingRecordSchema, PoWCaptchaRecordSchema, ScheduledTaskRecordSchema, ScheduledTaskSchema, SolutionRecordSchema, StoredStatusNames, UserCommitmentRecordSchema, UserCommitmentSchema, UserSolutionRecordSchema, } from "@prosopo/types-database";
5
- import { MongoDatabase } from "../base/mongo.js";
6
- var TableNames;
7
- (function (TableNames) {
8
- TableNames["captcha"] = "captcha";
9
- TableNames["dataset"] = "dataset";
10
- TableNames["solution"] = "solution";
11
- TableNames["commitment"] = "commitment";
12
- TableNames["usersolution"] = "usersolution";
13
- TableNames["pending"] = "pending";
14
- TableNames["scheduler"] = "scheduler";
15
- TableNames["powcaptcha"] = "powcaptcha";
16
- TableNames["client"] = "client";
17
- })(TableNames || (TableNames = {}));
18
- const PROVIDER_TABLES = [
19
- {
20
- collectionName: TableNames.captcha,
21
- modelName: "Captcha",
22
- schema: CaptchaRecordSchema,
23
- },
24
- {
25
- collectionName: TableNames.powcaptcha,
26
- modelName: "PowCaptcha",
27
- schema: PoWCaptchaRecordSchema,
28
- },
29
- {
30
- collectionName: TableNames.dataset,
31
- modelName: "Dataset",
32
- schema: DatasetRecordSchema,
33
- },
34
- {
35
- collectionName: TableNames.solution,
36
- modelName: "Solution",
37
- schema: SolutionRecordSchema,
38
- },
39
- {
40
- collectionName: TableNames.commitment,
41
- modelName: "UserCommitment",
42
- schema: UserCommitmentRecordSchema,
43
- },
44
- {
45
- collectionName: TableNames.usersolution,
46
- modelName: "UserSolution",
47
- schema: UserSolutionRecordSchema,
48
- },
49
- {
50
- collectionName: TableNames.pending,
51
- modelName: "Pending",
52
- schema: PendingRecordSchema,
53
- },
54
- {
55
- collectionName: TableNames.scheduler,
56
- modelName: "Scheduler",
57
- schema: ScheduledTaskRecordSchema,
58
- },
59
- {
60
- collectionName: TableNames.client,
61
- modelName: "Client",
62
- schema: ClientRecordSchema,
63
- },
64
- ];
65
- export class ProviderDatabase extends MongoDatabase {
66
- constructor(url, dbname, authSource, logger) {
67
- super(url, dbname, authSource, logger);
68
- this.tables = {};
69
- this.tables = {};
70
- }
71
- async connect() {
72
- await super.connect();
73
- this.loadTables();
74
- }
75
- loadTables() {
76
- const tables = {};
77
- PROVIDER_TABLES.map(({ collectionName, modelName, schema }) => {
78
- if (this.connection) {
79
- tables[collectionName] = this.connection.model(modelName, schema);
80
- }
81
- });
82
- this.tables = tables;
83
- }
84
- getTables() {
85
- if (!this.tables) {
86
- throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
87
- context: { failedFuncName: this.getTables.name },
88
- logger: this.logger,
89
- });
90
- }
91
- return this.tables;
92
- }
93
- async storeDataset(dataset) {
94
- try {
95
- this.logger.debug("Storing dataset in database");
96
- const parsedDataset = DatasetWithIdsAndTreeSchema.parse(dataset);
97
- const datasetDoc = {
98
- datasetId: parsedDataset.datasetId,
99
- datasetContentId: parsedDataset.datasetContentId,
100
- format: parsedDataset.format,
101
- contentTree: parsedDataset.contentTree,
102
- solutionTree: parsedDataset.solutionTree,
103
- };
104
- await this.tables.dataset?.updateOne({ datasetId: parsedDataset.datasetId }, { $set: datasetDoc }, { upsert: true });
105
- const captchaDocs = parsedDataset.captchas.map(({ solution, ...captcha }, index) => ({
106
- ...captcha,
107
- datasetId: parsedDataset.datasetId,
108
- datasetContentId: parsedDataset.datasetContentId,
109
- index,
110
- solved: !!solution?.length,
111
- }));
112
- this.logger.debug("Inserting captcha records");
113
- if (captchaDocs.length) {
114
- await this.tables?.captcha.bulkWrite(captchaDocs.map((captchaDoc) => ({
115
- updateOne: {
116
- filter: { captchaId: captchaDoc.captchaId },
117
- update: { $set: captchaDoc },
118
- upsert: true,
119
- },
120
- })));
121
- }
122
- const captchaSolutionDocs = parsedDataset.captchas
123
- .filter(({ solution }) => solution?.length)
124
- .map((captcha) => ({
125
- captchaId: captcha.captchaId,
126
- captchaContentId: captcha.captchaContentId,
127
- solution: captcha.solution,
128
- salt: captcha.salt,
129
- datasetId: parsedDataset.datasetId,
130
- datasetContentId: parsedDataset.datasetContentId,
131
- }));
132
- this.logger.debug("Inserting solution records");
133
- if (captchaSolutionDocs.length) {
134
- await this.tables?.solution.bulkWrite(captchaSolutionDocs.map((captchaSolutionDoc) => ({
135
- updateOne: {
136
- filter: { captchaId: captchaSolutionDoc.captchaId },
137
- update: { $set: captchaSolutionDoc },
138
- upsert: true,
139
- },
140
- })));
141
- }
142
- this.logger.debug("Dataset stored in database");
143
- }
144
- catch (err) {
145
- throw new ProsopoDBError("DATABASE.DATASET_LOAD_FAILED", {
146
- context: { failedFuncName: this.storeDataset.name, error: err },
147
- logger: this.logger,
148
- });
149
- }
150
- }
151
- async getSolutions(datasetId) {
152
- const docs = await this.tables?.solution
153
- .find({ datasetId })
154
- .lean();
155
- return docs ? docs : [];
156
- }
157
- async getDataset(datasetId) {
158
- const datasetDoc = await this.tables?.dataset
159
- .findOne({ datasetId: datasetId })
160
- .lean();
161
- if (datasetDoc) {
162
- const { datasetContentId, format, contentTree, solutionTree } = datasetDoc;
163
- const captchas = (await this.tables?.captcha.find({ datasetId }).lean()) ||
164
- [];
165
- const solutions = (await this.tables?.solution
166
- .find({ datasetId })
167
- .lean()) || [];
168
- const solutionsKeyed = {};
169
- for (const solution of solutions) {
170
- solutionsKeyed[solution.captchaId] = solution;
171
- }
172
- return {
173
- datasetId,
174
- datasetContentId,
175
- format,
176
- contentTree: contentTree || [],
177
- solutionTree: solutionTree || [],
178
- captchas: captchas.map((captchaDoc) => {
179
- const { captchaId, captchaContentId, items, target, salt, solved } = captchaDoc;
180
- const solution = solutionsKeyed[captchaId];
181
- return {
182
- captchaId,
183
- captchaContentId,
184
- solved: !!solved,
185
- salt,
186
- items,
187
- target,
188
- solution: solved && solution ? solution.solution : [],
189
- };
190
- }),
191
- };
192
- }
193
- throw new ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
194
- context: { failedFuncName: this.getDataset.name, datasetId },
195
- });
196
- }
197
- async getRandomCaptcha(solved, datasetId, size) {
198
- if (!isHex(datasetId)) {
199
- throw new ProsopoDBError("DATABASE.INVALID_HASH", {
200
- context: { failedFuncName: this.getRandomCaptcha.name, datasetId },
201
- });
202
- }
203
- const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
204
- const cursor = this.tables?.captcha.aggregate([
205
- { $match: { datasetId, solved } },
206
- { $sample: { size: sampleSize } },
207
- {
208
- $project: {
209
- datasetId: 1,
210
- datasetContentId: 1,
211
- captchaId: 1,
212
- captchaContentId: 1,
213
- items: 1,
214
- target: 1,
215
- },
216
- },
217
- ]);
218
- const docs = await cursor;
219
- if (docs?.length) {
220
- return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
221
- }
222
- throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
223
- context: {
224
- failedFuncName: this.getRandomCaptcha.name,
225
- solved,
226
- datasetId,
227
- size,
228
- },
229
- });
230
- }
231
- async getCaptchaById(captchaId) {
232
- const cursor = this.tables?.captcha
233
- .find({ captchaId: { $in: captchaId } })
234
- .lean();
235
- const docs = await cursor;
236
- if (docs?.length) {
237
- return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
238
- }
239
- throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
240
- context: { failedFuncName: this.getCaptchaById.name, captchaId },
241
- });
242
- }
243
- async updateCaptcha(captcha, datasetId) {
244
- if (!isHex(datasetId)) {
245
- throw new ProsopoDBError("DATABASE.INVALID_HASH", {
246
- context: { failedFuncName: this.updateCaptcha.name, datasetId },
247
- });
248
- }
249
- try {
250
- await this.tables?.captcha.updateOne({ datasetId }, { $set: captcha }, { upsert: false });
251
- }
252
- catch (err) {
253
- throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
254
- context: { failedFuncName: this.getDatasetDetails.name, error: err },
255
- });
256
- }
257
- }
258
- async removeCaptchas(captchaIds) {
259
- await this.tables?.captcha.deleteMany({ captchaId: { $in: captchaIds } });
260
- }
261
- async getDatasetDetails(datasetId) {
262
- if (!isHex(datasetId)) {
263
- throw new ProsopoDBError("DATABASE.INVALID_HASH", {
264
- context: { failedFuncName: this.getDatasetDetails.name, datasetId },
265
- });
266
- }
267
- const doc = await this.tables?.dataset
268
- .findOne({ datasetId })
269
- .lean();
270
- if (doc) {
271
- return doc;
272
- }
273
- throw new ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
274
- context: {
275
- failedFuncName: this.getDatasetDetails.name,
276
- datasetId,
277
- },
278
- });
279
- }
280
- async storeDappUserSolution(captchas, commit) {
281
- const commitmentRecord = UserCommitmentSchema.parse({
282
- ...commit,
283
- lastUpdatedTimestamp: Date.now(),
284
- });
285
- if (captchas.length) {
286
- await this.tables?.commitment.updateOne({
287
- id: commit.id,
288
- }, commitmentRecord, { upsert: true });
289
- const ops = captchas.map((captcha) => ({
290
- updateOne: {
291
- filter: { commitmentId: commit.id, captchaId: captcha.captchaId },
292
- update: {
293
- $set: {
294
- captchaId: captcha.captchaId,
295
- captchaContentId: captcha.captchaContentId,
296
- salt: captcha.salt,
297
- solution: captcha.solution,
298
- commitmentId: commit.id,
299
- processed: false,
300
- },
301
- },
302
- upsert: true,
303
- },
304
- }));
305
- await this.tables?.usersolution.bulkWrite(ops);
306
- }
307
- }
308
- async storePowCaptchaRecord(challenge, components, difficulty, providerSignature, ipAddress, headers, serverChecked = false, userSubmitted = false, storedStatus = StoredStatusNames.notStored, userSignature) {
309
- const tables = this.getTables();
310
- const powCaptchaRecord = {
311
- challenge,
312
- ...components,
313
- ipAddress,
314
- headers,
315
- result: { status: CaptchaStatus.pending },
316
- userSubmitted,
317
- serverChecked,
318
- difficulty,
319
- providerSignature,
320
- userSignature,
321
- lastUpdatedTimestamp: Date.now(),
322
- };
323
- try {
324
- await tables.powcaptcha.create(powCaptchaRecord);
325
- this.logger.info("PowCaptcha record added successfully", {
326
- challenge,
327
- userSubmitted,
328
- serverChecked,
329
- storedStatus,
330
- });
331
- }
332
- catch (error) {
333
- this.logger.error("Failed to add PowCaptcha record", {
334
- error,
335
- challenge,
336
- userSubmitted,
337
- serverChecked,
338
- storedStatus,
339
- });
340
- throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
341
- context: {
342
- error,
343
- challenge,
344
- userSubmitted,
345
- serverChecked,
346
- storedStatus,
347
- },
348
- logger: this.logger,
349
- });
350
- }
351
- }
352
- async getPowCaptchaRecordByChallenge(challenge) {
353
- if (!this.tables) {
354
- throw new ProsopoEnvError("DATABASE.DATABASE_UNDEFINED", {
355
- context: { failedFuncName: this.getPowCaptchaRecordByChallenge.name },
356
- logger: this.logger,
357
- });
358
- }
359
- try {
360
- const record = await this.tables.powcaptcha
361
- .findOne({ challenge })
362
- .lean();
363
- if (record) {
364
- this.logger.info("PowCaptcha record retrieved successfully", {
365
- challenge,
366
- });
367
- return record;
368
- }
369
- this.logger.info("No PowCaptcha record found", { challenge });
370
- return null;
371
- }
372
- catch (error) {
373
- this.logger.error("Failed to retrieve PowCaptcha record", {
374
- error,
375
- challenge,
376
- });
377
- throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
378
- context: { error, challenge },
379
- logger: this.logger,
380
- });
381
- }
382
- }
383
- async updatePowCaptchaRecord(challenge, result, serverChecked = false, userSubmitted = false, userSignature) {
384
- const tables = this.getTables();
385
- const timestamp = Date.now();
386
- const update = {
387
- result,
388
- serverChecked,
389
- userSubmitted,
390
- userSignature,
391
- lastUpdatedTimestamp: timestamp,
392
- };
393
- try {
394
- const updateResult = await tables.powcaptcha.updateOne({ challenge }, {
395
- $set: update,
396
- });
397
- if (updateResult.matchedCount === 0) {
398
- this.logger.info("No PowCaptcha record found to update", {
399
- challenge,
400
- ...update,
401
- });
402
- throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
403
- context: {
404
- challenge,
405
- ...update,
406
- },
407
- logger: this.logger,
408
- });
409
- }
410
- this.logger.info("PowCaptcha record updated successfully", {
411
- challenge,
412
- ...update,
413
- });
414
- }
415
- catch (error) {
416
- this.logger.error("Failed to update PowCaptcha record", {
417
- error,
418
- challenge,
419
- ...update,
420
- });
421
- throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
422
- context: {
423
- error,
424
- challenge,
425
- ...update,
426
- },
427
- logger: this.logger,
428
- });
429
- }
430
- }
431
- async getProcessedDappUserSolutions() {
432
- const docs = await this.tables?.usersolution
433
- .find({ processed: true })
434
- .lean();
435
- return docs || [];
436
- }
437
- async getProcessedDappUserCommitments() {
438
- const docs = await this.tables?.commitment
439
- .find({ processed: true })
440
- .lean();
441
- return docs || [];
442
- }
443
- async getCheckedDappUserCommitments() {
444
- const docs = await this.tables?.commitment
445
- .find({ [StoredStatusNames.serverChecked]: true })
446
- .lean();
447
- return docs || [];
448
- }
449
- async getUnstoredDappUserCommitments() {
450
- const docs = await this.tables?.commitment
451
- .find({
452
- $or: [
453
- { storedStatus: { $ne: StoredStatusNames.stored } },
454
- { storedStatus: { $exists: false } },
455
- ],
456
- })
457
- .lean();
458
- return docs || [];
459
- }
460
- async markDappUserCommitmentsStored(commitmentIds) {
461
- const updateDoc = {
462
- storedAtTimestamp: Date.now(),
463
- };
464
- await this.tables?.commitment.updateMany({ id: { $in: commitmentIds } }, { $set: updateDoc }, { upsert: false });
465
- }
466
- async markDappUserCommitmentsChecked(commitmentIds) {
467
- const updateDoc = {
468
- [StoredStatusNames.serverChecked]: true,
469
- lastUpdatedTimestamp: Date.now(),
470
- };
471
- await this.tables?.commitment.updateMany({ id: { $in: commitmentIds } }, { $set: updateDoc }, { upsert: false });
472
- }
473
- async getUnstoredDappUserPoWCommitments() {
474
- const docs = await this.tables?.powcaptcha
475
- .find({
476
- $or: [
477
- { storedStatus: { $ne: StoredStatusNames.stored } },
478
- { storedStatus: { $exists: false } },
479
- ],
480
- })
481
- .lean();
482
- return docs || [];
483
- }
484
- async markDappUserPoWCommitmentsStored(challenges) {
485
- const updateDoc = {
486
- storedAtTimestamp: Date.now(),
487
- };
488
- await this.tables?.powcaptcha.updateMany({ challenge: { $in: challenges } }, { $set: updateDoc }, { upsert: false });
489
- }
490
- async markDappUserPoWCommitmentsChecked(challenges) {
491
- const updateDoc = {
492
- [StoredStatusNames.serverChecked]: true,
493
- lastUpdatedTimestamp: Date.now(),
494
- };
495
- await this.tables?.powcaptcha.updateMany({ challenge: { $in: challenges } }, {
496
- $set: updateDoc,
497
- }, { upsert: false });
498
- }
499
- async removeProcessedDappUserSolutions(commitmentIds) {
500
- return this.tables?.usersolution.deleteMany({
501
- processed: true,
502
- commitmentId: { $in: commitmentIds },
503
- });
504
- }
505
- async removeProcessedDappUserCommitments(commitmentIds) {
506
- return this.tables?.commitment.deleteMany({
507
- processed: true,
508
- id: { $in: commitmentIds },
509
- });
510
- }
511
- async storeDappUserPending(userAccount, requestHash, salt, deadlineTimestamp, requestedAtTimestamp, ipAddress) {
512
- if (!isHex(requestHash)) {
513
- throw new ProsopoDBError("DATABASE.INVALID_HASH", {
514
- context: {
515
- failedFuncName: this.storeDappUserPending.name,
516
- requestHash,
517
- },
518
- });
519
- }
520
- const pendingRecord = {
521
- accountId: userAccount,
522
- pending: true,
523
- salt,
524
- requestHash,
525
- deadlineTimestamp,
526
- requestedAtTimestamp,
527
- ipAddress,
528
- };
529
- await this.tables?.pending.updateOne({ requestHash: requestHash }, { $set: pendingRecord }, { upsert: true });
530
- }
531
- async getDappUserPending(requestHash) {
532
- if (!isHex(requestHash)) {
533
- throw new ProsopoEnvError("DATABASE.INVALID_HASH", {
534
- context: { failedFuncName: this.getDappUserPending.name, requestHash },
535
- });
536
- }
537
- const doc = await this.tables?.pending
538
- .findOne({ requestHash: requestHash })
539
- .lean();
540
- if (doc) {
541
- return doc;
542
- }
543
- throw new ProsopoEnvError("DATABASE.PENDING_RECORD_NOT_FOUND", {
544
- context: { failedFuncName: this.getDappUserPending.name, requestHash },
545
- });
546
- }
547
- async updateDappUserPendingStatus(requestHash) {
548
- if (!isHex(requestHash)) {
549
- throw new ProsopoEnvError("DATABASE.INVALID_HASH", {
550
- context: {
551
- failedFuncName: this.updateDappUserPendingStatus.name,
552
- requestHash,
553
- },
554
- });
555
- }
556
- await this.tables?.pending.updateOne({ requestHash: requestHash }, {
557
- $set: {
558
- [CaptchaStatus.pending]: false,
559
- },
560
- }, { upsert: true });
561
- }
562
- async getAllCaptchasByDatasetId(datasetId, state) {
563
- const cursor = this.tables?.captcha
564
- .find({
565
- datasetId,
566
- solved: state === CaptchaStates.Solved,
567
- })
568
- .lean();
569
- const docs = await cursor;
570
- if (docs) {
571
- return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
572
- }
573
- throw new ProsopoEnvError("DATABASE.CAPTCHA_GET_FAILED");
574
- }
575
- async getAllDappUserSolutions(captchaId) {
576
- const cursor = this.tables?.usersolution
577
- ?.find({ captchaId: { $in: captchaId } })
578
- .lean();
579
- const docs = await cursor;
580
- if (docs) {
581
- return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
582
- }
583
- throw new ProsopoEnvError("DATABASE.SOLUTION_GET_FAILED");
584
- }
585
- async getDatasetIdWithSolvedCaptchasOfSizeN(solvedCaptchaCount) {
586
- const cursor = this.tables?.solution.aggregate([
587
- {
588
- $match: {},
589
- },
590
- {
591
- $group: {
592
- _id: "$datasetId",
593
- count: { $sum: 1 },
594
- },
595
- },
596
- {
597
- $match: {
598
- count: { $gte: solvedCaptchaCount },
599
- },
600
- },
601
- {
602
- $sample: { size: 1 },
603
- },
604
- ]);
605
- const docs = await cursor;
606
- if (docs?.length) {
607
- return docs[0]._id;
608
- }
609
- throw new ProsopoDBError("DATABASE.DATASET_WITH_SOLUTIONS_GET_FAILED");
610
- }
611
- async getRandomSolvedCaptchasFromSingleDataset(datasetId, size) {
612
- if (!isHex(datasetId)) {
613
- throw new ProsopoDBError("DATABASE.INVALID_HASH", {
614
- context: {
615
- failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
616
- datasetId,
617
- },
618
- });
619
- }
620
- const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
621
- const cursor = this.tables?.solution.aggregate([
622
- { $match: { datasetId } },
623
- { $sample: { size: sampleSize } },
624
- {
625
- $project: {
626
- captchaId: 1,
627
- captchaContentId: 1,
628
- solution: 1,
629
- },
630
- },
631
- ]);
632
- const docs = await cursor;
633
- if (docs?.length) {
634
- return docs;
635
- }
636
- throw new ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
637
- context: {
638
- failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
639
- datasetId,
640
- size,
641
- },
642
- });
643
- }
644
- async getDappUserSolutionById(commitmentId) {
645
- const cursor = this.tables?.usersolution
646
- ?.findOne({
647
- commitmentId: commitmentId,
648
- }, { projection: { _id: 0 } })
649
- .lean();
650
- const doc = await cursor;
651
- if (doc) {
652
- return doc;
653
- }
654
- throw new ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
655
- context: { failedFuncName: this.getCaptchaById.name, commitmentId },
656
- });
657
- }
658
- async getDappUserCommitmentById(commitmentId) {
659
- const commitmentCursor = this.tables?.commitment
660
- ?.findOne({ id: commitmentId })
661
- .lean();
662
- const doc = await commitmentCursor;
663
- return doc ? doc : undefined;
664
- }
665
- async getDappUserCommitmentByAccount(userAccount, dappAccount) {
666
- const docs = await this.tables?.commitment
667
- ?.find({ userAccount, dappAccount }, { _id: 0 }, { sort: { _id: -1 } })
668
- .lean();
669
- return docs ? docs : [];
670
- }
671
- async approveDappUserCommitment(commitmentId) {
672
- try {
673
- const result = { status: CaptchaStatus.approved };
674
- const updateDoc = {
675
- result,
676
- lastUpdatedTimestamp: Date.now(),
677
- };
678
- await this.tables?.commitment
679
- ?.findOneAndUpdate({ id: commitmentId }, { $set: updateDoc }, { upsert: false })
680
- .lean();
681
- }
682
- catch (err) {
683
- throw new ProsopoDBError("DATABASE.SOLUTION_APPROVE_FAILED", {
684
- context: { error: err, commitmentId },
685
- });
686
- }
687
- }
688
- async disapproveDappUserCommitment(commitmentId, reason) {
689
- try {
690
- const updateDoc = {
691
- result: { status: CaptchaStatus.disapproved, reason },
692
- lastUpdatedTimestamp: Date.now(),
693
- };
694
- await this.tables?.commitment
695
- ?.findOneAndUpdate({ id: commitmentId }, { $set: updateDoc }, { upsert: false })
696
- .lean();
697
- }
698
- catch (err) {
699
- throw new ProsopoDBError("DATABASE.SOLUTION_APPROVE_FAILED", {
700
- context: { error: err, commitmentId },
701
- });
702
- }
703
- }
704
- async flagProcessedDappUserSolutions(captchaIds) {
705
- try {
706
- await this.tables?.usersolution
707
- ?.updateMany({ captchaId: { $in: captchaIds } }, { $set: { processed: true } }, { upsert: false })
708
- .lean();
709
- }
710
- catch (err) {
711
- throw new ProsopoDBError("DATABASE.SOLUTION_FLAG_FAILED", {
712
- context: { error: err, captchaIds },
713
- });
714
- }
715
- }
716
- async flagProcessedDappUserCommitments(commitmentIds) {
717
- try {
718
- const distinctCommitmentIds = [...new Set(commitmentIds)];
719
- await this.tables?.commitment
720
- ?.updateMany({ id: { $in: distinctCommitmentIds } }, { $set: { processed: true } }, { upsert: false })
721
- .lean();
722
- }
723
- catch (err) {
724
- throw new ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
725
- context: { error: err, commitmentIds },
726
- });
727
- }
728
- }
729
- async getScheduledTaskStatus(taskId, status) {
730
- const cursor = await this.tables?.scheduler
731
- ?.findOne({ taskId: taskId, status: status })
732
- .lean();
733
- return cursor ? cursor : undefined;
734
- }
735
- async getLastScheduledTaskStatus(task, status) {
736
- const lookup = { processName: task };
737
- if (status) {
738
- lookup.status = status;
739
- }
740
- const cursor = await this.tables?.scheduler
741
- ?.findOne(lookup)
742
- .sort({ datetime: -1 })
743
- .limit(1)
744
- .lean();
745
- return cursor ? cursor : undefined;
746
- }
747
- async createScheduledTaskStatus(taskName, status) {
748
- const now = new Date().getTime();
749
- const doc = ScheduledTaskSchema.parse({
750
- processName: taskName,
751
- datetime: now,
752
- status,
753
- });
754
- const taskRecord = await this.tables?.scheduler.create(doc);
755
- return taskRecord._id;
756
- }
757
- async updateScheduledTaskStatus(taskId, status, result) {
758
- const update = {
759
- status,
760
- updated: new Date().getTime(),
761
- ...(result && { result }),
762
- };
763
- await this.tables?.scheduler.updateOne({ _id: taskId }, { $set: update }, {
764
- upsert: false,
765
- });
766
- }
767
- async updateClientRecords(clientRecords) {
768
- const ops = clientRecords.map((record) => {
769
- const clientRecord = {
770
- account: record.account,
771
- settings: record.settings,
772
- };
773
- return {
774
- updateOne: {
775
- filter: { account: record.account },
776
- update: {
777
- $set: clientRecord,
778
- },
779
- upsert: true,
780
- },
781
- };
782
- });
783
- await this.tables?.client.bulkWrite(ops);
784
- }
785
- }
786
- //# sourceMappingURL=provider.js.map