@prosopo/provider 2.0.3 → 2.1.1

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 (111) hide show
  1. package/coverage/base.css +224 -0
  2. package/coverage/block-navigation.js +87 -0
  3. package/coverage/clover.xml +6 -0
  4. package/coverage/coverage-final.json +1 -0
  5. package/coverage/favicon.png +0 -0
  6. package/coverage/index.html +101 -0
  7. package/coverage/prettify.css +1 -0
  8. package/coverage/prettify.js +2 -0
  9. package/coverage/sort-arrow-sprite.png +0 -0
  10. package/coverage/sorter.js +196 -0
  11. package/dist/api/admin.d.ts.map +1 -1
  12. package/dist/api/admin.js +19 -8
  13. package/dist/api/admin.js.map +1 -1
  14. package/dist/api/authMiddleware.d.ts +2 -3
  15. package/dist/api/authMiddleware.d.ts.map +1 -1
  16. package/dist/api/authMiddleware.js +16 -9
  17. package/dist/api/authMiddleware.js.map +1 -1
  18. package/dist/api/captcha.d.ts.map +1 -1
  19. package/dist/api/captcha.js +50 -30
  20. package/dist/api/captcha.js.map +1 -1
  21. package/dist/api/errorHandler.js.map +1 -1
  22. package/dist/api/verify.d.ts.map +1 -1
  23. package/dist/api/verify.js +3 -5
  24. package/dist/api/verify.js.map +1 -1
  25. package/dist/cjs/api/admin.cjs +17 -7
  26. package/dist/cjs/api/authMiddleware.cjs +16 -9
  27. package/dist/cjs/api/captcha.cjs +56 -31
  28. package/dist/cjs/api/verify.cjs +3 -4
  29. package/dist/cjs/index.cjs +3 -1
  30. package/dist/cjs/{api → schedulers}/captchaScheduler.cjs +2 -2
  31. package/dist/cjs/schedulers/getClientList.cjs +31 -0
  32. package/dist/cjs/tasks/client/clientTasks.cjs +148 -0
  33. package/dist/cjs/tasks/dataset/datasetTasks.cjs +0 -95
  34. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +7 -4
  35. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +3 -2
  36. package/dist/cjs/tasks/tasks.cjs +6 -0
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/{api → schedulers}/captchaScheduler.d.ts +1 -1
  42. package/dist/schedulers/captchaScheduler.d.ts.map +1 -0
  43. package/dist/{api → schedulers}/captchaScheduler.js +4 -4
  44. package/dist/schedulers/captchaScheduler.js.map +1 -0
  45. package/dist/schedulers/getClientList.d.ts +4 -0
  46. package/dist/schedulers/getClientList.d.ts.map +1 -0
  47. package/dist/schedulers/getClientList.js +28 -0
  48. package/dist/schedulers/getClientList.js.map +1 -0
  49. package/dist/tasks/client/clientTasks.d.ts +13 -0
  50. package/dist/tasks/client/clientTasks.d.ts.map +1 -0
  51. package/dist/tasks/client/clientTasks.js +87 -0
  52. package/dist/tasks/client/clientTasks.js.map +1 -0
  53. package/dist/tasks/dataset/datasetTasks.d.ts +4 -6
  54. package/dist/tasks/dataset/datasetTasks.d.ts.map +1 -1
  55. package/dist/tasks/dataset/datasetTasks.js +0 -52
  56. package/dist/tasks/dataset/datasetTasks.js.map +1 -1
  57. package/dist/tasks/dataset/datasetTasksUtils.js.map +1 -1
  58. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts +6 -6
  59. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
  60. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +4 -3
  61. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
  62. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.d.ts.map +1 -1
  63. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js.map +1 -1
  64. package/dist/tasks/powCaptcha/powTasks.d.ts +5 -5
  65. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  66. package/dist/tasks/powCaptcha/powTasks.js +3 -3
  67. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  68. package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +1 -1
  69. package/dist/tasks/powCaptcha/powTasksUtils.js.map +1 -1
  70. package/dist/tasks/tasks.d.ts +5 -3
  71. package/dist/tasks/tasks.d.ts.map +1 -1
  72. package/dist/tasks/tasks.js +2 -0
  73. package/dist/tasks/tasks.js.map +1 -1
  74. package/dist/tests/integration/imgCaptcha.integration.test.js +25 -7
  75. package/dist/tests/integration/imgCaptcha.integration.test.js.map +1 -1
  76. package/dist/tests/integration/mocks/solvedTestCaptchas.d.ts +8 -12
  77. package/dist/tests/integration/mocks/solvedTestCaptchas.d.ts.map +1 -1
  78. package/dist/tests/integration/mocks/solvedTestCaptchas.js.map +1 -1
  79. package/dist/tests/integration/powCaptcha.integration.test.js +62 -6
  80. package/dist/tests/integration/powCaptcha.integration.test.js.map +1 -1
  81. package/dist/tests/integration/registerSitekey.d.ts +2 -0
  82. package/dist/tests/integration/registerSitekey.d.ts.map +1 -0
  83. package/dist/tests/integration/registerSitekey.js +17 -0
  84. package/dist/tests/integration/registerSitekey.js.map +1 -0
  85. package/dist/tests/unit/api/authMiddleware.unit.test.js +6 -6
  86. package/dist/tests/unit/api/authMiddleware.unit.test.js.map +1 -1
  87. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.d.ts.map +1 -0
  88. package/dist/tests/unit/{api → schedulers}/captchaScheduler.unit.test.js +6 -4
  89. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -0
  90. package/dist/tests/unit/tasks/client/clientTasks.unit.test.d.ts +2 -0
  91. package/dist/tests/unit/tasks/client/clientTasks.unit.test.d.ts.map +1 -0
  92. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +172 -0
  93. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -0
  94. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js +12 -114
  95. package/dist/tests/unit/tasks/dataset/datasetTasks.unit.test.js.map +1 -1
  96. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +6 -2
  97. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +1 -1
  98. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
  99. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js +7 -2
  100. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +1 -1
  101. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +1 -1
  102. package/dist/util.d.ts +2 -2
  103. package/dist/util.d.ts.map +1 -1
  104. package/dist/util.js.map +1 -1
  105. package/package.json +66 -72
  106. package/vite.test.config.ts +3 -15
  107. package/dist/api/captchaScheduler.d.ts.map +0 -1
  108. package/dist/api/captchaScheduler.js.map +0 -1
  109. package/dist/tests/unit/api/captchaScheduler.unit.test.d.ts.map +0 -1
  110. package/dist/tests/unit/api/captchaScheduler.unit.test.js.map +0 -1
  111. /package/dist/tests/unit/{api → schedulers}/captchaScheduler.unit.test.d.ts +0 -0
@@ -15,14 +15,24 @@ function prosopoRouter(env) {
15
15
  const GetImageCaptchaChallengePath = `${types.ApiPaths.GetImageCaptchaChallenge}/:${types.ApiParams.datasetId}/:${types.ApiParams.user}/:${types.ApiParams.dapp}`;
16
16
  router.get(GetImageCaptchaChallengePath, async (req, res, next) => {
17
17
  try {
18
- const { datasetId, user } = types.CaptchaRequestBody.parse(req.params);
18
+ const { datasetId, user, dapp } = types.CaptchaRequestBody.parse(req.params);
19
19
  address.validateAddress(user, false, 42);
20
+ address.validateAddress(dapp, false, 42);
21
+ const clientRecord = await tasks$1.db.getClientRecord(dapp);
22
+ if (!clientRecord) {
23
+ return res.json({
24
+ error: req.i18n.t("API.SITE_KEY_NOT_REGISTERED"),
25
+ code: 200
26
+ });
27
+ }
20
28
  const taskData = await tasks$1.imgCaptchaManager.getRandomCaptchasAndRequestHash(
21
29
  datasetId,
22
30
  user,
23
- req.ip || NO_IP_ADDRESS
31
+ req.ip || NO_IP_ADDRESS,
32
+ util.flatten(req.headers, ",")
24
33
  );
25
34
  const captchaResponse = {
35
+ [types.ApiParams.status]: "ok",
26
36
  [types.ApiParams.captchas]: taskData.captchas.map((captcha) => ({
27
37
  ...captcha,
28
38
  items: captcha.items.map(
@@ -59,15 +69,23 @@ function prosopoRouter(env) {
59
69
  );
60
70
  }
61
71
  try {
72
+ const clientRecord = await tasks$1.db.getClientRecord(parsed.dapp);
73
+ if (!clientRecord) {
74
+ return res.json({
75
+ error: req.i18n.t("API.SITE_KEY_NOT_REGISTERED"),
76
+ code: 200
77
+ });
78
+ }
62
79
  const result = await tasks$1.imgCaptchaManager.dappUserSolution(
63
80
  parsed[types.ApiParams.user],
64
81
  parsed[types.ApiParams.dapp],
65
82
  parsed[types.ApiParams.requestHash],
66
83
  parsed[types.ApiParams.captchas],
67
84
  parsed[types.ApiParams.signature].user.requestHash,
68
- parseInt(parsed[types.ApiParams.timestamp]),
85
+ Number.parseInt(parsed[types.ApiParams.timestamp]),
69
86
  parsed[types.ApiParams.signature].provider.requestHash,
70
- req.ip || NO_IP_ADDRESS
87
+ req.ip || NO_IP_ADDRESS,
88
+ util.flatten(req.headers, ",")
71
89
  );
72
90
  const returnValue = {
73
91
  status: req.i18n.t(
@@ -88,11 +106,22 @@ function prosopoRouter(env) {
88
106
  router.post(types.ApiPaths.GetPowCaptchaChallenge, async (req, res, next) => {
89
107
  try {
90
108
  const { user, dapp } = types.GetPowCaptchaChallengeRequestBody.parse(req.body);
109
+ address.validateAddress(user, false, 42);
110
+ address.validateAddress(dapp, false, 42);
111
+ const clientRecord = await tasks$1.db.getClientRecord(dapp);
112
+ if (!clientRecord) {
113
+ return res.json({
114
+ error: req.i18n.t("API.SITE_KEY_NOT_REGISTERED"),
115
+ code: 200
116
+ });
117
+ }
91
118
  const origin = req.headers.origin;
92
119
  if (!origin) {
93
- throw new common.ProsopoApiError("API.BAD_REQUEST", {
94
- context: { code: 400, error: "origin header not found" }
95
- });
120
+ return next(
121
+ new common.ProsopoApiError("API.BAD_REQUEST", {
122
+ context: { error: "origin header not found", code: 400 }
123
+ })
124
+ );
96
125
  }
97
126
  const challenge = await tasks$1.powCaptchaManager.getPowCaptchaChallenge(
98
127
  user,
@@ -108,15 +137,17 @@ function prosopoRouter(env) {
108
137
  },
109
138
  challenge.difficulty,
110
139
  challenge.providerSignature,
111
- req.ip || NO_IP_ADDRESS
140
+ req.ip || NO_IP_ADDRESS,
141
+ util.flatten(req.headers, ",")
112
142
  );
113
143
  const getPowCaptchaResponse = {
114
- challenge: challenge.challenge,
115
- difficulty: challenge.difficulty,
116
- timestamp: challenge.requestedAtTimestamp.toString(),
117
- signature: {
118
- provider: {
119
- challenge: challenge.providerSignature
144
+ [types.ApiParams.status]: "ok",
145
+ [types.ApiParams.challenge]: challenge.challenge,
146
+ [types.ApiParams.difficulty]: challenge.difficulty,
147
+ [types.ApiParams.timestamp]: challenge.requestedAtTimestamp.toString(),
148
+ [types.ApiParams.signature]: {
149
+ [types.ApiParams.provider]: {
150
+ [types.ApiParams.challenge]: challenge.providerSignature
120
151
  }
121
152
  }
122
153
  };
@@ -132,7 +163,14 @@ function prosopoRouter(env) {
132
163
  });
133
164
  router.post(types.ApiPaths.SubmitPowCaptchaSolution, async (req, res, next) => {
134
165
  try {
135
- const { challenge, difficulty, signature, nonce, verifiedTimeout } = types.SubmitPowCaptchaSolutionBody.parse(req.body);
166
+ const { challenge, difficulty, signature, nonce, verifiedTimeout, dapp } = types.SubmitPowCaptchaSolutionBody.parse(req.body);
167
+ const clientRecord = await tasks$1.db.getClientRecord(dapp);
168
+ if (!clientRecord) {
169
+ return res.json({
170
+ error: req.i18n.t("API.SITE_KEY_NOT_REGISTERED"),
171
+ code: 200
172
+ });
173
+ }
136
174
  const verified = await tasks$1.powCaptchaManager.verifyPowCaptchaSolution(
137
175
  challenge,
138
176
  difficulty,
@@ -140,9 +178,10 @@ function prosopoRouter(env) {
140
178
  nonce,
141
179
  verifiedTimeout,
142
180
  signature.user.timestamp,
143
- req.ip || NO_IP_ADDRESS
181
+ req.ip || NO_IP_ADDRESS,
182
+ util.flatten(req.headers, ",")
144
183
  );
145
- const response = { verified };
184
+ const response = { status: "ok", verified };
146
185
  return res.json(response);
147
186
  } catch (err) {
148
187
  tasks$1.logger.error(err);
@@ -153,20 +192,6 @@ function prosopoRouter(env) {
153
192
  );
154
193
  }
155
194
  });
156
- router.post(types.ApiPaths.SubmitUserEvents, async (req, res, next) => {
157
- try {
158
- const { events, accountId } = req.body;
159
- await tasks$1.datasetManager.saveCaptchaEvent(events, accountId);
160
- return res.json({ status: "success" });
161
- } catch (err) {
162
- tasks$1.logger.error(err);
163
- return next(
164
- new common.ProsopoApiError("API.BAD_REQUEST", {
165
- context: { code: 400, error: err }
166
- })
167
- );
168
- }
169
- });
170
195
  router.get(types.ApiPaths.GetProviderDetails, async (req, res, next) => {
171
196
  try {
172
197
  return res.json({ version: util.version, ...{ message: "Provider online" } });
@@ -32,11 +32,10 @@ function prosopoVerifyRouter(env) {
32
32
  [types.ApiParams.verified]: false
33
33
  };
34
34
  return res.json(alreadyCheckedResponse);
35
- } else {
36
- await tasks$1.imgCaptchaManager.db.markDappUserCommitmentsChecked([
37
- solution.id
38
- ]);
39
35
  }
36
+ await tasks$1.imgCaptchaManager.db.markDappUserCommitmentsChecked([
37
+ solution.id
38
+ ]);
40
39
  }
41
40
  if (solution.result.status === types.CaptchaStatus.disapproved) {
42
41
  const disapprovedResponse = {
@@ -6,7 +6,8 @@ const captcha = require("./api/captcha.cjs");
6
6
  const verify = require("./api/verify.cjs");
7
7
  const admin = require("./api/admin.cjs");
8
8
  const errorHandler = require("./api/errorHandler.cjs");
9
- const captchaScheduler = require("./api/captchaScheduler.cjs");
9
+ const captchaScheduler = require("./schedulers/captchaScheduler.cjs");
10
+ const getClientList = require("./schedulers/getClientList.cjs");
10
11
  const tasks = require("./tasks/tasks.cjs");
11
12
  exports.checkIfTaskIsRunning = util.checkIfTaskIsRunning;
12
13
  exports.encodeStringAddress = util.encodeStringAddress;
@@ -16,4 +17,5 @@ exports.prosopoVerifyRouter = verify.prosopoVerifyRouter;
16
17
  exports.prosopoAdminRouter = admin.prosopoAdminRouter;
17
18
  exports.handleErrors = errorHandler.handleErrors;
18
19
  exports.storeCaptchasExternally = captchaScheduler.storeCaptchasExternally;
20
+ exports.getClientList = getClientList.getClientList;
19
21
  exports.Tasks = tasks.Tasks;
@@ -10,7 +10,7 @@ async function storeCaptchasExternally(pair, config) {
10
10
  await env$1.isReady();
11
11
  const tasks$1 = new tasks.Tasks(env$1);
12
12
  const defaultSchedule = "0 * * * *";
13
- const cronSchedule = config.captchaScheduler ? config.captchaScheduler.schedule ? config.captchaScheduler.schedule : defaultSchedule : defaultSchedule;
13
+ const cronSchedule = config.scheduledTasks?.captchaScheduler ? config.scheduledTasks.captchaScheduler.schedule ? config.scheduledTasks.captchaScheduler.schedule : defaultSchedule : defaultSchedule;
14
14
  const job = new cron.CronJob(cronSchedule, async () => {
15
15
  const taskRunning = await util.checkIfTaskIsRunning(
16
16
  types.ScheduledTaskNames.StoreCommitmentsExternal,
@@ -23,7 +23,7 @@ async function storeCaptchasExternally(pair, config) {
23
23
  env$1.logger.info(
24
24
  `${types.ScheduledTaskNames.StoreCommitmentsExternal} task....`
25
25
  );
26
- await tasks$1.datasetManager.storeCommitmentsExternal().catch((err) => {
26
+ await tasks$1.clientTaskManager.storeCommitmentsExternal().catch((err) => {
27
27
  env$1.logger.error(err);
28
28
  });
29
29
  }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const env = require("@prosopo/env");
4
+ const types = require("@prosopo/types");
5
+ const cron = require("cron");
6
+ const tasks = require("../tasks/tasks.cjs");
7
+ const util = require("../util.cjs");
8
+ async function getClientList(pair, config) {
9
+ const env$1 = new env.ProviderEnvironment(config, pair);
10
+ await env$1.isReady();
11
+ const tasks$1 = new tasks.Tasks(env$1);
12
+ const defaultSchedule = "0 * * * *";
13
+ const cronSchedule = config.scheduledTasks?.clientListScheduler ? config.scheduledTasks.clientListScheduler.schedule ? config.scheduledTasks.clientListScheduler.schedule : defaultSchedule : defaultSchedule;
14
+ const job = new cron.CronJob(cronSchedule, async () => {
15
+ const taskRunning = await util.checkIfTaskIsRunning(
16
+ types.ScheduledTaskNames.GetClientList,
17
+ env$1.getDb()
18
+ );
19
+ env$1.logger.info(
20
+ `${types.ScheduledTaskNames.GetClientList} task running: ${taskRunning}`
21
+ );
22
+ if (!taskRunning) {
23
+ env$1.logger.info(`${types.ScheduledTaskNames.GetClientList} task....`);
24
+ await tasks$1.clientTaskManager.getClientList().catch((err) => {
25
+ env$1.logger.error(err);
26
+ });
27
+ }
28
+ });
29
+ job.start();
30
+ }
31
+ exports.getClientList = getClientList;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const database = require("@prosopo/database");
4
+ const types = require("@prosopo/types");
5
+ class ClientTaskManager {
6
+ constructor(config, logger, db) {
7
+ this.config = config;
8
+ this.logger = logger;
9
+ this.providerDB = db;
10
+ }
11
+ /**
12
+ * @description Store commitments externally in the database
13
+ * @returns Promise<void>
14
+ */
15
+ async storeCommitmentsExternal() {
16
+ if (!this.config.mongoCaptchaUri) {
17
+ this.logger.info("Mongo env not set");
18
+ return;
19
+ }
20
+ const lastTask = await this.providerDB.getLastScheduledTaskStatus(
21
+ types.ScheduledTaskNames.StoreCommitmentsExternal,
22
+ types.ScheduledTaskStatus.Completed
23
+ );
24
+ const taskID = await this.providerDB.createScheduledTaskStatus(
25
+ types.ScheduledTaskNames.StoreCommitmentsExternal,
26
+ types.ScheduledTaskStatus.Running
27
+ );
28
+ try {
29
+ let commitments = await this.providerDB.getUnstoredDappUserCommitments();
30
+ let powRecords = await this.providerDB.getUnstoredDappUserPoWCommitments();
31
+ if (lastTask) {
32
+ this.logger.info(
33
+ `Filtering records to only get updated records: ${JSON.stringify(lastTask)}`
34
+ );
35
+ this.logger.info(
36
+ "Last task ran at ",
37
+ new Date(lastTask.updated || 0),
38
+ "Task ID",
39
+ taskID
40
+ );
41
+ commitments = commitments.filter(
42
+ (commitment) => lastTask.updated && commitment.lastUpdatedTimestamp && (commitment.lastUpdatedTimestamp > lastTask.updated || !commitment.lastUpdatedTimestamp)
43
+ );
44
+ powRecords = powRecords.filter((commitment) => {
45
+ return lastTask.updated && commitment.lastUpdatedTimestamp && // either the update stamp is more recent than the last time this task ran or there is no update stamp,
46
+ // so it is a new record
47
+ (commitment.lastUpdatedTimestamp > lastTask.updated || !commitment.lastUpdatedTimestamp);
48
+ });
49
+ }
50
+ if (commitments.length || powRecords.length) {
51
+ this.logger.info(
52
+ `Storing ${commitments.length} commitments externally`
53
+ );
54
+ this.logger.info(
55
+ `Storing ${powRecords.length} pow challenges externally`
56
+ );
57
+ const captchaDB = new database.CaptchaDatabase(
58
+ this.config.mongoCaptchaUri,
59
+ void 0,
60
+ void 0,
61
+ this.logger
62
+ );
63
+ await captchaDB.saveCaptchas(commitments, powRecords);
64
+ await this.providerDB.markDappUserCommitmentsStored(
65
+ commitments.map((commitment) => commitment.id)
66
+ );
67
+ await this.providerDB.markDappUserPoWCommitmentsStored(
68
+ powRecords.map((powRecords2) => powRecords2.challenge)
69
+ );
70
+ }
71
+ await this.providerDB.updateScheduledTaskStatus(
72
+ taskID,
73
+ types.ScheduledTaskStatus.Completed,
74
+ {
75
+ data: {
76
+ commitments: commitments.map((c) => c.id),
77
+ powRecords: powRecords.map((pr) => pr.challenge)
78
+ }
79
+ }
80
+ );
81
+ } catch (e) {
82
+ this.logger.error(e);
83
+ await this.providerDB.updateScheduledTaskStatus(
84
+ taskID,
85
+ types.ScheduledTaskStatus.Failed,
86
+ { error: String(e) }
87
+ );
88
+ }
89
+ }
90
+ /**
91
+ * @description Get a list of client accounts and their settings from the client database
92
+ * @returns Promise<void>
93
+ */
94
+ async getClientList() {
95
+ if (!this.config.mongoClientUri) {
96
+ this.logger.info("Mongo env not set");
97
+ return;
98
+ }
99
+ const lastTask = await this.providerDB.getLastScheduledTaskStatus(
100
+ types.ScheduledTaskNames.GetClientList,
101
+ types.ScheduledTaskStatus.Completed
102
+ );
103
+ const taskID = await this.providerDB.createScheduledTaskStatus(
104
+ types.ScheduledTaskNames.GetClientList,
105
+ types.ScheduledTaskStatus.Running
106
+ );
107
+ try {
108
+ const clientDB = new database.ClientDatabase(
109
+ this.config.mongoClientUri,
110
+ void 0,
111
+ // expected to come from URI
112
+ void 0,
113
+ // expected to come from URI
114
+ this.logger
115
+ );
116
+ const updatedAtTimestamp = lastTask ? lastTask.updated || 0 : 0;
117
+ console.log("updatedAtTimestamp", updatedAtTimestamp);
118
+ const newClientRecords = await clientDB.getUpdatedClients(updatedAtTimestamp);
119
+ if (newClientRecords) {
120
+ await this.providerDB.updateClientRecords(newClientRecords);
121
+ }
122
+ await this.providerDB.updateScheduledTaskStatus(
123
+ taskID,
124
+ types.ScheduledTaskStatus.Completed,
125
+ {
126
+ data: {
127
+ clientRecords: newClientRecords.map((c) => c.account)
128
+ }
129
+ }
130
+ );
131
+ } catch (e) {
132
+ this.logger.error(e);
133
+ await this.providerDB.updateScheduledTaskStatus(
134
+ taskID,
135
+ types.ScheduledTaskStatus.Failed,
136
+ { error: String(e) }
137
+ );
138
+ }
139
+ }
140
+ async registerSiteKey(siteKey) {
141
+ await this.providerDB.updateClientRecords([
142
+ {
143
+ account: siteKey
144
+ }
145
+ ]);
146
+ }
147
+ }
148
+ exports.ClientTaskManager = ClientTaskManager;
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const datasets = require("@prosopo/datasets");
4
- const types = require("@prosopo/types");
5
4
  const datasetTasksUtils = require("./datasetTasksUtils.cjs");
6
- const database = require("@prosopo/database");
7
5
  class DatasetManager {
8
6
  constructor(config, logger, captchaConfig, db) {
9
7
  this.config = config;
@@ -28,98 +26,5 @@ class DatasetManager {
28
26
  );
29
27
  await this.db?.storeDataset(dataset);
30
28
  }
31
- /**
32
- * @description Save captcha user events to external db
33
- *
34
- * **Note:** This is only used in development mode
35
- *
36
- * @param events
37
- * @param accountId
38
- * @returns
39
- */
40
- async saveCaptchaEvent(events, accountId) {
41
- if (!this.config.devOnlyWatchEvents || !this.config.mongoEventsUri) {
42
- this.logger.info("Dev watch events not set to true, not saving events");
43
- return;
44
- }
45
- await database.saveCaptchaEvent(events, accountId, this.config.mongoEventsUri);
46
- }
47
- /**
48
- * @description Store commitments externally in the database
49
- * @returns
50
- */
51
- async storeCommitmentsExternal() {
52
- if (!this.config.mongoCaptchaUri) {
53
- this.logger.info("Mongo env not set");
54
- return;
55
- }
56
- const lastTask = await this.db.getLastScheduledTaskStatus(
57
- types.ScheduledTaskNames.StoreCommitmentsExternal,
58
- types.ScheduledTaskStatus.Completed
59
- );
60
- const taskID = await this.db.createScheduledTaskStatus(
61
- types.ScheduledTaskNames.StoreCommitmentsExternal,
62
- types.ScheduledTaskStatus.Running
63
- );
64
- try {
65
- let commitments = await this.db.getUnstoredDappUserCommitments();
66
- let powRecords = await this.db.getUnstoredDappUserPoWCommitments();
67
- if (lastTask) {
68
- this.logger.info(
69
- `Filtering records to only get updated records: ${JSON.stringify(lastTask)}`
70
- );
71
- this.logger.info(
72
- "Last task ran at ",
73
- new Date(lastTask.updated || 0),
74
- "Task ID",
75
- taskID
76
- );
77
- commitments = commitments.filter(
78
- (commitment) => lastTask.updated && commitment.lastUpdatedTimestamp && (commitment.lastUpdatedTimestamp > lastTask.updated || !commitment.lastUpdatedTimestamp)
79
- );
80
- powRecords = powRecords.filter((commitment) => {
81
- return lastTask.updated && commitment.lastUpdatedTimestamp && // either the update stamp is more recent than the last time this task ran or there is no update stamp,
82
- // so it is a new record
83
- (commitment.lastUpdatedTimestamp > lastTask.updated || !commitment.lastUpdatedTimestamp);
84
- });
85
- }
86
- if (commitments.length || powRecords.length) {
87
- this.logger.info(
88
- `Storing ${commitments.length} commitments externally`
89
- );
90
- this.logger.info(
91
- `Storing ${powRecords.length} pow challenges externally`
92
- );
93
- await database.saveCaptchas(
94
- commitments,
95
- powRecords,
96
- this.config.mongoCaptchaUri
97
- );
98
- await this.db.markDappUserCommitmentsStored(
99
- commitments.map((commitment) => commitment.id)
100
- );
101
- await this.db.markDappUserPoWCommitmentsStored(
102
- powRecords.map((powRecords2) => powRecords2.challenge)
103
- );
104
- }
105
- await this.db.updateScheduledTaskStatus(
106
- taskID,
107
- types.ScheduledTaskStatus.Completed,
108
- {
109
- data: {
110
- commitments: commitments.map((c) => c.id),
111
- powRecords: powRecords.map((pr) => pr.challenge)
112
- }
113
- }
114
- );
115
- } catch (e) {
116
- this.logger.error(e);
117
- await this.db.updateScheduledTaskStatus(
118
- taskID,
119
- types.ScheduledTaskStatus.Failed,
120
- { error: e.toString() }
121
- );
122
- }
123
- }
124
29
  }
125
30
  exports.DatasetManager = DatasetManager;
@@ -29,7 +29,7 @@ class ImgCaptchaManager {
29
29
  }
30
30
  return captchaDocs;
31
31
  }
32
- async getRandomCaptchasAndRequestHash(datasetId, userAccount, ipAddress) {
32
+ async getRandomCaptchasAndRequestHash(datasetId, userAccount, ipAddress, headers) {
33
33
  const dataset = await this.db.getDatasetDetails(datasetId);
34
34
  if (!dataset) {
35
35
  throw new common.ProsopoEnvError("DATABASE.DATASET_GET_FAILED", {
@@ -78,7 +78,8 @@ class ImgCaptchaManager {
78
78
  salt,
79
79
  deadlineTs,
80
80
  currentTime,
81
- ipAddress
81
+ ipAddress,
82
+ headers
82
83
  );
83
84
  return {
84
85
  captchas,
@@ -97,9 +98,10 @@ class ImgCaptchaManager {
97
98
  * @param timestamp
98
99
  * @param providerRequestHashSignature
99
100
  * @param ipAddress
101
+ * @param headers
100
102
  * @return {Promise<DappUserSolutionResult>} result containing the contract event
101
103
  */
102
- async dappUserSolution(userAccount, dappAccount, requestHash, captchas, userRequestHashSignature, timestamp, providerRequestHashSignature, ipAddress) {
104
+ async dappUserSolution(userAccount, dappAccount, requestHash, captchas, userRequestHashSignature, timestamp, providerRequestHashSignature, ipAddress, headers) {
103
105
  const verification = utilCrypto.signatureVerify(
104
106
  util$1.stringToHex(requestHash),
105
107
  userRequestHashSignature,
@@ -159,7 +161,8 @@ class ImgCaptchaManager {
159
161
  userSubmitted: true,
160
162
  serverChecked: false,
161
163
  requestedAtTimestamp: timestamp,
162
- ipAddress
164
+ ipAddress,
165
+ headers
163
166
  };
164
167
  await this.db.storeDappUserSolution(receivedCaptchas, commit);
165
168
  if (datasets.compareCaptchaSolutions(receivedCaptchas, storedCaptchas)) {
@@ -41,8 +41,9 @@ class PowCaptchaManager {
41
41
  * @param {number} timeout - the time in milliseconds since the Provider was selected to provide the PoW captcha
42
42
  * @param {string} userTimestampSignature
43
43
  * @param ipAddress
44
+ * @param headers
44
45
  */
45
- async verifyPowCaptchaSolution(challenge, difficulty, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress) {
46
+ async verifyPowCaptchaSolution(challenge, difficulty, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress, headers) {
46
47
  powTasksUtils.checkPowSignature(
47
48
  challenge,
48
49
  providerChallengeSignature,
@@ -50,7 +51,7 @@ class PowCaptchaManager {
50
51
  types.ApiParams.challenge
51
52
  );
52
53
  const challengeSplit = challenge.split(this.POW_SEPARATOR);
53
- const timestamp = parseInt(util$1.at(challengeSplit, 0));
54
+ const timestamp = Number.parseInt(util$1.at(challengeSplit, 0));
54
55
  const userAccount = util$1.at(challengeSplit, 1);
55
56
  powTasksUtils.checkPowSignature(
56
57
  timestamp.toString(),
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const common = require("@prosopo/common");
4
+ const clientTasks = require("./client/clientTasks.cjs");
4
5
  const datasetTasks = require("./dataset/datasetTasks.cjs");
5
6
  const imgCaptchaTasks = require("./imgCaptcha/imgCaptchaTasks.cjs");
6
7
  const powTasks = require("./powCaptcha/powTasks.cjs");
@@ -29,6 +30,11 @@ class Tasks {
29
30
  this.logger,
30
31
  this.captchaConfig
31
32
  );
33
+ this.clientTaskManager = new clientTasks.ClientTaskManager(
34
+ this.config,
35
+ this.logger,
36
+ this.db
37
+ );
32
38
  }
33
39
  }
34
40
  exports.Tasks = Tasks;
package/dist/index.d.ts CHANGED
@@ -4,5 +4,6 @@ export * from "./api/captcha.js";
4
4
  export * from "./api/verify.js";
5
5
  export * from "./api/admin.js";
6
6
  export * from "./api/errorHandler.js";
7
- export * from "./api/captchaScheduler.js";
7
+ export * from "./schedulers/captchaScheduler.js";
8
+ export * from "./schedulers/getClientList.js";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC"}
package/dist/index.js CHANGED
@@ -4,5 +4,6 @@ export * from "./api/captcha.js";
4
4
  export * from "./api/verify.js";
5
5
  export * from "./api/admin.js";
6
6
  export * from "./api/errorHandler.js";
7
- export * from "./api/captchaScheduler.js";
7
+ export * from "./schedulers/captchaScheduler.js";
8
+ export * from "./schedulers/getClientList.js";
8
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC"}
@@ -1,4 +1,4 @@
1
1
  import type { KeyringPair } from "@polkadot/keyring/types";
2
- import { ProsopoConfigOutput } from "@prosopo/types";
2
+ import { type ProsopoConfigOutput } from "@prosopo/types";
3
3
  export declare function storeCaptchasExternally(pair: KeyringPair, config: ProsopoConfigOutput): Promise<void>;
4
4
  //# sourceMappingURL=captchaScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captchaScheduler.d.ts","sourceRoot":"","sources":["../../src/schedulers/captchaScheduler.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,gBAAgB,CAAC;AAK9E,wBAAsB,uBAAuB,CAC5C,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,mBAAmB,iBAkC3B"}
@@ -8,9 +8,9 @@ export async function storeCaptchasExternally(pair, config) {
8
8
  await env.isReady();
9
9
  const tasks = new Tasks(env);
10
10
  const defaultSchedule = "0 * * * *";
11
- const cronSchedule = config.captchaScheduler
12
- ? config.captchaScheduler.schedule
13
- ? config.captchaScheduler.schedule
11
+ const cronSchedule = config.scheduledTasks?.captchaScheduler
12
+ ? config.scheduledTasks.captchaScheduler.schedule
13
+ ? config.scheduledTasks.captchaScheduler.schedule
14
14
  : defaultSchedule
15
15
  : defaultSchedule;
16
16
  const job = new CronJob(cronSchedule, async () => {
@@ -18,7 +18,7 @@ export async function storeCaptchasExternally(pair, config) {
18
18
  env.logger.info(`${ScheduledTaskNames.StoreCommitmentsExternal} task running: ${taskRunning}`);
19
19
  if (!taskRunning) {
20
20
  env.logger.info(`${ScheduledTaskNames.StoreCommitmentsExternal} task....`);
21
- await tasks.datasetManager.storeCommitmentsExternal().catch((err) => {
21
+ await tasks.clientTaskManager.storeCommitmentsExternal().catch((err) => {
22
22
  env.logger.error(err);
23
23
  });
24
24
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captchaScheduler.js","sourceRoot":"","sources":["../../src/schedulers/captchaScheduler.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAA4B,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC5C,IAAiB,EACjB,MAA2B;IAE3B,MAAM,GAAG,GAAG,IAAI,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;IAEpB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IAG7B,MAAM,eAAe,GAAG,WAAW,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,EAAE,gBAAgB;QAC3D,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,QAAQ;YAChD,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,QAAQ;YACjD,CAAC,CAAC,eAAe;QAClB,CAAC,CAAC,eAAe,CAAC;IAEnB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAC7C,kBAAkB,CAAC,wBAAwB,EAC3C,GAAG,CAAC,KAAK,EAAE,CACX,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,IAAI,CACd,GAAG,kBAAkB,CAAC,wBAAwB,kBAAkB,WAAW,EAAE,CAC7E,CAAC;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,GAAG,CAAC,MAAM,CAAC,IAAI,CACd,GAAG,kBAAkB,CAAC,wBAAwB,WAAW,CACzD,CAAC;YACF,MAAM,KAAK,CAAC,iBAAiB,CAAC,wBAAwB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACtE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACJ,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,EAAE,CAAC;AACb,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { KeyringPair } from "@polkadot/keyring/types";
2
+ import { type ProsopoConfigOutput } from "@prosopo/types";
3
+ export declare function getClientList(pair: KeyringPair, config: ProsopoConfigOutput): Promise<void>;
4
+ //# sourceMappingURL=getClientList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getClientList.d.ts","sourceRoot":"","sources":["../../src/schedulers/getClientList.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,gBAAgB,CAAC;AAU9E,wBAAsB,aAAa,CAClC,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,mBAAmB,iBAgC3B"}