@digitaldefiance/node-express-suite 3.7.4 → 3.7.5

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 (878) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +4 -5
  3. package/src/__tests__/fixtures/{index.d.ts → index.ts} +0 -1
  4. package/src/__tests__/fixtures/model-mocks.mock.ts +164 -0
  5. package/src/__tests__/helpers/application.mock.ts +89 -0
  6. package/src/__tests__/helpers/{index.d.ts → index.ts} +0 -1
  7. package/src/__tests__/helpers/setup-test-env.ts +202 -0
  8. package/src/__tests__/{index.d.ts → index.ts} +0 -1
  9. package/src/application-base.ts +548 -0
  10. package/src/application-concrete.ts +62 -0
  11. package/src/application.ts +330 -0
  12. package/src/backup-code.ts +348 -0
  13. package/src/builders/application-builder.ts +147 -0
  14. package/src/builders/{index.d.ts → index.ts} +0 -1
  15. package/src/constants.ts +89 -0
  16. package/src/container/{index.d.ts → index.ts} +0 -1
  17. package/src/container/service-container.ts +85 -0
  18. package/src/container/service-definitions.ts +23 -0
  19. package/src/controllers/base.ts +512 -0
  20. package/src/controllers/{index.d.ts → index.ts} +0 -1
  21. package/src/controllers/user.ts +1734 -0
  22. package/src/database/database-initializer.ts +13 -0
  23. package/src/database/{index.d.ts → index.ts} +0 -1
  24. package/src/decorators/base-controller.ts +91 -0
  25. package/src/decorators/controller.ts +152 -0
  26. package/src/decorators/{index.d.ts → index.ts} +0 -1
  27. package/src/decorators/zod-validation.ts +64 -0
  28. package/src/defaults.ts +259 -0
  29. package/src/documents/base.ts +17 -0
  30. package/src/documents/email-token.ts +20 -0
  31. package/src/documents/{index.d.ts → index.ts} +0 -1
  32. package/src/documents/mnemonic.ts +20 -0
  33. package/src/documents/role.ts +19 -0
  34. package/src/documents/used-direct-login-token.ts +18 -0
  35. package/src/documents/user-role.ts +20 -0
  36. package/src/documents/user.ts +20 -0
  37. package/src/enumerations/base-model-name.ts +47 -0
  38. package/src/enumerations/{index.d.ts → index.ts} +0 -1
  39. package/src/enumerations/length-encoding-type.ts +16 -0
  40. package/src/enumerations/schema-collection.ts +39 -0
  41. package/src/enumerations/symmetric-error-type.ts +13 -0
  42. package/src/environment.ts +859 -0
  43. package/src/errors/express-validation.ts +38 -0
  44. package/src/errors/{index.d.ts → index.ts} +0 -1
  45. package/src/errors/invalid-backup-code-version.ts +30 -0
  46. package/src/errors/invalid-jwt-token.ts +24 -0
  47. package/src/errors/invalid-model.ts +24 -0
  48. package/src/errors/invalid-new-password.ts +33 -0
  49. package/src/errors/invalid-password.ts +28 -0
  50. package/src/errors/missing-validated-data.ts +55 -0
  51. package/src/errors/mnemonic-or-password-required.ts +26 -0
  52. package/src/errors/model-not-registered.ts +24 -0
  53. package/src/errors/mongoose-validation.ts +56 -0
  54. package/src/errors/symmetric.ts +53 -0
  55. package/src/errors/token-expired.ts +24 -0
  56. package/src/get-language.ts +64 -0
  57. package/src/get-timezone.ts +76 -0
  58. package/src/{index.d.ts → index.ts} +44 -2
  59. package/src/interfaces/api-error-response.ts +15 -0
  60. package/src/interfaces/api-express-validation-error-response.ts +17 -0
  61. package/src/interfaces/api-message-response.ts +12 -0
  62. package/src/interfaces/api-mongo-validation-error-response.ts +17 -0
  63. package/src/interfaces/api-responses/backup-codes-response.ts +15 -0
  64. package/src/interfaces/api-responses/challenge-response.ts +17 -0
  65. package/src/interfaces/api-responses/code-count-response.ts +12 -0
  66. package/src/interfaces/api-responses/{index.d.ts → index.ts} +0 -1
  67. package/src/interfaces/api-responses/login-response.ts +18 -0
  68. package/src/interfaces/api-responses/mnemonic-response.ts +15 -0
  69. package/src/interfaces/api-responses/registration-response.ts +17 -0
  70. package/src/interfaces/api-responses/request-user-response.ts +16 -0
  71. package/src/interfaces/api-responses/user-settings-response.ts +19 -0
  72. package/src/interfaces/application.ts +40 -0
  73. package/src/interfaces/backend-objects/email-token.ts +18 -0
  74. package/src/interfaces/backend-objects/{index.d.ts → index.ts} +0 -1
  75. package/src/interfaces/backend-objects/request-user.ts +19 -0
  76. package/src/interfaces/backend-objects/role.ts +18 -0
  77. package/src/interfaces/backend-objects/user.ts +18 -0
  78. package/src/interfaces/checksum-config.ts +15 -0
  79. package/src/interfaces/checksum-consts.ts +23 -0
  80. package/src/interfaces/constants.ts +114 -0
  81. package/src/interfaces/controller-config.ts +54 -0
  82. package/src/interfaces/create-user-basics.ts +24 -0
  83. package/src/interfaces/csp-config.ts +32 -0
  84. package/src/interfaces/csp-definition.ts +71 -0
  85. package/src/interfaces/db-init-result.ts +17 -0
  86. package/src/interfaces/deep-partial.ts +14 -0
  87. package/src/interfaces/discriminator-collections.ts +21 -0
  88. package/src/interfaces/email-service.ts +26 -0
  89. package/src/interfaces/environment-mongo.ts +86 -0
  90. package/src/interfaces/environment.ts +191 -0
  91. package/src/interfaces/failable-result.ts +20 -0
  92. package/src/interfaces/fec-consts.ts +14 -0
  93. package/src/interfaces/flexible-csp.ts +35 -0
  94. package/src/interfaces/handleable-error-options.ts +19 -0
  95. package/src/interfaces/{index.d.ts → index.ts} +0 -1
  96. package/src/interfaces/jwt-consts.ts +33 -0
  97. package/src/interfaces/jwt-sign-response.ts +31 -0
  98. package/src/interfaces/models/email-token.ts +13 -0
  99. package/src/interfaces/models/{index.d.ts → index.ts} +0 -1
  100. package/src/interfaces/models/mnemonic.ts +14 -0
  101. package/src/interfaces/models/role.ts +13 -0
  102. package/src/interfaces/models/token-role.ts +23 -0
  103. package/src/interfaces/models/used-direct-login-token.ts +21 -0
  104. package/src/interfaces/models/user-role.ts +23 -0
  105. package/src/interfaces/models/user.ts +30 -0
  106. package/src/interfaces/mongo-errors.ts +14 -0
  107. package/src/interfaces/request-user.ts +80 -0
  108. package/src/interfaces/required-string-keys.ts +33 -0
  109. package/src/interfaces/schema.ts +43 -0
  110. package/src/interfaces/server-init-result.ts +48 -0
  111. package/src/interfaces/status-code-response.ts +20 -0
  112. package/src/interfaces/symmetric-encryption-results.d.ts.map +1 -1
  113. package/src/interfaces/symmetric-encryption-results.js.map +1 -1
  114. package/src/interfaces/symmetric-encryption-results.ts +15 -0
  115. package/src/interfaces/test-environment.ts +23 -0
  116. package/src/interfaces/token-response.ts +16 -0
  117. package/src/middleware-utils.ts +138 -0
  118. package/src/middlewares/authenticate-crypto.ts +237 -0
  119. package/src/middlewares/authenticate-token.ts +165 -0
  120. package/src/middlewares/cleanup-crypto.ts +47 -0
  121. package/src/middlewares/{index.d.ts → index.ts} +0 -1
  122. package/src/middlewares/set-global-context-language.ts +38 -0
  123. package/src/model-registry.ts +142 -0
  124. package/src/models/email-token.ts +49 -0
  125. package/src/models/{index.d.ts → index.ts} +0 -1
  126. package/src/models/mnemonic.ts +42 -0
  127. package/src/models/role.ts +38 -0
  128. package/src/models/used-direct-login-token.ts +49 -0
  129. package/src/models/user-role.ts +40 -0
  130. package/src/models/user.ts +42 -0
  131. package/src/pipeline/{index.d.ts → index.ts} +0 -1
  132. package/src/pipeline/pipeline-builder.ts +27 -0
  133. package/src/plugins/{index.d.ts → index.ts} +0 -1
  134. package/src/plugins/plugin-interface.ts +19 -0
  135. package/src/plugins/plugin-manager.ts +53 -0
  136. package/src/registry/email-service-registry.ts +76 -0
  137. package/src/registry/{index.d.ts → index.ts} +0 -1
  138. package/src/responses/{index.d.ts → index.ts} +0 -1
  139. package/src/responses/response-builder.ts +166 -0
  140. package/src/routers/api.ts +233 -0
  141. package/src/routers/app.ts +395 -0
  142. package/src/routers/base.ts +34 -0
  143. package/src/routers/{index.d.ts → index.ts} +0 -1
  144. package/src/routers/router-config.ts +34 -0
  145. package/src/routing/index.ts +1 -0
  146. package/src/routing/route-builder.ts +214 -0
  147. package/src/schemas/email-token.ts +112 -0
  148. package/src/schemas/{index.d.ts → index.ts} +0 -1
  149. package/src/schemas/mnemonic.ts +48 -0
  150. package/src/schemas/role.ts +153 -0
  151. package/src/schemas/schema.ts +185 -0
  152. package/src/schemas/used-direct-login-token.ts +58 -0
  153. package/src/schemas/user-role.ts +93 -0
  154. package/src/schemas/user.ts +244 -0
  155. package/src/services/backup-code.ts +327 -0
  156. package/src/services/base.ts +46 -0
  157. package/src/services/checksum.ts +189 -0
  158. package/src/services/database-initialization.ts +1653 -0
  159. package/src/services/db-init-cache.ts +28 -0
  160. package/src/services/direct-login-token.ts +83 -0
  161. package/src/services/dummy-email-service.ts +43 -0
  162. package/src/services/fec-usage-example.ts +123 -0
  163. package/src/services/fec.ts +399 -0
  164. package/src/services/{index.d.ts → index.ts} +0 -1
  165. package/src/services/jwt.ts +146 -0
  166. package/src/services/key-wrapping.ts +528 -0
  167. package/src/services/mnemonic.ts +174 -0
  168. package/src/services/request-user.ts +127 -0
  169. package/src/services/role.ts +417 -0
  170. package/src/services/symmetric.ts +164 -0
  171. package/src/services/system-user.ts +87 -0
  172. package/src/services/user.ts +2324 -0
  173. package/src/services/xor.ts +39 -0
  174. package/src/testing.ts +9 -0
  175. package/src/transactions/{index.d.ts → index.ts} +0 -1
  176. package/src/transactions/transaction-manager.ts +63 -0
  177. package/src/types/app-config.ts +36 -0
  178. package/src/types/controller-config.ts +28 -0
  179. package/src/types/{environment-variables.d.ts → environment-variables.ts} +32 -5
  180. package/src/types/{index.d.ts → index.ts} +0 -1
  181. package/src/types/{mongoose-helpers.d.ts → mongoose-helpers.ts} +8 -2
  182. package/src/types/mongoose-override.d.ts +1 -0
  183. package/src/types/mongoose.d.ts +1 -0
  184. package/src/types.ts +189 -0
  185. package/src/utils.ts +1116 -0
  186. package/src/validation/{index.d.ts → index.ts} +0 -1
  187. package/src/validation/validation-builder.ts +155 -0
  188. package/src/__tests__/fixtures/index.d.ts.map +0 -1
  189. package/src/__tests__/fixtures/index.js +0 -5
  190. package/src/__tests__/fixtures/index.js.map +0 -1
  191. package/src/__tests__/fixtures/model-mocks.mock.d.ts +0 -12
  192. package/src/__tests__/fixtures/model-mocks.mock.d.ts.map +0 -1
  193. package/src/__tests__/fixtures/model-mocks.mock.js +0 -102
  194. package/src/__tests__/fixtures/model-mocks.mock.js.map +0 -1
  195. package/src/__tests__/helpers/application.mock.d.ts +0 -8
  196. package/src/__tests__/helpers/application.mock.d.ts.map +0 -1
  197. package/src/__tests__/helpers/application.mock.js +0 -77
  198. package/src/__tests__/helpers/application.mock.js.map +0 -1
  199. package/src/__tests__/helpers/index.d.ts.map +0 -1
  200. package/src/__tests__/helpers/index.js +0 -7
  201. package/src/__tests__/helpers/index.js.map +0 -1
  202. package/src/__tests__/helpers/setup-test-env.d.ts +0 -12
  203. package/src/__tests__/helpers/setup-test-env.d.ts.map +0 -1
  204. package/src/__tests__/helpers/setup-test-env.js +0 -121
  205. package/src/__tests__/helpers/setup-test-env.js.map +0 -1
  206. package/src/__tests__/index.d.ts.map +0 -1
  207. package/src/__tests__/index.js +0 -6
  208. package/src/__tests__/index.js.map +0 -1
  209. package/src/application-base.d.ts +0 -123
  210. package/src/application-base.d.ts.map +0 -1
  211. package/src/application-base.js +0 -359
  212. package/src/application-base.js.map +0 -1
  213. package/src/application-concrete.d.ts +0 -13
  214. package/src/application-concrete.d.ts.map +0 -1
  215. package/src/application-concrete.js +0 -21
  216. package/src/application-concrete.js.map +0 -1
  217. package/src/application.d.ts +0 -29
  218. package/src/application.d.ts.map +0 -1
  219. package/src/application.js +0 -167
  220. package/src/application.js.map +0 -1
  221. package/src/backup-code.d.ts +0 -67
  222. package/src/backup-code.d.ts.map +0 -1
  223. package/src/backup-code.js +0 -238
  224. package/src/backup-code.js.map +0 -1
  225. package/src/builders/application-builder.d.ts +0 -35
  226. package/src/builders/application-builder.d.ts.map +0 -1
  227. package/src/builders/application-builder.js +0 -64
  228. package/src/builders/application-builder.js.map +0 -1
  229. package/src/builders/index.d.ts.map +0 -1
  230. package/src/builders/index.js +0 -5
  231. package/src/builders/index.js.map +0 -1
  232. package/src/constants.d.ts +0 -16
  233. package/src/constants.d.ts.map +0 -1
  234. package/src/constants.js +0 -58
  235. package/src/constants.js.map +0 -1
  236. package/src/container/index.d.ts.map +0 -1
  237. package/src/container/index.js +0 -6
  238. package/src/container/index.js.map +0 -1
  239. package/src/container/service-container.d.ts +0 -11
  240. package/src/container/service-container.d.ts.map +0 -1
  241. package/src/container/service-container.js +0 -38
  242. package/src/container/service-container.js.map +0 -1
  243. package/src/container/service-definitions.d.ts +0 -11
  244. package/src/container/service-definitions.d.ts.map +0 -1
  245. package/src/container/service-definitions.js +0 -13
  246. package/src/container/service-definitions.js.map +0 -1
  247. package/src/controllers/base.d.ts +0 -67
  248. package/src/controllers/base.d.ts.map +0 -1
  249. package/src/controllers/base.js +0 -305
  250. package/src/controllers/base.js.map +0 -1
  251. package/src/controllers/index.d.ts.map +0 -1
  252. package/src/controllers/index.js +0 -6
  253. package/src/controllers/index.js.map +0 -1
  254. package/src/controllers/user.d.ts +0 -49
  255. package/src/controllers/user.d.ts.map +0 -1
  256. package/src/controllers/user.js +0 -919
  257. package/src/controllers/user.js.map +0 -1
  258. package/src/database/database-initializer.d.ts +0 -7
  259. package/src/database/database-initializer.d.ts.map +0 -1
  260. package/src/database/database-initializer.js +0 -3
  261. package/src/database/database-initializer.js.map +0 -1
  262. package/src/database/index.d.ts.map +0 -1
  263. package/src/database/index.js +0 -5
  264. package/src/database/index.js.map +0 -1
  265. package/src/decorators/base-controller.d.ts +0 -11
  266. package/src/decorators/base-controller.d.ts.map +0 -1
  267. package/src/decorators/base-controller.js +0 -60
  268. package/src/decorators/base-controller.js.map +0 -1
  269. package/src/decorators/controller.d.ts +0 -38
  270. package/src/decorators/controller.d.ts.map +0 -1
  271. package/src/decorators/controller.js +0 -68
  272. package/src/decorators/controller.js.map +0 -1
  273. package/src/decorators/index.d.ts.map +0 -1
  274. package/src/decorators/index.js +0 -7
  275. package/src/decorators/index.js.map +0 -1
  276. package/src/decorators/zod-validation.d.ts +0 -5
  277. package/src/decorators/zod-validation.d.ts.map +0 -1
  278. package/src/decorators/zod-validation.js +0 -48
  279. package/src/decorators/zod-validation.js.map +0 -1
  280. package/src/defaults.d.ts +0 -7
  281. package/src/defaults.d.ts.map +0 -1
  282. package/src/defaults.js +0 -205
  283. package/src/defaults.js.map +0 -1
  284. package/src/documents/base.d.ts +0 -4
  285. package/src/documents/base.d.ts.map +0 -1
  286. package/src/documents/base.js +0 -3
  287. package/src/documents/base.js.map +0 -1
  288. package/src/documents/email-token.d.ts +0 -8
  289. package/src/documents/email-token.d.ts.map +0 -1
  290. package/src/documents/email-token.js +0 -3
  291. package/src/documents/email-token.js.map +0 -1
  292. package/src/documents/index.d.ts.map +0 -1
  293. package/src/documents/index.js +0 -3
  294. package/src/documents/index.js.map +0 -1
  295. package/src/documents/mnemonic.d.ts +0 -8
  296. package/src/documents/mnemonic.d.ts.map +0 -1
  297. package/src/documents/mnemonic.js +0 -3
  298. package/src/documents/mnemonic.js.map +0 -1
  299. package/src/documents/role.d.ts +0 -8
  300. package/src/documents/role.d.ts.map +0 -1
  301. package/src/documents/role.js +0 -3
  302. package/src/documents/role.js.map +0 -1
  303. package/src/documents/used-direct-login-token.d.ts +0 -5
  304. package/src/documents/used-direct-login-token.d.ts.map +0 -1
  305. package/src/documents/used-direct-login-token.js +0 -3
  306. package/src/documents/used-direct-login-token.js.map +0 -1
  307. package/src/documents/user-role.d.ts +0 -8
  308. package/src/documents/user-role.d.ts.map +0 -1
  309. package/src/documents/user-role.js +0 -3
  310. package/src/documents/user-role.js.map +0 -1
  311. package/src/documents/user.d.ts +0 -8
  312. package/src/documents/user.d.ts.map +0 -1
  313. package/src/documents/user.js +0 -3
  314. package/src/documents/user.js.map +0 -1
  315. package/src/enumerations/base-model-name.d.ts +0 -38
  316. package/src/enumerations/base-model-name.d.ts.map +0 -1
  317. package/src/enumerations/base-model-name.js +0 -34
  318. package/src/enumerations/base-model-name.js.map +0 -1
  319. package/src/enumerations/index.d.ts.map +0 -1
  320. package/src/enumerations/index.js +0 -8
  321. package/src/enumerations/index.js.map +0 -1
  322. package/src/enumerations/length-encoding-type.d.ts +0 -7
  323. package/src/enumerations/length-encoding-type.d.ts.map +0 -1
  324. package/src/enumerations/length-encoding-type.js +0 -11
  325. package/src/enumerations/length-encoding-type.js.map +0 -1
  326. package/src/enumerations/schema-collection.d.ts +0 -34
  327. package/src/enumerations/schema-collection.d.ts.map +0 -1
  328. package/src/enumerations/schema-collection.js +0 -38
  329. package/src/enumerations/schema-collection.js.map +0 -1
  330. package/src/enumerations/symmetric-error-type.d.ts +0 -5
  331. package/src/enumerations/symmetric-error-type.d.ts.map +0 -1
  332. package/src/enumerations/symmetric-error-type.js +0 -9
  333. package/src/enumerations/symmetric-error-type.js.map +0 -1
  334. package/src/environment.d.ts +0 -189
  335. package/src/environment.d.ts.map +0 -1
  336. package/src/environment.js +0 -641
  337. package/src/environment.js.map +0 -1
  338. package/src/errors/express-validation.d.ts +0 -9
  339. package/src/errors/express-validation.d.ts.map +0 -1
  340. package/src/errors/express-validation.js +0 -18
  341. package/src/errors/express-validation.js.map +0 -1
  342. package/src/errors/index.d.ts.map +0 -1
  343. package/src/errors/index.js +0 -16
  344. package/src/errors/index.js.map +0 -1
  345. package/src/errors/invalid-backup-code-version.d.ts +0 -6
  346. package/src/errors/invalid-backup-code-version.d.ts.map +0 -1
  347. package/src/errors/invalid-backup-code-version.js +0 -16
  348. package/src/errors/invalid-backup-code-version.js.map +0 -1
  349. package/src/errors/invalid-jwt-token.d.ts +0 -5
  350. package/src/errors/invalid-jwt-token.d.ts.map +0 -1
  351. package/src/errors/invalid-jwt-token.js +0 -12
  352. package/src/errors/invalid-jwt-token.js.map +0 -1
  353. package/src/errors/invalid-model.d.ts +0 -6
  354. package/src/errors/invalid-model.d.ts.map +0 -1
  355. package/src/errors/invalid-model.js +0 -14
  356. package/src/errors/invalid-model.js.map +0 -1
  357. package/src/errors/invalid-new-password.d.ts +0 -5
  358. package/src/errors/invalid-new-password.d.ts.map +0 -1
  359. package/src/errors/invalid-new-password.js +0 -14
  360. package/src/errors/invalid-new-password.js.map +0 -1
  361. package/src/errors/invalid-password.d.ts +0 -5
  362. package/src/errors/invalid-password.d.ts.map +0 -1
  363. package/src/errors/invalid-password.js +0 -14
  364. package/src/errors/invalid-password.js.map +0 -1
  365. package/src/errors/missing-validated-data.d.ts +0 -7
  366. package/src/errors/missing-validated-data.d.ts.map +0 -1
  367. package/src/errors/missing-validated-data.js +0 -36
  368. package/src/errors/missing-validated-data.js.map +0 -1
  369. package/src/errors/mnemonic-or-password-required.d.ts +0 -5
  370. package/src/errors/mnemonic-or-password-required.d.ts.map +0 -1
  371. package/src/errors/mnemonic-or-password-required.js +0 -14
  372. package/src/errors/mnemonic-or-password-required.js.map +0 -1
  373. package/src/errors/model-not-registered.d.ts +0 -6
  374. package/src/errors/model-not-registered.d.ts.map +0 -1
  375. package/src/errors/model-not-registered.js +0 -14
  376. package/src/errors/model-not-registered.js.map +0 -1
  377. package/src/errors/mongoose-validation.d.ts +0 -12
  378. package/src/errors/mongoose-validation.d.ts.map +0 -1
  379. package/src/errors/mongoose-validation.js +0 -17
  380. package/src/errors/mongoose-validation.js.map +0 -1
  381. package/src/errors/symmetric.d.ts +0 -8
  382. package/src/errors/symmetric.d.ts.map +0 -1
  383. package/src/errors/symmetric.js +0 -22
  384. package/src/errors/symmetric.js.map +0 -1
  385. package/src/errors/token-expired.d.ts +0 -5
  386. package/src/errors/token-expired.d.ts.map +0 -1
  387. package/src/errors/token-expired.js +0 -12
  388. package/src/errors/token-expired.js.map +0 -1
  389. package/src/get-language.d.ts +0 -2
  390. package/src/get-language.d.ts.map +0 -1
  391. package/src/get-language.js +0 -30
  392. package/src/get-language.js.map +0 -1
  393. package/src/get-timezone.d.ts +0 -2
  394. package/src/get-timezone.d.ts.map +0 -1
  395. package/src/get-timezone.js +0 -39
  396. package/src/get-timezone.js.map +0 -1
  397. package/src/index.d.ts.map +0 -1
  398. package/src/index.js +0 -80
  399. package/src/index.js.map +0 -1
  400. package/src/interfaces/api-error-response.d.ts +0 -5
  401. package/src/interfaces/api-error-response.d.ts.map +0 -1
  402. package/src/interfaces/api-error-response.js +0 -3
  403. package/src/interfaces/api-error-response.js.map +0 -1
  404. package/src/interfaces/api-express-validation-error-response.d.ts +0 -7
  405. package/src/interfaces/api-express-validation-error-response.d.ts.map +0 -1
  406. package/src/interfaces/api-express-validation-error-response.js +0 -3
  407. package/src/interfaces/api-express-validation-error-response.js.map +0 -1
  408. package/src/interfaces/api-message-response.d.ts +0 -4
  409. package/src/interfaces/api-message-response.d.ts.map +0 -1
  410. package/src/interfaces/api-message-response.js +0 -3
  411. package/src/interfaces/api-message-response.js.map +0 -1
  412. package/src/interfaces/api-mongo-validation-error-response.d.ts +0 -6
  413. package/src/interfaces/api-mongo-validation-error-response.d.ts.map +0 -1
  414. package/src/interfaces/api-mongo-validation-error-response.js +0 -3
  415. package/src/interfaces/api-mongo-validation-error-response.js.map +0 -1
  416. package/src/interfaces/api-responses/backup-codes-response.d.ts +0 -5
  417. package/src/interfaces/api-responses/backup-codes-response.d.ts.map +0 -1
  418. package/src/interfaces/api-responses/backup-codes-response.js +0 -3
  419. package/src/interfaces/api-responses/backup-codes-response.js.map +0 -1
  420. package/src/interfaces/api-responses/challenge-response.d.ts +0 -6
  421. package/src/interfaces/api-responses/challenge-response.d.ts.map +0 -1
  422. package/src/interfaces/api-responses/challenge-response.js +0 -3
  423. package/src/interfaces/api-responses/challenge-response.js.map +0 -1
  424. package/src/interfaces/api-responses/code-count-response.d.ts +0 -5
  425. package/src/interfaces/api-responses/code-count-response.d.ts.map +0 -1
  426. package/src/interfaces/api-responses/code-count-response.js +0 -3
  427. package/src/interfaces/api-responses/code-count-response.js.map +0 -1
  428. package/src/interfaces/api-responses/index.d.ts.map +0 -1
  429. package/src/interfaces/api-responses/index.js +0 -12
  430. package/src/interfaces/api-responses/index.js.map +0 -1
  431. package/src/interfaces/api-responses/login-response.d.ts +0 -8
  432. package/src/interfaces/api-responses/login-response.d.ts.map +0 -1
  433. package/src/interfaces/api-responses/login-response.js +0 -3
  434. package/src/interfaces/api-responses/login-response.js.map +0 -1
  435. package/src/interfaces/api-responses/mnemonic-response.d.ts +0 -5
  436. package/src/interfaces/api-responses/mnemonic-response.d.ts.map +0 -1
  437. package/src/interfaces/api-responses/mnemonic-response.js +0 -3
  438. package/src/interfaces/api-responses/mnemonic-response.js.map +0 -1
  439. package/src/interfaces/api-responses/registration-response.d.ts +0 -6
  440. package/src/interfaces/api-responses/registration-response.d.ts.map +0 -1
  441. package/src/interfaces/api-responses/registration-response.js +0 -3
  442. package/src/interfaces/api-responses/registration-response.js.map +0 -1
  443. package/src/interfaces/api-responses/request-user-response.d.ts +0 -6
  444. package/src/interfaces/api-responses/request-user-response.d.ts.map +0 -1
  445. package/src/interfaces/api-responses/request-user-response.js +0 -3
  446. package/src/interfaces/api-responses/request-user-response.js.map +0 -1
  447. package/src/interfaces/api-responses/user-settings-response.d.ts +0 -12
  448. package/src/interfaces/api-responses/user-settings-response.d.ts.map +0 -1
  449. package/src/interfaces/api-responses/user-settings-response.js +0 -3
  450. package/src/interfaces/api-responses/user-settings-response.js.map +0 -1
  451. package/src/interfaces/application.d.ts +0 -17
  452. package/src/interfaces/application.d.ts.map +0 -1
  453. package/src/interfaces/application.js +0 -3
  454. package/src/interfaces/application.js.map +0 -1
  455. package/src/interfaces/backend-objects/email-token.d.ts +0 -4
  456. package/src/interfaces/backend-objects/email-token.d.ts.map +0 -1
  457. package/src/interfaces/backend-objects/email-token.js +0 -3
  458. package/src/interfaces/backend-objects/email-token.js.map +0 -1
  459. package/src/interfaces/backend-objects/index.d.ts.map +0 -1
  460. package/src/interfaces/backend-objects/index.js +0 -8
  461. package/src/interfaces/backend-objects/index.js.map +0 -1
  462. package/src/interfaces/backend-objects/request-user.d.ts +0 -5
  463. package/src/interfaces/backend-objects/request-user.d.ts.map +0 -1
  464. package/src/interfaces/backend-objects/request-user.js +0 -3
  465. package/src/interfaces/backend-objects/request-user.js.map +0 -1
  466. package/src/interfaces/backend-objects/role.d.ts +0 -4
  467. package/src/interfaces/backend-objects/role.d.ts.map +0 -1
  468. package/src/interfaces/backend-objects/role.js +0 -3
  469. package/src/interfaces/backend-objects/role.js.map +0 -1
  470. package/src/interfaces/backend-objects/user.d.ts +0 -4
  471. package/src/interfaces/backend-objects/user.d.ts.map +0 -1
  472. package/src/interfaces/backend-objects/user.js +0 -3
  473. package/src/interfaces/backend-objects/user.js.map +0 -1
  474. package/src/interfaces/checksum-config.d.ts +0 -5
  475. package/src/interfaces/checksum-config.d.ts.map +0 -1
  476. package/src/interfaces/checksum-config.js +0 -3
  477. package/src/interfaces/checksum-config.js.map +0 -1
  478. package/src/interfaces/checksum-consts.d.ts +0 -11
  479. package/src/interfaces/checksum-consts.d.ts.map +0 -1
  480. package/src/interfaces/checksum-consts.js +0 -3
  481. package/src/interfaces/checksum-consts.js.map +0 -1
  482. package/src/interfaces/constants.d.ts +0 -102
  483. package/src/interfaces/constants.d.ts.map +0 -1
  484. package/src/interfaces/constants.js +0 -3
  485. package/src/interfaces/constants.js.map +0 -1
  486. package/src/interfaces/controller-config.d.ts +0 -21
  487. package/src/interfaces/controller-config.d.ts.map +0 -1
  488. package/src/interfaces/controller-config.js +0 -3
  489. package/src/interfaces/controller-config.js.map +0 -1
  490. package/src/interfaces/create-user-basics.d.ts +0 -18
  491. package/src/interfaces/create-user-basics.d.ts.map +0 -1
  492. package/src/interfaces/create-user-basics.js +0 -3
  493. package/src/interfaces/create-user-basics.js.map +0 -1
  494. package/src/interfaces/csp-config.d.ts +0 -7
  495. package/src/interfaces/csp-config.d.ts.map +0 -1
  496. package/src/interfaces/csp-config.js +0 -13
  497. package/src/interfaces/csp-config.js.map +0 -1
  498. package/src/interfaces/csp-definition.d.ts +0 -13
  499. package/src/interfaces/csp-definition.d.ts.map +0 -1
  500. package/src/interfaces/csp-definition.js +0 -22
  501. package/src/interfaces/csp-definition.js.map +0 -1
  502. package/src/interfaces/db-init-result.d.ts +0 -5
  503. package/src/interfaces/db-init-result.d.ts.map +0 -1
  504. package/src/interfaces/db-init-result.js +0 -3
  505. package/src/interfaces/db-init-result.js.map +0 -1
  506. package/src/interfaces/deep-partial.d.ts +0 -4
  507. package/src/interfaces/deep-partial.d.ts.map +0 -1
  508. package/src/interfaces/deep-partial.js +0 -3
  509. package/src/interfaces/deep-partial.js.map +0 -1
  510. package/src/interfaces/discriminator-collections.d.ts +0 -7
  511. package/src/interfaces/discriminator-collections.d.ts.map +0 -1
  512. package/src/interfaces/discriminator-collections.js +0 -3
  513. package/src/interfaces/discriminator-collections.js.map +0 -1
  514. package/src/interfaces/email-service.d.ts +0 -4
  515. package/src/interfaces/email-service.d.ts.map +0 -1
  516. package/src/interfaces/email-service.js +0 -3
  517. package/src/interfaces/email-service.js.map +0 -1
  518. package/src/interfaces/environment-mongo.d.ts +0 -76
  519. package/src/interfaces/environment-mongo.d.ts.map +0 -1
  520. package/src/interfaces/environment-mongo.js +0 -3
  521. package/src/interfaces/environment-mongo.js.map +0 -1
  522. package/src/interfaces/environment.d.ts +0 -180
  523. package/src/interfaces/environment.d.ts.map +0 -1
  524. package/src/interfaces/environment.js +0 -3
  525. package/src/interfaces/environment.js.map +0 -1
  526. package/src/interfaces/failable-result.d.ts +0 -7
  527. package/src/interfaces/failable-result.d.ts.map +0 -1
  528. package/src/interfaces/failable-result.js +0 -3
  529. package/src/interfaces/failable-result.js.map +0 -1
  530. package/src/interfaces/fec-consts.d.ts +0 -5
  531. package/src/interfaces/fec-consts.d.ts.map +0 -1
  532. package/src/interfaces/fec-consts.js +0 -3
  533. package/src/interfaces/fec-consts.js.map +0 -1
  534. package/src/interfaces/flexible-csp.d.ts +0 -8
  535. package/src/interfaces/flexible-csp.d.ts.map +0 -1
  536. package/src/interfaces/flexible-csp.js +0 -14
  537. package/src/interfaces/flexible-csp.js.map +0 -1
  538. package/src/interfaces/handleable-error-options.d.ts +0 -7
  539. package/src/interfaces/handleable-error-options.d.ts.map +0 -1
  540. package/src/interfaces/handleable-error-options.js +0 -3
  541. package/src/interfaces/handleable-error-options.js.map +0 -1
  542. package/src/interfaces/index.d.ts.map +0 -1
  543. package/src/interfaces/index.js +0 -38
  544. package/src/interfaces/index.js.map +0 -1
  545. package/src/interfaces/jwt-consts.d.ts +0 -11
  546. package/src/interfaces/jwt-consts.d.ts.map +0 -1
  547. package/src/interfaces/jwt-consts.js +0 -3
  548. package/src/interfaces/jwt-consts.js.map +0 -1
  549. package/src/interfaces/jwt-sign-response.d.ts +0 -11
  550. package/src/interfaces/jwt-sign-response.d.ts.map +0 -1
  551. package/src/interfaces/jwt-sign-response.js +0 -3
  552. package/src/interfaces/jwt-sign-response.js.map +0 -1
  553. package/src/interfaces/models/email-token.d.ts +0 -6
  554. package/src/interfaces/models/email-token.d.ts.map +0 -1
  555. package/src/interfaces/models/email-token.js +0 -3
  556. package/src/interfaces/models/email-token.js.map +0 -1
  557. package/src/interfaces/models/index.d.ts.map +0 -1
  558. package/src/interfaces/models/index.js +0 -11
  559. package/src/interfaces/models/index.js.map +0 -1
  560. package/src/interfaces/models/mnemonic.d.ts +0 -6
  561. package/src/interfaces/models/mnemonic.d.ts.map +0 -1
  562. package/src/interfaces/models/mnemonic.js +0 -3
  563. package/src/interfaces/models/mnemonic.js.map +0 -1
  564. package/src/interfaces/models/role.d.ts +0 -6
  565. package/src/interfaces/models/role.d.ts.map +0 -1
  566. package/src/interfaces/models/role.js +0 -3
  567. package/src/interfaces/models/role.js.map +0 -1
  568. package/src/interfaces/models/token-role.d.ts +0 -11
  569. package/src/interfaces/models/token-role.d.ts.map +0 -1
  570. package/src/interfaces/models/token-role.js +0 -3
  571. package/src/interfaces/models/token-role.js.map +0 -1
  572. package/src/interfaces/models/used-direct-login-token.d.ts +0 -11
  573. package/src/interfaces/models/used-direct-login-token.d.ts.map +0 -1
  574. package/src/interfaces/models/used-direct-login-token.js +0 -3
  575. package/src/interfaces/models/used-direct-login-token.js.map +0 -1
  576. package/src/interfaces/models/user-role.d.ts +0 -11
  577. package/src/interfaces/models/user-role.d.ts.map +0 -1
  578. package/src/interfaces/models/user-role.js +0 -3
  579. package/src/interfaces/models/user-role.js.map +0 -1
  580. package/src/interfaces/models/user.d.ts +0 -11
  581. package/src/interfaces/models/user.d.ts.map +0 -1
  582. package/src/interfaces/models/user.js +0 -3
  583. package/src/interfaces/models/user.js.map +0 -1
  584. package/src/interfaces/mongo-errors.d.ts +0 -5
  585. package/src/interfaces/mongo-errors.d.ts.map +0 -1
  586. package/src/interfaces/mongo-errors.js +0 -3
  587. package/src/interfaces/mongo-errors.js.map +0 -1
  588. package/src/interfaces/request-user.d.ts +0 -58
  589. package/src/interfaces/request-user.d.ts.map +0 -1
  590. package/src/interfaces/request-user.js +0 -3
  591. package/src/interfaces/request-user.js.map +0 -1
  592. package/src/interfaces/required-string-keys.d.ts +0 -22
  593. package/src/interfaces/required-string-keys.d.ts.map +0 -1
  594. package/src/interfaces/required-string-keys.js +0 -3
  595. package/src/interfaces/required-string-keys.js.map +0 -1
  596. package/src/interfaces/schema.d.ts +0 -29
  597. package/src/interfaces/schema.d.ts.map +0 -1
  598. package/src/interfaces/schema.js +0 -3
  599. package/src/interfaces/schema.js.map +0 -1
  600. package/src/interfaces/server-init-result.d.ts +0 -35
  601. package/src/interfaces/server-init-result.d.ts.map +0 -1
  602. package/src/interfaces/server-init-result.js +0 -3
  603. package/src/interfaces/server-init-result.js.map +0 -1
  604. package/src/interfaces/status-code-response.d.ts +0 -7
  605. package/src/interfaces/status-code-response.d.ts.map +0 -1
  606. package/src/interfaces/status-code-response.js +0 -3
  607. package/src/interfaces/status-code-response.js.map +0 -1
  608. package/src/interfaces/symmetric-encryption-results.d.ts +0 -5
  609. package/src/interfaces/test-environment.d.ts +0 -12
  610. package/src/interfaces/test-environment.d.ts.map +0 -1
  611. package/src/interfaces/test-environment.js +0 -3
  612. package/src/interfaces/test-environment.js.map +0 -1
  613. package/src/interfaces/token-response.d.ts +0 -5
  614. package/src/interfaces/token-response.d.ts.map +0 -1
  615. package/src/interfaces/token-response.js +0 -3
  616. package/src/interfaces/token-response.js.map +0 -1
  617. package/src/middleware-utils.d.ts +0 -8
  618. package/src/middleware-utils.d.ts.map +0 -1
  619. package/src/middleware-utils.js +0 -94
  620. package/src/middleware-utils.js.map +0 -1
  621. package/src/middlewares/authenticate-crypto.d.ts +0 -10
  622. package/src/middlewares/authenticate-crypto.d.ts.map +0 -1
  623. package/src/middlewares/authenticate-crypto.js +0 -126
  624. package/src/middlewares/authenticate-crypto.js.map +0 -1
  625. package/src/middlewares/authenticate-token.d.ts +0 -21
  626. package/src/middlewares/authenticate-token.d.ts.map +0 -1
  627. package/src/middlewares/authenticate-token.js +0 -104
  628. package/src/middlewares/authenticate-token.js.map +0 -1
  629. package/src/middlewares/cleanup-crypto.d.ts +0 -7
  630. package/src/middlewares/cleanup-crypto.d.ts.map +0 -1
  631. package/src/middlewares/cleanup-crypto.js +0 -32
  632. package/src/middlewares/cleanup-crypto.js.map +0 -1
  633. package/src/middlewares/index.d.ts.map +0 -1
  634. package/src/middlewares/index.js +0 -8
  635. package/src/middlewares/index.js.map +0 -1
  636. package/src/middlewares/set-global-context-language.d.ts +0 -3
  637. package/src/middlewares/set-global-context-language.d.ts.map +0 -1
  638. package/src/middlewares/set-global-context-language.js +0 -14
  639. package/src/middlewares/set-global-context-language.js.map +0 -1
  640. package/src/model-registry.d.ts +0 -23
  641. package/src/model-registry.d.ts.map +0 -1
  642. package/src/model-registry.js +0 -47
  643. package/src/model-registry.js.map +0 -1
  644. package/src/models/email-token.d.ts +0 -8
  645. package/src/models/email-token.d.ts.map +0 -1
  646. package/src/models/email-token.js +0 -11
  647. package/src/models/email-token.js.map +0 -1
  648. package/src/models/index.d.ts.map +0 -1
  649. package/src/models/index.js +0 -10
  650. package/src/models/index.js.map +0 -1
  651. package/src/models/mnemonic.d.ts +0 -8
  652. package/src/models/mnemonic.d.ts.map +0 -1
  653. package/src/models/mnemonic.js +0 -11
  654. package/src/models/mnemonic.js.map +0 -1
  655. package/src/models/role.d.ts +0 -8
  656. package/src/models/role.d.ts.map +0 -1
  657. package/src/models/role.js +0 -11
  658. package/src/models/role.js.map +0 -1
  659. package/src/models/used-direct-login-token.d.ts +0 -8
  660. package/src/models/used-direct-login-token.d.ts.map +0 -1
  661. package/src/models/used-direct-login-token.js +0 -11
  662. package/src/models/used-direct-login-token.js.map +0 -1
  663. package/src/models/user-role.d.ts +0 -7
  664. package/src/models/user-role.d.ts.map +0 -1
  665. package/src/models/user-role.js +0 -10
  666. package/src/models/user-role.js.map +0 -1
  667. package/src/models/user.d.ts +0 -8
  668. package/src/models/user.d.ts.map +0 -1
  669. package/src/models/user.js +0 -11
  670. package/src/models/user.js.map +0 -1
  671. package/src/pipeline/index.d.ts.map +0 -1
  672. package/src/pipeline/index.js +0 -5
  673. package/src/pipeline/index.js.map +0 -1
  674. package/src/pipeline/pipeline-builder.d.ts +0 -8
  675. package/src/pipeline/pipeline-builder.d.ts.map +0 -1
  676. package/src/pipeline/pipeline-builder.js +0 -18
  677. package/src/pipeline/pipeline-builder.js.map +0 -1
  678. package/src/plugins/index.d.ts.map +0 -1
  679. package/src/plugins/index.js +0 -6
  680. package/src/plugins/index.js.map +0 -1
  681. package/src/plugins/plugin-interface.d.ts +0 -9
  682. package/src/plugins/plugin-interface.d.ts.map +0 -1
  683. package/src/plugins/plugin-interface.js +0 -3
  684. package/src/plugins/plugin-interface.js.map +0 -1
  685. package/src/plugins/plugin-manager.d.ts +0 -13
  686. package/src/plugins/plugin-manager.d.ts.map +0 -1
  687. package/src/plugins/plugin-manager.js +0 -37
  688. package/src/plugins/plugin-manager.js.map +0 -1
  689. package/src/registry/email-service-registry.d.ts +0 -27
  690. package/src/registry/email-service-registry.d.ts.map +0 -1
  691. package/src/registry/email-service-registry.js +0 -42
  692. package/src/registry/email-service-registry.js.map +0 -1
  693. package/src/registry/index.d.ts.map +0 -1
  694. package/src/registry/index.js +0 -6
  695. package/src/registry/index.js.map +0 -1
  696. package/src/responses/index.d.ts.map +0 -1
  697. package/src/responses/index.js +0 -5
  698. package/src/responses/index.js.map +0 -1
  699. package/src/responses/response-builder.d.ts +0 -24
  700. package/src/responses/response-builder.d.ts.map +0 -1
  701. package/src/responses/response-builder.js +0 -63
  702. package/src/responses/response-builder.js.map +0 -1
  703. package/src/routers/api.d.ts +0 -28
  704. package/src/routers/api.d.ts.map +0 -1
  705. package/src/routers/api.js +0 -80
  706. package/src/routers/api.js.map +0 -1
  707. package/src/routers/app.d.ts +0 -33
  708. package/src/routers/app.d.ts.map +0 -1
  709. package/src/routers/app.js +0 -228
  710. package/src/routers/app.js.map +0 -1
  711. package/src/routers/base.d.ts +0 -9
  712. package/src/routers/base.d.ts.map +0 -1
  713. package/src/routers/base.js +0 -14
  714. package/src/routers/base.js.map +0 -1
  715. package/src/routers/index.d.ts.map +0 -1
  716. package/src/routers/index.js +0 -7
  717. package/src/routers/index.js.map +0 -1
  718. package/src/routers/router-config.d.ts +0 -18
  719. package/src/routers/router-config.d.ts.map +0 -1
  720. package/src/routers/router-config.js +0 -8
  721. package/src/routers/router-config.js.map +0 -1
  722. package/src/routing/index.d.ts +0 -2
  723. package/src/routing/index.d.ts.map +0 -1
  724. package/src/routing/index.js +0 -5
  725. package/src/routing/index.js.map +0 -1
  726. package/src/routing/route-builder.d.ts +0 -36
  727. package/src/routing/route-builder.d.ts.map +0 -1
  728. package/src/routing/route-builder.js +0 -86
  729. package/src/routing/route-builder.js.map +0 -1
  730. package/src/schemas/email-token.d.ts +0 -49
  731. package/src/schemas/email-token.d.ts.map +0 -1
  732. package/src/schemas/email-token.js +0 -55
  733. package/src/schemas/email-token.js.map +0 -1
  734. package/src/schemas/index.d.ts.map +0 -1
  735. package/src/schemas/index.js +0 -11
  736. package/src/schemas/index.js.map +0 -1
  737. package/src/schemas/mnemonic.d.ts +0 -27
  738. package/src/schemas/mnemonic.d.ts.map +0 -1
  739. package/src/schemas/mnemonic.js +0 -31
  740. package/src/schemas/mnemonic.js.map +0 -1
  741. package/src/schemas/role.d.ts +0 -42
  742. package/src/schemas/role.d.ts.map +0 -1
  743. package/src/schemas/role.js +0 -89
  744. package/src/schemas/role.js.map +0 -1
  745. package/src/schemas/schema.d.ts +0 -42
  746. package/src/schemas/schema.d.ts.map +0 -1
  747. package/src/schemas/schema.js +0 -70
  748. package/src/schemas/schema.js.map +0 -1
  749. package/src/schemas/used-direct-login-token.d.ts +0 -37
  750. package/src/schemas/used-direct-login-token.d.ts.map +0 -1
  751. package/src/schemas/used-direct-login-token.js +0 -24
  752. package/src/schemas/used-direct-login-token.js.map +0 -1
  753. package/src/schemas/user-role.d.ts +0 -39
  754. package/src/schemas/user-role.d.ts.map +0 -1
  755. package/src/schemas/user-role.js +0 -55
  756. package/src/schemas/user-role.js.map +0 -1
  757. package/src/schemas/user.d.ts +0 -24
  758. package/src/schemas/user.d.ts.map +0 -1
  759. package/src/schemas/user.js +0 -195
  760. package/src/schemas/user.js.map +0 -1
  761. package/src/services/backup-code.d.ts +0 -76
  762. package/src/services/backup-code.d.ts.map +0 -1
  763. package/src/services/backup-code.js +0 -185
  764. package/src/services/backup-code.js.map +0 -1
  765. package/src/services/base.d.ts +0 -11
  766. package/src/services/base.d.ts.map +0 -1
  767. package/src/services/base.js +0 -15
  768. package/src/services/base.js.map +0 -1
  769. package/src/services/checksum.d.ts +0 -69
  770. package/src/services/checksum.d.ts.map +0 -1
  771. package/src/services/checksum.js +0 -145
  772. package/src/services/checksum.js.map +0 -1
  773. package/src/services/database-initialization.d.ts +0 -111
  774. package/src/services/database-initialization.d.ts.map +0 -1
  775. package/src/services/database-initialization.js +0 -878
  776. package/src/services/database-initialization.js.map +0 -1
  777. package/src/services/db-init-cache.d.ts +0 -10
  778. package/src/services/db-init-cache.d.ts.map +0 -1
  779. package/src/services/db-init-cache.js +0 -3
  780. package/src/services/db-init-cache.js.map +0 -1
  781. package/src/services/direct-login-token.d.ts +0 -7
  782. package/src/services/direct-login-token.d.ts.map +0 -1
  783. package/src/services/direct-login-token.js +0 -41
  784. package/src/services/direct-login-token.js.map +0 -1
  785. package/src/services/dummy-email-service.d.ts +0 -11
  786. package/src/services/dummy-email-service.d.ts.map +0 -1
  787. package/src/services/dummy-email-service.js +0 -16
  788. package/src/services/dummy-email-service.js.map +0 -1
  789. package/src/services/fec-usage-example.d.ts +0 -38
  790. package/src/services/fec-usage-example.d.ts.map +0 -1
  791. package/src/services/fec-usage-example.js +0 -75
  792. package/src/services/fec-usage-example.js.map +0 -1
  793. package/src/services/fec.d.ts +0 -46
  794. package/src/services/fec.d.ts.map +0 -1
  795. package/src/services/fec.js +0 -214
  796. package/src/services/fec.js.map +0 -1
  797. package/src/services/index.d.ts.map +0 -1
  798. package/src/services/index.js +0 -22
  799. package/src/services/index.js.map +0 -1
  800. package/src/services/jwt.d.ts +0 -30
  801. package/src/services/jwt.d.ts.map +0 -1
  802. package/src/services/jwt.js +0 -90
  803. package/src/services/jwt.js.map +0 -1
  804. package/src/services/key-wrapping.d.ts +0 -61
  805. package/src/services/key-wrapping.d.ts.map +0 -1
  806. package/src/services/key-wrapping.js +0 -307
  807. package/src/services/key-wrapping.js.map +0 -1
  808. package/src/services/mnemonic.d.ts +0 -62
  809. package/src/services/mnemonic.d.ts.map +0 -1
  810. package/src/services/mnemonic.js +0 -114
  811. package/src/services/mnemonic.js.map +0 -1
  812. package/src/services/request-user.d.ts +0 -23
  813. package/src/services/request-user.d.ts.map +0 -1
  814. package/src/services/request-user.js +0 -68
  815. package/src/services/request-user.js.map +0 -1
  816. package/src/services/role.d.ts +0 -87
  817. package/src/services/role.d.ts.map +0 -1
  818. package/src/services/role.js +0 -279
  819. package/src/services/role.js.map +0 -1
  820. package/src/services/symmetric.d.ts +0 -42
  821. package/src/services/symmetric.d.ts.map +0 -1
  822. package/src/services/symmetric.js +0 -101
  823. package/src/services/symmetric.js.map +0 -1
  824. package/src/services/system-user.d.ts +0 -16
  825. package/src/services/system-user.d.ts.map +0 -1
  826. package/src/services/system-user.js +0 -46
  827. package/src/services/system-user.js.map +0 -1
  828. package/src/services/user.d.ts +0 -345
  829. package/src/services/user.d.ts.map +0 -1
  830. package/src/services/user.js +0 -1447
  831. package/src/services/user.js.map +0 -1
  832. package/src/services/xor.d.ts +0 -24
  833. package/src/services/xor.d.ts.map +0 -1
  834. package/src/services/xor.js +0 -37
  835. package/src/services/xor.js.map +0 -1
  836. package/src/testing.d.ts +0 -3
  837. package/src/testing.d.ts.map +0 -1
  838. package/src/testing.js +0 -7
  839. package/src/testing.js.map +0 -1
  840. package/src/transactions/index.d.ts.map +0 -1
  841. package/src/transactions/index.js +0 -5
  842. package/src/transactions/index.js.map +0 -1
  843. package/src/transactions/transaction-manager.d.ts +0 -12
  844. package/src/transactions/transaction-manager.d.ts.map +0 -1
  845. package/src/transactions/transaction-manager.js +0 -30
  846. package/src/transactions/transaction-manager.js.map +0 -1
  847. package/src/types/app-config.d.ts +0 -16
  848. package/src/types/app-config.d.ts.map +0 -1
  849. package/src/types/app-config.js +0 -3
  850. package/src/types/app-config.js.map +0 -1
  851. package/src/types/controller-config.d.ts +0 -14
  852. package/src/types/controller-config.d.ts.map +0 -1
  853. package/src/types/controller-config.js +0 -3
  854. package/src/types/controller-config.js.map +0 -1
  855. package/src/types/environment-variables.d.ts.map +0 -1
  856. package/src/types/environment-variables.js +0 -39
  857. package/src/types/environment-variables.js.map +0 -1
  858. package/src/types/index.d.ts.map +0 -1
  859. package/src/types/index.js +0 -6
  860. package/src/types/index.js.map +0 -1
  861. package/src/types/mongoose-helpers.d.ts.map +0 -1
  862. package/src/types/mongoose-helpers.js +0 -6
  863. package/src/types/mongoose-helpers.js.map +0 -1
  864. package/src/types.d.ts +0 -104
  865. package/src/types.d.ts.map +0 -1
  866. package/src/types.js +0 -14
  867. package/src/types.js.map +0 -1
  868. package/src/utils.d.ts +0 -211
  869. package/src/utils.d.ts.map +0 -1
  870. package/src/utils.js +0 -818
  871. package/src/utils.js.map +0 -1
  872. package/src/validation/index.d.ts.map +0 -1
  873. package/src/validation/index.js +0 -5
  874. package/src/validation/index.js.map +0 -1
  875. package/src/validation/validation-builder.d.ts +0 -32
  876. package/src/validation/validation-builder.d.ts.map +0 -1
  877. package/src/validation/validation-builder.js +0 -81
  878. package/src/validation/validation-builder.js.map +0 -1
@@ -0,0 +1,1734 @@
1
+ /**
2
+ * @fileoverview User controller handling authentication, registration, and user management endpoints.
3
+ * Provides comprehensive user operations including login, password management, and settings.
4
+ * @module controllers/user
5
+ */
6
+
7
+ import { ECIES, SecureString, UINT64_SIZE } from '@digitaldefiance/ecies-lib';
8
+ import {
9
+ CoreLanguageCode,
10
+ HandleableError,
11
+ isValidTimezone,
12
+ LanguageCodes,
13
+ } from '@digitaldefiance/i18n-lib';
14
+ import {
15
+ Member as BackendMember,
16
+ ECIESService,
17
+ getEnhancedNodeIdProvider,
18
+ PlatformID,
19
+ } from '@digitaldefiance/node-ecies-lib';
20
+ import {
21
+ AccountStatus,
22
+ EmailTokenType,
23
+ GenericValidationError,
24
+ getSuiteCoreTranslation,
25
+ ITokenRole,
26
+ ITokenUser,
27
+ IUserBase,
28
+ SuiteCoreStringKey,
29
+ UsernameOrEmailRequiredError,
30
+ } from '@digitaldefiance/suite-core-lib';
31
+ import type { NextFunction, Request, Response } from 'express';
32
+ import { body } from 'express-validator';
33
+ import { z } from 'zod';
34
+ import { BackupCode } from '../backup-code';
35
+ import { DecoratorBaseController } from '../decorators/base-controller';
36
+ import { Controller, Get, Post } from '../decorators/controller';
37
+ import { IBaseDocument } from '../documents';
38
+ import { IUserDocument } from '../documents/user';
39
+ import { BaseModelName } from '../enumerations/base-model-name';
40
+ import { Environment } from '../environment';
41
+ import { MnemonicOrPasswordRequiredError } from '../errors/mnemonic-or-password-required';
42
+ import {
43
+ IApiChallengeResponse,
44
+ IApiCodeCountResponse,
45
+ IApiLoginResponse,
46
+ IApiMessageResponse,
47
+ IApiMnemonicResponse,
48
+ IApiRegistrationResponse,
49
+ IApiRequestUserResponse,
50
+ IApiUserSettingsResponse,
51
+ } from '../interfaces';
52
+ import { IApiBackupCodesResponse } from '../interfaces/api-responses/backup-codes-response';
53
+ import type { IApplication } from '../interfaces/application';
54
+ import { IConstants } from '../interfaces/constants';
55
+ import { IStatusCodeResponse } from '../interfaces/status-code-response';
56
+ import { findAuthToken } from '../middlewares/authenticate-token';
57
+ import { BackupCodeService } from '../services/backup-code';
58
+ import { JwtService } from '../services/jwt';
59
+ import { RequestUserService } from '../services/request-user';
60
+ import { RoleService } from '../services/role';
61
+ import { SystemUserService } from '../services/system-user';
62
+ import { UserService } from '../services/user';
63
+ import { ApiErrorResponse } from '../types';
64
+ import { requireValidatedFieldsAsync, withTransaction } from '../utils';
65
+
66
+ const isString = (v: unknown): v is string => typeof v === 'string';
67
+
68
+ const RegisterSchema = z.object({
69
+ username: z.string(),
70
+ email: z.string(),
71
+ timezone: z.string(),
72
+ password: z.string().min(8).optional(),
73
+ });
74
+
75
+ const EmailLoginChallengeSchema = z.object({
76
+ token: z.string(),
77
+ signature: z.string(),
78
+ email: z.string().optional(),
79
+ username: z.string().optional(),
80
+ });
81
+
82
+ const DirectLoginChallengeSchema = z.object({
83
+ challenge: z.string(),
84
+ signature: z.string(),
85
+ email: z.string().optional(),
86
+ username: z.string().optional(),
87
+ });
88
+
89
+ /**
90
+ * User controller handling all user-related API endpoints.
91
+ * Manages authentication, registration, password operations, settings, and backup codes.
92
+ * @template TID Platform ID type
93
+ * @template TDate Date type
94
+ * @template TLanguage Site language string type
95
+ * @template TAccountStatus Account status string type
96
+ * @template TUser User base type
97
+ * @template TTokenRole Token role type
98
+ * @template TTokenUser Token user type
99
+ * @template TApplication Application type
100
+ */
101
+ @Controller()
102
+ export class UserController<
103
+ TID extends PlatformID = Buffer,
104
+ TDate extends Date = Date,
105
+ TLanguage extends CoreLanguageCode = CoreLanguageCode,
106
+ TAccountStatus extends string = string,
107
+ TUser extends IUserBase<TID, TDate, TLanguage, TAccountStatus> = IUserBase<
108
+ TID,
109
+ TDate,
110
+ TLanguage,
111
+ TAccountStatus
112
+ >,
113
+ TTokenRole extends ITokenRole<TID, TDate> = ITokenRole<TID, TDate>,
114
+ TTokenUser extends ITokenUser = ITokenUser,
115
+ TApplication extends IApplication<TID> = IApplication<TID>,
116
+ > extends DecoratorBaseController<TLanguage, TID> {
117
+ protected readonly userService: UserService<
118
+ IUserDocument,
119
+ TID,
120
+ TDate,
121
+ TLanguage,
122
+ TAccountStatus,
123
+ Environment<TID>,
124
+ IConstants,
125
+ IBaseDocument<IUserDocument, TID>,
126
+ TUser,
127
+ TTokenRole,
128
+ TApplication
129
+ >;
130
+ protected readonly jwtService: JwtService<
131
+ TID,
132
+ TDate,
133
+ TTokenRole,
134
+ TTokenUser,
135
+ TApplication
136
+ >;
137
+ protected readonly backupCodeService: BackupCodeService<
138
+ TID,
139
+ TDate,
140
+ TTokenRole,
141
+ TApplication
142
+ >;
143
+ protected readonly roleService: RoleService<TID, TDate, TTokenRole>;
144
+ protected readonly eciesService: ECIESService<TID>;
145
+ protected readonly systemUser: BackendMember<TID>;
146
+
147
+ constructor(
148
+ application: IApplication<TID>,
149
+ jwtService: JwtService<TID, TDate, TTokenRole, TTokenUser, TApplication>,
150
+ userService: UserService<
151
+ any,
152
+ TID,
153
+ TDate,
154
+ TLanguage,
155
+ TAccountStatus,
156
+ any,
157
+ any,
158
+ any,
159
+ TUser,
160
+ TTokenRole,
161
+ TApplication
162
+ >,
163
+ backupCodeService: BackupCodeService<TID, TDate, TTokenRole, TApplication>,
164
+ roleService: RoleService<TID, TDate, TTokenRole>,
165
+ eciesService: ECIESService<TID>,
166
+ ) {
167
+ super(application);
168
+ this.jwtService = jwtService;
169
+ this.userService = userService;
170
+ this.backupCodeService = backupCodeService;
171
+ this.roleService = roleService;
172
+ this.eciesService = eciesService;
173
+ this.systemUser = SystemUserService.getSystemUser<TID>(
174
+ application.environment,
175
+ application.constants,
176
+ );
177
+ }
178
+
179
+ @Get('/verify', { auth: true })
180
+ async tokenVerifiedResponse(
181
+ req: Request,
182
+ _res: Response,
183
+ _next: NextFunction,
184
+ ): Promise<IStatusCodeResponse<IApiRequestUserResponse | ApiErrorResponse>> {
185
+ if (!req.user) {
186
+ throw new HandleableError(
187
+ new Error(
188
+ getSuiteCoreTranslation(SuiteCoreStringKey.Common_NoUserOnRequest),
189
+ ),
190
+ {
191
+ statusCode: 401,
192
+ },
193
+ );
194
+ }
195
+ const user = {
196
+ id: req.user.id,
197
+ email: req.user.email,
198
+ username: req.user.username,
199
+ roles: req.user.roles || [],
200
+ rolePrivileges: req.user.rolePrivileges,
201
+ timezone: req.user.timezone,
202
+ currency: req.user.currency,
203
+ emailVerified: req.user.emailVerified,
204
+ darkMode: req.user.darkMode,
205
+ siteLanguage: req.user.siteLanguage,
206
+ directChallenge: req.user.directChallenge,
207
+ ...(req.user.lastLogin && { lastLogin: req.user.lastLogin }),
208
+ };
209
+ return {
210
+ statusCode: 200,
211
+ response: {
212
+ message: getSuiteCoreTranslation(
213
+ SuiteCoreStringKey.Validation_TokenValid,
214
+ ),
215
+ user,
216
+ },
217
+ };
218
+ }
219
+
220
+ @Get('/refresh-token', { auth: true })
221
+ async refreshToken(
222
+ req: Request,
223
+ _res: Response,
224
+ _next: NextFunction,
225
+ ): Promise<IStatusCodeResponse<IApiLoginResponse | ApiErrorResponse>> {
226
+ const token = findAuthToken(req.headers);
227
+ if (!token) {
228
+ throw new GenericValidationError(
229
+ getSuiteCoreTranslation(SuiteCoreStringKey.Validation_TokenMissing),
230
+ );
231
+ }
232
+
233
+ const tokenUser = await this.jwtService.verifyToken(token);
234
+ if (!tokenUser) {
235
+ throw new GenericValidationError(
236
+ getSuiteCoreTranslation(SuiteCoreStringKey.Validation_TokenInvalid),
237
+ );
238
+ }
239
+
240
+ const UserModel = this.application.getModel<IUserDocument<string, TID>>(
241
+ BaseModelName.User,
242
+ );
243
+ const userDoc = await UserModel.findById(tokenUser.userId).select(
244
+ '-password',
245
+ );
246
+ if (!userDoc || userDoc.accountStatus !== AccountStatus.Active) {
247
+ throw new GenericValidationError(
248
+ getSuiteCoreTranslation(SuiteCoreStringKey.Validation_UserNotFound),
249
+ );
250
+ }
251
+ const { token: newToken, roles } = await this.jwtService.signToken(
252
+ userDoc,
253
+ this.application.environment.jwtSecret,
254
+ (req.user?.siteLanguage as string) ?? LanguageCodes.EN_US,
255
+ );
256
+
257
+ return {
258
+ statusCode: 200,
259
+ response: {
260
+ message: getSuiteCoreTranslation(SuiteCoreStringKey.TokenRefreshed),
261
+ user: RequestUserService.makeRequestUserDTO(userDoc, roles),
262
+ token: newToken,
263
+ serverPublicKey: this.application.environment.systemPublicKeyHex ?? '',
264
+ },
265
+ headers: {
266
+ Authorization: `Bearer ${newToken}`,
267
+ },
268
+ };
269
+ }
270
+
271
+ @Post('/register', {
272
+ schema: RegisterSchema,
273
+ validation: function (validationLanguage: TLanguage) {
274
+ const constants = this.constants;
275
+ return [
276
+ body('username')
277
+ .matches(constants.UsernameRegex)
278
+ .withMessage(
279
+ getSuiteCoreTranslation(
280
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate,
281
+ undefined,
282
+ validationLanguage,
283
+ ),
284
+ ),
285
+ body('email')
286
+ .isEmail()
287
+ .withMessage(
288
+ getSuiteCoreTranslation(
289
+ SuiteCoreStringKey.Validation_InvalidEmail,
290
+ undefined,
291
+ validationLanguage,
292
+ ),
293
+ ),
294
+ body('timezone')
295
+ .isString()
296
+ .custom((value) => isValidTimezone(value))
297
+ .withMessage(
298
+ getSuiteCoreTranslation(
299
+ SuiteCoreStringKey.Validation_TimezoneInvalid,
300
+ undefined,
301
+ validationLanguage,
302
+ ),
303
+ ),
304
+ body('password')
305
+ .optional()
306
+ .matches(constants.PasswordRegex)
307
+ .withMessage(
308
+ getSuiteCoreTranslation(
309
+ SuiteCoreStringKey.Validation_PasswordRegexErrorTemplate,
310
+ ),
311
+ ),
312
+ ];
313
+ },
314
+ })
315
+ async register(
316
+ req: Request,
317
+ _res: Response,
318
+ _next: NextFunction,
319
+ ): Promise<IStatusCodeResponse<IApiRegistrationResponse | ApiErrorResponse>> {
320
+ return await withTransaction(
321
+ this.application.db.connection,
322
+ this.application.environment.mongo.useTransactions,
323
+ undefined,
324
+ async (sess) => {
325
+ return await requireValidatedFieldsAsync(
326
+ req,
327
+ RegisterSchema,
328
+ async ({ username, email, timezone, password }) => {
329
+ if (
330
+ !isString(username) ||
331
+ !isString(email) ||
332
+ !isString(timezone)
333
+ ) {
334
+ throw new GenericValidationError(
335
+ getSuiteCoreTranslation(
336
+ SuiteCoreStringKey.Validation_MissingValidatedData,
337
+ ),
338
+ );
339
+ }
340
+
341
+ const { user, mnemonic, backupCodes } =
342
+ await this.userService.newUser(
343
+ this.systemUser,
344
+ {
345
+ username: username.trim(),
346
+ email: email.trim(),
347
+ timezone: timezone,
348
+ },
349
+ undefined,
350
+ undefined,
351
+ sess,
352
+ this.application.environment.debug,
353
+ password as string | undefined,
354
+ );
355
+
356
+ await this.userService.createAndSendEmailToken(
357
+ user,
358
+ EmailTokenType.AccountVerification,
359
+ sess,
360
+ this.application.environment.debug,
361
+ );
362
+
363
+ return {
364
+ statusCode: 201,
365
+ response: {
366
+ message: getSuiteCoreTranslation(
367
+ SuiteCoreStringKey.Registration_Success,
368
+ { MNEMONIC: mnemonic },
369
+ ),
370
+ mnemonic,
371
+ backupCodes,
372
+ },
373
+ };
374
+ },
375
+ );
376
+ },
377
+ {
378
+ timeoutMs: this.application.environment.mongo.transactionTimeout * 30,
379
+ },
380
+ );
381
+ }
382
+
383
+ @Post('/account-verification', {
384
+ validation: function (validationLanguage: TLanguage) {
385
+ const constants = this.constants;
386
+ return [
387
+ body('token')
388
+ .not()
389
+ .isEmpty()
390
+ .withMessage(
391
+ getSuiteCoreTranslation(
392
+ SuiteCoreStringKey.Validation_TokenRequired,
393
+ undefined,
394
+ validationLanguage,
395
+ ),
396
+ )
397
+ .matches(new RegExp(`^[a-f0-9]{${constants.EmailTokenLength * 2}}$`))
398
+ .withMessage(
399
+ getSuiteCoreTranslation(
400
+ SuiteCoreStringKey.Validation_InvalidToken,
401
+ undefined,
402
+ validationLanguage,
403
+ ),
404
+ ),
405
+ ];
406
+ },
407
+ })
408
+ async completeAccountVerification(
409
+ _req: Request,
410
+ _res: Response,
411
+ _next: NextFunction,
412
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
413
+ const { token } = this.validatedBody as { token?: unknown };
414
+
415
+ return await withTransaction(
416
+ this.application.db.connection,
417
+ this.application.environment.mongo.useTransactions,
418
+ undefined,
419
+ async (sess) => {
420
+ await this.userService.verifyAccountTokenAndComplete(
421
+ token as string,
422
+ sess,
423
+ );
424
+ return {
425
+ statusCode: 200,
426
+ response: {
427
+ message: getSuiteCoreTranslation(
428
+ SuiteCoreStringKey.EmailVerification_Success,
429
+ ),
430
+ },
431
+ };
432
+ },
433
+ );
434
+ }
435
+
436
+ @Post('/language', {
437
+ auth: true,
438
+ validation: function (validationLanguage: TLanguage) {
439
+ return [
440
+ body('language')
441
+ .isString()
442
+ .withMessage(
443
+ getSuiteCoreTranslation(
444
+ SuiteCoreStringKey.Validation_InvalidLanguage,
445
+ undefined,
446
+ validationLanguage,
447
+ ),
448
+ )
449
+ .isIn(Object.values(LanguageCodes))
450
+ .withMessage(
451
+ getSuiteCoreTranslation(
452
+ SuiteCoreStringKey.Validation_InvalidLanguage,
453
+ undefined,
454
+ validationLanguage,
455
+ ),
456
+ ),
457
+ ];
458
+ },
459
+ })
460
+ async setLanguage(
461
+ req: Request,
462
+ _res: Response,
463
+ _next: NextFunction,
464
+ ): Promise<IStatusCodeResponse<IApiRequestUserResponse | ApiErrorResponse>> {
465
+ return await withTransaction(
466
+ this.application.db.connection,
467
+ this.application.environment.mongo.useTransactions,
468
+ undefined,
469
+ async (sess) => {
470
+ const { language } = this.validatedBody as { language?: unknown };
471
+ if (!req.user) {
472
+ throw new HandleableError(
473
+ new Error(
474
+ getSuiteCoreTranslation(
475
+ SuiteCoreStringKey.Common_NoUserOnRequest,
476
+ ),
477
+ ),
478
+ { statusCode: 401 },
479
+ );
480
+ }
481
+
482
+ const user = await this.userService.updateSiteLanguage(
483
+ req.user.id,
484
+ language as string,
485
+ sess,
486
+ );
487
+
488
+ return {
489
+ statusCode: 200,
490
+ response: {
491
+ message: getSuiteCoreTranslation(
492
+ SuiteCoreStringKey.LanguageUpdate_Success,
493
+ ),
494
+ user,
495
+ },
496
+ };
497
+ },
498
+ );
499
+ }
500
+
501
+ @Post('/dark-mode', {
502
+ auth: true,
503
+ validation: function (validationLanguage: TLanguage) {
504
+ return [
505
+ body('darkMode')
506
+ .isBoolean()
507
+ .withMessage(
508
+ getSuiteCoreTranslation(
509
+ SuiteCoreStringKey.Validation_Required,
510
+ undefined,
511
+ validationLanguage,
512
+ ),
513
+ ),
514
+ ];
515
+ },
516
+ })
517
+ async setDarkMode(
518
+ req: Request,
519
+ _res: Response,
520
+ _next: NextFunction,
521
+ ): Promise<IStatusCodeResponse<IApiRequestUserResponse | ApiErrorResponse>> {
522
+ return await withTransaction(
523
+ this.application.db.connection,
524
+ this.application.environment.mongo.useTransactions,
525
+ undefined,
526
+ async (sess) => {
527
+ const { darkMode } = this.validatedBody as { darkMode?: unknown };
528
+ if (!req.user) {
529
+ throw new HandleableError(
530
+ new Error(
531
+ getSuiteCoreTranslation(
532
+ SuiteCoreStringKey.Common_NoUserOnRequest,
533
+ ),
534
+ ),
535
+ { statusCode: 401 },
536
+ );
537
+ }
538
+
539
+ const user = await this.userService.updateDarkMode(
540
+ req.user.id,
541
+ darkMode as boolean,
542
+ sess,
543
+ );
544
+
545
+ return {
546
+ statusCode: 200,
547
+ response: {
548
+ message: getSuiteCoreTranslation(
549
+ SuiteCoreStringKey.Settings_DarkModeSuccess,
550
+ ),
551
+ user,
552
+ },
553
+ };
554
+ },
555
+ );
556
+ }
557
+
558
+ @Get('/settings', { auth: true })
559
+ async getSettings(
560
+ req: Request,
561
+ _res: Response,
562
+ _next: NextFunction,
563
+ ): Promise<IStatusCodeResponse<IApiUserSettingsResponse | ApiErrorResponse>> {
564
+ if (!req.user) {
565
+ throw new HandleableError(
566
+ new Error(
567
+ getSuiteCoreTranslation(SuiteCoreStringKey.Common_NoUserOnRequest),
568
+ ),
569
+ { statusCode: 401 },
570
+ );
571
+ }
572
+
573
+ const UserModel = this.application.getModel<IUserDocument<string, TID>>(
574
+ BaseModelName.User,
575
+ );
576
+ const userDoc = await UserModel.findById(req.user.id);
577
+
578
+ return {
579
+ statusCode: 200,
580
+ response: {
581
+ message: getSuiteCoreTranslation(
582
+ SuiteCoreStringKey.Settings_RetrievedSuccess,
583
+ ),
584
+ settings: {
585
+ email: userDoc?.email || '',
586
+ timezone: userDoc?.timezone || '',
587
+ currency: userDoc?.currency || '',
588
+ siteLanguage: userDoc?.siteLanguage || '',
589
+ darkMode: userDoc?.darkMode || false,
590
+ directChallenge: userDoc?.directChallenge || false,
591
+ },
592
+ },
593
+ };
594
+ }
595
+
596
+ @Post('/settings', {
597
+ auth: true,
598
+ validation: function (validationLanguage: TLanguage) {
599
+ return [
600
+ body('email')
601
+ .optional()
602
+ .isEmail()
603
+ .withMessage(
604
+ getSuiteCoreTranslation(
605
+ SuiteCoreStringKey.Validation_InvalidEmail,
606
+ undefined,
607
+ validationLanguage,
608
+ ),
609
+ ),
610
+ body('timezone')
611
+ .optional()
612
+ .isString()
613
+ .custom((value) => isValidTimezone(value))
614
+ .withMessage(
615
+ getSuiteCoreTranslation(
616
+ SuiteCoreStringKey.Validation_TimezoneInvalid,
617
+ undefined,
618
+ validationLanguage,
619
+ ),
620
+ ),
621
+ body('siteLanguage')
622
+ .optional()
623
+ .isString()
624
+ .isIn(Object.values(LanguageCodes))
625
+ .withMessage(
626
+ getSuiteCoreTranslation(
627
+ SuiteCoreStringKey.Validation_InvalidLanguage,
628
+ undefined,
629
+ validationLanguage,
630
+ ),
631
+ ),
632
+ body('currency')
633
+ .optional()
634
+ .isString()
635
+ .withMessage(
636
+ getSuiteCoreTranslation(
637
+ SuiteCoreStringKey.Validation_CurrencyCodeRequired,
638
+ undefined,
639
+ validationLanguage,
640
+ ),
641
+ ),
642
+ body('darkMode')
643
+ .optional()
644
+ .isBoolean()
645
+ .withMessage(
646
+ getSuiteCoreTranslation(
647
+ SuiteCoreStringKey.Validation_Required,
648
+ undefined,
649
+ validationLanguage,
650
+ ),
651
+ ),
652
+ body('directChallenge')
653
+ .optional()
654
+ .isBoolean()
655
+ .withMessage(
656
+ getSuiteCoreTranslation(
657
+ SuiteCoreStringKey.Validation_Required,
658
+ undefined,
659
+ validationLanguage,
660
+ ),
661
+ ),
662
+ ];
663
+ },
664
+ })
665
+ async updateSettings(
666
+ req: Request,
667
+ _res: Response,
668
+ _next: NextFunction,
669
+ ): Promise<IStatusCodeResponse<IApiRequestUserResponse | ApiErrorResponse>> {
670
+ return await withTransaction(
671
+ this.application.db.connection,
672
+ this.application.environment.mongo.useTransactions,
673
+ undefined,
674
+ async (sess) => {
675
+ const {
676
+ email,
677
+ timezone,
678
+ siteLanguage,
679
+ currency,
680
+ darkMode,
681
+ directChallenge,
682
+ } = this.validatedBody;
683
+ if (!req.user) {
684
+ throw new HandleableError(
685
+ new Error(
686
+ getSuiteCoreTranslation(
687
+ SuiteCoreStringKey.Common_NoUserOnRequest,
688
+ ),
689
+ ),
690
+ { statusCode: 401 },
691
+ );
692
+ }
693
+
694
+ const user = await this.userService.updateUserSettings(
695
+ req.user.id,
696
+ {
697
+ ...(email !== undefined && { email: email as string }),
698
+ ...(timezone !== undefined && { timezone: timezone as string }),
699
+ ...(siteLanguage !== undefined && {
700
+ siteLanguage: siteLanguage as TLanguage,
701
+ }),
702
+ ...(currency !== undefined && { currency: currency as string }),
703
+ ...(darkMode !== undefined && { darkMode: darkMode as boolean }),
704
+ ...(directChallenge !== undefined && {
705
+ directChallenge: directChallenge as boolean,
706
+ }),
707
+ },
708
+ sess,
709
+ );
710
+
711
+ return {
712
+ statusCode: 200,
713
+ response: {
714
+ message: getSuiteCoreTranslation(
715
+ SuiteCoreStringKey.Settings_SaveSuccess,
716
+ ),
717
+ user,
718
+ },
719
+ };
720
+ },
721
+ );
722
+ }
723
+
724
+ @Get('/backup-codes', { auth: true })
725
+ async getBackupCodeCount(
726
+ req: Request,
727
+ _res: Response,
728
+ _next: NextFunction,
729
+ ): Promise<IStatusCodeResponse<IApiCodeCountResponse | ApiErrorResponse>> {
730
+ if (!req.user) {
731
+ throw new HandleableError(
732
+ new Error(
733
+ getSuiteCoreTranslation(SuiteCoreStringKey.Common_NoUserOnRequest),
734
+ ),
735
+ { statusCode: 401 },
736
+ );
737
+ }
738
+
739
+ const UserModel = this.application.getModel<IUserDocument<string, TID>>(
740
+ BaseModelName.User,
741
+ );
742
+ const user = await UserModel.findById(req.user.id);
743
+
744
+ return {
745
+ statusCode: 200,
746
+ response: {
747
+ message: 'Backup codes retrieved',
748
+ codeCount: user?.backupCodes?.length || 0,
749
+ } as IApiCodeCountResponse,
750
+ };
751
+ }
752
+
753
+ @Post('/backup-codes', {
754
+ auth: true,
755
+ cryptoAuth: true,
756
+ validation: function (validationLanguage: TLanguage) {
757
+ const constants = this.constants;
758
+ return [
759
+ body().custom((value, { req }) => {
760
+ if (!req.body?.password && !req.body?.mnemonic) {
761
+ throw new MnemonicOrPasswordRequiredError();
762
+ }
763
+ return true;
764
+ }),
765
+ body('password')
766
+ .optional()
767
+ .notEmpty()
768
+ .withMessage(
769
+ getSuiteCoreTranslation(
770
+ SuiteCoreStringKey.Validation_CurrentPasswordRequired,
771
+ undefined,
772
+ validationLanguage,
773
+ ),
774
+ ),
775
+ body('mnemonic')
776
+ .optional()
777
+ .notEmpty()
778
+ .withMessage(
779
+ getSuiteCoreTranslation(
780
+ SuiteCoreStringKey.Validation_MnemonicRequired,
781
+ undefined,
782
+ validationLanguage,
783
+ ),
784
+ )
785
+ .matches(constants.MnemonicRegex)
786
+ .withMessage(
787
+ getSuiteCoreTranslation(
788
+ SuiteCoreStringKey.Validation_MnemonicRegex,
789
+ undefined,
790
+ validationLanguage,
791
+ ),
792
+ ),
793
+ ];
794
+ },
795
+ })
796
+ async resetBackupCodes(
797
+ req: Request,
798
+ _res: Response,
799
+ _next: NextFunction,
800
+ ): Promise<IStatusCodeResponse<IApiBackupCodesResponse | ApiErrorResponse>> {
801
+ if (!req.user || !req.eciesUser || !req.eciesUser.hasPrivateKey) {
802
+ throw new HandleableError(
803
+ new Error(
804
+ getSuiteCoreTranslation(SuiteCoreStringKey.Common_NoUserOnRequest),
805
+ ),
806
+ { statusCode: 401 },
807
+ );
808
+ }
809
+
810
+ const newBackupCodes = await this.userService.resetUserBackupCodes(
811
+ req.eciesUser as BackendMember<TID>,
812
+ this.systemUser,
813
+ );
814
+ const codes = newBackupCodes.map((c) => c.notNullValue);
815
+ newBackupCodes.forEach((c) => c.dispose());
816
+
817
+ return {
818
+ statusCode: 200,
819
+ response: {
820
+ message: getSuiteCoreTranslation(
821
+ SuiteCoreStringKey.BackupCodeRecovery_YourNewCodes,
822
+ ),
823
+ backupCodes: codes,
824
+ },
825
+ };
826
+ }
827
+
828
+ @Post('/recover-mnemonic', {
829
+ auth: true,
830
+ cryptoAuth: true,
831
+ validation: function (validationLanguage: TLanguage) {
832
+ return [
833
+ body('password')
834
+ .isString()
835
+ .withMessage(
836
+ getSuiteCoreTranslation(
837
+ SuiteCoreStringKey.Validation_CurrentPasswordRequired,
838
+ undefined,
839
+ validationLanguage,
840
+ ),
841
+ ),
842
+ ];
843
+ },
844
+ })
845
+ async recoverMnemonic(
846
+ req: Request,
847
+ _res: Response,
848
+ _next: NextFunction,
849
+ ): Promise<IStatusCodeResponse<IApiMnemonicResponse | ApiErrorResponse>> {
850
+ return await withTransaction(
851
+ this.application.db.connection,
852
+ this.application.environment.mongo.useTransactions,
853
+ undefined,
854
+ async (sess) => {
855
+ if (!req.user) {
856
+ throw new HandleableError(
857
+ new Error(
858
+ getSuiteCoreTranslation(
859
+ SuiteCoreStringKey.Validation_InvalidCredentials,
860
+ ),
861
+ ),
862
+ { statusCode: 401 },
863
+ );
864
+ } else if (!req.eciesUser) {
865
+ throw new HandleableError(
866
+ new Error(
867
+ getSuiteCoreTranslation(
868
+ SuiteCoreStringKey.Validation_MnemonicOrPasswordRequired,
869
+ ),
870
+ ),
871
+ { statusCode: 401 },
872
+ );
873
+ }
874
+
875
+ const { password } = this.validatedBody as { password?: unknown };
876
+ if (!isString(password)) {
877
+ throw new GenericValidationError(
878
+ getSuiteCoreTranslation(
879
+ SuiteCoreStringKey.Validation_MissingValidatedData,
880
+ ),
881
+ );
882
+ }
883
+ const provider = getEnhancedNodeIdProvider<TID>();
884
+ const userDoc = await this.userService.findUserById(
885
+ provider.idFromString(req.user.id),
886
+ true,
887
+ sess,
888
+ );
889
+
890
+ const mnemonic = await this.userService.recoverMnemonic(
891
+ req.eciesUser,
892
+ userDoc.mnemonicRecovery,
893
+ );
894
+
895
+ return {
896
+ statusCode: 200,
897
+ response: {
898
+ message: getSuiteCoreTranslation(
899
+ SuiteCoreStringKey.MnemonicRecovery_Success,
900
+ ),
901
+ mnemonic: mnemonic.notNullValue,
902
+ },
903
+ };
904
+ },
905
+ );
906
+ }
907
+
908
+ @Post('/change-password', {
909
+ auth: true,
910
+ validation: function (validationLanguage: TLanguage) {
911
+ const constants = this.constants;
912
+ return [
913
+ body('currentPassword')
914
+ .notEmpty()
915
+ .withMessage(
916
+ getSuiteCoreTranslation(
917
+ SuiteCoreStringKey.Validation_Required,
918
+ undefined,
919
+ validationLanguage,
920
+ ),
921
+ ),
922
+ body('newPassword')
923
+ .matches(constants.PasswordRegex)
924
+ .withMessage(
925
+ getSuiteCoreTranslation(
926
+ SuiteCoreStringKey.Validation_PasswordRegexErrorTemplate,
927
+ ),
928
+ )
929
+ .notEmpty()
930
+ .withMessage(
931
+ getSuiteCoreTranslation(
932
+ SuiteCoreStringKey.Validation_Required,
933
+ undefined,
934
+ validationLanguage,
935
+ ),
936
+ ),
937
+ ];
938
+ },
939
+ })
940
+ async changePassword(
941
+ req: Request,
942
+ _res: Response,
943
+ _next: NextFunction,
944
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
945
+ return await withTransaction(
946
+ this.application.db.connection,
947
+ this.application.environment.mongo.useTransactions,
948
+ undefined,
949
+ async (sess) => {
950
+ const { currentPassword, newPassword } = this.validatedBody as {
951
+ currentPassword?: unknown;
952
+ newPassword?: unknown;
953
+ };
954
+ if (!req.user) {
955
+ throw new HandleableError(
956
+ new Error(
957
+ getSuiteCoreTranslation(
958
+ SuiteCoreStringKey.Common_NoUserOnRequest,
959
+ ),
960
+ ),
961
+ { statusCode: 401 },
962
+ );
963
+ }
964
+
965
+ if (!isString(currentPassword) || !isString(newPassword)) {
966
+ throw new GenericValidationError(
967
+ getSuiteCoreTranslation(
968
+ SuiteCoreStringKey.Validation_MissingValidatedData,
969
+ ),
970
+ );
971
+ }
972
+
973
+ await this.userService.changePassword(
974
+ req.user.id,
975
+ currentPassword,
976
+ newPassword,
977
+ sess,
978
+ );
979
+
980
+ return {
981
+ statusCode: 200,
982
+ response: {
983
+ message: getSuiteCoreTranslation(
984
+ SuiteCoreStringKey.PasswordChange_Success,
985
+ ),
986
+ },
987
+ };
988
+ },
989
+ );
990
+ }
991
+
992
+ @Post('/request-direct-login')
993
+ async requestDirectLogin(
994
+ _req: Request,
995
+ _res: Response,
996
+ _next: NextFunction,
997
+ ): Promise<IStatusCodeResponse<IApiChallengeResponse | ApiErrorResponse>> {
998
+ const challenge = this.userService.generateDirectLoginChallenge();
999
+ return {
1000
+ statusCode: 200,
1001
+ response: {
1002
+ challenge: challenge,
1003
+ message: getSuiteCoreTranslation(
1004
+ SuiteCoreStringKey.Login_ChallengeGenerated,
1005
+ ),
1006
+ serverPublicKey: this.application.environment.systemPublicKeyHex ?? '',
1007
+ },
1008
+ };
1009
+ }
1010
+
1011
+ @Post('/direct-challenge', {
1012
+ schema: DirectLoginChallengeSchema,
1013
+ validation: function (validationLanguage: TLanguage) {
1014
+ const constants = this.constants;
1015
+ return [
1016
+ body('challenge')
1017
+ .not()
1018
+ .isEmpty()
1019
+ .withMessage(
1020
+ getSuiteCoreTranslation(
1021
+ SuiteCoreStringKey.Validation_InvalidChallenge,
1022
+ undefined,
1023
+ validationLanguage,
1024
+ ),
1025
+ )
1026
+ .matches(
1027
+ new RegExp(
1028
+ `^[a-f0-9]{${(UINT64_SIZE + 32 + ECIES.SIGNATURE_SIZE) * 2}}$`,
1029
+ ),
1030
+ )
1031
+ .withMessage(
1032
+ getSuiteCoreTranslation(
1033
+ SuiteCoreStringKey.Validation_InvalidChallenge,
1034
+ undefined,
1035
+ validationLanguage,
1036
+ ),
1037
+ ),
1038
+ body('signature')
1039
+ .not()
1040
+ .isEmpty()
1041
+ .withMessage(
1042
+ getSuiteCoreTranslation(
1043
+ SuiteCoreStringKey.Validation_InvalidSignature,
1044
+ ),
1045
+ )
1046
+ .matches(new RegExp(`^[a-f0-9]{${ECIES.SIGNATURE_SIZE * 2}}$`))
1047
+ .withMessage(SuiteCoreStringKey.Validation_InvalidSignature),
1048
+ body().custom((value, { req }) => {
1049
+ if (!req.body.username && !req.body.email) {
1050
+ throw new UsernameOrEmailRequiredError();
1051
+ }
1052
+ return true;
1053
+ }),
1054
+ body('username')
1055
+ .optional()
1056
+ .matches(constants.UsernameRegex)
1057
+ .withMessage(
1058
+ getSuiteCoreTranslation(
1059
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate,
1060
+ undefined,
1061
+ validationLanguage,
1062
+ ),
1063
+ ),
1064
+ body('email')
1065
+ .optional()
1066
+ .isEmail()
1067
+ .withMessage(
1068
+ getSuiteCoreTranslation(
1069
+ SuiteCoreStringKey.Validation_InvalidEmail,
1070
+ undefined,
1071
+ validationLanguage,
1072
+ ),
1073
+ ),
1074
+ ];
1075
+ },
1076
+ })
1077
+ async directLoginChallenge(
1078
+ req: Request,
1079
+ _res: Response,
1080
+ _next: NextFunction,
1081
+ ): Promise<IStatusCodeResponse<IApiLoginResponse | ApiErrorResponse>> {
1082
+ return await withTransaction(
1083
+ this.application.db.connection,
1084
+ this.application.environment.mongo.useTransactions,
1085
+ undefined,
1086
+ async (sess) => {
1087
+ const { username, email, challenge, signature } = this
1088
+ .validatedBody as {
1089
+ username?: unknown;
1090
+ email?: unknown;
1091
+ challenge?: unknown;
1092
+ signature?: unknown;
1093
+ };
1094
+
1095
+ const { userDoc } = await this.userService.verifyDirectLoginChallenge(
1096
+ String(challenge),
1097
+ String(signature),
1098
+ username ? String(username) : undefined,
1099
+ email ? String(email) : undefined,
1100
+ sess,
1101
+ );
1102
+
1103
+ const { token: jwtToken, roles } = await this.jwtService.signToken(
1104
+ userDoc,
1105
+ this.application.environment.jwtSecret,
1106
+ (req.user?.siteLanguage as string) ?? LanguageCodes.EN_US,
1107
+ );
1108
+
1109
+ return {
1110
+ statusCode: 200,
1111
+ response: {
1112
+ user: RequestUserService.makeRequestUserDTO(userDoc, roles),
1113
+ token: jwtToken,
1114
+ serverPublicKey:
1115
+ this.application.environment.systemPublicKeyHex ?? '',
1116
+ message: getSuiteCoreTranslation(
1117
+ SuiteCoreStringKey.LoggedIn_Success,
1118
+ ),
1119
+ },
1120
+ };
1121
+ },
1122
+ );
1123
+ }
1124
+
1125
+ @Post('/request-email-login', {
1126
+ validation: function (validationLanguage: TLanguage) {
1127
+ const constants = this.constants;
1128
+ return [
1129
+ body().custom((value, { req }) => {
1130
+ if (!req.body.username && !req.body.email) {
1131
+ throw new UsernameOrEmailRequiredError();
1132
+ }
1133
+ return true;
1134
+ }),
1135
+ body('username')
1136
+ .optional()
1137
+ .matches(constants.UsernameRegex)
1138
+ .withMessage(
1139
+ getSuiteCoreTranslation(
1140
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate,
1141
+ undefined,
1142
+ validationLanguage,
1143
+ ),
1144
+ ),
1145
+ body('email')
1146
+ .optional()
1147
+ .isEmail()
1148
+ .withMessage(
1149
+ getSuiteCoreTranslation(
1150
+ SuiteCoreStringKey.Validation_InvalidEmail,
1151
+ undefined,
1152
+ validationLanguage,
1153
+ ),
1154
+ ),
1155
+ ];
1156
+ },
1157
+ })
1158
+ async requestEmailLogin(
1159
+ _req: Request,
1160
+ _res: Response,
1161
+ _next: NextFunction,
1162
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
1163
+ const { username, email } = this.validatedBody as {
1164
+ username?: unknown;
1165
+ email?: unknown;
1166
+ };
1167
+
1168
+ try {
1169
+ await withTransaction(
1170
+ this.application.db.connection,
1171
+ this.application.environment.mongo.useTransactions,
1172
+ undefined,
1173
+ async (sess) => {
1174
+ const userDoc = await this.userService.findUser(
1175
+ email as string,
1176
+ username as string,
1177
+ sess,
1178
+ );
1179
+ await this.userService.createAndSendEmailToken(
1180
+ userDoc,
1181
+ EmailTokenType.LoginRequest,
1182
+ sess,
1183
+ this.application.environment.debug,
1184
+ );
1185
+ },
1186
+ );
1187
+ } catch {
1188
+ // Suppress user-related errors for security
1189
+ }
1190
+
1191
+ return {
1192
+ statusCode: 200,
1193
+ response: {
1194
+ message: getSuiteCoreTranslation(SuiteCoreStringKey.Email_TokenSent),
1195
+ },
1196
+ };
1197
+ }
1198
+
1199
+ @Post('/email-challenge', {
1200
+ schema: EmailLoginChallengeSchema,
1201
+ validation: function (validationLanguage: TLanguage) {
1202
+ const constants = this.constants;
1203
+ return [
1204
+ body('token')
1205
+ .not()
1206
+ .isEmpty()
1207
+ .withMessage(
1208
+ getSuiteCoreTranslation(
1209
+ SuiteCoreStringKey.Validation_TokenRequired,
1210
+ undefined,
1211
+ validationLanguage,
1212
+ ),
1213
+ )
1214
+ .matches(new RegExp(`^[a-f0-9]{${constants.EmailTokenLength * 2}}$`))
1215
+ .withMessage(
1216
+ getSuiteCoreTranslation(
1217
+ SuiteCoreStringKey.Validation_InvalidToken,
1218
+ undefined,
1219
+ validationLanguage,
1220
+ ),
1221
+ ),
1222
+ body('signature')
1223
+ .not()
1224
+ .isEmpty()
1225
+ .withMessage(
1226
+ getSuiteCoreTranslation(
1227
+ SuiteCoreStringKey.Validation_InvalidSignature,
1228
+ ),
1229
+ )
1230
+ .matches(new RegExp(`^[a-f0-9]{${ECIES.SIGNATURE_SIZE * 2}}$`))
1231
+ .withMessage(SuiteCoreStringKey.Validation_InvalidSignature),
1232
+ body().custom((value, { req }) => {
1233
+ if (!req.body.username && !req.body.email) {
1234
+ throw new UsernameOrEmailRequiredError();
1235
+ }
1236
+ return true;
1237
+ }),
1238
+ body('username')
1239
+ .optional()
1240
+ .matches(constants.UsernameRegex)
1241
+ .withMessage(
1242
+ getSuiteCoreTranslation(
1243
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate,
1244
+ undefined,
1245
+ validationLanguage,
1246
+ ),
1247
+ ),
1248
+ body('email')
1249
+ .optional()
1250
+ .isEmail()
1251
+ .withMessage(
1252
+ getSuiteCoreTranslation(
1253
+ SuiteCoreStringKey.Validation_InvalidEmail,
1254
+ undefined,
1255
+ validationLanguage,
1256
+ ),
1257
+ ),
1258
+ ];
1259
+ },
1260
+ })
1261
+ async emailLoginChallenge(
1262
+ req: Request,
1263
+ _res: Response,
1264
+ _next: NextFunction,
1265
+ ): Promise<IStatusCodeResponse<IApiLoginResponse | ApiErrorResponse>> {
1266
+ return await withTransaction(
1267
+ this.application.db.connection,
1268
+ this.application.environment.mongo.useTransactions,
1269
+ undefined,
1270
+ async (sess) => {
1271
+ const { token, signature } = this.validatedBody as {
1272
+ token?: unknown;
1273
+ signature?: unknown;
1274
+ };
1275
+
1276
+ const userDoc = await this.userService.validateEmailLoginTokenChallenge(
1277
+ String(token),
1278
+ String(signature),
1279
+ sess,
1280
+ );
1281
+
1282
+ const { token: jwtToken, roles } = await this.jwtService.signToken(
1283
+ userDoc,
1284
+ this.application.environment.jwtSecret,
1285
+ (req.user?.siteLanguage as string) ?? LanguageCodes.EN_US,
1286
+ );
1287
+
1288
+ return {
1289
+ statusCode: 200,
1290
+ response: {
1291
+ user: RequestUserService.makeRequestUserDTO(userDoc, roles),
1292
+ token: jwtToken,
1293
+ serverPublicKey:
1294
+ this.application.environment.systemPublicKeyHex ?? '',
1295
+ message: getSuiteCoreTranslation(
1296
+ SuiteCoreStringKey.LoggedIn_Success,
1297
+ ),
1298
+ },
1299
+ };
1300
+ },
1301
+ );
1302
+ }
1303
+
1304
+ @Post('/resend-verification', {
1305
+ validation: function (validationLanguage: TLanguage) {
1306
+ const constants = this.constants;
1307
+ return [
1308
+ body().custom((value, { req }) => {
1309
+ if (!req.body.username && !req.body.email) {
1310
+ throw new UsernameOrEmailRequiredError();
1311
+ }
1312
+ return true;
1313
+ }),
1314
+ body('username')
1315
+ .optional()
1316
+ .isString()
1317
+ .matches(constants.UsernameRegex)
1318
+ .withMessage(
1319
+ getSuiteCoreTranslation(
1320
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate,
1321
+ undefined,
1322
+ validationLanguage,
1323
+ ),
1324
+ ),
1325
+ body('email').optional().isEmail(),
1326
+ ];
1327
+ },
1328
+ })
1329
+ async resendVerification(
1330
+ _req: Request,
1331
+ _res: Response,
1332
+ _next: NextFunction,
1333
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
1334
+ return await withTransaction(
1335
+ this.application.db.connection,
1336
+ this.application.environment.mongo.useTransactions,
1337
+ undefined,
1338
+ async (sess) => {
1339
+ const { username, email } = this.validatedBody as {
1340
+ username?: unknown;
1341
+ email?: unknown;
1342
+ };
1343
+
1344
+ const UserModel = this.application.getModel<IUserDocument<string, TID>>(
1345
+ BaseModelName.User,
1346
+ );
1347
+ const query: { username?: string; email?: string } = {};
1348
+ if (isString(username)) query.username = username;
1349
+ else if (isString(email)) query.email = email;
1350
+ else {
1351
+ throw new GenericValidationError(
1352
+ getSuiteCoreTranslation(
1353
+ SuiteCoreStringKey.Validation_MissingValidatedData,
1354
+ ),
1355
+ );
1356
+ }
1357
+
1358
+ const user = await UserModel.findOne(query).session(sess ?? null);
1359
+ if (!user) {
1360
+ throw new GenericValidationError(
1361
+ getSuiteCoreTranslation(SuiteCoreStringKey.Validation_UserNotFound),
1362
+ { statusCode: 404 },
1363
+ );
1364
+ }
1365
+
1366
+ await this.userService.resendEmailToken(
1367
+ user._id.toString(),
1368
+ EmailTokenType.AccountVerification,
1369
+ sess,
1370
+ this.application.environment.debug,
1371
+ );
1372
+
1373
+ return {
1374
+ statusCode: 200,
1375
+ response: {
1376
+ message: getSuiteCoreTranslation(
1377
+ SuiteCoreStringKey.EmailVerification_Resent,
1378
+ ),
1379
+ },
1380
+ };
1381
+ },
1382
+ );
1383
+ }
1384
+
1385
+ @Post('/backup-code', {
1386
+ validation: function (validationLanguage: TLanguage) {
1387
+ const constants = this.constants;
1388
+ return [
1389
+ body('email').optional().isEmail(),
1390
+ body('username')
1391
+ .optional()
1392
+ .matches(constants.UsernameRegex)
1393
+ .withMessage(
1394
+ getSuiteCoreTranslation(
1395
+ SuiteCoreStringKey.Validation_UsernameRegexErrorTemplate,
1396
+ undefined,
1397
+ validationLanguage,
1398
+ ),
1399
+ ),
1400
+ body('code')
1401
+ .custom((value) => {
1402
+ const normalized = BackupCode.normalizeCode(value);
1403
+ return (
1404
+ constants.BACKUP_CODES.DisplayRegex.test(value) ||
1405
+ constants.BACKUP_CODES.NormalizedHexRegex.test(normalized)
1406
+ );
1407
+ })
1408
+ .withMessage(
1409
+ getSuiteCoreTranslation(
1410
+ SuiteCoreStringKey.Validation_InvalidBackupCode,
1411
+ undefined,
1412
+ validationLanguage,
1413
+ ),
1414
+ ),
1415
+ body('recoverMnemonic').isBoolean().optional(),
1416
+ body('newPassword')
1417
+ .optional()
1418
+ .matches(constants.PasswordRegex)
1419
+ .withMessage(
1420
+ getSuiteCoreTranslation(
1421
+ SuiteCoreStringKey.Validation_PasswordRegexErrorTemplate,
1422
+ undefined,
1423
+ validationLanguage,
1424
+ ),
1425
+ ),
1426
+ ];
1427
+ },
1428
+ })
1429
+ async useBackupCodeLogin(
1430
+ _req: Request,
1431
+ _res: Response,
1432
+ _next: NextFunction,
1433
+ ): Promise<IStatusCodeResponse<IApiLoginResponse | ApiErrorResponse>> {
1434
+ return await withTransaction(
1435
+ this.application.db.connection,
1436
+ this.application.environment.mongo.useTransactions,
1437
+ undefined,
1438
+ async (sess) => {
1439
+ const { code, newPassword, email, username } = this.validatedBody as {
1440
+ code?: unknown;
1441
+ newPassword?: unknown;
1442
+ email?: unknown;
1443
+ username?: unknown;
1444
+ };
1445
+
1446
+ if (!code) {
1447
+ throw new GenericValidationError(
1448
+ getSuiteCoreTranslation(
1449
+ SuiteCoreStringKey.Validation_MissingValidatedData,
1450
+ ),
1451
+ );
1452
+ }
1453
+
1454
+ const recoverMnemonic =
1455
+ this.validatedBody?.['recoverMnemonic'] === 'true' ||
1456
+ this.validatedBody?.['recoverMnemonic'] === true;
1457
+
1458
+ const userDoc = await this.userService.findUser(
1459
+ email as string,
1460
+ username as string,
1461
+ sess,
1462
+ );
1463
+
1464
+ const {
1465
+ user,
1466
+ userDoc: updatedUserDoc,
1467
+ codeCount,
1468
+ } = await this.backupCodeService.recoverKeyWithBackupCode(
1469
+ userDoc,
1470
+ code as string,
1471
+ newPassword ? new SecureString(newPassword as string) : undefined,
1472
+ sess,
1473
+ );
1474
+
1475
+ let mnemonic: SecureString | undefined;
1476
+ if (recoverMnemonic) {
1477
+ mnemonic = await this.userService.recoverMnemonic(
1478
+ user,
1479
+ updatedUserDoc.mnemonicRecovery,
1480
+ );
1481
+ }
1482
+
1483
+ const { token, roles } = await this.jwtService.signToken(
1484
+ userDoc,
1485
+ this.application.environment.jwtSecret,
1486
+ LanguageCodes.EN_US,
1487
+ );
1488
+
1489
+ this.userService.updateLastLogin(updatedUserDoc._id).catch(() => {});
1490
+
1491
+ return {
1492
+ statusCode: 200,
1493
+ response: {
1494
+ user: RequestUserService.makeRequestUserDTO(userDoc, roles),
1495
+ token: token,
1496
+ message: getSuiteCoreTranslation(
1497
+ SuiteCoreStringKey.BackupCodeRecovery_Success,
1498
+ ),
1499
+ codeCount,
1500
+ ...(recoverMnemonic && mnemonic
1501
+ ? { mnemonic: mnemonic.value }
1502
+ : {}),
1503
+ serverPublicKey:
1504
+ this.application.environment.systemPublicKeyHex ?? '',
1505
+ },
1506
+ };
1507
+ },
1508
+ );
1509
+ }
1510
+
1511
+ @Post('/forgot-password', {
1512
+ validation: function (validationLanguage: TLanguage) {
1513
+ return [
1514
+ body('email')
1515
+ .isEmail()
1516
+ .withMessage(
1517
+ getSuiteCoreTranslation(
1518
+ SuiteCoreStringKey.Validation_InvalidEmail,
1519
+ undefined,
1520
+ validationLanguage,
1521
+ ),
1522
+ ),
1523
+ ];
1524
+ },
1525
+ })
1526
+ async forgotPassword(
1527
+ _req: Request,
1528
+ _res: Response,
1529
+ _next: NextFunction,
1530
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
1531
+ return await withTransaction(
1532
+ this.application.db.connection,
1533
+ this.application.environment.mongo.useTransactions,
1534
+ undefined,
1535
+ async (sess) => {
1536
+ const { email } = this.validatedBody as { email?: unknown };
1537
+
1538
+ const UserModel = this.application.getModel<IUserDocument<string, TID>>(
1539
+ BaseModelName.User,
1540
+ );
1541
+ if (!isString(email)) {
1542
+ throw new GenericValidationError(
1543
+ getSuiteCoreTranslation(
1544
+ SuiteCoreStringKey.Validation_MissingValidatedData,
1545
+ ),
1546
+ );
1547
+ }
1548
+
1549
+ const user = await UserModel.findOne({
1550
+ email: email.toLowerCase(),
1551
+ }).session(sess ?? null);
1552
+
1553
+ if (!user || !user.passwordWrappedPrivateKey) {
1554
+ return {
1555
+ statusCode: 200,
1556
+ response: {
1557
+ message: getSuiteCoreTranslation(
1558
+ SuiteCoreStringKey.PasswordReset_Success,
1559
+ ),
1560
+ },
1561
+ };
1562
+ }
1563
+
1564
+ // Mongoose document type doesn't exactly match IUserDocument generic signature
1565
+ // but the document has all required properties
1566
+ await this.userService.createAndSendEmailToken(
1567
+ user as unknown as IUserDocument<TLanguage, TID>,
1568
+ EmailTokenType.PasswordReset,
1569
+ sess,
1570
+ this.application.environment.debug,
1571
+ );
1572
+
1573
+ return {
1574
+ statusCode: 200,
1575
+ response: {
1576
+ message: getSuiteCoreTranslation(
1577
+ SuiteCoreStringKey.PasswordReset_Success,
1578
+ ),
1579
+ },
1580
+ };
1581
+ },
1582
+ );
1583
+ }
1584
+
1585
+ @Get('/verify-reset-token')
1586
+ async verifyResetToken(
1587
+ req: Request,
1588
+ _res: Response,
1589
+ _next: NextFunction,
1590
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
1591
+ const token = req.query['token'] as string;
1592
+ if (!token) {
1593
+ throw new GenericValidationError(
1594
+ getSuiteCoreTranslation(SuiteCoreStringKey.Validation_TokenMissing),
1595
+ );
1596
+ }
1597
+
1598
+ return await withTransaction(
1599
+ this.application.db.connection,
1600
+ this.application.environment.mongo.useTransactions,
1601
+ undefined,
1602
+ async (sess) => {
1603
+ await this.userService.verifyEmailToken(
1604
+ token,
1605
+ EmailTokenType.PasswordReset,
1606
+ sess,
1607
+ );
1608
+ return {
1609
+ statusCode: 200,
1610
+ response: {
1611
+ message: 'Token is valid',
1612
+ },
1613
+ };
1614
+ },
1615
+ );
1616
+ }
1617
+
1618
+ @Post('/reset-password', {
1619
+ validation: function (validationLanguage: TLanguage) {
1620
+ const constants = this.constants;
1621
+ return [
1622
+ body('token')
1623
+ .not()
1624
+ .isEmpty()
1625
+ .withMessage(
1626
+ getSuiteCoreTranslation(
1627
+ SuiteCoreStringKey.Validation_TokenRequired,
1628
+ undefined,
1629
+ validationLanguage,
1630
+ ),
1631
+ )
1632
+ .matches(new RegExp(`^[a-f0-9]{${constants.EmailTokenLength * 2}}$`))
1633
+ .withMessage(
1634
+ getSuiteCoreTranslation(
1635
+ SuiteCoreStringKey.Validation_InvalidToken,
1636
+ undefined,
1637
+ validationLanguage,
1638
+ ),
1639
+ ),
1640
+ body('newPassword')
1641
+ .optional()
1642
+ .isLength({ min: 8 })
1643
+ .withMessage(
1644
+ getSuiteCoreTranslation(
1645
+ SuiteCoreStringKey.Validation_PasswordMinLengthTemplate,
1646
+ undefined,
1647
+ validationLanguage,
1648
+ ),
1649
+ )
1650
+ .matches(constants.PasswordRegex)
1651
+ .withMessage(
1652
+ getSuiteCoreTranslation(
1653
+ SuiteCoreStringKey.Validation_PasswordRegexErrorTemplate,
1654
+ undefined,
1655
+ validationLanguage,
1656
+ ),
1657
+ ),
1658
+ body('password')
1659
+ .optional()
1660
+ .isLength({ min: 8 })
1661
+ .withMessage(
1662
+ getSuiteCoreTranslation(
1663
+ SuiteCoreStringKey.Validation_PasswordMinLengthTemplate,
1664
+ undefined,
1665
+ validationLanguage,
1666
+ ),
1667
+ )
1668
+ .matches(constants.PasswordRegex)
1669
+ .withMessage(
1670
+ getSuiteCoreTranslation(
1671
+ SuiteCoreStringKey.Validation_PasswordRegexErrorTemplate,
1672
+ undefined,
1673
+ validationLanguage,
1674
+ ),
1675
+ ),
1676
+ body('currentPassword').optional().isString(),
1677
+ body('mnemonic').optional().isString(),
1678
+ ];
1679
+ },
1680
+ })
1681
+ async resetPassword(
1682
+ _req: Request,
1683
+ _res: Response,
1684
+ _next: NextFunction,
1685
+ ): Promise<IStatusCodeResponse<IApiMessageResponse | ApiErrorResponse>> {
1686
+ return await withTransaction(
1687
+ this.application.db.connection,
1688
+ this.application.environment.mongo.useTransactions,
1689
+ undefined,
1690
+ async (sess) => {
1691
+ const { token, newPassword, password, currentPassword, mnemonic } =
1692
+ this.validatedBody;
1693
+ const selectedNewPassword = (newPassword ?? password) as
1694
+ | string
1695
+ | undefined;
1696
+
1697
+ if (!isString(token) || !isString(selectedNewPassword)) {
1698
+ throw new GenericValidationError(
1699
+ getSuiteCoreTranslation(
1700
+ SuiteCoreStringKey.Validation_MissingValidatedData,
1701
+ ),
1702
+ );
1703
+ }
1704
+
1705
+ const credential =
1706
+ (mnemonic as string | undefined) ??
1707
+ (currentPassword as string | undefined);
1708
+ if (!isString(credential)) {
1709
+ throw new GenericValidationError(
1710
+ getSuiteCoreTranslation(
1711
+ SuiteCoreStringKey.Validation_MissingValidatedData,
1712
+ ),
1713
+ );
1714
+ }
1715
+
1716
+ await this.userService.resetPasswordWithToken(
1717
+ token as string,
1718
+ selectedNewPassword,
1719
+ credential,
1720
+ sess,
1721
+ );
1722
+
1723
+ return {
1724
+ statusCode: 200,
1725
+ response: {
1726
+ message: getSuiteCoreTranslation(
1727
+ SuiteCoreStringKey.PasswordChange_Success,
1728
+ ),
1729
+ },
1730
+ };
1731
+ },
1732
+ );
1733
+ }
1734
+ }