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