@shipfox/api-auth 2.0.0

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 (319) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +116 -0
  5. package/LICENSE +21 -0
  6. package/README.md +336 -0
  7. package/dist/config.d.ts +22 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +95 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/core/auth.d.ts +108 -0
  12. package/dist/core/auth.d.ts.map +1 -0
  13. package/dist/core/auth.js +476 -0
  14. package/dist/core/auth.js.map +1 -0
  15. package/dist/core/entities/email-verification.d.ts +9 -0
  16. package/dist/core/entities/email-verification.d.ts.map +1 -0
  17. package/dist/core/entities/email-verification.js +3 -0
  18. package/dist/core/entities/email-verification.js.map +1 -0
  19. package/dist/core/entities/password-reset.d.ts +9 -0
  20. package/dist/core/entities/password-reset.d.ts.map +1 -0
  21. package/dist/core/entities/password-reset.js +3 -0
  22. package/dist/core/entities/password-reset.js.map +1 -0
  23. package/dist/core/entities/refresh-token.d.ts +12 -0
  24. package/dist/core/entities/refresh-token.d.ts.map +1 -0
  25. package/dist/core/entities/refresh-token.js +3 -0
  26. package/dist/core/entities/refresh-token.js.map +1 -0
  27. package/dist/core/entities/user.d.ts +12 -0
  28. package/dist/core/entities/user.d.ts.map +1 -0
  29. package/dist/core/entities/user.js +3 -0
  30. package/dist/core/entities/user.js.map +1 -0
  31. package/dist/core/errors.d.ts +54 -0
  32. package/dist/core/errors.d.ts.map +1 -0
  33. package/dist/core/errors.js +106 -0
  34. package/dist/core/errors.js.map +1 -0
  35. package/dist/core/job-lease-token.d.ts +12 -0
  36. package/dist/core/job-lease-token.d.ts.map +1 -0
  37. package/dist/core/job-lease-token.js +58 -0
  38. package/dist/core/job-lease-token.js.map +1 -0
  39. package/dist/core/jwt.d.ts +37 -0
  40. package/dist/core/jwt.d.ts.map +1 -0
  41. package/dist/core/jwt.js +46 -0
  42. package/dist/core/jwt.js.map +1 -0
  43. package/dist/core/password.d.ts +10 -0
  44. package/dist/core/password.d.ts.map +1 -0
  45. package/dist/core/password.js +13 -0
  46. package/dist/core/password.js.map +1 -0
  47. package/dist/core/rate-limit.d.ts +34 -0
  48. package/dist/core/rate-limit.d.ts.map +1 -0
  49. package/dist/core/rate-limit.js +76 -0
  50. package/dist/core/rate-limit.js.map +1 -0
  51. package/dist/core/runner-session-token.d.ts +6 -0
  52. package/dist/core/runner-session-token.d.ts.map +1 -0
  53. package/dist/core/runner-session-token.js +37 -0
  54. package/dist/core/runner-session-token.js.map +1 -0
  55. package/dist/db/db.d.ts +1723 -0
  56. package/dist/db/db.d.ts.map +1 -0
  57. package/dist/db/db.js +28 -0
  58. package/dist/db/db.js.map +1 -0
  59. package/dist/db/email-verifications.d.ts +39 -0
  60. package/dist/db/email-verifications.d.ts.map +1 -0
  61. package/dist/db/email-verifications.js +95 -0
  62. package/dist/db/email-verifications.js.map +1 -0
  63. package/dist/db/migrations.d.ts +2 -0
  64. package/dist/db/migrations.d.ts.map +1 -0
  65. package/dist/db/migrations.js +5 -0
  66. package/dist/db/migrations.js.map +1 -0
  67. package/dist/db/password-resets.d.ts +23 -0
  68. package/dist/db/password-resets.d.ts.map +1 -0
  69. package/dist/db/password-resets.js +37 -0
  70. package/dist/db/password-resets.js.map +1 -0
  71. package/dist/db/rate-limits.d.ts +18 -0
  72. package/dist/db/rate-limits.d.ts.map +1 -0
  73. package/dist/db/rate-limits.js +44 -0
  74. package/dist/db/rate-limits.js.map +1 -0
  75. package/dist/db/refresh-tokens.d.ts +44 -0
  76. package/dist/db/refresh-tokens.d.ts.map +1 -0
  77. package/dist/db/refresh-tokens.js +71 -0
  78. package/dist/db/refresh-tokens.js.map +1 -0
  79. package/dist/db/schema/common.d.ts +2 -0
  80. package/dist/db/schema/common.d.ts.map +1 -0
  81. package/dist/db/schema/common.js +4 -0
  82. package/dist/db/schema/common.js.map +1 -0
  83. package/dist/db/schema/email-verifications.d.ts +114 -0
  84. package/dist/db/schema/email-verifications.d.ts.map +1 -0
  85. package/dist/db/schema/email-verifications.js +35 -0
  86. package/dist/db/schema/email-verifications.js.map +1 -0
  87. package/dist/db/schema/outbox.d.ts +195 -0
  88. package/dist/db/schema/outbox.d.ts.map +1 -0
  89. package/dist/db/schema/outbox.js +5 -0
  90. package/dist/db/schema/outbox.js.map +1 -0
  91. package/dist/db/schema/password-resets.d.ts +114 -0
  92. package/dist/db/schema/password-resets.d.ts.map +1 -0
  93. package/dist/db/schema/password-resets.js +35 -0
  94. package/dist/db/schema/password-resets.js.map +1 -0
  95. package/dist/db/schema/rate-limits.d.ts +145 -0
  96. package/dist/db/schema/rate-limits.d.ts.map +1 -0
  97. package/dist/db/schema/rate-limits.js +25 -0
  98. package/dist/db/schema/rate-limits.js.map +1 -0
  99. package/dist/db/schema/refresh-tokens.d.ts +165 -0
  100. package/dist/db/schema/refresh-tokens.d.ts.map +1 -0
  101. package/dist/db/schema/refresh-tokens.js +47 -0
  102. package/dist/db/schema/refresh-tokens.js.map +1 -0
  103. package/dist/db/schema/users.d.ts +149 -0
  104. package/dist/db/schema/users.d.ts.map +1 -0
  105. package/dist/db/schema/users.js +40 -0
  106. package/dist/db/schema/users.js.map +1 -0
  107. package/dist/db/users.d.ts +28 -0
  108. package/dist/db/users.d.ts.map +1 -0
  109. package/dist/db/users.js +83 -0
  110. package/dist/db/users.js.map +1 -0
  111. package/dist/index.d.ts +14 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +52 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/metrics/index.d.ts +2 -0
  116. package/dist/metrics/index.d.ts.map +1 -0
  117. package/dist/metrics/index.js +3 -0
  118. package/dist/metrics/index.js.map +1 -0
  119. package/dist/metrics/instance.d.ts +16 -0
  120. package/dist/metrics/instance.d.ts.map +1 -0
  121. package/dist/metrics/instance.js +52 -0
  122. package/dist/metrics/instance.js.map +1 -0
  123. package/dist/presentation/auth/bearer-token-auth.d.ts +15 -0
  124. package/dist/presentation/auth/bearer-token-auth.d.ts.map +1 -0
  125. package/dist/presentation/auth/bearer-token-auth.js +31 -0
  126. package/dist/presentation/auth/bearer-token-auth.js.map +1 -0
  127. package/dist/presentation/auth/jwt-auth.d.ts +10 -0
  128. package/dist/presentation/auth/jwt-auth.d.ts.map +1 -0
  129. package/dist/presentation/auth/jwt-auth.js +31 -0
  130. package/dist/presentation/auth/jwt-auth.js.map +1 -0
  131. package/dist/presentation/auth/lease-token-auth.d.ts +15 -0
  132. package/dist/presentation/auth/lease-token-auth.d.ts.map +1 -0
  133. package/dist/presentation/auth/lease-token-auth.js +27 -0
  134. package/dist/presentation/auth/lease-token-auth.js.map +1 -0
  135. package/dist/presentation/auth/refresh-cookie.d.ts +7 -0
  136. package/dist/presentation/auth/refresh-cookie.d.ts.map +1 -0
  137. package/dist/presentation/auth/refresh-cookie.js +29 -0
  138. package/dist/presentation/auth/refresh-cookie.js.map +1 -0
  139. package/dist/presentation/auth/runner-session-auth.d.ts +3 -0
  140. package/dist/presentation/auth/runner-session-auth.d.ts.map +1 -0
  141. package/dist/presentation/auth/runner-session-auth.js +16 -0
  142. package/dist/presentation/auth/runner-session-auth.js.map +1 -0
  143. package/dist/presentation/dto/user.d.ts +8 -0
  144. package/dist/presentation/dto/user.d.ts.map +1 -0
  145. package/dist/presentation/dto/user.js +19 -0
  146. package/dist/presentation/dto/user.js.map +1 -0
  147. package/dist/presentation/e2eRoutes/create-session.d.ts +2 -0
  148. package/dist/presentation/e2eRoutes/create-session.d.ts.map +1 -0
  149. package/dist/presentation/e2eRoutes/create-session.js +49 -0
  150. package/dist/presentation/e2eRoutes/create-session.js.map +1 -0
  151. package/dist/presentation/e2eRoutes/create-user.d.ts +2 -0
  152. package/dist/presentation/e2eRoutes/create-user.d.ts.map +1 -0
  153. package/dist/presentation/e2eRoutes/create-user.js +42 -0
  154. package/dist/presentation/e2eRoutes/create-user.js.map +1 -0
  155. package/dist/presentation/e2eRoutes/index.d.ts +3 -0
  156. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
  157. package/dist/presentation/e2eRoutes/index.js +15 -0
  158. package/dist/presentation/e2eRoutes/index.js.map +1 -0
  159. package/dist/presentation/routes/email-verification/verify-email-confirm.d.ts +2 -0
  160. package/dist/presentation/routes/email-verification/verify-email-confirm.d.ts.map +1 -0
  161. package/dist/presentation/routes/email-verification/verify-email-confirm.js +35 -0
  162. package/dist/presentation/routes/email-verification/verify-email-confirm.js.map +1 -0
  163. package/dist/presentation/routes/email-verification/verify-email-resend.d.ts +2 -0
  164. package/dist/presentation/routes/email-verification/verify-email-resend.d.ts.map +1 -0
  165. package/dist/presentation/routes/email-verification/verify-email-resend.js +27 -0
  166. package/dist/presentation/routes/email-verification/verify-email-resend.js.map +1 -0
  167. package/dist/presentation/routes/index.d.ts +3 -0
  168. package/dist/presentation/routes/index.d.ts.map +1 -0
  169. package/dist/presentation/routes/index.js +31 -0
  170. package/dist/presentation/routes/index.js.map +1 -0
  171. package/dist/presentation/routes/password/change-password.d.ts +2 -0
  172. package/dist/presentation/routes/password/change-password.d.ts.map +1 -0
  173. package/dist/presentation/routes/password/change-password.js +50 -0
  174. package/dist/presentation/routes/password/change-password.js.map +1 -0
  175. package/dist/presentation/routes/password/password-reset-confirm.d.ts +2 -0
  176. package/dist/presentation/routes/password/password-reset-confirm.d.ts.map +1 -0
  177. package/dist/presentation/routes/password/password-reset-confirm.js +36 -0
  178. package/dist/presentation/routes/password/password-reset-confirm.js.map +1 -0
  179. package/dist/presentation/routes/password/password-reset-request.d.ts +2 -0
  180. package/dist/presentation/routes/password/password-reset-request.d.ts.map +1 -0
  181. package/dist/presentation/routes/password/password-reset-request.js +26 -0
  182. package/dist/presentation/routes/password/password-reset-request.js.map +1 -0
  183. package/dist/presentation/routes/rate-limit.d.ts +10 -0
  184. package/dist/presentation/routes/rate-limit.d.ts.map +1 -0
  185. package/dist/presentation/routes/rate-limit.js +101 -0
  186. package/dist/presentation/routes/rate-limit.js.map +1 -0
  187. package/dist/presentation/routes/registration/signup.d.ts +2 -0
  188. package/dist/presentation/routes/registration/signup.d.ts.map +1 -0
  189. package/dist/presentation/routes/registration/signup.js +82 -0
  190. package/dist/presentation/routes/registration/signup.js.map +1 -0
  191. package/dist/presentation/routes/session/login.d.ts +2 -0
  192. package/dist/presentation/routes/session/login.d.ts.map +1 -0
  193. package/dist/presentation/routes/session/login.js +48 -0
  194. package/dist/presentation/routes/session/login.js.map +1 -0
  195. package/dist/presentation/routes/session/logout.d.ts +2 -0
  196. package/dist/presentation/routes/session/logout.d.ts.map +1 -0
  197. package/dist/presentation/routes/session/logout.js +25 -0
  198. package/dist/presentation/routes/session/logout.js.map +1 -0
  199. package/dist/presentation/routes/session/me.d.ts +2 -0
  200. package/dist/presentation/routes/session/me.d.ts.map +1 -0
  201. package/dist/presentation/routes/session/me.js +42 -0
  202. package/dist/presentation/routes/session/me.js.map +1 -0
  203. package/dist/presentation/routes/session/refresh.d.ts +2 -0
  204. package/dist/presentation/routes/session/refresh.d.ts.map +1 -0
  205. package/dist/presentation/routes/session/refresh.js +49 -0
  206. package/dist/presentation/routes/session/refresh.js.map +1 -0
  207. package/dist/presentation/subscribers/index.d.ts +3 -0
  208. package/dist/presentation/subscribers/index.d.ts.map +1 -0
  209. package/dist/presentation/subscribers/index.js +4 -0
  210. package/dist/presentation/subscribers/index.js.map +1 -0
  211. package/dist/presentation/subscribers/on-email-verification-send-requested.d.ts +3 -0
  212. package/dist/presentation/subscribers/on-email-verification-send-requested.d.ts.map +1 -0
  213. package/dist/presentation/subscribers/on-email-verification-send-requested.js +13 -0
  214. package/dist/presentation/subscribers/on-email-verification-send-requested.js.map +1 -0
  215. package/dist/presentation/subscribers/on-password-reset-send-requested.d.ts +3 -0
  216. package/dist/presentation/subscribers/on-password-reset-send-requested.d.ts.map +1 -0
  217. package/dist/presentation/subscribers/on-password-reset-send-requested.js +14 -0
  218. package/dist/presentation/subscribers/on-password-reset-send-requested.js.map +1 -0
  219. package/dist/tsconfig.test.tsbuildinfo +1 -0
  220. package/drizzle/0000_initial.sql +81 -0
  221. package/drizzle/meta/0000_snapshot.json +643 -0
  222. package/drizzle/meta/_journal.json +13 -0
  223. package/drizzle.config.ts +7 -0
  224. package/package.json +88 -0
  225. package/src/config.ts +88 -0
  226. package/src/core/auth.test.ts +675 -0
  227. package/src/core/auth.ts +560 -0
  228. package/src/core/entities/email-verification.ts +8 -0
  229. package/src/core/entities/password-reset.ts +8 -0
  230. package/src/core/entities/refresh-token.ts +11 -0
  231. package/src/core/entities/user.ts +12 -0
  232. package/src/core/errors.ts +123 -0
  233. package/src/core/job-lease-token.test.ts +201 -0
  234. package/src/core/job-lease-token.ts +83 -0
  235. package/src/core/jwt.test.ts +180 -0
  236. package/src/core/jwt.ts +66 -0
  237. package/src/core/password.test.ts +28 -0
  238. package/src/core/password.ts +21 -0
  239. package/src/core/rate-limit.test.ts +462 -0
  240. package/src/core/rate-limit.ts +130 -0
  241. package/src/core/runner-session-token.test.ts +126 -0
  242. package/src/core/runner-session-token.ts +49 -0
  243. package/src/db/db.ts +28 -0
  244. package/src/db/email-verifications.test.ts +61 -0
  245. package/src/db/email-verifications.ts +160 -0
  246. package/src/db/migrations.ts +4 -0
  247. package/src/db/password-resets.test.ts +61 -0
  248. package/src/db/password-resets.ts +69 -0
  249. package/src/db/rate-limits.ts +69 -0
  250. package/src/db/refresh-tokens.test.ts +164 -0
  251. package/src/db/refresh-tokens.ts +149 -0
  252. package/src/db/schema/common.ts +3 -0
  253. package/src/db/schema/email-verifications.ts +37 -0
  254. package/src/db/schema/outbox.ts +4 -0
  255. package/src/db/schema/password-resets.ts +37 -0
  256. package/src/db/schema/rate-limits.ts +27 -0
  257. package/src/db/schema/refresh-tokens.ts +43 -0
  258. package/src/db/schema/users.ts +37 -0
  259. package/src/db/users.test.ts +75 -0
  260. package/src/db/users.ts +121 -0
  261. package/src/index.test.ts +39 -0
  262. package/src/index.ts +69 -0
  263. package/src/metrics/index.ts +13 -0
  264. package/src/metrics/instance.test.ts +69 -0
  265. package/src/metrics/instance.ts +77 -0
  266. package/src/presentation/auth/bearer-token-auth.test.ts +99 -0
  267. package/src/presentation/auth/bearer-token-auth.ts +51 -0
  268. package/src/presentation/auth/jwt-auth.test.ts +136 -0
  269. package/src/presentation/auth/jwt-auth.ts +39 -0
  270. package/src/presentation/auth/lease-token-auth.test.ts +56 -0
  271. package/src/presentation/auth/lease-token-auth.ts +25 -0
  272. package/src/presentation/auth/refresh-cookie.test.ts +39 -0
  273. package/src/presentation/auth/refresh-cookie.ts +34 -0
  274. package/src/presentation/auth/runner-session-auth.test.ts +54 -0
  275. package/src/presentation/auth/runner-session-auth.ts +13 -0
  276. package/src/presentation/dto/user.ts +21 -0
  277. package/src/presentation/e2eRoutes/create-session.ts +39 -0
  278. package/src/presentation/e2eRoutes/create-user.ts +38 -0
  279. package/src/presentation/e2eRoutes/index.test.ts +102 -0
  280. package/src/presentation/e2eRoutes/index.ts +10 -0
  281. package/src/presentation/routes/email-verification/verify-email-confirm.test.ts +66 -0
  282. package/src/presentation/routes/email-verification/verify-email-confirm.ts +37 -0
  283. package/src/presentation/routes/email-verification/verify-email-resend.test.ts +100 -0
  284. package/src/presentation/routes/email-verification/verify-email-resend.ts +26 -0
  285. package/src/presentation/routes/index.ts +29 -0
  286. package/src/presentation/routes/password/change-password.test.ts +106 -0
  287. package/src/presentation/routes/password/change-password.ts +45 -0
  288. package/src/presentation/routes/password/password-reset-confirm.test.ts +63 -0
  289. package/src/presentation/routes/password/password-reset-confirm.ts +35 -0
  290. package/src/presentation/routes/password/password-reset-request.test.ts +56 -0
  291. package/src/presentation/routes/password/password-reset-request.ts +25 -0
  292. package/src/presentation/routes/rate-limit.test.ts +341 -0
  293. package/src/presentation/routes/rate-limit.ts +119 -0
  294. package/src/presentation/routes/registration/signup.test.ts +284 -0
  295. package/src/presentation/routes/registration/signup.ts +81 -0
  296. package/src/presentation/routes/session/login.test.ts +77 -0
  297. package/src/presentation/routes/session/login.ts +50 -0
  298. package/src/presentation/routes/session/logout.test.ts +55 -0
  299. package/src/presentation/routes/session/logout.ts +23 -0
  300. package/src/presentation/routes/session/me.test.ts +56 -0
  301. package/src/presentation/routes/session/me.ts +35 -0
  302. package/src/presentation/routes/session/refresh.test.ts +89 -0
  303. package/src/presentation/routes/session/refresh.ts +54 -0
  304. package/src/presentation/subscribers/email-send-requested.test.ts +77 -0
  305. package/src/presentation/subscribers/index.ts +2 -0
  306. package/src/presentation/subscribers/on-email-verification-send-requested.ts +10 -0
  307. package/src/presentation/subscribers/on-password-reset-send-requested.ts +13 -0
  308. package/test/env.ts +10 -0
  309. package/test/factories/index.ts +1 -0
  310. package/test/factories/user.ts +36 -0
  311. package/test/globalSetup.ts +18 -0
  312. package/test/index.ts +1 -0
  313. package/test/routes.ts +275 -0
  314. package/test/setup.ts +17 -0
  315. package/tsconfig.build.json +9 -0
  316. package/tsconfig.build.tsbuildinfo +1 -0
  317. package/tsconfig.json +4 -0
  318. package/tsconfig.test.json +8 -0
  319. package/vitest.config.ts +11 -0
@@ -0,0 +1,15 @@
1
+ import cookie from '@fastify/cookie';
2
+ import { createE2eSessionRoute } from './create-session.js';
3
+ import { createE2eUserRoute } from './create-user.js';
4
+ export const authE2eRoutes = {
5
+ prefix: '/auth',
6
+ plugins: [
7
+ cookie
8
+ ],
9
+ routes: [
10
+ createE2eUserRoute,
11
+ createE2eSessionRoute
12
+ ]
13
+ };
14
+
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/e2eRoutes/index.ts"],"sourcesContent":["import cookie from '@fastify/cookie';\nimport type {RouteGroup} from '@shipfox/node-fastify';\nimport {createE2eSessionRoute} from './create-session.js';\nimport {createE2eUserRoute} from './create-user.js';\n\nexport const authE2eRoutes: RouteGroup = {\n prefix: '/auth',\n plugins: [cookie],\n routes: [createE2eUserRoute, createE2eSessionRoute],\n};\n"],"names":["cookie","createE2eSessionRoute","createE2eUserRoute","authE2eRoutes","prefix","plugins","routes"],"mappings":"AAAA,OAAOA,YAAY,kBAAkB;AAErC,SAAQC,qBAAqB,QAAO,sBAAsB;AAC1D,SAAQC,kBAAkB,QAAO,mBAAmB;AAEpD,OAAO,MAAMC,gBAA4B;IACvCC,QAAQ;IACRC,SAAS;QAACL;KAAO;IACjBM,QAAQ;QAACJ;QAAoBD;KAAsB;AACrD,EAAE"}
@@ -0,0 +1,2 @@
1
+ export declare const verifyEmailConfirmRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=verify-email-confirm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-email-confirm.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/email-verification/verify-email-confirm.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,uBAAuB,iDA0BlC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { verifyEmailConfirmBodySchema, verifyEmailConfirmResponseSchema } from '@shipfox/api-auth-dto';
2
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
3
+ import { confirmEmailVerification } from '#core/auth.js';
4
+ import { TokenInvalidError } from '#core/errors.js';
5
+ import { setRefreshTokenCookie } from '#presentation/auth/refresh-cookie.js';
6
+ import { toAuthSessionDto } from '#presentation/dto/user.js';
7
+ export const verifyEmailConfirmRoute = defineRoute({
8
+ method: 'POST',
9
+ path: '/verify-email/confirm',
10
+ description: 'Verify a user email address with the link sent by email.',
11
+ schema: {
12
+ body: verifyEmailConfirmBodySchema,
13
+ response: {
14
+ 200: verifyEmailConfirmResponseSchema
15
+ }
16
+ },
17
+ errorHandler: (error)=>{
18
+ if (error instanceof TokenInvalidError) {
19
+ throw new ClientError('Verification token is invalid or expired', 'token-invalid', {
20
+ status: 410
21
+ });
22
+ }
23
+ throw error;
24
+ },
25
+ handler: async (request, reply)=>{
26
+ const { token } = request.body;
27
+ const result = await confirmEmailVerification({
28
+ token
29
+ });
30
+ setRefreshTokenCookie(reply, result.refreshToken);
31
+ return toAuthSessionDto(result);
32
+ }
33
+ });
34
+
35
+ //# sourceMappingURL=verify-email-confirm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/email-verification/verify-email-confirm.ts"],"sourcesContent":["import {\n verifyEmailConfirmBodySchema,\n verifyEmailConfirmResponseSchema,\n} from '@shipfox/api-auth-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {confirmEmailVerification} from '#core/auth.js';\nimport {TokenInvalidError} from '#core/errors.js';\nimport {setRefreshTokenCookie} from '#presentation/auth/refresh-cookie.js';\nimport {toAuthSessionDto} from '#presentation/dto/user.js';\n\nexport const verifyEmailConfirmRoute = defineRoute({\n method: 'POST',\n path: '/verify-email/confirm',\n description: 'Verify a user email address with the link sent by email.',\n schema: {\n body: verifyEmailConfirmBodySchema,\n response: {\n 200: verifyEmailConfirmResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof TokenInvalidError) {\n throw new ClientError('Verification token is invalid or expired', 'token-invalid', {\n status: 410,\n });\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {token} = request.body;\n\n const result = await confirmEmailVerification({token});\n setRefreshTokenCookie(reply, result.refreshToken);\n\n return toAuthSessionDto(result);\n },\n});\n"],"names":["verifyEmailConfirmBodySchema","verifyEmailConfirmResponseSchema","ClientError","defineRoute","confirmEmailVerification","TokenInvalidError","setRefreshTokenCookie","toAuthSessionDto","verifyEmailConfirmRoute","method","path","description","schema","body","response","errorHandler","error","status","handler","request","reply","token","result","refreshToken"],"mappings":"AAAA,SACEA,4BAA4B,EAC5BC,gCAAgC,QAC3B,wBAAwB;AAC/B,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,wBAAwB,QAAO,gBAAgB;AACvD,SAAQC,iBAAiB,QAAO,kBAAkB;AAClD,SAAQC,qBAAqB,QAAO,uCAAuC;AAC3E,SAAQC,gBAAgB,QAAO,4BAA4B;AAE3D,OAAO,MAAMC,0BAA0BL,YAAY;IACjDM,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMb;QACNc,UAAU;YACR,KAAKb;QACP;IACF;IACAc,cAAc,CAACC;QACb,IAAIA,iBAAiBX,mBAAmB;YACtC,MAAM,IAAIH,YAAY,4CAA4C,iBAAiB;gBACjFe,QAAQ;YACV;QACF;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC,SAASC;QACvB,MAAM,EAACC,KAAK,EAAC,GAAGF,QAAQN,IAAI;QAE5B,MAAMS,SAAS,MAAMlB,yBAAyB;YAACiB;QAAK;QACpDf,sBAAsBc,OAAOE,OAAOC,YAAY;QAEhD,OAAOhB,iBAAiBe;IAC1B;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const verifyEmailResendRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=verify-email-resend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-email-resend.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/email-verification/verify-email-resend.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB,iDAoBjC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { verifyEmailResendBodySchema, verifyEmailResendResponseSchema } from '@shipfox/api-auth-dto';
2
+ import { defineRoute } from '@shipfox/node-fastify';
3
+ import { resendEmailVerification } from '#core/auth.js';
4
+ import { createAuthRateLimitPreHandler } from '#presentation/routes/rate-limit.js';
5
+ export const verifyEmailResendRoute = defineRoute({
6
+ method: 'POST',
7
+ path: '/verify-email/resend',
8
+ description: 'Send a new email verification link if the account can be verified.',
9
+ schema: {
10
+ body: verifyEmailResendBodySchema,
11
+ response: {
12
+ 200: verifyEmailResendResponseSchema
13
+ }
14
+ },
15
+ preHandler: createAuthRateLimitPreHandler('email-send'),
16
+ handler: async (request, reply)=>{
17
+ const { email } = request.body;
18
+ const result = await resendEmailVerification({
19
+ email
20
+ });
21
+ reply.code(200).send({
22
+ next_resend_available_at: result.nextResendAvailableAt.toISOString()
23
+ });
24
+ }
25
+ });
26
+
27
+ //# sourceMappingURL=verify-email-resend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/email-verification/verify-email-resend.ts"],"sourcesContent":["import {verifyEmailResendBodySchema, verifyEmailResendResponseSchema} from '@shipfox/api-auth-dto';\nimport {defineRoute} from '@shipfox/node-fastify';\nimport {resendEmailVerification} from '#core/auth.js';\nimport {createAuthRateLimitPreHandler} from '#presentation/routes/rate-limit.js';\n\nexport const verifyEmailResendRoute = defineRoute({\n method: 'POST',\n path: '/verify-email/resend',\n description: 'Send a new email verification link if the account can be verified.',\n schema: {\n body: verifyEmailResendBodySchema,\n response: {\n 200: verifyEmailResendResponseSchema,\n },\n },\n preHandler: createAuthRateLimitPreHandler('email-send'),\n handler: async (request, reply) => {\n const {email} = request.body;\n\n const result = await resendEmailVerification({email});\n\n reply.code(200).send({\n next_resend_available_at: result.nextResendAvailableAt.toISOString(),\n });\n },\n});\n"],"names":["verifyEmailResendBodySchema","verifyEmailResendResponseSchema","defineRoute","resendEmailVerification","createAuthRateLimitPreHandler","verifyEmailResendRoute","method","path","description","schema","body","response","preHandler","handler","request","reply","email","result","code","send","next_resend_available_at","nextResendAvailableAt","toISOString"],"mappings":"AAAA,SAAQA,2BAA2B,EAAEC,+BAA+B,QAAO,wBAAwB;AACnG,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SAAQC,uBAAuB,QAAO,gBAAgB;AACtD,SAAQC,6BAA6B,QAAO,qCAAqC;AAEjF,OAAO,MAAMC,yBAAyBH,YAAY;IAChDI,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMV;QACNW,UAAU;YACR,KAAKV;QACP;IACF;IACAW,YAAYR,8BAA8B;IAC1CS,SAAS,OAAOC,SAASC;QACvB,MAAM,EAACC,KAAK,EAAC,GAAGF,QAAQJ,IAAI;QAE5B,MAAMO,SAAS,MAAMd,wBAAwB;YAACa;QAAK;QAEnDD,MAAMG,IAAI,CAAC,KAAKC,IAAI,CAAC;YACnBC,0BAA0BH,OAAOI,qBAAqB,CAACC,WAAW;QACpE;IACF;AACF,GAAG"}
@@ -0,0 +1,3 @@
1
+ import type { RouteGroup } from '@shipfox/node-fastify';
2
+ export declare const authRoutes: RouteGroup;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAatD,eAAO,MAAM,UAAU,EAAE,UAexB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { authCookiePlugin } from '#presentation/auth/refresh-cookie.js';
2
+ import { verifyEmailConfirmRoute } from './email-verification/verify-email-confirm.js';
3
+ import { verifyEmailResendRoute } from './email-verification/verify-email-resend.js';
4
+ import { changePasswordRoute } from './password/change-password.js';
5
+ import { passwordResetConfirmRoute } from './password/password-reset-confirm.js';
6
+ import { passwordResetRequestRoute } from './password/password-reset-request.js';
7
+ import { signupRoute } from './registration/signup.js';
8
+ import { loginRoute } from './session/login.js';
9
+ import { logoutRoute } from './session/logout.js';
10
+ import { meRoute } from './session/me.js';
11
+ import { refreshRoute } from './session/refresh.js';
12
+ export const authRoutes = {
13
+ prefix: '/auth',
14
+ plugins: [
15
+ authCookiePlugin
16
+ ],
17
+ routes: [
18
+ signupRoute,
19
+ verifyEmailConfirmRoute,
20
+ verifyEmailResendRoute,
21
+ loginRoute,
22
+ refreshRoute,
23
+ logoutRoute,
24
+ meRoute,
25
+ changePasswordRoute,
26
+ passwordResetRequestRoute,
27
+ passwordResetConfirmRoute
28
+ ]
29
+ };
30
+
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/index.ts"],"sourcesContent":["import type {RouteGroup} from '@shipfox/node-fastify';\nimport {authCookiePlugin} from '#presentation/auth/refresh-cookie.js';\nimport {verifyEmailConfirmRoute} from './email-verification/verify-email-confirm.js';\nimport {verifyEmailResendRoute} from './email-verification/verify-email-resend.js';\nimport {changePasswordRoute} from './password/change-password.js';\nimport {passwordResetConfirmRoute} from './password/password-reset-confirm.js';\nimport {passwordResetRequestRoute} from './password/password-reset-request.js';\nimport {signupRoute} from './registration/signup.js';\nimport {loginRoute} from './session/login.js';\nimport {logoutRoute} from './session/logout.js';\nimport {meRoute} from './session/me.js';\nimport {refreshRoute} from './session/refresh.js';\n\nexport const authRoutes: RouteGroup = {\n prefix: '/auth',\n plugins: [authCookiePlugin],\n routes: [\n signupRoute,\n verifyEmailConfirmRoute,\n verifyEmailResendRoute,\n loginRoute,\n refreshRoute,\n logoutRoute,\n meRoute,\n changePasswordRoute,\n passwordResetRequestRoute,\n passwordResetConfirmRoute,\n ],\n};\n"],"names":["authCookiePlugin","verifyEmailConfirmRoute","verifyEmailResendRoute","changePasswordRoute","passwordResetConfirmRoute","passwordResetRequestRoute","signupRoute","loginRoute","logoutRoute","meRoute","refreshRoute","authRoutes","prefix","plugins","routes"],"mappings":"AACA,SAAQA,gBAAgB,QAAO,uCAAuC;AACtE,SAAQC,uBAAuB,QAAO,+CAA+C;AACrF,SAAQC,sBAAsB,QAAO,8CAA8C;AACnF,SAAQC,mBAAmB,QAAO,gCAAgC;AAClE,SAAQC,yBAAyB,QAAO,uCAAuC;AAC/E,SAAQC,yBAAyB,QAAO,uCAAuC;AAC/E,SAAQC,WAAW,QAAO,2BAA2B;AACrD,SAAQC,UAAU,QAAO,qBAAqB;AAC9C,SAAQC,WAAW,QAAO,sBAAsB;AAChD,SAAQC,OAAO,QAAO,kBAAkB;AACxC,SAAQC,YAAY,QAAO,uBAAuB;AAElD,OAAO,MAAMC,aAAyB;IACpCC,QAAQ;IACRC,SAAS;QAACb;KAAiB;IAC3Bc,QAAQ;QACNR;QACAL;QACAC;QACAK;QACAG;QACAF;QACAC;QACAN;QACAE;QACAD;KACD;AACH,EAAE"}
@@ -0,0 +1,2 @@
1
+ export declare const changePasswordRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=change-password.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-password.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/password/change-password.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,mBAAmB,iDAmC9B,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { AUTH_USER } from '@shipfox/api-auth-context';
2
+ import { changePasswordBodySchema } from '@shipfox/api-auth-dto';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { z } from 'zod';
5
+ import { changePassword } from '#core/auth.js';
6
+ import { InvalidCredentialsError, UserNotFoundError } from '#core/errors.js';
7
+ import { getClientContext } from '#presentation/auth/jwt-auth.js';
8
+ import { getRefreshTokenCookie } from '#presentation/auth/refresh-cookie.js';
9
+ export const changePasswordRoute = defineRoute({
10
+ method: 'POST',
11
+ path: '/change-password',
12
+ description: 'Change the signed-in user password.',
13
+ auth: AUTH_USER,
14
+ schema: {
15
+ body: changePasswordBodySchema,
16
+ response: {
17
+ 204: z.void()
18
+ }
19
+ },
20
+ errorHandler: (error)=>{
21
+ if (error instanceof UserNotFoundError) {
22
+ throw new ClientError('User not found', 'not-found', {
23
+ status: 404
24
+ });
25
+ }
26
+ if (error instanceof InvalidCredentialsError) {
27
+ throw new ClientError('Invalid credentials', 'invalid-credentials', {
28
+ status: 401
29
+ });
30
+ }
31
+ throw error;
32
+ },
33
+ handler: async (request, reply)=>{
34
+ const client = getClientContext(request);
35
+ if (!client) {
36
+ throw new ClientError('Authentication required', 'unauthorized', {
37
+ status: 401
38
+ });
39
+ }
40
+ await changePassword({
41
+ userId: client.userId,
42
+ currentPassword: request.body.current_password,
43
+ newPassword: request.body.new_password,
44
+ refreshToken: getRefreshTokenCookie(request)
45
+ });
46
+ reply.code(204);
47
+ }
48
+ });
49
+
50
+ //# sourceMappingURL=change-password.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/password/change-password.ts"],"sourcesContent":["import {AUTH_USER} from '@shipfox/api-auth-context';\nimport {changePasswordBodySchema} from '@shipfox/api-auth-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {changePassword} from '#core/auth.js';\nimport {InvalidCredentialsError, UserNotFoundError} from '#core/errors.js';\nimport {getClientContext} from '#presentation/auth/jwt-auth.js';\nimport {getRefreshTokenCookie} from '#presentation/auth/refresh-cookie.js';\n\nexport const changePasswordRoute = defineRoute({\n method: 'POST',\n path: '/change-password',\n description: 'Change the signed-in user password.',\n auth: AUTH_USER,\n schema: {\n body: changePasswordBodySchema,\n response: {\n 204: z.void(),\n },\n },\n errorHandler: (error) => {\n if (error instanceof UserNotFoundError) {\n throw new ClientError('User not found', 'not-found', {status: 404});\n }\n if (error instanceof InvalidCredentialsError) {\n throw new ClientError('Invalid credentials', 'invalid-credentials', {status: 401});\n }\n throw error;\n },\n handler: async (request, reply) => {\n const client = getClientContext(request);\n if (!client) {\n throw new ClientError('Authentication required', 'unauthorized', {status: 401});\n }\n\n await changePassword({\n userId: client.userId,\n currentPassword: request.body.current_password,\n newPassword: request.body.new_password,\n refreshToken: getRefreshTokenCookie(request),\n });\n\n reply.code(204);\n },\n});\n"],"names":["AUTH_USER","changePasswordBodySchema","ClientError","defineRoute","z","changePassword","InvalidCredentialsError","UserNotFoundError","getClientContext","getRefreshTokenCookie","changePasswordRoute","method","path","description","auth","schema","body","response","void","errorHandler","error","status","handler","request","reply","client","userId","currentPassword","current_password","newPassword","new_password","refreshToken","code"],"mappings":"AAAA,SAAQA,SAAS,QAAO,4BAA4B;AACpD,SAAQC,wBAAwB,QAAO,wBAAwB;AAC/D,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,cAAc,QAAO,gBAAgB;AAC7C,SAAQC,uBAAuB,EAAEC,iBAAiB,QAAO,kBAAkB;AAC3E,SAAQC,gBAAgB,QAAO,iCAAiC;AAChE,SAAQC,qBAAqB,QAAO,uCAAuC;AAE3E,OAAO,MAAMC,sBAAsBP,YAAY;IAC7CQ,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,MAAMd;IACNe,QAAQ;QACNC,MAAMf;QACNgB,UAAU;YACR,KAAKb,EAAEc,IAAI;QACb;IACF;IACAC,cAAc,CAACC;QACb,IAAIA,iBAAiBb,mBAAmB;YACtC,MAAM,IAAIL,YAAY,kBAAkB,aAAa;gBAACmB,QAAQ;YAAG;QACnE;QACA,IAAID,iBAAiBd,yBAAyB;YAC5C,MAAM,IAAIJ,YAAY,uBAAuB,uBAAuB;gBAACmB,QAAQ;YAAG;QAClF;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC,SAASC;QACvB,MAAMC,SAASjB,iBAAiBe;QAChC,IAAI,CAACE,QAAQ;YACX,MAAM,IAAIvB,YAAY,2BAA2B,gBAAgB;gBAACmB,QAAQ;YAAG;QAC/E;QAEA,MAAMhB,eAAe;YACnBqB,QAAQD,OAAOC,MAAM;YACrBC,iBAAiBJ,QAAQP,IAAI,CAACY,gBAAgB;YAC9CC,aAAaN,QAAQP,IAAI,CAACc,YAAY;YACtCC,cAActB,sBAAsBc;QACtC;QAEAC,MAAMQ,IAAI,CAAC;IACb;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const passwordResetConfirmRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=password-reset-confirm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-reset-confirm.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/password/password-reset-confirm.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,yBAAyB,iDAwBpC,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { passwordResetConfirmBodySchema, passwordResetConfirmResponseSchema } from '@shipfox/api-auth-dto';
2
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
3
+ import { confirmPasswordReset } from '#core/auth.js';
4
+ import { TokenInvalidError } from '#core/errors.js';
5
+ import { setRefreshTokenCookie } from '#presentation/auth/refresh-cookie.js';
6
+ import { toAuthSessionDto } from '#presentation/dto/user.js';
7
+ export const passwordResetConfirmRoute = defineRoute({
8
+ method: 'POST',
9
+ path: '/password-reset/confirm',
10
+ description: 'Set a new password using the link sent by email.',
11
+ schema: {
12
+ body: passwordResetConfirmBodySchema,
13
+ response: {
14
+ 200: passwordResetConfirmResponseSchema
15
+ }
16
+ },
17
+ errorHandler: (error)=>{
18
+ if (error instanceof TokenInvalidError) {
19
+ throw new ClientError('Reset token is invalid or expired', 'token-invalid', {
20
+ status: 410
21
+ });
22
+ }
23
+ throw error;
24
+ },
25
+ handler: async (request, reply)=>{
26
+ const { token, new_password } = request.body;
27
+ const result = await confirmPasswordReset({
28
+ token,
29
+ newPassword: new_password
30
+ });
31
+ setRefreshTokenCookie(reply, result.refreshToken);
32
+ return toAuthSessionDto(result);
33
+ }
34
+ });
35
+
36
+ //# sourceMappingURL=password-reset-confirm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/password/password-reset-confirm.ts"],"sourcesContent":["import {\n passwordResetConfirmBodySchema,\n passwordResetConfirmResponseSchema,\n} from '@shipfox/api-auth-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {confirmPasswordReset} from '#core/auth.js';\nimport {TokenInvalidError} from '#core/errors.js';\nimport {setRefreshTokenCookie} from '#presentation/auth/refresh-cookie.js';\nimport {toAuthSessionDto} from '#presentation/dto/user.js';\n\nexport const passwordResetConfirmRoute = defineRoute({\n method: 'POST',\n path: '/password-reset/confirm',\n description: 'Set a new password using the link sent by email.',\n schema: {\n body: passwordResetConfirmBodySchema,\n response: {\n 200: passwordResetConfirmResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof TokenInvalidError) {\n throw new ClientError('Reset token is invalid or expired', 'token-invalid', {status: 410});\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {token, new_password} = request.body;\n\n const result = await confirmPasswordReset({token, newPassword: new_password});\n setRefreshTokenCookie(reply, result.refreshToken);\n\n return toAuthSessionDto(result);\n },\n});\n"],"names":["passwordResetConfirmBodySchema","passwordResetConfirmResponseSchema","ClientError","defineRoute","confirmPasswordReset","TokenInvalidError","setRefreshTokenCookie","toAuthSessionDto","passwordResetConfirmRoute","method","path","description","schema","body","response","errorHandler","error","status","handler","request","reply","token","new_password","result","newPassword","refreshToken"],"mappings":"AAAA,SACEA,8BAA8B,EAC9BC,kCAAkC,QAC7B,wBAAwB;AAC/B,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,oBAAoB,QAAO,gBAAgB;AACnD,SAAQC,iBAAiB,QAAO,kBAAkB;AAClD,SAAQC,qBAAqB,QAAO,uCAAuC;AAC3E,SAAQC,gBAAgB,QAAO,4BAA4B;AAE3D,OAAO,MAAMC,4BAA4BL,YAAY;IACnDM,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMb;QACNc,UAAU;YACR,KAAKb;QACP;IACF;IACAc,cAAc,CAACC;QACb,IAAIA,iBAAiBX,mBAAmB;YACtC,MAAM,IAAIH,YAAY,qCAAqC,iBAAiB;gBAACe,QAAQ;YAAG;QAC1F;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC,SAASC;QACvB,MAAM,EAACC,KAAK,EAAEC,YAAY,EAAC,GAAGH,QAAQN,IAAI;QAE1C,MAAMU,SAAS,MAAMnB,qBAAqB;YAACiB;YAAOG,aAAaF;QAAY;QAC3EhB,sBAAsBc,OAAOG,OAAOE,YAAY;QAEhD,OAAOlB,iBAAiBgB;IAC1B;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const passwordResetRequestRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=password-reset-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-reset-request.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/password/password-reset-request.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,yBAAyB,iDAkBpC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { passwordResetRequestBodySchema } from '@shipfox/api-auth-dto';
2
+ import { defineRoute } from '@shipfox/node-fastify';
3
+ import { z } from 'zod';
4
+ import { requestPasswordReset } from '#core/auth.js';
5
+ import { createAuthRateLimitPreHandler } from '#presentation/routes/rate-limit.js';
6
+ export const passwordResetRequestRoute = defineRoute({
7
+ method: 'POST',
8
+ path: '/password-reset',
9
+ description: 'Send a password reset email when an account is eligible.',
10
+ schema: {
11
+ body: passwordResetRequestBodySchema,
12
+ response: {
13
+ 204: z.void()
14
+ }
15
+ },
16
+ preHandler: createAuthRateLimitPreHandler('email-send'),
17
+ handler: async (request, reply)=>{
18
+ const { email } = request.body;
19
+ await requestPasswordReset({
20
+ email
21
+ });
22
+ reply.code(204);
23
+ }
24
+ });
25
+
26
+ //# sourceMappingURL=password-reset-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/password/password-reset-request.ts"],"sourcesContent":["import {passwordResetRequestBodySchema} from '@shipfox/api-auth-dto';\nimport {defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {requestPasswordReset} from '#core/auth.js';\nimport {createAuthRateLimitPreHandler} from '#presentation/routes/rate-limit.js';\n\nexport const passwordResetRequestRoute = defineRoute({\n method: 'POST',\n path: '/password-reset',\n description: 'Send a password reset email when an account is eligible.',\n schema: {\n body: passwordResetRequestBodySchema,\n response: {\n 204: z.void(),\n },\n },\n preHandler: createAuthRateLimitPreHandler('email-send'),\n handler: async (request, reply) => {\n const {email} = request.body;\n\n await requestPasswordReset({email});\n\n reply.code(204);\n },\n});\n"],"names":["passwordResetRequestBodySchema","defineRoute","z","requestPasswordReset","createAuthRateLimitPreHandler","passwordResetRequestRoute","method","path","description","schema","body","response","void","preHandler","handler","request","reply","email","code"],"mappings":"AAAA,SAAQA,8BAA8B,QAAO,wBAAwB;AACrE,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,oBAAoB,QAAO,gBAAgB;AACnD,SAAQC,6BAA6B,QAAO,qCAAqC;AAEjF,OAAO,MAAMC,4BAA4BJ,YAAY;IACnDK,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMV;QACNW,UAAU;YACR,KAAKT,EAAEU,IAAI;QACb;IACF;IACAC,YAAYT,8BAA8B;IAC1CU,SAAS,OAAOC,SAASC;QACvB,MAAM,EAACC,KAAK,EAAC,GAAGF,QAAQL,IAAI;QAE5B,MAAMP,qBAAqB;YAACc;QAAK;QAEjCD,MAAME,IAAI,CAAC;IACb;AACF,GAAG"}
@@ -0,0 +1,10 @@
1
+ import { type FastifyReply, type FastifyRequest } from '@shipfox/node-fastify';
2
+ import { type AuthRateLimitAction } from '#core/rate-limit.js';
3
+ interface EmailBody {
4
+ email: string;
5
+ }
6
+ export declare function createAuthRateLimitPreHandler(action: AuthRateLimitAction): (request: FastifyRequest<{
7
+ Body: EmailBody;
8
+ }>, reply: FastifyReply) => Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,YAAY,EAAE,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,KAAK,mBAAmB,EAMzB,MAAM,qBAAqB,CAAC;AAa7B,UAAU,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AA6ED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,mBAAmB,IACzD,SAAS,cAAc,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAiB9F"}
@@ -0,0 +1,101 @@
1
+ import { ClientError } from '@shipfox/node-fastify';
2
+ import { AuthRateLimitExceededError, AuthRateLimitUnavailableError, checkAuthRateLimit } from '#core/rate-limit.js';
3
+ const policies = {
4
+ login: {
5
+ ip: {
6
+ limit: 60,
7
+ windowSeconds: 5 * 60
8
+ },
9
+ email: {
10
+ limit: 10,
11
+ windowSeconds: 15 * 60
12
+ }
13
+ },
14
+ 'email-send': {
15
+ ip: {
16
+ limit: 30,
17
+ windowSeconds: 60 * 60
18
+ },
19
+ email: {
20
+ limit: 3,
21
+ windowSeconds: 60 * 60
22
+ }
23
+ }
24
+ };
25
+ function routeName(request) {
26
+ return request.routeOptions.url ?? request.url.split('?')[0] ?? 'unknown';
27
+ }
28
+ async function enforceRateLimit(params) {
29
+ try {
30
+ await checkAuthRateLimit({
31
+ action: params.action,
32
+ scope: params.scope,
33
+ identifier: params.identifier,
34
+ ...policies[params.action][params.scope]
35
+ });
36
+ } catch (error) {
37
+ if (error instanceof AuthRateLimitExceededError) {
38
+ params.request.log.warn({
39
+ action: error.action,
40
+ scope: error.scope,
41
+ route: routeName(params.request),
42
+ retryAfterSeconds: error.retryAfterSeconds,
43
+ identifierHmacPrefix: error.identifierHmacPrefix
44
+ }, 'Auth rate limit blocked request');
45
+ params.reply.header('Retry-After', String(error.retryAfterSeconds));
46
+ throw new ClientError('Rate limit exceeded', 'rate-limited', {
47
+ status: 429,
48
+ details: {
49
+ retry_after_seconds: error.retryAfterSeconds
50
+ },
51
+ data: {
52
+ action: error.action,
53
+ scope: error.scope,
54
+ route: routeName(params.request),
55
+ identifierHmacPrefix: error.identifierHmacPrefix
56
+ },
57
+ cause: error
58
+ });
59
+ }
60
+ if (error instanceof AuthRateLimitUnavailableError) {
61
+ params.request.log.error({
62
+ action: error.action,
63
+ scope: error.scope,
64
+ route: routeName(params.request),
65
+ identifierHmacPrefix: error.identifierHmacPrefix,
66
+ err: error
67
+ }, 'Auth rate limiter unavailable');
68
+ throw new ClientError('Authentication rate limiter unavailable', 'auth-rate-limit-unavailable', {
69
+ status: 503,
70
+ data: {
71
+ action: error.action,
72
+ scope: error.scope,
73
+ route: routeName(params.request),
74
+ identifierHmacPrefix: error.identifierHmacPrefix
75
+ },
76
+ cause: error
77
+ });
78
+ }
79
+ throw error;
80
+ }
81
+ }
82
+ export function createAuthRateLimitPreHandler(action) {
83
+ return async (request, reply)=>{
84
+ await enforceRateLimit({
85
+ request,
86
+ reply,
87
+ action,
88
+ scope: 'ip',
89
+ identifier: request.ip
90
+ });
91
+ await enforceRateLimit({
92
+ request,
93
+ reply,
94
+ action,
95
+ scope: 'email',
96
+ identifier: request.body.email
97
+ });
98
+ };
99
+ }
100
+
101
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/presentation/routes/rate-limit.ts"],"sourcesContent":["import {ClientError, type FastifyReply, type FastifyRequest} from '@shipfox/node-fastify';\nimport {\n type AuthRateLimitAction,\n AuthRateLimitExceededError,\n type AuthRateLimitPolicy,\n type AuthRateLimitScope,\n AuthRateLimitUnavailableError,\n checkAuthRateLimit,\n} from '#core/rate-limit.js';\n\nconst policies: Record<AuthRateLimitAction, Record<AuthRateLimitScope, AuthRateLimitPolicy>> = {\n login: {\n ip: {limit: 60, windowSeconds: 5 * 60},\n email: {limit: 10, windowSeconds: 15 * 60},\n },\n 'email-send': {\n ip: {limit: 30, windowSeconds: 60 * 60},\n email: {limit: 3, windowSeconds: 60 * 60},\n },\n};\n\ninterface EmailBody {\n email: string;\n}\n\nfunction routeName(request: FastifyRequest): string {\n return request.routeOptions.url ?? request.url.split('?')[0] ?? 'unknown';\n}\n\nasync function enforceRateLimit(params: {\n request: FastifyRequest;\n reply: FastifyReply;\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifier: string;\n}): Promise<void> {\n try {\n await checkAuthRateLimit({\n action: params.action,\n scope: params.scope,\n identifier: params.identifier,\n ...policies[params.action][params.scope],\n });\n } catch (error) {\n if (error instanceof AuthRateLimitExceededError) {\n params.request.log.warn(\n {\n action: error.action,\n scope: error.scope,\n route: routeName(params.request),\n retryAfterSeconds: error.retryAfterSeconds,\n identifierHmacPrefix: error.identifierHmacPrefix,\n },\n 'Auth rate limit blocked request',\n );\n params.reply.header('Retry-After', String(error.retryAfterSeconds));\n throw new ClientError('Rate limit exceeded', 'rate-limited', {\n status: 429,\n details: {retry_after_seconds: error.retryAfterSeconds},\n data: {\n action: error.action,\n scope: error.scope,\n route: routeName(params.request),\n identifierHmacPrefix: error.identifierHmacPrefix,\n },\n cause: error,\n });\n }\n\n if (error instanceof AuthRateLimitUnavailableError) {\n params.request.log.error(\n {\n action: error.action,\n scope: error.scope,\n route: routeName(params.request),\n identifierHmacPrefix: error.identifierHmacPrefix,\n err: error,\n },\n 'Auth rate limiter unavailable',\n );\n throw new ClientError(\n 'Authentication rate limiter unavailable',\n 'auth-rate-limit-unavailable',\n {\n status: 503,\n data: {\n action: error.action,\n scope: error.scope,\n route: routeName(params.request),\n identifierHmacPrefix: error.identifierHmacPrefix,\n },\n cause: error,\n },\n );\n }\n\n throw error;\n }\n}\n\nexport function createAuthRateLimitPreHandler(action: AuthRateLimitAction) {\n return async (request: FastifyRequest<{Body: EmailBody}>, reply: FastifyReply): Promise<void> => {\n await enforceRateLimit({\n request,\n reply,\n action,\n scope: 'ip',\n identifier: request.ip,\n });\n\n await enforceRateLimit({\n request,\n reply,\n action,\n scope: 'email',\n identifier: request.body.email,\n });\n };\n}\n"],"names":["ClientError","AuthRateLimitExceededError","AuthRateLimitUnavailableError","checkAuthRateLimit","policies","login","ip","limit","windowSeconds","email","routeName","request","routeOptions","url","split","enforceRateLimit","params","action","scope","identifier","error","log","warn","route","retryAfterSeconds","identifierHmacPrefix","reply","header","String","status","details","retry_after_seconds","data","cause","err","createAuthRateLimitPreHandler","body"],"mappings":"AAAA,SAAQA,WAAW,QAA+C,wBAAwB;AAC1F,SAEEC,0BAA0B,EAG1BC,6BAA6B,EAC7BC,kBAAkB,QACb,sBAAsB;AAE7B,MAAMC,WAAyF;IAC7FC,OAAO;QACLC,IAAI;YAACC,OAAO;YAAIC,eAAe,IAAI;QAAE;QACrCC,OAAO;YAACF,OAAO;YAAIC,eAAe,KAAK;QAAE;IAC3C;IACA,cAAc;QACZF,IAAI;YAACC,OAAO;YAAIC,eAAe,KAAK;QAAE;QACtCC,OAAO;YAACF,OAAO;YAAGC,eAAe,KAAK;QAAE;IAC1C;AACF;AAMA,SAASE,UAAUC,OAAuB;IACxC,OAAOA,QAAQC,YAAY,CAACC,GAAG,IAAIF,QAAQE,GAAG,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI;AAClE;AAEA,eAAeC,iBAAiBC,MAM/B;IACC,IAAI;QACF,MAAMb,mBAAmB;YACvBc,QAAQD,OAAOC,MAAM;YACrBC,OAAOF,OAAOE,KAAK;YACnBC,YAAYH,OAAOG,UAAU;YAC7B,GAAGf,QAAQ,CAACY,OAAOC,MAAM,CAAC,CAACD,OAAOE,KAAK,CAAC;QAC1C;IACF,EAAE,OAAOE,OAAO;QACd,IAAIA,iBAAiBnB,4BAA4B;YAC/Ce,OAAOL,OAAO,CAACU,GAAG,CAACC,IAAI,CACrB;gBACEL,QAAQG,MAAMH,MAAM;gBACpBC,OAAOE,MAAMF,KAAK;gBAClBK,OAAOb,UAAUM,OAAOL,OAAO;gBAC/Ba,mBAAmBJ,MAAMI,iBAAiB;gBAC1CC,sBAAsBL,MAAMK,oBAAoB;YAClD,GACA;YAEFT,OAAOU,KAAK,CAACC,MAAM,CAAC,eAAeC,OAAOR,MAAMI,iBAAiB;YACjE,MAAM,IAAIxB,YAAY,uBAAuB,gBAAgB;gBAC3D6B,QAAQ;gBACRC,SAAS;oBAACC,qBAAqBX,MAAMI,iBAAiB;gBAAA;gBACtDQ,MAAM;oBACJf,QAAQG,MAAMH,MAAM;oBACpBC,OAAOE,MAAMF,KAAK;oBAClBK,OAAOb,UAAUM,OAAOL,OAAO;oBAC/Bc,sBAAsBL,MAAMK,oBAAoB;gBAClD;gBACAQ,OAAOb;YACT;QACF;QAEA,IAAIA,iBAAiBlB,+BAA+B;YAClDc,OAAOL,OAAO,CAACU,GAAG,CAACD,KAAK,CACtB;gBACEH,QAAQG,MAAMH,MAAM;gBACpBC,OAAOE,MAAMF,KAAK;gBAClBK,OAAOb,UAAUM,OAAOL,OAAO;gBAC/Bc,sBAAsBL,MAAMK,oBAAoB;gBAChDS,KAAKd;YACP,GACA;YAEF,MAAM,IAAIpB,YACR,2CACA,+BACA;gBACE6B,QAAQ;gBACRG,MAAM;oBACJf,QAAQG,MAAMH,MAAM;oBACpBC,OAAOE,MAAMF,KAAK;oBAClBK,OAAOb,UAAUM,OAAOL,OAAO;oBAC/Bc,sBAAsBL,MAAMK,oBAAoB;gBAClD;gBACAQ,OAAOb;YACT;QAEJ;QAEA,MAAMA;IACR;AACF;AAEA,OAAO,SAASe,8BAA8BlB,MAA2B;IACvE,OAAO,OAAON,SAA4Ce;QACxD,MAAMX,iBAAiB;YACrBJ;YACAe;YACAT;YACAC,OAAO;YACPC,YAAYR,QAAQL,EAAE;QACxB;QAEA,MAAMS,iBAAiB;YACrBJ;YACAe;YACAT;YACAC,OAAO;YACPC,YAAYR,QAAQyB,IAAI,CAAC3B,KAAK;QAChC;IACF;AACF"}
@@ -0,0 +1,2 @@
1
+ export declare const signupRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=signup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signup.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/registration/signup.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,WAAW,iDAmEtB,CAAC"}
@@ -0,0 +1,82 @@
1
+ import { signupBodySchema, signupResponseSchema } from '@shipfox/api-auth-dto';
2
+ import { InvitationEmailMismatchError, TokenAlreadyUsedError, TokenExpiredError, TokenInvalidError as WorkspacesTokenInvalidError } from '@shipfox/api-workspaces';
3
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
+ import { signup, signupWithInvitation } from '#core/auth.js';
5
+ import { EmailTakenError } from '#core/errors.js';
6
+ import { setRefreshTokenCookie } from '#presentation/auth/refresh-cookie.js';
7
+ import { toUserDto } from '#presentation/dto/user.js';
8
+ export const signupRoute = defineRoute({
9
+ method: 'POST',
10
+ path: '/signup',
11
+ description: 'Create a user account. Sends a verification email unless an invitation token is supplied.',
12
+ schema: {
13
+ body: signupBodySchema,
14
+ response: {
15
+ 201: signupResponseSchema
16
+ }
17
+ },
18
+ errorHandler: (error)=>{
19
+ if (error instanceof EmailTakenError) {
20
+ throw new ClientError('Email already registered', 'email-taken', {
21
+ status: 409
22
+ });
23
+ }
24
+ if (error instanceof WorkspacesTokenInvalidError) {
25
+ throw new ClientError('Invitation token is invalid', 'invitation-token-invalid', {
26
+ status: 410
27
+ });
28
+ }
29
+ if (error instanceof TokenAlreadyUsedError) {
30
+ throw new ClientError('Invitation has already been accepted', 'invitation-token-used', {
31
+ status: 410
32
+ });
33
+ }
34
+ if (error instanceof TokenExpiredError) {
35
+ throw new ClientError('Invitation has expired', 'invitation-token-expired', {
36
+ status: 410
37
+ });
38
+ }
39
+ if (error instanceof InvitationEmailMismatchError) {
40
+ throw new ClientError('Signup email does not match the invitation', 'invitation-email-mismatch', {
41
+ status: 403
42
+ });
43
+ }
44
+ throw error;
45
+ },
46
+ handler: async (request, reply)=>{
47
+ const { email, password, name, invitation_token } = request.body;
48
+ if (invitation_token === undefined) {
49
+ const user = await signup({
50
+ email,
51
+ password,
52
+ name
53
+ });
54
+ reply.code(201);
55
+ return {
56
+ user: toUserDto(user)
57
+ };
58
+ }
59
+ const result = await signupWithInvitation({
60
+ email,
61
+ password,
62
+ name,
63
+ invitationToken: invitation_token
64
+ });
65
+ setRefreshTokenCookie(reply, result.refreshToken);
66
+ reply.code(201);
67
+ return {
68
+ user: toUserDto(result.user),
69
+ token: result.token,
70
+ membership: result.membership ? {
71
+ id: result.membership.id,
72
+ user_id: result.membership.userId,
73
+ workspace_id: result.membership.workspaceId
74
+ } : null,
75
+ ...result.acceptError ? {
76
+ accept_error: result.acceptError
77
+ } : {}
78
+ };
79
+ }
80
+ });
81
+
82
+ //# sourceMappingURL=signup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/presentation/routes/registration/signup.ts"],"sourcesContent":["import {signupBodySchema, signupResponseSchema} from '@shipfox/api-auth-dto';\nimport {\n InvitationEmailMismatchError,\n TokenAlreadyUsedError,\n TokenExpiredError,\n TokenInvalidError as WorkspacesTokenInvalidError,\n} from '@shipfox/api-workspaces';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {signup, signupWithInvitation} from '#core/auth.js';\nimport {EmailTakenError} from '#core/errors.js';\nimport {setRefreshTokenCookie} from '#presentation/auth/refresh-cookie.js';\nimport {toUserDto} from '#presentation/dto/user.js';\n\nexport const signupRoute = defineRoute({\n method: 'POST',\n path: '/signup',\n description:\n 'Create a user account. Sends a verification email unless an invitation token is supplied.',\n schema: {\n body: signupBodySchema,\n response: {\n 201: signupResponseSchema,\n },\n },\n errorHandler: (error) => {\n if (error instanceof EmailTakenError) {\n throw new ClientError('Email already registered', 'email-taken', {status: 409});\n }\n if (error instanceof WorkspacesTokenInvalidError) {\n throw new ClientError('Invitation token is invalid', 'invitation-token-invalid', {\n status: 410,\n });\n }\n if (error instanceof TokenAlreadyUsedError) {\n throw new ClientError('Invitation has already been accepted', 'invitation-token-used', {\n status: 410,\n });\n }\n if (error instanceof TokenExpiredError) {\n throw new ClientError('Invitation has expired', 'invitation-token-expired', {status: 410});\n }\n if (error instanceof InvitationEmailMismatchError) {\n throw new ClientError(\n 'Signup email does not match the invitation',\n 'invitation-email-mismatch',\n {status: 403},\n );\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {email, password, name, invitation_token} = request.body;\n\n if (invitation_token === undefined) {\n const user = await signup({email, password, name});\n reply.code(201);\n return {user: toUserDto(user)};\n }\n\n const result = await signupWithInvitation({\n email,\n password,\n name,\n invitationToken: invitation_token,\n });\n setRefreshTokenCookie(reply, result.refreshToken);\n reply.code(201);\n return {\n user: toUserDto(result.user),\n token: result.token,\n membership: result.membership\n ? {\n id: result.membership.id,\n user_id: result.membership.userId,\n workspace_id: result.membership.workspaceId,\n }\n : null,\n ...(result.acceptError ? {accept_error: result.acceptError} : {}),\n };\n },\n});\n"],"names":["signupBodySchema","signupResponseSchema","InvitationEmailMismatchError","TokenAlreadyUsedError","TokenExpiredError","TokenInvalidError","WorkspacesTokenInvalidError","ClientError","defineRoute","signup","signupWithInvitation","EmailTakenError","setRefreshTokenCookie","toUserDto","signupRoute","method","path","description","schema","body","response","errorHandler","error","status","handler","request","reply","email","password","name","invitation_token","undefined","user","code","result","invitationToken","refreshToken","token","membership","id","user_id","userId","workspace_id","workspaceId","acceptError","accept_error"],"mappings":"AAAA,SAAQA,gBAAgB,EAAEC,oBAAoB,QAAO,wBAAwB;AAC7E,SACEC,4BAA4B,EAC5BC,qBAAqB,EACrBC,iBAAiB,EACjBC,qBAAqBC,2BAA2B,QAC3C,0BAA0B;AACjC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,MAAM,EAAEC,oBAAoB,QAAO,gBAAgB;AAC3D,SAAQC,eAAe,QAAO,kBAAkB;AAChD,SAAQC,qBAAqB,QAAO,uCAAuC;AAC3E,SAAQC,SAAS,QAAO,4BAA4B;AAEpD,OAAO,MAAMC,cAAcN,YAAY;IACrCO,QAAQ;IACRC,MAAM;IACNC,aACE;IACFC,QAAQ;QACNC,MAAMnB;QACNoB,UAAU;YACR,KAAKnB;QACP;IACF;IACAoB,cAAc,CAACC;QACb,IAAIA,iBAAiBX,iBAAiB;YACpC,MAAM,IAAIJ,YAAY,4BAA4B,eAAe;gBAACgB,QAAQ;YAAG;QAC/E;QACA,IAAID,iBAAiBhB,6BAA6B;YAChD,MAAM,IAAIC,YAAY,+BAA+B,4BAA4B;gBAC/EgB,QAAQ;YACV;QACF;QACA,IAAID,iBAAiBnB,uBAAuB;YAC1C,MAAM,IAAII,YAAY,wCAAwC,yBAAyB;gBACrFgB,QAAQ;YACV;QACF;QACA,IAAID,iBAAiBlB,mBAAmB;YACtC,MAAM,IAAIG,YAAY,0BAA0B,4BAA4B;gBAACgB,QAAQ;YAAG;QAC1F;QACA,IAAID,iBAAiBpB,8BAA8B;YACjD,MAAM,IAAIK,YACR,8CACA,6BACA;gBAACgB,QAAQ;YAAG;QAEhB;QACA,MAAMD;IACR;IACAE,SAAS,OAAOC,SAASC;QACvB,MAAM,EAACC,KAAK,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,gBAAgB,EAAC,GAAGL,QAAQN,IAAI;QAE9D,IAAIW,qBAAqBC,WAAW;YAClC,MAAMC,OAAO,MAAMvB,OAAO;gBAACkB;gBAAOC;gBAAUC;YAAI;YAChDH,MAAMO,IAAI,CAAC;YACX,OAAO;gBAACD,MAAMnB,UAAUmB;YAAK;QAC/B;QAEA,MAAME,SAAS,MAAMxB,qBAAqB;YACxCiB;YACAC;YACAC;YACAM,iBAAiBL;QACnB;QACAlB,sBAAsBc,OAAOQ,OAAOE,YAAY;QAChDV,MAAMO,IAAI,CAAC;QACX,OAAO;YACLD,MAAMnB,UAAUqB,OAAOF,IAAI;YAC3BK,OAAOH,OAAOG,KAAK;YACnBC,YAAYJ,OAAOI,UAAU,GACzB;gBACEC,IAAIL,OAAOI,UAAU,CAACC,EAAE;gBACxBC,SAASN,OAAOI,UAAU,CAACG,MAAM;gBACjCC,cAAcR,OAAOI,UAAU,CAACK,WAAW;YAC7C,IACA;YACJ,GAAIT,OAAOU,WAAW,GAAG;gBAACC,cAAcX,OAAOU,WAAW;YAAA,IAAI,CAAC,CAAC;QAClE;IACF;AACF,GAAG"}
@@ -0,0 +1,2 @@
1
+ export declare const loginRoute: import("@shipfox/node-fastify").RouteDefinition;
2
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/session/login.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,UAAU,iDAqCrB,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { loginBodySchema, loginResponseSchema } from '@shipfox/api-auth-dto';
2
+ import { ClientError, defineRoute } from '@shipfox/node-fastify';
3
+ import { login } from '#core/auth.js';
4
+ import { AuthDependencyUnavailableError, EmailNotVerifiedError, InvalidCredentialsError } from '#core/errors.js';
5
+ import { setRefreshTokenCookie } from '#presentation/auth/refresh-cookie.js';
6
+ import { toAuthSessionDto } from '#presentation/dto/user.js';
7
+ import { createAuthRateLimitPreHandler } from '#presentation/routes/rate-limit.js';
8
+ export const loginRoute = defineRoute({
9
+ method: 'POST',
10
+ path: '/login',
11
+ description: 'Sign in with an email address and password.',
12
+ schema: {
13
+ body: loginBodySchema,
14
+ response: {
15
+ 200: loginResponseSchema
16
+ }
17
+ },
18
+ preHandler: createAuthRateLimitPreHandler('login'),
19
+ errorHandler: (error)=>{
20
+ if (error instanceof InvalidCredentialsError) {
21
+ throw new ClientError('Invalid credentials', 'invalid-credentials', {
22
+ status: 401
23
+ });
24
+ }
25
+ if (error instanceof EmailNotVerifiedError) {
26
+ throw new ClientError('Email not verified', 'email-not-verified', {
27
+ status: 403
28
+ });
29
+ }
30
+ if (error instanceof AuthDependencyUnavailableError) {
31
+ throw new ClientError('Authentication dependency unavailable', 'auth-dependency-unavailable', {
32
+ status: 503
33
+ });
34
+ }
35
+ throw error;
36
+ },
37
+ handler: async (request, reply)=>{
38
+ const { email, password } = request.body;
39
+ const result = await login({
40
+ email,
41
+ password
42
+ });
43
+ setRefreshTokenCookie(reply, result.refreshToken);
44
+ return toAuthSessionDto(result);
45
+ }
46
+ });
47
+
48
+ //# sourceMappingURL=login.js.map