@prosopo/provider 3.13.0 → 3.13.6
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/CHANGELOG.md +98 -0
- package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +32 -25
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +32 -25
- package/dist/cjs/tasks/client/clientTasks.cjs +46 -8
- package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +7 -2
- package/dist/cjs/tasks/frictionless/frictionlessTasksUtils.cjs +4 -1
- package/dist/tasks/client/clientTasks.js +46 -8
- package/dist/tasks/frictionless/frictionlessTasks.js +7 -2
- package/dist/tasks/frictionless/frictionlessTasksUtils.js +4 -1
- package/package.json +20 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,103 @@
|
|
|
1
1
|
# @prosopo/provider
|
|
2
2
|
|
|
3
|
+
## 3.13.6
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- 93d92a7: little bump for publish all
|
|
7
|
+
- Updated dependencies [93d92a7]
|
|
8
|
+
- @prosopo/api@3.1.36
|
|
9
|
+
- @prosopo/api-express-router@3.0.39
|
|
10
|
+
- @prosopo/api-route@2.6.33
|
|
11
|
+
- @prosopo/common@3.1.25
|
|
12
|
+
- @prosopo/database@3.5.5
|
|
13
|
+
- @prosopo/datasets@3.0.48
|
|
14
|
+
- @prosopo/env@3.2.27
|
|
15
|
+
- @prosopo/keyring@2.8.39
|
|
16
|
+
- @prosopo/load-balancer@2.8.12
|
|
17
|
+
- @prosopo/locale@3.1.25
|
|
18
|
+
- @prosopo/types@3.6.3
|
|
19
|
+
- @prosopo/types-database@4.0.5
|
|
20
|
+
- @prosopo/types-env@2.7.52
|
|
21
|
+
- @prosopo/user-access-policy@3.5.31
|
|
22
|
+
- @prosopo/util@3.2.3
|
|
23
|
+
- @prosopo/util-crypto@13.5.27
|
|
24
|
+
|
|
25
|
+
## 3.13.5
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- 8ee8434: bump node engines to 24 and npm version to 11
|
|
29
|
+
- cfee479: make @prosopo/config a dev dep
|
|
30
|
+
- e843e62: Adding more sensible punishment for invalid decryption key
|
|
31
|
+
- Updated dependencies [8ee8434]
|
|
32
|
+
- Updated dependencies [cfee479]
|
|
33
|
+
- @prosopo/api-express-router@3.0.38
|
|
34
|
+
- @prosopo/user-access-policy@3.5.30
|
|
35
|
+
- @prosopo/types-database@4.0.4
|
|
36
|
+
- @prosopo/load-balancer@2.8.11
|
|
37
|
+
- @prosopo/util-crypto@13.5.26
|
|
38
|
+
- @prosopo/api-route@2.6.32
|
|
39
|
+
- @prosopo/types-env@2.7.51
|
|
40
|
+
- @prosopo/database@3.5.4
|
|
41
|
+
- @prosopo/datasets@3.0.47
|
|
42
|
+
- @prosopo/keyring@2.8.38
|
|
43
|
+
- @prosopo/common@3.1.24
|
|
44
|
+
- @prosopo/locale@3.1.24
|
|
45
|
+
- @prosopo/types@3.6.2
|
|
46
|
+
- @prosopo/util@3.2.2
|
|
47
|
+
- @prosopo/api@3.1.35
|
|
48
|
+
- @prosopo/env@3.2.26
|
|
49
|
+
|
|
50
|
+
## 3.13.4
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- e926831: mega mini bump for all to trigger publish all
|
|
54
|
+
- Updated dependencies [e926831]
|
|
55
|
+
- @prosopo/config@3.1.23
|
|
56
|
+
- @prosopo/api@3.1.34
|
|
57
|
+
- @prosopo/api-express-router@3.0.37
|
|
58
|
+
- @prosopo/api-route@2.6.31
|
|
59
|
+
- @prosopo/common@3.1.23
|
|
60
|
+
- @prosopo/database@3.5.3
|
|
61
|
+
- @prosopo/datasets@3.0.46
|
|
62
|
+
- @prosopo/env@3.2.25
|
|
63
|
+
- @prosopo/keyring@2.8.37
|
|
64
|
+
- @prosopo/load-balancer@2.8.10
|
|
65
|
+
- @prosopo/locale@3.1.23
|
|
66
|
+
- @prosopo/types@3.6.1
|
|
67
|
+
- @prosopo/types-database@4.0.3
|
|
68
|
+
- @prosopo/types-env@2.7.50
|
|
69
|
+
- @prosopo/user-access-policy@3.5.29
|
|
70
|
+
- @prosopo/util@3.2.1
|
|
71
|
+
- @prosopo/util-crypto@13.5.25
|
|
72
|
+
|
|
73
|
+
## 3.13.3
|
|
74
|
+
### Patch Changes
|
|
75
|
+
|
|
76
|
+
- 3be9174: Create scheduled task status
|
|
77
|
+
- Updated dependencies [0a9887c]
|
|
78
|
+
- @prosopo/types-database@4.0.2
|
|
79
|
+
- @prosopo/database@3.5.2
|
|
80
|
+
- @prosopo/datasets@3.0.45
|
|
81
|
+
- @prosopo/types-env@2.7.49
|
|
82
|
+
- @prosopo/env@3.2.24
|
|
83
|
+
- @prosopo/api-express-router@3.0.36
|
|
84
|
+
|
|
85
|
+
## 3.13.2
|
|
86
|
+
### Patch Changes
|
|
87
|
+
|
|
88
|
+
- Updated dependencies [3e5d80a]
|
|
89
|
+
- @prosopo/types-database@4.0.1
|
|
90
|
+
- @prosopo/database@3.5.1
|
|
91
|
+
- @prosopo/datasets@3.0.44
|
|
92
|
+
- @prosopo/types-env@2.7.48
|
|
93
|
+
- @prosopo/env@3.2.23
|
|
94
|
+
- @prosopo/api-express-router@3.0.35
|
|
95
|
+
|
|
96
|
+
## 3.13.1
|
|
97
|
+
### Patch Changes
|
|
98
|
+
|
|
99
|
+
- 447179c: Fix config and client getter
|
|
100
|
+
|
|
3
101
|
## 3.13.0
|
|
4
102
|
### Minor Changes
|
|
5
103
|
|
|
@@ -90,7 +90,8 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
90
90
|
userAgent,
|
|
91
91
|
webView,
|
|
92
92
|
iFrame,
|
|
93
|
-
decryptedHeadHash
|
|
93
|
+
decryptedHeadHash,
|
|
94
|
+
decryptionFailed
|
|
94
95
|
} = await tasks.frictionlessManager.decryptPayload(token, headHash);
|
|
95
96
|
req.logger.debug(() => ({
|
|
96
97
|
msg: "Decrypted payload",
|
|
@@ -160,29 +161,6 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
160
161
|
dapp,
|
|
161
162
|
userScope
|
|
162
163
|
))[0];
|
|
163
|
-
const headersUserAgent = req.headers["user-agent"];
|
|
164
|
-
const hashedHeadersUserAgent = headersUserAgent ? hashUserAgent(headersUserAgent) : "";
|
|
165
|
-
const headersProsopoUser = req.headers["prosopo-user"];
|
|
166
|
-
if (hashedHeadersUserAgent !== userAgent || headersProsopoUser !== userId) {
|
|
167
|
-
req.logger.info(() => ({
|
|
168
|
-
msg: "User agent or user id does not match",
|
|
169
|
-
data: {
|
|
170
|
-
headersUserAgent,
|
|
171
|
-
hashedHeadersUserAgent,
|
|
172
|
-
userAgent,
|
|
173
|
-
// This is the hashed user agent from the token
|
|
174
|
-
headersProsopoUser,
|
|
175
|
-
userId
|
|
176
|
-
}
|
|
177
|
-
}));
|
|
178
|
-
return res.json(
|
|
179
|
-
await tasks.frictionlessManager.sendImageCaptcha({
|
|
180
|
-
solvedImagesCount: timestampDecayFunction(timestamp),
|
|
181
|
-
userSitekeyIpHash,
|
|
182
|
-
reason: FrictionlessReason.USER_AGENT_MISMATCH
|
|
183
|
-
})
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
164
|
if (userAccessPolicy) {
|
|
187
165
|
const scoreUpdate = tasks.frictionlessManager.scoreIncreaseAccessPolicy(
|
|
188
166
|
userAccessPolicy,
|
|
@@ -211,6 +189,32 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
211
189
|
);
|
|
212
190
|
}
|
|
213
191
|
}
|
|
192
|
+
const headersUserAgent = req.headers["user-agent"];
|
|
193
|
+
const hashedHeadersUserAgent = headersUserAgent ? hashUserAgent(headersUserAgent) : "";
|
|
194
|
+
const headersProsopoUser = req.headers["prosopo-user"];
|
|
195
|
+
if (hashedHeadersUserAgent !== userAgent || headersProsopoUser !== userId) {
|
|
196
|
+
req.logger.info(() => ({
|
|
197
|
+
msg: "User agent or user id does not match",
|
|
198
|
+
data: {
|
|
199
|
+
headersUserAgent,
|
|
200
|
+
hashedHeadersUserAgent,
|
|
201
|
+
userAgent,
|
|
202
|
+
// This is the hashed user agent from the token
|
|
203
|
+
headersProsopoUser,
|
|
204
|
+
userId
|
|
205
|
+
}
|
|
206
|
+
}));
|
|
207
|
+
return res.json(
|
|
208
|
+
await tasks.frictionlessManager.sendImageCaptcha({
|
|
209
|
+
solvedImagesCount: timestampDecayFunction(
|
|
210
|
+
timestamp,
|
|
211
|
+
decryptionFailed
|
|
212
|
+
),
|
|
213
|
+
userSitekeyIpHash,
|
|
214
|
+
reason: FrictionlessReason.USER_AGENT_MISMATCH
|
|
215
|
+
})
|
|
216
|
+
);
|
|
217
|
+
}
|
|
214
218
|
if (clientRecord.settings.contextAware?.enabled) {
|
|
215
219
|
const clientEntropy = await tasks.frictionlessManager.getClientEntropy(
|
|
216
220
|
clientRecord.account
|
|
@@ -277,7 +281,10 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
277
281
|
tasks.frictionlessManager.updateScore(botScore, scoreComponents);
|
|
278
282
|
return res.json(
|
|
279
283
|
await tasks.frictionlessManager.sendImageCaptcha({
|
|
280
|
-
solvedImagesCount: timestampDecayFunction(
|
|
284
|
+
solvedImagesCount: timestampDecayFunction(
|
|
285
|
+
timestamp,
|
|
286
|
+
decryptionFailed
|
|
287
|
+
),
|
|
281
288
|
userSitekeyIpHash,
|
|
282
289
|
reason: FrictionlessReason.OLD_TIMESTAMP
|
|
283
290
|
})
|
|
@@ -91,7 +91,8 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
91
91
|
userAgent,
|
|
92
92
|
webView,
|
|
93
93
|
iFrame,
|
|
94
|
-
decryptedHeadHash
|
|
94
|
+
decryptedHeadHash,
|
|
95
|
+
decryptionFailed
|
|
95
96
|
} = await tasks$1.frictionlessManager.decryptPayload(token, headHash);
|
|
96
97
|
req.logger.debug(() => ({
|
|
97
98
|
msg: "Decrypted payload",
|
|
@@ -161,29 +162,6 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
161
162
|
dapp,
|
|
162
163
|
userScope
|
|
163
164
|
))[0];
|
|
164
|
-
const headersUserAgent = req.headers["user-agent"];
|
|
165
|
-
const hashedHeadersUserAgent = headersUserAgent ? hashUserAgent.hashUserAgent(headersUserAgent) : "";
|
|
166
|
-
const headersProsopoUser = req.headers["prosopo-user"];
|
|
167
|
-
if (hashedHeadersUserAgent !== userAgent || headersProsopoUser !== userId) {
|
|
168
|
-
req.logger.info(() => ({
|
|
169
|
-
msg: "User agent or user id does not match",
|
|
170
|
-
data: {
|
|
171
|
-
headersUserAgent,
|
|
172
|
-
hashedHeadersUserAgent,
|
|
173
|
-
userAgent,
|
|
174
|
-
// This is the hashed user agent from the token
|
|
175
|
-
headersProsopoUser,
|
|
176
|
-
userId
|
|
177
|
-
}
|
|
178
|
-
}));
|
|
179
|
-
return res.json(
|
|
180
|
-
await tasks$1.frictionlessManager.sendImageCaptcha({
|
|
181
|
-
solvedImagesCount: frictionlessTasksUtils.timestampDecayFunction(timestamp),
|
|
182
|
-
userSitekeyIpHash,
|
|
183
|
-
reason: frictionlessTasks.FrictionlessReason.USER_AGENT_MISMATCH
|
|
184
|
-
})
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
165
|
if (userAccessPolicy) {
|
|
188
166
|
const scoreUpdate = tasks$1.frictionlessManager.scoreIncreaseAccessPolicy(
|
|
189
167
|
userAccessPolicy,
|
|
@@ -212,6 +190,32 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
212
190
|
);
|
|
213
191
|
}
|
|
214
192
|
}
|
|
193
|
+
const headersUserAgent = req.headers["user-agent"];
|
|
194
|
+
const hashedHeadersUserAgent = headersUserAgent ? hashUserAgent.hashUserAgent(headersUserAgent) : "";
|
|
195
|
+
const headersProsopoUser = req.headers["prosopo-user"];
|
|
196
|
+
if (hashedHeadersUserAgent !== userAgent || headersProsopoUser !== userId) {
|
|
197
|
+
req.logger.info(() => ({
|
|
198
|
+
msg: "User agent or user id does not match",
|
|
199
|
+
data: {
|
|
200
|
+
headersUserAgent,
|
|
201
|
+
hashedHeadersUserAgent,
|
|
202
|
+
userAgent,
|
|
203
|
+
// This is the hashed user agent from the token
|
|
204
|
+
headersProsopoUser,
|
|
205
|
+
userId
|
|
206
|
+
}
|
|
207
|
+
}));
|
|
208
|
+
return res.json(
|
|
209
|
+
await tasks$1.frictionlessManager.sendImageCaptcha({
|
|
210
|
+
solvedImagesCount: frictionlessTasksUtils.timestampDecayFunction(
|
|
211
|
+
timestamp,
|
|
212
|
+
decryptionFailed
|
|
213
|
+
),
|
|
214
|
+
userSitekeyIpHash,
|
|
215
|
+
reason: frictionlessTasks.FrictionlessReason.USER_AGENT_MISMATCH
|
|
216
|
+
})
|
|
217
|
+
);
|
|
218
|
+
}
|
|
215
219
|
if (clientRecord.settings.contextAware?.enabled) {
|
|
216
220
|
const clientEntropy = await tasks$1.frictionlessManager.getClientEntropy(
|
|
217
221
|
clientRecord.account
|
|
@@ -278,7 +282,10 @@ const getFrictionlessCaptchaChallenge = (env, userAccessRulesStorage) => async (
|
|
|
278
282
|
tasks$1.frictionlessManager.updateScore(botScore, scoreComponents);
|
|
279
283
|
return res.json(
|
|
280
284
|
await tasks$1.frictionlessManager.sendImageCaptcha({
|
|
281
|
-
solvedImagesCount: frictionlessTasksUtils.timestampDecayFunction(
|
|
285
|
+
solvedImagesCount: frictionlessTasksUtils.timestampDecayFunction(
|
|
286
|
+
timestamp,
|
|
287
|
+
decryptionFailed
|
|
288
|
+
),
|
|
282
289
|
userSitekeyIpHash,
|
|
283
290
|
reason: frictionlessTasks.FrictionlessReason.OLD_TIMESTAMP
|
|
284
291
|
})
|
|
@@ -163,7 +163,13 @@ class ClientTaskManager {
|
|
|
163
163
|
this.logger
|
|
164
164
|
);
|
|
165
165
|
const tenMinuteWindow = 10 * 60 * 1e3;
|
|
166
|
-
const updatedAtTimestamp =
|
|
166
|
+
const updatedAtTimestamp = (() => {
|
|
167
|
+
const raw = lastTask?.updated;
|
|
168
|
+
if (!raw) return 0;
|
|
169
|
+
const ts = raw instanceof Date ? raw.getTime() : Date.parse(String(raw));
|
|
170
|
+
if (Number.isNaN(ts)) return 0;
|
|
171
|
+
return Math.max(ts - tenMinuteWindow, 0);
|
|
172
|
+
})();
|
|
167
173
|
this.logger.info(() => ({
|
|
168
174
|
msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}`
|
|
169
175
|
}));
|
|
@@ -201,14 +207,46 @@ class ClientTaskManager {
|
|
|
201
207
|
* @returns Promise<void>
|
|
202
208
|
*/
|
|
203
209
|
async calculateClientEntropy() {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(
|
|
211
|
+
types.ScheduledTaskNames.SetClientEntropy,
|
|
212
|
+
types.ScheduledTaskStatus.Running
|
|
213
|
+
);
|
|
214
|
+
try {
|
|
215
|
+
const clients = await this.providerDB.getAllClientRecords();
|
|
216
|
+
for (const client of clients) {
|
|
217
|
+
const sampleEntropies = await this.providerDB.sampleEntropy(
|
|
218
|
+
100,
|
|
219
|
+
client.account
|
|
220
|
+
);
|
|
221
|
+
const avgEntropy = util.majorityAverage(sampleEntropies);
|
|
222
|
+
await this.providerDB.setClientEntropy(client.account, avgEntropy);
|
|
223
|
+
}
|
|
224
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
225
|
+
taskID,
|
|
226
|
+
types.ScheduledTaskStatus.Completed,
|
|
227
|
+
{
|
|
228
|
+
data: {
|
|
229
|
+
clientRecords: clients.length
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
} catch (e) {
|
|
234
|
+
const calculateClientEntropiesError = new common.ProsopoApiError(
|
|
235
|
+
"DATABASE.UNKNOWN",
|
|
236
|
+
{
|
|
237
|
+
context: { error: e },
|
|
238
|
+
logger: this.logger
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
this.logger.error(() => ({
|
|
242
|
+
err: calculateClientEntropiesError,
|
|
243
|
+
msg: "Error calculating client entropy"
|
|
244
|
+
}));
|
|
245
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
246
|
+
taskID,
|
|
247
|
+
types.ScheduledTaskStatus.Failed,
|
|
248
|
+
{ error: String(e) }
|
|
209
249
|
);
|
|
210
|
-
const avgEntropy = util.majorityAverage(sampleEntropies);
|
|
211
|
-
await this.providerDB.setClientEntropy(client.account, avgEntropy);
|
|
212
250
|
}
|
|
213
251
|
}
|
|
214
252
|
async registerSiteKey(siteKey, tier, settings) {
|
|
@@ -249,6 +249,7 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
249
249
|
let webView;
|
|
250
250
|
let iFrame;
|
|
251
251
|
let decryptedHeadHash = "";
|
|
252
|
+
let decryptionFailed = false;
|
|
252
253
|
for (const [keyIndex, key] of decryptKeys.entries()) {
|
|
253
254
|
try {
|
|
254
255
|
this.logger.info(() => ({
|
|
@@ -296,6 +297,7 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
296
297
|
timestamp = 0;
|
|
297
298
|
providerSelectEntropy = DEFAULT_ENTROPY + 1;
|
|
298
299
|
decryptedHeadHash = "";
|
|
300
|
+
decryptionFailed = true;
|
|
299
301
|
}
|
|
300
302
|
}
|
|
301
303
|
}
|
|
@@ -311,6 +313,7 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
311
313
|
timestamp = 0;
|
|
312
314
|
providerSelectEntropy = DEFAULT_ENTROPY - undefinedCount;
|
|
313
315
|
decryptedHeadHash = "";
|
|
316
|
+
decryptionFailed = true;
|
|
314
317
|
}
|
|
315
318
|
this.logger.info(() => ({
|
|
316
319
|
msg: "decryptPayload result",
|
|
@@ -322,7 +325,8 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
322
325
|
userAgent,
|
|
323
326
|
webView,
|
|
324
327
|
iFrame,
|
|
325
|
-
decryptedHeadHash
|
|
328
|
+
decryptedHeadHash,
|
|
329
|
+
decryptionFailed
|
|
326
330
|
}
|
|
327
331
|
}));
|
|
328
332
|
return {
|
|
@@ -333,7 +337,8 @@ class FrictionlessManager extends captchaManager.CaptchaManager {
|
|
|
333
337
|
userAgent,
|
|
334
338
|
webView: webView || false,
|
|
335
339
|
iFrame: iFrame || false,
|
|
336
|
-
decryptedHeadHash
|
|
340
|
+
decryptedHeadHash,
|
|
341
|
+
decryptionFailed
|
|
337
342
|
};
|
|
338
343
|
}
|
|
339
344
|
async getClientEntropy(siteKey) {
|
|
@@ -8,7 +8,10 @@ const computeFrictionlessScore = (scoreComponents) => {
|
|
|
8
8
|
).toFixed(2)
|
|
9
9
|
);
|
|
10
10
|
};
|
|
11
|
-
const timestampDecayFunction = (timestamp) => {
|
|
11
|
+
const timestampDecayFunction = (timestamp, decryptionFailed) => {
|
|
12
|
+
if (decryptionFailed) {
|
|
13
|
+
return 6;
|
|
14
|
+
}
|
|
12
15
|
const max = (/* @__PURE__ */ new Date()).getTime();
|
|
13
16
|
if (max - timestamp > 36e5) {
|
|
14
17
|
return 12;
|
|
@@ -161,7 +161,13 @@ class ClientTaskManager {
|
|
|
161
161
|
this.logger
|
|
162
162
|
);
|
|
163
163
|
const tenMinuteWindow = 10 * 60 * 1e3;
|
|
164
|
-
const updatedAtTimestamp =
|
|
164
|
+
const updatedAtTimestamp = (() => {
|
|
165
|
+
const raw = lastTask?.updated;
|
|
166
|
+
if (!raw) return 0;
|
|
167
|
+
const ts = raw instanceof Date ? raw.getTime() : Date.parse(String(raw));
|
|
168
|
+
if (Number.isNaN(ts)) return 0;
|
|
169
|
+
return Math.max(ts - tenMinuteWindow, 0);
|
|
170
|
+
})();
|
|
165
171
|
this.logger.info(() => ({
|
|
166
172
|
msg: `Getting updated client records since ${new Date(updatedAtTimestamp).toDateString()}`
|
|
167
173
|
}));
|
|
@@ -199,14 +205,46 @@ class ClientTaskManager {
|
|
|
199
205
|
* @returns Promise<void>
|
|
200
206
|
*/
|
|
201
207
|
async calculateClientEntropy() {
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
const taskID = await this.providerDB.createScheduledTaskStatus(
|
|
209
|
+
ScheduledTaskNames.SetClientEntropy,
|
|
210
|
+
ScheduledTaskStatus.Running
|
|
211
|
+
);
|
|
212
|
+
try {
|
|
213
|
+
const clients = await this.providerDB.getAllClientRecords();
|
|
214
|
+
for (const client of clients) {
|
|
215
|
+
const sampleEntropies = await this.providerDB.sampleEntropy(
|
|
216
|
+
100,
|
|
217
|
+
client.account
|
|
218
|
+
);
|
|
219
|
+
const avgEntropy = majorityAverage(sampleEntropies);
|
|
220
|
+
await this.providerDB.setClientEntropy(client.account, avgEntropy);
|
|
221
|
+
}
|
|
222
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
223
|
+
taskID,
|
|
224
|
+
ScheduledTaskStatus.Completed,
|
|
225
|
+
{
|
|
226
|
+
data: {
|
|
227
|
+
clientRecords: clients.length
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
} catch (e) {
|
|
232
|
+
const calculateClientEntropiesError = new ProsopoApiError(
|
|
233
|
+
"DATABASE.UNKNOWN",
|
|
234
|
+
{
|
|
235
|
+
context: { error: e },
|
|
236
|
+
logger: this.logger
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
this.logger.error(() => ({
|
|
240
|
+
err: calculateClientEntropiesError,
|
|
241
|
+
msg: "Error calculating client entropy"
|
|
242
|
+
}));
|
|
243
|
+
await this.providerDB.updateScheduledTaskStatus(
|
|
244
|
+
taskID,
|
|
245
|
+
ScheduledTaskStatus.Failed,
|
|
246
|
+
{ error: String(e) }
|
|
207
247
|
);
|
|
208
|
-
const avgEntropy = majorityAverage(sampleEntropies);
|
|
209
|
-
await this.providerDB.setClientEntropy(client.account, avgEntropy);
|
|
210
248
|
}
|
|
211
249
|
}
|
|
212
250
|
async registerSiteKey(siteKey, tier, settings) {
|
|
@@ -247,6 +247,7 @@ class FrictionlessManager extends CaptchaManager {
|
|
|
247
247
|
let webView;
|
|
248
248
|
let iFrame;
|
|
249
249
|
let decryptedHeadHash = "";
|
|
250
|
+
let decryptionFailed = false;
|
|
250
251
|
for (const [keyIndex, key] of decryptKeys.entries()) {
|
|
251
252
|
try {
|
|
252
253
|
this.logger.info(() => ({
|
|
@@ -294,6 +295,7 @@ class FrictionlessManager extends CaptchaManager {
|
|
|
294
295
|
timestamp = 0;
|
|
295
296
|
providerSelectEntropy = DEFAULT_ENTROPY + 1;
|
|
296
297
|
decryptedHeadHash = "";
|
|
298
|
+
decryptionFailed = true;
|
|
297
299
|
}
|
|
298
300
|
}
|
|
299
301
|
}
|
|
@@ -309,6 +311,7 @@ class FrictionlessManager extends CaptchaManager {
|
|
|
309
311
|
timestamp = 0;
|
|
310
312
|
providerSelectEntropy = DEFAULT_ENTROPY - undefinedCount;
|
|
311
313
|
decryptedHeadHash = "";
|
|
314
|
+
decryptionFailed = true;
|
|
312
315
|
}
|
|
313
316
|
this.logger.info(() => ({
|
|
314
317
|
msg: "decryptPayload result",
|
|
@@ -320,7 +323,8 @@ class FrictionlessManager extends CaptchaManager {
|
|
|
320
323
|
userAgent,
|
|
321
324
|
webView,
|
|
322
325
|
iFrame,
|
|
323
|
-
decryptedHeadHash
|
|
326
|
+
decryptedHeadHash,
|
|
327
|
+
decryptionFailed
|
|
324
328
|
}
|
|
325
329
|
}));
|
|
326
330
|
return {
|
|
@@ -331,7 +335,8 @@ class FrictionlessManager extends CaptchaManager {
|
|
|
331
335
|
userAgent,
|
|
332
336
|
webView: webView || false,
|
|
333
337
|
iFrame: iFrame || false,
|
|
334
|
-
decryptedHeadHash
|
|
338
|
+
decryptedHeadHash,
|
|
339
|
+
decryptionFailed
|
|
335
340
|
};
|
|
336
341
|
}
|
|
337
342
|
async getClientEntropy(siteKey) {
|
|
@@ -6,7 +6,10 @@ const computeFrictionlessScore = (scoreComponents) => {
|
|
|
6
6
|
).toFixed(2)
|
|
7
7
|
);
|
|
8
8
|
};
|
|
9
|
-
const timestampDecayFunction = (timestamp) => {
|
|
9
|
+
const timestampDecayFunction = (timestamp, decryptionFailed) => {
|
|
10
|
+
if (decryptionFailed) {
|
|
11
|
+
return 6;
|
|
12
|
+
}
|
|
10
13
|
const max = (/* @__PURE__ */ new Date()).getTime();
|
|
11
14
|
if (max - timestamp > 36e5) {
|
|
12
15
|
return 12;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosopo/provider",
|
|
3
|
-
"version": "3.13.
|
|
3
|
+
"version": "3.13.6",
|
|
4
4
|
"author": "PROSOPO LIMITED <info@prosopo.io>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": "
|
|
9
|
-
"npm": "
|
|
8
|
+
"node": "^24",
|
|
9
|
+
"npm": "^11"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"clean": "del-cli --verbose dist tsconfig.tsbuildinfo",
|
|
@@ -22,23 +22,22 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@noble/hashes": "1.8.0",
|
|
24
24
|
"@polkadot/util": "13.5.7",
|
|
25
|
-
"@prosopo/api": "3.1.
|
|
26
|
-
"@prosopo/api-express-router": "3.0.
|
|
27
|
-
"@prosopo/api-route": "2.6.
|
|
28
|
-
"@prosopo/common": "3.1.
|
|
29
|
-
"@prosopo/
|
|
30
|
-
"@prosopo/
|
|
31
|
-
"@prosopo/
|
|
32
|
-
"@prosopo/
|
|
33
|
-
"@prosopo/
|
|
34
|
-
"@prosopo/
|
|
35
|
-
"@prosopo/
|
|
36
|
-
"@prosopo/types": "
|
|
37
|
-
"@prosopo/types-
|
|
38
|
-
"@prosopo/
|
|
39
|
-
"@prosopo/
|
|
40
|
-
"@prosopo/util": "
|
|
41
|
-
"@prosopo/util-crypto": "13.5.24",
|
|
25
|
+
"@prosopo/api": "3.1.36",
|
|
26
|
+
"@prosopo/api-express-router": "3.0.39",
|
|
27
|
+
"@prosopo/api-route": "2.6.33",
|
|
28
|
+
"@prosopo/common": "3.1.25",
|
|
29
|
+
"@prosopo/database": "3.5.5",
|
|
30
|
+
"@prosopo/datasets": "3.0.48",
|
|
31
|
+
"@prosopo/env": "3.2.27",
|
|
32
|
+
"@prosopo/keyring": "2.8.39",
|
|
33
|
+
"@prosopo/load-balancer": "2.8.12",
|
|
34
|
+
"@prosopo/locale": "3.1.25",
|
|
35
|
+
"@prosopo/types": "3.6.3",
|
|
36
|
+
"@prosopo/types-database": "4.0.5",
|
|
37
|
+
"@prosopo/types-env": "2.7.52",
|
|
38
|
+
"@prosopo/user-access-policy": "3.5.31",
|
|
39
|
+
"@prosopo/util": "3.2.3",
|
|
40
|
+
"@prosopo/util-crypto": "13.5.27",
|
|
42
41
|
"cron": "3.1.7",
|
|
43
42
|
"express": "4.21.2",
|
|
44
43
|
"geolib": "3.3.4",
|
|
@@ -50,6 +49,7 @@
|
|
|
50
49
|
"zod": "3.23.8"
|
|
51
50
|
},
|
|
52
51
|
"devDependencies": {
|
|
52
|
+
"@prosopo/config": "3.1.25",
|
|
53
53
|
"@types/node": "22.5.5",
|
|
54
54
|
"@types/uuid": "10.0.0",
|
|
55
55
|
"@vitest/coverage-v8": "3.2.4",
|