@prosopo/provider 3.12.3 → 3.13.0

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 (49) hide show
  1. package/CHANGELOG.md +214 -0
  2. package/dist/api/admin/apiAdminRoutesProvider.js +13 -18
  3. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +40 -0
  4. package/dist/api/blacklistRequestInspector.js +4 -4
  5. package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +338 -0
  6. package/dist/api/captcha/getImageCaptchaChallenge.js +150 -0
  7. package/dist/api/captcha/getPoWCaptchaChallenge.js +156 -0
  8. package/dist/api/captcha/submitImageCaptchaSolution.js +87 -0
  9. package/dist/api/captcha/submitPoWCaptchaSolution.js +77 -0
  10. package/dist/api/captcha.js +18 -606
  11. package/dist/api/verify.js +24 -1
  12. package/dist/cjs/api/admin/apiAdminRoutesProvider.cjs +13 -18
  13. package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +2 -1
  14. package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +3 -2
  15. package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +41 -0
  16. package/dist/cjs/api/blacklistRequestInspector.cjs +3 -3
  17. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +337 -0
  18. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +149 -0
  19. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +155 -0
  20. package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +86 -0
  21. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +76 -0
  22. package/dist/cjs/api/captcha.cjs +17 -605
  23. package/dist/cjs/api/ja4Middleware.cjs +2 -1
  24. package/dist/cjs/api/verify.cjs +24 -1
  25. package/dist/cjs/index.cjs +2 -0
  26. package/dist/cjs/schedulers/setClientEntropy.cjs +36 -0
  27. package/dist/cjs/tasks/captchaManager.cjs +7 -22
  28. package/dist/cjs/tasks/client/clientTasks.cjs +18 -36
  29. package/dist/cjs/tasks/detection/decodePayload.cjs +385 -714
  30. package/dist/cjs/tasks/detection/getBotScore.cjs +15 -2
  31. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +136 -30
  32. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +25 -13
  33. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +8 -8
  34. package/dist/cjs/tasks/tasks.cjs +1 -0
  35. package/dist/cjs/util.cjs +14 -1
  36. package/dist/cjs/utils/hashUserIp.cjs +9 -0
  37. package/dist/index.js +2 -0
  38. package/dist/schedulers/setClientEntropy.js +36 -0
  39. package/dist/tasks/captchaManager.js +5 -21
  40. package/dist/tasks/client/clientTasks.js +19 -37
  41. package/dist/tasks/detection/decodePayload.js +385 -714
  42. package/dist/tasks/detection/getBotScore.js +17 -4
  43. package/dist/tasks/frictionless/frictionlessTasks.js +137 -31
  44. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +25 -13
  45. package/dist/tasks/powCaptcha/powTasks.js +8 -8
  46. package/dist/tasks/tasks.js +1 -0
  47. package/dist/util.js +14 -1
  48. package/dist/utils/hashUserIp.js +9 -0
  49. package/package.json +24 -25
@@ -2,7 +2,7 @@ import { createPrivateKey } from "node:crypto";
2
2
  import { ProsopoApiError } from "@prosopo/common";
3
3
  import { CaptchaDatabase, ClientDatabase } from "@prosopo/database";
4
4
  import { ScheduledTaskNames, ScheduledTaskStatus } from "@prosopo/types";
5
- import { parseUrl } from "@prosopo/util";
5
+ import { majorityAverage, parseUrl } from "@prosopo/util";
6
6
  import { validateSiteKey } from "../../api/validateAddress.js";
7
7
  const isValidPrivateKey = (privateKeyString) => {
8
8
  const privateKey = Buffer.from(privateKeyString, "base64").toString("ascii");
@@ -100,44 +100,11 @@ class ClientTaskManager {
100
100
  async (skip) => await this.providerDB.getUnstoredSessionRecords(BATCH_SIZE, skip),
101
101
  async (batch) => {
102
102
  const filteredBatch = lastTask?.updated ? batch.filter((record) => this.isRecordUpdated(record)) : batch;
103
- const frictionlessTokenRecords = await this.providerDB.getFrictionlessTokenRecordsByTokenIds(
104
- filteredBatch.map((record) => record.tokenId)
105
- );
106
- this.logger.info(() => ({
107
- msg: `Frictionless token records: ${frictionlessTokenRecords.length}`
108
- }));
109
- const filteredBatchWithScores = filteredBatch.map((record) => {
110
- const tokenRecord = frictionlessTokenRecords.find(
111
- (tokenRecord2) => tokenRecord2._id?.toString() === record.tokenId.toString()
112
- );
113
- if (!tokenRecord) {
114
- this.logger.error(() => ({
115
- msg: "No token record found",
116
- data: { tokenId: record.tokenId }
117
- }));
118
- return {
119
- ...record,
120
- score: 0,
121
- scoreComponents: {
122
- baseScore: 0
123
- },
124
- threshold: 0
125
- };
126
- }
127
- const { _id, token, ...tokenRecordWithoutId } = tokenRecord;
128
- return {
129
- ...record,
130
- ...tokenRecordWithoutId
131
- };
132
- });
133
103
  if (filteredBatch.length > 0) {
134
- await captchaDB.saveCaptchas(filteredBatchWithScores, [], []);
104
+ await captchaDB.saveCaptchas(filteredBatch, [], []);
135
105
  await this.providerDB.markSessionRecordsStored(
136
106
  filteredBatch.map((record) => record.sessionId)
137
107
  );
138
- await this.providerDB.markFrictionlessTokenRecordsStored(
139
- filteredBatch.map((record) => record.tokenId).filter((id) => !!id)
140
- );
141
108
  }
142
109
  processedSessionRecords += filteredBatch.length;
143
110
  }
@@ -194,7 +161,7 @@ class ClientTaskManager {
194
161
  this.logger
195
162
  );
196
163
  const tenMinuteWindow = 10 * 60 * 1e3;
197
- const updatedAtTimestamp = lastTask?.updated ? lastTask.updated - tenMinuteWindow || 0 : 0;
164
+ const updatedAtTimestamp = lastTask?.updated ? lastTask.updated.getTime() - tenMinuteWindow || 0 : 0;
198
165
  this.logger.info(() => ({
199
166
  msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}`
200
167
  }));
@@ -227,6 +194,21 @@ class ClientTaskManager {
227
194
  );
228
195
  }
229
196
  }
197
+ /**
198
+ * @description Calculate client entropy scores and update in db
199
+ * @returns Promise<void>
200
+ */
201
+ async calculateClientEntropy() {
202
+ const clients = await this.providerDB.getAllClientRecords();
203
+ for (const client of clients) {
204
+ const sampleEntropies = await this.providerDB.sampleEntropy(
205
+ 100,
206
+ client.account
207
+ );
208
+ const avgEntropy = majorityAverage(sampleEntropies);
209
+ await this.providerDB.setClientEntropy(client.account, avgEntropy);
210
+ }
211
+ }
230
212
  async registerSiteKey(siteKey, tier, settings) {
231
213
  validateSiteKey(siteKey);
232
214
  await this.providerDB.updateClientRecords([
@@ -293,7 +275,7 @@ class ClientTaskManager {
293
275
  }
294
276
  isRecordUpdated(record) {
295
277
  const { lastUpdatedTimestamp, storedAtTimestamp } = record;
296
- return !lastUpdatedTimestamp || !storedAtTimestamp || lastUpdatedTimestamp > storedAtTimestamp;
278
+ return !lastUpdatedTimestamp || !storedAtTimestamp || lastUpdatedTimestamp.getTime() > storedAtTimestamp.getTime();
297
279
  }
298
280
  async processBatchesWithCursor(fetchBatch, processBatch) {
299
281
  let skip = 0;