@prosopo/database 4.6.0 → 4.6.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 (43) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +6 -6
  2. package/.turbo/turbo-build$colon$esm.log +6 -6
  3. package/.turbo/turbo-build$colon$tsc.log +15 -15
  4. package/CHANGELOG.md +34 -0
  5. package/dist/cjs/databases/captcha.cjs +9 -8
  6. package/dist/cjs/databases/centralDbStreamer.cjs +4 -4
  7. package/dist/cjs/databases/index.cjs +1 -0
  8. package/dist/cjs/databases/provider.cjs +36 -7
  9. package/dist/cjs/index.cjs +1 -0
  10. package/dist/esm/databases/captcha.js +9 -9
  11. package/dist/esm/databases/centralDbStreamer.js +5 -5
  12. package/dist/esm/databases/index.js +2 -2
  13. package/dist/esm/databases/provider.js +36 -7
  14. package/dist/esm/index.js +2 -2
  15. package/dist/tsc/databases/captcha.d.ts +4 -0
  16. package/dist/tsc/databases/captcha.d.ts.map +1 -1
  17. package/dist/tsc/databases/captcha.js +8 -8
  18. package/dist/tsc/databases/captcha.js.map +1 -1
  19. package/dist/tsc/databases/centralDbStreamer.js +5 -5
  20. package/dist/tsc/databases/centralDbStreamer.js.map +1 -1
  21. package/dist/tsc/databases/provider.d.ts +2 -8
  22. package/dist/tsc/databases/provider.d.ts.map +1 -1
  23. package/dist/tsc/databases/provider.js +34 -9
  24. package/dist/tsc/databases/provider.js.map +1 -1
  25. package/dist/tsc/tests/integration/insertMissingSpamEmailDomains.integration.test.d.ts +2 -0
  26. package/dist/tsc/tests/integration/insertMissingSpamEmailDomains.integration.test.d.ts.map +1 -0
  27. package/dist/tsc/tests/integration/insertMissingSpamEmailDomains.integration.test.js +91 -0
  28. package/dist/tsc/tests/integration/insertMissingSpamEmailDomains.integration.test.js.map +1 -0
  29. package/dist/tsc/tests/integration/saveCaptchasStoredAt.integration.test.d.ts +2 -0
  30. package/dist/tsc/tests/integration/saveCaptchasStoredAt.integration.test.d.ts.map +1 -0
  31. package/dist/tsc/tests/integration/saveCaptchasStoredAt.integration.test.js +84 -0
  32. package/dist/tsc/tests/integration/saveCaptchasStoredAt.integration.test.js.map +1 -0
  33. package/dist/tsc/tests/unit/databases/centralDbStreamer.unit.test.js +11 -0
  34. package/dist/tsc/tests/unit/databases/centralDbStreamer.unit.test.js.map +1 -1
  35. package/dist/types/databases/captcha.d.ts +4 -0
  36. package/dist/types/databases/captcha.d.ts.map +1 -1
  37. package/dist/types/databases/provider.d.ts +2 -8
  38. package/dist/types/databases/provider.d.ts.map +1 -1
  39. package/dist/types/tests/integration/insertMissingSpamEmailDomains.integration.test.d.ts +2 -0
  40. package/dist/types/tests/integration/insertMissingSpamEmailDomains.integration.test.d.ts.map +1 -0
  41. package/dist/types/tests/integration/saveCaptchasStoredAt.integration.test.d.ts +2 -0
  42. package/dist/types/tests/integration/saveCaptchasStoredAt.integration.test.d.ts.map +1 -0
  43. package/package.json +7 -7
@@ -40,16 +40,16 @@ computing gzip size...
40
40
  dist/cjs/base/index.cjs 0.43 kB │ gzip: 0.16 kB
41
41
  dist/cjs/base/mongoMemory.cjs 0.66 kB │ gzip: 0.32 kB
42
42
  dist/cjs/_virtual/_rolldown/runtime.cjs 1.00 kB │ gzip: 0.50 kB
43
- dist/cjs/databases/index.cjs 1.14 kB │ gzip: 0.32 kB
43
+ dist/cjs/databases/index.cjs 1.20 kB │ gzip: 0.34 kB
44
44
  dist/cjs/databases/clientRecordCache.cjs 1.45 kB │ gzip: 0.69 kB
45
- dist/cjs/index.cjs 1.87 kB │ gzip: 0.54 kB
45
+ dist/cjs/index.cjs 1.93 kB │ gzip: 0.55 kB
46
46
  dist/cjs/databases/client.cjs 1.96 kB │ gzip: 0.82 kB
47
47
  dist/cjs/mongooseOptions.cjs 3.74 kB │ gzip: 1.56 kB
48
48
  dist/cjs/base/mongo.cjs 4.47 kB │ gzip: 1.49 kB
49
49
  dist/cjs/base/reconcileIndexes.cjs 5.97 kB │ gzip: 1.98 kB
50
- dist/cjs/databases/centralDbStreamer.cjs 6.40 kB │ gzip: 1.52 kB
51
- dist/cjs/databases/captcha.cjs 8.39 kB │ gzip: 2.40 kB
50
+ dist/cjs/databases/centralDbStreamer.cjs 6.48 kB │ gzip: 1.52 kB
51
+ dist/cjs/databases/captcha.cjs 8.46 kB │ gzip: 2.44 kB
52
52
  dist/cjs/redisCache.cjs 14.30 kB │ gzip: 4.45 kB
53
- dist/cjs/databases/provider.cjs 71.07 kB │ gzip: 13.59 kB
53
+ dist/cjs/databases/provider.cjs 72.31 kB │ gzip: 13.98 kB
54
54
 
55
- ✓ built in 73ms
55
+ ✓ built in 141ms
@@ -40,16 +40,16 @@ computing gzip size...
40
40
  dist/esm/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
41
41
  dist/esm/base/index.js 0.25 kB │ gzip: 0.12 kB
42
42
  dist/esm/base/mongoMemory.js 0.60 kB │ gzip: 0.30 kB
43
- dist/esm/databases/index.js 0.77 kB │ gzip: 0.27 kB
44
- dist/esm/index.js 1.19 kB │ gzip: 0.42 kB
43
+ dist/esm/databases/index.js 0.81 kB │ gzip: 0.28 kB
44
+ dist/esm/index.js 1.22 kB │ gzip: 0.43 kB
45
45
  dist/esm/databases/clientRecordCache.js 1.40 kB │ gzip: 0.68 kB
46
46
  dist/esm/databases/client.js 1.85 kB │ gzip: 0.80 kB
47
47
  dist/esm/mongooseOptions.js 3.58 kB │ gzip: 1.53 kB
48
48
  dist/esm/base/mongo.js 4.22 kB │ gzip: 1.40 kB
49
49
  dist/esm/base/reconcileIndexes.js 5.93 kB │ gzip: 1.97 kB
50
- dist/esm/databases/centralDbStreamer.js 6.33 kB │ gzip: 1.51 kB
51
- dist/esm/databases/captcha.js 8.29 kB │ gzip: 2.40 kB
50
+ dist/esm/databases/centralDbStreamer.js 6.37 kB │ gzip: 1.51 kB
51
+ dist/esm/databases/captcha.js 8.33 kB │ gzip: 2.43 kB
52
52
  dist/esm/redisCache.js 14.25 kB │ gzip: 4.43 kB
53
- dist/esm/databases/provider.js 69.29 kB │ gzip: 13.59 kB
53
+ dist/esm/databases/provider.js 70.50 kB │ gzip: 13.97 kB
54
54
 
55
- ✓ built in 112ms
55
+ ✓ built in 110ms
@@ -1,5 +1,5 @@
1
1
  $ tsc --build --verbose
2
- 10:56:34 AM - Projects in this build:
2
+ 11:51:55 AM - Projects in this build:
3
3
  * ../../dev/config/tsconfig.json
4
4
  * ../util/tsconfig.json
5
5
  * ../locale/tsconfig.json
@@ -14,31 +14,31 @@ $ tsc --build --verbose
14
14
  * ../types-database/tsconfig.json
15
15
  * tsconfig.json
16
16
 
17
- 10:56:34 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/modifyExportsFiles.test.ts' is older than output '../../dev/config/dist/tsc/tsconfig.tsbuildinfo'
17
+ 11:51:56 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/dist/tsc/tsconfig.tsbuildinfo'
18
18
 
19
- 10:56:34 AM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/dist/tsc/tsconfig.tsbuildinfo'
19
+ 11:51:56 AM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/dist/tsc/tsconfig.tsbuildinfo'
20
20
 
21
- 10:56:34 AM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/dist/tsc/tsconfig.tsbuildinfo'
21
+ 11:51:56 AM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/process.ts' is older than output '../locale/dist/tsc/tsconfig.tsbuildinfo'
22
22
 
23
- 10:56:34 AM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/dist/tsc/tsconfig.tsbuildinfo'
23
+ 11:51:56 AM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/dist/tsc/tsconfig.tsbuildinfo'
24
24
 
25
- 10:56:34 AM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/dist/tsc/tsconfig.tsbuildinfo'
25
+ 11:51:56 AM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/dist/tsc/tsconfig.tsbuildinfo'
26
26
 
27
- 10:56:34 AM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/tests/errorSites.unit.test.ts' is older than output '../common/dist/tsc/tsconfig.tsbuildinfo'
27
+ 11:51:56 AM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/utils/batches.ts' is older than output '../common/dist/tsc/tsconfig.tsbuildinfo'
28
28
 
29
- 10:56:34 AM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/dist/tsc/tsconfig.tsbuildinfo'
29
+ 11:51:56 AM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/dist/tsc/tsconfig.tsbuildinfo'
30
30
 
31
- 10:56:34 AM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/dist/tsc/tsconfig.tsbuildinfo'
31
+ 11:51:56 AM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/dist/tsc/tsconfig.tsbuildinfo'
32
32
 
33
- 10:56:34 AM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/dist/tsc/tsconfig.tsbuildinfo'
33
+ 11:51:56 AM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/dist/tsc/tsconfig.tsbuildinfo'
34
34
 
35
- 10:56:34 AM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/dist/tsc/tsconfig.tsbuildinfo'
35
+ 11:51:56 AM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/dist/tsc/tsconfig.tsbuildinfo'
36
36
 
37
- 10:56:34 AM - Project '../user-access-policy/tsconfig.json' is up to date because newest input '../user-access-policy/src/transformRule.ts' is older than output '../user-access-policy/dist/tsc/tsconfig.tsbuildinfo'
37
+ 11:51:56 AM - Project '../user-access-policy/tsconfig.json' is up to date because newest input '../user-access-policy/src/ruleRecord.ts' is older than output '../user-access-policy/dist/tsc/tsconfig.tsbuildinfo'
38
38
 
39
- 10:56:34 AM - Project '../types-database/tsconfig.json' is up to date because newest input '../types-database/src/types.test-d.ts' is older than output '../types-database/dist/tsc/tsconfig.tsbuildinfo'
39
+ 11:51:56 AM - Project '../types-database/tsconfig.json' is up to date because newest input '../types-database/src/types.test-d.ts' is older than output '../types-database/dist/tsc/tsconfig.tsbuildinfo'
40
40
 
41
- 10:56:34 AM - Project 'tsconfig.json' is out of date because output file 'dist/tsc/tsconfig.tsbuildinfo' does not exist
41
+ 11:51:56 AM - Project 'tsconfig.json' is out of date because output file 'dist/tsc/tsconfig.tsbuildinfo' does not exist
42
42
 
43
- 10:56:34 AM - Building project '/home/runner/work/captcha/captcha/packages/database/tsconfig.json'...
43
+ 11:51:56 AM - Building project '/home/runner/work/captcha/captcha/packages/database/tsconfig.json'...
44
44
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @prosopo/database
2
2
 
3
+ ## 4.6.2
4
+ ### Patch Changes
5
+
6
+ - a85559d: Records copied to the central captcha store no longer carry the provider's `storedAtTimestamp`. The central store's `storedAtTimestamp` TTL index is now one year; provider stores keep four weeks.
7
+ - Updated dependencies [a85559d]
8
+ - Updated dependencies [d9520ea]
9
+ - Updated dependencies [1ba238e]
10
+ - @prosopo/types-database@5.18.0
11
+ - @prosopo/types@5.26.0
12
+ - @prosopo/util@3.6.0
13
+ - @prosopo/user-access-policy@3.15.18
14
+ - @prosopo/common@3.3.2
15
+ - @prosopo/logger@2.1.9
16
+ - @prosopo/redis-client@1.0.46
17
+
18
+ ## 4.6.1
19
+ ### Patch Changes
20
+
21
+ - 007f43c: A puzzle served after a wrong answer is now judged on the device the failed solve showed, and an escalation's solve readings are no longer dropped.
22
+
23
+ - After a wrong puzzle answer, the widget names the failed challenge in a new `retryOf` field on the next `/frictionless` request. `BotDetectionFunction` and `ProviderApi.getFrictionlessCaptcha` take it as a new trailing argument.
24
+ - The provider carries the failed solve's device readings onto the new session only when its own record of that puzzle shows the same client: same site, user account and exact IP address, identical user agent and TLS fingerprint, and a solve that was submitted and failed. The readings come from that solve's own behavioural payload, and each failed puzzle can be followed once (`claimPuzzleCaptchaRetry`). Anything else is ignored.
25
+ - `createSession` now persists `solveDevice`. It was missing from the session's field list, so a PoW escalation's solve readings never reached the challenge they were meant to size.
26
+ - ec54f21: The scheduled spam email domain sync now only writes domains that are not already stored. It used to upsert the whole list (about 225k domains) on every run, which rewrote every row and held Mongo write locks for around 8 seconds per batch on every provider at the same time, slowing requests on the hour. It now reads the stored domains with an index-only scan and upserts just the new ones.
27
+
28
+ `bulkUpdateSpamEmailDomains` on the provider database is replaced by `insertMissingSpamEmailDomains(domains)`, which returns how many domains were added. The task records that count as `domainsAdded` alongside `domainsProcessed`. Domains that drop off the source lists are still kept, as before.
29
+ - Updated dependencies [b80b627]
30
+ - Updated dependencies [007f43c]
31
+ - Updated dependencies [ec54f21]
32
+ - @prosopo/types@5.25.0
33
+ - @prosopo/types-database@5.17.0
34
+ - @prosopo/common@3.3.2
35
+ - @prosopo/user-access-policy@3.15.17
36
+
3
37
  ## 4.6.0
4
38
  ### Minor Changes
5
39
 
@@ -39,6 +39,10 @@ var CAPTCHA_TABLES = [
39
39
  schema: _prosopo_types_database.StoredIconOrderCaptchaRecordSchema
40
40
  }
41
41
  ];
42
+ var toCentralRecord = (record) => {
43
+ const { _id, storedAtTimestamp, ...centralRecord } = record;
44
+ return centralRecord;
45
+ };
42
46
  var CaptchaDatabase = class CaptchaDatabase extends require_mongo.MongoDatabase {
43
47
  constructor(url, dbname, authSource, logger, timeouts) {
44
48
  super(url, dbname, authSource, logger, timeouts);
@@ -126,8 +130,7 @@ var CaptchaDatabase = class CaptchaDatabase extends require_mongo.MongoDatabase
126
130
  await this.connect();
127
131
  if (sessionEvents.length) {
128
132
  const result = await this.tables.session.bulkWrite(sessionEvents.map((document) => {
129
- const { _id, ...safeDoc } = document;
130
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
133
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(document));
131
134
  return { updateOne: {
132
135
  filter: { sessionId: normalised.sessionId },
133
136
  update: { $set: normalised },
@@ -146,8 +149,7 @@ var CaptchaDatabase = class CaptchaDatabase extends require_mongo.MongoDatabase
146
149
  }
147
150
  if (imageCaptchaEvents.length) {
148
151
  const result = await this.tables.commitment.bulkWrite(imageCaptchaEvents.map((doc) => {
149
- const { _id, ...safeDoc } = doc;
150
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
152
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
151
153
  return { updateOne: {
152
154
  filter: { id: normalised.id },
153
155
  update: { $set: normalised },
@@ -166,8 +168,7 @@ var CaptchaDatabase = class CaptchaDatabase extends require_mongo.MongoDatabase
166
168
  }
167
169
  if (powCaptchaEvents.length) {
168
170
  const result = await this.tables.powcaptcha.bulkWrite(powCaptchaEvents.map((doc) => {
169
- const { _id, ...safeDoc } = doc;
170
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
171
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
171
172
  return { updateOne: {
172
173
  filter: { challenge: normalised.challenge },
173
174
  update: { $set: normalised },
@@ -192,8 +193,7 @@ var CaptchaDatabase = class CaptchaDatabase extends require_mongo.MongoDatabase
192
193
  async upsertChallengeRecords(table, records, msg) {
193
194
  if (!records.length) return;
194
195
  const result = await this.tables[table].bulkWrite(records.map((doc) => {
195
- const { _id, ...safeDoc } = doc;
196
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
196
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
197
197
  return { updateOne: {
198
198
  filter: { challenge: normalised.challenge },
199
199
  update: { $set: normalised },
@@ -238,3 +238,4 @@ var CaptchaDatabase = class CaptchaDatabase extends require_mongo.MongoDatabase
238
238
  };
239
239
  //#endregion
240
240
  exports.CaptchaDatabase = CaptchaDatabase;
241
+ exports.toCentralRecord = toCentralRecord;
@@ -57,7 +57,7 @@ var CentralDbStreamer = class CentralDbStreamer {
57
57
  streamPowRecord(record, markStored) {
58
58
  const timestamp = this.getRecordTimestamp(record);
59
59
  this.ensureConnected().then(() => {
60
- const { _id, ...safeDoc } = record;
60
+ const safeDoc = require_captcha.toCentralRecord(record);
61
61
  return this.db.tables.powcaptcha.updateOne({ challenge: safeDoc.challenge }, { $set: safeDoc }, { upsert: true });
62
62
  }).then(() => markStored?.(timestamp)).catch((err) => {
63
63
  this.logger.error(() => ({
@@ -86,7 +86,7 @@ var CentralDbStreamer = class CentralDbStreamer {
86
86
  streamImageRecord(record, markStored) {
87
87
  const timestamp = this.getRecordTimestamp(record);
88
88
  this.ensureConnected().then(() => {
89
- const { _id, ...safeDoc } = record;
89
+ const safeDoc = require_captcha.toCentralRecord(record);
90
90
  return this.db.tables.commitment.updateOne({ id: safeDoc.id }, { $set: safeDoc }, { upsert: true });
91
91
  }).then(() => markStored?.(timestamp)).catch((err) => {
92
92
  this.logger.error(() => ({
@@ -136,7 +136,7 @@ var CentralDbStreamer = class CentralDbStreamer {
136
136
  streamChallengeRecord(table, label, record, markStored) {
137
137
  const timestamp = this.getRecordTimestamp(record);
138
138
  this.ensureConnected().then(() => {
139
- const { _id, ...safeDoc } = record;
139
+ const safeDoc = require_captcha.toCentralRecord(record);
140
140
  return this.db.tables[table].updateOne({ challenge: safeDoc.challenge }, { $set: safeDoc }, { upsert: true });
141
141
  }).then(() => markStored?.(timestamp)).catch((err) => {
142
142
  this.logger.error(() => ({
@@ -162,7 +162,7 @@ var CentralDbStreamer = class CentralDbStreamer {
162
162
  streamSessionRecord(record, markStored) {
163
163
  const timestamp = this.getRecordTimestamp(record);
164
164
  this.ensureConnected().then(() => {
165
- const { _id, ...safeDoc } = record;
165
+ const safeDoc = require_captcha.toCentralRecord(record);
166
166
  return this.db.tables.session.updateOne({ sessionId: safeDoc.sessionId }, { $set: safeDoc }, { upsert: true });
167
167
  }).then(() => markStored?.(timestamp)).catch((err) => {
168
168
  this.logger.error(() => ({
@@ -19,3 +19,4 @@ exports.CentralDbStreamer = require_centralDbStreamer.CentralDbStreamer;
19
19
  exports.ClientDatabase = require_client.ClientDatabase;
20
20
  exports.Databases = Databases;
21
21
  exports.ProviderDatabase = require_provider.ProviderDatabase;
22
+ exports.toCentralRecord = require_captcha.toCentralRecord;
@@ -1052,6 +1052,19 @@ var ProviderDatabase = class ProviderDatabase extends require_mongo.MongoDatabas
1052
1052
  async updatePuzzleCaptchaRecord(challenge, updates) {
1053
1053
  await this.updateInteractiveCaptchaRecord(this.interactiveCollection(_prosopo_types.CaptchaType.puzzle), challenge, updates);
1054
1054
  }
1055
+ /**
1056
+ * Take a failed puzzle for one retry. Succeeds once per puzzle, and only
1057
+ * for a puzzle that was submitted and disapproved.
1058
+ * @returns true when this call took it
1059
+ */
1060
+ async claimPuzzleCaptchaRetry(challenge) {
1061
+ return (await this.getTables()[this.interactiveCollection(_prosopo_types.CaptchaType.puzzle).table].updateOne({
1062
+ challenge,
1063
+ userSubmitted: true,
1064
+ "result.status": _prosopo_types.CaptchaStatus.disapproved,
1065
+ retried: { $ne: true }
1066
+ }, { $set: { retried: true } })).modifiedCount === 1;
1067
+ }
1055
1068
  async updateIconOrderCaptchaRecord(challenge, updates) {
1056
1069
  await this.updateInteractiveCaptchaRecord(this.interactiveCollection(_prosopo_types.CaptchaType.iconOrder), challenge, updates);
1057
1070
  }
@@ -2085,19 +2098,35 @@ var ProviderDatabase = class ProviderDatabase extends require_mongo.MongoDatabas
2085
2098
  const query = suffixCandidates.length > 0 ? { domain: { $in: suffixCandidates } } : { domain };
2086
2099
  return await this.tables.spamEmailDomain.findOne(query).exec();
2087
2100
  }
2088
- async bulkUpdateSpamEmailDomains(domains, upsert) {
2101
+ /**
2102
+ * Store any of `domains` not already in the collection and return how many
2103
+ * were added. The source lists hold ~225k domains and barely change between
2104
+ * runs, so upserting all of them rewrote every row and held write locks for
2105
+ * ~8s per batch on each provider at the same moment. Reading the existing
2106
+ * set first is an index-only scan, and only the difference is written.
2107
+ */
2108
+ async insertMissingSpamEmailDomains(domains) {
2089
2109
  if (!this.tables?.spamEmailDomain) throw new _prosopo_common.ProsopoError({
2090
2110
  code: "DB_QUERY_FAILED",
2091
2111
  errorSite: "DBSE-51",
2092
2112
  message: "Failed to import database engine",
2093
- context: { failedFuncName: this.bulkUpdateSpamEmailDomains.name }
2113
+ context: { failedFuncName: this.insertMissingSpamEmailDomains.name }
2094
2114
  });
2095
- const bulkOps = domains.map((op) => ({ updateOne: {
2096
- filter: op.filter,
2097
- update: { $set: op.update },
2098
- upsert
2115
+ const missing = new Set(domains);
2116
+ if (missing.size === 0) return 0;
2117
+ const existing = this.tables.spamEmailDomain.find({}, {
2118
+ domain: 1,
2119
+ _id: 0
2120
+ }).hint({ domain: 1 }).lean().cursor();
2121
+ for await (const record of existing) missing.delete(record.domain);
2122
+ if (missing.size === 0) return 0;
2123
+ const bulkOps = Array.from(missing, (domain) => ({ updateOne: {
2124
+ filter: { domain },
2125
+ update: { $set: { domain } },
2126
+ upsert: true
2099
2127
  } }));
2100
- if (bulkOps.length > 0) await this.tables.spamEmailDomain.bulkWrite(bulkOps);
2128
+ await this.tables.spamEmailDomain.bulkWrite(bulkOps, { ordered: false });
2129
+ return missing.size;
2101
2130
  }
2102
2131
  };
2103
2132
  //#endregion
@@ -28,3 +28,4 @@ exports.defaultIndexName = require_reconcileIndexes.defaultIndexName;
28
28
  exports.getMongoCompressors = require_mongooseOptions.getMongoCompressors;
29
29
  exports.getMongoConnectionOptions = require_mongooseOptions.getMongoConnectionOptions;
30
30
  exports.reconcileIndexes = require_reconcileIndexes.reconcileIndexes;
31
+ exports.toCentralRecord = require_captcha.toCentralRecord;
@@ -39,6 +39,10 @@ var CAPTCHA_TABLES = [
39
39
  schema: StoredIconOrderCaptchaRecordSchema
40
40
  }
41
41
  ];
42
+ var toCentralRecord = (record) => {
43
+ const { _id, storedAtTimestamp, ...centralRecord } = record;
44
+ return centralRecord;
45
+ };
42
46
  var CaptchaDatabase = class CaptchaDatabase extends MongoDatabase {
43
47
  constructor(url, dbname, authSource, logger, timeouts) {
44
48
  super(url, dbname, authSource, logger, timeouts);
@@ -126,8 +130,7 @@ var CaptchaDatabase = class CaptchaDatabase extends MongoDatabase {
126
130
  await this.connect();
127
131
  if (sessionEvents.length) {
128
132
  const result = await this.tables.session.bulkWrite(sessionEvents.map((document) => {
129
- const { _id, ...safeDoc } = document;
130
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
133
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(document));
131
134
  return { updateOne: {
132
135
  filter: { sessionId: normalised.sessionId },
133
136
  update: { $set: normalised },
@@ -146,8 +149,7 @@ var CaptchaDatabase = class CaptchaDatabase extends MongoDatabase {
146
149
  }
147
150
  if (imageCaptchaEvents.length) {
148
151
  const result = await this.tables.commitment.bulkWrite(imageCaptchaEvents.map((doc) => {
149
- const { _id, ...safeDoc } = doc;
150
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
152
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
151
153
  return { updateOne: {
152
154
  filter: { id: normalised.id },
153
155
  update: { $set: normalised },
@@ -166,8 +168,7 @@ var CaptchaDatabase = class CaptchaDatabase extends MongoDatabase {
166
168
  }
167
169
  if (powCaptchaEvents.length) {
168
170
  const result = await this.tables.powcaptcha.bulkWrite(powCaptchaEvents.map((doc) => {
169
- const { _id, ...safeDoc } = doc;
170
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
171
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
171
172
  return { updateOne: {
172
173
  filter: { challenge: normalised.challenge },
173
174
  update: { $set: normalised },
@@ -192,8 +193,7 @@ var CaptchaDatabase = class CaptchaDatabase extends MongoDatabase {
192
193
  async upsertChallengeRecords(table, records, msg) {
193
194
  if (!records.length) return;
194
195
  const result = await this.tables[table].bulkWrite(records.map((doc) => {
195
- const { _id, ...safeDoc } = doc;
196
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
196
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
197
197
  return { updateOne: {
198
198
  filter: { challenge: normalised.challenge },
199
199
  update: { $set: normalised },
@@ -237,4 +237,4 @@ var CaptchaDatabase = class CaptchaDatabase extends MongoDatabase {
237
237
  }
238
238
  };
239
239
  //#endregion
240
- export { CaptchaDatabase };
240
+ export { CaptchaDatabase, toCentralRecord };
@@ -1,4 +1,4 @@
1
- import { CaptchaDatabase } from "./captcha.js";
1
+ import { CaptchaDatabase, toCentralRecord } from "./captcha.js";
2
2
  import { getLogger } from "@prosopo/logger";
3
3
  //#region src/databases/centralDbStreamer.ts
4
4
  /**
@@ -57,7 +57,7 @@ var CentralDbStreamer = class CentralDbStreamer {
57
57
  streamPowRecord(record, markStored) {
58
58
  const timestamp = this.getRecordTimestamp(record);
59
59
  this.ensureConnected().then(() => {
60
- const { _id, ...safeDoc } = record;
60
+ const safeDoc = toCentralRecord(record);
61
61
  return this.db.tables.powcaptcha.updateOne({ challenge: safeDoc.challenge }, { $set: safeDoc }, { upsert: true });
62
62
  }).then(() => markStored?.(timestamp)).catch((err) => {
63
63
  this.logger.error(() => ({
@@ -86,7 +86,7 @@ var CentralDbStreamer = class CentralDbStreamer {
86
86
  streamImageRecord(record, markStored) {
87
87
  const timestamp = this.getRecordTimestamp(record);
88
88
  this.ensureConnected().then(() => {
89
- const { _id, ...safeDoc } = record;
89
+ const safeDoc = toCentralRecord(record);
90
90
  return this.db.tables.commitment.updateOne({ id: safeDoc.id }, { $set: safeDoc }, { upsert: true });
91
91
  }).then(() => markStored?.(timestamp)).catch((err) => {
92
92
  this.logger.error(() => ({
@@ -136,7 +136,7 @@ var CentralDbStreamer = class CentralDbStreamer {
136
136
  streamChallengeRecord(table, label, record, markStored) {
137
137
  const timestamp = this.getRecordTimestamp(record);
138
138
  this.ensureConnected().then(() => {
139
- const { _id, ...safeDoc } = record;
139
+ const safeDoc = toCentralRecord(record);
140
140
  return this.db.tables[table].updateOne({ challenge: safeDoc.challenge }, { $set: safeDoc }, { upsert: true });
141
141
  }).then(() => markStored?.(timestamp)).catch((err) => {
142
142
  this.logger.error(() => ({
@@ -162,7 +162,7 @@ var CentralDbStreamer = class CentralDbStreamer {
162
162
  streamSessionRecord(record, markStored) {
163
163
  const timestamp = this.getRecordTimestamp(record);
164
164
  this.ensureConnected().then(() => {
165
- const { _id, ...safeDoc } = record;
165
+ const safeDoc = toCentralRecord(record);
166
166
  return this.db.tables.session.updateOne({ sessionId: safeDoc.sessionId }, { $set: safeDoc }, { upsert: true });
167
167
  }).then(() => markStored?.(timestamp)).catch((err) => {
168
168
  this.logger.error(() => ({
@@ -1,6 +1,6 @@
1
1
  import { MongoDatabase } from "../base/mongo.js";
2
2
  import { MongoMemoryDatabase } from "../base/mongoMemory.js";
3
- import { CaptchaDatabase } from "./captcha.js";
3
+ import { CaptchaDatabase, toCentralRecord } from "./captcha.js";
4
4
  import { ClientDatabase } from "./client.js";
5
5
  import { ProviderDatabase } from "./provider.js";
6
6
  import { CentralDbStreamer } from "./centralDbStreamer.js";
@@ -14,4 +14,4 @@ var Databases = {
14
14
  [DatabaseTypes.Values.mongoMemory]: MongoMemoryDatabase
15
15
  };
16
16
  //#endregion
17
- export { CaptchaDatabase, CentralDbStreamer, ClientDatabase, Databases, ProviderDatabase };
17
+ export { CaptchaDatabase, CentralDbStreamer, ClientDatabase, Databases, ProviderDatabase, toCentralRecord };
@@ -1052,6 +1052,19 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
1052
1052
  async updatePuzzleCaptchaRecord(challenge, updates) {
1053
1053
  await this.updateInteractiveCaptchaRecord(this.interactiveCollection(CaptchaType.puzzle), challenge, updates);
1054
1054
  }
1055
+ /**
1056
+ * Take a failed puzzle for one retry. Succeeds once per puzzle, and only
1057
+ * for a puzzle that was submitted and disapproved.
1058
+ * @returns true when this call took it
1059
+ */
1060
+ async claimPuzzleCaptchaRetry(challenge) {
1061
+ return (await this.getTables()[this.interactiveCollection(CaptchaType.puzzle).table].updateOne({
1062
+ challenge,
1063
+ userSubmitted: true,
1064
+ "result.status": CaptchaStatus.disapproved,
1065
+ retried: { $ne: true }
1066
+ }, { $set: { retried: true } })).modifiedCount === 1;
1067
+ }
1055
1068
  async updateIconOrderCaptchaRecord(challenge, updates) {
1056
1069
  await this.updateInteractiveCaptchaRecord(this.interactiveCollection(CaptchaType.iconOrder), challenge, updates);
1057
1070
  }
@@ -2085,19 +2098,35 @@ var ProviderDatabase = class ProviderDatabase extends MongoDatabase {
2085
2098
  const query = suffixCandidates.length > 0 ? { domain: { $in: suffixCandidates } } : { domain };
2086
2099
  return await this.tables.spamEmailDomain.findOne(query).exec();
2087
2100
  }
2088
- async bulkUpdateSpamEmailDomains(domains, upsert) {
2101
+ /**
2102
+ * Store any of `domains` not already in the collection and return how many
2103
+ * were added. The source lists hold ~225k domains and barely change between
2104
+ * runs, so upserting all of them rewrote every row and held write locks for
2105
+ * ~8s per batch on each provider at the same moment. Reading the existing
2106
+ * set first is an index-only scan, and only the difference is written.
2107
+ */
2108
+ async insertMissingSpamEmailDomains(domains) {
2089
2109
  if (!this.tables?.spamEmailDomain) throw new ProsopoError({
2090
2110
  code: "DB_QUERY_FAILED",
2091
2111
  errorSite: "DBSE-51",
2092
2112
  message: "Failed to import database engine",
2093
- context: { failedFuncName: this.bulkUpdateSpamEmailDomains.name }
2113
+ context: { failedFuncName: this.insertMissingSpamEmailDomains.name }
2094
2114
  });
2095
- const bulkOps = domains.map((op) => ({ updateOne: {
2096
- filter: op.filter,
2097
- update: { $set: op.update },
2098
- upsert
2115
+ const missing = new Set(domains);
2116
+ if (missing.size === 0) return 0;
2117
+ const existing = this.tables.spamEmailDomain.find({}, {
2118
+ domain: 1,
2119
+ _id: 0
2120
+ }).hint({ domain: 1 }).lean().cursor();
2121
+ for await (const record of existing) missing.delete(record.domain);
2122
+ if (missing.size === 0) return 0;
2123
+ const bulkOps = Array.from(missing, (domain) => ({ updateOne: {
2124
+ filter: { domain },
2125
+ update: { $set: { domain } },
2126
+ upsert: true
2099
2127
  } }));
2100
- if (bulkOps.length > 0) await this.tables.spamEmailDomain.bulkWrite(bulkOps);
2128
+ await this.tables.spamEmailDomain.bulkWrite(bulkOps, { ordered: false });
2129
+ return missing.size;
2101
2130
  }
2102
2131
  };
2103
2132
  //#endregion
package/dist/esm/index.js CHANGED
@@ -3,7 +3,7 @@ import { DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_SERVER_SELECTION_TIMEOUT_MS, getMon
3
3
  import { MongoDatabase } from "./base/mongo.js";
4
4
  import { MongoMemoryDatabase } from "./base/mongoMemory.js";
5
5
  import { defaultIndexName, reconcileIndexes } from "./base/reconcileIndexes.js";
6
- import { CaptchaDatabase } from "./databases/captcha.js";
6
+ import { CaptchaDatabase, toCentralRecord } from "./databases/captcha.js";
7
7
  import { ClientDatabase } from "./databases/client.js";
8
8
  import { ProviderDatabase } from "./databases/provider.js";
9
9
  import { CentralDbStreamer } from "./databases/centralDbStreamer.js";
@@ -13,4 +13,4 @@ import { makeDirectory } from "make-dir";
13
13
  //#region src/index.ts
14
14
  console.debug(makeDirectory);
15
15
  //#endregion
16
- export { CaptchaDatabase, CentralDbStreamer, ClientDatabase, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_SERVER_SELECTION_TIMEOUT_MS, DETECTOR_BUNDLE_TTL_SECONDS, Databases, MongoDatabase, MongoMemoryDatabase, ProviderDatabase, RedisWriteQueue, defaultIndexName, getMongoCompressors, getMongoConnectionOptions, reconcileIndexes };
16
+ export { CaptchaDatabase, CentralDbStreamer, ClientDatabase, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_SERVER_SELECTION_TIMEOUT_MS, DETECTOR_BUNDLE_TTL_SECONDS, Databases, MongoDatabase, MongoMemoryDatabase, ProviderDatabase, RedisWriteQueue, defaultIndexName, getMongoCompressors, getMongoConnectionOptions, reconcileIndexes, toCentralRecord };
@@ -11,6 +11,10 @@ declare enum TableNames {
11
11
  audiocaptcha = "audiocaptcha",
12
12
  iconordercaptcha = "iconordercaptcha"
13
13
  }
14
+ export declare const toCentralRecord: <T extends {
15
+ _id?: unknown;
16
+ storedAtTimestamp?: Date;
17
+ }>(record: T) => Omit<T, "_id" | "storedAtTimestamp">;
14
18
  export declare class CaptchaDatabase extends MongoDatabase implements ICaptchaDatabase {
15
19
  tables: Tables<TableNames>;
16
20
  private indexesEnsured;
@@ -1 +1 @@
1
- {"version":3,"file":"captcha.d.ts","sourceRoot":"","sources":["../../../src/databases/captcha.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,iBAAiB,CAAC;AACzD,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAKxB,KAAK,aAAa,EAGlB,KAAK,MAAM,EACX,KAAK,oBAAoB,EACzB,MAAM,yBAAyB,CAAC;AAajC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACN,KAAK,uBAAuB,EAC5B,aAAa,EAEb,MAAM,kBAAkB,CAAC;AAI1B,aAAK,UAAU;IACd,iBAAiB,sBAAsB;IACvC,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,YAAY,iBAAiB;IAC7B,gBAAgB,qBAAqB;CACrC;AAmCD,qBAAa,eAAgB,SAAQ,aAAc,YAAW,gBAAgB;IAC7E,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC3B,OAAO,CAAC,cAAc,CAAS;gBAG9B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,uBAAuB;IAMpB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUvC,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC;IAYzB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAqDpC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAoBnC,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAajC,YAAY,CACjB,aAAa,EAAE,aAAa,EAAE,EAC9B,kBAAkB,EAAE,oBAAoB,EAAE,EAC1C,gBAAgB,EAAE,gBAAgB,EAAE,EACpC,mBAAmB,GAAE,mBAAmB,EAAO,EAC/C,sBAAsB,GAAE,sBAAsB,EAAO,EACrD,kBAAkB,GAAE,kBAAkB,EAAO;YA0HhC,sBAAsB;IAuC9B,WAAW,CAChB,MAAM,GAAE,WAAW,CAAC,iBAAiB,CAAM,EAC3C,KAAK,SAAM,GACT,OAAO,CAAC;QACV,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;QAC9C,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;QACtC,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;QAC5C,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;QAC1C,uBAAuB,EAAE,sBAAsB,EAAE,CAAC;KAClD,CAAC;CA+CF"}
1
+ {"version":3,"file":"captcha.d.ts","sourceRoot":"","sources":["../../../src/databases/captcha.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,iBAAiB,CAAC;AACzD,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAKxB,KAAK,aAAa,EAGlB,KAAK,MAAM,EACX,KAAK,oBAAoB,EACzB,MAAM,yBAAyB,CAAC;AAajC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACN,KAAK,uBAAuB,EAC5B,aAAa,EAEb,MAAM,kBAAkB,CAAC;AAI1B,aAAK,UAAU;IACd,iBAAiB,sBAAsB;IACvC,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,YAAY,iBAAiB;IAC7B,gBAAgB,qBAAqB;CACrC;AAmCD,eAAO,MAAM,eAAe,GAC3B,CAAC,SAAS;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,IAAI,CAAA;CAAE,UAE7C,CAAC,KACP,IAAI,CAAC,CAAC,EAAE,KAAK,GAAG,mBAAmB,CAGrC,CAAC;AAEF,qBAAa,eAAgB,SAAQ,aAAc,YAAW,gBAAgB;IAC7E,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC3B,OAAO,CAAC,cAAc,CAAS;gBAG9B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,uBAAuB;IAMpB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUvC,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC;IAYzB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAqDpC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAoBnC,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAajC,YAAY,CACjB,aAAa,EAAE,aAAa,EAAE,EAC9B,kBAAkB,EAAE,oBAAoB,EAAE,EAC1C,gBAAgB,EAAE,gBAAgB,EAAE,EACpC,mBAAmB,GAAE,mBAAmB,EAAO,EAC/C,sBAAsB,GAAE,sBAAsB,EAAO,EACrD,kBAAkB,GAAE,kBAAkB,EAAO;YA2HhC,sBAAsB;IAwC9B,WAAW,CAChB,MAAM,GAAE,WAAW,CAAC,iBAAiB,CAAM,EAC3C,KAAK,SAAM,GACT,OAAO,CAAC;QACV,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;QAC9C,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;QACtC,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;QAC5C,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;QAC1C,uBAAuB,EAAE,sBAAsB,EAAE,CAAC;KAClD,CAAC;CA+CF"}
@@ -50,6 +50,10 @@ const CAPTCHA_TABLES = [
50
50
  schema: StoredIconOrderCaptchaRecordSchema,
51
51
  },
52
52
  ];
53
+ export const toCentralRecord = (record) => {
54
+ const { _id, storedAtTimestamp, ...centralRecord } = record;
55
+ return centralRecord;
56
+ };
53
57
  export class CaptchaDatabase extends MongoDatabase {
54
58
  constructor(url, dbname, authSource, logger, timeouts) {
55
59
  super(url, dbname, authSource, logger, timeouts);
@@ -137,8 +141,7 @@ export class CaptchaDatabase extends MongoDatabase {
137
141
  await this.connect();
138
142
  if (sessionEvents.length) {
139
143
  const result = await this.tables.session.bulkWrite(sessionEvents.map((document) => {
140
- const { _id, ...safeDoc } = document;
141
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
144
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(document));
142
145
  return {
143
146
  updateOne: {
144
147
  filter: { sessionId: normalised.sessionId },
@@ -159,8 +162,7 @@ export class CaptchaDatabase extends MongoDatabase {
159
162
  }
160
163
  if (imageCaptchaEvents.length) {
161
164
  const result = await this.tables.commitment.bulkWrite(imageCaptchaEvents.map((doc) => {
162
- const { _id, ...safeDoc } = doc;
163
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
165
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
164
166
  return {
165
167
  updateOne: {
166
168
  filter: { id: normalised.id },
@@ -181,8 +183,7 @@ export class CaptchaDatabase extends MongoDatabase {
181
183
  }
182
184
  if (powCaptchaEvents.length) {
183
185
  const result = await this.tables.powcaptcha.bulkWrite(powCaptchaEvents.map((doc) => {
184
- const { _id, ...safeDoc } = doc;
185
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
186
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
186
187
  return {
187
188
  updateOne: {
188
189
  filter: { challenge: normalised.challenge },
@@ -211,8 +212,7 @@ export class CaptchaDatabase extends MongoDatabase {
211
212
  return;
212
213
  }
213
214
  const result = await this.tables[table].bulkWrite(records.map((doc) => {
214
- const { _id, ...safeDoc } = doc;
215
- const normalised = CaptchaDatabase.normaliseDocCompositeIps(safeDoc);
215
+ const normalised = CaptchaDatabase.normaliseDocCompositeIps(toCentralRecord(doc));
216
216
  return {
217
217
  updateOne: {
218
218
  filter: { challenge: normalised.challenge },
@@ -1 +1 @@
1
- {"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../../src/databases/captcha.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../../src/databases/captcha.ts"],"names":[],"mappings":"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"}