@jmlq/auth 0.0.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/README.md +306 -0
  2. package/dist/examples/bcrypt-password-hasher.example.d.ts +3 -0
  3. package/dist/examples/bcrypt-password-hasher.example.js +78 -0
  4. package/dist/examples/entity-object.example.d.ts +39 -0
  5. package/dist/examples/entity-object.example.js +411 -0
  6. package/dist/examples/factory-auth-service-example.d.ts +3 -0
  7. package/dist/examples/factory-auth-service-example.js +84 -0
  8. package/dist/examples/index.example.d.ts +12 -0
  9. package/dist/examples/index.example.js +171 -0
  10. package/dist/examples/jwt-algoritm.example.d.ts +47 -0
  11. package/dist/examples/jwt-algoritm.example.js +447 -0
  12. package/dist/examples/jwt-token-generator.example.d.ts +6 -0
  13. package/dist/examples/jwt-token-generator.example.js +49 -0
  14. package/dist/examples/jwt-verifier.example.d.ts +3 -0
  15. package/dist/examples/jwt-verifier.example.js +80 -0
  16. package/dist/examples/password-policy.example.d.ts +7 -0
  17. package/dist/examples/password-policy.example.js +57 -0
  18. package/dist/examples/service-jwt-token.example.d.ts +3 -0
  19. package/dist/examples/service-jwt-token.example.js +154 -0
  20. package/dist/examples/service-token-session.example.d.ts +3 -0
  21. package/dist/examples/service-token-session.example.js +139 -0
  22. package/dist/examples/use-case-login-with-password.example.d.ts +6 -0
  23. package/dist/examples/use-case-login-with-password.example.js +105 -0
  24. package/dist/examples/use-case-logout.example.d.ts +7 -0
  25. package/dist/examples/use-case-logout.example.js +134 -0
  26. package/dist/examples/use-case-refresh-token.example.d.ts +11 -0
  27. package/dist/examples/use-case-refresh-token.example.js +164 -0
  28. package/dist/examples/use-case-register-user.example.d.ts +9 -0
  29. package/dist/examples/use-case-register-user.example.js +110 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +17 -0
  32. package/dist/src/application/dtos/index.d.ts +4 -0
  33. package/dist/src/application/dtos/index.js +20 -0
  34. package/dist/src/application/dtos/login.dto.d.ts +9 -0
  35. package/dist/src/application/dtos/login.dto.js +2 -0
  36. package/dist/src/application/dtos/logout.dto.d.ts +7 -0
  37. package/dist/src/application/dtos/logout.dto.js +2 -0
  38. package/dist/src/application/dtos/refresh-token.dto.d.ts +7 -0
  39. package/dist/src/application/dtos/refresh-token.dto.js +2 -0
  40. package/dist/src/application/dtos/register-user.dto.d.ts +16 -0
  41. package/dist/src/application/dtos/register-user.dto.js +2 -0
  42. package/dist/src/application/factories/auth-service.factory.d.ts +5 -0
  43. package/dist/src/application/factories/auth-service.factory.js +51 -0
  44. package/dist/src/application/factories/index.d.ts +1 -0
  45. package/dist/src/application/factories/index.js +17 -0
  46. package/dist/src/application/index.d.ts +3 -0
  47. package/dist/src/application/index.js +19 -0
  48. package/dist/src/application/use-cases/index.d.ts +4 -0
  49. package/dist/src/application/use-cases/index.js +20 -0
  50. package/dist/src/application/use-cases/login-with-password.use-case.d.ts +9 -0
  51. package/dist/src/application/use-cases/login-with-password.use-case.js +36 -0
  52. package/dist/src/application/use-cases/logout.use-case.d.ts +7 -0
  53. package/dist/src/application/use-cases/logout.use-case.js +22 -0
  54. package/dist/src/application/use-cases/refresh-token.use-case.d.ts +7 -0
  55. package/dist/src/application/use-cases/refresh-token.use-case.js +23 -0
  56. package/dist/src/application/use-cases/register-user.use-case.d.ts +10 -0
  57. package/dist/src/application/use-cases/register-user.use-case.js +37 -0
  58. package/dist/src/domain/entities/credential.entity.d.ts +78 -0
  59. package/dist/src/domain/entities/credential.entity.js +92 -0
  60. package/dist/src/domain/entities/index.d.ts +2 -0
  61. package/dist/src/domain/entities/index.js +18 -0
  62. package/dist/src/domain/entities/user.entity.d.ts +97 -0
  63. package/dist/src/domain/entities/user.entity.js +116 -0
  64. package/dist/src/domain/errors/auth-domain-error.d.ts +82 -0
  65. package/dist/src/domain/errors/auth-domain-error.js +112 -0
  66. package/dist/src/domain/errors/auth.errors.d.ts +56 -0
  67. package/dist/src/domain/errors/auth.errors.js +76 -0
  68. package/dist/src/domain/errors/identity.errors.d.ts +34 -0
  69. package/dist/src/domain/errors/identity.errors.js +82 -0
  70. package/dist/src/domain/errors/index.d.ts +2 -0
  71. package/dist/src/domain/errors/index.js +18 -0
  72. package/dist/src/domain/index.d.ts +6 -0
  73. package/dist/src/domain/index.js +22 -0
  74. package/dist/src/domain/object-values/email.d.ts +37 -0
  75. package/dist/src/domain/object-values/email.js +56 -0
  76. package/dist/src/domain/object-values/hashed-password.d.ts +28 -0
  77. package/dist/src/domain/object-values/hashed-password.js +73 -0
  78. package/dist/src/domain/object-values/id.d.ts +8 -0
  79. package/dist/src/domain/object-values/id.js +28 -0
  80. package/dist/src/domain/object-values/index.d.ts +5 -0
  81. package/dist/src/domain/object-values/index.js +13 -0
  82. package/dist/src/domain/object-values/permission.d.ts +15 -0
  83. package/dist/src/domain/object-values/permission.js +57 -0
  84. package/dist/src/domain/object-values/role.d.ts +25 -0
  85. package/dist/src/domain/object-values/role.js +108 -0
  86. package/dist/src/domain/ports/auth/password-hasher.d.ts +7 -0
  87. package/dist/src/domain/ports/auth/password-hasher.js +2 -0
  88. package/dist/src/domain/ports/auth/password-policy-config.port.d.ts +0 -0
  89. package/dist/src/domain/ports/auth/password-policy-config.port.js +10 -0
  90. package/dist/src/domain/ports/auth/password-policy.port.d.ts +10 -0
  91. package/dist/src/domain/ports/auth/password-policy.port.js +2 -0
  92. package/dist/src/domain/ports/config/auth-config.port.d.ts +19 -0
  93. package/dist/src/domain/ports/config/auth-config.port.js +3 -0
  94. package/dist/src/domain/ports/index.d.ts +9 -0
  95. package/dist/src/domain/ports/index.js +25 -0
  96. package/dist/src/domain/ports/jwt/factory/signature-strategy-factory.port.d.ts +14 -0
  97. package/dist/src/domain/ports/jwt/factory/signature-strategy-factory.port.js +2 -0
  98. package/dist/src/domain/ports/jwt/payload/jwt-payload.port.d.ts +12 -0
  99. package/dist/src/domain/ports/jwt/payload/jwt-payload.port.js +2 -0
  100. package/dist/src/domain/ports/jwt/signature-strategy-factory.port.d.ts +14 -0
  101. package/dist/src/domain/ports/jwt/signature-strategy-factory.port.js +2 -0
  102. package/dist/src/domain/ports/jwt/signature-strategy.d.ts +30 -0
  103. package/dist/src/domain/ports/jwt/signature-strategy.js +4 -0
  104. package/dist/src/domain/ports/jwt/signature-strategy.port.d.ts +31 -0
  105. package/dist/src/domain/ports/jwt/signature-strategy.port.js +4 -0
  106. package/dist/src/domain/ports/jwt/strategy/signature-strategy.port.d.ts +31 -0
  107. package/dist/src/domain/ports/jwt/strategy/signature-strategy.port.js +4 -0
  108. package/dist/src/domain/ports/repository/credential.repository.d.ts +10 -0
  109. package/dist/src/domain/ports/repository/credential.repository.js +2 -0
  110. package/dist/src/domain/ports/repository/index.d.ts +2 -0
  111. package/dist/src/domain/ports/repository/index.js +18 -0
  112. package/dist/src/domain/ports/repository/user.repository.d.ts +13 -0
  113. package/dist/src/domain/ports/repository/user.repository.js +2 -0
  114. package/dist/src/domain/ports/token/token-session.port.d.ts +7 -0
  115. package/dist/src/domain/ports/token/token-session.port.js +2 -0
  116. package/dist/src/domain/ports/token/token.service.port.d.ts +9 -0
  117. package/dist/src/domain/ports/token/token.service.port.js +2 -0
  118. package/dist/src/domain/props/create-payload-props.port.d.ts +0 -0
  119. package/dist/src/domain/props/create-payload-props.port.js +8 -0
  120. package/dist/src/domain/props/entities/credential.props.d.ts +8 -0
  121. package/dist/src/domain/props/entities/credential.props.js +2 -0
  122. package/dist/src/domain/props/entities/index.d.ts +2 -0
  123. package/dist/src/domain/props/entities/index.js +18 -0
  124. package/dist/src/domain/props/entities/user.props.d.ts +10 -0
  125. package/dist/src/domain/props/entities/user.props.js +2 -0
  126. package/dist/src/domain/props/index.d.ts +2 -0
  127. package/dist/src/domain/props/index.js +18 -0
  128. package/dist/src/domain/props/jwt/create-payload.props.d.ts +9 -0
  129. package/dist/src/domain/props/jwt/create-payload.props.js +2 -0
  130. package/dist/src/domain/props/jwt/generate-access-token.props.d.ts +8 -0
  131. package/dist/src/domain/props/jwt/generate-access-token.props.js +2 -0
  132. package/dist/src/domain/props/jwt/generate-refresh-token.props.d.ts +8 -0
  133. package/dist/src/domain/props/jwt/generate-refresh-token.props.js +2 -0
  134. package/dist/src/domain/props/jwt/generate-token.props.d.ts +10 -0
  135. package/dist/src/domain/props/jwt/generate-token.props.js +2 -0
  136. package/dist/src/domain/props/jwt/index.d.ts +5 -0
  137. package/dist/src/domain/props/jwt/index.js +21 -0
  138. package/dist/src/domain/props/jwt/jwt-subject.d.ts +7 -0
  139. package/dist/src/domain/props/jwt/jwt-subject.js +2 -0
  140. package/dist/src/domain/props/jwt/jwt-user.d.ts +7 -0
  141. package/dist/src/domain/props/jwt/jwt-user.js +2 -0
  142. package/dist/src/domain/props/services/generate-access-token.props.d.ts +8 -0
  143. package/dist/src/domain/props/services/generate-access-token.props.js +2 -0
  144. package/dist/src/domain/props/services/generate-refresh-token.props.d.ts +8 -0
  145. package/dist/src/domain/props/services/generate-refresh-token.props.js +2 -0
  146. package/dist/src/domain/props/services/index.d.ts +2 -0
  147. package/dist/src/domain/props/services/index.js +18 -0
  148. package/dist/src/domain/services/index.d.ts +1 -0
  149. package/dist/src/domain/services/index.js +17 -0
  150. package/dist/src/domain/services/password-policy.service.d.ts +8 -0
  151. package/dist/src/domain/services/password-policy.service.js +29 -0
  152. package/dist/src/domain/services/token.service.port.d.ts +9 -0
  153. package/dist/src/domain/services/token.service.port.js +2 -0
  154. package/dist/src/index.d.ts +78 -0
  155. package/dist/src/index.js +94 -0
  156. package/dist/src/infrastructure/index.d.ts +5 -0
  157. package/dist/src/infrastructure/index.js +21 -0
  158. package/dist/src/infrastructure/jwt/factory/index.d.ts +1 -0
  159. package/dist/src/infrastructure/jwt/factory/index.js +17 -0
  160. package/dist/src/infrastructure/jwt/factory/signature-strategy.factory.d.ts +21 -0
  161. package/dist/src/infrastructure/jwt/factory/signature-strategy.factory.js +61 -0
  162. package/dist/src/infrastructure/jwt/index.d.ts +3 -0
  163. package/dist/src/infrastructure/jwt/index.js +19 -0
  164. package/dist/src/infrastructure/jwt/signature-strategy.factory.d.ts +21 -0
  165. package/dist/src/infrastructure/jwt/signature-strategy.factory.js +61 -0
  166. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature-strategy.d.ts +47 -0
  167. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature-strategy.js +124 -0
  168. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature.strategy.d.ts +47 -0
  169. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature.strategy.js +124 -0
  170. package/dist/src/infrastructure/jwt/strategies/hmac-signature-strategy.d.ts +54 -0
  171. package/dist/src/infrastructure/jwt/strategies/hmac-signature-strategy.js +129 -0
  172. package/dist/src/infrastructure/jwt/strategies/hmac-signature.strategy.d.ts +54 -0
  173. package/dist/src/infrastructure/jwt/strategies/hmac-signature.strategy.js +129 -0
  174. package/dist/src/infrastructure/jwt/strategies/index.d.ts +3 -0
  175. package/dist/src/infrastructure/jwt/strategies/index.js +19 -0
  176. package/dist/src/infrastructure/jwt/strategies/rsa-signature-strategy.d.ts +47 -0
  177. package/dist/src/infrastructure/jwt/strategies/rsa-signature-strategy.js +124 -0
  178. package/dist/src/infrastructure/jwt/strategies/rsa-signature.strategy.d.ts +47 -0
  179. package/dist/src/infrastructure/jwt/strategies/rsa-signature.strategy.js +124 -0
  180. package/dist/src/infrastructure/jwt/token/actions/jwt-token-generator.d.ts +57 -0
  181. package/dist/src/infrastructure/jwt/token/actions/jwt-token-generator.js +123 -0
  182. package/dist/src/infrastructure/jwt/token/actions/jwt-token-verifier.d.ts +59 -0
  183. package/dist/src/infrastructure/jwt/token/actions/jwt-token-verifier.js +100 -0
  184. package/dist/src/infrastructure/jwt/token/index.d.ts +5 -0
  185. package/dist/src/infrastructure/jwt/token/index.js +21 -0
  186. package/dist/src/infrastructure/jwt/token/jwt-signer.d.ts +33 -0
  187. package/dist/src/infrastructure/jwt/token/jwt-signer.js +46 -0
  188. package/dist/src/infrastructure/jwt/token/jwt-token-parser.d.ts +29 -0
  189. package/dist/src/infrastructure/jwt/token/jwt-token-parser.js +57 -0
  190. package/dist/src/infrastructure/jwt/token/jwt-token-validator.d.ts +32 -0
  191. package/dist/src/infrastructure/jwt/token/jwt-token-validator.js +77 -0
  192. package/dist/src/infrastructure/jwt/token/tools/jwt-signer.d.ts +33 -0
  193. package/dist/src/infrastructure/jwt/token/tools/jwt-signer.js +46 -0
  194. package/dist/src/infrastructure/jwt/token/tools/jwt-token-parser.d.ts +30 -0
  195. package/dist/src/infrastructure/jwt/token/tools/jwt-token-parser.js +57 -0
  196. package/dist/src/infrastructure/jwt/token/tools/jwt-token-validator.d.ts +32 -0
  197. package/dist/src/infrastructure/jwt/token/tools/jwt-token-validator.js +77 -0
  198. package/dist/src/infrastructure/repositories/index.d.ts +1 -0
  199. package/dist/src/infrastructure/repositories/index.js +17 -0
  200. package/dist/src/infrastructure/repositories/test/in-memory-credential.repository.d.ts +12 -0
  201. package/dist/src/infrastructure/repositories/test/in-memory-credential.repository.js +68 -0
  202. package/dist/src/infrastructure/repositories/test/in-memory-token-session.repository.d.ts +67 -0
  203. package/dist/src/infrastructure/repositories/test/in-memory-token-session.repository.js +128 -0
  204. package/dist/src/infrastructure/repositories/test/in-memory-user.repository.d.ts +11 -0
  205. package/dist/src/infrastructure/repositories/test/in-memory-user.repository.js +49 -0
  206. package/dist/src/infrastructure/repositories/test/index.d.ts +2 -0
  207. package/dist/src/infrastructure/repositories/test/index.js +18 -0
  208. package/dist/src/infrastructure/security/bcrypt-password-hasher.d.ts +6 -0
  209. package/dist/src/infrastructure/security/bcrypt-password-hasher.js +19 -0
  210. package/dist/src/infrastructure/security/index.d.ts +1 -0
  211. package/dist/src/infrastructure/security/index.js +17 -0
  212. package/dist/src/infrastructure/services/default-token-session.service.d.ts +18 -0
  213. package/dist/src/infrastructure/services/default-token-session.service.js +88 -0
  214. package/dist/src/infrastructure/services/index.d.ts +2 -0
  215. package/dist/src/infrastructure/services/index.js +18 -0
  216. package/dist/src/infrastructure/services/jwt-token.service.d.ts +15 -0
  217. package/dist/src/infrastructure/services/jwt-token.service.js +44 -0
  218. package/dist/src/infrastructure/services/simple-jwt-token.service.d.ts +15 -0
  219. package/dist/src/infrastructure/services/simple-jwt-token.service.js +46 -0
  220. package/dist/src/infrastructure/services/token-session.service.d.ts +24 -0
  221. package/dist/src/infrastructure/services/token-session.service.js +131 -0
  222. package/dist/src/infrastructure/types/auth-service-container.d.ts +14 -0
  223. package/dist/src/infrastructure/types/auth-service-container.js +2 -0
  224. package/dist/src/infrastructure/types/index.d.ts +1 -0
  225. package/dist/src/infrastructure/types/index.js +17 -0
  226. package/dist/src/shared/constants/index.d.ts +1 -0
  227. package/dist/src/shared/constants/index.js +17 -0
  228. package/dist/src/shared/constants/jwt-algorithms.d.ts +17 -0
  229. package/dist/src/shared/constants/jwt-algorithms.js +23 -0
  230. package/dist/src/shared/encoders/base64-url-encoder.d.ts +29 -0
  231. package/dist/src/shared/encoders/base64-url-encoder.js +45 -0
  232. package/dist/src/shared/encoders/index.d.ts +1 -0
  233. package/dist/src/shared/encoders/index.js +17 -0
  234. package/dist/src/shared/index.d.ts +4 -0
  235. package/dist/src/shared/index.js +20 -0
  236. package/dist/src/shared/types/index.d.ts +1 -0
  237. package/dist/src/shared/types/index.js +17 -0
  238. package/dist/src/shared/types/jwt.d.ts +25 -0
  239. package/dist/src/shared/types/jwt.js +2 -0
  240. package/dist/src/shared/types/jwt.types.d.ts +39 -0
  241. package/dist/src/shared/types/jwt.types.js +2 -0
  242. package/dist/src/shared/utils/index.d.ts +1 -0
  243. package/dist/src/shared/utils/index.js +17 -0
  244. package/dist/src/shared/utils/time-parser.d.ts +28 -0
  245. package/dist/src/shared/utils/time-parser.js +76 -0
  246. package/dist/tests/application/factory/auth-service-factory.spec.d.ts +1 -0
  247. package/dist/tests/application/factory/auth-service-factory.spec.js +97 -0
  248. package/dist/tests/application/use-cases/login-with-password.integration.spec.d.ts +1 -0
  249. package/dist/tests/application/use-cases/login-with-password.integration.spec.js +140 -0
  250. package/dist/tests/application/use-cases/logout-use-case.spec.d.ts +1 -0
  251. package/dist/tests/application/use-cases/logout-use-case.spec.js +40 -0
  252. package/dist/tests/application/use-cases/refresh-token-use-case.spec.d.ts +1 -0
  253. package/dist/tests/application/use-cases/refresh-token-use-case.spec.js +116 -0
  254. package/dist/tests/application/use-cases/register-user.usecase.spec.d.ts +1 -0
  255. package/dist/tests/application/use-cases/register-user.usecase.spec.js +151 -0
  256. package/dist/tests/domain/entities/credential.spec.d.ts +1 -0
  257. package/dist/tests/domain/entities/credential.spec.js +93 -0
  258. package/dist/tests/domain/entities/user.spec.d.ts +1 -0
  259. package/dist/tests/domain/entities/user.spec.js +93 -0
  260. package/dist/tests/domain/object-values/email.spec.d.ts +1 -0
  261. package/dist/tests/domain/object-values/email.spec.js +77 -0
  262. package/dist/tests/domain/object-values/hashed-password.spec.d.ts +1 -0
  263. package/dist/tests/domain/object-values/hashed-password.spec.js +54 -0
  264. package/dist/tests/domain/object-values/id.spec.d.ts +1 -0
  265. package/dist/tests/domain/object-values/id.spec.js +48 -0
  266. package/dist/tests/domain/object-values/permission.spec.d.ts +1 -0
  267. package/dist/tests/domain/object-values/permission.spec.js +75 -0
  268. package/dist/tests/domain/object-values/role.spec.d.ts +1 -0
  269. package/dist/tests/domain/object-values/role.spec.js +139 -0
  270. package/dist/tests/domain/services/default-password-policy.spec.d.ts +1 -0
  271. package/dist/tests/domain/services/default-password-policy.spec.js +69 -0
  272. package/dist/tests/doman/entities/credential.spec.d.ts +1 -0
  273. package/dist/tests/doman/entities/credential.spec.js +93 -0
  274. package/dist/tests/doman/entities/user.spec.d.ts +1 -0
  275. package/dist/tests/doman/entities/user.spec.js +93 -0
  276. package/dist/tests/doman/object-values/email.spec.d.ts +1 -0
  277. package/dist/tests/doman/object-values/email.spec.js +77 -0
  278. package/dist/tests/doman/object-values/hashed-password.spec.d.ts +1 -0
  279. package/dist/tests/doman/object-values/hashed-password.spec.js +54 -0
  280. package/dist/tests/doman/object-values/id.spec.d.ts +1 -0
  281. package/dist/tests/doman/object-values/id.spec.js +48 -0
  282. package/dist/tests/doman/object-values/permission.spec.d.ts +1 -0
  283. package/dist/tests/doman/object-values/permission.spec.js +75 -0
  284. package/dist/tests/doman/object-values/role.spec.d.ts +1 -0
  285. package/dist/tests/doman/object-values/role.spec.js +139 -0
  286. package/dist/tests/helpers/make-jwt-subject.d.ts +7 -0
  287. package/dist/tests/helpers/make-jwt-subject.js +16 -0
  288. package/dist/tests/helpers/make-jwt-user.d.ts +7 -0
  289. package/dist/tests/helpers/make-jwt-user.js +16 -0
  290. package/dist/tests/helpers/make-user.d.ts +2 -0
  291. package/dist/tests/helpers/make-user.js +15 -0
  292. package/dist/tests/infrastructure/jwt/signature-strategy-factory.spec.d.ts +1 -0
  293. package/dist/tests/infrastructure/jwt/signature-strategy-factory.spec.js +127 -0
  294. package/dist/tests/infrastructure/jwt/strategies/ecdsa-signature-strategy.spec.d.ts +1 -0
  295. package/dist/tests/infrastructure/jwt/strategies/ecdsa-signature-strategy.spec.js +157 -0
  296. package/dist/tests/infrastructure/jwt/strategies/hmac-signature-strategy.spec.d.ts +1 -0
  297. package/dist/tests/infrastructure/jwt/strategies/hmac-signature-strategy.spec.js +150 -0
  298. package/dist/tests/infrastructure/jwt/strategies/rsa-signature-strategy..spec.d.ts +1 -0
  299. package/dist/tests/infrastructure/jwt/strategies/rsa-signature-strategy..spec.js +156 -0
  300. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-generator.spec.d.ts +1 -0
  301. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-generator.spec.js +179 -0
  302. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-verifier.spec.d.ts +1 -0
  303. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-verifier.spec.js +142 -0
  304. package/dist/tests/infrastructure/jwt/token/jwt-signer.spec.d.ts +1 -0
  305. package/dist/tests/infrastructure/jwt/token/jwt-signer.spec.js +125 -0
  306. package/dist/tests/infrastructure/jwt/token/jwt-token-parser.spec.d.ts +1 -0
  307. package/dist/tests/infrastructure/jwt/token/jwt-token-parser.spec.js +116 -0
  308. package/dist/tests/infrastructure/jwt/token/jwt-token-validator.spec.d.ts +1 -0
  309. package/dist/tests/infrastructure/jwt/token/jwt-token-validator.spec.js +88 -0
  310. package/dist/tests/infrastructure/jwt/token/tools/jwt-signer.spec.d.ts +1 -0
  311. package/dist/tests/infrastructure/jwt/token/tools/jwt-signer.spec.js +126 -0
  312. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-parser.spec.d.ts +1 -0
  313. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-parser.spec.js +116 -0
  314. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-validator.spec.d.ts +1 -0
  315. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-validator.spec.js +88 -0
  316. package/dist/tests/infrastructure/security/security/bcrypt-password-hasher.spec.d.ts +1 -0
  317. package/dist/tests/infrastructure/security/security/bcrypt-password-hasher.spec.js +37 -0
  318. package/dist/tests/infrastructure/services/jwt-token-service.spec.d.ts +1 -0
  319. package/dist/tests/infrastructure/services/jwt-token-service.spec.js +145 -0
  320. package/dist/tests/infrastructure/services/token-session.service.spec.d.ts +1 -0
  321. package/dist/tests/infrastructure/services/token-session.service.spec.js +269 -0
  322. package/dist/tests/shared/constants/jwt-algorithms.spec.d.ts +1 -0
  323. package/dist/tests/shared/constants/jwt-algorithms.spec.js +27 -0
  324. package/dist/tests/shared/encoders/base64-url-encoder.spec.d.ts +1 -0
  325. package/dist/tests/shared/encoders/base64-url-encoder.spec.js +70 -0
  326. package/dist/tests/shared/utils/time-parser.spec.d.ts +1 -0
  327. package/dist/tests/shared/utils/time-parser.spec.js +80 -0
  328. package/dist/utils/index.d.ts +1 -0
  329. package/dist/utils/index.js +17 -0
  330. package/dist/utils/time-parser.d.ts +28 -0
  331. package/dist/utils/time-parser.js +76 -0
  332. package/package.json +48 -0
@@ -0,0 +1,28 @@
1
+ export declare class TimeParser {
2
+ private static readonly TIME_UNITS;
3
+ private static readonly TIME_PATTERN;
4
+ /**
5
+ * Convierte una cadena de tiempo (ej: "15m", "1h", "7d") a milisegundos
6
+ * @param timeString - Cadena de tiempo en formato número + unidad
7
+ * @returns Tiempo en milisegundos
8
+ * @throws Error si el formato es inválido
9
+ */
10
+ static parseToMilliseconds(timeString: string): number;
11
+ /**
12
+ * Valida si una cadena de tiempo tiene el formato correcto
13
+ * @param timeString - Cadena de tiempo a validar
14
+ * @returns true si es válida, false en caso contrario
15
+ */
16
+ static isValidTimeString(timeString: string): boolean;
17
+ /**
18
+ * Obtiene las unidades de tiempo soportadas
19
+ * @returns Array con las unidades soportadas
20
+ */
21
+ static getSupportedUnits(): string[];
22
+ /**
23
+ * Convierte milisegundos a formato legible
24
+ * @param milliseconds - Tiempo en milisegundos
25
+ * @returns Cadena de tiempo legible
26
+ */
27
+ static formatMilliseconds(milliseconds: number): string;
28
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimeParser = void 0;
4
+ class TimeParser {
5
+ /**
6
+ * Convierte una cadena de tiempo (ej: "15m", "1h", "7d") a milisegundos
7
+ * @param timeString - Cadena de tiempo en formato número + unidad
8
+ * @returns Tiempo en milisegundos
9
+ * @throws Error si el formato es inválido
10
+ */
11
+ static parseToMilliseconds(timeString) {
12
+ if (!timeString || typeof timeString !== "string") {
13
+ throw new Error("Time string is required and must be a string");
14
+ }
15
+ const trimmed = timeString.trim().toLowerCase();
16
+ const match = trimmed.match(this.TIME_PATTERN);
17
+ if (!match) {
18
+ throw new Error(`Invalid time format: "${timeString}". Expected format: number + unit (s, m, h, d). Examples: "15m", "1h", "7d"`);
19
+ }
20
+ const [, valueStr, unit] = match;
21
+ const value = parseInt(valueStr, 10);
22
+ if (isNaN(value) || value <= 0) {
23
+ throw new Error(`Invalid time value: "${valueStr}". Must be a positive number`);
24
+ }
25
+ const multiplier = this.TIME_UNITS[unit];
26
+ return value * multiplier;
27
+ }
28
+ /**
29
+ * Valida si una cadena de tiempo tiene el formato correcto
30
+ * @param timeString - Cadena de tiempo a validar
31
+ * @returns true si es válida, false en caso contrario
32
+ */
33
+ static isValidTimeString(timeString) {
34
+ try {
35
+ this.parseToMilliseconds(timeString);
36
+ return true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * Obtiene las unidades de tiempo soportadas
44
+ * @returns Array con las unidades soportadas
45
+ */
46
+ static getSupportedUnits() {
47
+ return Object.keys(this.TIME_UNITS);
48
+ }
49
+ /**
50
+ * Convierte milisegundos a formato legible
51
+ * @param milliseconds - Tiempo en milisegundos
52
+ * @returns Cadena de tiempo legible
53
+ */
54
+ static formatMilliseconds(milliseconds) {
55
+ const units = [
56
+ { unit: "d", value: 24 * 60 * 60 * 1000 },
57
+ { unit: "h", value: 60 * 60 * 1000 },
58
+ { unit: "m", value: 60 * 1000 },
59
+ { unit: "s", value: 1000 },
60
+ ];
61
+ for (const { unit, value } of units) {
62
+ if (milliseconds >= value && milliseconds % value === 0) {
63
+ return `${milliseconds / value}${unit}`;
64
+ }
65
+ }
66
+ return `${milliseconds}ms`;
67
+ }
68
+ }
69
+ exports.TimeParser = TimeParser;
70
+ TimeParser.TIME_UNITS = {
71
+ s: 1000, // segundos
72
+ m: 60 * 1000, // minutos
73
+ h: 60 * 60 * 1000, // horas
74
+ d: 24 * 60 * 60 * 1000, // días
75
+ };
76
+ TimeParser.TIME_PATTERN = /^(\d+)([smhd])$/;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ // tests/application/factory/auth-service-factory.spec.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const domain_1 = require("../../../src/domain");
5
+ const infrastructure_1 = require("../../../src/infrastructure");
6
+ const use_cases_1 = require("../../../src/application/use-cases");
7
+ const application_1 = require("src/application");
8
+ describe("AuthServiceFactory", () => {
9
+ let config;
10
+ let userRepository;
11
+ let credentialRepository;
12
+ // const algorithm: AnyAlgorithm = "HS256";
13
+ beforeEach(() => {
14
+ config = {
15
+ jwt: {
16
+ accessTokenSecret: "access-secret",
17
+ refreshTokenSecret: "refresh-secret",
18
+ accessTokenExpirationMs: 15 * 60 * 1000,
19
+ refreshTokenExpirationMs: 7 * 24 * 60 * 60 * 1000,
20
+ accessTokenExpiration: "15m",
21
+ refreshTokenExpiration: "7d",
22
+ },
23
+ info: {
24
+ issuer: "test-issuer",
25
+ audience: "test-audience",
26
+ },
27
+ bcrypt: {
28
+ saltRounds: 10,
29
+ },
30
+ algorithm: "HS256",
31
+ };
32
+ userRepository = new infrastructure_1.InMemoryUserRepository();
33
+ credentialRepository = new infrastructure_1.InMemoryCredentialRepository();
34
+ });
35
+ it("debería crear un contenedor con todas las dependencias correctamente instanciadas", () => {
36
+ const container = application_1.AuthServiceFactory.create(config, userRepository, credentialRepository);
37
+ // Repositorios: deben ser exactamente los mismos que pasamos
38
+ expect(container.userRepository).toBe(userRepository);
39
+ expect(container.credentialRepository).toBe(credentialRepository);
40
+ // Servicios de dominio / infraestructura
41
+ expect(container.passwordHasher).toBeInstanceOf(infrastructure_1.BcryptPasswordHasher);
42
+ expect(container.passwordPolicy).toBeInstanceOf(domain_1.DefaultPasswordPolicy);
43
+ expect(container.tokenService).toBeInstanceOf(infrastructure_1.JwtTokenService);
44
+ expect(container.tokenSession).toBeInstanceOf(infrastructure_1.TokenSessionService);
45
+ // Casos de uso
46
+ expect(container.registerUserUseCase).toBeInstanceOf(use_cases_1.RegisterUserUseCase);
47
+ expect(container.loginWithPasswordUseCase).toBeInstanceOf(use_cases_1.LoginWithPasswordUseCase);
48
+ expect(container.refreshTokenUseCase).toBeInstanceOf(use_cases_1.RefreshTokenUseCase);
49
+ expect(container.logoutUseCase).toBeInstanceOf(use_cases_1.LogoutUseCase);
50
+ });
51
+ it("debería inyectar correctamente JwtTokenService con la configuración JWT recibida", () => {
52
+ const container = application_1.AuthServiceFactory.create(config, userRepository, credentialRepository);
53
+ const tokenService = container.tokenService;
54
+ const jwtConfig = tokenService.config;
55
+ expect(jwtConfig.accessTokenSecret).toBe(config.jwt.accessTokenSecret);
56
+ expect(jwtConfig.refreshTokenSecret).toBe(config.jwt.refreshTokenSecret);
57
+ expect(jwtConfig.accessTokenExpirationMs).toBe(config.jwt.accessTokenExpirationMs);
58
+ expect(jwtConfig.refreshTokenExpirationMs).toBe(config.jwt.refreshTokenExpirationMs);
59
+ expect(tokenService.jwtGenerator).toBeInstanceOf(infrastructure_1.JwtTokenGenerator);
60
+ expect(tokenService.jwtVerifier).toBeInstanceOf(infrastructure_1.JwtTokenVerifier);
61
+ expect(tokenService.jwtValidator).toBeInstanceOf(infrastructure_1.JwtTokenValidator);
62
+ const jwtGenerator = tokenService.jwtGenerator;
63
+ expect(jwtGenerator.signer).toBeInstanceOf(infrastructure_1.JwtSigner);
64
+ expect(jwtGenerator.encoder).toBeDefined();
65
+ });
66
+ it("debería compartir las mismas instancias de repositorios y servicios entre los casos de uso", () => {
67
+ const container = application_1.AuthServiceFactory.create(config, userRepository, credentialRepository);
68
+ const { userRepository: ur, credentialRepository: cr, passwordHasher, passwordPolicy, tokenService, tokenSession, registerUserUseCase, loginWithPasswordUseCase, refreshTokenUseCase, logoutUseCase, } = container;
69
+ // RegisterUserUseCase
70
+ expect(registerUserUseCase.userRepository).toBe(ur);
71
+ expect(registerUserUseCase.passwordHasher).toBe(passwordHasher);
72
+ expect(registerUserUseCase.passwordPolicy).toBe(passwordPolicy);
73
+ // LoginWithPasswordUseCase
74
+ expect(loginWithPasswordUseCase.userRepository).toBe(ur);
75
+ expect(loginWithPasswordUseCase.passwordHasher).toBe(passwordHasher);
76
+ expect(loginWithPasswordUseCase.tokenSessionService).toBe(tokenSession);
77
+ // RefreshTokenUseCase
78
+ const refreshValues = Object.values(refreshTokenUseCase);
79
+ expect(refreshValues).toContain(tokenSession);
80
+ // LogoutUseCase
81
+ const logoutValues = Object.values(logoutUseCase);
82
+ expect(logoutValues).toContain(tokenSession);
83
+ // TokenSessionService wiring interno
84
+ expect(tokenSession.userRepository).toBe(ur);
85
+ expect(tokenSession.credentialRepository).toBe(cr);
86
+ expect(tokenSession.tokenService).toBe(tokenService);
87
+ });
88
+ it("debería respetar las instancias de repositorios entregadas por el llamador", () => {
89
+ const otherUserRepo = new infrastructure_1.InMemoryUserRepository();
90
+ const otherCredRepo = new infrastructure_1.InMemoryCredentialRepository();
91
+ const container = application_1.AuthServiceFactory.create(config, otherUserRepo, otherCredRepo);
92
+ expect(container.userRepository).toBe(otherUserRepo);
93
+ expect(container.credentialRepository).toBe(otherCredRepo);
94
+ expect(container.userRepository).not.toBe(userRepository);
95
+ expect(container.credentialRepository).not.toBe(credentialRepository);
96
+ });
97
+ });
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const application_1 = require("src/application");
4
+ const domain_1 = require("src/domain");
5
+ const infrastructure_1 = require("src/infrastructure");
6
+ /**
7
+ * FakeTokenSession usa el repositorio de credenciales real,
8
+ * pero genera tokens simples sin firmar, sólo para pruebas.
9
+ */
10
+ class FakeTokenSession {
11
+ constructor(credentialRepo) {
12
+ this.credentialRepo = credentialRepo;
13
+ }
14
+ async createSession(user) {
15
+ const credential = new domain_1.Credential({
16
+ userId: user.id,
17
+ accessToken: `access-${user.id.getValue()}`,
18
+ refreshToken: `refresh-${user.id.getValue()}`,
19
+ expiresAt: new Date(Date.now() + 60 * 60 * 1000),
20
+ createdAt: new Date(),
21
+ });
22
+ await this.credentialRepo.save(credential);
23
+ return credential;
24
+ }
25
+ }
26
+ // Constantes comunes
27
+ const plainPassword = "MySecureP@ssw0rd";
28
+ const bcryptHash = "$2b$10$CwTycUXWue0Thq9StjUM0uJ8E9aG7vlYgSi0hd0eZBwbNG0Ax7Anm";
29
+ describe("LoginWithPasswordUseCase (integración con repositorios en memoria)", () => {
30
+ let userRepository;
31
+ let credentialRepository;
32
+ let passwordHasher;
33
+ let tokenSessionService;
34
+ let createSessionSpy;
35
+ let useCase;
36
+ beforeEach(() => {
37
+ userRepository = new infrastructure_1.InMemoryUserRepository();
38
+ credentialRepository = new infrastructure_1.InMemoryCredentialRepository();
39
+ passwordHasher = {
40
+ hash: jest.fn(),
41
+ compare: jest.fn(),
42
+ };
43
+ tokenSessionService = new FakeTokenSession(credentialRepository);
44
+ createSessionSpy = jest.spyOn(tokenSessionService, "createSession");
45
+ useCase = new application_1.LoginWithPasswordUseCase(userRepository, passwordHasher, tokenSessionService);
46
+ });
47
+ afterEach(() => {
48
+ jest.clearAllMocks();
49
+ });
50
+ const createUser = (props) => new domain_1.User({
51
+ id: new domain_1.Id("user-123"),
52
+ email: new domain_1.Email("login@example.com"),
53
+ password: new domain_1.HashedPassword(bcryptHash),
54
+ isActive: true,
55
+ roles: [new domain_1.Role("user")],
56
+ createdAt: new Date(),
57
+ updatedAt: new Date(),
58
+ ...props,
59
+ });
60
+ it("debe crear una sesión persistida al loguear correctamente", async () => {
61
+ const emailValue = "login@example.com";
62
+ const user = createUser({ email: new domain_1.Email(emailValue) });
63
+ await userRepository.save(user);
64
+ passwordHasher.compare.mockResolvedValue(true);
65
+ const request = {
66
+ email: emailValue,
67
+ password: plainPassword,
68
+ };
69
+ // Act
70
+ const response = await useCase.execute(request);
71
+ // Assert: respuesta
72
+ expect(response.accessToken).toBe("access-user-123");
73
+ expect(response.refreshToken).toBe("refresh-user-123");
74
+ // Assert: credencial persistida en el repositorio
75
+ const storedCredential = await credentialRepository.findByUserId(user.id);
76
+ expect(storedCredential).not.toBeNull();
77
+ expect(storedCredential?.accessToken).toBe("access-user-123");
78
+ expect(storedCredential?.refreshToken).toBe("refresh-user-123");
79
+ // Assert: se llamó a createSession
80
+ expect(createSessionSpy).toHaveBeenCalledTimes(1);
81
+ expect(createSessionSpy).toHaveBeenCalledWith(user);
82
+ });
83
+ it("debe loguear correctamente cuando las credenciales son válidas y el usuario está activo", async () => {
84
+ const emailValue = "user@example.com";
85
+ const user = createUser({ email: new domain_1.Email(emailValue) });
86
+ await userRepository.save(user);
87
+ passwordHasher.compare.mockResolvedValue(true);
88
+ const request = {
89
+ email: emailValue,
90
+ password: plainPassword,
91
+ };
92
+ // Act
93
+ const response = await useCase.execute(request);
94
+ // Assert
95
+ expect(passwordHasher.compare).toHaveBeenCalledTimes(1);
96
+ expect(passwordHasher.compare).toHaveBeenCalledWith(request.password, user.password.serialize());
97
+ expect(createSessionSpy).toHaveBeenCalledTimes(1);
98
+ expect(createSessionSpy).toHaveBeenCalledWith(user);
99
+ expect(response).toEqual({
100
+ accessToken: "access-user-123",
101
+ refreshToken: "refresh-user-123",
102
+ });
103
+ });
104
+ it("debe lanzar UserNotFoundError cuando el usuario no existe", async () => {
105
+ const request = {
106
+ email: "unknown@example.com",
107
+ password: "whatever",
108
+ };
109
+ await expect(useCase.execute(request)).rejects.toBeInstanceOf(domain_1.UserNotFoundError);
110
+ expect(passwordHasher.compare).not.toHaveBeenCalled();
111
+ expect(createSessionSpy).not.toHaveBeenCalled();
112
+ });
113
+ it("debe lanzar UserDisabledError cuando el usuario está inactivo", async () => {
114
+ const emailValue = "disabled@example.com";
115
+ const user = createUser({ email: new domain_1.Email(emailValue) });
116
+ // Forzamos que canLogin() devuelva false
117
+ jest.spyOn(user, "canLogin").mockReturnValue(false);
118
+ await userRepository.save(user);
119
+ const request = {
120
+ email: emailValue,
121
+ password: "any-password",
122
+ };
123
+ await expect(useCase.execute(request)).rejects.toBeInstanceOf(domain_1.UserDisabledError);
124
+ expect(passwordHasher.compare).not.toHaveBeenCalled();
125
+ expect(createSessionSpy).not.toHaveBeenCalled();
126
+ });
127
+ it("debe lanzar PasswordMismatchError cuando la contraseña es incorrecta", async () => {
128
+ const emailValue = "user@example.com";
129
+ const user = createUser({ email: new domain_1.Email(emailValue) });
130
+ await userRepository.save(user);
131
+ passwordHasher.compare.mockResolvedValue(false);
132
+ const request = {
133
+ email: emailValue,
134
+ password: "wrong-password",
135
+ };
136
+ await expect(useCase.execute(request)).rejects.toBeInstanceOf(domain_1.PasswordMismatchError);
137
+ expect(passwordHasher.compare).toHaveBeenCalledTimes(1);
138
+ expect(createSessionSpy).not.toHaveBeenCalled();
139
+ });
140
+ });
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ // tests/application/use-cases/logout.usecase.spec.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const application_1 = require("src/application");
5
+ const domain_1 = require("../../../src/domain");
6
+ describe("LogoutUseCase", () => {
7
+ let tokenSessionMock;
8
+ let useCase;
9
+ beforeEach(() => {
10
+ tokenSessionMock = {
11
+ revokeSession: jest.fn(),
12
+ };
13
+ // Solo necesitamos revokeSession para este caso de uso,
14
+ // así que casteamos al tipo completo de ITokenSession.
15
+ useCase = new application_1.LogoutUseCase(tokenSessionMock);
16
+ });
17
+ it("debería cerrar sesión correctamente cuando revokeSession no lanza error", async () => {
18
+ // Arrange
19
+ const request = { refreshToken: "valid-refresh-token" };
20
+ tokenSessionMock.revokeSession.mockResolvedValueOnce(); // Promise<void>
21
+ // Act
22
+ const response = await useCase.execute(request);
23
+ // Assert
24
+ expect(tokenSessionMock.revokeSession).toHaveBeenCalledTimes(1);
25
+ expect(tokenSessionMock.revokeSession).toHaveBeenCalledWith("valid-refresh-token");
26
+ expect(response).toEqual({
27
+ success: true,
28
+ message: "Successfully logged out",
29
+ });
30
+ });
31
+ it("debería lanzar LogoutError cuando revokeSession lanza un error", async () => {
32
+ // Arrange
33
+ const request = { refreshToken: "invalid-refresh-token" };
34
+ tokenSessionMock.revokeSession.mockRejectedValueOnce(new Error("Some low-level error"));
35
+ // Act & Assert
36
+ await expect(useCase.execute(request)).rejects.toEqual(new domain_1.LogoutError("Failed to logout: invalid refresh token"));
37
+ expect(tokenSessionMock.revokeSession).toHaveBeenCalledTimes(1);
38
+ expect(tokenSessionMock.revokeSession).toHaveBeenCalledWith("invalid-refresh-token");
39
+ });
40
+ });
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const application_1 = require("src/application");
4
+ const refresh_token_use_case_1 = require("src/application/use-cases/refresh-token.use-case");
5
+ const domain_1 = require("src/domain");
6
+ const infrastructure_1 = require("src/infrastructure");
7
+ const shared_1 = require("src/shared");
8
+ describe("RefreshTokenUseCase", () => {
9
+ let userRepo;
10
+ let credentialRepo;
11
+ let passwordHasher;
12
+ let jwtSigner;
13
+ let tokenGenerator;
14
+ let tokenSessionService;
15
+ const jwtConfig = {
16
+ accessTokenSecret: "access_secret_key_123",
17
+ refreshTokenSecret: "refresh_secret_key_123",
18
+ accessTokenExpirationMs: 1000 * 60 * 15, // 15 minutos
19
+ refreshTokenExpirationMs: 1000 * 60 * 60 * 24, // 1 día,
20
+ algorithm: "HS256",
21
+ };
22
+ // Hash válido de "Password123!" (cost 10)
23
+ const VALID_BCRYPT = "$2b$10$CwTycUXWue0Thq9StjUM0uJ8rS8o9VZqvE8G9W9C6q7CwTycUXWu2";
24
+ beforeEach(() => {
25
+ userRepo = new infrastructure_1.InMemoryUserRepository();
26
+ credentialRepo = new infrastructure_1.InMemoryCredentialRepository();
27
+ passwordHasher = new infrastructure_1.BcryptPasswordHasher();
28
+ jwtSigner = new infrastructure_1.JwtSigner(new shared_1.Base64UrlEncoder());
29
+ // 👇 Ajuste: orden típico (signer, encoder). Mantén tu firma real si difiere.
30
+ tokenGenerator = new infrastructure_1.JwtTokenGenerator(new shared_1.Base64UrlEncoder(), jwtSigner);
31
+ // TokenSessionJWT implementa ITokenSession
32
+ class TokenSessionJWT {
33
+ constructor(tokenGen, credentialRepo) {
34
+ this.tokenGen = tokenGen;
35
+ this.credentialRepo = credentialRepo;
36
+ }
37
+ validateSession(_accessToken) {
38
+ throw new Error("Method not implemented.");
39
+ }
40
+ async createSession(user) {
41
+ const accessToken = this.tokenGen.generateAccessToken({
42
+ user: {
43
+ id: user.id.getValue(),
44
+ email: user.email.toString(),
45
+ roles: user.roles.map((r) => ({ role: r.getValuePublic().role })),
46
+ },
47
+ config: jwtConfig,
48
+ });
49
+ const refreshToken = this.tokenGen.generateRefreshToken({
50
+ user: {
51
+ id: user.id.getValue(),
52
+ email: user.email.toString(),
53
+ roles: user.roles.map((r) => ({ role: r.getValuePublic().role })),
54
+ },
55
+ config: jwtConfig,
56
+ });
57
+ const credential = new domain_1.Credential({
58
+ userId: new domain_1.Id(user.id.getValue()),
59
+ accessToken,
60
+ refreshToken,
61
+ expiresAt: new Date(Date.now() + jwtConfig.accessTokenExpirationMs),
62
+ createdAt: new Date(),
63
+ });
64
+ await this.credentialRepo.save(credential);
65
+ return credential;
66
+ }
67
+ async refreshSession(refreshToken) {
68
+ const found = await this.credentialRepo.findByRefreshToken(refreshToken);
69
+ if (!found)
70
+ throw new domain_1.InvalidOrExpiredRefreshTokenError();
71
+ // ✅ (opcional) rotar: revocar el refresh anterior para evitar reutilización
72
+ await this.credentialRepo.deleteByRefreshToken(refreshToken);
73
+ const user = new domain_1.User({
74
+ id: new domain_1.Id(found.userId.getValue()),
75
+ email: new domain_1.Email("user@example.com"),
76
+ roles: [new domain_1.Role("USER")],
77
+ password: new domain_1.HashedPassword(VALID_BCRYPT),
78
+ isActive: true,
79
+ createdAt: new Date(),
80
+ updatedAt: new Date(),
81
+ });
82
+ return this.createSession(user);
83
+ }
84
+ async revokeSession(refreshToken) {
85
+ await this.credentialRepo.deleteByRefreshToken(refreshToken);
86
+ }
87
+ }
88
+ tokenSessionService = new TokenSessionJWT(tokenGenerator, credentialRepo);
89
+ });
90
+ it("debería crear un usuario, loguearlo y refrescar su token", async () => {
91
+ // 1️⃣ Registrar usuario
92
+ const passwordPolicy = new domain_1.DefaultPasswordPolicy();
93
+ const registerUser = new application_1.RegisterUserUseCase(userRepo, passwordHasher, passwordPolicy);
94
+ const email = "user@example.com";
95
+ const password = "Password123!";
96
+ const roles = [{ role: "USER" }];
97
+ await registerUser.execute({ email, password, roles });
98
+ // 2️⃣ Loguear usuario
99
+ const login = new application_1.LoginWithPasswordUseCase(userRepo, passwordHasher, tokenSessionService);
100
+ const loginResponse = await login.execute({ email, password });
101
+ expect(loginResponse.accessToken).toBeDefined();
102
+ expect(loginResponse.refreshToken).toBeDefined();
103
+ // 3️⃣ Refrescar Token
104
+ const refreshTokenUseCase = new refresh_token_use_case_1.RefreshTokenUseCase(tokenSessionService);
105
+ const refreshed = await refreshTokenUseCase.execute({
106
+ refreshToken: loginResponse.refreshToken,
107
+ });
108
+ expect(refreshed.accessToken).toBeDefined();
109
+ expect(refreshed.refreshToken).toBeDefined();
110
+ expect(refreshed.refreshToken).not.toEqual(loginResponse.refreshToken);
111
+ });
112
+ it("debería lanzar InvalidOrExpiredRefreshTokenError si el token no existe", async () => {
113
+ const refreshTokenUseCase = new refresh_token_use_case_1.RefreshTokenUseCase(tokenSessionService);
114
+ await expect(refreshTokenUseCase.execute({ refreshToken: "invalid.token" })).rejects.toThrow(domain_1.InvalidOrExpiredRefreshTokenError);
115
+ });
116
+ });
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const application_1 = require("src/application");
4
+ const domain_1 = require("src/domain");
5
+ describe("RegisterUserUseCase", () => {
6
+ let userRepository;
7
+ let passwordHasher;
8
+ let passwordPolicy;
9
+ let useCase;
10
+ beforeEach(() => {
11
+ userRepository = {
12
+ findByEmail: jest.fn(),
13
+ save: jest.fn(),
14
+ // agrega otros métodos del repo si existen, con jest.fn()
15
+ };
16
+ passwordHasher = {
17
+ hash: jest.fn(),
18
+ };
19
+ passwordPolicy = {
20
+ validateStrength: jest.fn(),
21
+ getRequirements: jest.fn(),
22
+ };
23
+ useCase = new application_1.RegisterUserUseCase(userRepository, passwordHasher, passwordPolicy);
24
+ jest.clearAllMocks();
25
+ });
26
+ it("debería lanzar PasswordPolicyViolationError si la contraseña no cumple la política", async () => {
27
+ const weakPasswordErrors = ["Too short", "No number"];
28
+ passwordPolicy.validateStrength.mockReturnValue({
29
+ isValid: false,
30
+ errors: weakPasswordErrors,
31
+ });
32
+ const request = {
33
+ email: "test@example.com",
34
+ password: "weak",
35
+ roles: [],
36
+ };
37
+ await expect(useCase.execute(request)).rejects.toBeInstanceOf(domain_1.PasswordPolicyViolationError);
38
+ expect(passwordPolicy.validateStrength).toHaveBeenCalledWith(request.password);
39
+ expect(userRepository.findByEmail).not.toHaveBeenCalled();
40
+ expect(passwordHasher.hash).not.toHaveBeenCalled();
41
+ expect(userRepository.save).not.toHaveBeenCalled();
42
+ });
43
+ it("debería lanzar EmailAlreadyInUseError si el email ya existe", async () => {
44
+ passwordPolicy.validateStrength.mockReturnValue({
45
+ isValid: true,
46
+ errors: [],
47
+ });
48
+ // No necesitamos un User real, basta con algo truthy
49
+ const existingUser = {};
50
+ userRepository.findByEmail.mockResolvedValue(existingUser);
51
+ const request = {
52
+ email: "used@example.com",
53
+ password: "StrongP@ss1",
54
+ roles: [],
55
+ };
56
+ await expect(useCase.execute(request)).rejects.toBeInstanceOf(domain_1.EmailAlreadyInUseError);
57
+ expect(passwordPolicy.validateStrength).toHaveBeenCalledWith(request.password);
58
+ expect(userRepository.findByEmail).toHaveBeenCalledTimes(1);
59
+ expect(passwordHasher.hash).not.toHaveBeenCalled();
60
+ expect(userRepository.save).not.toHaveBeenCalled();
61
+ });
62
+ it("debería registrar un usuario, guardar en el repositorio y retornar la respuesta correcta", async () => {
63
+ passwordPolicy.validateStrength.mockReturnValue({
64
+ isValid: true,
65
+ errors: [],
66
+ });
67
+ userRepository.findByEmail.mockResolvedValue(null);
68
+ const hashedPassword = "hashed-password-123";
69
+ passwordHasher.hash.mockResolvedValue(hashedPassword);
70
+ const request = {
71
+ email: "newuser@example.com",
72
+ password: "StrongP@ss1",
73
+ roles: [
74
+ {
75
+ role: "ADMIN",
76
+ permissions: ["user.read", "user.write"],
77
+ },
78
+ ],
79
+ };
80
+ // Fake user que retornará User.create
81
+ const fakeUserIdValue = "generated-user-id";
82
+ const fakePublicRoles = [
83
+ {
84
+ role: "ADMIN",
85
+ permissions: ["user.read", "user.write"],
86
+ },
87
+ ];
88
+ const fakeUser = {
89
+ id: {
90
+ getValue: jest.fn().mockReturnValue(fakeUserIdValue),
91
+ },
92
+ roles: [
93
+ {
94
+ getValuePublic: jest.fn().mockReturnValue(fakePublicRoles[0]),
95
+ },
96
+ ],
97
+ isActive: true,
98
+ };
99
+ const createSpy = jest
100
+ .spyOn(domain_1.User, "create")
101
+ .mockReturnValue(fakeUser);
102
+ const result = await useCase.execute(request);
103
+ // Validar interacción con passwordPolicy y repos
104
+ expect(passwordPolicy.validateStrength).toHaveBeenCalledWith(request.password);
105
+ expect(userRepository.findByEmail).toHaveBeenCalledTimes(1);
106
+ expect(passwordHasher.hash).toHaveBeenCalledWith(request.password);
107
+ // Validar que se llama User.create con los argumentos esperados
108
+ expect(createSpy).toHaveBeenCalledWith(request.email, expect.arrayContaining([
109
+ expect.objectContaining({}), // aquí solo validamos que se pasó al menos un Role
110
+ ]), hashedPassword);
111
+ // Validar que se persiste el usuario
112
+ expect(userRepository.save).toHaveBeenCalledWith(fakeUser);
113
+ const expectedResponse = {
114
+ id: fakeUserIdValue,
115
+ roles: fakePublicRoles,
116
+ isActive: true,
117
+ };
118
+ expect(result).toEqual(expectedResponse);
119
+ });
120
+ it("debería permitir registrar usuario sin roles (array vacío por defecto)", async () => {
121
+ passwordPolicy.validateStrength.mockReturnValue({
122
+ isValid: true,
123
+ errors: [],
124
+ });
125
+ userRepository.findByEmail.mockResolvedValue(null);
126
+ const hashedPassword = "hashed-no-roles";
127
+ passwordHasher.hash.mockResolvedValue(hashedPassword);
128
+ const request = {
129
+ email: "noroles@example.com",
130
+ password: "StrongP@ss1",
131
+ // roles: undefined
132
+ };
133
+ const fakeUser = {
134
+ id: {
135
+ getValue: jest.fn().mockReturnValue("no-roles-id"),
136
+ },
137
+ roles: [],
138
+ isActive: true,
139
+ };
140
+ jest.spyOn(domain_1.User, "create").mockReturnValue(fakeUser);
141
+ const result = await useCase.execute(request);
142
+ expect(userRepository.findByEmail).toHaveBeenCalledTimes(1);
143
+ expect(passwordHasher.hash).toHaveBeenCalledWith(request.password);
144
+ expect(userRepository.save).toHaveBeenCalledWith(fakeUser);
145
+ expect(result).toEqual({
146
+ id: "no-roles-id",
147
+ roles: [],
148
+ isActive: true,
149
+ });
150
+ });
151
+ });
@@ -0,0 +1 @@
1
+ export {};