@intlayer/backend 3.0.3 → 3.2.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 (272) hide show
  1. package/dist/cjs/controllers/dictionary.controller.cjs +91 -18
  2. package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
  3. package/dist/cjs/controllers/organization.controller.cjs +140 -12
  4. package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
  5. package/dist/cjs/controllers/project.controller.cjs +181 -31
  6. package/dist/cjs/controllers/project.controller.cjs.map +1 -1
  7. package/dist/cjs/controllers/projectAccessKey.controller.cjs +61 -10
  8. package/dist/cjs/controllers/projectAccessKey.controller.cjs.map +1 -1
  9. package/dist/cjs/controllers/sessionAuth.controller.cjs +291 -62
  10. package/dist/cjs/controllers/sessionAuth.controller.cjs.map +1 -1
  11. package/dist/cjs/controllers/stripe.controller.cjs +84 -0
  12. package/dist/cjs/controllers/stripe.controller.cjs.map +1 -0
  13. package/dist/cjs/controllers/user.controller.cjs +49 -20
  14. package/dist/cjs/controllers/user.controller.cjs.map +1 -1
  15. package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs +182 -0
  16. package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs.map +1 -0
  17. package/dist/cjs/emails/SubscriptionPaymentError.cjs +182 -0
  18. package/dist/cjs/emails/SubscriptionPaymentError.cjs.map +1 -0
  19. package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs +188 -0
  20. package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs.map +1 -0
  21. package/dist/cjs/export.cjs.map +1 -1
  22. package/dist/cjs/index.cjs +16 -5
  23. package/dist/cjs/index.cjs.map +1 -1
  24. package/dist/cjs/middlewares/oAuth2.middleware.cjs +10 -0
  25. package/dist/cjs/middlewares/oAuth2.middleware.cjs.map +1 -1
  26. package/dist/cjs/middlewares/sessionAuth.middleware.cjs +50 -10
  27. package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
  28. package/dist/cjs/routes/dictionary.routes.cjs +2 -62
  29. package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
  30. package/dist/cjs/routes/organization.routes.cjs +1 -25
  31. package/dist/cjs/routes/organization.routes.cjs.map +1 -1
  32. package/dist/cjs/routes/project.routes.cjs +10 -85
  33. package/dist/cjs/routes/project.routes.cjs.map +1 -1
  34. package/dist/cjs/routes/sessionAuth.routes.cjs +26 -25
  35. package/dist/cjs/routes/sessionAuth.routes.cjs.map +1 -1
  36. package/dist/cjs/routes/stripe.routes.cjs +42 -0
  37. package/dist/cjs/routes/stripe.routes.cjs.map +1 -0
  38. package/dist/cjs/routes/user.routes.cjs +6 -27
  39. package/dist/cjs/routes/user.routes.cjs.map +1 -1
  40. package/dist/cjs/schemas/organization.schema.cjs +5 -0
  41. package/dist/cjs/schemas/organization.schema.cjs.map +1 -1
  42. package/dist/cjs/{middlewares/admin.middleware.cjs → schemas/plans.schema.cjs} +32 -20
  43. package/dist/cjs/schemas/plans.schema.cjs.map +1 -0
  44. package/dist/cjs/schemas/project.schema.cjs +14 -1
  45. package/dist/cjs/schemas/project.schema.cjs.map +1 -1
  46. package/dist/cjs/schemas/user.schema.cjs +5 -1
  47. package/dist/cjs/schemas/user.schema.cjs.map +1 -1
  48. package/dist/cjs/services/dictionary.service.cjs.map +1 -1
  49. package/dist/cjs/services/email.service.cjs +113 -43
  50. package/dist/cjs/services/email.service.cjs.map +1 -1
  51. package/dist/cjs/services/oAuth2.service.cjs +16 -8
  52. package/dist/cjs/services/oAuth2.service.cjs.map +1 -1
  53. package/dist/cjs/services/organization.service.cjs +63 -8
  54. package/dist/cjs/services/organization.service.cjs.map +1 -1
  55. package/dist/cjs/services/project.service.cjs +9 -5
  56. package/dist/cjs/services/project.service.cjs.map +1 -1
  57. package/dist/cjs/services/projectAccessKey.service.cjs +42 -10
  58. package/dist/cjs/services/projectAccessKey.service.cjs.map +1 -1
  59. package/dist/cjs/services/sessionAuth.service.cjs +9 -11
  60. package/dist/cjs/services/sessionAuth.service.cjs.map +1 -1
  61. package/dist/cjs/services/subscription.service.cjs +201 -0
  62. package/dist/cjs/services/subscription.service.cjs.map +1 -0
  63. package/dist/cjs/services/user.service.cjs +1 -3
  64. package/dist/cjs/services/user.service.cjs.map +1 -1
  65. package/dist/cjs/types/dictionary.types.cjs.map +1 -1
  66. package/dist/cjs/types/organization.types.cjs.map +1 -1
  67. package/dist/cjs/types/plan.types.cjs +17 -0
  68. package/dist/cjs/types/plan.types.cjs.map +1 -0
  69. package/dist/cjs/types/project.types.cjs.map +1 -1
  70. package/dist/cjs/types/session.types.cjs.map +1 -1
  71. package/dist/cjs/types/user.types.cjs.map +1 -1
  72. package/dist/cjs/utils/errors/ErrorHandler.cjs +29 -9
  73. package/dist/cjs/utils/errors/ErrorHandler.cjs.map +1 -1
  74. package/dist/cjs/utils/errors/ErrorsClass.cjs +17 -3
  75. package/dist/cjs/utils/errors/ErrorsClass.cjs.map +1 -1
  76. package/dist/cjs/utils/errors/errorCodes.cjs +321 -9
  77. package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
  78. package/dist/cjs/utils/mapper/organization.cjs.map +1 -1
  79. package/dist/cjs/utils/mapper/project.cjs +19 -3
  80. package/dist/cjs/utils/mapper/project.cjs.map +1 -1
  81. package/dist/cjs/utils/mapper/user.cjs.map +1 -1
  82. package/dist/cjs/utils/plan.cjs +75 -0
  83. package/dist/cjs/utils/plan.cjs.map +1 -0
  84. package/dist/cjs/utils/responseData.cjs +8 -0
  85. package/dist/cjs/utils/responseData.cjs.map +1 -1
  86. package/dist/cjs/webhooks/stripe.webhook.cjs +133 -0
  87. package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -0
  88. package/dist/esm/controllers/dictionary.controller.mjs +91 -18
  89. package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
  90. package/dist/esm/controllers/organization.controller.mjs +140 -12
  91. package/dist/esm/controllers/organization.controller.mjs.map +1 -1
  92. package/dist/esm/controllers/project.controller.mjs +181 -31
  93. package/dist/esm/controllers/project.controller.mjs.map +1 -1
  94. package/dist/esm/controllers/projectAccessKey.controller.mjs +61 -10
  95. package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
  96. package/dist/esm/controllers/sessionAuth.controller.mjs +287 -61
  97. package/dist/esm/controllers/sessionAuth.controller.mjs.map +1 -1
  98. package/dist/esm/controllers/stripe.controller.mjs +60 -0
  99. package/dist/esm/controllers/stripe.controller.mjs.map +1 -0
  100. package/dist/esm/controllers/user.controller.mjs +49 -20
  101. package/dist/esm/controllers/user.controller.mjs.map +1 -1
  102. package/dist/esm/emails/SubscriptionPaymentCancellation.mjs +168 -0
  103. package/dist/esm/emails/SubscriptionPaymentCancellation.mjs.map +1 -0
  104. package/dist/esm/emails/SubscriptionPaymentError.mjs +168 -0
  105. package/dist/esm/emails/SubscriptionPaymentError.mjs.map +1 -0
  106. package/dist/esm/emails/SubscriptionPaymentSuccess.mjs +174 -0
  107. package/dist/esm/emails/SubscriptionPaymentSuccess.mjs.map +1 -0
  108. package/dist/esm/export.mjs.map +1 -1
  109. package/dist/esm/index.mjs +19 -7
  110. package/dist/esm/index.mjs.map +1 -1
  111. package/dist/esm/middlewares/oAuth2.middleware.mjs +10 -0
  112. package/dist/esm/middlewares/oAuth2.middleware.mjs.map +1 -1
  113. package/dist/esm/middlewares/sessionAuth.middleware.mjs +49 -9
  114. package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
  115. package/dist/esm/routes/dictionary.routes.mjs +2 -62
  116. package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
  117. package/dist/esm/routes/organization.routes.mjs +1 -25
  118. package/dist/esm/routes/organization.routes.mjs.map +1 -1
  119. package/dist/esm/routes/project.routes.mjs +10 -85
  120. package/dist/esm/routes/project.routes.mjs.map +1 -1
  121. package/dist/esm/routes/sessionAuth.routes.mjs +29 -26
  122. package/dist/esm/routes/sessionAuth.routes.mjs.map +1 -1
  123. package/dist/esm/routes/stripe.routes.mjs +17 -0
  124. package/dist/esm/routes/stripe.routes.mjs.map +1 -0
  125. package/dist/esm/routes/user.routes.mjs +6 -27
  126. package/dist/esm/routes/user.routes.mjs.map +1 -1
  127. package/dist/esm/schemas/organization.schema.mjs +5 -0
  128. package/dist/esm/schemas/organization.schema.mjs.map +1 -1
  129. package/dist/esm/schemas/plans.schema.mjs +32 -0
  130. package/dist/esm/schemas/plans.schema.mjs.map +1 -0
  131. package/dist/esm/schemas/project.schema.mjs +13 -1
  132. package/dist/esm/schemas/project.schema.mjs.map +1 -1
  133. package/dist/esm/schemas/user.schema.mjs +5 -1
  134. package/dist/esm/schemas/user.schema.mjs.map +1 -1
  135. package/dist/esm/services/dictionary.service.mjs.map +1 -1
  136. package/dist/esm/services/email.service.mjs +125 -43
  137. package/dist/esm/services/email.service.mjs.map +1 -1
  138. package/dist/esm/services/oAuth2.service.mjs +16 -8
  139. package/dist/esm/services/oAuth2.service.mjs.map +1 -1
  140. package/dist/esm/services/organization.service.mjs +58 -7
  141. package/dist/esm/services/organization.service.mjs.map +1 -1
  142. package/dist/esm/services/project.service.mjs +9 -5
  143. package/dist/esm/services/project.service.mjs.map +1 -1
  144. package/dist/esm/services/projectAccessKey.service.mjs +42 -10
  145. package/dist/esm/services/projectAccessKey.service.mjs.map +1 -1
  146. package/dist/esm/services/sessionAuth.service.mjs +9 -10
  147. package/dist/esm/services/sessionAuth.service.mjs.map +1 -1
  148. package/dist/esm/services/subscription.service.mjs +178 -0
  149. package/dist/esm/services/subscription.service.mjs.map +1 -0
  150. package/dist/esm/services/user.service.mjs +1 -3
  151. package/dist/esm/services/user.service.mjs.map +1 -1
  152. package/dist/esm/types/plan.types.mjs +1 -0
  153. package/dist/esm/types/plan.types.mjs.map +1 -0
  154. package/dist/esm/utils/errors/ErrorHandler.mjs +29 -9
  155. package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
  156. package/dist/esm/utils/errors/ErrorsClass.mjs +17 -3
  157. package/dist/esm/utils/errors/ErrorsClass.mjs.map +1 -1
  158. package/dist/esm/utils/errors/errorCodes.mjs +321 -9
  159. package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
  160. package/dist/esm/utils/mapper/organization.mjs.map +1 -1
  161. package/dist/esm/utils/mapper/project.mjs +17 -2
  162. package/dist/esm/utils/mapper/project.mjs.map +1 -1
  163. package/dist/esm/utils/mapper/user.mjs.map +1 -1
  164. package/dist/esm/utils/plan.mjs +50 -0
  165. package/dist/esm/utils/plan.mjs.map +1 -0
  166. package/dist/esm/utils/responseData.mjs +8 -0
  167. package/dist/esm/utils/responseData.mjs.map +1 -1
  168. package/dist/esm/webhooks/stripe.webhook.mjs +113 -0
  169. package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -0
  170. package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
  171. package/dist/types/controllers/organization.controller.d.ts.map +1 -1
  172. package/dist/types/controllers/project.controller.d.ts +9 -7
  173. package/dist/types/controllers/project.controller.d.ts.map +1 -1
  174. package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
  175. package/dist/types/controllers/sessionAuth.controller.d.ts +28 -9
  176. package/dist/types/controllers/sessionAuth.controller.d.ts.map +1 -1
  177. package/dist/types/controllers/stripe.controller.d.ts +17 -0
  178. package/dist/types/controllers/stripe.controller.d.ts.map +1 -0
  179. package/dist/types/controllers/user.controller.d.ts.map +1 -1
  180. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +20 -0
  181. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -0
  182. package/dist/types/emails/SubscriptionPaymentError.d.ts +20 -0
  183. package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -0
  184. package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +20 -0
  185. package/dist/types/emails/SubscriptionPaymentSuccess.d.ts.map +1 -0
  186. package/dist/types/export.d.ts +2 -0
  187. package/dist/types/export.d.ts.map +1 -1
  188. package/dist/types/index.d.ts.map +1 -1
  189. package/dist/types/middlewares/oAuth2.middleware.d.ts.map +1 -1
  190. package/dist/types/middlewares/sessionAuth.middleware.d.ts +13 -7
  191. package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
  192. package/dist/types/models/dictionary.model.d.ts +1 -1
  193. package/dist/types/models/oAuth2.model.d.ts +1 -1
  194. package/dist/types/models/organization.model.d.ts +2 -1
  195. package/dist/types/models/organization.model.d.ts.map +1 -1
  196. package/dist/types/models/plan.moddel.d.ts +11 -0
  197. package/dist/types/models/plan.moddel.d.ts.map +1 -0
  198. package/dist/types/models/project.model.d.ts +1 -1
  199. package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
  200. package/dist/types/routes/organization.routes.d.ts.map +1 -1
  201. package/dist/types/routes/project.routes.d.ts.map +1 -1
  202. package/dist/types/routes/sessionAuth.routes.d.ts +15 -2
  203. package/dist/types/routes/sessionAuth.routes.d.ts.map +1 -1
  204. package/dist/types/routes/stripe.routes.d.ts +10 -0
  205. package/dist/types/routes/stripe.routes.d.ts.map +1 -0
  206. package/dist/types/routes/user.routes.d.ts.map +1 -1
  207. package/dist/types/schemas/dictionary.schema.d.ts +2 -2
  208. package/dist/types/schemas/oAuth2.schema.d.ts +2 -2
  209. package/dist/types/schemas/organization.schema.d.ts +3 -2
  210. package/dist/types/schemas/organization.schema.d.ts.map +1 -1
  211. package/dist/types/schemas/plans.schema.d.ts +16 -0
  212. package/dist/types/schemas/plans.schema.d.ts.map +1 -0
  213. package/dist/types/schemas/project.schema.d.ts +12 -3
  214. package/dist/types/schemas/project.schema.d.ts.map +1 -1
  215. package/dist/types/schemas/user.schema.d.ts +2 -2
  216. package/dist/types/schemas/user.schema.d.ts.map +1 -1
  217. package/dist/types/services/dictionary.service.d.ts +9 -9
  218. package/dist/types/services/dictionary.service.d.ts.map +1 -1
  219. package/dist/types/services/email.service.d.ts +33 -4
  220. package/dist/types/services/email.service.d.ts.map +1 -1
  221. package/dist/types/services/oAuth2.service.d.ts +7 -5
  222. package/dist/types/services/oAuth2.service.d.ts.map +1 -1
  223. package/dist/types/services/organization.service.d.ts +27 -6
  224. package/dist/types/services/organization.service.d.ts.map +1 -1
  225. package/dist/types/services/plans.service.d.ts +35 -0
  226. package/dist/types/services/plans.service.d.ts.map +1 -0
  227. package/dist/types/services/project.service.d.ts +6 -6
  228. package/dist/types/services/project.service.d.ts.map +1 -1
  229. package/dist/types/services/projectAccessKey.service.d.ts +4 -4
  230. package/dist/types/services/projectAccessKey.service.d.ts.map +1 -1
  231. package/dist/types/services/sessionAuth.service.d.ts +9 -16
  232. package/dist/types/services/sessionAuth.service.d.ts.map +1 -1
  233. package/dist/types/services/subscription.service.d.ts +22 -0
  234. package/dist/types/services/subscription.service.d.ts.map +1 -0
  235. package/dist/types/services/user.service.d.ts +11 -19
  236. package/dist/types/services/user.service.d.ts.map +1 -1
  237. package/dist/types/types/dictionary.types.d.ts +2 -2
  238. package/dist/types/types/dictionary.types.d.ts.map +1 -1
  239. package/dist/types/types/organization.types.d.ts +4 -2
  240. package/dist/types/types/organization.types.d.ts.map +1 -1
  241. package/dist/types/types/plan.types.d.ts +18 -0
  242. package/dist/types/types/plan.types.d.ts.map +1 -0
  243. package/dist/types/types/project.types.d.ts +13 -2
  244. package/dist/types/types/project.types.d.ts.map +1 -1
  245. package/dist/types/types/session.types.d.ts +6 -6
  246. package/dist/types/types/session.types.d.ts.map +1 -1
  247. package/dist/types/types/user.types.d.ts +2 -1
  248. package/dist/types/types/user.types.d.ts.map +1 -1
  249. package/dist/types/utils/errors/ErrorHandler.d.ts +5 -3
  250. package/dist/types/utils/errors/ErrorHandler.d.ts.map +1 -1
  251. package/dist/types/utils/errors/ErrorsClass.d.ts +4 -1
  252. package/dist/types/utils/errors/ErrorsClass.d.ts.map +1 -1
  253. package/dist/types/utils/errors/errorCodes.d.ts +313 -1
  254. package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
  255. package/dist/types/utils/mapper/organization.d.ts +1 -1
  256. package/dist/types/utils/mapper/organization.d.ts.map +1 -1
  257. package/dist/types/utils/mapper/project.d.ts +10 -1
  258. package/dist/types/utils/mapper/project.d.ts.map +1 -1
  259. package/dist/types/utils/mapper/user.d.ts +1 -1
  260. package/dist/types/utils/mapper/user.d.ts.map +1 -1
  261. package/dist/types/utils/plan.d.ts +17 -0
  262. package/dist/types/utils/plan.d.ts.map +1 -0
  263. package/dist/types/utils/responseData.d.ts +13 -2
  264. package/dist/types/utils/responseData.d.ts.map +1 -1
  265. package/dist/types/webhooks/stripe.d.ts +3 -0
  266. package/dist/types/webhooks/stripe.d.ts.map +1 -0
  267. package/dist/types/webhooks/stripe.webhook.d.ts +3 -0
  268. package/dist/types/webhooks/stripe.webhook.d.ts.map +1 -0
  269. package/package.json +27 -24
  270. package/dist/cjs/middlewares/admin.middleware.cjs.map +0 -1
  271. package/dist/esm/middlewares/admin.middleware.mjs +0 -20
  272. package/dist/esm/middlewares/admin.middleware.mjs.map +0 -1
@@ -27,14 +27,20 @@ var import_project = require('./../models/project.model.cjs');
27
27
  var import_errors = require('./../utils/errors/index.cjs');
28
28
  var import_oAuth2 = require('./oAuth2.service.cjs');
29
29
  var import_project2 = require('./project.service.cjs');
30
- const addNewAccessKey = async (accessKeyData, projectId, user) => {
30
+ const addNewAccessKey = async (accessKeyData, projectId, user, organizationRights, projectRights, dictionaryRights) => {
31
31
  const { clientId, clientSecret } = (0, import_oAuth2.generateClientCredentials)();
32
32
  const newAccessKey = {
33
33
  ...accessKeyData,
34
34
  clientId,
35
35
  clientSecret,
36
36
  userId: user._id,
37
- accessToken: []
37
+ accessToken: [],
38
+ rights: restrictAccessKeyRights(
39
+ accessKeyData,
40
+ organizationRights,
41
+ projectRights,
42
+ dictionaryRights
43
+ )
38
44
  };
39
45
  const result = await import_project.ProjectModel.updateOne(
40
46
  { _id: projectId },
@@ -60,9 +66,9 @@ const addNewAccessKey = async (accessKeyData, projectId, user) => {
60
66
  }
61
67
  return newAccessKeyId;
62
68
  };
63
- const deleteAccessKey = async (clientId, project) => {
69
+ const deleteAccessKey = async (clientId, project, userId) => {
64
70
  const projectAccess = project.oAuth2Access.find(
65
- (access) => access.clientId === clientId
71
+ (access) => access.clientId === clientId && String(access.userId) === String(userId)
66
72
  );
67
73
  if (!projectAccess) {
68
74
  throw new import_errors.GenericError("ACCESS_KEY_NOT_FOUND", {
@@ -71,7 +77,10 @@ const deleteAccessKey = async (clientId, project) => {
71
77
  });
72
78
  }
73
79
  const result = await import_project.ProjectModel.updateOne(
74
- { "oAuth2Access.clientId": clientId },
80
+ {
81
+ "oAuth2Access.clientId": clientId,
82
+ "oAuth2Access.userId": String(userId)
83
+ },
75
84
  { $pull: { oAuth2Access: { clientId } } }
76
85
  );
77
86
  if (result.modifiedCount === 0) {
@@ -82,15 +91,17 @@ const deleteAccessKey = async (clientId, project) => {
82
91
  }
83
92
  return projectAccess;
84
93
  };
85
- const refreshAccessKey = async (clientId, projectId) => {
94
+ const refreshAccessKey = async (clientId, projectId, userId) => {
86
95
  const project = await import_project.ProjectModel.findOne({
87
96
  _id: projectId,
88
- "oAuth2Access.clientId": clientId
97
+ "oAuth2Access.clientId": clientId,
98
+ "oAuth2Access.userId": String(userId)
89
99
  });
90
100
  if (!project) {
91
101
  throw new import_errors.GenericError("PROJECT_NOT_FOUND", {
92
102
  clientId,
93
- projectId
103
+ projectId,
104
+ userId
94
105
  });
95
106
  }
96
107
  const projectAccess = project.oAuth2Access.find(
@@ -104,7 +115,10 @@ const refreshAccessKey = async (clientId, projectId) => {
104
115
  }
105
116
  const { clientSecret } = (0, import_oAuth2.generateClientCredentials)();
106
117
  const result = await import_project.ProjectModel.updateOne(
107
- { "oAuth2Access.clientId": clientId },
118
+ {
119
+ "oAuth2Access.clientId": clientId,
120
+ "oAuth2Access.userId": String(userId)
121
+ },
108
122
  {
109
123
  $set: {
110
124
  "oAuth2Access.$.clientId": projectAccess.clientId,
@@ -125,11 +139,29 @@ const refreshAccessKey = async (clientId, projectId) => {
125
139
  if (!newAccessKeyId) {
126
140
  throw new import_errors.GenericError("ACCESS_KEY_CREATION_FAILED", {
127
141
  accessKeyData: updatedProject.oAuth2Access,
128
- projectId
142
+ projectId,
143
+ userId
129
144
  });
130
145
  }
131
146
  return newAccessKeyId;
132
147
  };
148
+ const restrictRights = (givenRights, userRights) => {
149
+ const restrictedRights = {};
150
+ for (const key in givenRights) {
151
+ if (Object.prototype.hasOwnProperty.call(givenRights, key)) {
152
+ restrictedRights[key] = givenRights[key] && userRights[key];
153
+ }
154
+ }
155
+ return restrictedRights;
156
+ };
157
+ const restrictAccessKeyRights = (accessKey, organizationsRights, projectRights, dictionaryRights) => ({
158
+ dictionary: restrictRights(accessKey.rights.dictionary, dictionaryRights),
159
+ project: restrictRights(accessKey.rights.project, projectRights),
160
+ organization: restrictRights(
161
+ accessKey.rights.organization,
162
+ organizationsRights
163
+ )
164
+ });
133
165
  // Annotate the CommonJS export names for ESM import in node:
134
166
  0 && (module.exports = {
135
167
  addNewAccessKey,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/projectAccessKey.service.ts"],"sourcesContent":["import { ProjectModel } from '@models/project.model';\nimport { GenericError } from '@utils/errors';\nimport type { ObjectId } from 'mongoose';\nimport { generateClientCredentials } from './oAuth2.service';\nimport { getProjectById } from './project.service';\nimport type {\n AccessKeyData,\n OAuth2Access,\n OAuth2AccessData,\n Project,\n} from '@/types/project.types';\nimport { User } from '@/types/user.types';\n\n/**\n * Adds a new access key to a project.\n *\n * @param accessKeyData - The access key data.\n * @param projectId - The ID of the project to add the access key to.\n * @param user - The user adding the access key.\n * @returns The new access key.\n *\n */\nexport const addNewAccessKey = async (\n accessKeyData: AccessKeyData,\n projectId: string | ObjectId,\n user: User\n): Promise<OAuth2Access> => {\n const { clientId, clientSecret } = generateClientCredentials();\n\n const newAccessKey: OAuth2AccessData = {\n ...accessKeyData,\n clientId,\n clientSecret,\n userId: user._id,\n accessToken: [],\n };\n\n const result = await ProjectModel.updateOne(\n { _id: projectId },\n { $push: { oAuth2Access: newAccessKey } }\n );\n\n if (result.modifiedCount === 0) {\n throw new GenericError('ACCESS_KEY_CREATION_FAILED', {\n accessKeyData,\n projectId,\n userId: user._id,\n });\n }\n\n const updatedProject = await getProjectById(projectId);\n\n const newAccessKeyId = updatedProject.oAuth2Access.find(\n (access) => access.clientId === clientId\n );\n\n if (!newAccessKeyId) {\n throw new GenericError('ACCESS_KEY_CREATION_FAILED', {\n accessKeyData,\n projectId,\n userId: user._id,\n });\n }\n\n return newAccessKeyId;\n};\n\nexport const deleteAccessKey = async (\n clientId: string | ObjectId,\n project: Project\n) => {\n const projectAccess = project.oAuth2Access.find(\n (access) => access.clientId === clientId\n );\n\n if (!projectAccess) {\n throw new GenericError('ACCESS_KEY_NOT_FOUND', {\n clientId,\n projectId: project._id,\n });\n }\n\n const result = await ProjectModel.updateOne(\n { 'oAuth2Access.clientId': clientId },\n { $pull: { oAuth2Access: { clientId } } }\n );\n\n if (result.modifiedCount === 0) {\n throw new GenericError('ACCESS_KEY_DELETION_FAILED', {\n clientId,\n projectId: project._id,\n });\n }\n\n return projectAccess;\n};\n\nexport const refreshAccessKey = async (\n clientId: string | ObjectId,\n projectId: string | ObjectId\n): Promise<OAuth2Access> => {\n const project = await ProjectModel.findOne({\n _id: projectId,\n 'oAuth2Access.clientId': clientId,\n });\n\n if (!project) {\n throw new GenericError('PROJECT_NOT_FOUND', {\n clientId,\n projectId,\n });\n }\n\n const projectAccess = project.oAuth2Access.find(\n (access) => access.clientId === clientId\n );\n\n if (!projectAccess) {\n throw new GenericError('ACCESS_KEY_NOT_FOUND', {\n clientId,\n projectId: project._id,\n });\n }\n\n const { clientSecret } = generateClientCredentials();\n\n const result = await ProjectModel.updateOne(\n { 'oAuth2Access.clientId': clientId },\n {\n $set: {\n 'oAuth2Access.$.clientId': projectAccess.clientId,\n 'oAuth2Access.$.clientSecret': clientSecret,\n },\n }\n );\n\n if (result.modifiedCount === 0) {\n throw new GenericError('ACCESS_KEy_UPDATE_FAILED', {\n clientId,\n projectId,\n });\n }\n\n const updatedProject = await getProjectById(projectId);\n\n const newAccessKeyId = updatedProject.oAuth2Access.find(\n (access) => access.clientId === projectAccess.clientId\n );\n\n if (!newAccessKeyId) {\n throw new GenericError('ACCESS_KEY_CREATION_FAILED', {\n accessKeyData: updatedProject.oAuth2Access,\n projectId,\n });\n }\n\n return newAccessKeyId;\n};\n"],"mappings":"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","names":["import_project"]}
1
+ {"version":3,"sources":["../../../src/services/projectAccessKey.service.ts"],"sourcesContent":["import { ProjectModel } from '@models/project.model';\nimport { GenericError } from '@utils/errors';\nimport type { ObjectId } from 'mongoose';\nimport { generateClientCredentials } from './oAuth2.service';\nimport { getProjectById } from './project.service';\nimport type {\n AccessKeyData,\n OAuth2Access,\n OAuth2AccessData,\n Project,\n Rights,\n TokenRights,\n} from '@/types/project.types';\nimport { User } from '@/types/user.types';\n\n/**\n * Adds a new access key to a project.\n *\n * @param accessKeyData - The access key data.\n * @param projectId - The ID of the project to add the access key to.\n * @param user - The user adding the access key.\n * @returns The new access key.\n *\n */\nexport const addNewAccessKey = async (\n accessKeyData: AccessKeyData,\n projectId: string | ObjectId,\n user: User,\n organizationRights: Rights,\n projectRights: Rights,\n dictionaryRights: Rights\n): Promise<OAuth2Access> => {\n const { clientId, clientSecret } = generateClientCredentials();\n\n const newAccessKey: OAuth2AccessData = {\n ...accessKeyData,\n clientId,\n clientSecret,\n userId: user._id,\n accessToken: [],\n rights: restrictAccessKeyRights(\n accessKeyData,\n organizationRights,\n projectRights,\n dictionaryRights\n ),\n };\n\n const result = await ProjectModel.updateOne(\n { _id: projectId },\n { $push: { oAuth2Access: newAccessKey } }\n );\n\n if (result.modifiedCount === 0) {\n throw new GenericError('ACCESS_KEY_CREATION_FAILED', {\n accessKeyData,\n projectId,\n userId: user._id,\n });\n }\n\n const updatedProject = await getProjectById(projectId);\n\n const newAccessKeyId = updatedProject.oAuth2Access.find(\n (access) => access.clientId === clientId\n );\n\n if (!newAccessKeyId) {\n throw new GenericError('ACCESS_KEY_CREATION_FAILED', {\n accessKeyData,\n projectId,\n userId: user._id,\n });\n }\n\n return newAccessKeyId;\n};\n\nexport const deleteAccessKey = async (\n clientId: string | ObjectId,\n project: Project,\n userId: string | ObjectId\n) => {\n const projectAccess = project.oAuth2Access.find(\n (access) =>\n access.clientId === clientId && String(access.userId) === String(userId)\n );\n\n if (!projectAccess) {\n throw new GenericError('ACCESS_KEY_NOT_FOUND', {\n clientId,\n projectId: project._id,\n });\n }\n\n const result = await ProjectModel.updateOne(\n {\n 'oAuth2Access.clientId': clientId,\n 'oAuth2Access.userId': String(userId),\n },\n { $pull: { oAuth2Access: { clientId } } }\n );\n\n if (result.modifiedCount === 0) {\n throw new GenericError('ACCESS_KEY_DELETION_FAILED', {\n clientId,\n projectId: project._id,\n });\n }\n\n return projectAccess;\n};\n\nexport const refreshAccessKey = async (\n clientId: string | ObjectId,\n projectId: string | ObjectId,\n userId: string | ObjectId\n): Promise<OAuth2Access> => {\n const project = await ProjectModel.findOne({\n _id: projectId,\n 'oAuth2Access.clientId': clientId,\n 'oAuth2Access.userId': String(userId),\n });\n\n if (!project) {\n throw new GenericError('PROJECT_NOT_FOUND', {\n clientId,\n projectId,\n userId,\n });\n }\n\n const projectAccess = project.oAuth2Access.find(\n (access) => access.clientId === clientId\n );\n\n if (!projectAccess) {\n throw new GenericError('ACCESS_KEY_NOT_FOUND', {\n clientId,\n projectId: project._id,\n });\n }\n\n const { clientSecret } = generateClientCredentials();\n\n const result = await ProjectModel.updateOne(\n {\n 'oAuth2Access.clientId': clientId,\n 'oAuth2Access.userId': String(userId),\n },\n {\n $set: {\n 'oAuth2Access.$.clientId': projectAccess.clientId,\n 'oAuth2Access.$.clientSecret': clientSecret,\n },\n }\n );\n\n if (result.modifiedCount === 0) {\n throw new GenericError('ACCESS_KEy_UPDATE_FAILED', {\n clientId,\n projectId,\n });\n }\n\n const updatedProject = await getProjectById(projectId);\n\n const newAccessKeyId = updatedProject.oAuth2Access.find(\n (access) => access.clientId === projectAccess.clientId\n );\n\n if (!newAccessKeyId) {\n throw new GenericError('ACCESS_KEY_CREATION_FAILED', {\n accessKeyData: updatedProject.oAuth2Access,\n projectId,\n userId,\n });\n }\n\n return newAccessKeyId;\n};\n\nconst restrictRights = (givenRights: Rights, userRights: Rights): Rights => {\n const restrictedRights: Rights = {} as Rights;\n\n for (const key in givenRights) {\n if (Object.prototype.hasOwnProperty.call(givenRights, key)) {\n restrictedRights[key as keyof Rights] =\n givenRights[key as keyof Rights] && userRights[key as keyof Rights];\n }\n }\n\n return restrictedRights;\n};\n\nconst restrictAccessKeyRights = (\n accessKey: AccessKeyData,\n organizationsRights: Rights,\n projectRights: Rights,\n dictionaryRights: Rights\n): TokenRights => ({\n dictionary: restrictRights(accessKey.rights.dictionary, dictionaryRights),\n project: restrictRights(accessKey.rights.project, projectRights),\n organization: restrictRights(\n accessKey.rights.organization,\n organizationsRights\n ),\n});\n"],"mappings":"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","names":["import_project"]}
@@ -28,7 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var sessionAuth_service_exports = {};
30
30
  __export(sessionAuth_service_exports, {
31
- activateUser: () => activateUser,
32
31
  addSession: () => addSession,
33
32
  addUserProvider: () => addUserProvider,
34
33
  changeUserPassword: () => changeUserPassword,
@@ -51,6 +50,7 @@ __export(sessionAuth_service_exports, {
51
50
  updateUserProvider: () => updateUserProvider
52
51
  });
53
52
  module.exports = __toCommonJS(sessionAuth_service_exports);
53
+ var import_crypto = __toESM(require("crypto"), 1);
54
54
  var import_logger = require('./../logger/index.cjs');
55
55
  var import_cookies = require('./../utils/cookies.cjs');
56
56
  var import_errors = require('./../utils/errors/index.cjs');
@@ -161,11 +161,6 @@ const clearProjectAuth = (res) => {
161
161
  res.locals.project = null;
162
162
  res.cookie(import_cookies.Cookies.JWT_PROJECT, "", (0, import_cookies.getClearCookieOptions)());
163
163
  };
164
- const activateUser = async (userId, secret) => {
165
- return await updateUserProvider(userId, "email", {
166
- secret
167
- });
168
- };
169
164
  const generateSecret = (length) => {
170
165
  const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
171
166
  return Array.from(
@@ -187,7 +182,13 @@ const resetUserPassword = async (userId, secret, newPassword) => {
187
182
  if (!emailAndPasswordProvider) {
188
183
  throw new import_errors.GenericError("USER_PROVIDER_NOT_FOUND", { userId });
189
184
  }
190
- if (emailAndPasswordProvider.secret !== secret) {
185
+ if (!emailAndPasswordProvider.secret) {
186
+ throw new import_errors.GenericError("USER_PROVIDER_SECRET_NOT_DEFINED", { userId });
187
+ }
188
+ if (!import_crypto.default.timingSafeEqual(
189
+ Buffer.from(emailAndPasswordProvider.secret),
190
+ Buffer.from(secret)
191
+ )) {
191
192
  throw new import_errors.GenericError("USER_PROVIDER_SECRET_NOT_VALID", { userId });
192
193
  }
193
194
  const updatedUser = await updateUserProvider(userId, "email", {
@@ -337,13 +338,11 @@ const hashUserPassword = async (userWithPasswordNotHashed) => {
337
338
  });
338
339
  return { ...user, provider: userProvider };
339
340
  };
340
- const changeUserPassword = async (userId, oldPassword, newPassword) => {
341
+ const changeUserPassword = async (userId, newPassword) => {
341
342
  const user = await (0, import_user2.getUserById)(userId);
342
343
  if (!user) {
343
344
  throw new import_errors.GenericError("USER_NOT_FOUND", { userId });
344
345
  }
345
- const { email } = user;
346
- await testUserPassword(email, oldPassword);
347
346
  const updatedUser = await updateUserProvider(userId, "email", {
348
347
  passwordHash: await (0, import_bcrypt.hash)(newPassword, await (0, import_bcrypt.genSalt)())
349
348
  });
@@ -361,7 +360,6 @@ const resetPassword = async (userId, password) => {
361
360
  };
362
361
  // Annotate the CommonJS export names for ESM import in node:
363
362
  0 && (module.exports = {
364
- activateUser,
365
363
  addSession,
366
364
  addUserProvider,
367
365
  changeUserPassword,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/sessionAuth.service.ts"],"sourcesContent":["import { logger } from '@logger';\nimport { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport {\n Cookies,\n getClearCookieOptions,\n getCookieOptions,\n MAX_AGE,\n} from '@utils/cookies';\nimport { GenericError } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hash, genSalt, compare } from 'bcrypt';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t } from 'express-intlayer';\nimport jwt from 'jsonwebtoken';\nimport type { Document, ObjectId } from 'mongoose';\nimport { v4 as uuidv4 } from 'uuid';\n// eslint-disable-next-line import/no-cycle\nimport { getUserByEmail, getUserById, updateUserById } from './user.service';\nimport type { Organization } from '@/types/organization.types';\nimport type { Project } from '@/types/project.types';\nimport type {\n SessionProviders,\n EmailPasswordSessionProvider,\n GoogleSessionProvider,\n GithubSessionProvider,\n Session,\n} from '@/types/session.types';\nimport type { User, UserWithPasswordNotHashed } from '@/types/user.types';\n\n/**\n * Adds a session to a user or updates the existing one.\n * @param user - User object.\n * @returns Updated user object.\n */\nexport const addSession = async (user: User): Promise<User> => {\n const userSessionToken = uuidv4();\n\n const session: Session = {\n sessionToken: userSessionToken,\n expires: new Date(Date.now() + MAX_AGE),\n };\n\n const updatedUser: User = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\nexport const removeSession = async (user: User): Promise<User> => {\n const session = undefined;\n\n const updatedUser: User = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\n/**\n * Set user auth locals object\n * @param res - Express response object.\n * @param user - User object.\n */\nexport const setUserAuth = async (res: Response, user: User) => {\n const formattedUser = mapUserToAPI(user);\n\n const userToken = jwt.sign(formattedUser, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!userToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_USER', { user });\n }\n\n const cookieOptions = getCookieOptions();\n\n res.cookie(Cookies.JWT_USER, userToken, cookieOptions);\n\n const userWithSession = await addSession(user);\n\n const userSessionToken = userWithSession.session?.sessionToken;\n\n res.cookie(Cookies.JWT_AUTH, userSessionToken, cookieOptions);\n\n res.locals.user = user;\n logger.info(\n `User logged in - User: Name: ${user.name}, id: ${String(user._id)}`\n );\n};\n\n/**\n * Clears the JWT auth cookies and user locals object.\n * @param res - Express response object.\n */\nexport const clearUserAuth = async (res: ResponseWithInformation) => {\n const { user } = res.locals;\n const cookiesOptions = getClearCookieOptions();\n\n if (user) {\n await removeSession(user);\n }\n\n res.cookie(Cookies.JWT_AUTH, '', cookiesOptions);\n res.cookie(Cookies.JWT_USER, '', cookiesOptions);\n\n res.locals.user = null;\n res.locals.authType = null;\n};\n\n/**\n *\n * @param res\n * @param organization\n * @returns\n */\nexport const setOrganizationAuth = (\n res: ResponseWithInformation,\n organization: Organization\n) => {\n const organizationData = {\n _id: organization._id,\n name: organization.name,\n };\n\n const organizationToken = jwt.sign(\n organizationData,\n process.env.JWT_TOKEN_SECRET!,\n {\n expiresIn: MAX_AGE,\n }\n );\n\n if (!organizationToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_ORGANIZATION', {\n organization,\n });\n }\n\n res.cookie(Cookies.JWT_ORGANIZATION, organizationToken, getCookieOptions());\n\n res.locals.organization = organization;\n};\n\n/**\n * Clears the JWT organization cookies and organization locals object.\n * @param res - Express response object.\n */\nexport const clearOrganizationAuth = (res: ResponseWithInformation) => {\n res.locals.organization = null;\n\n res.cookie(Cookies.JWT_ORGANIZATION, '', getClearCookieOptions());\n};\n\n/**\n * Set project auth locals object\n * @param res - Express response object.\n * @param project - Project object.\n */\nexport const setProjectAuth = (\n res: ResponseWithInformation,\n project: Project\n) => {\n const { organization } = res.locals;\n const projectData = {\n _id: project._id,\n name: project.name,\n };\n\n const projectToken = jwt.sign(projectData, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!projectToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_PROJECT', {\n project,\n });\n }\n\n res.cookie(Cookies.JWT_PROJECT, projectToken, getCookieOptions());\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n project,\n });\n }\n\n if (\n // if the project is not in the organization's projects\n String(organization._id) !== String(project.organizationId)\n ) {\n throw new GenericError('JWT_TOKEN_ORGANIZATION_MISMATCH_PROJECT', {\n project,\n });\n }\n\n res.locals.project = project;\n};\n\n/**\n * Clears the JWT project cookies and project locals object.\n * @param res - Express response object.\n */\nexport const clearProjectAuth = (res: Response) => {\n res.locals.project = null;\n\n res.cookie(Cookies.JWT_PROJECT, '', getClearCookieOptions());\n};\n\n/**\n * Activates a user by setting the emailValidated flag to true.\n * @param user - The user object.\n * @returns\n */\nexport const activateUser = async (\n userId: string | ObjectId,\n secret: string\n): Promise<User> => {\n return await updateUserProvider(userId, 'email', {\n secret,\n });\n};\n\n/**\n * Generates a random secret string of a specified length.\n * @param length - The length of the secret.\n * @returns The generated secret string.\n */\nexport const generateSecret = (length: number): string => {\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n characters.charAt(Math.floor(Math.random() * characters.length))\n ).join('');\n};\n\n/**\n * Handles a password reset request for a user.\n * @param email - The user's email.\n * @param organization - The organization associated with the user.\n * @returns The user object or null if no user was found.\n */\nexport const requestPasswordReset = async (\n email: string\n): Promise<User | null> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { email });\n }\n\n return updateUserProvider(user._id as unknown as string, 'email', {\n secret: generateSecret(35),\n });\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetUserPassword = async (\n userId: string | ObjectId,\n secret: string,\n newPassword: string\n): Promise<User> => {\n const emailAndPasswordProvider = await getUserProvider(userId, 'email');\n\n if (!emailAndPasswordProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', { userId });\n }\n\n if (emailAndPasswordProvider.secret !== secret) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_VALID', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n secret,\n });\n\n return updatedUser;\n};\n\ntype UserProvider<T extends SessionProviders['provider']> = T extends 'email'\n ? EmailPasswordSessionProvider\n : T extends 'google'\n ? GoogleSessionProvider\n : T extends 'github'\n ? GithubSessionProvider\n : SessionProviders;\n\n/**\n * Gets a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to get.\n * @returns The user's provider.\n */\nexport const getUserProvider = async <T extends SessionProviders['provider']>(\n userId: string | ObjectId,\n provider: T,\n providerAccountId?: string\n): Promise<UserProvider<T> | null> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const userProvider = user.provider?.find(\n (providerEl) =>\n (providerEl.provider === provider && !providerAccountId) ||\n (providerAccountId &&\n (providerEl as GithubSessionProvider).providerAccountId ===\n providerAccountId)\n );\n\n return (userProvider as UserProvider<T>) ?? null;\n};\n\n/**\n * Formats the given fields of a user's provider.\n * @param provider - The provider to update.\n * @param user - The user object.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user provider.\n */\nexport const formatUserProviderUpdate = <\n T extends SessionProviders['provider'],\n>(\n provider: T,\n user: Partial<User>,\n providerUpdate: Partial<UserProvider<T>>\n): User['provider'] => {\n const userProvider: SessionProviders[] = (\n user.provider as unknown as Document\n ).toObject();\n const userProviderToUpdate = userProvider?.find(\n (providerEl) => providerEl.provider === provider\n );\n\n let updatedProvider: User['provider'];\n\n if (userProviderToUpdate) {\n const otherProviders =\n user.provider?.filter((p) => p.provider !== provider) ?? [];\n\n updatedProvider = [\n ...otherProviders,\n { ...userProviderToUpdate, ...providerUpdate, provider },\n ];\n } else {\n updatedProvider = [\n ...(user.provider ?? []),\n { ...providerUpdate, provider } as SessionProviders,\n ];\n }\n\n return updatedProvider;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to update.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const updateUserProvider = async <\n T extends SessionProviders['provider'],\n>(\n userId: string | ObjectId,\n provider: T,\n providerUpdate: Partial<UserProvider<T>>\n): Promise<User> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const formattedProviderToUpdate = formatUserProviderUpdate(\n provider,\n user,\n providerUpdate\n );\n\n const updatedUser: User = await updateUserById(userId, {\n provider: formattedProviderToUpdate,\n });\n\n logger.info(\n `User provider updated - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const addUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders\n): Promise<User> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(userId, provider.provider);\n\n if (existingProvider) {\n throw new GenericError('USER_PROVIDER_ALREADY_EXISTS', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = [...(user.provider ?? []), provider];\n\n const updatedUser = await updateUserById(userId, {\n provider: updatedProvider,\n });\n\n logger.info(\n `User provider added - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider.provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Removes a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to remove.\n * @returns The updated user.\n */\nexport const removeUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders['provider'],\n providerAccountId?: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(\n userId,\n provider,\n providerAccountId\n );\n\n if (!existingProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = user.provider?.filter(\n (p) =>\n p.provider !== provider &&\n (!providerAccountId ||\n (providerAccountId &&\n (p as GithubSessionProvider).providerAccountId !== providerAccountId))\n );\n\n return await updateUserById(userId, {\n provider: updatedProvider,\n });\n};\n\ntype TestUserPasswordResult = { user: User | null; error?: string };\n\n/**\n * Logs in a user.\n * @param email - The user's email.\n * @param password - The user's password.\n * @returns The user object.\n */\nexport const testUserPassword = async (\n email: string,\n password: string\n): Promise<TestUserPasswordResult> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n const errorMessages = {\n en: `User not found - ${email}`,\n fr: `Utilisateur non trouvé - ${email}`,\n es: `Usuario no encontrado - ${email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const userEmailPasswordProvider = user.provider?.find(\n (provider) => provider.provider === 'email'\n );\n\n if (!userEmailPasswordProvider?.passwordHash) {\n const errorMessages = {\n en: `User request to login but no password defined: ${user.email}`,\n fr: `Demande de connexion d'utilisateur mais pas de mot de passe défini : ${user.email}`,\n es: `Solicitud de inicio de sesión de usuario pero no se define la contraseña : ${user.email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const isMatch = await compare(\n password,\n userEmailPasswordProvider.passwordHash\n );\n\n if (!isMatch) {\n const errorMessages = {\n en: `Incorrect email or password: ${email}`,\n fr: `Email ou mot de passe incorrect : ${email}`,\n es: `Correo electrónico o contraseña incorrecta : ${email}`,\n };\n\n logger.error(errorMessages.en);\n\n // Await a random time to prevent brute force attacks\n const randomNumber = Math.floor(Math.random() * 1000) + 1000;\n await new Promise((resolve) => setTimeout(resolve, randomNumber));\n\n return { user: null, error: t(errorMessages) };\n }\n\n return { user };\n};\n\n/**\n * Hashes a user's password.\n * @param userWithPasswordNotHashed - The user object with password not hashed.\n * @returns The user object with hashed password.\n */\nexport const hashUserPassword = async (\n userWithPasswordNotHashed: UserWithPasswordNotHashed\n): Promise<Partial<User>> => {\n const { password, ...user } = userWithPasswordNotHashed;\n\n if (!password) {\n throw new GenericError('USER_PASSWORD_NOT_DEFINED', { user });\n }\n\n const userProvider = formatUserProviderUpdate('email', user, {\n passwordHash: await hash(password, await genSalt()),\n secret: generateSecret(35),\n });\n\n return { ...user, provider: userProvider };\n};\n\n/**\n * Changes a user's password.\n * @param userId - The ID of the user.\n * @param oldPassword - The user's old password.\n * @param newPassword - The user's new password.\n * @returns The updated user or null if the password change failed.\n */\nexport const changeUserPassword = async (\n userId: string | ObjectId,\n oldPassword: string,\n newPassword: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const { email } = user;\n\n await testUserPassword(email, oldPassword);\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n });\n\n return updatedUser;\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetPassword = async (userId: string, password: string) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(password, await genSalt()),\n });\n\n return updatedUser;\n};\n"],"mappings":"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","names":["import_user","uuidv4","jwt"]}
1
+ {"version":3,"sources":["../../../src/services/sessionAuth.service.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { logger } from '@logger';\nimport { ResponseWithInformation } from '@middlewares/sessionAuth.middleware';\nimport {\n Cookies,\n getClearCookieOptions,\n getCookieOptions,\n MAX_AGE,\n} from '@utils/cookies';\nimport { GenericError } from '@utils/errors';\nimport { mapUserToAPI } from '@utils/mapper/user';\nimport { hash, genSalt, compare } from 'bcrypt';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t } from 'express-intlayer';\nimport jwt from 'jsonwebtoken';\nimport type { Document, ObjectId } from 'mongoose';\nimport { v4 as uuidv4 } from 'uuid';\n// eslint-disable-next-line import/no-cycle\nimport { getUserByEmail, getUserById, updateUserById } from './user.service';\nimport type { Organization } from '@/types/organization.types';\nimport type { Project } from '@/types/project.types';\nimport type {\n SessionProviders,\n EmailPasswordSessionProvider,\n GoogleSessionProvider,\n GithubSessionProvider,\n Session,\n} from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Adds a session to a user or updates the existing one.\n * @param user - User object.\n * @returns Updated user object.\n */\nexport const addSession = async (user: User): Promise<UserDocument> => {\n const userSessionToken = uuidv4();\n\n const session: Session = {\n sessionToken: userSessionToken,\n expires: new Date(Date.now() + MAX_AGE),\n };\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\nexport const removeSession = async (user: User): Promise<UserDocument> => {\n const session = undefined;\n\n const updatedUser: UserDocument = await updateUserById(user._id, { session });\n\n return updatedUser;\n};\n\n/**\n * Set user auth locals object\n * @param res - Express response object.\n * @param user - User object.\n */\nexport const setUserAuth = async (res: Response, user: User) => {\n const formattedUser = mapUserToAPI(user);\n\n const userToken = jwt.sign(formattedUser, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!userToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_USER', { user });\n }\n\n const cookieOptions = getCookieOptions();\n\n res.cookie(Cookies.JWT_USER, userToken, cookieOptions);\n\n const userWithSession: UserDocument = await addSession(user);\n\n const userSessionToken = userWithSession.session?.sessionToken;\n\n res.cookie(Cookies.JWT_AUTH, userSessionToken, cookieOptions);\n\n res.locals.user = user;\n logger.info(\n `User logged in - User: Name: ${user.name}, id: ${String(user._id)}`\n );\n};\n\n/**\n * Clears the JWT auth cookies and user locals object.\n * @param res - Express response object.\n */\nexport const clearUserAuth = async (res: ResponseWithInformation) => {\n const { user } = res.locals;\n const cookiesOptions = getClearCookieOptions();\n\n if (user) {\n await removeSession(user);\n }\n\n res.cookie(Cookies.JWT_AUTH, '', cookiesOptions);\n res.cookie(Cookies.JWT_USER, '', cookiesOptions);\n\n res.locals.user = null;\n res.locals.authType = null;\n};\n\n/**\n *\n * @param res\n * @param organization\n * @returns\n */\nexport const setOrganizationAuth = (\n res: ResponseWithInformation,\n organization: Organization\n) => {\n const organizationData = {\n _id: organization._id,\n name: organization.name,\n };\n\n const organizationToken = jwt.sign(\n organizationData,\n process.env.JWT_TOKEN_SECRET!,\n {\n expiresIn: MAX_AGE,\n }\n );\n\n if (!organizationToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_ORGANIZATION', {\n organization,\n });\n }\n\n res.cookie(Cookies.JWT_ORGANIZATION, organizationToken, getCookieOptions());\n\n res.locals.organization = organization;\n};\n\n/**\n * Clears the JWT organization cookies and organization locals object.\n * @param res - Express response object.\n */\nexport const clearOrganizationAuth = (res: ResponseWithInformation) => {\n res.locals.organization = null;\n\n res.cookie(Cookies.JWT_ORGANIZATION, '', getClearCookieOptions());\n};\n\n/**\n * Set project auth locals object\n * @param res - Express response object.\n * @param project - Project object.\n */\nexport const setProjectAuth = (\n res: ResponseWithInformation,\n project: Project\n) => {\n const { organization } = res.locals;\n const projectData = {\n _id: project._id,\n name: project.name,\n };\n\n const projectToken = jwt.sign(projectData, process.env.JWT_TOKEN_SECRET!, {\n expiresIn: MAX_AGE,\n });\n\n if (!projectToken) {\n throw new GenericError('JWT_TOKEN_CREATION_FAILED_PROJECT', {\n project,\n });\n }\n\n res.cookie(Cookies.JWT_PROJECT, projectToken, getCookieOptions());\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n project,\n });\n }\n\n if (\n // if the project is not in the organization's projects\n String(organization._id) !== String(project.organizationId)\n ) {\n throw new GenericError('JWT_TOKEN_ORGANIZATION_MISMATCH_PROJECT', {\n project,\n });\n }\n\n res.locals.project = project;\n};\n\n/**\n * Clears the JWT project cookies and project locals object.\n * @param res - Express response object.\n */\nexport const clearProjectAuth = (res: Response) => {\n res.locals.project = null;\n\n res.cookie(Cookies.JWT_PROJECT, '', getClearCookieOptions());\n};\n\n/**\n * Generates a random secret string of a specified length.\n * @param length - The length of the secret.\n * @returns The generated secret string.\n */\nexport const generateSecret = (length: number): string => {\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n characters.charAt(Math.floor(Math.random() * characters.length))\n ).join('');\n};\n\n/**\n * Handles a password reset request for a user.\n * @param email - The user's email.\n * @param organization - The organization associated with the user.\n * @returns The user object or null if no user was found.\n */\nexport const requestPasswordReset = async (\n email: string\n): Promise<User | null> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { email });\n }\n\n return updateUserProvider(user._id as unknown as string, 'email', {\n secret: generateSecret(35),\n });\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetUserPassword = async (\n userId: string | ObjectId,\n secret: string,\n newPassword: string\n): Promise<User> => {\n const emailAndPasswordProvider = await getUserProvider(userId, 'email');\n\n if (!emailAndPasswordProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', { userId });\n }\n\n if (!emailAndPasswordProvider.secret) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_DEFINED', { userId });\n }\n\n if (\n !crypto.timingSafeEqual(\n Buffer.from(emailAndPasswordProvider.secret),\n Buffer.from(secret)\n )\n ) {\n throw new GenericError('USER_PROVIDER_SECRET_NOT_VALID', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n secret,\n });\n\n return updatedUser;\n};\n\ntype UserProvider<T extends SessionProviders['provider']> = T extends 'email'\n ? EmailPasswordSessionProvider\n : T extends 'google'\n ? GoogleSessionProvider\n : T extends 'github'\n ? GithubSessionProvider\n : SessionProviders;\n\n/**\n * Gets a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to get.\n * @returns The user's provider.\n */\nexport const getUserProvider = async <T extends SessionProviders['provider']>(\n userId: string | ObjectId,\n provider: T,\n providerAccountId?: string\n): Promise<UserProvider<T> | null> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const userProvider = user.provider?.find(\n (providerEl) =>\n (providerEl.provider === provider && !providerAccountId) ||\n (providerAccountId &&\n (providerEl as GithubSessionProvider).providerAccountId ===\n providerAccountId)\n );\n\n return (userProvider as UserProvider<T>) ?? null;\n};\n\n/**\n * Formats the given fields of a user's provider.\n * @param provider - The provider to update.\n * @param user - The user object.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user provider.\n */\nexport const formatUserProviderUpdate = <\n T extends SessionProviders['provider'],\n>(\n provider: T,\n user: Partial<User>,\n providerUpdate: Partial<UserProvider<T>>\n): User['provider'] => {\n const userProvider: SessionProviders[] = (\n user.provider as unknown as Document\n ).toObject();\n const userProviderToUpdate = userProvider?.find(\n (providerEl) => providerEl.provider === provider\n );\n\n let updatedProvider: User['provider'];\n\n if (userProviderToUpdate) {\n const otherProviders =\n user.provider?.filter((p) => p.provider !== provider) ?? [];\n\n updatedProvider = [\n ...otherProviders,\n { ...userProviderToUpdate, ...providerUpdate, provider },\n ];\n } else {\n updatedProvider = [\n ...(user.provider ?? []),\n { ...providerUpdate, provider } as SessionProviders,\n ];\n }\n\n return updatedProvider;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to update.\n * @param providerUpdate - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const updateUserProvider = async <\n T extends SessionProviders['provider'],\n>(\n userId: string | ObjectId,\n provider: T,\n providerUpdate: Partial<UserProvider<T>>\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const formattedProviderToUpdate = formatUserProviderUpdate(\n provider,\n user,\n providerUpdate\n );\n\n const updatedUser: UserDocument = await updateUserById(userId, {\n provider: formattedProviderToUpdate,\n });\n\n logger.info(\n `User provider updated - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Updates the given fields of a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The updates to apply to the provider.\n * @returns The updated user.\n */\nexport const addUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders\n): Promise<UserDocument> => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(userId, provider.provider);\n\n if (existingProvider) {\n throw new GenericError('USER_PROVIDER_ALREADY_EXISTS', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = [...(user.provider ?? []), provider];\n\n const updatedUser = await updateUserById(userId, {\n provider: updatedProvider,\n });\n\n logger.info(\n `User provider added - User: Name: ${updatedUser.name}, id: ${String(updatedUser._id)} - Provider: ${provider.provider}`\n );\n\n return updatedUser;\n};\n\n/**\n * Removes a user's provider.\n * @param userId - The ID of the user.\n * @param provider - The provider to remove.\n * @returns The updated user.\n */\nexport const removeUserProvider = async (\n userId: string | ObjectId,\n provider: SessionProviders['provider'],\n providerAccountId?: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const existingProvider = await getUserProvider(\n userId,\n provider,\n providerAccountId\n );\n\n if (!existingProvider) {\n throw new GenericError('USER_PROVIDER_NOT_FOUND', {\n userId,\n provider,\n });\n }\n\n const updatedProvider = user.provider?.filter(\n (p) =>\n p.provider !== provider &&\n (!providerAccountId ||\n (providerAccountId &&\n (p as GithubSessionProvider).providerAccountId !== providerAccountId))\n );\n\n return await updateUserById(userId, {\n provider: updatedProvider,\n });\n};\n\ntype TestUserPasswordResult = { user: User | null; error?: string };\n\n/**\n * Logs in a user.\n * @param email - The user's email.\n * @param password - The user's password.\n * @returns The user object.\n */\nexport const testUserPassword = async (\n email: string,\n password: string\n): Promise<TestUserPasswordResult> => {\n const user = await getUserByEmail(email);\n\n if (!user) {\n const errorMessages = {\n en: `User not found - ${email}`,\n fr: `Utilisateur non trouvé - ${email}`,\n es: `Usuario no encontrado - ${email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const userEmailPasswordProvider = user.provider?.find(\n (provider) => provider.provider === 'email'\n );\n\n if (!userEmailPasswordProvider?.passwordHash) {\n const errorMessages = {\n en: `User request to login but no password defined: ${user.email}`,\n fr: `Demande de connexion d'utilisateur mais pas de mot de passe défini : ${user.email}`,\n es: `Solicitud de inicio de sesión de usuario pero no se define la contraseña : ${user.email}`,\n };\n\n return { user: null, error: t(errorMessages) };\n }\n\n const isMatch = await compare(\n password,\n userEmailPasswordProvider.passwordHash\n );\n\n if (!isMatch) {\n const errorMessages = {\n en: `Incorrect email or password: ${email}`,\n fr: `Email ou mot de passe incorrect : ${email}`,\n es: `Correo electrónico o contraseña incorrecta : ${email}`,\n };\n\n logger.error(errorMessages.en);\n\n // Await a random time to prevent brute force attacks\n const randomNumber = Math.floor(Math.random() * 1000) + 1000;\n await new Promise((resolve) => setTimeout(resolve, randomNumber));\n\n return { user: null, error: t(errorMessages) };\n }\n\n return { user };\n};\n\n/**\n * Hashes a user's password.\n * @param userWithPasswordNotHashed - The user object with password not hashed.\n * @returns The user object with hashed password.\n */\nexport const hashUserPassword = async (\n userWithPasswordNotHashed: UserWithPasswordNotHashed\n): Promise<Partial<UserDocument>> => {\n const { password, ...user } = userWithPasswordNotHashed;\n\n if (!password) {\n throw new GenericError('USER_PASSWORD_NOT_DEFINED', { user });\n }\n\n const userProvider = formatUserProviderUpdate('email', user, {\n passwordHash: await hash(password, await genSalt()),\n secret: generateSecret(35),\n });\n\n return { ...user, provider: userProvider };\n};\n\n/**\n * Changes a user's password.\n * @param userId - The ID of the user.\n * @param newPassword - The user's new password.\n * @returns The updated user or null if the password change failed.\n */\nexport const changeUserPassword = async (\n userId: string | ObjectId,\n newPassword: string\n) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: User = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(newPassword, await genSalt()),\n });\n\n return updatedUser;\n};\n\n/**\n * Resets a user's password.\n * @param userId - The ID of the user.\n * @param secret - The secret token associated with the user.\n * @param newPassword - The new password to set.\n * @returns The updated user or null if the reset failed.\n */\nexport const resetPassword = async (userId: string, password: string) => {\n const user = await getUserById(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n const updatedUser: UserDocument = await updateUserProvider(userId, 'email', {\n passwordHash: await hash(password, await genSalt()),\n });\n\n return updatedUser;\n};\n"],"mappings":"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","names":["import_user","uuidv4","jwt","crypto"]}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var subscription_service_exports = {};
20
+ __export(subscription_service_exports, {
21
+ addSubscription: () => addSubscription,
22
+ cancelSubscription: () => cancelSubscription,
23
+ changeSubscriptionStatus: () => changeSubscriptionStatus
24
+ });
25
+ module.exports = __toCommonJS(subscription_service_exports);
26
+ var import_logger = require('./../logger/index.cjs');
27
+ var import_errors = require('./../utils/errors/index.cjs');
28
+ var import_plan = require('./../utils/plan.cjs');
29
+ var import_intlayer = require("intlayer");
30
+ var import_stripe = require("stripe");
31
+ var import_email = require('./email.service.cjs');
32
+ var import_organization = require('./organization.service.cjs');
33
+ var import_user = require('./user.service.cjs');
34
+ const addSubscription = async (priceId, customerId, email, locale = import_intlayer.Locales.ENGLISH) => {
35
+ let user = await (0, import_user.getUserByEmail)(email);
36
+ const organization = await (0, import_organization.getOrganizationByCustomerId)(customerId);
37
+ if (!organization) {
38
+ throw new import_errors.GenericError("ORGANIZATION_NOT_FOUND", {
39
+ customerId
40
+ });
41
+ }
42
+ if (!user) {
43
+ user = await (0, import_user.createUser)({
44
+ email
45
+ });
46
+ }
47
+ if (!user) {
48
+ throw new import_errors.GenericError("USER_NOT_FOUND", {
49
+ email
50
+ });
51
+ }
52
+ if (user.customerId !== customerId) {
53
+ user.customerId = customerId;
54
+ await user.save();
55
+ }
56
+ const planType = (0, import_plan.retrievePlanInformation)(priceId);
57
+ if (organization.plan) {
58
+ await cancelSubscription(organization.plan.customerId);
59
+ const editedOrganization2 = await (0, import_organization.updatePlan)(organization, {
60
+ ...organization.plan,
61
+ creatorId: user._id,
62
+ priceId,
63
+ type: planType.type,
64
+ period: planType.period,
65
+ status: "ACTIVE"
66
+ });
67
+ if (!editedOrganization2) {
68
+ throw new import_errors.GenericError("ORGANIZATION_UPDATE_FAILED", {
69
+ organizationId: organization._id
70
+ });
71
+ }
72
+ import_logger.logger.info(
73
+ `Updated plan for organization ${organization._id} - ${planType.type} - ${planType.period}`
74
+ );
75
+ return editedOrganization2.plan;
76
+ }
77
+ const editedOrganization = await (0, import_organization.updatePlan)(organization, {
78
+ creatorId: user._id,
79
+ priceId,
80
+ type: planType.type,
81
+ period: planType.period,
82
+ status: "ACTIVE"
83
+ });
84
+ if (!editedOrganization) {
85
+ throw new import_errors.GenericError("ORGANIZATION_UPDATE_FAILED", {
86
+ organizationId: organization._id
87
+ });
88
+ }
89
+ const { type } = (0, import_plan.retrievePlanInformation)(priceId);
90
+ await (0, import_email.sendEmail)({
91
+ type: "subscriptionPaymentSuccess",
92
+ to: user.email,
93
+ username: user.name,
94
+ planName: type,
95
+ subscriptionStartDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
96
+ email,
97
+ manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`,
98
+ locale
99
+ });
100
+ import_logger.logger.info(
101
+ `Created plan for organization ${organization._id} - ${planType.type} - ${planType.period}`
102
+ );
103
+ return editedOrganization.plan;
104
+ };
105
+ const getActiveSubscriptions = async (customerId) => {
106
+ const stripe = new import_stripe.Stripe(process.env.STRIPE_SECRET_KEY);
107
+ const subscriptions = await stripe.subscriptions.list({
108
+ customer: customerId,
109
+ status: "active"
110
+ });
111
+ return subscriptions.data;
112
+ };
113
+ const cancelSubscription = async (customerId) => {
114
+ const stripe = new import_stripe.Stripe(process.env.STRIPE_SECRET_KEY);
115
+ const organization = await (0, import_organization.getOrganizationByCustomerId)(customerId);
116
+ if (!organization) {
117
+ throw new import_errors.GenericError("ORGANIZATION_NOT_FOUND", {
118
+ customerId
119
+ });
120
+ }
121
+ if (!organization.plan) {
122
+ throw new import_errors.GenericError("ORGANIZATION_PLAN_NOT_FOUND", {
123
+ customerId
124
+ });
125
+ }
126
+ const activeSubscriptions = await getActiveSubscriptions(customerId);
127
+ for (const sub of activeSubscriptions) {
128
+ await stripe.subscriptions.cancel(sub.id);
129
+ }
130
+ import_logger.logger.info(
131
+ `Cancelled plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period}`
132
+ );
133
+ return organization.plan;
134
+ };
135
+ const changeSubscriptionStatus = async (customerId, status, locale = import_intlayer.Locales.ENGLISH) => {
136
+ const organization = await (0, import_organization.getOrganizationByCustomerId)(customerId);
137
+ if (!organization) {
138
+ throw new import_errors.GenericError("ORGANIZATION_NOT_FOUND", {
139
+ customerId
140
+ });
141
+ }
142
+ if (!organization.plan) {
143
+ throw new import_errors.GenericError("ORGANIZATION_PLAN_NOT_FOUND", {
144
+ customerId
145
+ });
146
+ }
147
+ const editedOrganization = await (0, import_organization.updatePlan)(organization, {
148
+ status
149
+ });
150
+ if (!editedOrganization) {
151
+ throw new import_errors.GenericError("ORGANIZATION_UPDATE_FAILED", {
152
+ organizationId: organization._id
153
+ });
154
+ }
155
+ const user = await (0, import_user.getUserById)(organization.plan.creatorId);
156
+ import_logger.logger.info(
157
+ `Updated plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period} - ${status}`
158
+ );
159
+ if (status === "ACTIVE") {
160
+ await (0, import_email.sendEmail)({
161
+ type: "subscriptionPaymentSuccess",
162
+ to: user.email,
163
+ username: user.name,
164
+ email: user.email,
165
+ planName: organization.plan.type,
166
+ subscriptionStartDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
167
+ manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`,
168
+ locale
169
+ });
170
+ } else if (status === "CANCELLED") {
171
+ await (0, import_email.sendEmail)({
172
+ type: "subscriptionPaymentCancellation",
173
+ to: user.email,
174
+ username: user.name,
175
+ email: user.email,
176
+ planName: organization.plan.type,
177
+ cancellationDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
178
+ reactivateLink: `${process.env.CLIENT_URL}/dashboard`,
179
+ locale
180
+ });
181
+ } else if (status === "ERROR") {
182
+ await (0, import_email.sendEmail)({
183
+ type: "subscriptionPaymentError",
184
+ to: user.email,
185
+ username: user.name,
186
+ email: user.email,
187
+ planName: organization.plan.type,
188
+ errorDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
189
+ retryPaymentLink: `${process.env.CLIENT_URL}/dashboard`,
190
+ locale
191
+ });
192
+ }
193
+ return editedOrganization.plan;
194
+ };
195
+ // Annotate the CommonJS export names for ESM import in node:
196
+ 0 && (module.exports = {
197
+ addSubscription,
198
+ cancelSubscription,
199
+ changeSubscriptionStatus
200
+ });
201
+ //# sourceMappingURL=subscription.service.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/services/subscription.service.ts"],"sourcesContent":["import { logger } from '@logger';\nimport { GenericError } from '@utils/errors';\nimport { retrievePlanInformation } from '@utils/plan';\nimport { Locales } from 'intlayer';\nimport { Stripe } from 'stripe';\nimport { sendEmail } from './email.service';\nimport {\n getOrganizationByCustomerId,\n updatePlan,\n} from './organization.service';\nimport { getUserByEmail, createUser, getUserById } from './user.service';\nimport { Plan } from '@/types/plan.types';\n\n/**\n * Adds a subscription to an organization.\n * @param priceId - The ID of the price to add.\n * @param customerId - The ID of the customer to add.\n * @param email - The email of the user to add.\n * @param locale - The locale of the user to add.\n * @returns The added plan.\n */\nexport const addSubscription = async (\n priceId: string,\n customerId: string,\n email: string,\n locale: Locales = Locales.ENGLISH\n): Promise<Plan | null> => {\n let user = await getUserByEmail(email);\n const organization = await getOrganizationByCustomerId(customerId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n customerId,\n });\n }\n\n if (!user) {\n user = await createUser({\n email,\n });\n }\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', {\n email,\n });\n }\n\n if (user.customerId !== customerId) {\n user.customerId = customerId as string;\n await user.save();\n }\n const planType = retrievePlanInformation(priceId!);\n\n if (organization.plan) {\n // Cancel the current plan\n await cancelSubscription(organization.plan.customerId!);\n\n const editedOrganization = await updatePlan(organization, {\n ...organization.plan,\n creatorId: user._id,\n priceId: priceId!,\n type: planType.type,\n period: planType.period,\n status: 'ACTIVE',\n });\n\n if (!editedOrganization) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization._id,\n });\n }\n\n logger.info(\n `Updated plan for organization ${organization._id} - ${planType.type} - ${planType.period}`\n );\n\n return editedOrganization.plan;\n }\n\n const editedOrganization = await updatePlan(organization, {\n creatorId: user._id,\n priceId: priceId!,\n type: planType.type,\n period: planType.period,\n status: 'ACTIVE',\n });\n\n if (!editedOrganization) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization._id,\n });\n }\n\n const { type } = retrievePlanInformation(priceId!);\n\n await sendEmail({\n type: 'subscriptionPaymentSuccess',\n to: user.email,\n username: user.name,\n planName: type,\n subscriptionStartDate: new Date().toLocaleDateString(),\n email,\n manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n\n logger.info(\n `Created plan for organization ${organization._id} - ${planType.type} - ${planType.period}`\n );\n\n return editedOrganization.plan;\n};\n\n/* Function to retrieve active subscriptions for a customer\n * Returns an array of Stripe.Subscription objects\n */\nconst getActiveSubscriptions = async (\n customerId: string\n): Promise<Stripe.Subscription[]> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n const subscriptions = await stripe.subscriptions.list({\n customer: customerId,\n status: 'active',\n });\n return subscriptions.data;\n};\n\nexport const cancelSubscription = async (customerId: string) => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const organization = await getOrganizationByCustomerId(customerId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n customerId,\n });\n }\n\n if (!organization.plan) {\n throw new GenericError('ORGANIZATION_PLAN_NOT_FOUND', {\n customerId,\n });\n }\n\n // Retrieve and cancel existing subscriptions\n const activeSubscriptions = await getActiveSubscriptions(customerId);\n for (const sub of activeSubscriptions) {\n await stripe.subscriptions.cancel(sub.id);\n }\n\n logger.info(\n `Cancelled plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period}`\n );\n\n return organization.plan;\n};\n\n/**\n * Changes the subscription status of an organization.\n *\n * @param customerId - The ID of the customer to change the subscription status for.\n * @param status - The new status of the subscription.\n * @param locale - The locale of the user to change the subscription status for.\n * @returns The updated plan.\n */\nexport const changeSubscriptionStatus = async (\n customerId: string,\n status: Plan['status'],\n locale: Locales = Locales.ENGLISH\n) => {\n const organization = await getOrganizationByCustomerId(customerId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n customerId,\n });\n }\n\n if (!organization.plan) {\n throw new GenericError('ORGANIZATION_PLAN_NOT_FOUND', {\n customerId,\n });\n }\n\n const editedOrganization = await updatePlan(organization, {\n status,\n });\n\n if (!editedOrganization) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization._id,\n });\n }\n\n const user = await getUserById(organization.plan.creatorId!);\n\n logger.info(\n `Updated plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period} - ${status}`\n );\n\n if (status === 'ACTIVE') {\n await sendEmail({\n type: 'subscriptionPaymentSuccess',\n to: user!.email,\n username: user!.name,\n email: user!.email,\n planName: organization.plan.type,\n subscriptionStartDate: new Date().toLocaleDateString(),\n manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n } else if (status === 'CANCELLED') {\n await sendEmail({\n type: 'subscriptionPaymentCancellation',\n to: user!.email,\n username: user!.name,\n email: user!.email,\n planName: organization.plan.type,\n cancellationDate: new Date().toLocaleDateString(),\n reactivateLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n } else if (status === 'ERROR') {\n await sendEmail({\n type: 'subscriptionPaymentError',\n to: user!.email,\n username: user!.name,\n email: user!.email,\n planName: organization.plan.type,\n errorDate: new Date().toLocaleDateString(),\n retryPaymentLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n }\n\n return editedOrganization.plan;\n};\n"],"mappings":"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","names":["editedOrganization"]}
@@ -67,9 +67,7 @@ const checkUserExists = async (email) => {
67
67
  const user = await import_user.UserModel.exists({ email });
68
68
  return user !== null;
69
69
  };
70
- const getUserById = async (userId) => {
71
- return await import_user.UserModel.findById(userId);
72
- };
70
+ const getUserById = async (userId) => await import_user.UserModel.findById(userId);
73
71
  const getUsersByIds = async (userIds) => {
74
72
  return await import_user.UserModel.find({ _id: { $in: userIds } });
75
73
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/services/user.service.ts"],"sourcesContent":["import { UserModel } from '@models/user.model';\nimport { GenericError } from '@utils/errors';\nimport type { UserFilters } from '@utils/filtersAndPagination/getUserFiltersAndPagination';\nimport {\n type FieldsToCheck,\n type UserFields,\n validateUser,\n} from '@utils/validation/validateUser';\nimport type { ObjectId } from 'mongoose';\n// eslint-disable-next-line import/no-cycle\nimport { hashUserPassword } from './sessionAuth.service';\nimport type { SessionProviders } from '@/types/session.types';\nimport type {\n User,\n UserAPI,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Creates a new user with password in the database and hashes the password.\n * @param user - User object with password not hashed.\n * @returns Created user object.\n */\nexport const createUser = async (user: UserWithPasswordNotHashed) => {\n const fieldsToCheck: FieldsToCheck[] = ['email'];\n\n const errors = validateUser(user, fieldsToCheck);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('USER_INVALID_FIELDS', {\n userEmail: user.email,\n errors,\n });\n }\n\n let newUser: User;\n\n if (user.password) {\n const userWithHashedPassword = await hashUserPassword(user);\n\n newUser = await UserModel.create(userWithHashedPassword);\n } else {\n newUser = await UserModel.create(user);\n }\n\n if (!newUser) {\n throw new GenericError('USER_CREATION_FAILED', { userEmail: user.email });\n }\n\n return newUser;\n};\n\n/**\n * Retrieves a user by email.\n * @param email - User's email.\n * @returns User object or null if no user was found.\n */\nexport const getUserByEmail = async (email: string): Promise<User | null> => {\n return await UserModel.findOne({ email });\n};\n\n/**\n * Retrieves users list by email.\n * @param emails - Users email.\n * @returns User object or null if no user was found.\n */\nexport const getUsersByEmails = async (\n emails: string[]\n): Promise<User[] | null> => {\n return await UserModel.find({ email: { $in: emails } });\n};\n\n/**\n * Checks if a user exists by email.\n * @param email - User's email.\n * @returns True if the user exists, false otherwise.\n */\nexport const checkUserExists = async (email: string) => {\n const user = await UserModel.exists({ email });\n return user !== null;\n};\n\n/**\n * Retrieves a user by ID.\n * @param userId - User's ID.\n * @returns User object or null if no user was found.\n */\nexport const getUserById = async (\n userId: string | ObjectId\n): Promise<User | null> => {\n return await UserModel.findById(userId);\n};\n\n/**\n * Retrieves a user by ID.\n * @param userId - User's ID.\n * @returns User object or null if no user was found.\n */\nexport const getUsersByIds = async (\n userIds: (string | ObjectId)[]\n): Promise<User[] | null> => {\n return await UserModel.find({ _id: { $in: userIds } });\n};\n\n/**\n * Retrieves a user by session token.\n * @param sessionToken - The session token.\n * @returns User object or null if no user was found.\n */\nexport const getUserBySession = async (sessionToken: string) => {\n // Get an user by session token and check if it expired\n const user = await UserModel.findOne({\n 'session.sessionToken': sessionToken,\n });\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { sessionToken });\n }\n\n if (user.session?.expires && user.session.expires < new Date()) {\n throw new GenericError('USER_SESSION_EXPIRED', {\n sessionToken,\n userId: user.id,\n });\n }\n\n return user;\n};\n\n/**\n * Retrieves a user by account.\n * @param provider - The provider of the account.\n * @param providerAccountId - The provider account ID.\n * @returns User object or null if no user was found.\n */\nexport const getUserByAccount = async (\n provider: SessionProviders['provider'],\n providerAccountId: string\n): Promise<User> => {\n const user = await UserModel.findOne({\n provider: [{ provider, providerAccountId }],\n });\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', {\n provider,\n providerAccountId,\n });\n }\n\n return user;\n};\n\n/**\n * Finds users based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of users matching the filters.\n */\nexport const findUsers = async (\n filters: UserFilters,\n skip: number,\n limit: number\n): Promise<User[]> => {\n return await UserModel.find(filters).skip(skip).limit(limit);\n};\n\n/**\n * Counts the total number of users that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of users.\n */\nexport const countUsers = async (filters: UserFilters): Promise<number> => {\n const count = await UserModel.countDocuments(filters);\n\n if (typeof count === 'undefined') {\n throw new GenericError('USER_COUNT_FAILED');\n }\n\n return count;\n};\n\n/**\n * Updates a user's information.\n * @param user - The user object.\n * @param updates - The updates to apply to the user.\n * @returns The updated user.\n */\nexport const updateUserById = async (\n userId: string | ObjectId,\n updates: Partial<User>\n): Promise<User> => {\n const keyToValidate = Object.keys(updates) as UserFields;\n const errors = validateUser(updates, keyToValidate);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('USER_INVALID_FIELDS', {\n userId,\n errors,\n });\n }\n\n const result = await UserModel.updateOne({ _id: userId }, { $set: updates });\n\n if (result.matchedCount === 0) {\n throw new GenericError('USER_UPDATE_FAILED', { userId });\n }\n\n const updatedUser = await UserModel.findById(userId);\n\n if (!updatedUser) {\n throw new GenericError('USER_UPDATED_USER_NOT_FOUND', { userId });\n }\n\n return updatedUser;\n};\n\n/**\n * Deletes a user from the database.\n * @param userId - The user object.\n * @returns\n */\nexport const deleteUser = async (userId: string | ObjectId) => {\n await getUserById(userId);\n\n const user = await UserModel.findByIdAndDelete(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n return user;\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/services/user.service.ts"],"sourcesContent":["import { UserModel } from '@models/user.model';\nimport { GenericError } from '@utils/errors';\nimport type { UserFilters } from '@utils/filtersAndPagination/getUserFiltersAndPagination';\nimport {\n type FieldsToCheck,\n type UserFields,\n validateUser,\n} from '@utils/validation/validateUser';\nimport type { ObjectId } from 'mongoose';\n// eslint-disable-next-line import/no-cycle\nimport { hashUserPassword } from './sessionAuth.service';\nimport type { SessionProviders } from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Creates a new user with password in the database and hashes the password.\n * @param user - User object with password not hashed.\n * @returns Created user object.\n */\nexport const createUser = async (\n user: UserWithPasswordNotHashed\n): Promise<UserDocument> => {\n const fieldsToCheck: FieldsToCheck[] = ['email'];\n\n const errors = validateUser(user, fieldsToCheck);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('USER_INVALID_FIELDS', {\n userEmail: user.email,\n errors,\n });\n }\n\n let newUser: UserDocument;\n\n if (user.password) {\n const userWithHashedPassword = await hashUserPassword(user);\n\n newUser = await UserModel.create(userWithHashedPassword);\n } else {\n newUser = await UserModel.create(user);\n }\n\n if (!newUser) {\n throw new GenericError('USER_CREATION_FAILED', { userEmail: user.email });\n }\n\n return newUser;\n};\n\n/**\n * Retrieves a user by email.\n * @param email - User's email.\n * @returns User object or null if no user was found.\n */\nexport const getUserByEmail = async (\n email: string\n): Promise<UserDocument | null> => {\n return await UserModel.findOne({ email });\n};\n\n/**\n * Retrieves users list by email.\n * @param emails - Users email.\n * @returns User object or null if no user was found.\n */\nexport const getUsersByEmails = async (\n emails: string[]\n): Promise<UserDocument[] | null> => {\n return await UserModel.find({ email: { $in: emails } });\n};\n\n/**\n * Checks if a user exists by email.\n * @param email - User's email.\n * @returns True if the user exists, false otherwise.\n */\nexport const checkUserExists = async (email: string): Promise<boolean> => {\n const user = await UserModel.exists({ email });\n return user !== null;\n};\n\n/**\n * Retrieves a user by ID.\n * @param userId - User's ID.\n * @returns User object or null if no user was found.\n */\nexport const getUserById = async (\n userId: string | ObjectId\n): Promise<UserDocument | null> => await UserModel.findById(userId);\n\n/**\n * Retrieves a user by ID.\n * @param userId - User's ID.\n * @returns User object or null if no user was found.\n */\nexport const getUsersByIds = async (\n userIds: (string | ObjectId)[]\n): Promise<UserDocument[] | null> => {\n return await UserModel.find({ _id: { $in: userIds } });\n};\n\n/**\n * Retrieves a user by session token.\n * @param sessionToken - The session token.\n * @returns User object or null if no user was found.\n */\nexport const getUserBySession = async (\n sessionToken: string\n): Promise<UserDocument> => {\n // Get an user by session token and check if it expired\n const user = await UserModel.findOne({\n 'session.sessionToken': sessionToken,\n });\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { sessionToken });\n }\n\n if (user.session?.expires && user.session.expires < new Date()) {\n throw new GenericError('USER_SESSION_EXPIRED', {\n sessionToken,\n userId: user.id,\n });\n }\n\n return user;\n};\n\n/**\n * Retrieves a user by account.\n * @param provider - The provider of the account.\n * @param providerAccountId - The provider account ID.\n * @returns User object or null if no user was found.\n */\nexport const getUserByAccount = async (\n provider: SessionProviders['provider'],\n providerAccountId: string\n): Promise<UserDocument> => {\n const user = await UserModel.findOne({\n provider: [{ provider, providerAccountId }],\n });\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', {\n provider,\n providerAccountId,\n });\n }\n\n return user;\n};\n\n/**\n * Finds users based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of users matching the filters.\n */\nexport const findUsers = async (\n filters: UserFilters,\n skip: number,\n limit: number\n): Promise<UserDocument[]> => {\n return await UserModel.find(filters).skip(skip).limit(limit);\n};\n\n/**\n * Counts the total number of users that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of users.\n */\nexport const countUsers = async (filters: UserFilters): Promise<number> => {\n const count = await UserModel.countDocuments(filters);\n\n if (typeof count === 'undefined') {\n throw new GenericError('USER_COUNT_FAILED');\n }\n\n return count;\n};\n\n/**\n * Updates a user's information.\n * @param user - The user object.\n * @param updates - The updates to apply to the user.\n * @returns The updated user.\n */\nexport const updateUserById = async (\n userId: string | ObjectId,\n updates: Partial<User>\n): Promise<UserDocument> => {\n const keyToValidate = Object.keys(updates) as UserFields;\n const errors = validateUser(updates, keyToValidate);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('USER_INVALID_FIELDS', {\n userId,\n errors,\n });\n }\n\n const result = await UserModel.updateOne({ _id: userId }, { $set: updates });\n\n if (result.matchedCount === 0) {\n throw new GenericError('USER_UPDATE_FAILED', { userId });\n }\n\n const updatedUser = await UserModel.findById(userId);\n\n if (!updatedUser) {\n throw new GenericError('USER_UPDATED_USER_NOT_FOUND', { userId });\n }\n\n return updatedUser;\n};\n\n/**\n * Deletes a user from the database.\n * @param userId - The user object.\n * @returns\n */\nexport const deleteUser = async (\n userId: string | ObjectId\n): Promise<UserDocument> => {\n await getUserById(userId);\n\n const user = await UserModel.findByIdAndDelete(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n return user;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA0B;AAC1B,oBAA6B;AAE7B,0BAIO;AAGP,yBAAiC;AAa1B,MAAM,aAAa,OACxB,SAC0B;AAC1B,QAAM,gBAAiC,CAAC,OAAO;AAE/C,QAAM,aAAS,kCAAa,MAAM,aAAa;AAE/C,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,2BAAa,uBAAuB;AAAA,MAC5C,WAAW,KAAK;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI;AAEJ,MAAI,KAAK,UAAU;AACjB,UAAM,yBAAyB,UAAM,qCAAiB,IAAI;AAE1D,cAAU,MAAM,sBAAU,OAAO,sBAAsB;AAAA,EACzD,OAAO;AACL,cAAU,MAAM,sBAAU,OAAO,IAAI;AAAA,EACvC;AAEA,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,2BAAa,wBAAwB,EAAE,WAAW,KAAK,MAAM,CAAC;AAAA,EAC1E;AAEA,SAAO;AACT;AAOO,MAAM,iBAAiB,OAC5B,UACiC;AACjC,SAAO,MAAM,sBAAU,QAAQ,EAAE,MAAM,CAAC;AAC1C;AAOO,MAAM,mBAAmB,OAC9B,WACmC;AACnC,SAAO,MAAM,sBAAU,KAAK,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;AACxD;AAOO,MAAM,kBAAkB,OAAO,UAAoC;AACxE,QAAM,OAAO,MAAM,sBAAU,OAAO,EAAE,MAAM,CAAC;AAC7C,SAAO,SAAS;AAClB;AAOO,MAAM,cAAc,OACzB,WACiC,MAAM,sBAAU,SAAS,MAAM;AAO3D,MAAM,gBAAgB,OAC3B,YACmC;AACnC,SAAO,MAAM,sBAAU,KAAK,EAAE,KAAK,EAAE,KAAK,QAAQ,EAAE,CAAC;AACvD;AAOO,MAAM,mBAAmB,OAC9B,iBAC0B;AAE1B,QAAM,OAAO,MAAM,sBAAU,QAAQ;AAAA,IACnC,wBAAwB;AAAA,EAC1B,CAAC;AAED,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,2BAAa,kBAAkB,EAAE,aAAa,CAAC;AAAA,EAC3D;AAEA,MAAI,KAAK,SAAS,WAAW,KAAK,QAAQ,UAAU,oBAAI,KAAK,GAAG;AAC9D,UAAM,IAAI,2BAAa,wBAAwB;AAAA,MAC7C;AAAA,MACA,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAQO,MAAM,mBAAmB,OAC9B,UACA,sBAC0B;AAC1B,QAAM,OAAO,MAAM,sBAAU,QAAQ;AAAA,IACnC,UAAU,CAAC,EAAE,UAAU,kBAAkB,CAAC;AAAA,EAC5C,CAAC;AAED,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,2BAAa,kBAAkB;AAAA,MACvC;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AASO,MAAM,YAAY,OACvB,SACA,MACA,UAC4B;AAC5B,SAAO,MAAM,sBAAU,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK;AAC7D;AAOO,MAAM,aAAa,OAAO,YAA0C;AACzE,QAAM,QAAQ,MAAM,sBAAU,eAAe,OAAO;AAEpD,MAAI,OAAO,UAAU,aAAa;AAChC,UAAM,IAAI,2BAAa,mBAAmB;AAAA,EAC5C;AAEA,SAAO;AACT;AAQO,MAAM,iBAAiB,OAC5B,QACA,YAC0B;AAC1B,QAAM,gBAAgB,OAAO,KAAK,OAAO;AACzC,QAAM,aAAS,kCAAa,SAAS,aAAa;AAElD,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,2BAAa,uBAAuB;AAAA,MAC5C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM,sBAAU,UAAU,EAAE,KAAK,OAAO,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE3E,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,IAAI,2BAAa,sBAAsB,EAAE,OAAO,CAAC;AAAA,EACzD;AAEA,QAAM,cAAc,MAAM,sBAAU,SAAS,MAAM;AAEnD,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,2BAAa,+BAA+B,EAAE,OAAO,CAAC;AAAA,EAClE;AAEA,SAAO;AACT;AAOO,MAAM,aAAa,OACxB,WAC0B;AAC1B,QAAM,YAAY,MAAM;AAExB,QAAM,OAAO,MAAM,sBAAU,kBAAkB,MAAM;AAErD,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,2BAAa,kBAAkB,EAAE,OAAO,CAAC;AAAA,EACrD;AAEA,SAAO;AACT;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/types/dictionary.types.ts"],"sourcesContent":["import type { DictionaryValue } from '@intlayer/core';\nimport type { Model, ObjectId, Document } from 'mongoose';\nimport type { Project } from './project.types';\nimport type { User } from './user.types';\n\nexport type DictionaryCreationData = {\n projectIds: (Project['_id'] | string)[];\n key: string;\n content?: DictionaryValue;\n title?: string;\n description?: string;\n version?: number;\n filePath?: string;\n};\n\nexport type DictionaryData = {\n projectIds: (Project['_id'] | string)[];\n key: string;\n content: DictionaryValue[];\n creatorId: User['_id'];\n title?: string;\n description?: string;\n version?: number;\n filePath?: Record<string, string>;\n};\n\nexport type Dictionary = DictionaryData & {\n _id: ObjectId;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type DictionaryAPI = Omit<DictionaryData, 'filePath' | 'content'> & {\n content: DictionaryValue;\n filePath?: string;\n};\n\nexport type DictionaryDocument = Document<Dictionary> & Dictionary;\nexport type DictionaryModelType = Model<Dictionary>;\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../../src/types/dictionary.types.ts"],"sourcesContent":["import type { DictionaryValue } from '@intlayer/core';\nimport type { Model, ObjectId, Document } from 'mongoose';\nimport type { Project } from './project.types';\nimport type { User } from './user.types';\n\nexport type DictionaryCreationData = {\n projectIds: (Project['_id'] | string)[];\n key: string;\n content?: DictionaryValue;\n title?: string;\n description?: string;\n version?: number;\n filePath?: string;\n};\n\nexport type DictionaryData = {\n projectIds: (Project['_id'] | string)[];\n key: string;\n content: DictionaryValue[];\n creatorId: User['_id'];\n title?: string;\n description?: string;\n version?: number;\n filePath?: Record<string, string>;\n};\n\nexport type Dictionary = DictionaryData & {\n _id: ObjectId;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type DictionaryAPI = Omit<Dictionary, 'filePath' | 'content'> & {\n content: DictionaryValue;\n filePath?: string;\n};\n\nexport type DictionaryDocument = Document<unknown, {}, Dictionary> & Dictionary;\nexport type DictionaryModelType = Model<Dictionary>;\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/types/organization.types.ts"],"sourcesContent":["import type { ObjectId, Document } from 'mongoose';\nimport type { User } from './user.types';\n\nexport type OrganizationCreationData = {\n name: Organization['name'];\n};\n\nexport type OrganizationData = {\n name: string;\n membersIds: User['_id'][];\n adminsIds: User['_id'][];\n};\n\nexport type Organization = OrganizationData & {\n _id: ObjectId;\n creatorId: User['_id'];\n createdAt: number;\n updatedAt: number;\n};\n\nexport type OrganizationAPI = Omit<OrganizationData, 'adminsIds'> & {\n adminsIds?: User['_id'][];\n};\n\nexport type OrganizationDocument = Document<Organization> & Organization;\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../../src/types/organization.types.ts"],"sourcesContent":["import type { ObjectId, Document } from 'mongoose';\nimport { Plan } from './plan.types';\nimport type { User } from './user.types';\n\nexport type OrganizationCreationData = {\n name: Organization['name'];\n};\n\nexport type OrganizationData = {\n name: string;\n membersIds: User['_id'][];\n adminsIds: User['_id'][];\n};\n\nexport type Organization = OrganizationData & {\n _id: ObjectId;\n creatorId: User['_id'];\n plan: Plan;\n createdAt: number;\n updatedAt: number;\n};\n\nexport type OrganizationAPI = Omit<Organization, 'adminsIds'> & {\n adminsIds?: User['_id'][];\n};\n\nexport type OrganizationDocument = Document<unknown, {}, Organization> &\n Organization;\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}