@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.
- 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
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSesNotification = parseSesNotification;
|
|
4
|
+
/**
|
|
5
|
+
* O SES publica o mesmo fato em dois formatos, e qual deles chega depende de
|
|
6
|
+
* como as notificacoes foram ligadas:
|
|
7
|
+
*
|
|
8
|
+
* - notificacoes por identidade (o caminho simples): `notificationType`
|
|
9
|
+
* - configuration set com event destination: `eventType`
|
|
10
|
+
*
|
|
11
|
+
* Suportar os dois e barato e evita que a escolha feita no console da AWS - que
|
|
12
|
+
* nem sempre e nossa - quebre a ingestao.
|
|
13
|
+
*/
|
|
14
|
+
function parseSesNotification(payload) {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
16
|
+
const rawType = String((_b = (_a = payload === null || payload === void 0 ? void 0 : payload.notificationType) !== null && _a !== void 0 ? _a : payload === null || payload === void 0 ? void 0 : payload.eventType) !== null && _b !== void 0 ? _b : '').trim();
|
|
17
|
+
if (!rawType)
|
|
18
|
+
return [];
|
|
19
|
+
const providerMessageId = String((_d = (_c = payload === null || payload === void 0 ? void 0 : payload.mail) === null || _c === void 0 ? void 0 : _c.messageId) !== null && _d !== void 0 ? _d : '').trim();
|
|
20
|
+
if (!providerMessageId)
|
|
21
|
+
return [];
|
|
22
|
+
const type = rawType.toLowerCase();
|
|
23
|
+
const mailTimestamp = (_e = payload === null || payload === void 0 ? void 0 : payload.mail) === null || _e === void 0 ? void 0 : _e.timestamp;
|
|
24
|
+
switch (type) {
|
|
25
|
+
case 'bounce': {
|
|
26
|
+
const bounce = (_f = payload.bounce) !== null && _f !== void 0 ? _f : {};
|
|
27
|
+
const recipients = Array.isArray(bounce.bouncedRecipients)
|
|
28
|
+
? bounce.bouncedRecipients
|
|
29
|
+
: [];
|
|
30
|
+
const occurredAt = toDate((_g = bounce.timestamp) !== null && _g !== void 0 ? _g : mailTimestamp);
|
|
31
|
+
// Um bounce sem destinatario listado ainda e um bounce: registrar sem
|
|
32
|
+
// e-mail e melhor que descartar a unica evidencia de que a mensagem voltou.
|
|
33
|
+
if (!recipients.length) {
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
providerMessageId,
|
|
37
|
+
recipientEmail: null,
|
|
38
|
+
eventType: type,
|
|
39
|
+
bounceType: str(bounce.bounceType),
|
|
40
|
+
bounceSubtype: str(bounce.bounceSubType),
|
|
41
|
+
diagnosticCode: null,
|
|
42
|
+
reportingMta: str(bounce.reportingMTA),
|
|
43
|
+
occurredAt,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
return recipients.map((recipient) => {
|
|
48
|
+
var _a;
|
|
49
|
+
return ({
|
|
50
|
+
providerMessageId,
|
|
51
|
+
recipientEmail: str(recipient === null || recipient === void 0 ? void 0 : recipient.emailAddress),
|
|
52
|
+
eventType: type,
|
|
53
|
+
bounceType: str(bounce.bounceType),
|
|
54
|
+
bounceSubtype: str(bounce.bounceSubType),
|
|
55
|
+
// A resposta literal do servidor destinatario - o campo que responde
|
|
56
|
+
// "por que nao chegou".
|
|
57
|
+
diagnosticCode: (_a = str(recipient === null || recipient === void 0 ? void 0 : recipient.diagnosticCode)) !== null && _a !== void 0 ? _a : str(recipient === null || recipient === void 0 ? void 0 : recipient.status),
|
|
58
|
+
reportingMta: str(bounce.reportingMTA),
|
|
59
|
+
occurredAt,
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
case 'complaint': {
|
|
64
|
+
const complaint = (_h = payload.complaint) !== null && _h !== void 0 ? _h : {};
|
|
65
|
+
const recipients = Array.isArray(complaint.complainedRecipients)
|
|
66
|
+
? complaint.complainedRecipients
|
|
67
|
+
: [];
|
|
68
|
+
const occurredAt = toDate((_j = complaint.timestamp) !== null && _j !== void 0 ? _j : mailTimestamp);
|
|
69
|
+
const feedback = str(complaint.complaintFeedbackType);
|
|
70
|
+
if (!recipients.length) {
|
|
71
|
+
return [
|
|
72
|
+
buildSimple(providerMessageId, null, type, occurredAt, feedback, null),
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
return recipients.map((recipient) => buildSimple(providerMessageId, str(recipient === null || recipient === void 0 ? void 0 : recipient.emailAddress), type, occurredAt, feedback, null));
|
|
76
|
+
}
|
|
77
|
+
case 'delivery': {
|
|
78
|
+
const delivery = (_k = payload.delivery) !== null && _k !== void 0 ? _k : {};
|
|
79
|
+
const recipients = Array.isArray(delivery.recipients) ? delivery.recipients : [];
|
|
80
|
+
const occurredAt = toDate((_l = delivery.timestamp) !== null && _l !== void 0 ? _l : mailTimestamp);
|
|
81
|
+
if (!recipients.length) {
|
|
82
|
+
return [
|
|
83
|
+
buildSimple(providerMessageId, null, type, occurredAt, str(delivery.smtpResponse), str(delivery.reportingMTA)),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
return recipients.map((recipient) => buildSimple(providerMessageId, str(recipient), type, occurredAt, str(delivery.smtpResponse), str(delivery.reportingMTA)));
|
|
87
|
+
}
|
|
88
|
+
default: {
|
|
89
|
+
// Send, Reject, Open, Click, DeliveryDelay, RenderingFailure e o que a AWS
|
|
90
|
+
// acrescentar depois. Guardar o desconhecido e o que faz um tipo novo
|
|
91
|
+
// aparecer no log em vez de sumir.
|
|
92
|
+
const destinations = Array.isArray((_m = payload === null || payload === void 0 ? void 0 : payload.mail) === null || _m === void 0 ? void 0 : _m.destination)
|
|
93
|
+
? payload.mail.destination
|
|
94
|
+
: [];
|
|
95
|
+
const occurredAt = toDate(mailTimestamp);
|
|
96
|
+
const detail = (_r = (_p = str((_o = payload === null || payload === void 0 ? void 0 : payload.reject) === null || _o === void 0 ? void 0 : _o.reason)) !== null && _p !== void 0 ? _p : str((_q = payload === null || payload === void 0 ? void 0 : payload.failure) === null || _q === void 0 ? void 0 : _q.errorMessage)) !== null && _r !== void 0 ? _r : str((_s = payload === null || payload === void 0 ? void 0 : payload.deliveryDelay) === null || _s === void 0 ? void 0 : _s.delayType);
|
|
97
|
+
if (!destinations.length) {
|
|
98
|
+
return [
|
|
99
|
+
buildSimple(providerMessageId, null, type, occurredAt, detail, null),
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
return destinations.map((address) => buildSimple(providerMessageId, str(address), type, occurredAt, detail, null));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function buildSimple(providerMessageId, recipientEmail, eventType, occurredAt, diagnosticCode, reportingMta) {
|
|
107
|
+
return {
|
|
108
|
+
providerMessageId,
|
|
109
|
+
recipientEmail,
|
|
110
|
+
eventType,
|
|
111
|
+
bounceType: null,
|
|
112
|
+
bounceSubtype: null,
|
|
113
|
+
diagnosticCode,
|
|
114
|
+
reportingMta,
|
|
115
|
+
occurredAt,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function str(value) {
|
|
119
|
+
const text = String(value !== null && value !== void 0 ? value : '').trim();
|
|
120
|
+
return text || null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Data do provedor. Cai para agora quando o timestamp vem ausente ou invalido -
|
|
124
|
+
* a coluna e NOT NULL e faz parte da chave de dedupe, entao um `Invalid Date`
|
|
125
|
+
* derrubaria a ingestao inteira do lote.
|
|
126
|
+
*/
|
|
127
|
+
function toDate(value) {
|
|
128
|
+
const parsed = new Date(String(value !== null && value !== void 0 ? value : ''));
|
|
129
|
+
return Number.isNaN(parsed.getTime()) ? new Date() : parsed;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=ses-event.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ses-event.parser.js","sourceRoot":"","sources":["../../src/mail-delivery/ses-event.parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
2
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
3
|
+
import { IWebhookProtocolAdapter, WebhookProtocolRegistry, WebhookProtocolRequest, WebhookProtocolResponse } from '../webhook-integration/webhook-protocol.registry';
|
|
4
|
+
import { MailDeliveryService } from './mail-delivery.service';
|
|
5
|
+
/**
|
|
6
|
+
* Eventos de entrega do Amazon SES, publicados via SNS, sobre o webhook publico
|
|
7
|
+
* do core.
|
|
8
|
+
*
|
|
9
|
+
* Duas camadas de credencial, como o resto dos adaptadores:
|
|
10
|
+
*
|
|
11
|
+
* 1. o `public_uuid` da URL, que a requisicao ja provou conhecer para este
|
|
12
|
+
* adaptador sequer ser chamado;
|
|
13
|
+
* 2. a assinatura RSA do proprio SNS, verificada contra o certificado da AWS.
|
|
14
|
+
*
|
|
15
|
+
* A segunda existe porque a primeira e uma URL: ela vaza em log de proxy, em
|
|
16
|
+
* print de tela, em copiar-e-colar. Um evento de bounce forjado envenenaria o
|
|
17
|
+
* historico de entrega exatamente da tela que existe para ser confiavel.
|
|
18
|
+
*/
|
|
19
|
+
export declare class SesWebhookService implements OnModuleInit, IWebhookProtocolAdapter {
|
|
20
|
+
private readonly prisma;
|
|
21
|
+
private readonly protocolRegistry;
|
|
22
|
+
private readonly delivery;
|
|
23
|
+
private readonly logger;
|
|
24
|
+
private readonly certCache;
|
|
25
|
+
constructor(prisma: PrismaService, protocolRegistry: WebhookProtocolRegistry, delivery: MailDeliveryService);
|
|
26
|
+
onModuleInit(): void;
|
|
27
|
+
/** O SNS so faz POST; nao existe handshake por GET. */
|
|
28
|
+
verify(): Promise<WebhookProtocolResponse>;
|
|
29
|
+
handle(request: WebhookProtocolRequest): Promise<WebhookProtocolResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Sem este passo a subscription fica em PendingConfirmation para sempre e
|
|
32
|
+
* nenhum evento chega - a falha silenciosa classica desse setup, que parece
|
|
33
|
+
* "a AWS nao esta mandando nada".
|
|
34
|
+
*/
|
|
35
|
+
private confirmSubscription;
|
|
36
|
+
private handleNotification;
|
|
37
|
+
/**
|
|
38
|
+
* Confere que o evento veio do topico esperado.
|
|
39
|
+
*
|
|
40
|
+
* A assinatura prova apenas que a mensagem saiu do SNS da AWS - de qualquer
|
|
41
|
+
* conta, de qualquer topico. Sem esta checagem, quem descobrisse a URL poderia
|
|
42
|
+
* publicar bounces forjados no proprio topico e envenenar o historico de
|
|
43
|
+
* entrega justamente da tela que existe para ser confiavel.
|
|
44
|
+
*
|
|
45
|
+
* Com `sns_topic_arn` vazio o evento passa, com aviso: e o estado do setup
|
|
46
|
+
* inicial, antes de o topico existir. Preencher o campo no perfil e o que
|
|
47
|
+
* fecha a porta.
|
|
48
|
+
*/
|
|
49
|
+
private checkTopic;
|
|
50
|
+
/**
|
|
51
|
+
* O SNS envia `Content-Type: text/plain`, entao o body pode chegar como string
|
|
52
|
+
* mesmo com o parser de JSON configurado. Aceitar as duas formas evita depender
|
|
53
|
+
* de um detalhe do middleware.
|
|
54
|
+
*/
|
|
55
|
+
private readEnvelope;
|
|
56
|
+
private fetchCertificate;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=ses-webhook.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ses-webhook.service.d.ts","sourceRoot":"","sources":["../../src/mail-delivery/ses-webhook.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAA8B,YAAY,EAAc,MAAM,gBAAgB,CAAC;AACtF,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAe9D;;;;;;;;;;;;;GAaG;AACH,qBACa,iBAAkB,YAAW,YAAY,EAAE,uBAAuB;IAM3E,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAP3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAIpC,MAAM,EAAE,aAAa,EACrB,gBAAgB,EAAE,uBAAuB,EACzC,QAAQ,EAAE,mBAAmB;IAGhD,YAAY;IAIZ,uDAAuD;IACjD,MAAM,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAI1C,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAwC/E;;;;OAIG;YACW,mBAAmB;YA8BnB,kBAAkB;IAgBhC;;;;;;;;;;;OAWG;YACW,UAAU;IA6BxB;;;;OAIG;IACH,OAAO,CAAC,YAAY;YAwBN,gBAAgB;CAoB/B"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var SesWebhookService_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.SesWebhookService = void 0;
|
|
17
|
+
const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
18
|
+
const common_1 = require("@nestjs/common");
|
|
19
|
+
const webhook_protocol_registry_1 = require("../webhook-integration/webhook-protocol.registry");
|
|
20
|
+
const mail_delivery_service_1 = require("./mail-delivery.service");
|
|
21
|
+
const mail_delivery_constants_1 = require("./mail-delivery.constants");
|
|
22
|
+
const sns_message_util_1 = require("./sns-message.util");
|
|
23
|
+
/**
|
|
24
|
+
* 403 sem corpo: numa rota publica, dizer o motivo ajuda a mapear o que existe.
|
|
25
|
+
* O `logReason` fica so no log de chamadas, que exige login para ser lido.
|
|
26
|
+
*/
|
|
27
|
+
function forbidden(logReason) {
|
|
28
|
+
return { status: 403, contentType: 'text/plain', body: '', logReason };
|
|
29
|
+
}
|
|
30
|
+
/** Certificados da AWS mudam raramente; baixar um por notificacao seria absurdo. */
|
|
31
|
+
const CERT_CACHE_MAX = 8;
|
|
32
|
+
/**
|
|
33
|
+
* Eventos de entrega do Amazon SES, publicados via SNS, sobre o webhook publico
|
|
34
|
+
* do core.
|
|
35
|
+
*
|
|
36
|
+
* Duas camadas de credencial, como o resto dos adaptadores:
|
|
37
|
+
*
|
|
38
|
+
* 1. o `public_uuid` da URL, que a requisicao ja provou conhecer para este
|
|
39
|
+
* adaptador sequer ser chamado;
|
|
40
|
+
* 2. a assinatura RSA do proprio SNS, verificada contra o certificado da AWS.
|
|
41
|
+
*
|
|
42
|
+
* A segunda existe porque a primeira e uma URL: ela vaza em log de proxy, em
|
|
43
|
+
* print de tela, em copiar-e-colar. Um evento de bounce forjado envenenaria o
|
|
44
|
+
* historico de entrega exatamente da tela que existe para ser confiavel.
|
|
45
|
+
*/
|
|
46
|
+
let SesWebhookService = SesWebhookService_1 = class SesWebhookService {
|
|
47
|
+
constructor(prisma, protocolRegistry, delivery) {
|
|
48
|
+
this.prisma = prisma;
|
|
49
|
+
this.protocolRegistry = protocolRegistry;
|
|
50
|
+
this.delivery = delivery;
|
|
51
|
+
this.logger = new common_1.Logger(SesWebhookService_1.name);
|
|
52
|
+
this.certCache = new Map();
|
|
53
|
+
}
|
|
54
|
+
onModuleInit() {
|
|
55
|
+
this.protocolRegistry.register(mail_delivery_constants_1.SES_DELIVERY_WEBHOOK_PROTOCOL, this);
|
|
56
|
+
}
|
|
57
|
+
/** O SNS so faz POST; nao existe handshake por GET. */
|
|
58
|
+
async verify() {
|
|
59
|
+
return forbidden('GET not supported');
|
|
60
|
+
}
|
|
61
|
+
async handle(request) {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
const envelope = this.readEnvelope(request);
|
|
64
|
+
if (!envelope)
|
|
65
|
+
return forbidden('body is not an SNS envelope');
|
|
66
|
+
const signature = await (0, sns_message_util_1.verifySnsSignature)(envelope, (url) => this.fetchCertificate(url));
|
|
67
|
+
if (!signature.valid) {
|
|
68
|
+
this.logger.warn(`[ses] rejected webhook=${request.integration.id}: ${signature.reason}`);
|
|
69
|
+
return forbidden(`invalid SNS signature: ${signature.reason}`);
|
|
70
|
+
}
|
|
71
|
+
const topic = await this.checkTopic(request, envelope);
|
|
72
|
+
if (!topic.ok) {
|
|
73
|
+
this.logger.warn(`[ses] rejected webhook=${request.integration.id}: ${topic.reason}`);
|
|
74
|
+
return forbidden((_a = topic.reason) !== null && _a !== void 0 ? _a : 'topic mismatch');
|
|
75
|
+
}
|
|
76
|
+
switch (String(envelope.Type)) {
|
|
77
|
+
case 'SubscriptionConfirmation':
|
|
78
|
+
return this.confirmSubscription(envelope);
|
|
79
|
+
case 'UnsubscribeConfirmation':
|
|
80
|
+
this.logger.warn(`[ses] subscription removed from topic ${(_b = envelope.TopicArn) !== null && _b !== void 0 ? _b : '?'}`);
|
|
81
|
+
return { status: 200, body: { ok: true, type: 'UnsubscribeConfirmation' } };
|
|
82
|
+
case 'Notification':
|
|
83
|
+
return this.handleNotification(envelope);
|
|
84
|
+
default:
|
|
85
|
+
return forbidden(`unsupported SNS type "${envelope.Type}"`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Sem este passo a subscription fica em PendingConfirmation para sempre e
|
|
90
|
+
* nenhum evento chega - a falha silenciosa classica desse setup, que parece
|
|
91
|
+
* "a AWS nao esta mandando nada".
|
|
92
|
+
*/
|
|
93
|
+
async confirmSubscription(envelope) {
|
|
94
|
+
var _a;
|
|
95
|
+
const url = String((_a = envelope.SubscribeURL) !== null && _a !== void 0 ? _a : '');
|
|
96
|
+
// Mesma trava do certificado: seguir uma URL escolhida por quem chama
|
|
97
|
+
// transformaria este endpoint num buscador de URLs arbitrarias.
|
|
98
|
+
if (!(0, sns_message_util_1.isAwsSigningUrl)(url)) {
|
|
99
|
+
return forbidden('SubscribeURL is not an AWS SNS endpoint');
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const response = await fetch(url, { method: 'GET' });
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
this.logger.error(`[ses] subscription confirmation failed with HTTP ${response.status}`);
|
|
105
|
+
return { status: 502, body: { ok: false, reason: 'confirmation-failed' } };
|
|
106
|
+
}
|
|
107
|
+
this.logger.log(`[ses] subscription confirmed for topic ${envelope.TopicArn}`);
|
|
108
|
+
return { status: 200, body: { ok: true, type: 'SubscriptionConfirmation' } };
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
this.logger.error(`[ses] subscription confirmation error: ${error === null || error === void 0 ? void 0 : error.message}`);
|
|
112
|
+
return { status: 502, body: { ok: false, reason: 'confirmation-error' } };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async handleNotification(envelope) {
|
|
116
|
+
var _a;
|
|
117
|
+
let payload;
|
|
118
|
+
try {
|
|
119
|
+
// `Message` e uma string com o JSON do evento: a dupla serializacao e do
|
|
120
|
+
// protocolo do SNS.
|
|
121
|
+
payload = JSON.parse(String((_a = envelope.Message) !== null && _a !== void 0 ? _a : ''));
|
|
122
|
+
}
|
|
123
|
+
catch (_b) {
|
|
124
|
+
return { status: 400, body: { ok: false, reason: 'invalid-message-json' } };
|
|
125
|
+
}
|
|
126
|
+
const result = await this.delivery.ingestSesNotification(payload);
|
|
127
|
+
return { status: 200, body: Object.assign({ ok: true }, result) };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Confere que o evento veio do topico esperado.
|
|
131
|
+
*
|
|
132
|
+
* A assinatura prova apenas que a mensagem saiu do SNS da AWS - de qualquer
|
|
133
|
+
* conta, de qualquer topico. Sem esta checagem, quem descobrisse a URL poderia
|
|
134
|
+
* publicar bounces forjados no proprio topico e envenenar o historico de
|
|
135
|
+
* entrega justamente da tela que existe para ser confiavel.
|
|
136
|
+
*
|
|
137
|
+
* Com `sns_topic_arn` vazio o evento passa, com aviso: e o estado do setup
|
|
138
|
+
* inicial, antes de o topico existir. Preencher o campo no perfil e o que
|
|
139
|
+
* fecha a porta.
|
|
140
|
+
*/
|
|
141
|
+
async checkTopic(request, envelope) {
|
|
142
|
+
var _a, _b, _c;
|
|
143
|
+
const profileId = request.integration.integration_profile_id;
|
|
144
|
+
if (!profileId)
|
|
145
|
+
return { ok: true };
|
|
146
|
+
const profile = await this.prisma.integration_profile.findUnique({
|
|
147
|
+
where: { id: profileId },
|
|
148
|
+
select: { config: true },
|
|
149
|
+
});
|
|
150
|
+
const expected = String((_b = (_a = profile === null || profile === void 0 ? void 0 : profile.config) === null || _a === void 0 ? void 0 : _a.sns_topic_arn) !== null && _b !== void 0 ? _b : '').trim();
|
|
151
|
+
if (!expected) {
|
|
152
|
+
this.logger.warn(`[ses] profile ${profileId} has no sns_topic_arn: accepting events from any SNS topic`);
|
|
153
|
+
return { ok: true };
|
|
154
|
+
}
|
|
155
|
+
const received = String((_c = envelope.TopicArn) !== null && _c !== void 0 ? _c : '').trim();
|
|
156
|
+
return received === expected
|
|
157
|
+
? { ok: true }
|
|
158
|
+
: { ok: false, reason: 'TopicArn does not match the configured topic' };
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* O SNS envia `Content-Type: text/plain`, entao o body pode chegar como string
|
|
162
|
+
* mesmo com o parser de JSON configurado. Aceitar as duas formas evita depender
|
|
163
|
+
* de um detalhe do middleware.
|
|
164
|
+
*/
|
|
165
|
+
readEnvelope(request) {
|
|
166
|
+
const body = request.body;
|
|
167
|
+
if (body && typeof body === 'object' && !Buffer.isBuffer(body)) {
|
|
168
|
+
const envelope = body;
|
|
169
|
+
return envelope.Type ? envelope : null;
|
|
170
|
+
}
|
|
171
|
+
const raw = typeof body === 'string'
|
|
172
|
+
? body
|
|
173
|
+
: request.rawBody
|
|
174
|
+
? request.rawBody.toString('utf8')
|
|
175
|
+
: '';
|
|
176
|
+
if (!raw)
|
|
177
|
+
return null;
|
|
178
|
+
try {
|
|
179
|
+
const parsed = JSON.parse(raw);
|
|
180
|
+
return (parsed === null || parsed === void 0 ? void 0 : parsed.Type) ? parsed : null;
|
|
181
|
+
}
|
|
182
|
+
catch (_a) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async fetchCertificate(url) {
|
|
187
|
+
const cached = this.certCache.get(url);
|
|
188
|
+
if (cached)
|
|
189
|
+
return cached;
|
|
190
|
+
const response = await fetch(url);
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
throw new Error(`HTTP ${response.status}`);
|
|
193
|
+
}
|
|
194
|
+
const pem = await response.text();
|
|
195
|
+
// Cache pequeno com descarte do mais antigo: a URL do certificado muda de
|
|
196
|
+
// tempos em tempos e um Map sem teto viraria vazamento lento.
|
|
197
|
+
if (this.certCache.size >= CERT_CACHE_MAX) {
|
|
198
|
+
const oldest = this.certCache.keys().next().value;
|
|
199
|
+
if (oldest)
|
|
200
|
+
this.certCache.delete(oldest);
|
|
201
|
+
}
|
|
202
|
+
this.certCache.set(url, pem);
|
|
203
|
+
return pem;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
exports.SesWebhookService = SesWebhookService;
|
|
207
|
+
exports.SesWebhookService = SesWebhookService = SesWebhookService_1 = __decorate([
|
|
208
|
+
(0, common_1.Injectable)(),
|
|
209
|
+
__param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_prisma_1.PrismaService))),
|
|
210
|
+
__metadata("design:paramtypes", [api_prisma_1.PrismaService,
|
|
211
|
+
webhook_protocol_registry_1.WebhookProtocolRegistry,
|
|
212
|
+
mail_delivery_service_1.MailDeliveryService])
|
|
213
|
+
], SesWebhookService);
|
|
214
|
+
//# sourceMappingURL=ses-webhook.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ses-webhook.service.js","sourceRoot":"","sources":["../../src/mail-delivery/ses-webhook.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Envelope do SNS. `Message` e uma string com o JSON do evento de verdade -
|
|
3
|
+
* dupla serializacao e do protocolo, nao um engano.
|
|
4
|
+
*/
|
|
5
|
+
export type SnsEnvelope = {
|
|
6
|
+
Type?: string;
|
|
7
|
+
MessageId?: string;
|
|
8
|
+
TopicArn?: string;
|
|
9
|
+
Subject?: string;
|
|
10
|
+
Message?: string;
|
|
11
|
+
Timestamp?: string;
|
|
12
|
+
Token?: string;
|
|
13
|
+
SubscribeURL?: string;
|
|
14
|
+
SignatureVersion?: string;
|
|
15
|
+
Signature?: string;
|
|
16
|
+
SigningCertURL?: string;
|
|
17
|
+
SigningCertUrl?: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* So a AWS pode ser a origem do certificado.
|
|
21
|
+
*
|
|
22
|
+
* Sem esta trava, quem manda o webhook escolhe de onde baixamos a chave publica
|
|
23
|
+
* - e passa a poder assinar o que quiser. E a diferenca entre validar assinatura
|
|
24
|
+
* e encenar que valida.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isAwsSigningUrl(url: string): boolean;
|
|
27
|
+
/** Monta a string canonica `chave\nvalor\n` dos campos assinados. */
|
|
28
|
+
export declare function buildStringToSign(envelope: SnsEnvelope): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Verifica a assinatura do envelope contra o certificado da AWS.
|
|
31
|
+
*
|
|
32
|
+
* `certificateFetcher` e injetado para o teste nao depender de rede.
|
|
33
|
+
*/
|
|
34
|
+
export declare function verifySnsSignature(envelope: SnsEnvelope, certificateFetcher: (url: string) => Promise<string>): Promise<{
|
|
35
|
+
valid: boolean;
|
|
36
|
+
reason?: string;
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=sns-message.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sns-message.util.d.ts","sourceRoot":"","sources":["../../src/mail-delivery/sns-message.util.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAqBF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQpD;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAatE;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,WAAW,EACrB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GACnD,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA2C9C"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAwsSigningUrl = isAwsSigningUrl;
|
|
4
|
+
exports.buildStringToSign = buildStringToSign;
|
|
5
|
+
exports.verifySnsSignature = verifySnsSignature;
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
/**
|
|
8
|
+
* Campos que entram na string assinada, na ordem exata definida pela AWS.
|
|
9
|
+
* A ordem nao e alfabetica por acaso: e a especificacao, e trocar dois campos
|
|
10
|
+
* de lugar faz toda assinatura valida ser recusada.
|
|
11
|
+
*/
|
|
12
|
+
const SIGNED_KEYS = {
|
|
13
|
+
Notification: ['Message', 'MessageId', 'Subject', 'Timestamp', 'TopicArn', 'Type'],
|
|
14
|
+
SubscriptionConfirmation: [
|
|
15
|
+
'Message',
|
|
16
|
+
'MessageId',
|
|
17
|
+
'SubscribeURL',
|
|
18
|
+
'Timestamp',
|
|
19
|
+
'Token',
|
|
20
|
+
'TopicArn',
|
|
21
|
+
'Type',
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
SIGNED_KEYS.UnsubscribeConfirmation = SIGNED_KEYS.SubscriptionConfirmation;
|
|
25
|
+
/**
|
|
26
|
+
* So a AWS pode ser a origem do certificado.
|
|
27
|
+
*
|
|
28
|
+
* Sem esta trava, quem manda o webhook escolhe de onde baixamos a chave publica
|
|
29
|
+
* - e passa a poder assinar o que quiser. E a diferenca entre validar assinatura
|
|
30
|
+
* e encenar que valida.
|
|
31
|
+
*/
|
|
32
|
+
function isAwsSigningUrl(url) {
|
|
33
|
+
try {
|
|
34
|
+
const parsed = new URL(url);
|
|
35
|
+
if (parsed.protocol !== 'https:')
|
|
36
|
+
return false;
|
|
37
|
+
return /^sns\.[a-z0-9-]+\.amazonaws\.com(\.cn)?$/.test(parsed.hostname);
|
|
38
|
+
}
|
|
39
|
+
catch (_a) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Monta a string canonica `chave\nvalor\n` dos campos assinados. */
|
|
44
|
+
function buildStringToSign(envelope) {
|
|
45
|
+
var _a;
|
|
46
|
+
const keys = SIGNED_KEYS[String((_a = envelope.Type) !== null && _a !== void 0 ? _a : '')];
|
|
47
|
+
if (!keys)
|
|
48
|
+
return null;
|
|
49
|
+
let out = '';
|
|
50
|
+
for (const key of keys) {
|
|
51
|
+
const value = envelope[key];
|
|
52
|
+
// Campo ausente e pulado (o `Subject` costuma nao vir); presente e vazio
|
|
53
|
+
// entra, porque foi assim que a AWS assinou.
|
|
54
|
+
if (value === undefined || value === null)
|
|
55
|
+
continue;
|
|
56
|
+
out += `${key}\n${String(value)}\n`;
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Verifica a assinatura do envelope contra o certificado da AWS.
|
|
62
|
+
*
|
|
63
|
+
* `certificateFetcher` e injetado para o teste nao depender de rede.
|
|
64
|
+
*/
|
|
65
|
+
async function verifySnsSignature(envelope, certificateFetcher) {
|
|
66
|
+
var _a, _b, _c;
|
|
67
|
+
const certUrl = String((_b = (_a = envelope.SigningCertURL) !== null && _a !== void 0 ? _a : envelope.SigningCertUrl) !== null && _b !== void 0 ? _b : '');
|
|
68
|
+
if (!certUrl)
|
|
69
|
+
return { valid: false, reason: 'missing SigningCertURL' };
|
|
70
|
+
if (!isAwsSigningUrl(certUrl)) {
|
|
71
|
+
return { valid: false, reason: 'SigningCertURL is not an AWS SNS endpoint' };
|
|
72
|
+
}
|
|
73
|
+
if (!envelope.Signature)
|
|
74
|
+
return { valid: false, reason: 'missing Signature' };
|
|
75
|
+
const stringToSign = buildStringToSign(envelope);
|
|
76
|
+
if (!stringToSign) {
|
|
77
|
+
return { valid: false, reason: `unsupported SNS message type "${envelope.Type}"` };
|
|
78
|
+
}
|
|
79
|
+
// SignatureVersion 1 assina com SHA1; a 2, com SHA256. Qualquer outra e
|
|
80
|
+
// desconhecida e recusada em vez de adivinhada.
|
|
81
|
+
const version = String((_c = envelope.SignatureVersion) !== null && _c !== void 0 ? _c : '1');
|
|
82
|
+
const algorithm = version === '2' ? 'RSA-SHA256' : version === '1' ? 'RSA-SHA1' : null;
|
|
83
|
+
if (!algorithm) {
|
|
84
|
+
return { valid: false, reason: `unsupported SignatureVersion "${version}"` };
|
|
85
|
+
}
|
|
86
|
+
let certificate;
|
|
87
|
+
try {
|
|
88
|
+
certificate = await certificateFetcher(certUrl);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return {
|
|
92
|
+
valid: false,
|
|
93
|
+
reason: `could not fetch signing certificate: ${error === null || error === void 0 ? void 0 : error.message}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const verifier = (0, crypto_1.createVerify)(algorithm);
|
|
98
|
+
verifier.update(stringToSign, 'utf8');
|
|
99
|
+
const valid = verifier.verify(certificate, String(envelope.Signature), 'base64');
|
|
100
|
+
return valid ? { valid: true } : { valid: false, reason: 'signature mismatch' };
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
return {
|
|
104
|
+
valid: false,
|
|
105
|
+
reason: `signature check failed: ${error === null || error === void 0 ? void 0 : error.message}`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=sns-message.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sns-message.util.js","sourceRoot":"","sources":["../../src/mail-delivery/sns-message.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,11 @@ import { PaginationDTO } from '@hed-hog/api-pagination';
|
|
|
2
2
|
export declare class QueryMailSentListDTO extends PaginationDTO {
|
|
3
3
|
status?: 'all' | 'received' | 'read' | 'error';
|
|
4
4
|
hasError?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Desfecho reportado pelo provedor. `pending` e a ausencia de desfecho: ele
|
|
7
|
+
* aceitou a mensagem e nao disse mais nada.
|
|
8
|
+
*/
|
|
9
|
+
deliveryStatus?: 'all' | 'pending' | 'delivered' | 'bounced' | 'complained' | 'rejected';
|
|
5
10
|
recipientEmail?: string;
|
|
6
11
|
createdAtFrom?: string;
|
|
7
12
|
createdAtTo?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-mail-sent-list.dto.d.ts","sourceRoot":"","sources":["../../../src/mail-sent/dto/query-mail-sent-list.dto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAIxD,qBAAa,oBAAqB,SAAQ,aAAa;IAIrD,MAAM,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IAK/C,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"query-mail-sent-list.dto.d.ts","sourceRoot":"","sources":["../../../src/mail-sent/dto/query-mail-sent-list.dto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAIxD,qBAAa,oBAAqB,SAAQ,aAAa;IAIrD,MAAM,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IAK/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IAIH,cAAc,CAAC,EACX,KAAK,GACL,SAAS,GACT,WAAW,GACX,SAAS,GACT,YAAY,GACZ,UAAU,CAAC;IAKf,cAAc,CAAC,EAAE,MAAM,CAAC;IAKxB,aAAa,CAAC,EAAE,MAAM,CAAC;IAKvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -28,6 +28,12 @@ __decorate([
|
|
|
28
28
|
(0, class_validator_1.IsString)(),
|
|
29
29
|
__metadata("design:type", String)
|
|
30
30
|
], QueryMailSentListDTO.prototype, "hasError", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_validator_1.IsOptional)(),
|
|
33
|
+
(0, class_transformer_1.Transform)(({ value }) => String(value !== null && value !== void 0 ? value : '').trim().toLowerCase()),
|
|
34
|
+
(0, class_validator_1.IsIn)(['all', 'pending', 'delivered', 'bounced', 'complained', 'rejected']),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], QueryMailSentListDTO.prototype, "deliveryStatus", void 0);
|
|
31
37
|
__decorate([
|
|
32
38
|
(0, class_validator_1.IsOptional)(),
|
|
33
39
|
(0, class_transformer_1.Transform)(({ value }) => String(value !== null && value !== void 0 ? value : '').trim()),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-mail-sent-list.dto.js","sourceRoot":"","sources":["../../../src/mail-sent/dto/query-mail-sent-list.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4DAAwD;AACxD,yDAA8C;AAC9C,qDAA6D;AAE7D,MAAa,oBAAqB,SAAQ,8BAAa;
|
|
1
|
+
{"version":3,"file":"query-mail-sent-list.dto.js","sourceRoot":"","sources":["../../../src/mail-sent/dto/query-mail-sent-list.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4DAAwD;AACxD,yDAA8C;AAC9C,qDAA6D;AAE7D,MAAa,oBAAqB,SAAQ,8BAAa;CAwCtD;AAxCD,oDAwCC;AApCC;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClE,IAAA,sBAAI,EAAC,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;;oDACI;AAK/C;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClE,IAAA,0BAAQ,GAAE;;sDACO;AASlB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClE,IAAA,sBAAI,EAAC,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;;4DAO5D;AAKf;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAA,0BAAQ,GAAE;;4DACa;AAKxB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAA,0BAAQ,GAAE;;2DACY;AAKvB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,6BAAS,EAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAA,0BAAQ,GAAE;;yDACU"}
|