@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 @@
|
|
|
1
|
+
{"version":3,"file":"impersonation.controller.js","sourceRoot":"","sources":["../../src/impersonation/impersonation.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modulo proprio, e nao mais um endpoint no AuthModule, porque a simulacao tem
|
|
3
|
+
* um ciclo de vida completo (emitir → resgatar → encerrar → auditar) e uma
|
|
4
|
+
* denylist de rotas que o RoleGuard consulta.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ImpersonationModule {
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=impersonation.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impersonation.module.d.ts","sourceRoot":"","sources":["../../src/impersonation/impersonation.module.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,qBAca,mBAAmB;CAAG"}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ImpersonationModule = void 0;
|
|
10
|
+
const api_pagination_1 = require("@hed-hog/api-pagination");
|
|
11
|
+
const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
12
|
+
const common_1 = require("@nestjs/common");
|
|
13
|
+
const security_module_1 = require("../security/security.module");
|
|
14
|
+
const session_module_1 = require("../session/session.module");
|
|
15
|
+
const setting_module_1 = require("../setting/setting.module");
|
|
16
|
+
const token_module_1 = require("../token/token.module");
|
|
17
|
+
const user_module_1 = require("../user/user.module");
|
|
18
|
+
const impersonation_controller_1 = require("./impersonation.controller");
|
|
19
|
+
const impersonation_service_1 = require("./impersonation.service");
|
|
20
|
+
/**
|
|
21
|
+
* Modulo proprio, e nao mais um endpoint no AuthModule, porque a simulacao tem
|
|
22
|
+
* um ciclo de vida completo (emitir → resgatar → encerrar → auditar) e uma
|
|
23
|
+
* denylist de rotas que o RoleGuard consulta.
|
|
24
|
+
*/
|
|
25
|
+
let ImpersonationModule = class ImpersonationModule {
|
|
26
|
+
};
|
|
27
|
+
exports.ImpersonationModule = ImpersonationModule;
|
|
28
|
+
exports.ImpersonationModule = ImpersonationModule = __decorate([
|
|
29
|
+
(0, common_1.Module)({
|
|
30
|
+
imports: [
|
|
31
|
+
(0, common_1.forwardRef)(() => api_prisma_1.PrismaModule),
|
|
32
|
+
(0, common_1.forwardRef)(() => security_module_1.SecurityModule),
|
|
33
|
+
(0, common_1.forwardRef)(() => setting_module_1.SettingModule),
|
|
34
|
+
(0, common_1.forwardRef)(() => token_module_1.TokenModule),
|
|
35
|
+
(0, common_1.forwardRef)(() => session_module_1.SessionModule),
|
|
36
|
+
(0, common_1.forwardRef)(() => user_module_1.UserModule),
|
|
37
|
+
(0, common_1.forwardRef)(() => api_pagination_1.PaginationModule),
|
|
38
|
+
],
|
|
39
|
+
controllers: [impersonation_controller_1.ImpersonationController],
|
|
40
|
+
providers: [impersonation_service_1.ImpersonationService],
|
|
41
|
+
exports: [impersonation_service_1.ImpersonationService],
|
|
42
|
+
})
|
|
43
|
+
], ImpersonationModule);
|
|
44
|
+
//# sourceMappingURL=impersonation.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impersonation.module.js","sourceRoot":"","sources":["../../src/impersonation/impersonation.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,4DAA2D;AAC3D,oDAAmD;AACnD,2CAAoD;AACpD,iEAA6D;AAC7D,8DAA0D;AAC1D,8DAA0D;AAC1D,wDAAoD;AACpD,qDAAiD;AACjD,yEAAqE;AACrE,mEAA+D;AAE/D;;;;GAIG;AAeI,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;CAAG,CAAA;AAAtB,kDAAmB;8BAAnB,mBAAmB;IAd/B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,yBAAY,CAAC;YAC9B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,gCAAc,CAAC;YAChC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,8BAAa,CAAC;YAC/B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,0BAAW,CAAC;YAC7B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,8BAAa,CAAC;YAC/B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,wBAAU,CAAC;YAC5B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,iCAAgB,CAAC;SACnC;QACD,WAAW,EAAE,CAAC,kDAAuB,CAAC;QACtC,SAAS,EAAE,CAAC,4CAAoB,CAAC;QACjC,OAAO,EAAE,CAAC,4CAAoB,CAAC;KAChC,CAAC;GACW,mBAAmB,CAAG"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
2
|
+
import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
|
|
3
|
+
import { SecurityService } from '../security/security.service';
|
|
4
|
+
import { SessionService } from '../session/session.service';
|
|
5
|
+
import { SettingService } from '../setting/setting.service';
|
|
6
|
+
import { TokenService } from '../token/token.service';
|
|
7
|
+
import { UserService } from '../user/user.service';
|
|
8
|
+
type StartParams = {
|
|
9
|
+
locale: string;
|
|
10
|
+
operatorUserId: number;
|
|
11
|
+
targetUserId: number;
|
|
12
|
+
app: string;
|
|
13
|
+
reason?: string | null;
|
|
14
|
+
isImpersonating: boolean;
|
|
15
|
+
ipAddress: string;
|
|
16
|
+
userAgent: string;
|
|
17
|
+
};
|
|
18
|
+
type RedeemParams = {
|
|
19
|
+
locale: string;
|
|
20
|
+
code: string;
|
|
21
|
+
ipAddress: string;
|
|
22
|
+
userAgent: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Simulacao de acesso: um operador ve o sistema como outro usuario, por uma
|
|
26
|
+
* janela curta, com tudo marcado como simulado.
|
|
27
|
+
*
|
|
28
|
+
* DESENHO EM DUAS ETAPAS. `start` nao devolve token nenhum — devolve um codigo
|
|
29
|
+
* de uso unico com TTL de 60s, que viaja no FRAGMENT da URL da aba nova
|
|
30
|
+
* (fragment nao chega ao servidor, entao nao entra em log de acesso nem em
|
|
31
|
+
* Referer). Quem cria a sessao e o `redeem`, na aba de destino. Assim a sessao
|
|
32
|
+
* do operador nunca e tocada: nenhum cookie `rt` e emitido, nenhum
|
|
33
|
+
* `localStorage` compartilhado e sobrescrito.
|
|
34
|
+
*
|
|
35
|
+
* A SESSAO E NAO RENOVAVEL POR CONSTRUCAO. `SessionService.createImpersonation`
|
|
36
|
+
* gera o token opaco e o descarta, entao nao existe refresh token para ela em
|
|
37
|
+
* lugar nenhum — e nao apenas "e proibido renovar".
|
|
38
|
+
*/
|
|
39
|
+
export declare class ImpersonationService {
|
|
40
|
+
private readonly prisma;
|
|
41
|
+
private readonly security;
|
|
42
|
+
private readonly setting;
|
|
43
|
+
private readonly token;
|
|
44
|
+
private readonly session;
|
|
45
|
+
private readonly user;
|
|
46
|
+
private readonly pagination;
|
|
47
|
+
private readonly logger;
|
|
48
|
+
/** Curto: o codigo so precisa sobreviver ao carregamento da aba nova. */
|
|
49
|
+
private readonly codeTtlMs;
|
|
50
|
+
/** Caminho da tela de resgate, igual nos tres apps. */
|
|
51
|
+
static readonly REDEEM_PATH = "/simulacao";
|
|
52
|
+
/**
|
|
53
|
+
* Simular quem ja e administrador nao ajuda em nada no suporte e transformaria
|
|
54
|
+
* o papel `admin-impersonation` num atalho para virar `admin`.
|
|
55
|
+
*/
|
|
56
|
+
private static readonly BLOCKED_TARGET_ROLES;
|
|
57
|
+
/**
|
|
58
|
+
* Apps com tela de resgate. `training` tem autenticacao propria e nao usa o
|
|
59
|
+
* @hed-hog/next-app-provider, entao ficou fora desta fase.
|
|
60
|
+
*/
|
|
61
|
+
private static readonly REDEEMABLE_APPS;
|
|
62
|
+
constructor(prisma: PrismaService, security: SecurityService, setting: SettingService, token: TokenService, session: SessionService, user: UserService, pagination: PaginationService);
|
|
63
|
+
start(params: StartParams): Promise<{
|
|
64
|
+
url: string;
|
|
65
|
+
expiresAt: string;
|
|
66
|
+
}>;
|
|
67
|
+
redeem(params: RedeemParams): Promise<{
|
|
68
|
+
accessToken: string;
|
|
69
|
+
expiresAt: string;
|
|
70
|
+
sessionId: number;
|
|
71
|
+
app: string;
|
|
72
|
+
operator: {
|
|
73
|
+
id: number;
|
|
74
|
+
name: string;
|
|
75
|
+
};
|
|
76
|
+
target: {
|
|
77
|
+
id: number;
|
|
78
|
+
name: string;
|
|
79
|
+
};
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Chamado pela propria sessao simulada, entao todos os identificadores vem do
|
|
83
|
+
* `request.auth` — nao ha parametro que permita encerrar sessao alheia.
|
|
84
|
+
*/
|
|
85
|
+
stop(params: {
|
|
86
|
+
sessionId: number | null;
|
|
87
|
+
targetUserId: number;
|
|
88
|
+
operatorUserId: number | null;
|
|
89
|
+
ipAddress?: string;
|
|
90
|
+
}): Promise<{
|
|
91
|
+
ended: boolean;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* Fonte de verdade do banner. A `sessionStorage` do cliente e so cache — e
|
|
95
|
+
* gravavel pelo proprio navegador, entao nao serve para decidir nada.
|
|
96
|
+
*/
|
|
97
|
+
currentSession(sessionId: number | null): Promise<{
|
|
98
|
+
active: false;
|
|
99
|
+
operator?: undefined;
|
|
100
|
+
target?: undefined;
|
|
101
|
+
reason?: undefined;
|
|
102
|
+
expiresAt?: undefined;
|
|
103
|
+
} | {
|
|
104
|
+
active: true;
|
|
105
|
+
operator: {
|
|
106
|
+
id: number;
|
|
107
|
+
name: string;
|
|
108
|
+
};
|
|
109
|
+
target: {
|
|
110
|
+
id: number;
|
|
111
|
+
name: string;
|
|
112
|
+
};
|
|
113
|
+
reason: string;
|
|
114
|
+
expiresAt: string;
|
|
115
|
+
}>;
|
|
116
|
+
/** Apps que o operador pode escolher como destino. */
|
|
117
|
+
listRedeemableApps(): Promise<{
|
|
118
|
+
key: string;
|
|
119
|
+
url: string;
|
|
120
|
+
}[]>;
|
|
121
|
+
history(paginationParams: PaginationDTO, filters: {
|
|
122
|
+
targetUserId?: number;
|
|
123
|
+
}): Promise<{
|
|
124
|
+
data: {
|
|
125
|
+
id: any;
|
|
126
|
+
app: any;
|
|
127
|
+
reason: any;
|
|
128
|
+
sessionId: any;
|
|
129
|
+
operator: {
|
|
130
|
+
id: number;
|
|
131
|
+
name: string;
|
|
132
|
+
};
|
|
133
|
+
target: {
|
|
134
|
+
id: number;
|
|
135
|
+
name: string;
|
|
136
|
+
};
|
|
137
|
+
issuedIp: any;
|
|
138
|
+
redeemedIp: any;
|
|
139
|
+
consumedAt: any;
|
|
140
|
+
endedAt: any;
|
|
141
|
+
expiresAt: any;
|
|
142
|
+
createdAt: any;
|
|
143
|
+
}[];
|
|
144
|
+
total: any;
|
|
145
|
+
lastPage: number;
|
|
146
|
+
page: number;
|
|
147
|
+
pageSize: number;
|
|
148
|
+
}>;
|
|
149
|
+
/**
|
|
150
|
+
* Concessoes nao resgatadas viram lixo em 60s. As consumidas ficam: sao a
|
|
151
|
+
* trilha de auditoria.
|
|
152
|
+
*/
|
|
153
|
+
purgeExpired(): Promise<void>;
|
|
154
|
+
private assertTargetIsEligible;
|
|
155
|
+
private resolveAppOrigin;
|
|
156
|
+
/**
|
|
157
|
+
* `app-urls` e uma lista de `chave=url`. Mesmo formato lido por
|
|
158
|
+
* `ChallengeService.resolveAppKeyFromOrigin` e `OAuthService`.
|
|
159
|
+
*/
|
|
160
|
+
private parseAppUrls;
|
|
161
|
+
private getUserPair;
|
|
162
|
+
}
|
|
163
|
+
export {};
|
|
164
|
+
//# sourceMappingURL=impersonation.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impersonation.service.d.ts","sourceRoot":"","sources":["../../src/impersonation/impersonation.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAU,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAW3E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAUF;;;;;;;;;;;;;;GAcG;AACH,qBACa,oBAAoB;IAuB7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAErB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAlC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAEhE,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IAEpC,uDAAuD;IACvD,MAAM,CAAC,QAAQ,CAAC,WAAW,gBAAgB;IAE3C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAoC;IAEhF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAkC;gBAItD,MAAM,EAAE,aAAa,EAErB,QAAQ,EAAE,eAAe,EAEzB,OAAO,EAAE,cAAc,EAEvB,KAAK,EAAE,YAAY,EAEnB,OAAO,EAAE,cAAc,EAEvB,IAAI,EAAE,WAAW,EAEjB,UAAU,EAAE,iBAAiB;IAO1C,KAAK,CAAC,MAAM,EAAE,WAAW;;;;IAyEzB,MAAM,CAAC,MAAM,EAAE,YAAY;;;;;;;;;;;;;;IA4GjC;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;;;IAoDD;;;OAGG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;IAkC7C,sDAAsD;IAChD,kBAAkB;;;;IASlB,OAAO,CAAC,gBAAgB,EAAE,aAAa,EAAE,OAAO,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;IAwDjF;;;OAGG;IAEG,YAAY;YAiBJ,sBAAsB;YA2CtB,gBAAgB;IA2B9B;;;OAGG;IACH,OAAO,CAAC,YAAY;YAgBN,WAAW;CAY1B"}
|
|
@@ -0,0 +1,408 @@
|
|
|
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 ImpersonationService_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ImpersonationService = void 0;
|
|
17
|
+
// `Prisma` vem de @hed-hog/api-prisma, nao de '@prisma/client': o tsconfig do
|
|
18
|
+
// monorepo mapeia '@prisma/client' para o client gerado, que nao expoe
|
|
19
|
+
// `Prisma.sql`. E a convencao do repo inteiro.
|
|
20
|
+
const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
21
|
+
const api_locale_1 = require("@hed-hog/api-locale");
|
|
22
|
+
const api_pagination_1 = require("@hed-hog/api-pagination");
|
|
23
|
+
const common_1 = require("@nestjs/common");
|
|
24
|
+
const schedule_1 = require("@nestjs/schedule");
|
|
25
|
+
const security_service_1 = require("../security/security.service");
|
|
26
|
+
const session_service_1 = require("../session/session.service");
|
|
27
|
+
const setting_service_1 = require("../setting/setting.service");
|
|
28
|
+
const token_service_1 = require("../token/token.service");
|
|
29
|
+
const user_service_1 = require("../user/user.service");
|
|
30
|
+
/**
|
|
31
|
+
* Simulacao de acesso: um operador ve o sistema como outro usuario, por uma
|
|
32
|
+
* janela curta, com tudo marcado como simulado.
|
|
33
|
+
*
|
|
34
|
+
* DESENHO EM DUAS ETAPAS. `start` nao devolve token nenhum — devolve um codigo
|
|
35
|
+
* de uso unico com TTL de 60s, que viaja no FRAGMENT da URL da aba nova
|
|
36
|
+
* (fragment nao chega ao servidor, entao nao entra em log de acesso nem em
|
|
37
|
+
* Referer). Quem cria a sessao e o `redeem`, na aba de destino. Assim a sessao
|
|
38
|
+
* do operador nunca e tocada: nenhum cookie `rt` e emitido, nenhum
|
|
39
|
+
* `localStorage` compartilhado e sobrescrito.
|
|
40
|
+
*
|
|
41
|
+
* A SESSAO E NAO RENOVAVEL POR CONSTRUCAO. `SessionService.createImpersonation`
|
|
42
|
+
* gera o token opaco e o descarta, entao nao existe refresh token para ela em
|
|
43
|
+
* lugar nenhum — e nao apenas "e proibido renovar".
|
|
44
|
+
*/
|
|
45
|
+
let ImpersonationService = ImpersonationService_1 = class ImpersonationService {
|
|
46
|
+
constructor(prisma, security, setting, token, session, user, pagination) {
|
|
47
|
+
this.prisma = prisma;
|
|
48
|
+
this.security = security;
|
|
49
|
+
this.setting = setting;
|
|
50
|
+
this.token = token;
|
|
51
|
+
this.session = session;
|
|
52
|
+
this.user = user;
|
|
53
|
+
this.pagination = pagination;
|
|
54
|
+
this.logger = new common_1.Logger(ImpersonationService_1.name);
|
|
55
|
+
/** Curto: o codigo so precisa sobreviver ao carregamento da aba nova. */
|
|
56
|
+
this.codeTtlMs = 60000;
|
|
57
|
+
}
|
|
58
|
+
// ==========================================
|
|
59
|
+
// Etapa 1 — emissao do codigo
|
|
60
|
+
// ==========================================
|
|
61
|
+
async start(params) {
|
|
62
|
+
var _a;
|
|
63
|
+
const { locale, operatorUserId, targetUserId } = params;
|
|
64
|
+
if (params.isImpersonating) {
|
|
65
|
+
throw new common_1.ForbiddenException((0, api_locale_1.getLocaleText)('impersonation.nested', locale, 'You cannot start an access simulation from inside another one.'));
|
|
66
|
+
}
|
|
67
|
+
if (operatorUserId === targetUserId) {
|
|
68
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('impersonation.self', locale, 'You cannot simulate your own access.'));
|
|
69
|
+
}
|
|
70
|
+
await this.assertTargetIsEligible(locale, targetUserId);
|
|
71
|
+
const origin = await this.resolveAppOrigin(locale, params.app);
|
|
72
|
+
const code = this.security.randomOpaque(32);
|
|
73
|
+
const codeHash = this.security.hashSha256(code);
|
|
74
|
+
const reason = ((_a = params.reason) === null || _a === void 0 ? void 0 : _a.trim()) ? params.reason.trim().slice(0, 255) : null;
|
|
75
|
+
const expiresAt = new Date(Date.now() + this.codeTtlMs);
|
|
76
|
+
const grant = await this.prisma.impersonation_grant.create({
|
|
77
|
+
data: {
|
|
78
|
+
code_hash: codeHash,
|
|
79
|
+
impersonator_user_id: operatorUserId,
|
|
80
|
+
target_user_id: targetUserId,
|
|
81
|
+
app: params.app,
|
|
82
|
+
reason,
|
|
83
|
+
issued_ip: params.ipAddress || null,
|
|
84
|
+
issued_user_agent: params.userAgent || null,
|
|
85
|
+
expires_at: expiresAt,
|
|
86
|
+
},
|
|
87
|
+
select: { id: true },
|
|
88
|
+
});
|
|
89
|
+
// A TENTATIVA ja vira auditoria, mesmo que o codigo nunca seja resgatado —
|
|
90
|
+
// pedir acesso a conta de alguem e o evento relevante, nao so consumi-lo.
|
|
91
|
+
await this.user.recordUserChange({
|
|
92
|
+
targetUserId,
|
|
93
|
+
actorUserId: operatorUserId,
|
|
94
|
+
action: 'impersonation_requested',
|
|
95
|
+
summary: `app=${params.app} grant=#${grant.id}${reason ? ` reason=${reason}` : ''}`,
|
|
96
|
+
ipAddress: params.ipAddress || null,
|
|
97
|
+
});
|
|
98
|
+
this.logger.log(`[Impersonation] grant=#${grant.id} operator=${operatorUserId} target=${targetUserId} app=${params.app} ip=${params.ipAddress}`);
|
|
99
|
+
return {
|
|
100
|
+
// O codigo vai no fragment: nunca chega ao servidor de destino, nao entra
|
|
101
|
+
// em access_log nem em Referer, e a tela de resgate o apaga com
|
|
102
|
+
// history.replaceState logo apos ler.
|
|
103
|
+
url: `${origin}${ImpersonationService_1.REDEEM_PATH}#code=${code}`,
|
|
104
|
+
expiresAt: expiresAt.toISOString(),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// ==========================================
|
|
108
|
+
// Etapa 2 — resgate na aba de destino
|
|
109
|
+
// ==========================================
|
|
110
|
+
async redeem(params) {
|
|
111
|
+
var _a;
|
|
112
|
+
const { locale } = params;
|
|
113
|
+
const codeHash = this.security.hashSha256((_a = params.code) !== null && _a !== void 0 ? _a : '');
|
|
114
|
+
// Consumo atomico: dois requests com o mesmo codigo — o caso de replay — so
|
|
115
|
+
// podem ter um vencedor, decidido pelo banco.
|
|
116
|
+
const rows = await this.prisma.$queryRaw(api_prisma_1.Prisma.sql `
|
|
117
|
+
UPDATE impersonation_grant
|
|
118
|
+
SET consumed_at = NOW(),
|
|
119
|
+
redeemed_ip = ${params.ipAddress || null},
|
|
120
|
+
redeemed_user_agent = ${params.userAgent || null}
|
|
121
|
+
WHERE code_hash = ${codeHash}
|
|
122
|
+
AND expires_at > NOW()
|
|
123
|
+
AND consumed_at IS NULL
|
|
124
|
+
RETURNING id, impersonator_user_id, target_user_id, app, reason
|
|
125
|
+
`);
|
|
126
|
+
const grant = rows[0];
|
|
127
|
+
if (!grant) {
|
|
128
|
+
// Uma mensagem so para todos os modos de falha (inexistente, expirado, ja
|
|
129
|
+
// usado): distingui-los entregaria um oraculo a quem tem so o codigo.
|
|
130
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('impersonation.invalidCode', locale, 'Invalid, expired or already used simulation code.'));
|
|
131
|
+
}
|
|
132
|
+
// Revalida: o alvo pode ter virado admin ou sido desativado dentro dos 60s.
|
|
133
|
+
await this.assertTargetIsEligible(locale, grant.target_user_id);
|
|
134
|
+
const settings = await this.setting.getSettingValues(['impersonation-session-minutes']);
|
|
135
|
+
const minutes = Number(settings['impersonation-session-minutes']) || 30;
|
|
136
|
+
const session = await this.session.createImpersonation(locale, grant.target_user_id, grant.impersonator_user_id, params.ipAddress, params.userAgent, minutes, grant.reason);
|
|
137
|
+
// `expiresIn` por chamada: o token precisa morrer junto com a sessao, nao
|
|
138
|
+
// aos 15 minutos globais do JwtModule (e nao ha refresh para renova-lo).
|
|
139
|
+
const accessToken = await this.token.createAccessToken({
|
|
140
|
+
sub: grant.target_user_id,
|
|
141
|
+
sessionId: session.id,
|
|
142
|
+
act: grant.impersonator_user_id,
|
|
143
|
+
imp: true,
|
|
144
|
+
}, { expiresIn: minutes * 60 });
|
|
145
|
+
await this.prisma.impersonation_grant.update({
|
|
146
|
+
where: { id: grant.id },
|
|
147
|
+
data: { session_id: session.id },
|
|
148
|
+
});
|
|
149
|
+
const [operator, target] = await this.getUserPair(grant.impersonator_user_id, grant.target_user_id);
|
|
150
|
+
await Promise.all([
|
|
151
|
+
this.user.registerUserActivity(grant.target_user_id, 'impersonationStarted', grant.impersonator_user_id),
|
|
152
|
+
this.user.registerUserActivity(grant.impersonator_user_id, 'impersonationPerformed', grant.target_user_id),
|
|
153
|
+
this.user.recordUserChange({
|
|
154
|
+
targetUserId: grant.target_user_id,
|
|
155
|
+
actorUserId: grant.impersonator_user_id,
|
|
156
|
+
action: 'impersonation_started',
|
|
157
|
+
summary: `app=${grant.app} session=#${session.id} expires=${session.expires_at.toISOString()}${grant.reason ? ` reason=${grant.reason}` : ''}`,
|
|
158
|
+
ipAddress: params.ipAddress || null,
|
|
159
|
+
}),
|
|
160
|
+
]);
|
|
161
|
+
this.logger.log(`[Impersonation] redeemed grant=#${grant.id} session=#${session.id} operator=${grant.impersonator_user_id} target=${grant.target_user_id} minutes=${minutes}`);
|
|
162
|
+
return {
|
|
163
|
+
accessToken,
|
|
164
|
+
expiresAt: session.expires_at.toISOString(),
|
|
165
|
+
sessionId: session.id,
|
|
166
|
+
app: grant.app,
|
|
167
|
+
operator,
|
|
168
|
+
target,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// ==========================================
|
|
172
|
+
// Encerrar
|
|
173
|
+
// ==========================================
|
|
174
|
+
/**
|
|
175
|
+
* Chamado pela propria sessao simulada, entao todos os identificadores vem do
|
|
176
|
+
* `request.auth` — nao ha parametro que permita encerrar sessao alheia.
|
|
177
|
+
*/
|
|
178
|
+
async stop(params) {
|
|
179
|
+
if (!params.sessionId || !params.operatorUserId) {
|
|
180
|
+
return { ended: false };
|
|
181
|
+
}
|
|
182
|
+
const revoked = await this.prisma.user_session.updateMany({
|
|
183
|
+
where: {
|
|
184
|
+
id: params.sessionId,
|
|
185
|
+
revoked_at: null,
|
|
186
|
+
impersonator_user_id: { not: null },
|
|
187
|
+
},
|
|
188
|
+
data: { revoked_at: new Date() },
|
|
189
|
+
});
|
|
190
|
+
await this.prisma.impersonation_grant.updateMany({
|
|
191
|
+
where: { session_id: params.sessionId, ended_at: null },
|
|
192
|
+
data: { ended_at: new Date() },
|
|
193
|
+
});
|
|
194
|
+
if (revoked.count > 0) {
|
|
195
|
+
await Promise.all([
|
|
196
|
+
this.user.registerUserActivity(params.targetUserId, 'impersonationEnded', params.operatorUserId),
|
|
197
|
+
this.user.registerUserActivity(params.operatorUserId, 'impersonationPerformedEnded', params.targetUserId),
|
|
198
|
+
this.user.recordUserChange({
|
|
199
|
+
targetUserId: params.targetUserId,
|
|
200
|
+
actorUserId: params.operatorUserId,
|
|
201
|
+
action: 'impersonation_ended',
|
|
202
|
+
summary: `session=#${params.sessionId}`,
|
|
203
|
+
ipAddress: params.ipAddress || null,
|
|
204
|
+
}),
|
|
205
|
+
]);
|
|
206
|
+
}
|
|
207
|
+
this.logger.log(`[Impersonation] stopped session=#${params.sessionId} operator=${params.operatorUserId} target=${params.targetUserId} revoked=${revoked.count}`);
|
|
208
|
+
return { ended: revoked.count > 0 };
|
|
209
|
+
}
|
|
210
|
+
// ==========================================
|
|
211
|
+
// Leitura
|
|
212
|
+
// ==========================================
|
|
213
|
+
/**
|
|
214
|
+
* Fonte de verdade do banner. A `sessionStorage` do cliente e so cache — e
|
|
215
|
+
* gravavel pelo proprio navegador, entao nao serve para decidir nada.
|
|
216
|
+
*/
|
|
217
|
+
async currentSession(sessionId) {
|
|
218
|
+
if (!sessionId) {
|
|
219
|
+
return { active: false };
|
|
220
|
+
}
|
|
221
|
+
const session = await this.prisma.user_session.findUnique({
|
|
222
|
+
where: { id: sessionId },
|
|
223
|
+
select: {
|
|
224
|
+
user_id: true,
|
|
225
|
+
impersonator_user_id: true,
|
|
226
|
+
impersonation_reason: true,
|
|
227
|
+
expires_at: true,
|
|
228
|
+
revoked_at: true,
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
if (!(session === null || session === void 0 ? void 0 : session.impersonator_user_id) || session.revoked_at) {
|
|
232
|
+
return { active: false };
|
|
233
|
+
}
|
|
234
|
+
const [operator, target] = await this.getUserPair(session.impersonator_user_id, session.user_id);
|
|
235
|
+
return {
|
|
236
|
+
active: true,
|
|
237
|
+
operator,
|
|
238
|
+
target,
|
|
239
|
+
reason: session.impersonation_reason,
|
|
240
|
+
expiresAt: session.expires_at.toISOString(),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/** Apps que o operador pode escolher como destino. */
|
|
244
|
+
async listRedeemableApps() {
|
|
245
|
+
const settings = await this.setting.getSettingValues(['app-urls']);
|
|
246
|
+
const entries = this.parseAppUrls(settings['app-urls']);
|
|
247
|
+
return ImpersonationService_1.REDEEMABLE_APPS.filter((key) => entries.has(key)).map((key) => ({ key, url: entries.get(key) }));
|
|
248
|
+
}
|
|
249
|
+
async history(paginationParams, filters) {
|
|
250
|
+
const where = {};
|
|
251
|
+
if (filters.targetUserId) {
|
|
252
|
+
where.target_user_id = filters.targetUserId;
|
|
253
|
+
}
|
|
254
|
+
const paginated = await this.pagination.paginatePrismaModel(this.prisma.impersonation_grant, Object.assign(Object.assign({}, paginationParams), { sortField: (paginationParams === null || paginationParams === void 0 ? void 0 : paginationParams.sortField) || 'created_at', sortOrder: (paginationParams === null || paginationParams === void 0 ? void 0 : paginationParams.sortOrder) || 'desc', validSortFields: ['id', 'created_at', 'consumed_at', 'ended_at'], where }));
|
|
255
|
+
const rows = (paginated.data || []);
|
|
256
|
+
const ids = [
|
|
257
|
+
...new Set(rows.flatMap((row) => [row.impersonator_user_id, row.target_user_id])),
|
|
258
|
+
].filter((id) => typeof id === 'number');
|
|
259
|
+
const users = ids.length
|
|
260
|
+
? await this.prisma.user.findMany({
|
|
261
|
+
where: { id: { in: ids } },
|
|
262
|
+
select: { id: true, name: true },
|
|
263
|
+
})
|
|
264
|
+
: [];
|
|
265
|
+
const byId = new Map(users.map((user) => [user.id, user]));
|
|
266
|
+
return Object.assign(Object.assign({}, paginated), { data: rows.map((row) => {
|
|
267
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
268
|
+
return ({
|
|
269
|
+
// `code_hash` nunca sai daqui.
|
|
270
|
+
id: row.id,
|
|
271
|
+
app: row.app,
|
|
272
|
+
reason: row.reason,
|
|
273
|
+
sessionId: row.session_id,
|
|
274
|
+
operator: (_a = byId.get(row.impersonator_user_id)) !== null && _a !== void 0 ? _a : null,
|
|
275
|
+
target: (_b = byId.get(row.target_user_id)) !== null && _b !== void 0 ? _b : null,
|
|
276
|
+
issuedIp: row.issued_ip,
|
|
277
|
+
redeemedIp: row.redeemed_ip,
|
|
278
|
+
consumedAt: (_e = (_d = (_c = row.consumed_at) === null || _c === void 0 ? void 0 : _c.toISOString) === null || _d === void 0 ? void 0 : _d.call(_c)) !== null && _e !== void 0 ? _e : null,
|
|
279
|
+
endedAt: (_h = (_g = (_f = row.ended_at) === null || _f === void 0 ? void 0 : _f.toISOString) === null || _g === void 0 ? void 0 : _g.call(_f)) !== null && _h !== void 0 ? _h : null,
|
|
280
|
+
expiresAt: (_l = (_k = (_j = row.expires_at) === null || _j === void 0 ? void 0 : _j.toISOString) === null || _k === void 0 ? void 0 : _k.call(_j)) !== null && _l !== void 0 ? _l : null,
|
|
281
|
+
createdAt: (_p = (_o = (_m = row.created_at) === null || _m === void 0 ? void 0 : _m.toISOString) === null || _o === void 0 ? void 0 : _o.call(_m)) !== null && _p !== void 0 ? _p : null,
|
|
282
|
+
});
|
|
283
|
+
}) });
|
|
284
|
+
}
|
|
285
|
+
// ==========================================
|
|
286
|
+
// Manutencao
|
|
287
|
+
// ==========================================
|
|
288
|
+
/**
|
|
289
|
+
* Concessoes nao resgatadas viram lixo em 60s. As consumidas ficam: sao a
|
|
290
|
+
* trilha de auditoria.
|
|
291
|
+
*/
|
|
292
|
+
async purgeExpired() {
|
|
293
|
+
const { count } = await this.prisma.impersonation_grant.deleteMany({
|
|
294
|
+
where: {
|
|
295
|
+
consumed_at: null,
|
|
296
|
+
expires_at: { lt: new Date(Date.now() - 24 * 60 * 60 * 1000) },
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
if (count > 0) {
|
|
300
|
+
this.logger.log(`[Impersonation] purged ${count} unredeemed grant(s)`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// ==========================================
|
|
304
|
+
// Helpers
|
|
305
|
+
// ==========================================
|
|
306
|
+
async assertTargetIsEligible(locale, targetUserId) {
|
|
307
|
+
const target = await this.prisma.user.findUnique({
|
|
308
|
+
where: { id: targetUserId },
|
|
309
|
+
select: {
|
|
310
|
+
id: true,
|
|
311
|
+
deactivated_at: true,
|
|
312
|
+
role_user: { select: { role: { select: { slug: true } } } },
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
if (!target) {
|
|
316
|
+
throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('userNotFound', locale, 'User not found'));
|
|
317
|
+
}
|
|
318
|
+
// Conta excluida pelo proprio usuario: os identificadores ja foram
|
|
319
|
+
// anonimizados, entao nao ha o que simular.
|
|
320
|
+
if (target.deactivated_at) {
|
|
321
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('impersonation.deactivatedTarget', locale, 'This account has been deactivated and cannot be simulated.'));
|
|
322
|
+
}
|
|
323
|
+
// Conta suspensa CONTINUA simulavel de proposito: "o usuario nao consegue
|
|
324
|
+
// entrar" e justamente o chamado de suporte mais comum.
|
|
325
|
+
const slugs = target.role_user.map((link) => { var _a; return (_a = link.role) === null || _a === void 0 ? void 0 : _a.slug; }).filter(Boolean);
|
|
326
|
+
if (slugs.some((slug) => ImpersonationService_1.BLOCKED_TARGET_ROLES.includes(slug))) {
|
|
327
|
+
throw new common_1.ForbiddenException((0, api_locale_1.getLocaleText)('impersonation.privilegedTarget', locale, 'Administrators cannot be simulated.'));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
async resolveAppOrigin(locale, app) {
|
|
331
|
+
if (!ImpersonationService_1.REDEEMABLE_APPS.includes(app)) {
|
|
332
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('impersonation.unknownApp', locale, 'This application does not support access simulation.'));
|
|
333
|
+
}
|
|
334
|
+
const settings = await this.setting.getSettingValues(['app-urls']);
|
|
335
|
+
const origin = this.parseAppUrls(settings['app-urls']).get(app);
|
|
336
|
+
if (!origin) {
|
|
337
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('impersonation.appNotConfigured', locale, 'This application has no URL configured in the app-urls setting.'));
|
|
338
|
+
}
|
|
339
|
+
return origin;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* `app-urls` e uma lista de `chave=url`. Mesmo formato lido por
|
|
343
|
+
* `ChallengeService.resolveAppKeyFromOrigin` e `OAuthService`.
|
|
344
|
+
*/
|
|
345
|
+
parseAppUrls(value) {
|
|
346
|
+
const entries = new Map();
|
|
347
|
+
const list = Array.isArray(value) ? value : [];
|
|
348
|
+
for (const entry of list) {
|
|
349
|
+
const separatorIndex = entry.indexOf('=');
|
|
350
|
+
if (separatorIndex === -1)
|
|
351
|
+
continue;
|
|
352
|
+
const key = entry.slice(0, separatorIndex).trim();
|
|
353
|
+
const url = entry.slice(separatorIndex + 1).trim().replace(/\/+$/, '');
|
|
354
|
+
if (key && url)
|
|
355
|
+
entries.set(key, url);
|
|
356
|
+
}
|
|
357
|
+
return entries;
|
|
358
|
+
}
|
|
359
|
+
async getUserPair(operatorId, targetId) {
|
|
360
|
+
var _a, _b;
|
|
361
|
+
const users = await this.prisma.user.findMany({
|
|
362
|
+
where: { id: { in: [operatorId, targetId] } },
|
|
363
|
+
select: { id: true, name: true },
|
|
364
|
+
});
|
|
365
|
+
const byId = new Map(users.map((user) => [user.id, user]));
|
|
366
|
+
return [
|
|
367
|
+
(_a = byId.get(operatorId)) !== null && _a !== void 0 ? _a : { id: operatorId, name: '' },
|
|
368
|
+
(_b = byId.get(targetId)) !== null && _b !== void 0 ? _b : { id: targetId, name: '' },
|
|
369
|
+
];
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
exports.ImpersonationService = ImpersonationService;
|
|
373
|
+
/** Caminho da tela de resgate, igual nos tres apps. */
|
|
374
|
+
ImpersonationService.REDEEM_PATH = '/simulacao';
|
|
375
|
+
/**
|
|
376
|
+
* Simular quem ja e administrador nao ajuda em nada no suporte e transformaria
|
|
377
|
+
* o papel `admin-impersonation` num atalho para virar `admin`.
|
|
378
|
+
*/
|
|
379
|
+
ImpersonationService.BLOCKED_TARGET_ROLES = ['admin', 'admin-impersonation'];
|
|
380
|
+
/**
|
|
381
|
+
* Apps com tela de resgate. `training` tem autenticacao propria e nao usa o
|
|
382
|
+
* @hed-hog/next-app-provider, entao ficou fora desta fase.
|
|
383
|
+
*/
|
|
384
|
+
ImpersonationService.REDEEMABLE_APPS = ['admin', 'class', 'partners'];
|
|
385
|
+
__decorate([
|
|
386
|
+
(0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_DAY_AT_4AM),
|
|
387
|
+
__metadata("design:type", Function),
|
|
388
|
+
__metadata("design:paramtypes", []),
|
|
389
|
+
__metadata("design:returntype", Promise)
|
|
390
|
+
], ImpersonationService.prototype, "purgeExpired", null);
|
|
391
|
+
exports.ImpersonationService = ImpersonationService = ImpersonationService_1 = __decorate([
|
|
392
|
+
(0, common_1.Injectable)(),
|
|
393
|
+
__param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_prisma_1.PrismaService))),
|
|
394
|
+
__param(1, (0, common_1.Inject)((0, common_1.forwardRef)(() => security_service_1.SecurityService))),
|
|
395
|
+
__param(2, (0, common_1.Inject)((0, common_1.forwardRef)(() => setting_service_1.SettingService))),
|
|
396
|
+
__param(3, (0, common_1.Inject)((0, common_1.forwardRef)(() => token_service_1.TokenService))),
|
|
397
|
+
__param(4, (0, common_1.Inject)((0, common_1.forwardRef)(() => session_service_1.SessionService))),
|
|
398
|
+
__param(5, (0, common_1.Inject)((0, common_1.forwardRef)(() => user_service_1.UserService))),
|
|
399
|
+
__param(6, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_pagination_1.PaginationService))),
|
|
400
|
+
__metadata("design:paramtypes", [api_prisma_1.PrismaService,
|
|
401
|
+
security_service_1.SecurityService,
|
|
402
|
+
setting_service_1.SettingService,
|
|
403
|
+
token_service_1.TokenService,
|
|
404
|
+
session_service_1.SessionService,
|
|
405
|
+
user_service_1.UserService,
|
|
406
|
+
api_pagination_1.PaginationService])
|
|
407
|
+
], ImpersonationService);
|
|
408
|
+
//# sourceMappingURL=impersonation.service.js.map
|