@hed-hog/core 0.0.390 → 0.0.394

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 (528) hide show
  1. package/README.md +39 -0
  2. package/dist/access-log/access-log.controller.d.ts.map +1 -1
  3. package/dist/access-log/access-log.controller.js +1 -1
  4. package/dist/access-log/access-log.controller.js.map +1 -1
  5. package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
  6. package/dist/access-log/access-log.interceptor.js +8 -5
  7. package/dist/access-log/access-log.interceptor.js.map +1 -1
  8. package/dist/access-log/access-log.service.d.ts +4 -0
  9. package/dist/access-log/access-log.service.d.ts.map +1 -1
  10. package/dist/access-log/access-log.service.js +31 -4
  11. package/dist/access-log/access-log.service.js.map +1 -1
  12. package/dist/access-log/dto/query-access-log.dto.d.ts +2 -0
  13. package/dist/access-log/dto/query-access-log.dto.d.ts.map +1 -1
  14. package/dist/access-log/dto/query-access-log.dto.js +5 -0
  15. package/dist/access-log/dto/query-access-log.dto.js.map +1 -1
  16. package/dist/ai/ai.controller.d.ts +12 -8
  17. package/dist/ai/ai.controller.d.ts.map +1 -1
  18. package/dist/ai/ai.controller.js +17 -2
  19. package/dist/ai/ai.controller.js.map +1 -1
  20. package/dist/ai/ai.module.d.ts.map +1 -1
  21. package/dist/ai/ai.module.js +3 -2
  22. package/dist/ai/ai.module.js.map +1 -1
  23. package/dist/ai/ai.service.d.ts +30 -1
  24. package/dist/ai/ai.service.d.ts.map +1 -1
  25. package/dist/ai/ai.service.js +97 -3
  26. package/dist/ai/ai.service.js.map +1 -1
  27. package/dist/ai/dto/richtext-edit-html.dto.d.ts +5 -0
  28. package/dist/ai/dto/richtext-edit-html.dto.d.ts.map +1 -0
  29. package/dist/ai/dto/richtext-edit-html.dto.js +27 -0
  30. package/dist/ai/dto/richtext-edit-html.dto.js.map +1 -0
  31. package/dist/ai/richtext-ai.prompts.d.ts +5 -0
  32. package/dist/ai/richtext-ai.prompts.d.ts.map +1 -0
  33. package/dist/ai/richtext-ai.prompts.js +57 -0
  34. package/dist/ai/richtext-ai.prompts.js.map +1 -0
  35. package/dist/ai/richtext-ai.service.d.ts +34 -0
  36. package/dist/ai/richtext-ai.service.d.ts.map +1 -0
  37. package/dist/ai/richtext-ai.service.js +95 -0
  38. package/dist/ai/richtext-ai.service.js.map +1 -0
  39. package/dist/ai-instruction/ai-instruction.controller.d.ts +5 -5
  40. package/dist/auth/auth.controller.d.ts +66 -7
  41. package/dist/auth/auth.controller.d.ts.map +1 -1
  42. package/dist/auth/auth.controller.js +67 -23
  43. package/dist/auth/auth.controller.js.map +1 -1
  44. package/dist/auth/auth.module.d.ts.map +1 -1
  45. package/dist/auth/auth.module.js +2 -0
  46. package/dist/auth/auth.module.js.map +1 -1
  47. package/dist/auth/auth.service.d.ts +136 -4
  48. package/dist/auth/auth.service.d.ts.map +1 -1
  49. package/dist/auth/auth.service.js +246 -48
  50. package/dist/auth/auth.service.js.map +1 -1
  51. package/dist/auth/dto/confirm-email.dto.d.ts +4 -0
  52. package/dist/auth/dto/confirm-email.dto.d.ts.map +1 -0
  53. package/dist/auth/dto/confirm-email.dto.js +22 -0
  54. package/dist/auth/dto/confirm-email.dto.js.map +1 -0
  55. package/dist/auth/dto/resend-confirmation.dto.d.ts +8 -0
  56. package/dist/auth/dto/resend-confirmation.dto.d.ts.map +1 -0
  57. package/dist/auth/dto/resend-confirmation.dto.js +36 -0
  58. package/dist/auth/dto/resend-confirmation.dto.js.map +1 -0
  59. package/dist/authorize/authorize.controller.d.ts +1 -1
  60. package/dist/authorize/authorize.controller.d.ts.map +1 -1
  61. package/dist/authorize/authorize.controller.js +4 -2
  62. package/dist/authorize/authorize.controller.js.map +1 -1
  63. package/dist/authorize/authorize.service.d.ts +7 -0
  64. package/dist/authorize/authorize.service.d.ts.map +1 -1
  65. package/dist/authorize/authorize.service.js +1 -1
  66. package/dist/authorize/authorize.service.js.map +1 -1
  67. package/dist/challenge/challenge.service.d.ts +18 -5
  68. package/dist/challenge/challenge.service.d.ts.map +1 -1
  69. package/dist/challenge/challenge.service.js +50 -3
  70. package/dist/challenge/challenge.service.js.map +1 -1
  71. package/dist/core.module.d.ts.map +1 -1
  72. package/dist/core.module.js +17 -0
  73. package/dist/core.module.js.map +1 -1
  74. package/dist/dashboard/dashboard/dashboard.controller.d.ts +6 -6
  75. package/dist/dashboard/dashboard/dashboard.service.d.ts +6 -6
  76. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +4 -4
  77. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +4 -4
  78. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +1 -1
  79. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +1 -1
  80. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +2 -2
  81. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +2 -2
  82. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +2 -2
  83. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +2 -2
  84. package/dist/file/file.controller.d.ts +8 -1
  85. package/dist/file/file.controller.d.ts.map +1 -1
  86. package/dist/file/file.controller.js +45 -7
  87. package/dist/file/file.controller.js.map +1 -1
  88. package/dist/file/file.service.d.ts +128 -1
  89. package/dist/file/file.service.d.ts.map +1 -1
  90. package/dist/file/file.service.js +319 -8
  91. package/dist/file/file.service.js.map +1 -1
  92. package/dist/file/image-optimization.service.d.ts +43 -0
  93. package/dist/file/image-optimization.service.d.ts.map +1 -1
  94. package/dist/file/image-optimization.service.js +154 -0
  95. package/dist/file/image-optimization.service.js.map +1 -1
  96. package/dist/file/provider/abstract.provider.d.ts +16 -0
  97. package/dist/file/provider/abstract.provider.d.ts.map +1 -1
  98. package/dist/file/provider/abstract.provider.js +4 -0
  99. package/dist/file/provider/abstract.provider.js.map +1 -1
  100. package/dist/file/provider/gcs.provider.d.ts +2 -0
  101. package/dist/file/provider/gcs.provider.d.ts.map +1 -1
  102. package/dist/file/provider/gcs.provider.js +10 -0
  103. package/dist/file/provider/gcs.provider.js.map +1 -1
  104. package/dist/file/provider/local.provider.d.ts +1 -0
  105. package/dist/file/provider/local.provider.d.ts.map +1 -1
  106. package/dist/file/provider/local.provider.js +13 -0
  107. package/dist/file/provider/local.provider.js.map +1 -1
  108. package/dist/file/provider/s3.provider.d.ts +5 -0
  109. package/dist/file/provider/s3.provider.d.ts.map +1 -1
  110. package/dist/file/provider/s3.provider.js +15 -0
  111. package/dist/file/provider/s3.provider.js.map +1 -1
  112. package/dist/file/provider/spaces.provider.d.ts +5 -0
  113. package/dist/file/provider/spaces.provider.d.ts.map +1 -1
  114. package/dist/file/provider/spaces.provider.js +16 -0
  115. package/dist/file/provider/spaces.provider.js.map +1 -1
  116. package/dist/impersonation/dto/redeem-impersonation.dto.d.ts +4 -0
  117. package/dist/impersonation/dto/redeem-impersonation.dto.d.ts.map +1 -0
  118. package/dist/impersonation/dto/redeem-impersonation.dto.js +23 -0
  119. package/dist/impersonation/dto/redeem-impersonation.dto.js.map +1 -0
  120. package/dist/impersonation/dto/start-impersonation.dto.d.ts +7 -0
  121. package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -0
  122. package/dist/impersonation/dto/start-impersonation.dto.js +27 -0
  123. package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -0
  124. package/dist/impersonation/impersonation-restrictions.d.ts +26 -0
  125. package/dist/impersonation/impersonation-restrictions.d.ts.map +1 -0
  126. package/dist/impersonation/impersonation-restrictions.js +76 -0
  127. package/dist/impersonation/impersonation-restrictions.js.map +1 -0
  128. package/dist/impersonation/impersonation.controller.d.ts +90 -0
  129. package/dist/impersonation/impersonation.controller.d.ts.map +1 -0
  130. package/dist/impersonation/impersonation.controller.js +135 -0
  131. package/dist/impersonation/impersonation.controller.js.map +1 -0
  132. package/dist/impersonation/impersonation.module.d.ts +8 -0
  133. package/dist/impersonation/impersonation.module.d.ts.map +1 -0
  134. package/dist/impersonation/impersonation.module.js +44 -0
  135. package/dist/impersonation/impersonation.module.js.map +1 -0
  136. package/dist/impersonation/impersonation.service.d.ts +164 -0
  137. package/dist/impersonation/impersonation.service.d.ts.map +1 -0
  138. package/dist/impersonation/impersonation.service.js +408 -0
  139. package/dist/impersonation/impersonation.service.js.map +1 -0
  140. package/dist/index.d.ts +17 -0
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +19 -0
  143. package/dist/index.js.map +1 -1
  144. package/dist/integration/services/outbox-polling.coordinator.d.ts +2 -0
  145. package/dist/integration/services/outbox-polling.coordinator.d.ts.map +1 -1
  146. package/dist/integration/services/outbox-polling.coordinator.js +50 -30
  147. package/dist/integration/services/outbox-polling.coordinator.js.map +1 -1
  148. package/dist/integration/services/outbox.service.d.ts.map +1 -1
  149. package/dist/integration/services/outbox.service.js +5 -1
  150. package/dist/integration/services/outbox.service.js.map +1 -1
  151. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  152. package/dist/integration-profile/integration-profile.secrets.js +3 -0
  153. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  154. package/dist/integration-profile/integration-profile.utils.d.ts +14 -0
  155. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
  156. package/dist/integration-profile/integration-profile.utils.js +26 -0
  157. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  158. package/dist/integration-profile/testers/email.testers.d.ts.map +1 -1
  159. package/dist/integration-profile/testers/email.testers.js +28 -0
  160. package/dist/integration-profile/testers/email.testers.js.map +1 -1
  161. package/dist/language/en.json +11 -0
  162. package/dist/language/pt.json +11 -0
  163. package/dist/mail/dto/send.dto.d.ts +38 -1
  164. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  165. package/dist/mail/dto/send.dto.js +10 -0
  166. package/dist/mail/dto/send.dto.js.map +1 -1
  167. package/dist/mail/mail.controller.d.ts +1 -0
  168. package/dist/mail/mail.controller.d.ts.map +1 -1
  169. package/dist/mail/mail.module.d.ts.map +1 -1
  170. package/dist/mail/mail.module.js +2 -0
  171. package/dist/mail/mail.module.js.map +1 -1
  172. package/dist/mail/mail.service.d.ts +48 -4
  173. package/dist/mail/mail.service.d.ts.map +1 -1
  174. package/dist/mail/mail.service.js +187 -35
  175. package/dist/mail/mail.service.js.map +1 -1
  176. package/dist/mail-delivery/mail-delivery-provision.service.d.ts +21 -0
  177. package/dist/mail-delivery/mail-delivery-provision.service.d.ts.map +1 -0
  178. package/dist/mail-delivery/mail-delivery-provision.service.js +64 -0
  179. package/dist/mail-delivery/mail-delivery-provision.service.js.map +1 -0
  180. package/dist/mail-delivery/mail-delivery.constants.d.ts +17 -0
  181. package/dist/mail-delivery/mail-delivery.constants.d.ts.map +1 -0
  182. package/dist/mail-delivery/mail-delivery.constants.js +31 -0
  183. package/dist/mail-delivery/mail-delivery.constants.js.map +1 -0
  184. package/dist/mail-delivery/mail-delivery.controller.d.ts +19 -0
  185. package/dist/mail-delivery/mail-delivery.controller.d.ts.map +1 -0
  186. package/dist/mail-delivery/mail-delivery.controller.js +53 -0
  187. package/dist/mail-delivery/mail-delivery.controller.js.map +1 -0
  188. package/dist/mail-delivery/mail-delivery.module.d.ts +7 -0
  189. package/dist/mail-delivery/mail-delivery.module.d.ts.map +1 -0
  190. package/dist/mail-delivery/mail-delivery.module.js +36 -0
  191. package/dist/mail-delivery/mail-delivery.module.js.map +1 -0
  192. package/dist/mail-delivery/mail-delivery.service.d.ts +38 -0
  193. package/dist/mail-delivery/mail-delivery.service.d.ts.map +1 -0
  194. package/dist/mail-delivery/mail-delivery.service.js +140 -0
  195. package/dist/mail-delivery/mail-delivery.service.js.map +1 -0
  196. package/dist/mail-delivery/ses-event.parser.d.ts +27 -0
  197. package/dist/mail-delivery/ses-event.parser.d.ts.map +1 -0
  198. package/dist/mail-delivery/ses-event.parser.js +131 -0
  199. package/dist/mail-delivery/ses-event.parser.js.map +1 -0
  200. package/dist/mail-delivery/ses-webhook.service.d.ts +58 -0
  201. package/dist/mail-delivery/ses-webhook.service.d.ts.map +1 -0
  202. package/dist/mail-delivery/ses-webhook.service.js +214 -0
  203. package/dist/mail-delivery/ses-webhook.service.js.map +1 -0
  204. package/dist/mail-delivery/sns-message.util.d.ts +38 -0
  205. package/dist/mail-delivery/sns-message.util.d.ts.map +1 -0
  206. package/dist/mail-delivery/sns-message.util.js +109 -0
  207. package/dist/mail-delivery/sns-message.util.js.map +1 -0
  208. package/dist/mail-sent/dto/query-mail-sent-list.dto.d.ts +5 -0
  209. package/dist/mail-sent/dto/query-mail-sent-list.dto.d.ts.map +1 -1
  210. package/dist/mail-sent/dto/query-mail-sent-list.dto.js +6 -0
  211. package/dist/mail-sent/dto/query-mail-sent-list.dto.js.map +1 -1
  212. package/dist/mail-sent/mail-sent.controller.d.ts +39 -0
  213. package/dist/mail-sent/mail-sent.controller.d.ts.map +1 -1
  214. package/dist/mail-sent/mail-sent.service.d.ts +39 -0
  215. package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
  216. package/dist/mail-sent/mail-sent.service.js +45 -4
  217. package/dist/mail-sent/mail-sent.service.js.map +1 -1
  218. package/dist/mailbox/mailbox-fetcher.registry.d.ts +100 -0
  219. package/dist/mailbox/mailbox-fetcher.registry.d.ts.map +1 -0
  220. package/dist/mailbox/mailbox-fetcher.registry.js +59 -0
  221. package/dist/mailbox/mailbox-fetcher.registry.js.map +1 -0
  222. package/dist/mailbox/mailbox.module.d.ts +8 -0
  223. package/dist/mailbox/mailbox.module.d.ts.map +1 -0
  224. package/dist/mailbox/mailbox.module.js +27 -0
  225. package/dist/mailbox/mailbox.module.js.map +1 -0
  226. package/dist/meeting/meeting-provider.registry.d.ts +155 -0
  227. package/dist/meeting/meeting-provider.registry.d.ts.map +1 -0
  228. package/dist/meeting/meeting-provider.registry.js +53 -0
  229. package/dist/meeting/meeting-provider.registry.js.map +1 -0
  230. package/dist/meeting/meeting.constants.d.ts +47 -0
  231. package/dist/meeting/meeting.constants.d.ts.map +1 -0
  232. package/dist/meeting/meeting.constants.js +21 -0
  233. package/dist/meeting/meeting.constants.js.map +1 -0
  234. package/dist/meeting/meeting.module.d.ts +7 -0
  235. package/dist/meeting/meeting.module.d.ts.map +1 -0
  236. package/dist/meeting/meeting.module.js +26 -0
  237. package/dist/meeting/meeting.module.js.map +1 -0
  238. package/dist/middlewares/locale-injection.middleware.d.ts +12 -0
  239. package/dist/middlewares/locale-injection.middleware.d.ts.map +1 -1
  240. package/dist/middlewares/locale-injection.middleware.js +20 -4
  241. package/dist/middlewares/locale-injection.middleware.js.map +1 -1
  242. package/dist/oauth/providers/google.provider.d.ts +7 -0
  243. package/dist/oauth/providers/google.provider.d.ts.map +1 -1
  244. package/dist/oauth/providers/google.provider.js +43 -13
  245. package/dist/oauth/providers/google.provider.js.map +1 -1
  246. package/dist/observability/monitored-cron.d.ts +34 -0
  247. package/dist/observability/monitored-cron.d.ts.map +1 -0
  248. package/dist/observability/monitored-cron.js +118 -0
  249. package/dist/observability/monitored-cron.js.map +1 -0
  250. package/dist/pairing/dto/approve-reverse-pairing.dto.d.ts +12 -0
  251. package/dist/pairing/dto/approve-reverse-pairing.dto.d.ts.map +1 -0
  252. package/dist/pairing/dto/approve-reverse-pairing.dto.js +30 -0
  253. package/dist/pairing/dto/approve-reverse-pairing.dto.js.map +1 -0
  254. package/dist/pairing/dto/claim-pairing.dto.d.ts +11 -0
  255. package/dist/pairing/dto/claim-pairing.dto.d.ts.map +1 -0
  256. package/dist/pairing/dto/claim-pairing.dto.js +35 -0
  257. package/dist/pairing/dto/claim-pairing.dto.js.map +1 -0
  258. package/dist/pairing/dto/confirm-pairing.dto.d.ts +10 -0
  259. package/dist/pairing/dto/confirm-pairing.dto.d.ts.map +1 -0
  260. package/dist/pairing/dto/confirm-pairing.dto.js +24 -0
  261. package/dist/pairing/dto/confirm-pairing.dto.js.map +1 -0
  262. package/dist/pairing/dto/poll-reverse-pairing.dto.d.ts +5 -0
  263. package/dist/pairing/dto/poll-reverse-pairing.dto.d.ts.map +1 -0
  264. package/dist/pairing/dto/poll-reverse-pairing.dto.js +24 -0
  265. package/dist/pairing/dto/poll-reverse-pairing.dto.js.map +1 -0
  266. package/dist/pairing/dto/start-pairing.dto.d.ts +11 -0
  267. package/dist/pairing/dto/start-pairing.dto.d.ts.map +1 -0
  268. package/dist/pairing/dto/start-pairing.dto.js +30 -0
  269. package/dist/pairing/dto/start-pairing.dto.js.map +1 -0
  270. package/dist/pairing/dto/start-reverse-pairing.dto.d.ts +24 -0
  271. package/dist/pairing/dto/start-reverse-pairing.dto.d.ts.map +1 -0
  272. package/dist/pairing/dto/start-reverse-pairing.dto.js +47 -0
  273. package/dist/pairing/dto/start-reverse-pairing.dto.js.map +1 -0
  274. package/dist/pairing/pairing.controller.d.ts +118 -0
  275. package/dist/pairing/pairing.controller.d.ts.map +1 -0
  276. package/dist/pairing/pairing.controller.js +296 -0
  277. package/dist/pairing/pairing.controller.js.map +1 -0
  278. package/dist/pairing/pairing.module.d.ts +10 -0
  279. package/dist/pairing/pairing.module.d.ts.map +1 -0
  280. package/dist/pairing/pairing.module.js +40 -0
  281. package/dist/pairing/pairing.module.js.map +1 -0
  282. package/dist/pairing/pairing.service.d.ts +238 -0
  283. package/dist/pairing/pairing.service.d.ts.map +1 -0
  284. package/dist/pairing/pairing.service.js +495 -0
  285. package/dist/pairing/pairing.service.js.map +1 -0
  286. package/dist/pdf/pdf.service.d.ts +3 -6
  287. package/dist/pdf/pdf.service.d.ts.map +1 -1
  288. package/dist/pdf/pdf.service.js +8 -20
  289. package/dist/pdf/pdf.service.js.map +1 -1
  290. package/dist/profile/profile.controller.d.ts +11 -0
  291. package/dist/profile/profile.controller.d.ts.map +1 -1
  292. package/dist/profile/profile.service.d.ts +11 -0
  293. package/dist/profile/profile.service.d.ts.map +1 -1
  294. package/dist/profile/profile.service.js +20 -11
  295. package/dist/profile/profile.service.js.map +1 -1
  296. package/dist/redis/redis-pubsub.d.ts.map +1 -1
  297. package/dist/redis/redis-pubsub.js +44 -0
  298. package/dist/redis/redis-pubsub.js.map +1 -1
  299. package/dist/role/guards/role.guard.d.ts +5 -0
  300. package/dist/role/guards/role.guard.d.ts.map +1 -1
  301. package/dist/role/guards/role.guard.js +41 -39
  302. package/dist/role/guards/role.guard.js.map +1 -1
  303. package/dist/session/session.controller.d.ts +2 -0
  304. package/dist/session/session.controller.d.ts.map +1 -1
  305. package/dist/session/session.service.d.ts +39 -0
  306. package/dist/session/session.service.d.ts.map +1 -1
  307. package/dist/session/session.service.js +91 -8
  308. package/dist/session/session.service.js.map +1 -1
  309. package/dist/setting/brand-asset.service.d.ts +48 -0
  310. package/dist/setting/brand-asset.service.d.ts.map +1 -0
  311. package/dist/setting/brand-asset.service.js +130 -0
  312. package/dist/setting/brand-asset.service.js.map +1 -0
  313. package/dist/setting/setting.module.d.ts.map +1 -1
  314. package/dist/setting/setting.module.js +3 -2
  315. package/dist/setting/setting.module.js.map +1 -1
  316. package/dist/setting/setting.service.d.ts +33 -0
  317. package/dist/setting/setting.service.d.ts.map +1 -1
  318. package/dist/setting/setting.service.js +88 -0
  319. package/dist/setting/setting.service.js.map +1 -1
  320. package/dist/token/token.service.d.ts +23 -2
  321. package/dist/token/token.service.d.ts.map +1 -1
  322. package/dist/token/token.service.js +39 -4
  323. package/dist/token/token.service.js.map +1 -1
  324. package/dist/user/user.controller.d.ts +8 -22
  325. package/dist/user/user.controller.d.ts.map +1 -1
  326. package/dist/user/user.service.d.ts +44 -24
  327. package/dist/user/user.service.d.ts.map +1 -1
  328. package/dist/user/user.service.js +89 -6
  329. package/dist/user/user.service.js.map +1 -1
  330. package/dist/user-device/user-device.controller.d.ts +54 -0
  331. package/dist/user-device/user-device.controller.d.ts.map +1 -0
  332. package/dist/user-device/user-device.controller.js +103 -0
  333. package/dist/user-device/user-device.controller.js.map +1 -0
  334. package/dist/user-device/user-device.module.d.ts +3 -0
  335. package/dist/user-device/user-device.module.d.ts.map +1 -0
  336. package/dist/user-device/user-device.module.js +26 -0
  337. package/dist/user-device/user-device.module.js.map +1 -0
  338. package/dist/user-device/user-device.service.d.ts +71 -0
  339. package/dist/user-device/user-device.service.d.ts.map +1 -0
  340. package/dist/user-device/user-device.service.js +158 -0
  341. package/dist/user-device/user-device.service.js.map +1 -0
  342. package/dist/utils/device-key.d.ts +23 -0
  343. package/dist/utils/device-key.d.ts.map +1 -0
  344. package/dist/utils/device-key.js +31 -0
  345. package/dist/utils/device-key.js.map +1 -0
  346. package/dist/utils/geo-ip.d.ts +38 -0
  347. package/dist/utils/geo-ip.d.ts.map +1 -0
  348. package/dist/utils/geo-ip.js +122 -0
  349. package/dist/utils/geo-ip.js.map +1 -0
  350. package/dist/utils/locale-context.d.ts +10 -7
  351. package/dist/utils/locale-context.d.ts.map +1 -1
  352. package/dist/utils/locale-context.js +14 -8
  353. package/dist/utils/locale-context.js.map +1 -1
  354. package/dist/utils/security-event-vars.d.ts +56 -0
  355. package/dist/utils/security-event-vars.d.ts.map +1 -0
  356. package/dist/utils/security-event-vars.js +109 -0
  357. package/dist/utils/security-event-vars.js.map +1 -0
  358. package/dist/utils/user-agent.d.ts +19 -0
  359. package/dist/utils/user-agent.d.ts.map +1 -0
  360. package/dist/utils/user-agent.js +36 -0
  361. package/dist/utils/user-agent.js.map +1 -0
  362. package/dist/webhook-integration/webhook-integration.service.d.ts +5 -0
  363. package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
  364. package/dist/webhook-integration/webhook-integration.service.js +50 -4
  365. package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
  366. package/dist/webhook-integration/webhook-protocol.registry.d.ts +6 -0
  367. package/dist/webhook-integration/webhook-protocol.registry.d.ts.map +1 -1
  368. package/dist/webhook-integration/webhook-protocol.registry.js.map +1 -1
  369. package/hedhog/data/integration_provider.yaml +9 -0
  370. package/hedhog/data/mail.yaml +198 -62
  371. package/hedhog/data/mail_layout.yaml +43 -33
  372. package/hedhog/data/menu.yaml +2 -0
  373. package/hedhog/data/role.yaml +16 -0
  374. package/hedhog/data/route.yaml +172 -3
  375. package/hedhog/data/setting_group.yaml +178 -2
  376. package/hedhog/data/setting_subgroup.yaml +8 -0
  377. package/hedhog/frontend/app/_lib/hooks/use-core-access.test.tsx.ejs +125 -0
  378. package/hedhog/frontend/app/_lib/hooks/use-core-access.ts.ejs +29 -0
  379. package/hedhog/frontend/app/_lib/hooks/use-impersonation-access.test.ts.ejs +71 -0
  380. package/hedhog/frontend/app/_lib/hooks/use-impersonation-access.ts.ejs +32 -0
  381. package/hedhog/frontend/app/access-log/page.tsx.ejs +96 -22
  382. package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +17 -1
  383. package/hedhog/frontend/app/account/components/known-devices.tsx.ejs +89 -0
  384. package/hedhog/frontend/app/account/components/profile-form.tsx.ejs +2 -1
  385. package/hedhog/frontend/app/account/components/user-devices-list.tsx.ejs +186 -0
  386. package/hedhog/frontend/app/account/devices/page.tsx.ejs +5 -0
  387. package/hedhog/frontend/app/account/layout.tsx.ejs +2 -0
  388. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +298 -0
  389. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +376 -1236
  390. package/hedhog/frontend/app/mail/log/page.tsx.ejs +210 -3
  391. package/hedhog/frontend/app/mail/template/page.tsx.ejs +190 -132
  392. package/hedhog/frontend/app/users/active-session.tsx.ejs +58 -11
  393. package/hedhog/frontend/app/users/page.tsx.ejs +69 -10
  394. package/hedhog/frontend/app/users/simulate-access-dialog.test.tsx.ejs +202 -0
  395. package/hedhog/frontend/app/users/simulate-access-dialog.tsx.ejs +170 -0
  396. package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +19 -0
  397. package/hedhog/frontend/app/users/user-devices.tsx.ejs +89 -0
  398. package/hedhog/frontend/app/users/user-logs.tsx.ejs +13 -1
  399. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +46 -24
  400. package/hedhog/frontend/messages/en.json +146 -48
  401. package/hedhog/frontend/messages/pt.json +146 -48
  402. package/hedhog/table/access_log.yaml +7 -0
  403. package/hedhog/table/file.yaml +8 -0
  404. package/hedhog/table/mail_delivery_event.yaml +76 -0
  405. package/hedhog/table/mail_sent.yaml +23 -0
  406. package/hedhog/table/user_activity.yaml +9 -0
  407. package/hedhog/table/user_device.yaml +52 -0
  408. package/hedhog/table/user_session.yaml +20 -1
  409. package/package.json +6 -5
  410. package/src/access-log/access-log.controller.ts +1 -0
  411. package/src/access-log/access-log.interceptor.ts +5 -1
  412. package/src/access-log/access-log.service.spec.ts +33 -2
  413. package/src/access-log/access-log.service.ts +38 -0
  414. package/src/access-log/dto/query-access-log.dto.ts +5 -0
  415. package/src/ai/ai.controller.ts +9 -0
  416. package/src/ai/ai.module.ts +3 -2
  417. package/src/ai/ai.service.ts +150 -13
  418. package/src/ai/dto/richtext-edit-html.dto.ts +11 -0
  419. package/src/ai/richtext-ai.prompts.ts +57 -0
  420. package/src/ai/richtext-ai.service.ts +109 -0
  421. package/src/auth/auth.controller.ts +47 -8
  422. package/src/auth/auth.module.ts +2 -0
  423. package/src/auth/auth.service.spec.ts +383 -6
  424. package/src/auth/auth.service.ts +345 -56
  425. package/src/auth/dto/confirm-email.dto.ts +7 -0
  426. package/src/auth/dto/resend-confirmation.dto.ts +20 -0
  427. package/src/authorize/authorize.controller.ts +2 -0
  428. package/src/authorize/authorize.service.spec.ts +23 -0
  429. package/src/authorize/authorize.service.ts +8 -0
  430. package/src/challenge/challenge.service.spec.ts +73 -0
  431. package/src/challenge/challenge.service.ts +62 -3
  432. package/src/core.module.ts +19 -0
  433. package/src/file/file.controller.ts +54 -4
  434. package/src/file/file.service.spec.ts +275 -105
  435. package/src/file/file.service.ts +409 -14
  436. package/src/file/image-optimization.service.spec.ts +92 -0
  437. package/src/file/image-optimization.service.ts +202 -0
  438. package/src/file/provider/abstract.provider.ts +23 -0
  439. package/src/file/provider/gcs.provider.ts +17 -0
  440. package/src/file/provider/local.provider.ts +21 -0
  441. package/src/file/provider/s3.provider.ts +25 -0
  442. package/src/file/provider/spaces.provider.ts +26 -0
  443. package/src/impersonation/dto/redeem-impersonation.dto.ts +8 -0
  444. package/src/impersonation/dto/start-impersonation.dto.ts +13 -0
  445. package/src/impersonation/impersonation-restrictions.ts +84 -0
  446. package/src/impersonation/impersonation.controller.ts +109 -0
  447. package/src/impersonation/impersonation.module.ts +31 -0
  448. package/src/impersonation/impersonation.service.spec.ts +427 -0
  449. package/src/impersonation/impersonation.service.ts +577 -0
  450. package/src/index.ts +21 -0
  451. package/src/integration/services/outbox-polling.coordinator.spec.ts +90 -0
  452. package/src/integration/services/outbox-polling.coordinator.ts +62 -40
  453. package/src/integration/services/outbox.service.spec.ts +8 -0
  454. package/src/integration/services/outbox.service.ts +19 -13
  455. package/src/integration-profile/integration-profile.secrets.ts +3 -0
  456. package/src/integration-profile/integration-profile.utils.ts +38 -0
  457. package/src/integration-profile/testers/email.testers.ts +34 -1
  458. package/src/language/en.json +11 -0
  459. package/src/language/pt.json +11 -0
  460. package/src/mail/dto/send.dto.ts +46 -2
  461. package/src/mail/mail-template.spec.ts +79 -2
  462. package/src/mail/mail.module.ts +2 -0
  463. package/src/mail/mail.service.spec.ts +307 -6
  464. package/src/mail/mail.service.ts +227 -30
  465. package/src/mail-delivery/mail-delivery-provision.service.ts +66 -0
  466. package/src/mail-delivery/mail-delivery.constants.ts +31 -0
  467. package/src/mail-delivery/mail-delivery.controller.ts +38 -0
  468. package/src/mail-delivery/mail-delivery.module.ts +23 -0
  469. package/src/mail-delivery/mail-delivery.service.spec.ts +136 -0
  470. package/src/mail-delivery/mail-delivery.service.ts +152 -0
  471. package/src/mail-delivery/ses-event.parser.spec.ts +140 -0
  472. package/src/mail-delivery/ses-event.parser.ts +191 -0
  473. package/src/mail-delivery/ses-webhook.service.spec.ts +170 -0
  474. package/src/mail-delivery/ses-webhook.service.ts +240 -0
  475. package/src/mail-delivery/sns-message.util.spec.ts +163 -0
  476. package/src/mail-delivery/sns-message.util.ts +125 -0
  477. package/src/mail-sent/dto/query-mail-sent-list.dto.ts +15 -0
  478. package/src/mail-sent/mail-sent.service.ts +46 -2
  479. package/src/mailbox/mailbox-fetcher.registry.ts +132 -0
  480. package/src/mailbox/mailbox.module.ts +14 -0
  481. package/src/meeting/meeting-provider.registry.ts +193 -0
  482. package/src/meeting/meeting.constants.ts +53 -0
  483. package/src/meeting/meeting.module.ts +13 -0
  484. package/src/middlewares/locale-injection.middleware.ts +25 -6
  485. package/src/oauth/providers/google.provider.ts +49 -15
  486. package/src/observability/monitored-cron.spec.ts +102 -0
  487. package/src/observability/monitored-cron.ts +110 -0
  488. package/src/pairing/dto/approve-reverse-pairing.dto.ts +20 -0
  489. package/src/pairing/dto/claim-pairing.dto.ts +19 -0
  490. package/src/pairing/dto/confirm-pairing.dto.ts +14 -0
  491. package/src/pairing/dto/poll-reverse-pairing.dto.ts +9 -0
  492. package/src/pairing/dto/start-pairing.dto.ts +19 -0
  493. package/src/pairing/dto/start-reverse-pairing.dto.ts +45 -0
  494. package/src/pairing/pairing.controller.ts +246 -0
  495. package/src/pairing/pairing.module.ts +27 -0
  496. package/src/pairing/pairing.service.spec.ts +462 -0
  497. package/src/pairing/pairing.service.ts +614 -0
  498. package/src/pdf/pdf.service.ts +6 -24
  499. package/src/profile/profile.service.ts +26 -8
  500. package/src/redis/redis-pubsub.ts +11 -0
  501. package/src/role/guards/role.guard.spec.ts +75 -0
  502. package/src/role/guards/role.guard.ts +64 -46
  503. package/src/session/session.service.spec.ts +81 -0
  504. package/src/session/session.service.ts +93 -6
  505. package/src/setting/brand-asset.service.ts +137 -0
  506. package/src/setting/setting.module.ts +3 -2
  507. package/src/setting/setting.service.spec.ts +79 -1
  508. package/src/setting/setting.service.ts +109 -1
  509. package/src/token/token.service.spec.ts +62 -0
  510. package/src/token/token.service.ts +57 -3
  511. package/src/user/user.service.spec.ts +33 -2
  512. package/src/user/user.service.ts +108 -6
  513. package/src/user-device/user-device.controller.ts +77 -0
  514. package/src/user-device/user-device.module.ts +13 -0
  515. package/src/user-device/user-device.service.spec.ts +234 -0
  516. package/src/user-device/user-device.service.ts +168 -0
  517. package/src/utils/device-key.spec.ts +57 -0
  518. package/src/utils/device-key.ts +32 -0
  519. package/src/utils/geo-ip.spec.ts +134 -0
  520. package/src/utils/geo-ip.ts +93 -0
  521. package/src/utils/locale-context.spec.ts +27 -1
  522. package/src/utils/locale-context.ts +15 -12
  523. package/src/utils/security-event-vars.spec.ts +161 -0
  524. package/src/utils/security-event-vars.ts +153 -0
  525. package/src/utils/user-agent.spec.ts +37 -0
  526. package/src/utils/user-agent.ts +46 -0
  527. package/src/webhook-integration/webhook-integration.service.ts +57 -3
  528. package/src/webhook-integration/webhook-protocol.registry.ts +6 -0
@@ -1,6 +1,13 @@
1
1
  import { DeleteDTO } from '@hed-hog/api';
2
- import { getLocaleText, LocaleService } from '@hed-hog/api-locale';
3
2
  import {
3
+ getLocaleText,
4
+ isLocaleDetectedFromContext,
5
+ LocaleService,
6
+ normalizeLocaleCode,
7
+ } from '@hed-hog/api-locale';
8
+ import {
9
+ DEFAULT_PRIMARY_COLOR,
10
+ DEFAULT_PRIMARY_FOREGROUND,
4
11
  MailLayout,
5
12
  MailService as MailMainService,
6
13
  renderMailTemplate,
@@ -20,17 +27,21 @@ import * as Handlebars from 'handlebars';
20
27
  import {
21
28
  buildMailConfigFromIntegration,
22
29
  getFromAddress,
30
+ getReplyToAddress,
23
31
  } from '../integration-profile/integration-profile.utils';
24
32
  import { IntegrationDeveloperApiService } from '../integration/services/integration-developer-api.service';
33
+ import { BrandAssetService } from '../setting/brand-asset.service';
25
34
  import { SettingService } from '../setting/setting.service';
26
35
  import { CreateDTO } from './dto/create.dto';
27
36
  import { ImportDTO } from './dto/import.dto';
28
37
  import { PreviewDTO } from './dto/preview.dto';
29
- import { SendTemplatedMailDTO } from './dto/send.dto';
38
+ import { SendTemplatedMailDTO, SendTemplatedMailResult } from './dto/send.dto';
30
39
  import { TestMailDTO } from './dto/test-mail.dto';
31
40
  import { UpdateDTO } from './dto/update.dto';
32
41
  import { IncidentService } from '../incident/incident.service';
33
42
 
43
+ export type { SendTemplatedMailResult } from './dto/send.dto';
44
+
34
45
  @Injectable()
35
46
  export class MailService implements OnModuleInit {
36
47
  private readonly logger = new Logger(MailService.name);
@@ -51,6 +62,8 @@ export class MailService implements OnModuleInit {
51
62
  private readonly integrationApi: IntegrationDeveloperApiService,
52
63
  @Inject(forwardRef(() => IncidentService))
53
64
  private readonly incident: IncidentService,
65
+ @Inject(forwardRef(() => BrandAssetService))
66
+ private readonly brandAsset: BrandAssetService,
54
67
  ) { }
55
68
 
56
69
  onModuleInit(): void {
@@ -61,6 +74,13 @@ export class MailService implements OnModuleInit {
61
74
  handler: async (event) => {
62
75
  const slug = String(event.payload?.slug || '').trim();
63
76
 
77
+ // O layout resolvido (logo, cores, nome) fica ate 60s em cache no
78
+ // api-mail. Sem descartar aqui, "subi o logo e mandei um teste" - o
79
+ // fluxo natural de validacao - mostraria o valor antigo.
80
+ if (MailService.BRAND_SLUGS.has(slug)) {
81
+ this.mailMainService.invalidateLayoutCache();
82
+ }
83
+
64
84
  if (!this.isMailConfigSlug(slug)) {
65
85
  return;
66
86
  }
@@ -71,6 +91,16 @@ export class MailService implements OnModuleInit {
71
91
 
72
92
  }
73
93
 
94
+ /** Settings que compoem o cabecalho do e-mail resolvido em `resolveLayout`. */
95
+ private static readonly BRAND_SLUGS = new Set([
96
+ 'image-url',
97
+ 'url',
98
+ 'api-url',
99
+ 'system-name',
100
+ 'theme-primary-light',
101
+ 'theme-primary-foreground-light',
102
+ ]);
103
+
74
104
  private isMailConfigSlug(slug: string) {
75
105
  return slug === this.integrationProfileSettingSlug;
76
106
  }
@@ -79,6 +109,29 @@ export class MailService implements OnModuleInit {
79
109
  return value === true || value === 'true';
80
110
  }
81
111
 
112
+ /**
113
+ * Cor de marca (`theme-primary-light`) e seu contraste (`theme-primary-foreground-light`),
114
+ * disponibilizadas como `{{primaryColor}}`/`{{primaryForeground}}` no corpo Handlebars dos
115
+ * templates (ex.: o botao de CTA de um convite) e no layout base do e-mail.
116
+ */
117
+ private async getThemeVariables(): Promise<{
118
+ primaryColor: string;
119
+ primaryForeground: string;
120
+ }> {
121
+ const settings = await this.setting.getSettingValues([
122
+ 'theme-primary-light',
123
+ 'theme-primary-foreground-light',
124
+ ]);
125
+
126
+ return {
127
+ primaryColor:
128
+ (settings['theme-primary-light'] as string) || DEFAULT_PRIMARY_COLOR,
129
+ primaryForeground:
130
+ (settings['theme-primary-foreground-light'] as string) ||
131
+ DEFAULT_PRIMARY_FOREGROUND,
132
+ };
133
+ }
134
+
82
135
  private async syncConfiguredMailFlag() {
83
136
  try {
84
137
  const settings = await this.setting.getSettingValues([
@@ -117,7 +170,7 @@ export class MailService implements OnModuleInit {
117
170
  * Otherwise the global integration profile setting is read.
118
171
  * Returns the active from address and the built config object.
119
172
  */
120
- async reloadConfig(profileSlug?: string): Promise<{ success: boolean; provider: string; from: string; config: any }> {
173
+ async reloadConfig(profileSlug?: string): Promise<{ success: boolean; provider: string; from: string; replyTo?: string; config: any }> {
121
174
  try {
122
175
  let resolvedProfileSlug = String(profileSlug ?? '').trim();
123
176
 
@@ -159,8 +212,9 @@ export class MailService implements OnModuleInit {
159
212
  this.logger.log(`Mail configuration reloaded from profile "${profile.name}" (${providerSlug})`);
160
213
 
161
214
  const from = getFromAddress(profile.config);
215
+ const replyTo = getReplyToAddress(profile.config);
162
216
 
163
- return { success: true, provider: providerSlug, from, config };
217
+ return { success: true, provider: providerSlug, from, replyTo, config };
164
218
  } catch (error) {
165
219
  this.logger.error('Error reloading mail configuration:', error);
166
220
  throw error;
@@ -395,10 +449,17 @@ export class MailService implements OnModuleInit {
395
449
  });
396
450
  }
397
451
 
452
+ /**
453
+ * Continua sem lancar: ha dezenas de call sites que disparam e-mail sem
454
+ * `await`, e transformar isto em excecao derrubaria fluxos que hoje so perdem
455
+ * a notificacao. O que muda e o *retorno* - quem se importa (a fila do SAC,
456
+ * por exemplo) agora consegue distinguir enviado de engolido, em vez de
457
+ * assumir sucesso porque a promise resolveu.
458
+ */
398
459
  async sendTemplatedMail(
399
460
  locale: string,
400
- { email, slug, variables, profileSlug, app }: SendTemplatedMailDTO,
401
- ) {
461
+ { email, slug, variables, profileSlug, replyTo, app, userId }: SendTemplatedMailDTO,
462
+ ): Promise<SendTemplatedMailResult> {
402
463
  const settings = await this.setting.getSettingValues(['configured-mail']);
403
464
 
404
465
  if (!this.isSettingEnabled(settings['configured-mail'])) {
@@ -412,29 +473,67 @@ export class MailService implements OnModuleInit {
412
473
  message: 'Envio de e-mail abortado: a configuracao de e-mail nao esta ativa.',
413
474
  context: { slug },
414
475
  });
415
- return;
476
+ return { sent: false, reason: 'mail-not-configured' };
416
477
  }
417
478
 
418
479
  try {
419
- const { from } = await this.reloadConfig(profileSlug);
420
- const localeRecord = await this.getLocaleRecord(locale);
421
- const mail = await this.getMailTemplate(slug, localeRecord.id);
422
- const { subject, body } = mail.mail_locale[0];
423
- const brandName = await this.mailMainService.getBrandName(app, locale);
424
- const mergedVariables = { brandName, ...variables };
480
+ // O `replyTo` do perfil de integracao entra como padrao para que a
481
+ // resposta de quem trata o e-mail transacional como conversa caia numa
482
+ // caixa monitorada, e nao no remetente. Quem passa `replyTo` no DTO
483
+ // continua mandando.
484
+ const { from, replyTo: profileReplyTo } = await this.reloadConfig(profileSlug);
485
+ const resolvedReplyTo = replyTo?.trim() || profileReplyTo;
486
+ const recipientLocale = await this.resolveRecipientLocale(email, locale, userId);
487
+ const mail = await this.getMailTemplate(slug);
488
+ const translation = this.pickTranslation(mail, recipientLocale);
489
+
490
+ if (!translation) {
491
+ // Antes isto era um TypeError em `mail_locale[0]`, engolido pelo catch
492
+ // abaixo e reportado como `send-failed` - um template sem traducao
493
+ // nenhuma parecia falha do provedor.
494
+ this.logger.error(`Template "${slug}" has no translation available.`);
495
+ this.incident.record({
496
+ source: 'core.mail',
497
+ code: 'mail_template_no_locale',
498
+ severity: 'critical',
499
+ message: `Template "${slug}" nao tem nenhuma traducao cadastrada.`,
500
+ key: slug,
501
+ context: { slug, locale: recipientLocale },
502
+ });
503
+
504
+ return { sent: false, reason: 'template-locale-missing' };
505
+ }
506
+
507
+ const { subject, body, code: templateLocale } = translation;
508
+ const brandName = await this.mailMainService.getBrandName(app, templateLocale);
509
+ const { primaryColor, primaryForeground } = await this.getThemeVariables();
510
+ const mergedVariables = { brandName, primaryColor, primaryForeground, ...variables };
425
511
  const parsedSubject = this.interpolateTemplate(subject, mergedVariables);
426
512
  const parsedBody = this.interpolateTemplate(body, mergedVariables);
427
513
 
428
- await this.mailMainService.send({
514
+ const sendResult: any = await this.mailMainService.send({
429
515
  to: email,
430
516
  from,
517
+ ...(resolvedReplyTo ? { replyTo: resolvedReplyTo } : {}),
431
518
  subject: parsedSubject,
432
519
  body: parsedBody,
433
520
  mail_id: mail.id,
434
- locale,
521
+ // O layout (header/footer) e escolhido por este locale la no api-mail,
522
+ // entao tem que ser o do template escolhido, nao o cru do request.
523
+ locale: templateLocale,
435
524
  app,
436
525
  });
437
526
 
527
+ const providerMessageId =
528
+ sendResult?.result?.MessageId ??
529
+ sendResult?.result?.messageId ??
530
+ sendResult?.result?.data?.id ??
531
+ null;
532
+
533
+ return {
534
+ sent: true,
535
+ providerMessageId: providerMessageId ? String(providerMessageId) : null,
536
+ };
438
537
  } catch (error) {
439
538
  this.logger.error('Error sending templated mail:', error);
440
539
  // Agrupado por slug: um template quebrado vira um incidente com contador,
@@ -446,28 +545,109 @@ export class MailService implements OnModuleInit {
446
545
  key: slug,
447
546
  context: { slug, locale },
448
547
  });
548
+
549
+ return {
550
+ sent: false,
551
+ reason: 'send-failed',
552
+ error: error instanceof Error ? error.message : String(error),
553
+ };
449
554
  }
450
555
  }
451
556
 
452
- private async getLocaleRecord(locale: string) {
453
- const localeRecord = await this.prismaService.locale.findUnique({
454
- where: { code: locale },
557
+ /**
558
+ * Idioma em que ESTE destinatario deve receber o e-mail.
559
+ *
560
+ * Publico porque quem pre-formata variaveis antes de enviar (data e pais do
561
+ * alerta de seguranca) precisa do mesmo idioma que o corpo, senao o texto sai
562
+ * em portugues com a data em ingles. E idempotente: chamar aqui e passar o
563
+ * resultado como `locale` no envio da no mesmo lugar.
564
+ *
565
+ * Ordem:
566
+ * 1. preferencia gravada do destinatario - escolha explicita sempre vence;
567
+ * 2. locale do chamador, se o cliente realmente declarou um idioma;
568
+ * 3. setting global `language`;
569
+ * 4. `en`.
570
+ */
571
+ async resolveRecipientLocale(
572
+ email: string,
573
+ callerLocale?: string | null,
574
+ userId?: number,
575
+ ): Promise<string> {
576
+ try {
577
+ const recipientId = userId ?? (await this.findUserIdByEmail(email));
578
+ const resolved = await this.setting.resolveUserLocale(recipientId);
579
+
580
+ // A cadeia do `SettingService` usa o locale do CONTEXTO da requisicao.
581
+ // Quase sempre e o mesmo que chegou aqui, mas ha envios fora de request
582
+ // (fila, cron) e chamadores que passam um locale proprio: nesses, o
583
+ // `callerLocale` e a unica pista que existe.
584
+ if (resolved !== 'en') {
585
+ return resolved;
586
+ }
587
+
588
+ return normalizeLocaleCode(callerLocale) ?? resolved;
589
+ } catch (error) {
590
+ this.logger.warn(
591
+ `Falling back to caller locale while resolving recipient language: ${error}`,
592
+ );
593
+
594
+ return normalizeLocaleCode(callerLocale) ?? 'en';
595
+ }
596
+ }
597
+
598
+ /** `user_identifier` tem unique (type, value), entao e busca por indice. */
599
+ private async findUserIdByEmail(email: string): Promise<number | null> {
600
+ const value = String(email ?? '').trim();
601
+
602
+ if (!value) {
603
+ return null;
604
+ }
605
+
606
+ const identifier = await this.prismaService.user_identifier.findFirst({
607
+ where: { type: 'email', value },
608
+ select: { user_id: true },
455
609
  });
456
610
 
457
- if (!localeRecord) {
458
- throw new Error(`Locale "${locale}" not found`);
611
+ return identifier?.user_id ?? null;
612
+ }
613
+
614
+ /**
615
+ * Escolhe a traducao do template, caindo para o que existir.
616
+ *
617
+ * O filtro por locale ficava na propria query e `mail_locale[0]` era acessado
618
+ * sem checagem: template sem a traducao pedida virava TypeError silencioso.
619
+ * Trazendo todas as traducoes numa query so, a escolha vira decisao explicita
620
+ * - e o `locale.findUnique` que estourava com `pt-BR` deixa de ser preciso.
621
+ */
622
+ private pickTranslation(mail: any, requested: string) {
623
+ const translations = (mail?.mail_locale ?? [])
624
+ .map((item: any) => ({
625
+ subject: item?.subject,
626
+ body: item?.body,
627
+ code: item?.locale?.code,
628
+ }))
629
+ .filter((item: any) => item.code && item.subject != null && item.body != null);
630
+
631
+ if (!translations.length) {
632
+ return null;
459
633
  }
460
634
 
461
- return localeRecord;
635
+ const byCode = (code: string) =>
636
+ translations.find((item: any) => item.code === code);
637
+
638
+ return byCode(requested) ?? byCode('pt') ?? byCode('en') ?? translations[0];
462
639
  }
463
640
 
464
- private async getMailTemplate(slug: string, localeId: number) {
641
+ private async getMailTemplate(slug: string) {
465
642
  const mail = await this.prismaService.mail.findUnique({
466
643
  where: { slug },
467
644
  include: {
468
645
  mail_locale: {
469
- where: { locale_id: localeId },
470
- select: { subject: true, body: true },
646
+ select: {
647
+ subject: true,
648
+ body: true,
649
+ locale: { select: { code: true } },
650
+ },
471
651
  },
472
652
  mail_var: {
473
653
  select: { name: true },
@@ -476,7 +656,7 @@ export class MailService implements OnModuleInit {
476
656
  });
477
657
 
478
658
  if (!mail) {
479
- throw new Error(`Template "${slug}" not found for locale "${localeId}"`);
659
+ throw new Error(`Template "${slug}" not found`);
480
660
  }
481
661
 
482
662
  return mail;
@@ -544,9 +724,23 @@ export class MailService implements OnModuleInit {
544
724
  locale: string,
545
725
  { subject, body, variables, use_layout, layout }: PreviewDTO,
546
726
  ): Promise<{ html: string }> {
547
- const settings = await this.setting.getSettingValues(['system-name']);
727
+ const settings = await this.setting.getSettingValues([
728
+ 'system-name',
729
+ 'theme-primary-light',
730
+ 'theme-primary-foreground-light',
731
+ 'image-url',
732
+ ]);
548
733
  const brandName = settings['system-name'] as string;
549
- const data = { brandName, ...(variables || {}) };
734
+ const primaryColor =
735
+ (settings['theme-primary-light'] as string) || DEFAULT_PRIMARY_COLOR;
736
+ const primaryForeground =
737
+ (settings['theme-primary-foreground-light'] as string) ||
738
+ DEFAULT_PRIMARY_FOREGROUND;
739
+ const rawLogoUrl = settings['image-url'] as string;
740
+ const logoUrl = rawLogoUrl
741
+ ? (await this.brandAsset.resolveAssetUrl(rawLogoUrl)) || undefined
742
+ : undefined;
743
+ const data = { brandName, primaryColor, primaryForeground, ...(variables || {}) };
550
744
  const parsedSubject = subject ? this.interpolateTemplate(subject, data) : '';
551
745
  const parsedBody = body ? this.interpolateTemplate(body, data) : '';
552
746
 
@@ -569,6 +763,9 @@ export class MailService implements OnModuleInit {
569
763
  // devolver o corpo cru.
570
764
  layout: use_layout === false ? { wrapper: '' } : resolvedLayout,
571
765
  brandName,
766
+ primaryColor,
767
+ primaryForeground,
768
+ logoUrl,
572
769
  lang: locale,
573
770
  });
574
771
 
@@ -582,8 +779,7 @@ export class MailService implements OnModuleInit {
582
779
  body,
583
780
  variables,
584
781
  }: TestMailDTO) {
585
- const localeRecord = await this.getLocaleRecord(locale);
586
- const mail = await this.getMailTemplate(slug, localeRecord.id);
782
+ const mail = await this.getMailTemplate(slug);
587
783
  const settings = await this.setting.getSettingValues(['configured-mail']);
588
784
 
589
785
  if (!this.isSettingEnabled(settings['configured-mail'])) {
@@ -594,7 +790,8 @@ export class MailService implements OnModuleInit {
594
790
 
595
791
  try {
596
792
  const brandName = await this.mailMainService.getBrandName(undefined, locale);
597
- const mergedVariables = { brandName, ...(variables || {}) };
793
+ const { primaryColor, primaryForeground } = await this.getThemeVariables();
794
+ const mergedVariables = { brandName, primaryColor, primaryForeground, ...(variables || {}) };
598
795
  const parsedSubject = this.interpolateTemplate(subject, mergedVariables);
599
796
  const parsedBody = this.interpolateTemplate(body, mergedVariables);
600
797
 
@@ -0,0 +1,66 @@
1
+ import { PrismaService } from '@hed-hog/api-prisma';
2
+ import {
3
+ BadRequestException,
4
+ Inject,
5
+ Injectable,
6
+ forwardRef,
7
+ } from '@nestjs/common';
8
+ import { WebhookIntegrationService } from '../webhook-integration/webhook-integration.service';
9
+ import {
10
+ SES_DELIVERY_WEBHOOK_PROTOCOL,
11
+ SES_PROVIDER_SLUG,
12
+ SES_WEBHOOK_SLUG_PREFIX,
13
+ } from './mail-delivery.constants';
14
+
15
+ export type SesWebhookInfo = {
16
+ /** URL para assinar no topico SNS (subscription HTTPS). */
17
+ publicUrl: string | null;
18
+ publicUuid: string;
19
+ webhookIntegrationId: number;
20
+ };
21
+
22
+ /**
23
+ * Provisiona o webhook que recebe os eventos de entrega de um perfil SES.
24
+ *
25
+ * Idempotente: a chave e (protocol, integration_profile_id), entao chamar de
26
+ * novo devolve o mesmo UUID - e a URL ja assinada no topico SNS continua valida.
27
+ */
28
+ @Injectable()
29
+ export class MailDeliveryProvisionService {
30
+ constructor(
31
+ @Inject(forwardRef(() => PrismaService))
32
+ private readonly prisma: PrismaService,
33
+ private readonly webhookIntegration: WebhookIntegrationService,
34
+ ) {}
35
+
36
+ async provision(integrationProfileId: number): Promise<SesWebhookInfo> {
37
+ const profile = await this.prisma.integration_profile.findFirst({
38
+ where: {
39
+ id: integrationProfileId,
40
+ integration_provider: { slug: SES_PROVIDER_SLUG },
41
+ },
42
+ select: { id: true, slug: true, name: true },
43
+ });
44
+
45
+ if (!profile) {
46
+ throw new BadRequestException(
47
+ `Integration profile ${integrationProfileId} is not a "${SES_PROVIDER_SLUG}" profile.`,
48
+ );
49
+ }
50
+
51
+ const webhook = await this.webhookIntegration.provisionProtocolWebhook({
52
+ slug: `${SES_WEBHOOK_SLUG_PREFIX}-${profile.slug}`,
53
+ name: `SES — entrega (${profile.name})`,
54
+ description:
55
+ 'Recebe bounce, complaint e delivery do Amazon SES. A URL vai numa subscription HTTPS do tópico SNS configurado nas notificações da identidade.',
56
+ protocol: SES_DELIVERY_WEBHOOK_PROTOCOL,
57
+ integrationProfileId: profile.id,
58
+ });
59
+
60
+ return {
61
+ publicUrl: webhook.public_url ?? null,
62
+ publicUuid: webhook.public_uuid,
63
+ webhookIntegrationId: webhook.id,
64
+ };
65
+ }
66
+ }
@@ -0,0 +1,31 @@
1
+ /** Protocolo do adaptador registrado no WebhookProtocolRegistry. */
2
+ export const SES_DELIVERY_WEBHOOK_PROTOCOL = 'aws-ses';
3
+
4
+ /** Prefixo do slug do webhook provisionado por perfil. */
5
+ export const SES_WEBHOOK_SLUG_PREFIX = 'ses-delivery';
6
+
7
+ export const SES_PROVIDER_SLUG = 'ses';
8
+
9
+ /**
10
+ * Desfecho consolidado gravado em `mail_sent.delivery_status`.
11
+ *
12
+ * A ordem e a precedencia: um evento so sobrescreve o status atual se tiver
13
+ * rank maior ou igual. Sem isso um `Delivery` que chega depois de um
14
+ * `Complaint` - o que acontece, porque o destinatario marca como spam depois de
15
+ * receber - apagaria a reclamacao e diria que esta tudo bem.
16
+ */
17
+ export const MAIL_DELIVERY_STATUS_RANK: Record<string, number> = {
18
+ delivered: 1,
19
+ rejected: 2,
20
+ bounced: 3,
21
+ complained: 4,
22
+ };
23
+
24
+ /** Tipo de evento do provedor -> desfecho que ele representa. */
25
+ export const MAIL_DELIVERY_EVENT_STATUS: Record<string, string> = {
26
+ delivery: 'delivered',
27
+ bounce: 'bounced',
28
+ complaint: 'complained',
29
+ reject: 'rejected',
30
+ renderingfailure: 'rejected',
31
+ };
@@ -0,0 +1,38 @@
1
+ import { Role } from '@hed-hog/api';
2
+ import {
3
+ Controller,
4
+ Inject,
5
+ Param,
6
+ ParseIntPipe,
7
+ Post,
8
+ forwardRef,
9
+ } from '@nestjs/common';
10
+ import { MailDeliveryProvisionService } from './mail-delivery-provision.service';
11
+
12
+ /**
13
+ * Via administrativa do rastreio de entrega.
14
+ *
15
+ * O endpoint que recebe os eventos e o `/webhook/:uuid` publico do core, servido
16
+ * pelo adaptador do protocolo `aws-ses` - por isso ele nao aparece aqui nem no
17
+ * route.yaml: o RoleGuard curto-circuita em IS_PUBLIC_KEY antes de ler a tabela
18
+ * de rotas, e uma linha la seria peso morto.
19
+ */
20
+ @Role()
21
+ @Controller('mail-delivery')
22
+ export class MailDeliveryController {
23
+ constructor(
24
+ @Inject(forwardRef(() => MailDeliveryProvisionService))
25
+ private readonly provision: MailDeliveryProvisionService,
26
+ ) {}
27
+
28
+ /**
29
+ * Devolve a URL para assinar no topico SNS. Idempotente: chamar de novo
30
+ * devolve o mesmo UUID, entao uma subscription ja criada continua valendo.
31
+ */
32
+ @Post('provision/:integrationProfileId')
33
+ async provisionWebhook(
34
+ @Param('integrationProfileId', ParseIntPipe) integrationProfileId: number,
35
+ ) {
36
+ return this.provision.provision(integrationProfileId);
37
+ }
38
+ }
@@ -0,0 +1,23 @@
1
+ import { PrismaModule } from '@hed-hog/api-prisma';
2
+ import { Module, forwardRef } from '@nestjs/common';
3
+ import { WebhookIntegrationModule } from '../webhook-integration/webhook-integration.module';
4
+ import { MailDeliveryProvisionService } from './mail-delivery-provision.service';
5
+ import { MailDeliveryController } from './mail-delivery.controller';
6
+ import { MailDeliveryService } from './mail-delivery.service';
7
+ import { SesWebhookService } from './ses-webhook.service';
8
+
9
+ /**
10
+ * Rastreio de entrega do e-mail: consome o que o provedor diz depois de aceitar
11
+ * a mensagem e o reflete em `mail_sent`.
12
+ */
13
+ @Module({
14
+ imports: [
15
+ forwardRef(() => PrismaModule),
16
+ // O adaptador se registra no WebhookProtocolRegistry, que mora aqui.
17
+ forwardRef(() => WebhookIntegrationModule),
18
+ ],
19
+ controllers: [MailDeliveryController],
20
+ providers: [MailDeliveryService, MailDeliveryProvisionService, SesWebhookService],
21
+ exports: [MailDeliveryService, MailDeliveryProvisionService],
22
+ })
23
+ export class MailDeliveryModule {}