@digitaldefiance/node-express-suite 3.6.20 → 3.6.21

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