@intlayer/backend 3.1.0 → 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 (216) hide show
  1. package/dist/cjs/controllers/dictionary.controller.cjs +41 -0
  2. package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
  3. package/dist/cjs/controllers/organization.controller.cjs +73 -4
  4. package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
  5. package/dist/cjs/controllers/project.controller.cjs +71 -7
  6. package/dist/cjs/controllers/project.controller.cjs.map +1 -1
  7. package/dist/cjs/controllers/projectAccessKey.controller.cjs +31 -0
  8. package/dist/cjs/controllers/projectAccessKey.controller.cjs.map +1 -1
  9. package/dist/cjs/controllers/sessionAuth.controller.cjs +277 -57
  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 +40 -3
  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 +15 -5
  23. package/dist/cjs/index.cjs.map +1 -1
  24. package/dist/cjs/middlewares/sessionAuth.middleware.cjs +4 -6
  25. package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
  26. package/dist/cjs/routes/dictionary.routes.cjs +2 -62
  27. package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
  28. package/dist/cjs/routes/organization.routes.cjs +1 -25
  29. package/dist/cjs/routes/organization.routes.cjs.map +1 -1
  30. package/dist/cjs/routes/project.routes.cjs +10 -85
  31. package/dist/cjs/routes/project.routes.cjs.map +1 -1
  32. package/dist/cjs/routes/sessionAuth.routes.cjs +26 -25
  33. package/dist/cjs/routes/sessionAuth.routes.cjs.map +1 -1
  34. package/dist/cjs/{models/plan.moddel.cjs → routes/stripe.routes.cjs} +20 -9
  35. package/dist/cjs/routes/stripe.routes.cjs.map +1 -0
  36. package/dist/cjs/routes/user.routes.cjs +6 -27
  37. package/dist/cjs/routes/user.routes.cjs.map +1 -1
  38. package/dist/cjs/schemas/organization.schema.cjs +5 -0
  39. package/dist/cjs/schemas/organization.schema.cjs.map +1 -1
  40. package/dist/cjs/schemas/plans.schema.cjs +2 -8
  41. package/dist/cjs/schemas/plans.schema.cjs.map +1 -1
  42. package/dist/cjs/schemas/user.schema.cjs +1 -1
  43. package/dist/cjs/schemas/user.schema.cjs.map +1 -1
  44. package/dist/cjs/services/email.service.cjs +113 -43
  45. package/dist/cjs/services/email.service.cjs.map +1 -1
  46. package/dist/cjs/services/organization.service.cjs +55 -8
  47. package/dist/cjs/services/organization.service.cjs.map +1 -1
  48. package/dist/cjs/services/project.service.cjs +1 -3
  49. package/dist/cjs/services/project.service.cjs.map +1 -1
  50. package/dist/cjs/services/sessionAuth.service.cjs +9 -11
  51. package/dist/cjs/services/sessionAuth.service.cjs.map +1 -1
  52. package/dist/cjs/services/subscription.service.cjs +134 -51
  53. package/dist/cjs/services/subscription.service.cjs.map +1 -1
  54. package/dist/cjs/services/user.service.cjs +1 -3
  55. package/dist/cjs/services/user.service.cjs.map +1 -1
  56. package/dist/cjs/types/organization.types.cjs.map +1 -1
  57. package/dist/cjs/types/plan.types.cjs.map +1 -1
  58. package/dist/cjs/types/session.types.cjs.map +1 -1
  59. package/dist/cjs/utils/errors/ErrorHandler.cjs +29 -9
  60. package/dist/cjs/utils/errors/ErrorHandler.cjs.map +1 -1
  61. package/dist/cjs/utils/errors/ErrorsClass.cjs +17 -3
  62. package/dist/cjs/utils/errors/ErrorsClass.cjs.map +1 -1
  63. package/dist/cjs/utils/errors/errorCodes.cjs +99 -8
  64. package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
  65. package/dist/cjs/utils/mapper/project.cjs +1 -1
  66. package/dist/cjs/utils/mapper/project.cjs.map +1 -1
  67. package/dist/cjs/utils/plan.cjs +7 -2
  68. package/dist/cjs/utils/plan.cjs.map +1 -1
  69. package/dist/cjs/utils/responseData.cjs +8 -0
  70. package/dist/cjs/utils/responseData.cjs.map +1 -1
  71. package/dist/cjs/webhooks/stripe.webhook.cjs +133 -0
  72. package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -0
  73. package/dist/esm/controllers/dictionary.controller.mjs +41 -0
  74. package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
  75. package/dist/esm/controllers/organization.controller.mjs +73 -4
  76. package/dist/esm/controllers/organization.controller.mjs.map +1 -1
  77. package/dist/esm/controllers/project.controller.mjs +71 -7
  78. package/dist/esm/controllers/project.controller.mjs.map +1 -1
  79. package/dist/esm/controllers/projectAccessKey.controller.mjs +31 -0
  80. package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
  81. package/dist/esm/controllers/sessionAuth.controller.mjs +273 -56
  82. package/dist/esm/controllers/sessionAuth.controller.mjs.map +1 -1
  83. package/dist/esm/controllers/stripe.controller.mjs +60 -0
  84. package/dist/esm/controllers/stripe.controller.mjs.map +1 -0
  85. package/dist/esm/controllers/user.controller.mjs +40 -3
  86. package/dist/esm/controllers/user.controller.mjs.map +1 -1
  87. package/dist/esm/emails/SubscriptionPaymentCancellation.mjs +168 -0
  88. package/dist/esm/emails/SubscriptionPaymentCancellation.mjs.map +1 -0
  89. package/dist/esm/emails/SubscriptionPaymentError.mjs +168 -0
  90. package/dist/esm/emails/SubscriptionPaymentError.mjs.map +1 -0
  91. package/dist/esm/emails/SubscriptionPaymentSuccess.mjs +174 -0
  92. package/dist/esm/emails/SubscriptionPaymentSuccess.mjs.map +1 -0
  93. package/dist/esm/export.mjs.map +1 -1
  94. package/dist/esm/index.mjs +15 -5
  95. package/dist/esm/index.mjs.map +1 -1
  96. package/dist/esm/middlewares/sessionAuth.middleware.mjs +4 -6
  97. package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
  98. package/dist/esm/routes/dictionary.routes.mjs +2 -62
  99. package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
  100. package/dist/esm/routes/organization.routes.mjs +1 -25
  101. package/dist/esm/routes/organization.routes.mjs.map +1 -1
  102. package/dist/esm/routes/project.routes.mjs +10 -85
  103. package/dist/esm/routes/project.routes.mjs.map +1 -1
  104. package/dist/esm/routes/sessionAuth.routes.mjs +29 -26
  105. package/dist/esm/routes/sessionAuth.routes.mjs.map +1 -1
  106. package/dist/esm/routes/stripe.routes.mjs +17 -0
  107. package/dist/esm/routes/stripe.routes.mjs.map +1 -0
  108. package/dist/esm/routes/user.routes.mjs +6 -27
  109. package/dist/esm/routes/user.routes.mjs.map +1 -1
  110. package/dist/esm/schemas/organization.schema.mjs +5 -0
  111. package/dist/esm/schemas/organization.schema.mjs.map +1 -1
  112. package/dist/esm/schemas/plans.schema.mjs +2 -8
  113. package/dist/esm/schemas/plans.schema.mjs.map +1 -1
  114. package/dist/esm/schemas/user.schema.mjs +1 -1
  115. package/dist/esm/schemas/user.schema.mjs.map +1 -1
  116. package/dist/esm/services/email.service.mjs +125 -43
  117. package/dist/esm/services/email.service.mjs.map +1 -1
  118. package/dist/esm/services/organization.service.mjs +51 -7
  119. package/dist/esm/services/organization.service.mjs.map +1 -1
  120. package/dist/esm/services/project.service.mjs +1 -3
  121. package/dist/esm/services/project.service.mjs.map +1 -1
  122. package/dist/esm/services/sessionAuth.service.mjs +9 -10
  123. package/dist/esm/services/sessionAuth.service.mjs.map +1 -1
  124. package/dist/esm/services/subscription.service.mjs +136 -53
  125. package/dist/esm/services/subscription.service.mjs.map +1 -1
  126. package/dist/esm/services/user.service.mjs +1 -3
  127. package/dist/esm/services/user.service.mjs.map +1 -1
  128. package/dist/esm/utils/errors/ErrorHandler.mjs +29 -9
  129. package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
  130. package/dist/esm/utils/errors/ErrorsClass.mjs +17 -3
  131. package/dist/esm/utils/errors/ErrorsClass.mjs.map +1 -1
  132. package/dist/esm/utils/errors/errorCodes.mjs +99 -8
  133. package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
  134. package/dist/esm/utils/mapper/project.mjs +1 -1
  135. package/dist/esm/utils/mapper/project.mjs.map +1 -1
  136. package/dist/esm/utils/plan.mjs +7 -2
  137. package/dist/esm/utils/plan.mjs.map +1 -1
  138. package/dist/esm/utils/responseData.mjs +8 -0
  139. package/dist/esm/utils/responseData.mjs.map +1 -1
  140. package/dist/esm/webhooks/stripe.webhook.mjs +113 -0
  141. package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -0
  142. package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
  143. package/dist/types/controllers/organization.controller.d.ts.map +1 -1
  144. package/dist/types/controllers/project.controller.d.ts.map +1 -1
  145. package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
  146. package/dist/types/controllers/sessionAuth.controller.d.ts +24 -5
  147. package/dist/types/controllers/sessionAuth.controller.d.ts.map +1 -1
  148. package/dist/types/controllers/stripe.controller.d.ts +17 -0
  149. package/dist/types/controllers/stripe.controller.d.ts.map +1 -0
  150. package/dist/types/controllers/user.controller.d.ts.map +1 -1
  151. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +20 -0
  152. package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -0
  153. package/dist/types/emails/SubscriptionPaymentError.d.ts +20 -0
  154. package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -0
  155. package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +20 -0
  156. package/dist/types/emails/SubscriptionPaymentSuccess.d.ts.map +1 -0
  157. package/dist/types/export.d.ts +1 -0
  158. package/dist/types/export.d.ts.map +1 -1
  159. package/dist/types/index.d.ts.map +1 -1
  160. package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
  161. package/dist/types/models/organization.model.d.ts +1 -0
  162. package/dist/types/models/organization.model.d.ts.map +1 -1
  163. package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
  164. package/dist/types/routes/organization.routes.d.ts.map +1 -1
  165. package/dist/types/routes/project.routes.d.ts.map +1 -1
  166. package/dist/types/routes/sessionAuth.routes.d.ts +15 -2
  167. package/dist/types/routes/sessionAuth.routes.d.ts.map +1 -1
  168. package/dist/types/routes/stripe.routes.d.ts +10 -0
  169. package/dist/types/routes/stripe.routes.d.ts.map +1 -0
  170. package/dist/types/routes/user.routes.d.ts.map +1 -1
  171. package/dist/types/schemas/organization.schema.d.ts +1 -0
  172. package/dist/types/schemas/organization.schema.d.ts.map +1 -1
  173. package/dist/types/schemas/plans.schema.d.ts.map +1 -1
  174. package/dist/types/services/email.service.d.ts +33 -4
  175. package/dist/types/services/email.service.d.ts.map +1 -1
  176. package/dist/types/services/organization.service.d.ts +15 -0
  177. package/dist/types/services/organization.service.d.ts.map +1 -1
  178. package/dist/types/services/project.service.d.ts.map +1 -1
  179. package/dist/types/services/sessionAuth.service.d.ts +1 -8
  180. package/dist/types/services/sessionAuth.service.d.ts.map +1 -1
  181. package/dist/types/services/subscription.service.d.ts +20 -5
  182. package/dist/types/services/subscription.service.d.ts.map +1 -1
  183. package/dist/types/services/user.service.d.ts.map +1 -1
  184. package/dist/types/types/organization.types.d.ts +2 -0
  185. package/dist/types/types/organization.types.d.ts.map +1 -1
  186. package/dist/types/types/plan.types.d.ts +2 -3
  187. package/dist/types/types/plan.types.d.ts.map +1 -1
  188. package/dist/types/types/session.types.d.ts +6 -6
  189. package/dist/types/types/session.types.d.ts.map +1 -1
  190. package/dist/types/utils/errors/ErrorHandler.d.ts +5 -3
  191. package/dist/types/utils/errors/ErrorHandler.d.ts.map +1 -1
  192. package/dist/types/utils/errors/ErrorsClass.d.ts +4 -1
  193. package/dist/types/utils/errors/ErrorsClass.d.ts.map +1 -1
  194. package/dist/types/utils/errors/errorCodes.d.ts +92 -1
  195. package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
  196. package/dist/types/utils/mapper/project.d.ts +1 -1
  197. package/dist/types/utils/mapper/project.d.ts.map +1 -1
  198. package/dist/types/utils/plan.d.ts +1 -1
  199. package/dist/types/utils/plan.d.ts.map +1 -1
  200. package/dist/types/utils/responseData.d.ts +13 -2
  201. package/dist/types/utils/responseData.d.ts.map +1 -1
  202. package/dist/types/webhooks/stripe.d.ts.map +1 -1
  203. package/dist/types/webhooks/stripe.webhook.d.ts +3 -0
  204. package/dist/types/webhooks/stripe.webhook.d.ts.map +1 -0
  205. package/package.json +6 -5
  206. package/dist/cjs/models/plan.moddel.cjs.map +0 -1
  207. package/dist/cjs/services/plans.service.cjs +0 -72
  208. package/dist/cjs/services/plans.service.cjs.map +0 -1
  209. package/dist/cjs/webhooks/stripe.cjs +0 -94
  210. package/dist/cjs/webhooks/stripe.cjs.map +0 -1
  211. package/dist/esm/models/plan.moddel.mjs +0 -7
  212. package/dist/esm/models/plan.moddel.mjs.map +0 -1
  213. package/dist/esm/services/plans.service.mjs +0 -44
  214. package/dist/esm/services/plans.service.mjs.map +0 -1
  215. package/dist/esm/webhooks/stripe.mjs +0 -70
  216. package/dist/esm/webhooks/stripe.mjs.map +0 -1
@@ -0,0 +1,168 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Html,
4
+ Head,
5
+ Preview,
6
+ Tailwind,
7
+ Body,
8
+ Section,
9
+ Img,
10
+ Heading,
11
+ Container,
12
+ Button,
13
+ Text
14
+ } from "@react-email/components";
15
+ const SubscriptionPaymentErrorEN = ({
16
+ username,
17
+ planName,
18
+ errorDate,
19
+ retryPaymentLink
20
+ }) => {
21
+ const previewText = `There was an issue with your ${planName} subscription payment`;
22
+ return /* @__PURE__ */ jsxs(Html, { children: [
23
+ /* @__PURE__ */ jsx(Head, {}),
24
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
25
+ /* @__PURE__ */ jsx(Tailwind, { children: /* @__PURE__ */ jsx(Body, { className: "m-auto px-2 font-sans", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]", children: [
26
+ /* @__PURE__ */ jsx(Section, { className: "mt-[32px]", children: /* @__PURE__ */ jsx(
27
+ Img,
28
+ {
29
+ src: `https://intlayer.org/assets/favicon-32x32.png`,
30
+ width: "40",
31
+ height: "37",
32
+ alt: "Intlayer",
33
+ className: "mx-auto my-0"
34
+ }
35
+ ) }),
36
+ /* @__PURE__ */ jsx(Heading, { className: "mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black", children: "Payment Issue Detected" }),
37
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
38
+ "Hello ",
39
+ username,
40
+ ","
41
+ ] }),
42
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
43
+ "We encountered an issue processing your payment for the",
44
+ " ",
45
+ /* @__PURE__ */ jsx("strong", { children: planName }),
46
+ " plan on ",
47
+ /* @__PURE__ */ jsx("strong", { children: errorDate }),
48
+ ". Please update your payment information to ensure continued access to your subscription."
49
+ ] }),
50
+ /* @__PURE__ */ jsx(Section, { className: "my-[32px] text-center", children: /* @__PURE__ */ jsx(
51
+ Button,
52
+ {
53
+ className: "rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline",
54
+ href: retryPaymentLink,
55
+ children: "Retry Payment"
56
+ }
57
+ ) })
58
+ ] }) }) })
59
+ ] });
60
+ };
61
+ const SubscriptionPaymentErrorFR = ({
62
+ username,
63
+ planName,
64
+ errorDate,
65
+ retryPaymentLink
66
+ }) => {
67
+ const previewText = `Un probl\xE8me est survenu avec votre paiement pour l'abonnement ${planName}`;
68
+ return /* @__PURE__ */ jsxs(Html, { children: [
69
+ /* @__PURE__ */ jsx(Head, {}),
70
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
71
+ /* @__PURE__ */ jsx(Tailwind, { children: /* @__PURE__ */ jsx(Body, { className: "m-auto px-2 font-sans", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]", children: [
72
+ /* @__PURE__ */ jsx(Section, { className: "mt-[32px]", children: /* @__PURE__ */ jsx(
73
+ Img,
74
+ {
75
+ src: `https://intlayer.org/assets/favicon-32x32.png`,
76
+ width: "40",
77
+ height: "37",
78
+ alt: "Intlayer",
79
+ className: "mx-auto my-0"
80
+ }
81
+ ) }),
82
+ /* @__PURE__ */ jsx(Heading, { className: "mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black", children: "Probl\xE8me de Paiement" }),
83
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
84
+ "Bonjour ",
85
+ username,
86
+ ","
87
+ ] }),
88
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
89
+ "Nous avons rencontr\xE9 un probl\xE8me lors du traitement de votre paiement pour le plan ",
90
+ /* @__PURE__ */ jsx("strong", { children: planName }),
91
+ " le",
92
+ " ",
93
+ /* @__PURE__ */ jsx("strong", { children: errorDate }),
94
+ ". Veuillez mettre \xE0 jour vos informations de paiement pour garantir un acc\xE8s continu \xE0 votre abonnement."
95
+ ] }),
96
+ /* @__PURE__ */ jsx(Section, { className: "my-[32px] text-center", children: /* @__PURE__ */ jsx(
97
+ Button,
98
+ {
99
+ className: "rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline",
100
+ href: retryPaymentLink,
101
+ children: "R\xE9essayer le Paiement"
102
+ }
103
+ ) })
104
+ ] }) }) })
105
+ ] });
106
+ };
107
+ const SubscriptionPaymentErrorES = ({
108
+ username,
109
+ planName,
110
+ errorDate,
111
+ retryPaymentLink
112
+ }) => {
113
+ const previewText = `Hubo un problema con el pago de tu suscripci\xF3n ${planName}`;
114
+ return /* @__PURE__ */ jsxs(Html, { children: [
115
+ /* @__PURE__ */ jsx(Head, {}),
116
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
117
+ /* @__PURE__ */ jsx(Tailwind, { children: /* @__PURE__ */ jsx(Body, { className: "m-auto px-2 font-sans", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]", children: [
118
+ /* @__PURE__ */ jsx(Section, { className: "mt-[32px]", children: /* @__PURE__ */ jsx(
119
+ Img,
120
+ {
121
+ src: `https://intlayer.org/assets/favicon-32x32.png`,
122
+ width: "40",
123
+ height: "37",
124
+ alt: "Intlayer",
125
+ className: "mx-auto my-0"
126
+ }
127
+ ) }),
128
+ /* @__PURE__ */ jsx(Heading, { className: "mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black", children: "Problema de Pago" }),
129
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
130
+ "Hola ",
131
+ username,
132
+ ","
133
+ ] }),
134
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
135
+ "Hubo un problema al procesar tu pago para el plan",
136
+ " ",
137
+ /* @__PURE__ */ jsx("strong", { children: planName }),
138
+ " el ",
139
+ /* @__PURE__ */ jsx("strong", { children: errorDate }),
140
+ ". Por favor, actualiza tu informaci\xF3n de pago para garantizar el acceso continuo a tu suscripci\xF3n."
141
+ ] }),
142
+ /* @__PURE__ */ jsx(Section, { className: "my-[32px] text-center", children: /* @__PURE__ */ jsx(
143
+ Button,
144
+ {
145
+ className: "rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline",
146
+ href: retryPaymentLink,
147
+ children: "Reintentar el Pago"
148
+ }
149
+ ) })
150
+ ] }) }) })
151
+ ] });
152
+ };
153
+ const PreviewProps = {
154
+ username: "John Doe",
155
+ email: "john.doe@example.com",
156
+ planName: "Pro Plan",
157
+ errorDate: "November 18, 2024",
158
+ retryPaymentLink: "https://intlayer.org/retry-payment"
159
+ };
160
+ SubscriptionPaymentErrorEN.PreviewProps = PreviewProps;
161
+ SubscriptionPaymentErrorFR.PreviewProps = PreviewProps;
162
+ SubscriptionPaymentErrorES.PreviewProps = PreviewProps;
163
+ export {
164
+ SubscriptionPaymentErrorEN,
165
+ SubscriptionPaymentErrorES,
166
+ SubscriptionPaymentErrorFR
167
+ };
168
+ //# sourceMappingURL=SubscriptionPaymentError.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/emails/SubscriptionPaymentError.tsx"],"sourcesContent":["import {\n Html,\n Head,\n Preview,\n Tailwind,\n Body,\n Section,\n Img,\n Heading,\n Container,\n Button,\n Text,\n} from '@react-email/components';\n\nexport type SubscriptionPaymentErrorProps = {\n username: string; // The name of the user receiving the email\n email: string; // The email address of the user\n planName: string; // The name of the subscription plan\n errorDate: string; // The date the payment error occurred\n retryPaymentLink: string; // A link for the user to retry their payment\n};\n\n// Payment Error Email - English (EN)\nexport const SubscriptionPaymentErrorEN = ({\n username,\n planName,\n errorDate,\n retryPaymentLink,\n}: SubscriptionPaymentErrorProps) => {\n const previewText = `There was an issue with your ${planName} subscription payment`;\n\n return (\n <Html>\n <Head />\n <Preview>{previewText}</Preview>\n <Tailwind>\n <Body className=\"m-auto px-2 font-sans\">\n <Container className=\"mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]\">\n <Section className=\"mt-[32px]\">\n <Img\n src={`https://intlayer.org/assets/favicon-32x32.png`}\n width=\"40\"\n height=\"37\"\n alt=\"Intlayer\"\n className=\"mx-auto my-0\"\n />\n </Section>\n <Heading className=\"mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black\">\n Payment Issue Detected\n </Heading>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Hello {username},\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n We encountered an issue processing your payment for the{' '}\n <strong>{planName}</strong> plan on <strong>{errorDate}</strong>.\n Please update your payment information to ensure continued access\n to your subscription.\n </Text>\n <Section className=\"my-[32px] text-center\">\n <Button\n className=\"rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline\"\n href={retryPaymentLink}\n >\n Retry Payment\n </Button>\n </Section>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n};\n\n// Payment Error Email - French (FR)\nexport const SubscriptionPaymentErrorFR = ({\n username,\n planName,\n errorDate,\n retryPaymentLink,\n}: SubscriptionPaymentErrorProps) => {\n const previewText = `Un problème est survenu avec votre paiement pour l'abonnement ${planName}`;\n\n return (\n <Html>\n <Head />\n <Preview>{previewText}</Preview>\n <Tailwind>\n <Body className=\"m-auto px-2 font-sans\">\n <Container className=\"mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]\">\n <Section className=\"mt-[32px]\">\n <Img\n src={`https://intlayer.org/assets/favicon-32x32.png`}\n width=\"40\"\n height=\"37\"\n alt=\"Intlayer\"\n className=\"mx-auto my-0\"\n />\n </Section>\n <Heading className=\"mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black\">\n Problème de Paiement\n </Heading>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Bonjour {username},\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Nous avons rencontré un problème lors du traitement de votre\n paiement pour le plan <strong>{planName}</strong> le{' '}\n <strong>{errorDate}</strong>. Veuillez mettre à jour vos\n informations de paiement pour garantir un accès continu à votre\n abonnement.\n </Text>\n <Section className=\"my-[32px] text-center\">\n <Button\n className=\"rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline\"\n href={retryPaymentLink}\n >\n Réessayer le Paiement\n </Button>\n </Section>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n};\n\n// Payment Error Email - Spanish (ES)\nexport const SubscriptionPaymentErrorES = ({\n username,\n planName,\n errorDate,\n retryPaymentLink,\n}: SubscriptionPaymentErrorProps) => {\n const previewText = `Hubo un problema con el pago de tu suscripción ${planName}`;\n\n return (\n <Html>\n <Head />\n <Preview>{previewText}</Preview>\n <Tailwind>\n <Body className=\"m-auto px-2 font-sans\">\n <Container className=\"mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]\">\n <Section className=\"mt-[32px]\">\n <Img\n src={`https://intlayer.org/assets/favicon-32x32.png`}\n width=\"40\"\n height=\"37\"\n alt=\"Intlayer\"\n className=\"mx-auto my-0\"\n />\n </Section>\n <Heading className=\"mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black\">\n Problema de Pago\n </Heading>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Hola {username},\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Hubo un problema al procesar tu pago para el plan{' '}\n <strong>{planName}</strong> el <strong>{errorDate}</strong>. Por\n favor, actualiza tu información de pago para garantizar el acceso\n continuo a tu suscripción.\n </Text>\n <Section className=\"my-[32px] text-center\">\n <Button\n className=\"rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline\"\n href={retryPaymentLink}\n >\n Reintentar el Pago\n </Button>\n </Section>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n};\n\n// Preview Props Example\nconst PreviewProps: SubscriptionPaymentErrorProps = {\n username: 'John Doe',\n email: 'john.doe@example.com',\n planName: 'Pro Plan',\n errorDate: 'November 18, 2024',\n retryPaymentLink: 'https://intlayer.org/retry-payment',\n};\n\nSubscriptionPaymentErrorEN.PreviewProps = PreviewProps;\nSubscriptionPaymentErrorFR.PreviewProps = PreviewProps;\nSubscriptionPaymentErrorES.PreviewProps = PreviewProps;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,174 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Html,
4
+ Head,
5
+ Preview,
6
+ Tailwind,
7
+ Body,
8
+ Section,
9
+ Img,
10
+ Heading,
11
+ Container,
12
+ Button,
13
+ Text
14
+ } from "@react-email/components";
15
+ const SubscriptionPaymentSuccessEN = ({
16
+ username,
17
+ planName,
18
+ subscriptionStartDate,
19
+ manageSubscriptionLink
20
+ }) => {
21
+ const previewText = `Your payment for ${planName} subscription is confirmed`;
22
+ return /* @__PURE__ */ jsxs(Html, { children: [
23
+ /* @__PURE__ */ jsx(Head, {}),
24
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
25
+ /* @__PURE__ */ jsx(Tailwind, { children: /* @__PURE__ */ jsx(Body, { className: "m-auto px-2 font-sans", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]", children: [
26
+ /* @__PURE__ */ jsx(Section, { className: "mt-[32px]", children: /* @__PURE__ */ jsx(
27
+ Img,
28
+ {
29
+ src: `https://intlayer.org/assets/favicon-32x32.png`,
30
+ width: "40",
31
+ height: "37",
32
+ alt: "Intlayer",
33
+ className: "mx-auto my-0"
34
+ }
35
+ ) }),
36
+ /* @__PURE__ */ jsx(Heading, { className: "mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black", children: "Payment Confirmed" }),
37
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
38
+ "Hello ",
39
+ username,
40
+ ","
41
+ ] }),
42
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
43
+ "Thank you for your payment! Your subscription to the",
44
+ " ",
45
+ /* @__PURE__ */ jsx("strong", { children: planName }),
46
+ " plan is now active."
47
+ ] }),
48
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
49
+ "Start Date: ",
50
+ /* @__PURE__ */ jsx("strong", { children: subscriptionStartDate })
51
+ ] }),
52
+ /* @__PURE__ */ jsx(Section, { className: "my-[32px] text-center", children: /* @__PURE__ */ jsx(
53
+ Button,
54
+ {
55
+ className: "rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline",
56
+ href: manageSubscriptionLink,
57
+ children: "Manage Your Subscription"
58
+ }
59
+ ) })
60
+ ] }) }) })
61
+ ] });
62
+ };
63
+ const SubscriptionPaymentSuccessFR = ({
64
+ username,
65
+ planName,
66
+ subscriptionStartDate,
67
+ manageSubscriptionLink
68
+ }) => {
69
+ const previewText = `Votre paiement pour l'abonnement ${planName} est confirm\xE9`;
70
+ return /* @__PURE__ */ jsxs(Html, { children: [
71
+ /* @__PURE__ */ jsx(Head, {}),
72
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
73
+ /* @__PURE__ */ jsx(Tailwind, { children: /* @__PURE__ */ jsx(Body, { className: "m-auto px-2 font-sans", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]", children: [
74
+ /* @__PURE__ */ jsx(Section, { className: "mt-[32px]", children: /* @__PURE__ */ jsx(
75
+ Img,
76
+ {
77
+ src: `https://intlayer.org/assets/favicon-32x32.png`,
78
+ width: "40",
79
+ height: "37",
80
+ alt: "Intlayer",
81
+ className: "mx-auto my-0"
82
+ }
83
+ ) }),
84
+ /* @__PURE__ */ jsx(Heading, { className: "mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black", children: "Paiement Confirm\xE9" }),
85
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
86
+ "Bonjour ",
87
+ username,
88
+ ","
89
+ ] }),
90
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
91
+ "Merci pour votre paiement ! Votre abonnement au plan",
92
+ " ",
93
+ /* @__PURE__ */ jsx("strong", { children: planName }),
94
+ " est maintenant actif."
95
+ ] }),
96
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
97
+ "Date de d\xE9but : ",
98
+ /* @__PURE__ */ jsx("strong", { children: subscriptionStartDate })
99
+ ] }),
100
+ /* @__PURE__ */ jsx(Section, { className: "my-[32px] text-center", children: /* @__PURE__ */ jsx(
101
+ Button,
102
+ {
103
+ className: "rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline",
104
+ href: manageSubscriptionLink,
105
+ children: "G\xE9rer votre abonnement"
106
+ }
107
+ ) })
108
+ ] }) }) })
109
+ ] });
110
+ };
111
+ const SubscriptionPaymentSuccessES = ({
112
+ username,
113
+ planName,
114
+ subscriptionStartDate,
115
+ manageSubscriptionLink
116
+ }) => {
117
+ const previewText = `Tu pago por la suscripci\xF3n ${planName} ha sido confirmado`;
118
+ return /* @__PURE__ */ jsxs(Html, { children: [
119
+ /* @__PURE__ */ jsx(Head, {}),
120
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
121
+ /* @__PURE__ */ jsx(Tailwind, { children: /* @__PURE__ */ jsx(Body, { className: "m-auto px-2 font-sans", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]", children: [
122
+ /* @__PURE__ */ jsx(Section, { className: "mt-[32px]", children: /* @__PURE__ */ jsx(
123
+ Img,
124
+ {
125
+ src: `https://intlayer.org/assets/favicon-32x32.png`,
126
+ width: "40",
127
+ height: "37",
128
+ alt: "Intlayer",
129
+ className: "mx-auto my-0"
130
+ }
131
+ ) }),
132
+ /* @__PURE__ */ jsx(Heading, { className: "mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black", children: "Pago Confirmado" }),
133
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
134
+ "Hola ",
135
+ username,
136
+ ","
137
+ ] }),
138
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
139
+ "\xA1Gracias por tu pago! Tu suscripci\xF3n al plan",
140
+ " ",
141
+ /* @__PURE__ */ jsx("strong", { children: planName }),
142
+ " ya est\xE1 activa."
143
+ ] }),
144
+ /* @__PURE__ */ jsxs(Text, { className: "text-[14px] leading-[24px] text-black", children: [
145
+ "Fecha de inicio: ",
146
+ /* @__PURE__ */ jsx("strong", { children: subscriptionStartDate })
147
+ ] }),
148
+ /* @__PURE__ */ jsx(Section, { className: "my-[32px] text-center", children: /* @__PURE__ */ jsx(
149
+ Button,
150
+ {
151
+ className: "rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline",
152
+ href: manageSubscriptionLink,
153
+ children: "Gestionar tu suscripci\xF3n"
154
+ }
155
+ ) })
156
+ ] }) }) })
157
+ ] });
158
+ };
159
+ const PreviewProps = {
160
+ username: "John Doe",
161
+ email: "john.doe@example.com",
162
+ planName: "Pro Plan",
163
+ subscriptionStartDate: "November 20, 2024",
164
+ manageSubscriptionLink: "https://intlayer.org/manage-subscription"
165
+ };
166
+ SubscriptionPaymentSuccessEN.PreviewProps = PreviewProps;
167
+ SubscriptionPaymentSuccessFR.PreviewProps = PreviewProps;
168
+ SubscriptionPaymentSuccessES.PreviewProps = PreviewProps;
169
+ export {
170
+ SubscriptionPaymentSuccessEN,
171
+ SubscriptionPaymentSuccessES,
172
+ SubscriptionPaymentSuccessFR
173
+ };
174
+ //# sourceMappingURL=SubscriptionPaymentSuccess.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/emails/SubscriptionPaymentSuccess.tsx"],"sourcesContent":["import {\n Html,\n Head,\n Preview,\n Tailwind,\n Body,\n Section,\n Img,\n Heading,\n Container,\n Button,\n Text,\n} from '@react-email/components';\n\nexport type SubscriptionPaymentSuccessProps = {\n username: string; // The name of the user receiving the email\n email: string; // The email address of the user\n planName: string; // The name of the subscription plan\n subscriptionStartDate: string; // The start date of the subscription\n manageSubscriptionLink: string; // A link for the user to manage their subscription\n};\n\nexport const SubscriptionPaymentSuccessEN = ({\n username,\n planName,\n subscriptionStartDate,\n manageSubscriptionLink,\n}: SubscriptionPaymentSuccessProps) => {\n const previewText = `Your payment for ${planName} subscription is confirmed`;\n\n return (\n <Html>\n <Head />\n <Preview>{previewText}</Preview>\n <Tailwind>\n <Body className=\"m-auto px-2 font-sans\">\n <Container className=\"mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]\">\n <Section className=\"mt-[32px]\">\n <Img\n src={`https://intlayer.org/assets/favicon-32x32.png`}\n width=\"40\"\n height=\"37\"\n alt=\"Intlayer\"\n className=\"mx-auto my-0\"\n />\n </Section>\n <Heading className=\"mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black\">\n Payment Confirmed\n </Heading>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Hello {username},\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Thank you for your payment! Your subscription to the{' '}\n <strong>{planName}</strong> plan is now active.\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Start Date: <strong>{subscriptionStartDate}</strong>\n </Text>\n <Section className=\"my-[32px] text-center\">\n <Button\n className=\"rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline\"\n href={manageSubscriptionLink}\n >\n Manage Your Subscription\n </Button>\n </Section>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n};\n\nexport const SubscriptionPaymentSuccessFR = ({\n username,\n planName,\n subscriptionStartDate,\n manageSubscriptionLink,\n}: SubscriptionPaymentSuccessProps) => {\n const previewText = `Votre paiement pour l'abonnement ${planName} est confirmé`;\n\n return (\n <Html>\n <Head />\n <Preview>{previewText}</Preview>\n <Tailwind>\n <Body className=\"m-auto px-2 font-sans\">\n <Container className=\"mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]\">\n <Section className=\"mt-[32px]\">\n <Img\n src={`https://intlayer.org/assets/favicon-32x32.png`}\n width=\"40\"\n height=\"37\"\n alt=\"Intlayer\"\n className=\"mx-auto my-0\"\n />\n </Section>\n <Heading className=\"mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black\">\n Paiement Confirmé\n </Heading>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Bonjour {username},\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Merci pour votre paiement ! Votre abonnement au plan{' '}\n <strong>{planName}</strong> est maintenant actif.\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Date de début : <strong>{subscriptionStartDate}</strong>\n </Text>\n <Section className=\"my-[32px] text-center\">\n <Button\n className=\"rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline\"\n href={manageSubscriptionLink}\n >\n Gérer votre abonnement\n </Button>\n </Section>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n};\n\nexport const SubscriptionPaymentSuccessES = ({\n username,\n planName,\n subscriptionStartDate,\n manageSubscriptionLink,\n}: SubscriptionPaymentSuccessProps) => {\n const previewText = `Tu pago por la suscripción ${planName} ha sido confirmado`;\n\n return (\n <Html>\n <Head />\n <Preview>{previewText}</Preview>\n <Tailwind>\n <Body className=\"m-auto px-2 font-sans\">\n <Container className=\"mx-auto my-[40px] max-w-[465px] rounded-xl border border-solid border-[#eaeaea] bg-white p-[20px]\">\n <Section className=\"mt-[32px]\">\n <Img\n src={`https://intlayer.org/assets/favicon-32x32.png`}\n width=\"40\"\n height=\"37\"\n alt=\"Intlayer\"\n className=\"mx-auto my-0\"\n />\n </Section>\n <Heading className=\"mx-0 my-[30px] p-0 text-center text-[24px] font-normal text-black\">\n Pago Confirmado\n </Heading>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Hola {username},\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n ¡Gracias por tu pago! Tu suscripción al plan{' '}\n <strong>{planName}</strong> ya está activa.\n </Text>\n <Text className=\"text-[14px] leading-[24px] text-black\">\n Fecha de inicio: <strong>{subscriptionStartDate}</strong>\n </Text>\n <Section className=\"my-[32px] text-center\">\n <Button\n className=\"rounded-md bg-[#000000] px-5 py-3 text-center text-[12px] font-semibold text-white no-underline\"\n href={manageSubscriptionLink}\n >\n Gestionar tu suscripción\n </Button>\n </Section>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n};\n\nconst PreviewProps: SubscriptionPaymentSuccessProps = {\n username: 'John Doe',\n email: 'john.doe@example.com',\n planName: 'Pro Plan',\n subscriptionStartDate: 'November 20, 2024',\n manageSubscriptionLink: 'https://intlayer.org/manage-subscription',\n};\n\nSubscriptionPaymentSuccessEN.PreviewProps = PreviewProps;\nSubscriptionPaymentSuccessFR.PreviewProps = PreviewProps;\nSubscriptionPaymentSuccessES.PreviewProps = PreviewProps;\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/export.ts"],"sourcesContent":["// Routes\nexport { userRoutes } from '@routes/user.routes';\nexport { organizationRoutes } from '@routes/organization.routes';\nexport { projectRoutes } from '@routes/project.routes';\nexport { dictionaryRoutes } from '@routes/dictionary.routes';\nexport { sessionAuthRoutes } from '@routes/sessionAuth.routes';\n\n// Controllers types\nexport type * from '@controllers/sessionAuth.controller';\nexport type * from '@controllers/oAuth2.controller';\nexport type * from '@controllers/organization.controller';\nexport type * from '@controllers/project.controller';\nexport type * from '@controllers/projectAccessKey.controller';\nexport type * from '@controllers/user.controller';\nexport type * from '@controllers/dictionary.controller';\n\n// Objects types\nexport type * from '@/types/organization.types';\nexport type * from '@/types/project.types';\nexport type * from '@/types/user.types';\nexport type * from '@/types/dictionary.types';\nexport type * from '@/types/plan.types';\n\n// Utils\nexport * from '@utils/cookies';\nexport * from '@utils/httpStatusCodes';\n"],"mappings":"AACA,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAmBlC,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../src/export.ts"],"sourcesContent":["// Routes\nexport { userRoutes } from '@routes/user.routes';\nexport { organizationRoutes } from '@routes/organization.routes';\nexport { projectRoutes } from '@routes/project.routes';\nexport { dictionaryRoutes } from '@routes/dictionary.routes';\nexport { sessionAuthRoutes } from '@routes/sessionAuth.routes';\n\n// Controllers types\nexport type * from '@controllers/sessionAuth.controller';\nexport type * from '@controllers/oAuth2.controller';\nexport type * from '@controllers/organization.controller';\nexport type * from '@controllers/project.controller';\nexport type * from '@controllers/projectAccessKey.controller';\nexport type * from '@controllers/user.controller';\nexport type * from '@controllers/dictionary.controller';\nexport type * from '@controllers/stripe.controller';\n\n// Objects types\nexport type * from '@/types/organization.types';\nexport type * from '@/types/project.types';\nexport type * from '@/types/user.types';\nexport type * from '@/types/dictionary.types';\nexport type * from '@/types/plan.types';\n\n// Utils\nexport * from '@utils/cookies';\nexport * from '@utils/httpStatusCodes';\n"],"mappings":"AACA,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAoBlC,cAAc;AACd,cAAc;","names":[]}
@@ -4,6 +4,7 @@ import cors from "cors";
4
4
  import dotenv from "dotenv";
5
5
  import express, { raw } from "express";
6
6
  import { intlayer, t } from "express-intlayer";
7
+ import helmet from "helmet";
7
8
  import {
8
9
  attachOAuthInstance,
9
10
  authenticateOAuth2
@@ -20,7 +21,8 @@ import { organizationRouter } from './routes/organization.routes.mjs';
20
21
  import { projectRouter } from './routes/project.routes.mjs';
21
22
  import { sessionAuthRouter } from './routes/sessionAuth.routes.mjs';
22
23
  import { userRouter } from './routes/user.routes.mjs';
23
- import { stripeWebhook } from './webhooks/stripe.mjs';
24
+ import { stripeRouter } from './routes/stripe.routes.mjs';
25
+ import { stripeWebhook } from './webhooks/stripe.webhook.mjs';
24
26
  import { getOAuth2Token } from './controllers/oAuth2.controller.mjs';
25
27
  import {
26
28
  getSessionInformation,
@@ -31,21 +33,29 @@ import { connectDB } from './utils/mongoDB/connectDB.mjs';
31
33
  import { logger } from './logger/index.mjs';
32
34
  const app = express();
33
35
  app.disable("x-powered-by");
36
+ app.use(helmet());
34
37
  const env = app.get("env");
35
38
  logger.info(`run as ${env}`);
36
39
  dotenv.config({ path: [".env", `.env.${env}`] });
40
+ app.use(cookieParser());
41
+ app.use(intlayer());
37
42
  const isDev = env === "development";
38
43
  connectDB();
44
+ app.post("/webhook/stripe", raw({ type: "application/json" }), stripeWebhook);
39
45
  app.use(compression());
40
46
  app.use(express.json({ limit: "50mb" }));
41
47
  app.use(express.urlencoded({ extended: true }));
42
- app.use(cookieParser());
43
- app.use(intlayer());
44
48
  const whitelist = [process.env.CLIENT_URL];
45
49
  const corsOptions = {
46
50
  origin: whitelist,
47
51
  credentials: true,
48
- allowedHeaders: ["authorization", "Content-Type", "credentials"],
52
+ allowedHeaders: [
53
+ "authorization",
54
+ "Content-Type",
55
+ "credentials",
56
+ "cache-control",
57
+ "Access-Control-Allow-Origin"
58
+ ],
49
59
  exposedHeaders: [""],
50
60
  preflightContinue: false,
51
61
  methods: "GET,HEAD,PUT,PATCH,POST,DELETE"
@@ -65,7 +75,6 @@ app.use(/(.*)/, checkUser);
65
75
  app.use(/(.*)/, checkOrganization);
66
76
  app.use(/(.*)/, checkProject);
67
77
  app.use(/(.*)/, checkAdmin);
68
- app.post("/webhook/stripe", raw({ type: "application/json" }), stripeWebhook);
69
78
  if (isDev) {
70
79
  app.use(logAPIRequestURL);
71
80
  }
@@ -94,6 +103,7 @@ app.use("/api/user", userRouter);
94
103
  app.use("/api/organization", organizationRouter);
95
104
  app.use("/api/project", projectRouter);
96
105
  app.use("/api/dictionary", dictionaryRouter);
106
+ app.use("/api/stripe", stripeRouter);
97
107
  app.listen(process.env.PORT, () => {
98
108
  logger.info(`Listening on port ${process.env.PORT}`);
99
109
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["/* eslint-disable import/order */\n\n// Libraries\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport cors, { type CorsOptions } from 'cors';\nimport dotenv from 'dotenv';\nimport express, { raw, type Express } from 'express';\nimport { intlayer, t } from 'express-intlayer';\n\n// Middlewares\nimport {\n attachOAuthInstance,\n authenticateOAuth2,\n RequestWithOAuth2Information,\n} from '@middlewares/oAuth2.middleware';\nimport { logAPIRequestURL } from '@middlewares/request.middleware';\nimport {\n checkUser,\n checkOrganization,\n checkProject,\n checkAdmin,\n ResponseWithInformation,\n} from '@middlewares/sessionAuth.middleware';\n\n// Routes\nimport { dictionaryRouter } from '@routes/dictionary.routes';\nimport { organizationRouter } from '@routes/organization.routes';\nimport { projectRouter } from '@routes/project.routes';\nimport { sessionAuthRouter } from '@routes/sessionAuth.routes';\nimport { userRouter } from '@routes/user.routes';\n\n// Webhooks\nimport { stripeWebhook } from '@webhooks/stripe';\n\n// Controllers\nimport { getOAuth2Token } from '@controllers/oAuth2.controller';\nimport {\n getSessionInformation,\n setCSRFToken,\n} from '@controllers/sessionAuth.controller';\n\n// Utils\nimport { doubleCsrfProtection } from '@utils/CSRF';\nimport { connectDB } from '@utils/mongoDB/connectDB';\n\n// Logger\nimport { logger } from './logger';\n\nconst app: Express = express();\n\napp.disable('x-powered-by'); // Disabled to prevent attackers from knowing that the app is running Express\n\n// Environment variables\nconst env = app.get('env');\n\nlogger.info(`run as ${env}`);\n\ndotenv.config({ path: ['.env', `.env.${env}`] });\n\nconst isDev = env === 'development';\n\nconnectDB();\n\n// Compress all HTTP responses\napp.use(compression());\n\n// Parse incoming requests with JSON payloads\napp.use(express.json({ limit: '50mb' }));\n\n// Parse incoming requests with urlencoded payloads\napp.use(express.urlencoded({ extended: true }));\n\n// Parse incoming requests with cookies\napp.use(cookieParser());\n\n// Load internationalization request handler\napp.use(intlayer());\n\n// CORS\nconst whitelist: string[] = [process.env.CLIENT_URL!];\nconst corsOptions: CorsOptions = {\n origin: whitelist,\n credentials: true,\n allowedHeaders: ['authorization', 'Content-Type', 'credentials'],\n exposedHeaders: [''],\n preflightContinue: false,\n methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',\n};\napp.use(cors(corsOptions));\nlogger.info('url whitelist : ', whitelist.join(', '));\n\n// Liveness check\napp.get('/', (_req, res) => {\n res.send(\n t({\n en: 'Ok - locale: en',\n fr: 'Ok - locale: fr',\n es: 'Ok - locale: es',\n })\n );\n});\n\n// middleware - jwt & session auth\napp.use(/(.*)/, checkUser);\napp.use(/(.*)/, checkOrganization);\napp.use(/(.*)/, checkProject);\napp.use(/(.*)/, checkAdmin);\n\n// Stripe webhook\napp.post('/webhook/stripe', raw({ type: 'application/json' }), stripeWebhook);\n\n// debug\nif (isDev) {\n app.use(logAPIRequestURL);\n}\n\n// Sessions\napp.get('/session', getSessionInformation);\napp.use('/api/auth', sessionAuthRouter);\n\n// CSRF\napp.get('/csrf-token', setCSRFToken);\n\n// oAuth2\napp.use(/(.*)/, attachOAuthInstance);\napp.post('/oauth2/token', getOAuth2Token); // Route to get the token\napp.use(/(.*)/, (req, res, next) => {\n // If the request is not already authenticated check the oAuth2 token\n if (!res.locals.authType) {\n return authenticateOAuth2(\n req as RequestWithOAuth2Information,\n res as ResponseWithInformation,\n next\n );\n }\n next();\n});\n\n// CSRF protection\napp.use(/(.*)/, (req, res, next) => {\n // If the request is authenticated using the session auth check the CSRF token\n if (res.locals.authType === 'session') {\n return doubleCsrfProtection(req, res, next);\n }\n next();\n});\n\n// Routes\napp.use('/api/user', userRouter);\napp.use('/api/organization', organizationRouter);\napp.use('/api/project', projectRouter);\napp.use('/api/dictionary', dictionaryRouter);\n\n// Server\napp.listen(process.env.PORT, () => {\n logger.info(`Listening on port ${process.env.PORT}`);\n});\n\n// Export tu use as serverless function\nexport default app;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["/* eslint-disable import/order */\n\n// Libraries\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport cors, { type CorsOptions } from 'cors';\nimport dotenv from 'dotenv';\nimport express, { raw, type Express } from 'express';\nimport { intlayer, t } from 'express-intlayer';\nimport helmet from 'helmet';\n\n// Middlewares\nimport {\n attachOAuthInstance,\n authenticateOAuth2,\n RequestWithOAuth2Information,\n} from '@middlewares/oAuth2.middleware';\nimport { logAPIRequestURL } from '@middlewares/request.middleware';\nimport {\n checkUser,\n checkOrganization,\n checkProject,\n checkAdmin,\n ResponseWithInformation,\n} from '@middlewares/sessionAuth.middleware';\n\n// Routes\nimport { dictionaryRouter } from '@routes/dictionary.routes';\nimport { organizationRouter } from '@routes/organization.routes';\nimport { projectRouter } from '@routes/project.routes';\nimport { sessionAuthRouter } from '@routes/sessionAuth.routes';\nimport { userRouter } from '@routes/user.routes';\nimport { stripeRouter } from '@routes/stripe.routes';\n\n// Webhooks\nimport { stripeWebhook } from '@webhooks/stripe.webhook';\n\n// Controllers\nimport { getOAuth2Token } from '@controllers/oAuth2.controller';\nimport {\n getSessionInformation,\n setCSRFToken,\n} from '@controllers/sessionAuth.controller';\n\n// Utils\nimport { doubleCsrfProtection } from '@utils/CSRF';\nimport { connectDB } from '@utils/mongoDB/connectDB';\n\n// Logger\nimport { logger } from './logger';\n\nconst app: Express = express();\n\napp.disable('x-powered-by'); // Disabled to prevent attackers from knowing that the app is running Express\napp.use(helmet());\n\n// Environment variables\nconst env = app.get('env');\n\nlogger.info(`run as ${env}`);\n\ndotenv.config({ path: ['.env', `.env.${env}`] });\n\n// Parse incoming requests with cookies\napp.use(cookieParser());\n\n// Load internationalization request handler\napp.use(intlayer());\n\nconst isDev = env === 'development';\n\n// Connect to MongoDB\nconnectDB();\n\n// Stripe\napp.post('/webhook/stripe', raw({ type: 'application/json' }), stripeWebhook);\n\n// Compress all HTTP responses\napp.use(compression());\n\n// Parse incoming requests with JSON payloads\napp.use(express.json({ limit: '50mb' }));\n\n// Parse incoming requests with urlencoded payloads\napp.use(express.urlencoded({ extended: true }));\n\n// CORS\nconst whitelist: string[] = [process.env.CLIENT_URL!];\nconst corsOptions: CorsOptions = {\n origin: whitelist,\n credentials: true,\n allowedHeaders: [\n 'authorization',\n 'Content-Type',\n 'credentials',\n 'cache-control',\n 'Access-Control-Allow-Origin',\n ],\n exposedHeaders: [''],\n preflightContinue: false,\n methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',\n};\napp.use(cors(corsOptions));\nlogger.info('url whitelist : ', whitelist.join(', '));\n\n// Liveness check\napp.get('/', (_req, res) => {\n res.send(\n t({\n en: 'Ok - locale: en',\n fr: 'Ok - locale: fr',\n es: 'Ok - locale: es',\n })\n );\n});\n\n// middleware - jwt & session auth\napp.use(/(.*)/, checkUser);\napp.use(/(.*)/, checkOrganization);\napp.use(/(.*)/, checkProject);\napp.use(/(.*)/, checkAdmin);\n\n// debug\nif (isDev) {\n app.use(logAPIRequestURL);\n}\n\n// Sessions\napp.get('/session', getSessionInformation);\napp.use('/api/auth', sessionAuthRouter);\n\n// CSRF\napp.get('/csrf-token', setCSRFToken);\n\n// oAuth2\napp.use(/(.*)/, attachOAuthInstance);\napp.post('/oauth2/token', getOAuth2Token); // Route to get the token\napp.use(/(.*)/, (req, res, next) => {\n // If the request is not already authenticated check the oAuth2 token\n if (!res.locals.authType) {\n return authenticateOAuth2(\n req as RequestWithOAuth2Information,\n res as ResponseWithInformation,\n next\n );\n }\n next();\n});\n\n// CSRF protection\napp.use(/(.*)/, (req, res, next) => {\n // If the request is authenticated using the session auth check the CSRF token\n if (res.locals.authType === 'session') {\n return doubleCsrfProtection(req, res, next);\n }\n next();\n});\n\n// Routes\napp.use('/api/user', userRouter);\napp.use('/api/organization', organizationRouter);\napp.use('/api/project', projectRouter);\napp.use('/api/dictionary', dictionaryRouter);\napp.use('/api/stripe', stripeRouter);\n\n// Server\napp.listen(process.env.PORT, () => {\n logger.info(`Listening on port ${process.env.PORT}`);\n});\n\n// Export tu use as serverless function\nexport default app;\n"],"mappings":"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","names":[]}
@@ -13,9 +13,7 @@ const checkUser = async (req, res, next) => {
13
13
  res.locals.authType = null;
14
14
  try {
15
15
  if (sessionToken) {
16
- const user = await getUserBySessionService(
17
- sessionToken
18
- );
16
+ const user = await getUserBySessionService(sessionToken);
19
17
  if (user) {
20
18
  res.locals.user = user.toObject();
21
19
  res.locals.authType = "session";
@@ -88,17 +86,17 @@ const checkAdmin = async (_req, res, next) => {
88
86
  return next();
89
87
  }
90
88
  res.locals.organizationRights = {
91
- read: false,
89
+ read: true,
92
90
  write: false,
93
91
  admin: false
94
92
  };
95
93
  res.locals.projectRights = {
96
- read: false,
94
+ read: true,
97
95
  write: false,
98
96
  admin: false
99
97
  };
100
98
  res.locals.projectRights = {
101
- read: false,
99
+ read: true,
102
100
  write: false,
103
101
  admin: false
104
102
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/middlewares/sessionAuth.middleware.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { OrganizationModel } from '@models/organization.model';\nimport { ProjectModel } from '@models/project.model';\nimport {\n clearOrganizationAuth,\n clearProjectAuth,\n} from '@services/sessionAuth.service';\nimport { getUserBySession as getUserBySessionService } from '@services/user.service';\nimport { Cookies } from '@utils/cookies';\nimport type { Request, Response, NextFunction } from 'express';\nimport jwt from 'jsonwebtoken';\nimport type {\n Organization,\n OrganizationDocument,\n} from '@/types/organization.types';\nimport type { Project, ProjectDocument, Rights } from '@/types/project.types';\nimport type { User, UserDocument } from '@/types/user.types';\n\nexport type ResponseWithInformation<ResBody = any> = Response<\n ResBody,\n {\n user: User | null;\n // Auth Context\n organization: Organization | null;\n project: Project | null;\n authType: 'session' | 'oauth2' | null;\n // Auth Rights - oAuth2 Auth\n organizationRights: Rights | null;\n projectRights: Rights | null;\n dictionaryRights: Rights | null;\n // Auth Rights - Session Auth\n isOrganizationAdmin: boolean | null;\n isProjectAdmin: boolean | null;\n }\n>;\n\nexport const checkUser = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { [Cookies.JWT_AUTH]: sessionToken } = req.cookies;\n\n res.locals.user = null;\n res.locals.authType = null;\n\n try {\n if (sessionToken) {\n const user: UserDocument | null = (await getUserBySessionService(\n sessionToken\n )) as UserDocument | null;\n\n if (user) {\n res.locals.user = user.toObject();\n res.locals.authType = 'session';\n }\n }\n } catch (error) {\n console.error('Error fetching session:', error);\n }\n\n return next();\n};\n\nexport const checkOrganization = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenOrganization = req.cookies[Cookies.JWT_ORGANIZATION];\n\n res.locals.organization = null;\n\n try {\n if (!jwtTokenOrganization || jwtTokenOrganization === 'undefined') {\n clearOrganizationAuth(res);\n return next();\n }\n\n const organizationData = jwt.verify(\n jwtTokenOrganization,\n process.env.JWT_TOKEN_SECRET!\n ) as Organization;\n\n if (!organizationData) {\n clearOrganizationAuth(res);\n return next();\n }\n\n const organization: OrganizationDocument | null =\n await OrganizationModel.findById(organizationData._id);\n\n if (!organization) {\n clearOrganizationAuth(res);\n return next();\n }\n\n res.locals.organization = organization.toObject();\n } catch (error) {\n console.error('Error fetching organization:', error);\n }\n\n return next();\n};\n\nexport const checkProject = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenProject = req.cookies[Cookies.JWT_PROJECT];\n res.locals.project = null;\n\n try {\n if (!jwtTokenProject || jwtTokenProject === 'undefined') {\n clearProjectAuth(res);\n return next();\n }\n\n const decodedTokenProject = jwt.verify(\n jwtTokenProject,\n process.env.JWT_TOKEN_SECRET!\n ) as Project;\n\n if (!decodedTokenProject) {\n clearProjectAuth(res);\n return next();\n }\n\n const project: ProjectDocument | null = await ProjectModel.findById(\n decodedTokenProject._id\n );\n\n if (\n !project ||\n !res.locals.organization ||\n String(project.organizationId) !== String(res.locals.organization._id)\n ) {\n clearProjectAuth(res);\n return next();\n }\n\n res.locals.project = project.toObject();\n } catch (error) {\n console.error('Error fetching project:', error);\n }\n\n return next();\n};\n\n/**\n * Middleware to check if the user is an admin of the organization or project\n * Sets the following properties in res.locals:\n * - isOrganizationAdmin: boolean\n * - isProjectAdmin: boolean\n */\nexport const checkAdmin = async (\n _req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { organization, project, user, authType } = res.locals;\n\n if (authType !== 'session') {\n return next();\n }\n\n res.locals.organizationRights = {\n read: false,\n write: false,\n admin: false,\n };\n res.locals.projectRights = {\n read: false,\n write: false,\n admin: false,\n };\n res.locals.projectRights = {\n read: false,\n write: false,\n admin: false,\n };\n\n if (user) {\n if (organization) {\n const isOrganizationAdmin: boolean =\n organization.adminsIds\n .map((id) => String(id))\n .includes(String(user._id)) ?? false;\n\n res.locals.isOrganizationAdmin = isOrganizationAdmin;\n\n res.locals.organizationRights = {\n read: true,\n write: isOrganizationAdmin,\n admin: isOrganizationAdmin,\n };\n }\n\n if (project) {\n const isProjectAdmin: boolean =\n project.adminsIds.map((id) => String(id)).includes(String(user._id)) ??\n false;\n\n res.locals.isProjectAdmin = isProjectAdmin;\n\n res.locals.projectRights = {\n read: true,\n write: isProjectAdmin,\n admin: isProjectAdmin,\n };\n\n res.locals.dictionaryRights = {\n read: true,\n write: true,\n admin: true,\n };\n }\n }\n\n return next();\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/middlewares/sessionAuth.middleware.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { OrganizationModel } from '@models/organization.model';\nimport { ProjectModel } from '@models/project.model';\nimport {\n clearOrganizationAuth,\n clearProjectAuth,\n} from '@services/sessionAuth.service';\nimport { getUserBySession as getUserBySessionService } from '@services/user.service';\nimport { Cookies } from '@utils/cookies';\nimport type { Request, Response, NextFunction } from 'express';\nimport jwt from 'jsonwebtoken';\nimport type {\n Organization,\n OrganizationDocument,\n} from '@/types/organization.types';\nimport type { Project, ProjectDocument, Rights } from '@/types/project.types';\nimport type { User } from '@/types/user.types';\n\nexport type ResponseWithInformation<ResBody = any> = Response<\n ResBody,\n {\n user: User | null;\n // Auth Context\n organization: Organization | null;\n project: Project | null;\n authType: 'session' | 'oauth2' | null;\n // Auth Rights - oAuth2 Auth\n organizationRights: Rights | null;\n projectRights: Rights | null;\n dictionaryRights: Rights | null;\n // Auth Rights - Session Auth\n isOrganizationAdmin: boolean | null;\n isProjectAdmin: boolean | null;\n }\n>;\n\nexport const checkUser = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { [Cookies.JWT_AUTH]: sessionToken } = req.cookies;\n\n res.locals.user = null;\n res.locals.authType = null;\n\n try {\n if (sessionToken) {\n const user = await getUserBySessionService(sessionToken);\n\n if (user) {\n res.locals.user = user.toObject();\n res.locals.authType = 'session';\n }\n }\n } catch (error) {\n console.error('Error fetching session:', error);\n }\n\n return next();\n};\n\nexport const checkOrganization = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenOrganization = req.cookies[Cookies.JWT_ORGANIZATION];\n\n res.locals.organization = null;\n\n try {\n if (!jwtTokenOrganization || jwtTokenOrganization === 'undefined') {\n clearOrganizationAuth(res);\n return next();\n }\n\n const organizationData = jwt.verify(\n jwtTokenOrganization,\n process.env.JWT_TOKEN_SECRET!\n ) as Organization;\n\n if (!organizationData) {\n clearOrganizationAuth(res);\n return next();\n }\n\n const organization: OrganizationDocument | null =\n await OrganizationModel.findById(organizationData._id);\n\n if (!organization) {\n clearOrganizationAuth(res);\n return next();\n }\n\n res.locals.organization = organization.toObject();\n } catch (error) {\n console.error('Error fetching organization:', error);\n }\n\n return next();\n};\n\nexport const checkProject = async (\n req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const jwtTokenProject = req.cookies[Cookies.JWT_PROJECT];\n res.locals.project = null;\n\n try {\n if (!jwtTokenProject || jwtTokenProject === 'undefined') {\n clearProjectAuth(res);\n return next();\n }\n\n const decodedTokenProject = jwt.verify(\n jwtTokenProject,\n process.env.JWT_TOKEN_SECRET!\n ) as Project;\n\n if (!decodedTokenProject) {\n clearProjectAuth(res);\n return next();\n }\n\n const project: ProjectDocument | null = await ProjectModel.findById(\n decodedTokenProject._id\n );\n\n if (\n !project ||\n !res.locals.organization ||\n String(project.organizationId) !== String(res.locals.organization._id)\n ) {\n clearProjectAuth(res);\n return next();\n }\n\n res.locals.project = project.toObject();\n } catch (error) {\n console.error('Error fetching project:', error);\n }\n\n return next();\n};\n\n/**\n * Middleware to check if the user is an admin of the organization or project\n * Sets the following properties in res.locals:\n * - isOrganizationAdmin: boolean\n * - isProjectAdmin: boolean\n */\nexport const checkAdmin = async (\n _req: Request,\n res: ResponseWithInformation,\n next: NextFunction\n): Promise<void> => {\n const { organization, project, user, authType } = res.locals;\n\n if (authType !== 'session') {\n return next();\n }\n\n res.locals.organizationRights = {\n read: true,\n write: false,\n admin: false,\n };\n res.locals.projectRights = {\n read: true,\n write: false,\n admin: false,\n };\n res.locals.projectRights = {\n read: true,\n write: false,\n admin: false,\n };\n\n if (user) {\n if (organization) {\n const isOrganizationAdmin: boolean =\n organization.adminsIds\n .map((id) => String(id))\n .includes(String(user._id)) ?? false;\n\n res.locals.isOrganizationAdmin = isOrganizationAdmin;\n\n res.locals.organizationRights = {\n read: true,\n write: isOrganizationAdmin,\n admin: isOrganizationAdmin,\n };\n }\n\n if (project) {\n const isProjectAdmin: boolean =\n project.adminsIds.map((id) => String(id)).includes(String(user._id)) ??\n false;\n\n res.locals.isProjectAdmin = isProjectAdmin;\n\n res.locals.projectRights = {\n read: true,\n write: isProjectAdmin,\n admin: isProjectAdmin,\n };\n\n res.locals.dictionaryRights = {\n read: true,\n write: true,\n admin: true,\n };\n }\n }\n\n return next();\n};\n"],"mappings":"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","names":[]}