@hed-hog/core 0.0.390 → 0.0.393
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.
- package/README.md +39 -0
- package/dist/access-log/access-log.controller.d.ts.map +1 -1
- package/dist/access-log/access-log.controller.js +1 -1
- package/dist/access-log/access-log.controller.js.map +1 -1
- package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
- package/dist/access-log/access-log.interceptor.js +8 -5
- package/dist/access-log/access-log.interceptor.js.map +1 -1
- package/dist/access-log/access-log.service.d.ts +4 -0
- package/dist/access-log/access-log.service.d.ts.map +1 -1
- package/dist/access-log/access-log.service.js +31 -4
- package/dist/access-log/access-log.service.js.map +1 -1
- package/dist/access-log/dto/query-access-log.dto.d.ts +2 -0
- package/dist/access-log/dto/query-access-log.dto.d.ts.map +1 -1
- package/dist/access-log/dto/query-access-log.dto.js +5 -0
- package/dist/access-log/dto/query-access-log.dto.js.map +1 -1
- package/dist/ai/ai.controller.d.ts +12 -8
- package/dist/ai/ai.controller.d.ts.map +1 -1
- package/dist/ai/ai.controller.js +17 -2
- package/dist/ai/ai.controller.js.map +1 -1
- package/dist/ai/ai.module.d.ts.map +1 -1
- package/dist/ai/ai.module.js +3 -2
- package/dist/ai/ai.module.js.map +1 -1
- package/dist/ai/ai.service.d.ts +30 -1
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +97 -3
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai/dto/richtext-edit-html.dto.d.ts +5 -0
- package/dist/ai/dto/richtext-edit-html.dto.d.ts.map +1 -0
- package/dist/ai/dto/richtext-edit-html.dto.js +27 -0
- package/dist/ai/dto/richtext-edit-html.dto.js.map +1 -0
- package/dist/ai/richtext-ai.prompts.d.ts +5 -0
- package/dist/ai/richtext-ai.prompts.d.ts.map +1 -0
- package/dist/ai/richtext-ai.prompts.js +57 -0
- package/dist/ai/richtext-ai.prompts.js.map +1 -0
- package/dist/ai/richtext-ai.service.d.ts +34 -0
- package/dist/ai/richtext-ai.service.d.ts.map +1 -0
- package/dist/ai/richtext-ai.service.js +95 -0
- package/dist/ai/richtext-ai.service.js.map +1 -0
- package/dist/ai-instruction/ai-instruction.controller.d.ts +5 -5
- package/dist/auth/auth.controller.d.ts +66 -7
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +67 -23
- package/dist/auth/auth.controller.js.map +1 -1
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +2 -0
- package/dist/auth/auth.module.js.map +1 -1
- package/dist/auth/auth.service.d.ts +136 -4
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +246 -48
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/dto/confirm-email.dto.d.ts +4 -0
- package/dist/auth/dto/confirm-email.dto.d.ts.map +1 -0
- package/dist/auth/dto/confirm-email.dto.js +22 -0
- package/dist/auth/dto/confirm-email.dto.js.map +1 -0
- package/dist/auth/dto/resend-confirmation.dto.d.ts +8 -0
- package/dist/auth/dto/resend-confirmation.dto.d.ts.map +1 -0
- package/dist/auth/dto/resend-confirmation.dto.js +36 -0
- package/dist/auth/dto/resend-confirmation.dto.js.map +1 -0
- package/dist/authorize/authorize.controller.d.ts +1 -1
- package/dist/authorize/authorize.controller.d.ts.map +1 -1
- package/dist/authorize/authorize.controller.js +4 -2
- package/dist/authorize/authorize.controller.js.map +1 -1
- package/dist/authorize/authorize.service.d.ts +7 -0
- package/dist/authorize/authorize.service.d.ts.map +1 -1
- package/dist/authorize/authorize.service.js +1 -1
- package/dist/authorize/authorize.service.js.map +1 -1
- package/dist/challenge/challenge.service.d.ts +18 -5
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +50 -3
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +17 -0
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +6 -6
- package/dist/dashboard/dashboard/dashboard.service.d.ts +6 -6
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +4 -4
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +4 -4
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +2 -2
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +2 -2
- package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +2 -2
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +2 -2
- package/dist/file/file.controller.d.ts +8 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +45 -7
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.service.d.ts +128 -1
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +319 -8
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/image-optimization.service.d.ts +43 -0
- package/dist/file/image-optimization.service.d.ts.map +1 -1
- package/dist/file/image-optimization.service.js +154 -0
- package/dist/file/image-optimization.service.js.map +1 -1
- package/dist/file/provider/abstract.provider.d.ts +16 -0
- package/dist/file/provider/abstract.provider.d.ts.map +1 -1
- package/dist/file/provider/abstract.provider.js +4 -0
- package/dist/file/provider/abstract.provider.js.map +1 -1
- package/dist/file/provider/gcs.provider.d.ts +2 -0
- package/dist/file/provider/gcs.provider.d.ts.map +1 -1
- package/dist/file/provider/gcs.provider.js +10 -0
- package/dist/file/provider/gcs.provider.js.map +1 -1
- package/dist/file/provider/local.provider.d.ts +1 -0
- package/dist/file/provider/local.provider.d.ts.map +1 -1
- package/dist/file/provider/local.provider.js +13 -0
- package/dist/file/provider/local.provider.js.map +1 -1
- package/dist/file/provider/s3.provider.d.ts +5 -0
- package/dist/file/provider/s3.provider.d.ts.map +1 -1
- package/dist/file/provider/s3.provider.js +15 -0
- package/dist/file/provider/s3.provider.js.map +1 -1
- package/dist/file/provider/spaces.provider.d.ts +5 -0
- package/dist/file/provider/spaces.provider.d.ts.map +1 -1
- package/dist/file/provider/spaces.provider.js +16 -0
- package/dist/file/provider/spaces.provider.js.map +1 -1
- package/dist/impersonation/dto/redeem-impersonation.dto.d.ts +4 -0
- package/dist/impersonation/dto/redeem-impersonation.dto.d.ts.map +1 -0
- package/dist/impersonation/dto/redeem-impersonation.dto.js +23 -0
- package/dist/impersonation/dto/redeem-impersonation.dto.js.map +1 -0
- package/dist/impersonation/dto/start-impersonation.dto.d.ts +7 -0
- package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -0
- package/dist/impersonation/dto/start-impersonation.dto.js +27 -0
- package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -0
- package/dist/impersonation/impersonation-restrictions.d.ts +26 -0
- package/dist/impersonation/impersonation-restrictions.d.ts.map +1 -0
- package/dist/impersonation/impersonation-restrictions.js +76 -0
- package/dist/impersonation/impersonation-restrictions.js.map +1 -0
- package/dist/impersonation/impersonation.controller.d.ts +90 -0
- package/dist/impersonation/impersonation.controller.d.ts.map +1 -0
- package/dist/impersonation/impersonation.controller.js +135 -0
- package/dist/impersonation/impersonation.controller.js.map +1 -0
- package/dist/impersonation/impersonation.module.d.ts +8 -0
- package/dist/impersonation/impersonation.module.d.ts.map +1 -0
- package/dist/impersonation/impersonation.module.js +44 -0
- package/dist/impersonation/impersonation.module.js.map +1 -0
- package/dist/impersonation/impersonation.service.d.ts +164 -0
- package/dist/impersonation/impersonation.service.d.ts.map +1 -0
- package/dist/impersonation/impersonation.service.js +408 -0
- package/dist/impersonation/impersonation.service.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/integration/services/outbox-polling.coordinator.d.ts +2 -0
- package/dist/integration/services/outbox-polling.coordinator.d.ts.map +1 -1
- package/dist/integration/services/outbox-polling.coordinator.js +50 -30
- package/dist/integration/services/outbox-polling.coordinator.js.map +1 -1
- package/dist/integration/services/outbox.service.d.ts.map +1 -1
- package/dist/integration/services/outbox.service.js +5 -1
- package/dist/integration/services/outbox.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +3 -0
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +14 -0
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +26 -0
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/email.testers.d.ts.map +1 -1
- package/dist/integration-profile/testers/email.testers.js +28 -0
- package/dist/integration-profile/testers/email.testers.js.map +1 -1
- package/dist/language/en.json +11 -0
- package/dist/language/pt.json +11 -0
- package/dist/mail/dto/send.dto.d.ts +38 -1
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js +10 -0
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.controller.d.ts +1 -0
- package/dist/mail/mail.controller.d.ts.map +1 -1
- package/dist/mail/mail.module.d.ts.map +1 -1
- package/dist/mail/mail.module.js +2 -0
- package/dist/mail/mail.module.js.map +1 -1
- package/dist/mail/mail.service.d.ts +48 -4
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +187 -35
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mail-delivery/mail-delivery-provision.service.d.ts +21 -0
- package/dist/mail-delivery/mail-delivery-provision.service.d.ts.map +1 -0
- package/dist/mail-delivery/mail-delivery-provision.service.js +64 -0
- package/dist/mail-delivery/mail-delivery-provision.service.js.map +1 -0
- package/dist/mail-delivery/mail-delivery.constants.d.ts +17 -0
- package/dist/mail-delivery/mail-delivery.constants.d.ts.map +1 -0
- package/dist/mail-delivery/mail-delivery.constants.js +31 -0
- package/dist/mail-delivery/mail-delivery.constants.js.map +1 -0
- package/dist/mail-delivery/mail-delivery.controller.d.ts +19 -0
- package/dist/mail-delivery/mail-delivery.controller.d.ts.map +1 -0
- package/dist/mail-delivery/mail-delivery.controller.js +53 -0
- package/dist/mail-delivery/mail-delivery.controller.js.map +1 -0
- package/dist/mail-delivery/mail-delivery.module.d.ts +7 -0
- package/dist/mail-delivery/mail-delivery.module.d.ts.map +1 -0
- package/dist/mail-delivery/mail-delivery.module.js +36 -0
- package/dist/mail-delivery/mail-delivery.module.js.map +1 -0
- package/dist/mail-delivery/mail-delivery.service.d.ts +38 -0
- package/dist/mail-delivery/mail-delivery.service.d.ts.map +1 -0
- package/dist/mail-delivery/mail-delivery.service.js +140 -0
- package/dist/mail-delivery/mail-delivery.service.js.map +1 -0
- package/dist/mail-delivery/ses-event.parser.d.ts +27 -0
- package/dist/mail-delivery/ses-event.parser.d.ts.map +1 -0
- package/dist/mail-delivery/ses-event.parser.js +131 -0
- package/dist/mail-delivery/ses-event.parser.js.map +1 -0
- package/dist/mail-delivery/ses-webhook.service.d.ts +58 -0
- package/dist/mail-delivery/ses-webhook.service.d.ts.map +1 -0
- package/dist/mail-delivery/ses-webhook.service.js +214 -0
- package/dist/mail-delivery/ses-webhook.service.js.map +1 -0
- package/dist/mail-delivery/sns-message.util.d.ts +38 -0
- package/dist/mail-delivery/sns-message.util.d.ts.map +1 -0
- package/dist/mail-delivery/sns-message.util.js +109 -0
- package/dist/mail-delivery/sns-message.util.js.map +1 -0
- package/dist/mail-sent/dto/query-mail-sent-list.dto.d.ts +5 -0
- package/dist/mail-sent/dto/query-mail-sent-list.dto.d.ts.map +1 -1
- package/dist/mail-sent/dto/query-mail-sent-list.dto.js +6 -0
- package/dist/mail-sent/dto/query-mail-sent-list.dto.js.map +1 -1
- package/dist/mail-sent/mail-sent.controller.d.ts +39 -0
- package/dist/mail-sent/mail-sent.controller.d.ts.map +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts +39 -0
- package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
- package/dist/mail-sent/mail-sent.service.js +45 -4
- package/dist/mail-sent/mail-sent.service.js.map +1 -1
- package/dist/mailbox/mailbox-fetcher.registry.d.ts +100 -0
- package/dist/mailbox/mailbox-fetcher.registry.d.ts.map +1 -0
- package/dist/mailbox/mailbox-fetcher.registry.js +59 -0
- package/dist/mailbox/mailbox-fetcher.registry.js.map +1 -0
- package/dist/mailbox/mailbox.module.d.ts +8 -0
- package/dist/mailbox/mailbox.module.d.ts.map +1 -0
- package/dist/mailbox/mailbox.module.js +27 -0
- package/dist/mailbox/mailbox.module.js.map +1 -0
- package/dist/meeting/meeting-provider.registry.d.ts +155 -0
- package/dist/meeting/meeting-provider.registry.d.ts.map +1 -0
- package/dist/meeting/meeting-provider.registry.js +53 -0
- package/dist/meeting/meeting-provider.registry.js.map +1 -0
- package/dist/meeting/meeting.constants.d.ts +47 -0
- package/dist/meeting/meeting.constants.d.ts.map +1 -0
- package/dist/meeting/meeting.constants.js +21 -0
- package/dist/meeting/meeting.constants.js.map +1 -0
- package/dist/meeting/meeting.module.d.ts +7 -0
- package/dist/meeting/meeting.module.d.ts.map +1 -0
- package/dist/meeting/meeting.module.js +26 -0
- package/dist/meeting/meeting.module.js.map +1 -0
- package/dist/middlewares/locale-injection.middleware.d.ts +12 -0
- package/dist/middlewares/locale-injection.middleware.d.ts.map +1 -1
- package/dist/middlewares/locale-injection.middleware.js +20 -4
- package/dist/middlewares/locale-injection.middleware.js.map +1 -1
- package/dist/oauth/providers/google.provider.d.ts +7 -0
- package/dist/oauth/providers/google.provider.d.ts.map +1 -1
- package/dist/oauth/providers/google.provider.js +43 -13
- package/dist/oauth/providers/google.provider.js.map +1 -1
- package/dist/observability/monitored-cron.d.ts +34 -0
- package/dist/observability/monitored-cron.d.ts.map +1 -0
- package/dist/observability/monitored-cron.js +118 -0
- package/dist/observability/monitored-cron.js.map +1 -0
- package/dist/pairing/dto/approve-reverse-pairing.dto.d.ts +12 -0
- package/dist/pairing/dto/approve-reverse-pairing.dto.d.ts.map +1 -0
- package/dist/pairing/dto/approve-reverse-pairing.dto.js +30 -0
- package/dist/pairing/dto/approve-reverse-pairing.dto.js.map +1 -0
- package/dist/pairing/dto/claim-pairing.dto.d.ts +11 -0
- package/dist/pairing/dto/claim-pairing.dto.d.ts.map +1 -0
- package/dist/pairing/dto/claim-pairing.dto.js +35 -0
- package/dist/pairing/dto/claim-pairing.dto.js.map +1 -0
- package/dist/pairing/dto/confirm-pairing.dto.d.ts +10 -0
- package/dist/pairing/dto/confirm-pairing.dto.d.ts.map +1 -0
- package/dist/pairing/dto/confirm-pairing.dto.js +24 -0
- package/dist/pairing/dto/confirm-pairing.dto.js.map +1 -0
- package/dist/pairing/dto/poll-reverse-pairing.dto.d.ts +5 -0
- package/dist/pairing/dto/poll-reverse-pairing.dto.d.ts.map +1 -0
- package/dist/pairing/dto/poll-reverse-pairing.dto.js +24 -0
- package/dist/pairing/dto/poll-reverse-pairing.dto.js.map +1 -0
- package/dist/pairing/dto/start-pairing.dto.d.ts +11 -0
- package/dist/pairing/dto/start-pairing.dto.d.ts.map +1 -0
- package/dist/pairing/dto/start-pairing.dto.js +30 -0
- package/dist/pairing/dto/start-pairing.dto.js.map +1 -0
- package/dist/pairing/dto/start-reverse-pairing.dto.d.ts +24 -0
- package/dist/pairing/dto/start-reverse-pairing.dto.d.ts.map +1 -0
- package/dist/pairing/dto/start-reverse-pairing.dto.js +47 -0
- package/dist/pairing/dto/start-reverse-pairing.dto.js.map +1 -0
- package/dist/pairing/pairing.controller.d.ts +118 -0
- package/dist/pairing/pairing.controller.d.ts.map +1 -0
- package/dist/pairing/pairing.controller.js +296 -0
- package/dist/pairing/pairing.controller.js.map +1 -0
- package/dist/pairing/pairing.module.d.ts +10 -0
- package/dist/pairing/pairing.module.d.ts.map +1 -0
- package/dist/pairing/pairing.module.js +40 -0
- package/dist/pairing/pairing.module.js.map +1 -0
- package/dist/pairing/pairing.service.d.ts +238 -0
- package/dist/pairing/pairing.service.d.ts.map +1 -0
- package/dist/pairing/pairing.service.js +495 -0
- package/dist/pairing/pairing.service.js.map +1 -0
- package/dist/pdf/pdf.service.d.ts +3 -6
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +8 -20
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +11 -0
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.service.d.ts +11 -0
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +20 -11
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/redis/redis-pubsub.d.ts.map +1 -1
- package/dist/redis/redis-pubsub.js +44 -0
- package/dist/redis/redis-pubsub.js.map +1 -1
- package/dist/role/guards/role.guard.d.ts +5 -0
- package/dist/role/guards/role.guard.d.ts.map +1 -1
- package/dist/role/guards/role.guard.js +41 -39
- package/dist/role/guards/role.guard.js.map +1 -1
- package/dist/session/session.controller.d.ts +2 -0
- package/dist/session/session.controller.d.ts.map +1 -1
- package/dist/session/session.service.d.ts +39 -0
- package/dist/session/session.service.d.ts.map +1 -1
- package/dist/session/session.service.js +91 -8
- package/dist/session/session.service.js.map +1 -1
- package/dist/setting/brand-asset.service.d.ts +48 -0
- package/dist/setting/brand-asset.service.d.ts.map +1 -0
- package/dist/setting/brand-asset.service.js +130 -0
- package/dist/setting/brand-asset.service.js.map +1 -0
- package/dist/setting/setting.module.d.ts.map +1 -1
- package/dist/setting/setting.module.js +3 -2
- package/dist/setting/setting.module.js.map +1 -1
- package/dist/setting/setting.service.d.ts +33 -0
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +88 -0
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/token/token.service.d.ts +23 -2
- package/dist/token/token.service.d.ts.map +1 -1
- package/dist/token/token.service.js +39 -4
- package/dist/token/token.service.js.map +1 -1
- package/dist/user/user.controller.d.ts +8 -22
- package/dist/user/user.controller.d.ts.map +1 -1
- package/dist/user/user.service.d.ts +44 -24
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +89 -6
- package/dist/user/user.service.js.map +1 -1
- package/dist/user-device/user-device.controller.d.ts +54 -0
- package/dist/user-device/user-device.controller.d.ts.map +1 -0
- package/dist/user-device/user-device.controller.js +103 -0
- package/dist/user-device/user-device.controller.js.map +1 -0
- package/dist/user-device/user-device.module.d.ts +3 -0
- package/dist/user-device/user-device.module.d.ts.map +1 -0
- package/dist/user-device/user-device.module.js +26 -0
- package/dist/user-device/user-device.module.js.map +1 -0
- package/dist/user-device/user-device.service.d.ts +71 -0
- package/dist/user-device/user-device.service.d.ts.map +1 -0
- package/dist/user-device/user-device.service.js +158 -0
- package/dist/user-device/user-device.service.js.map +1 -0
- package/dist/utils/device-key.d.ts +23 -0
- package/dist/utils/device-key.d.ts.map +1 -0
- package/dist/utils/device-key.js +31 -0
- package/dist/utils/device-key.js.map +1 -0
- package/dist/utils/geo-ip.d.ts +38 -0
- package/dist/utils/geo-ip.d.ts.map +1 -0
- package/dist/utils/geo-ip.js +122 -0
- package/dist/utils/geo-ip.js.map +1 -0
- package/dist/utils/locale-context.d.ts +10 -7
- package/dist/utils/locale-context.d.ts.map +1 -1
- package/dist/utils/locale-context.js +14 -8
- package/dist/utils/locale-context.js.map +1 -1
- package/dist/utils/security-event-vars.d.ts +56 -0
- package/dist/utils/security-event-vars.d.ts.map +1 -0
- package/dist/utils/security-event-vars.js +109 -0
- package/dist/utils/security-event-vars.js.map +1 -0
- package/dist/utils/user-agent.d.ts +19 -0
- package/dist/utils/user-agent.d.ts.map +1 -0
- package/dist/utils/user-agent.js +36 -0
- package/dist/utils/user-agent.js.map +1 -0
- package/dist/webhook-integration/webhook-integration.service.d.ts +5 -0
- package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.js +50 -4
- package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
- package/dist/webhook-integration/webhook-protocol.registry.d.ts +6 -0
- package/dist/webhook-integration/webhook-protocol.registry.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-protocol.registry.js.map +1 -1
- package/hedhog/data/integration_provider.yaml +9 -0
- package/hedhog/data/mail.yaml +198 -62
- package/hedhog/data/mail_layout.yaml +43 -33
- package/hedhog/data/menu.yaml +2 -0
- package/hedhog/data/role.yaml +16 -0
- package/hedhog/data/route.yaml +172 -3
- package/hedhog/data/setting_group.yaml +178 -2
- package/hedhog/data/setting_subgroup.yaml +8 -0
- package/hedhog/frontend/app/_lib/hooks/use-core-access.test.tsx.ejs +125 -0
- package/hedhog/frontend/app/_lib/hooks/use-core-access.ts.ejs +29 -0
- package/hedhog/frontend/app/_lib/hooks/use-impersonation-access.test.ts.ejs +71 -0
- package/hedhog/frontend/app/_lib/hooks/use-impersonation-access.ts.ejs +32 -0
- package/hedhog/frontend/app/access-log/page.tsx.ejs +96 -22
- package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +17 -1
- package/hedhog/frontend/app/account/components/known-devices.tsx.ejs +89 -0
- package/hedhog/frontend/app/account/components/profile-form.tsx.ejs +2 -1
- package/hedhog/frontend/app/account/components/user-devices-list.tsx.ejs +186 -0
- package/hedhog/frontend/app/account/devices/page.tsx.ejs +5 -0
- package/hedhog/frontend/app/account/layout.tsx.ejs +2 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +298 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +376 -1236
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +210 -3
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +190 -132
- package/hedhog/frontend/app/users/active-session.tsx.ejs +58 -11
- package/hedhog/frontend/app/users/page.tsx.ejs +69 -10
- package/hedhog/frontend/app/users/simulate-access-dialog.test.tsx.ejs +202 -0
- package/hedhog/frontend/app/users/simulate-access-dialog.tsx.ejs +170 -0
- package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +19 -0
- package/hedhog/frontend/app/users/user-devices.tsx.ejs +89 -0
- package/hedhog/frontend/app/users/user-logs.tsx.ejs +13 -1
- package/hedhog/frontend/app/users/user-sheet.tsx.ejs +46 -24
- package/hedhog/frontend/messages/en.json +146 -48
- package/hedhog/frontend/messages/pt.json +146 -48
- package/hedhog/table/access_log.yaml +7 -0
- package/hedhog/table/file.yaml +8 -0
- package/hedhog/table/mail_delivery_event.yaml +76 -0
- package/hedhog/table/mail_sent.yaml +23 -0
- package/hedhog/table/user_activity.yaml +9 -0
- package/hedhog/table/user_device.yaml +52 -0
- package/hedhog/table/user_session.yaml +20 -1
- package/package.json +6 -5
- package/src/access-log/access-log.controller.ts +1 -0
- package/src/access-log/access-log.interceptor.ts +5 -1
- package/src/access-log/access-log.service.spec.ts +33 -2
- package/src/access-log/access-log.service.ts +38 -0
- package/src/access-log/dto/query-access-log.dto.ts +5 -0
- package/src/ai/ai.controller.ts +9 -0
- package/src/ai/ai.module.ts +3 -2
- package/src/ai/ai.service.ts +150 -13
- package/src/ai/dto/richtext-edit-html.dto.ts +11 -0
- package/src/ai/richtext-ai.prompts.ts +57 -0
- package/src/ai/richtext-ai.service.ts +109 -0
- package/src/auth/auth.controller.ts +47 -8
- package/src/auth/auth.module.ts +2 -0
- package/src/auth/auth.service.spec.ts +383 -6
- package/src/auth/auth.service.ts +345 -56
- package/src/auth/dto/confirm-email.dto.ts +7 -0
- package/src/auth/dto/resend-confirmation.dto.ts +20 -0
- package/src/authorize/authorize.controller.ts +2 -0
- package/src/authorize/authorize.service.spec.ts +23 -0
- package/src/authorize/authorize.service.ts +8 -0
- package/src/challenge/challenge.service.spec.ts +73 -0
- package/src/challenge/challenge.service.ts +62 -3
- package/src/core.module.ts +19 -0
- package/src/file/file.controller.ts +54 -4
- package/src/file/file.service.spec.ts +275 -105
- package/src/file/file.service.ts +409 -14
- package/src/file/image-optimization.service.spec.ts +92 -0
- package/src/file/image-optimization.service.ts +202 -0
- package/src/file/provider/abstract.provider.ts +23 -0
- package/src/file/provider/gcs.provider.ts +17 -0
- package/src/file/provider/local.provider.ts +21 -0
- package/src/file/provider/s3.provider.ts +25 -0
- package/src/file/provider/spaces.provider.ts +26 -0
- package/src/impersonation/dto/redeem-impersonation.dto.ts +8 -0
- package/src/impersonation/dto/start-impersonation.dto.ts +13 -0
- package/src/impersonation/impersonation-restrictions.ts +84 -0
- package/src/impersonation/impersonation.controller.ts +109 -0
- package/src/impersonation/impersonation.module.ts +31 -0
- package/src/impersonation/impersonation.service.spec.ts +427 -0
- package/src/impersonation/impersonation.service.ts +577 -0
- package/src/index.ts +21 -0
- package/src/integration/services/outbox-polling.coordinator.spec.ts +90 -0
- package/src/integration/services/outbox-polling.coordinator.ts +62 -40
- package/src/integration/services/outbox.service.spec.ts +8 -0
- package/src/integration/services/outbox.service.ts +19 -13
- package/src/integration-profile/integration-profile.secrets.ts +3 -0
- package/src/integration-profile/integration-profile.utils.ts +38 -0
- package/src/integration-profile/testers/email.testers.ts +34 -1
- package/src/language/en.json +11 -0
- package/src/language/pt.json +11 -0
- package/src/mail/dto/send.dto.ts +46 -2
- package/src/mail/mail-template.spec.ts +79 -2
- package/src/mail/mail.module.ts +2 -0
- package/src/mail/mail.service.spec.ts +307 -6
- package/src/mail/mail.service.ts +227 -30
- package/src/mail-delivery/mail-delivery-provision.service.ts +66 -0
- package/src/mail-delivery/mail-delivery.constants.ts +31 -0
- package/src/mail-delivery/mail-delivery.controller.ts +38 -0
- package/src/mail-delivery/mail-delivery.module.ts +23 -0
- package/src/mail-delivery/mail-delivery.service.spec.ts +136 -0
- package/src/mail-delivery/mail-delivery.service.ts +152 -0
- package/src/mail-delivery/ses-event.parser.spec.ts +140 -0
- package/src/mail-delivery/ses-event.parser.ts +191 -0
- package/src/mail-delivery/ses-webhook.service.spec.ts +170 -0
- package/src/mail-delivery/ses-webhook.service.ts +240 -0
- package/src/mail-delivery/sns-message.util.spec.ts +163 -0
- package/src/mail-delivery/sns-message.util.ts +125 -0
- package/src/mail-sent/dto/query-mail-sent-list.dto.ts +15 -0
- package/src/mail-sent/mail-sent.service.ts +46 -2
- package/src/mailbox/mailbox-fetcher.registry.ts +132 -0
- package/src/mailbox/mailbox.module.ts +14 -0
- package/src/meeting/meeting-provider.registry.ts +193 -0
- package/src/meeting/meeting.constants.ts +53 -0
- package/src/meeting/meeting.module.ts +13 -0
- package/src/middlewares/locale-injection.middleware.ts +25 -6
- package/src/oauth/providers/google.provider.ts +49 -15
- package/src/observability/monitored-cron.spec.ts +102 -0
- package/src/observability/monitored-cron.ts +110 -0
- package/src/pairing/dto/approve-reverse-pairing.dto.ts +20 -0
- package/src/pairing/dto/claim-pairing.dto.ts +19 -0
- package/src/pairing/dto/confirm-pairing.dto.ts +14 -0
- package/src/pairing/dto/poll-reverse-pairing.dto.ts +9 -0
- package/src/pairing/dto/start-pairing.dto.ts +19 -0
- package/src/pairing/dto/start-reverse-pairing.dto.ts +45 -0
- package/src/pairing/pairing.controller.ts +246 -0
- package/src/pairing/pairing.module.ts +27 -0
- package/src/pairing/pairing.service.spec.ts +462 -0
- package/src/pairing/pairing.service.ts +614 -0
- package/src/pdf/pdf.service.ts +6 -24
- package/src/profile/profile.service.ts +26 -8
- package/src/redis/redis-pubsub.ts +11 -0
- package/src/role/guards/role.guard.spec.ts +75 -0
- package/src/role/guards/role.guard.ts +64 -46
- package/src/session/session.service.spec.ts +81 -0
- package/src/session/session.service.ts +93 -6
- package/src/setting/brand-asset.service.ts +137 -0
- package/src/setting/setting.module.ts +3 -2
- package/src/setting/setting.service.spec.ts +79 -1
- package/src/setting/setting.service.ts +109 -1
- package/src/token/token.service.spec.ts +62 -0
- package/src/token/token.service.ts +57 -3
- package/src/user/user.service.spec.ts +33 -2
- package/src/user/user.service.ts +108 -6
- package/src/user-device/user-device.controller.ts +77 -0
- package/src/user-device/user-device.module.ts +13 -0
- package/src/user-device/user-device.service.spec.ts +234 -0
- package/src/user-device/user-device.service.ts +168 -0
- package/src/utils/device-key.spec.ts +57 -0
- package/src/utils/device-key.ts +32 -0
- package/src/utils/geo-ip.spec.ts +134 -0
- package/src/utils/geo-ip.ts +93 -0
- package/src/utils/locale-context.spec.ts +27 -1
- package/src/utils/locale-context.ts +15 -12
- package/src/utils/security-event-vars.spec.ts +161 -0
- package/src/utils/security-event-vars.ts +153 -0
- package/src/utils/user-agent.spec.ts +37 -0
- package/src/utils/user-agent.ts +46 -0
- package/src/webhook-integration/webhook-integration.service.ts +57 -3
- package/src/webhook-integration/webhook-protocol.registry.ts +6 -0
package/src/mail/mail.service.ts
CHANGED
|
@@ -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
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
const
|
|
424
|
-
const
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
-
|
|
458
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
470
|
-
|
|
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
|
|
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([
|
|
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
|
|
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
|
|
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
|
|
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 {}
|