@hed-hog/core 0.0.387 → 0.0.393
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -11
- 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 +11 -6
- 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-attachment.fragments.d.ts +23 -0
- package/dist/ai/ai-attachment.fragments.d.ts.map +1 -0
- package/dist/ai/ai-attachment.fragments.js +34 -0
- package/dist/ai/ai-attachment.fragments.js.map +1 -0
- package/dist/ai/ai.controller.d.ts +12 -17
- 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.prompts.d.ts +16 -0
- package/dist/ai/ai.prompts.d.ts.map +1 -0
- package/dist/ai/ai.prompts.js +37 -0
- package/dist/ai/ai.prompts.js.map +1 -0
- package/dist/ai/ai.service.d.ts +92 -12
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +309 -88
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai/dto/chat.dto.d.ts +4 -1
- package/dist/ai/dto/chat.dto.d.ts.map +1 -1
- package/dist/ai/dto/chat.dto.js +23 -1
- package/dist/ai/dto/chat.dto.js.map +1 -1
- package/dist/ai/dto/create-agent.dto.d.ts +1 -1
- package/dist/ai/dto/create-agent.dto.d.ts.map +1 -1
- package/dist/ai/dto/create-agent.dto.js +1 -1
- package/dist/ai/dto/create-agent.dto.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/dto/update-agent.dto.d.ts +1 -1
- package/dist/ai/dto/update-agent.dto.d.ts.map +1 -1
- package/dist/ai/dto/update-agent.dto.js +1 -1
- package/dist/ai/dto/update-agent.dto.js.map +1 -1
- 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 +59 -5
- package/dist/ai-instruction/ai-instruction.controller.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.controller.js +63 -20
- package/dist/ai-instruction/ai-instruction.controller.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.module.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.module.js +13 -2
- package/dist/ai-instruction/ai-instruction.module.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.d.ts +131 -6
- package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.js +533 -60
- package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
- package/dist/ai-instruction/ai-prompt-builder.service.d.ts +8 -0
- package/dist/ai-instruction/ai-prompt-builder.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-prompt-builder.service.js +10 -1
- package/dist/ai-instruction/ai-prompt-builder.service.js.map +1 -1
- package/dist/ai-instruction/ai-prompt-registry.d.ts +45 -0
- package/dist/ai-instruction/ai-prompt-registry.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-registry.js +49 -0
- package/dist/ai-instruction/ai-prompt-registry.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +89 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js +222 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-template.util.d.ts +70 -0
- package/dist/ai-instruction/ai-prompt-template.util.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-template.util.js +154 -0
- package/dist/ai-instruction/ai-prompt-template.util.js.map +1 -0
- package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts +5 -0
- package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts.map +1 -1
- package/dist/ai-instruction/dto/create-ai-instruction.dto.js +27 -1
- package/dist/ai-instruction/dto/create-ai-instruction.dto.js.map +1 -1
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts +14 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts.map +1 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.js +42 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.js.map +1 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts +11 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts.map +1 -1
- package/dist/ai-instruction/dto/update-ai-instruction.dto.js +34 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.js.map +1 -1
- package/dist/ai-instruction/types/ai-instruction.types.d.ts +13 -1
- package/dist/ai-instruction/types/ai-instruction.types.d.ts.map +1 -1
- package/dist/ai-instruction/types/ai-instruction.types.js +10 -0
- package/dist/ai-instruction/types/ai-instruction.types.js.map +1 -1
- package/dist/auth/auth.controller.d.ts +89 -15
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +116 -44
- 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 +169 -12
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +314 -67
- 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/captcha/captcha.module.d.ts +3 -0
- package/dist/captcha/captcha.module.d.ts.map +1 -0
- package/dist/captcha/captcha.module.js +23 -0
- package/dist/captcha/captcha.module.js.map +1 -0
- package/dist/captcha/captcha.service.d.ts +38 -0
- package/dist/captcha/captcha.service.d.ts.map +1 -0
- package/dist/captcha/captcha.service.js +144 -0
- package/dist/captcha/captcha.service.js.map +1 -0
- package/dist/challenge/challenge.service.d.ts +31 -9
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +111 -16
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/core.module.d.ts +3 -1
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +46 -2
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +21 -21
- package/dist/dashboard/dashboard/dashboard.service.d.ts +21 -21
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +10 -10
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +10 -10
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +20 -20
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +20 -20
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +3 -3
- 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/dashboard/dashboard-role/dashboard-role.controller.d.ts +13 -13
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +13 -13
- 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 +134 -1
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +363 -12
- 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/incident/incident-notifier.service.d.ts +36 -0
- package/dist/incident/incident-notifier.service.d.ts.map +1 -0
- package/dist/incident/incident-notifier.service.js +208 -0
- package/dist/incident/incident-notifier.service.js.map +1 -0
- package/dist/incident/incident.controller.d.ts +23 -0
- package/dist/incident/incident.controller.d.ts.map +1 -0
- package/dist/incident/incident.controller.js +75 -0
- package/dist/incident/incident.controller.js.map +1 -0
- package/dist/incident/incident.module.d.ts +7 -0
- package/dist/incident/incident.module.d.ts.map +1 -0
- package/dist/incident/incident.module.js +32 -0
- package/dist/incident/incident.module.js.map +1 -0
- package/dist/incident/incident.service.d.ts +72 -0
- package/dist/incident/incident.service.d.ts.map +1 -0
- package/dist/incident/incident.service.js +184 -0
- package/dist/incident/incident.service.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -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/dto/test.dto.d.ts +13 -0
- package/dist/integration-profile/dto/test.dto.d.ts.map +1 -0
- package/dist/integration-profile/dto/test.dto.js +26 -0
- package/dist/integration-profile/dto/test.dto.js.map +1 -0
- package/dist/integration-profile/integration-profile.controller.d.ts +12 -1
- package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.controller.js +9 -1
- package/dist/integration-profile/integration-profile.controller.js.map +1 -1
- package/dist/integration-profile/integration-profile.module.d.ts +6 -1
- package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.module.js +26 -3
- package/dist/integration-profile/integration-profile.module.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +12 -1
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +26 -7
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +94 -91
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +27 -1
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +46 -5
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/ai.testers.d.ts +3 -0
- package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/ai.testers.js +125 -0
- package/dist/integration-profile/testers/ai.testers.js.map +1 -0
- package/dist/integration-profile/testers/captcha.testers.d.ts +3 -0
- package/dist/integration-profile/testers/captcha.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/captcha.testers.js +121 -0
- package/dist/integration-profile/testers/captcha.testers.js.map +1 -0
- package/dist/integration-profile/testers/email.testers.d.ts +3 -0
- package/dist/integration-profile/testers/email.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/email.testers.js +156 -0
- package/dist/integration-profile/testers/email.testers.js.map +1 -0
- package/dist/integration-profile/testers/http-probe.d.ts +57 -0
- package/dist/integration-profile/testers/http-probe.d.ts.map +1 -0
- package/dist/integration-profile/testers/http-probe.js +140 -0
- package/dist/integration-profile/testers/http-probe.js.map +1 -0
- package/dist/integration-profile/testers/index.d.ts +12 -0
- package/dist/integration-profile/testers/index.d.ts.map +1 -0
- package/dist/integration-profile/testers/index.js +45 -0
- package/dist/integration-profile/testers/index.js.map +1 -0
- package/dist/integration-profile/testers/infrastructure.testers.d.ts +3 -0
- package/dist/integration-profile/testers/infrastructure.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/infrastructure.testers.js +105 -0
- package/dist/integration-profile/testers/infrastructure.testers.js.map +1 -0
- package/dist/integration-profile/testers/integration-tester.registry.d.ts +17 -0
- package/dist/integration-profile/testers/integration-tester.registry.d.ts.map +1 -0
- package/dist/integration-profile/testers/integration-tester.registry.js +52 -0
- package/dist/integration-profile/testers/integration-tester.registry.js.map +1 -0
- package/dist/integration-profile/testers/integration-tester.types.d.ts +55 -0
- package/dist/integration-profile/testers/integration-tester.types.d.ts.map +1 -0
- package/dist/integration-profile/testers/integration-tester.types.js +16 -0
- package/dist/integration-profile/testers/integration-tester.types.js.map +1 -0
- package/dist/integration-profile/testers/messaging.testers.d.ts +3 -0
- package/dist/integration-profile/testers/messaging.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/messaging.testers.js +70 -0
- package/dist/integration-profile/testers/messaging.testers.js.map +1 -0
- package/dist/integration-profile/testers/oauth.testers.d.ts +3 -0
- package/dist/integration-profile/testers/oauth.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/oauth.testers.js +285 -0
- package/dist/integration-profile/testers/oauth.testers.js.map +1 -0
- package/dist/integration-profile/testers/payment.testers.d.ts +3 -0
- package/dist/integration-profile/testers/payment.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/payment.testers.js +169 -0
- package/dist/integration-profile/testers/payment.testers.js.map +1 -0
- package/dist/integration-profile/testers/storage.testers.d.ts +3 -0
- package/dist/integration-profile/testers/storage.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/storage.testers.js +208 -0
- package/dist/integration-profile/testers/storage.testers.js.map +1 -0
- package/dist/language/en.json +15 -2
- package/dist/language/pt.json +15 -2
- package/dist/leaked-password/leaked-password.controller.d.ts +24 -0
- package/dist/leaked-password/leaked-password.controller.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.controller.js +78 -0
- package/dist/leaked-password/leaked-password.controller.js.map +1 -0
- package/dist/leaked-password/leaked-password.module.d.ts +8 -0
- package/dist/leaked-password/leaked-password.module.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.module.js +31 -0
- package/dist/leaked-password/leaked-password.module.js.map +1 -0
- package/dist/leaked-password/leaked-password.service.d.ts +64 -0
- package/dist/leaked-password/leaked-password.service.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.service.js +218 -0
- package/dist/leaked-password/leaked-password.service.js.map +1 -0
- package/dist/locale/locale.controller.d.ts +1 -1
- package/dist/locale/locale.service.d.ts +1 -1
- package/dist/mail/dto/preview.dto.d.ts +18 -0
- package/dist/mail/dto/preview.dto.d.ts.map +1 -0
- package/dist/mail/dto/preview.dto.js +66 -0
- package/dist/mail/dto/preview.dto.js.map +1 -0
- package/dist/mail/dto/send.dto.d.ts +44 -0
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js +20 -0
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.controller.d.ts +5 -0
- package/dist/mail/mail.controller.d.ts.map +1 -1
- package/dist/mail/mail.controller.js +16 -2
- package/dist/mail/mail.controller.js.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 +69 -4
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +278 -37
- 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-layout/dto/update.dto.d.ts +17 -0
- package/dist/mail-layout/dto/update.dto.d.ts.map +1 -0
- package/dist/mail-layout/dto/update.dto.js +27 -0
- package/dist/mail-layout/dto/update.dto.js.map +1 -0
- package/dist/mail-layout/mail-layout.controller.d.ts +15 -0
- package/dist/mail-layout/mail-layout.controller.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.controller.js +71 -0
- package/dist/mail-layout/mail-layout.controller.js.map +1 -0
- package/dist/mail-layout/mail-layout.module.d.ts +3 -0
- package/dist/mail-layout/mail-layout.module.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.module.js +35 -0
- package/dist/mail-layout/mail-layout.module.js.map +1 -0
- package/dist/mail-layout/mail-layout.service.d.ts +27 -0
- package/dist/mail-layout/mail-layout.service.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.service.js +80 -0
- package/dist/mail-layout/mail-layout.service.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/mcp-chat/mcp-chat.controller.d.ts +2 -2
- package/dist/mcp-chat/mcp-chat.service.d.ts +24 -2
- package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +80 -24
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- 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/menu/menu.controller.d.ts +3 -3
- package/dist/menu/menu.service.d.ts +3 -3
- 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/notification/notification.controller.d.ts +12 -12
- package/dist/notification/notification.service.d.ts +12 -12
- package/dist/oauth/oauth-token-broker.service.d.ts +72 -0
- package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -0
- package/dist/oauth/oauth-token-broker.service.js +258 -0
- package/dist/oauth/oauth-token-broker.service.js.map +1 -0
- package/dist/oauth/oauth.module.d.ts.map +1 -1
- package/dist/oauth/oauth.module.js +3 -1
- package/dist/oauth/oauth.module.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +2 -0
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +6 -3
- package/dist/oauth/oauth.service.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 +11 -6
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +60 -20
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/presence/presence.controller.d.ts +16 -0
- package/dist/presence/presence.controller.d.ts.map +1 -0
- package/dist/presence/presence.controller.js +60 -0
- package/dist/presence/presence.controller.js.map +1 -0
- package/dist/presence/presence.listener.d.ts +29 -0
- package/dist/presence/presence.listener.d.ts.map +1 -0
- package/dist/presence/presence.listener.js +82 -0
- package/dist/presence/presence.listener.js.map +1 -0
- package/dist/presence/presence.module.d.ts +3 -0
- package/dist/presence/presence.module.d.ts.map +1 -0
- package/dist/presence/presence.module.js +32 -0
- package/dist/presence/presence.module.js.map +1 -0
- package/dist/presence/presence.service.d.ts +42 -0
- package/dist/presence/presence.service.d.ts.map +1 -0
- package/dist/presence/presence.service.js +147 -0
- package/dist/presence/presence.service.js.map +1 -0
- package/dist/profile/dto/delete-account.dto.d.ts +8 -0
- package/dist/profile/dto/delete-account.dto.d.ts.map +1 -0
- package/dist/profile/dto/delete-account.dto.js +22 -0
- package/dist/profile/dto/delete-account.dto.js.map +1 -0
- package/dist/profile/events/profile-account-deleted.event.d.ts +12 -0
- package/dist/profile/events/profile-account-deleted.event.d.ts.map +1 -0
- package/dist/profile/events/profile-account-deleted.event.js +17 -0
- package/dist/profile/events/profile-account-deleted.event.js.map +1 -0
- package/dist/profile/profile.controller.d.ts +32 -15
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.controller.js +75 -46
- package/dist/profile/profile.controller.js.map +1 -1
- package/dist/profile/profile.service.d.ts +41 -18
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +133 -48
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/realtime/realtime.gateway.d.ts +48 -0
- package/dist/realtime/realtime.gateway.d.ts.map +1 -0
- package/dist/realtime/realtime.gateway.js +156 -0
- package/dist/realtime/realtime.gateway.js.map +1 -0
- package/dist/realtime/realtime.module.d.ts +8 -0
- package/dist/realtime/realtime.module.d.ts.map +1 -0
- package/dist/realtime/realtime.module.js +29 -0
- package/dist/realtime/realtime.module.js.map +1 -0
- package/dist/realtime/realtime.service.d.ts +51 -0
- package/dist/realtime/realtime.service.d.ts.map +1 -0
- package/dist/realtime/realtime.service.js +177 -0
- package/dist/realtime/realtime.service.js.map +1 -0
- package/dist/redis/redis-pubsub.d.ts +27 -0
- package/dist/redis/redis-pubsub.d.ts.map +1 -0
- package/dist/redis/redis-pubsub.js +184 -0
- package/dist/redis/redis-pubsub.js.map +1 -0
- 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/role/role.controller.d.ts +3 -3
- package/dist/role/role.service.d.ts +3 -3
- 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/dto/create.dto.d.ts.map +1 -1
- package/dist/setting/dto/create.dto.js +9 -2
- package/dist/setting/dto/create.dto.js.map +1 -1
- package/dist/setting/setting.controller.d.ts +5 -5
- 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 +41 -5
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +113 -1
- 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/dto/create-with-email-and-password.dto.d.ts +2 -0
- package/dist/user/dto/create-with-email-and-password.dto.d.ts.map +1 -1
- package/dist/user/dto/create-with-email-and-password.dto.js +5 -0
- package/dist/user/dto/create-with-email-and-password.dto.js.map +1 -1
- package/dist/user/dto/query-user-mail-list.dto.d.ts +5 -0
- package/dist/user/dto/query-user-mail-list.dto.d.ts.map +1 -0
- package/dist/user/dto/query-user-mail-list.dto.js +25 -0
- package/dist/user/dto/query-user-mail-list.dto.js.map +1 -0
- package/dist/user/user-credential.util.d.ts +19 -0
- package/dist/user/user-credential.util.d.ts.map +1 -0
- package/dist/user/user-credential.util.js +32 -0
- package/dist/user/user-credential.util.js.map +1 -0
- package/dist/user/user.controller.d.ts +24 -26
- package/dist/user/user.controller.d.ts.map +1 -1
- package/dist/user/user.controller.js +18 -3
- package/dist/user/user.controller.js.map +1 -1
- package/dist/user/user.service.d.ts +71 -29
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +291 -17
- 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/validators/is-strong-password-with-settings.validator.d.ts.map +1 -1
- package/dist/validators/is-strong-password-with-settings.validator.js +11 -0
- package/dist/validators/is-strong-password-with-settings.validator.js.map +1 -1
- package/dist/validators/service-locator.d.ts +9 -0
- package/dist/validators/service-locator.d.ts.map +1 -1
- package/dist/validators/service-locator.js +12 -0
- package/dist/validators/service-locator.js.map +1 -1
- 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/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
- package/hedhog/data/integration_provider.yaml +25 -0
- package/hedhog/data/mail.yaml +275 -112
- package/hedhog/data/mail_layout.yaml +198 -0
- package/hedhog/data/menu.yaml +69 -3
- package/hedhog/data/role.yaml +16 -0
- package/hedhog/data/route.yaml +307 -3
- package/hedhog/data/setting_group.yaml +315 -1
- 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/mfa-setup-dialog.tsx.ejs +36 -0
- package/hedhog/frontend/app/account/components/profile-form.tsx.ejs +2 -1
- package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
- 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/hooks/use-mfa-setup.ts.ejs +10 -7
- package/hedhog/frontend/app/account/layout.tsx.ejs +2 -0
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
- package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
- package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
- package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
- package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
- package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
- package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
- package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -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 +410 -1223
- package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +153 -84
- package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +210 -3
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +292 -200
- package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
- package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
- package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
- package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
- package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
- package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
- package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
- package/hedhog/frontend/app/users/active-session.tsx.ejs +58 -11
- package/hedhog/frontend/app/users/page.tsx.ejs +186 -21
- 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 +250 -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-mails.tsx.ejs +399 -0
- package/hedhog/frontend/app/users/user-sheet.tsx.ejs +106 -99
- package/hedhog/frontend/messages/en.json +643 -49
- package/hedhog/frontend/messages/pt.json +643 -49
- package/hedhog/table/access_log.yaml +7 -0
- package/hedhog/table/ai_agent.yaml +1 -0
- package/hedhog/table/ai_instruction.yaml +15 -0
- package/hedhog/table/file.yaml +8 -0
- package/hedhog/table/leaked_password.yaml +18 -0
- package/hedhog/table/mail_delivery_event.yaml +76 -0
- package/hedhog/table/mail_layout.yaml +35 -0
- package/hedhog/table/mail_sent.yaml +23 -0
- package/hedhog/table/mail_var.yaml +4 -0
- package/hedhog/table/setting.yaml +1 -0
- package/hedhog/table/system_incident.yaml +59 -0
- package/hedhog/table/user_activity.yaml +9 -0
- package/hedhog/table/user_device.yaml +52 -0
- package/hedhog/table/user_presence.yaml +36 -0
- package/hedhog/table/user_session.yaml +20 -1
- package/package.json +7 -2
- package/src/access-log/access-log.controller.ts +1 -0
- package/src/access-log/access-log.interceptor.ts +9 -3
- 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-attachment.fragments.spec.ts +319 -0
- package/src/ai/ai-attachment.fragments.ts +35 -0
- package/src/ai/ai.controller.ts +9 -0
- package/src/ai/ai.module.ts +3 -2
- package/src/ai/ai.prompts.ts +38 -0
- package/src/ai/ai.service.spec.ts +280 -0
- package/src/ai/ai.service.ts +475 -82
- package/src/ai/dto/chat.dto.ts +33 -3
- package/src/ai/dto/create-agent.dto.ts +2 -2
- package/src/ai/dto/richtext-edit-html.dto.ts +11 -0
- package/src/ai/dto/update-agent.dto.ts +2 -2
- package/src/ai/richtext-ai.prompts.ts +57 -0
- package/src/ai/richtext-ai.service.ts +109 -0
- package/src/ai-instruction/ai-instruction.controller.ts +40 -9
- package/src/ai-instruction/ai-instruction.module.ts +13 -2
- package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
- package/src/ai-instruction/ai-instruction.service.ts +661 -62
- package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
- package/src/ai-instruction/ai-prompt-registry.ts +87 -0
- package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
- package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
- package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
- package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
- package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
- package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
- package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
- package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
- package/src/auth/auth.controller.ts +78 -13
- package/src/auth/auth.module.ts +2 -0
- package/src/auth/auth.service.spec.ts +386 -7
- package/src/auth/auth.service.ts +435 -81
- 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/captcha/captcha.module.ts +10 -0
- package/src/captcha/captcha.service.spec.ts +210 -0
- package/src/captcha/captcha.service.ts +191 -0
- package/src/challenge/challenge.service.spec.ts +112 -4
- package/src/challenge/challenge.service.ts +131 -17
- package/src/core.module.ts +46 -1
- package/src/file/file.controller.ts +54 -4
- package/src/file/file.service.spec.ts +275 -0
- package/src/file/file.service.ts +468 -16
- 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/incident/incident-notifier.service.spec.ts +205 -0
- package/src/incident/incident-notifier.service.ts +241 -0
- package/src/incident/incident.controller.ts +38 -0
- package/src/incident/incident.module.ts +19 -0
- package/src/incident/incident.service.spec.ts +150 -0
- package/src/incident/incident.service.ts +209 -0
- package/src/index.ts +58 -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/dto/test.dto.ts +19 -0
- package/src/integration-profile/integration-profile.controller.ts +10 -1
- package/src/integration-profile/integration-profile.module.spec.ts +51 -0
- package/src/integration-profile/integration-profile.module.ts +23 -4
- package/src/integration-profile/integration-profile.secrets.ts +12 -1
- package/src/integration-profile/integration-profile.service.spec.ts +279 -0
- package/src/integration-profile/integration-profile.service.ts +120 -124
- package/src/integration-profile/integration-profile.utils.spec.ts +22 -0
- package/src/integration-profile/integration-profile.utils.ts +78 -3
- package/src/integration-profile/testers/ai.testers.ts +165 -0
- package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
- package/src/integration-profile/testers/captcha.testers.ts +139 -0
- package/src/integration-profile/testers/email.testers.ts +194 -0
- package/src/integration-profile/testers/http-probe.spec.ts +153 -0
- package/src/integration-profile/testers/http-probe.ts +171 -0
- package/src/integration-profile/testers/index.ts +30 -0
- package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
- package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
- package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
- package/src/integration-profile/testers/integration-tester.types.ts +61 -0
- package/src/integration-profile/testers/messaging.testers.ts +102 -0
- package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
- package/src/integration-profile/testers/oauth.testers.ts +305 -0
- package/src/integration-profile/testers/payment.testers.ts +185 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
- package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
- package/src/integration-profile/testers/storage.testers.ts +226 -0
- package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
- package/src/language/en.json +15 -2
- package/src/language/pt.json +15 -2
- package/src/leaked-password/README.md +83 -0
- package/src/leaked-password/leaked-password.controller.ts +52 -0
- package/src/leaked-password/leaked-password.module.ts +18 -0
- package/src/leaked-password/leaked-password.service.ts +242 -0
- package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
- package/src/leaked-password/seed/common-passwords.txt +335 -0
- package/src/mail/dto/preview.dto.ts +50 -0
- package/src/mail/dto/send.dto.ts +58 -1
- package/src/mail/mail-template.spec.ts +274 -0
- package/src/mail/mail.controller.ts +9 -2
- package/src/mail/mail.module.ts +2 -0
- package/src/mail/mail.service.spec.ts +422 -6
- package/src/mail/mail.service.ts +337 -34
- 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-layout/dto/update.dto.ts +19 -0
- package/src/mail-layout/mail-layout.controller.ts +47 -0
- package/src/mail-layout/mail-layout.module.ts +22 -0
- package/src/mail-layout/mail-layout.service.ts +94 -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/mcp-chat/mcp-chat.service.spec.ts +236 -0
- package/src/mcp-chat/mcp-chat.service.ts +122 -26
- 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/oauth-token-broker.service.spec.ts +172 -0
- package/src/oauth/oauth-token-broker.service.ts +363 -0
- package/src/oauth/oauth.module.ts +3 -1
- package/src/oauth/oauth.service.ts +8 -2
- 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 +81 -24
- package/src/presence/presence.controller.ts +29 -0
- package/src/presence/presence.listener.ts +53 -0
- package/src/presence/presence.module.ts +19 -0
- package/src/presence/presence.service.spec.ts +97 -0
- package/src/presence/presence.service.ts +160 -0
- package/src/profile/dto/delete-account.dto.ts +11 -0
- package/src/profile/events/profile-account-deleted.event.ts +13 -0
- package/src/profile/profile.controller.ts +46 -34
- package/src/profile/profile.service.ts +164 -46
- package/src/realtime/realtime.gateway.ts +138 -0
- package/src/realtime/realtime.module.ts +16 -0
- package/src/realtime/realtime.service.spec.ts +50 -0
- package/src/realtime/realtime.service.ts +187 -0
- package/src/redis/redis-pubsub.ts +190 -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/dto/create.dto.ts +13 -2
- package/src/setting/setting.module.ts +3 -2
- package/src/setting/setting.service.spec.ts +135 -1
- package/src/setting/setting.service.ts +138 -2
- package/src/token/token.service.spec.ts +62 -0
- package/src/token/token.service.ts +57 -3
- package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
- package/src/user/dto/query-user-mail-list.dto.ts +10 -0
- package/src/user/user-credential.util.ts +35 -0
- package/src/user/user.controller.ts +17 -2
- package/src/user/user.service.spec.ts +186 -2
- package/src/user/user.service.ts +361 -16
- 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/validators/is-strong-password-with-settings.validator.ts +12 -0
- package/src/validators/service-locator.ts +15 -0
- package/src/webhook-integration/webhook-integration.service.ts +57 -3
- package/src/webhook-integration/webhook-protocol.registry.ts +6 -0
- package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +313 -0
package/src/file/file.service.ts
CHANGED
|
@@ -31,9 +31,12 @@ import {
|
|
|
31
31
|
OnModuleInit
|
|
32
32
|
} from '@nestjs/common';
|
|
33
33
|
import { JwtService } from '@nestjs/jwt';
|
|
34
|
+
import type { Request } from 'express';
|
|
34
35
|
import { createWriteStream, promises as fs } from 'fs';
|
|
35
|
-
import {
|
|
36
|
+
import { tmpdir } from 'os';
|
|
37
|
+
import { basename, dirname, extname, join } from 'path';
|
|
36
38
|
import { pipeline } from 'stream/promises';
|
|
39
|
+
import { v4 } from 'uuid';
|
|
37
40
|
import {
|
|
38
41
|
buildStorageConfigFromIntegration,
|
|
39
42
|
resolveFileProviderSlug,
|
|
@@ -41,15 +44,48 @@ import {
|
|
|
41
44
|
} from '../integration-profile/integration-profile.utils';
|
|
42
45
|
import { SettingService } from '../setting/setting.service';
|
|
43
46
|
import { DeleteDTO } from './dto/delete.dto';
|
|
44
|
-
import {
|
|
45
|
-
|
|
47
|
+
import {
|
|
48
|
+
ImageOptimizationService,
|
|
49
|
+
ImageVariantFormat,
|
|
50
|
+
} from './image-optimization.service';
|
|
51
|
+
import {
|
|
52
|
+
AbstractProvider,
|
|
53
|
+
supportsServerSideCopy,
|
|
54
|
+
} from './provider/abstract.provider';
|
|
46
55
|
import { ProviderFactory } from './provider/provider.factory';
|
|
47
56
|
|
|
57
|
+
type ResolvedProvider = {
|
|
58
|
+
provider: AbstractProvider;
|
|
59
|
+
providerId: number;
|
|
60
|
+
expiresAt: number;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolver o provider custa 3 queries (setting + integration_profile, que ainda decifra o
|
|
65
|
+
* config, + file_provider) e reconstrói o client de storage a cada arquivo. Em upload em
|
|
66
|
+
* massa — segmentos HLS, frames, pacotes SCORM — isso vira milhares de round-trips em
|
|
67
|
+
* rajadas paralelas e é o que estoura o pool de conexões durante a conversão de vídeo.
|
|
68
|
+
* A janela curta mantém a troca de perfil de storage praticamente imediata.
|
|
69
|
+
*/
|
|
70
|
+
const PROVIDER_CACHE_TTL_MS = Math.max(
|
|
71
|
+
0,
|
|
72
|
+
Number(process.env.FILE_PROVIDER_CACHE_TTL_MS ?? 30_000),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
/** Raw `?w=`/`?f=`/`?q=` query values for the public image endpoint. */
|
|
76
|
+
export type ImageVariantRequest = {
|
|
77
|
+
width?: number | string;
|
|
78
|
+
format?: string;
|
|
79
|
+
quality?: number | string;
|
|
80
|
+
};
|
|
81
|
+
|
|
48
82
|
@Injectable()
|
|
49
83
|
export class FileService implements OnModuleInit {
|
|
50
84
|
private readonly logger = new Logger(FileService.name);
|
|
51
85
|
private providerId: number | undefined;
|
|
52
86
|
private mimetypes: Record<string, number> = {};
|
|
87
|
+
private cachedProvider: ResolvedProvider | null = null;
|
|
88
|
+
private providerResolution: Promise<AbstractProvider> | null = null;
|
|
53
89
|
|
|
54
90
|
private resolveProviderPath(file: { location: string; path: string }): string {
|
|
55
91
|
// Supports legacy basename-only values while prioritizing full provider keys.
|
|
@@ -103,6 +139,26 @@ export class FileService implements OnModuleInit {
|
|
|
103
139
|
}
|
|
104
140
|
|
|
105
141
|
async getProvider(): Promise<AbstractProvider> {
|
|
142
|
+
const cached = this.cachedProvider;
|
|
143
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
144
|
+
this.providerId = cached.providerId;
|
|
145
|
+
return cached.provider;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Uploads paralelos (lotes de segmentos HLS) chegam aqui juntos; sem esta deduplicação
|
|
149
|
+
// cada um dispara o mesmo conjunto de queries em vez de aproveitar a primeira resolução.
|
|
150
|
+
if (this.providerResolution) {
|
|
151
|
+
return this.providerResolution;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
this.providerResolution = this.resolveProvider().finally(() => {
|
|
155
|
+
this.providerResolution = null;
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return this.providerResolution;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private async resolveProvider(): Promise<AbstractProvider> {
|
|
106
162
|
const settings = await this.settingService.getSettingValues(['file-storage-profile-id']);
|
|
107
163
|
const profileSlug = String(settings['file-storage-profile-id'] ?? '').trim();
|
|
108
164
|
|
|
@@ -143,7 +199,17 @@ export class FileService implements OnModuleInit {
|
|
|
143
199
|
}
|
|
144
200
|
|
|
145
201
|
this.providerId = providerData.id;
|
|
146
|
-
|
|
202
|
+
const provider = await ProviderFactory.create(enumProvider, config, this.jwtService);
|
|
203
|
+
|
|
204
|
+
if (PROVIDER_CACHE_TTL_MS > 0) {
|
|
205
|
+
this.cachedProvider = {
|
|
206
|
+
provider,
|
|
207
|
+
providerId: providerData.id,
|
|
208
|
+
expiresAt: Date.now() + PROVIDER_CACHE_TTL_MS,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return provider;
|
|
147
213
|
}
|
|
148
214
|
|
|
149
215
|
async getMimeType(mimetype: string) {
|
|
@@ -417,6 +483,50 @@ export class FileService implements OnModuleInit {
|
|
|
417
483
|
};
|
|
418
484
|
}
|
|
419
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Renderiza um cartão social 1200x630 (JPEG) a partir de arquivos do acervo.
|
|
488
|
+
*
|
|
489
|
+
* Devolve `null` quando não há arquivo utilizável — quem chama deve responder
|
|
490
|
+
* 404 e deixar o consumidor cair na imagem padrão da marca, nunca 500: do
|
|
491
|
+
* outro lado costuma haver um robô de link preview.
|
|
492
|
+
*/
|
|
493
|
+
async renderShareCard(options: {
|
|
494
|
+
backgroundFileId?: number | null;
|
|
495
|
+
overlayFileId?: number | null;
|
|
496
|
+
background?: string | null;
|
|
497
|
+
}): Promise<{ buffer: Buffer; contentType: string } | null> {
|
|
498
|
+
const load = async (fileId?: number | null): Promise<Buffer | null> => {
|
|
499
|
+
if (!fileId) return null;
|
|
500
|
+
try {
|
|
501
|
+
const { buffer } = await this.getBuffer(fileId);
|
|
502
|
+
return buffer;
|
|
503
|
+
} catch {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const [background, overlay] = await Promise.all([
|
|
509
|
+
load(options.backgroundFileId),
|
|
510
|
+
load(options.overlayFileId),
|
|
511
|
+
]);
|
|
512
|
+
|
|
513
|
+
if (!background && !overlay) {
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const buffer = await this.imageOptimizationService.composeShareCard(
|
|
518
|
+
background,
|
|
519
|
+
overlay,
|
|
520
|
+
{ background: options.background },
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
if (!buffer) {
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return { buffer, contentType: 'image/jpeg' };
|
|
528
|
+
}
|
|
529
|
+
|
|
420
530
|
async getLocalFile(fileId: number, res: any){
|
|
421
531
|
const { buffer, file } = await this.getBuffer(fileId);
|
|
422
532
|
res.set({
|
|
@@ -430,6 +540,15 @@ export class FileService implements OnModuleInit {
|
|
|
430
540
|
destination: string,
|
|
431
541
|
fileBuffer: MulterFile,
|
|
432
542
|
resize?: { maxWidth?: number; maxHeight?: number },
|
|
543
|
+
// Escape hatch para chamadores INTERNOS que já validaram por conta própria —
|
|
544
|
+
// o mesmo par de flags que `uploadFromPath` sempre teve. O FileController não
|
|
545
|
+
// repassa este argumento, então não há como acioná-lo por HTTP.
|
|
546
|
+
// `isPrivate` tira o arquivo das rotas que servem por id sem autenticação.
|
|
547
|
+
options?: {
|
|
548
|
+
skipMimeValidation?: boolean;
|
|
549
|
+
skipSizeValidation?: boolean;
|
|
550
|
+
isPrivate?: boolean;
|
|
551
|
+
},
|
|
433
552
|
) {
|
|
434
553
|
|
|
435
554
|
if (!fileBuffer) {
|
|
@@ -442,13 +561,16 @@ export class FileService implements OnModuleInit {
|
|
|
442
561
|
|
|
443
562
|
const provider = await this.getProvider();
|
|
444
563
|
|
|
445
|
-
if (
|
|
564
|
+
if (
|
|
565
|
+
!options?.skipMimeValidation &&
|
|
566
|
+
!(await this.acceptMimetypes(fileBuffer.mimetype))
|
|
567
|
+
) {
|
|
446
568
|
throw new BadRequestException(
|
|
447
569
|
`Invalid file type: ${fileBuffer.mimetype}`,
|
|
448
570
|
);
|
|
449
571
|
}
|
|
450
572
|
|
|
451
|
-
if (!(await this.maxFileSize(fileBuffer.size))) {
|
|
573
|
+
if (!options?.skipSizeValidation && !(await this.maxFileSize(fileBuffer.size))) {
|
|
452
574
|
throw new BadRequestException(`File too large: ${fileBuffer.size} bytes`);
|
|
453
575
|
}
|
|
454
576
|
|
|
@@ -487,6 +609,7 @@ export class FileService implements OnModuleInit {
|
|
|
487
609
|
location: destination,
|
|
488
610
|
mimetype_id: await this.getMimeType(optimized.mimetype),
|
|
489
611
|
size: optimized.buffer.length,
|
|
612
|
+
is_private: options?.isPrivate ?? false,
|
|
490
613
|
},
|
|
491
614
|
});
|
|
492
615
|
|
|
@@ -504,6 +627,10 @@ export class FileService implements OnModuleInit {
|
|
|
504
627
|
encoding?: string;
|
|
505
628
|
skipMimeValidation?: boolean;
|
|
506
629
|
skipSizeValidation?: boolean;
|
|
630
|
+
// Tira o arquivo das rotas que servem por id sem autenticação.
|
|
631
|
+
isPrivate?: boolean;
|
|
632
|
+
// Mesmo par maxWidth/maxHeight que `upload` aceita — só tem efeito em image/*.
|
|
633
|
+
resize?: { maxWidth?: number; maxHeight?: number };
|
|
507
634
|
},
|
|
508
635
|
) {
|
|
509
636
|
if (!filePath) {
|
|
@@ -559,6 +686,7 @@ export class FileService implements OnModuleInit {
|
|
|
559
686
|
location: destination,
|
|
560
687
|
mimetype_id: await this.getMimeType(mimetype),
|
|
561
688
|
size,
|
|
689
|
+
is_private: metadata?.isPrivate ?? false,
|
|
562
690
|
},
|
|
563
691
|
});
|
|
564
692
|
}
|
|
@@ -569,6 +697,10 @@ export class FileService implements OnModuleInit {
|
|
|
569
697
|
rawBuffer,
|
|
570
698
|
mimetype,
|
|
571
699
|
originalname,
|
|
700
|
+
{
|
|
701
|
+
maxWidth: metadata?.resize?.maxWidth,
|
|
702
|
+
maxHeight: metadata?.resize?.maxHeight,
|
|
703
|
+
},
|
|
572
704
|
);
|
|
573
705
|
|
|
574
706
|
const url = await provider.upload(destination, {
|
|
@@ -591,6 +723,7 @@ export class FileService implements OnModuleInit {
|
|
|
591
723
|
location: destination,
|
|
592
724
|
mimetype_id: await this.getMimeType(optimized.mimetype),
|
|
593
725
|
size: optimized.buffer.length,
|
|
726
|
+
is_private: metadata?.isPrivate ?? false,
|
|
594
727
|
},
|
|
595
728
|
});
|
|
596
729
|
|
|
@@ -747,10 +880,125 @@ export class FileService implements OnModuleInit {
|
|
|
747
880
|
return file;
|
|
748
881
|
}
|
|
749
882
|
|
|
883
|
+
/**
|
|
884
|
+
* Creates an independent copy of a stored file: new bytes in storage + a new `file` row.
|
|
885
|
+
*
|
|
886
|
+
* Unlike sharing a `file_id`, the result survives the original being deleted — which is what
|
|
887
|
+
* "duplicate files" means when copying course content between courses.
|
|
888
|
+
*
|
|
889
|
+
* `filename` and `destination` default to the source's, so a caller that only wants
|
|
890
|
+
* independent bytes gets them without thinking about paths. Passing `destination` matters for
|
|
891
|
+
* artifacts addressed by their location (HLS manifests and segments).
|
|
892
|
+
*
|
|
893
|
+
* The bytes are copied server-side when the active provider supports it; otherwise — and when
|
|
894
|
+
* the provider-side copy fails, e.g. an object above S3's 5GB CopyObject cap — they are
|
|
895
|
+
* streamed through a temp file, never buffered in RAM. Mime/size validation is skipped: the
|
|
896
|
+
* source already passed it at upload time.
|
|
897
|
+
*/
|
|
898
|
+
async duplicate(
|
|
899
|
+
fileId: number,
|
|
900
|
+
options?: { destination?: string; filename?: string },
|
|
901
|
+
) {
|
|
902
|
+
const source = await this.prismaService.file.findUnique({
|
|
903
|
+
where: { id: fileId },
|
|
904
|
+
include: { file_mimetype: true },
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
if (!source) {
|
|
908
|
+
throw new NotFoundException(`File not found: ${fileId}`);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
const destination = options?.destination ?? source.location;
|
|
912
|
+
const filename = options?.filename ?? source.filename;
|
|
913
|
+
const sourcePath = this.resolveProviderPath(source);
|
|
914
|
+
const provider = await this.getProvider();
|
|
915
|
+
|
|
916
|
+
let storedFilename: string | null = null;
|
|
917
|
+
|
|
918
|
+
if (supportsServerSideCopy(provider)) {
|
|
919
|
+
try {
|
|
920
|
+
storedFilename = await provider.copy(sourcePath, destination, filename);
|
|
921
|
+
} catch (error) {
|
|
922
|
+
this.logger.warn(
|
|
923
|
+
`Server-side copy failed for file ${fileId}, falling back to streaming: ${
|
|
924
|
+
error instanceof Error ? error.message : String(error)
|
|
925
|
+
}`,
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
if (storedFilename === null) {
|
|
931
|
+
const tempPath = join(tmpdir(), `hedhog-file-copy-${v4()}`);
|
|
932
|
+
try {
|
|
933
|
+
await this.downloadToPath(fileId, tempPath);
|
|
934
|
+
storedFilename = await provider.uploadFromPath(destination, tempPath, {
|
|
935
|
+
filename,
|
|
936
|
+
mimetype: source.file_mimetype?.name,
|
|
937
|
+
});
|
|
938
|
+
} finally {
|
|
939
|
+
await fs.unlink(tempPath).catch(() => undefined);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
return this.prismaService.file.create({
|
|
944
|
+
data: {
|
|
945
|
+
filename,
|
|
946
|
+
path: storedFilename,
|
|
947
|
+
provider_id: this.providerId,
|
|
948
|
+
location: destination,
|
|
949
|
+
mimetype_id: source.mimetype_id,
|
|
950
|
+
size: source.size ?? 0,
|
|
951
|
+
},
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
|
|
750
955
|
async readStream(filepath: string) {
|
|
751
956
|
return (await this.getProvider()).readStream(filepath);
|
|
752
957
|
}
|
|
753
958
|
|
|
959
|
+
/**
|
|
960
|
+
* Confere se os bytes de um `file` estão mesmo no storage, devolvendo o tamanho
|
|
961
|
+
* relatado pelo provider ao lado do tamanho declarado no banco.
|
|
962
|
+
*
|
|
963
|
+
* Existe para quem precisa **provar** que a cópia sobreviveu antes de apagar o
|
|
964
|
+
* original em outro lugar: o registro em banco sozinho não é prova, porque é
|
|
965
|
+
* gravado depois do upload e nada reconcilia os dois se o insert falhar no meio
|
|
966
|
+
* — o blob fica órfão ou a linha aponta para o vazio, e ninguém percebe até
|
|
967
|
+
* alguém tentar ler.
|
|
968
|
+
*
|
|
969
|
+
* Não lança quando o objeto está ausente: devolve `storedSize: null`, para o
|
|
970
|
+
* chamador decidir o que fazer com a divergência.
|
|
971
|
+
*/
|
|
972
|
+
async statStoredFile(
|
|
973
|
+
fileId: number,
|
|
974
|
+
): Promise<{ storedSize: number | null; declaredSize: number }> {
|
|
975
|
+
if (!fileId) {
|
|
976
|
+
throw new BadRequestException(`No file ID provided`);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
const file = await this.prismaService.file.findUnique({
|
|
980
|
+
where: { id: fileId },
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
if (!file) {
|
|
984
|
+
throw new NotFoundException(`File not found: ${fileId}`);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
const provider = await this.getProvider();
|
|
988
|
+
|
|
989
|
+
try {
|
|
990
|
+
const metadata = await provider.metaData(this.resolveProviderPath(file));
|
|
991
|
+
return {
|
|
992
|
+
storedSize: this.getFileSizeFromMetadata(metadata) ?? null,
|
|
993
|
+
declaredSize: Number(file.size ?? 0),
|
|
994
|
+
};
|
|
995
|
+
} catch {
|
|
996
|
+
// Qualquer falha de leitura de metadado — ausente, sem permissão, provider
|
|
997
|
+
// fora do ar — é tratada como "não deu para provar", nunca como sucesso.
|
|
998
|
+
return { storedSize: null, declaredSize: Number(file.size ?? 0) };
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
754
1002
|
private getFileSizeFromMetadata(metadata: any): number | undefined {
|
|
755
1003
|
if (!metadata) {
|
|
756
1004
|
return undefined;
|
|
@@ -853,13 +1101,25 @@ export class FileService implements OnModuleInit {
|
|
|
853
1101
|
* Resolves the file record and its storage metadata (mimetype + size) without
|
|
854
1102
|
* opening a read stream — so callers can answer a conditional 304 cheaply.
|
|
855
1103
|
*/
|
|
1104
|
+
/**
|
|
1105
|
+
* Metadados para servir um arquivo POR ID.
|
|
1106
|
+
*
|
|
1107
|
+
* Só os dois handlers anônimos passam por aqui (`serveFileById` e
|
|
1108
|
+
* `serveImageById`), e é por isso que a checagem de `is_private` mora neste
|
|
1109
|
+
* ponto e não em cada um: id de arquivo é sequencial, então servir por id é uma
|
|
1110
|
+
* porta enumerável. O caminho por token (`download`) não passa por aqui, então
|
|
1111
|
+
* um arquivo privado continua acessível ao admin via
|
|
1112
|
+
* `PUT /file/open/:id` -> token -> `GET /file/open/:token`.
|
|
1113
|
+
*/
|
|
856
1114
|
private async resolveFileMeta(locale: string, id: number) {
|
|
857
1115
|
const file = await this.prismaService.file.findFirst({
|
|
858
1116
|
where: { id },
|
|
859
1117
|
include: { file_mimetype: true },
|
|
860
1118
|
});
|
|
861
1119
|
|
|
862
|
-
|
|
1120
|
+
// Privado responde igual a inexistente: confirmar que o id existe já
|
|
1121
|
+
// entregaria metade do que a enumeração procura.
|
|
1122
|
+
if (!file || file.is_private) {
|
|
863
1123
|
throw new NotFoundException(
|
|
864
1124
|
getLocaleText('file.download.not_found', locale, `Not found: ${id}`),
|
|
865
1125
|
);
|
|
@@ -953,16 +1213,82 @@ export class FileService implements OnModuleInit {
|
|
|
953
1213
|
return mimetype ?? 'application/octet-stream';
|
|
954
1214
|
}
|
|
955
1215
|
|
|
1216
|
+
/**
|
|
1217
|
+
* Widths this endpoint is willing to render. An allowlist is required, not a
|
|
1218
|
+
* range check: the endpoint is `@Public()`, and an arbitrary width means
|
|
1219
|
+
* arbitrary CPU and an unbounded number of cache entries per file.
|
|
1220
|
+
*/
|
|
1221
|
+
private async getAllowedImageWidths(): Promise<number[]> {
|
|
1222
|
+
const DEFAULT_WIDTHS = [64, 128, 320, 400, 480, 640, 896, 1200];
|
|
1223
|
+
const settings = await this.settingService.getSettingValues(
|
|
1224
|
+
'image-resize-allowed-widths',
|
|
1225
|
+
);
|
|
1226
|
+
try {
|
|
1227
|
+
const parsed = JSON.parse(settings['image-resize-allowed-widths'] ?? '');
|
|
1228
|
+
const widths = (Array.isArray(parsed) ? parsed : [])
|
|
1229
|
+
.map((w: unknown) => Math.round(Number(w)))
|
|
1230
|
+
.filter((w: number) => Number.isFinite(w) && w > 0);
|
|
1231
|
+
return widths.length ? widths : DEFAULT_WIDTHS;
|
|
1232
|
+
} catch {
|
|
1233
|
+
return DEFAULT_WIDTHS;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Resolves the requested variant against the allowlist. Anything unknown or
|
|
1239
|
+
* out of the list collapses to "no variant", which serves the original bytes
|
|
1240
|
+
* instead of failing — a stale `?w=` in cached HTML must not 500.
|
|
1241
|
+
*/
|
|
1242
|
+
private async resolveImageVariant(variant?: ImageVariantRequest) {
|
|
1243
|
+
const width = Math.round(Number(variant?.width) || 0);
|
|
1244
|
+
if (width <= 0) return null;
|
|
1245
|
+
|
|
1246
|
+
const allowed = await this.getAllowedImageWidths();
|
|
1247
|
+
if (!allowed.includes(width)) return null;
|
|
1248
|
+
|
|
1249
|
+
const format = ['webp', 'jpeg', 'png', 'avif'].includes(
|
|
1250
|
+
String(variant?.format),
|
|
1251
|
+
)
|
|
1252
|
+
? (String(variant?.format) as ImageVariantFormat)
|
|
1253
|
+
: undefined;
|
|
1254
|
+
|
|
1255
|
+
const rawQuality = Math.round(Number(variant?.quality) || 0);
|
|
1256
|
+
const quality =
|
|
1257
|
+
rawQuality >= 50 && rawQuality <= 95 ? rawQuality : 80;
|
|
1258
|
+
|
|
1259
|
+
return { width, format, quality };
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
/** Absolute path of the on-disk cache entry for a rendered variant. */
|
|
1263
|
+
private imageVariantCachePath(
|
|
1264
|
+
id: number,
|
|
1265
|
+
size: number | undefined,
|
|
1266
|
+
width: number,
|
|
1267
|
+
format: string,
|
|
1268
|
+
quality: number,
|
|
1269
|
+
) {
|
|
1270
|
+
return join(
|
|
1271
|
+
tmpdir(),
|
|
1272
|
+
'hedhog-image-variants',
|
|
1273
|
+
`${id}-${size ?? 0}-w${width}-${format}-q${quality}`,
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
956
1277
|
/**
|
|
957
1278
|
* Serves an image by id with strong, immutable HTTP caching. The content of a
|
|
958
1279
|
* given fileId never changes (a new upload yields a new id), so the ETag is
|
|
959
1280
|
* derived from id+size instead of hashing the buffer, keeping it streaming.
|
|
1281
|
+
*
|
|
1282
|
+
* With a `variant` (`?w=`), the bytes are resized before being sent and the
|
|
1283
|
+
* ETag carries the variant parameters — otherwise a conditional request for
|
|
1284
|
+
* one width would get a 304 while holding the bytes of another.
|
|
960
1285
|
*/
|
|
961
1286
|
async serveImageById(
|
|
962
1287
|
locale: string,
|
|
963
1288
|
id: number,
|
|
964
1289
|
ifNoneMatch: string | undefined,
|
|
965
1290
|
res: any,
|
|
1291
|
+
variant?: ImageVariantRequest,
|
|
966
1292
|
) {
|
|
967
1293
|
const { provider, providerPath, size, mimetype, filename } =
|
|
968
1294
|
await this.resolveFileMeta(locale, id);
|
|
@@ -984,26 +1310,122 @@ export class FileService implements OnModuleInit {
|
|
|
984
1310
|
);
|
|
985
1311
|
}
|
|
986
1312
|
|
|
987
|
-
const
|
|
1313
|
+
const resolved = await this.resolveImageVariant(variant);
|
|
1314
|
+
const variantSuffix = resolved
|
|
1315
|
+
? `-w${resolved.width}-${resolved.format ?? 'auto'}-q${resolved.quality}`
|
|
1316
|
+
: '';
|
|
1317
|
+
const etag = `"img-${id}-${size ?? 0}${variantSuffix}"`;
|
|
988
1318
|
if (ifNoneMatch && ifNoneMatch === etag) {
|
|
989
1319
|
res.status(304).end();
|
|
990
1320
|
return;
|
|
991
1321
|
}
|
|
992
1322
|
|
|
993
1323
|
const ttl = await this.getCacheTtl('image-cache-ttl-seconds', 2592000);
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1324
|
+
const cacheControl = `public, max-age=${ttl}, immutable`;
|
|
1325
|
+
|
|
1326
|
+
if (resolved) {
|
|
1327
|
+
const rendered = await this.renderImageVariant(
|
|
1328
|
+
provider,
|
|
1329
|
+
providerPath,
|
|
1330
|
+
contentType,
|
|
1331
|
+
id,
|
|
1332
|
+
size,
|
|
1333
|
+
resolved,
|
|
1334
|
+
);
|
|
1335
|
+
// A null render (unsupported format, sharp failure) falls through to the
|
|
1336
|
+
// original bytes below rather than erroring the request.
|
|
1337
|
+
if (rendered) {
|
|
1338
|
+
const ext = rendered.mimetype.replace('image/', '');
|
|
1339
|
+
this.setInlineHeaders(
|
|
1340
|
+
res,
|
|
1341
|
+
`${basename(filename, extname(filename))}.${ext === 'jpeg' ? 'jpg' : ext}`,
|
|
1342
|
+
rendered.mimetype,
|
|
1343
|
+
rendered.buffer.length,
|
|
1344
|
+
cacheControl,
|
|
1345
|
+
etag,
|
|
1346
|
+
);
|
|
1347
|
+
res.end(rendered.buffer);
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
this.setInlineHeaders(res, filename, contentType, size, cacheControl, etag);
|
|
1002
1353
|
|
|
1003
1354
|
const stream = await provider.readStream(providerPath);
|
|
1004
1355
|
stream.pipe(res);
|
|
1005
1356
|
}
|
|
1006
1357
|
|
|
1358
|
+
/**
|
|
1359
|
+
* Produces (and memoizes on disk) a resized variant of a stored image.
|
|
1360
|
+
* The cache key includes the file size, so re-uploading under the same id —
|
|
1361
|
+
* which the storage layer does not normally do — cannot serve stale bytes.
|
|
1362
|
+
*/
|
|
1363
|
+
private async renderImageVariant(
|
|
1364
|
+
provider: any,
|
|
1365
|
+
providerPath: string,
|
|
1366
|
+
contentType: string,
|
|
1367
|
+
id: number,
|
|
1368
|
+
size: number | undefined,
|
|
1369
|
+
variant: { width: number; format?: ImageVariantFormat; quality: number },
|
|
1370
|
+
): Promise<{ buffer: Buffer; mimetype: string } | null> {
|
|
1371
|
+
const format =
|
|
1372
|
+
variant.format ??
|
|
1373
|
+
(contentType === 'image/png'
|
|
1374
|
+
? 'png'
|
|
1375
|
+
: contentType === 'image/webp'
|
|
1376
|
+
? 'webp'
|
|
1377
|
+
: contentType === 'image/avif'
|
|
1378
|
+
? 'avif'
|
|
1379
|
+
: 'jpeg');
|
|
1380
|
+
const cachePath = this.imageVariantCachePath(
|
|
1381
|
+
id,
|
|
1382
|
+
size,
|
|
1383
|
+
variant.width,
|
|
1384
|
+
format,
|
|
1385
|
+
variant.quality,
|
|
1386
|
+
);
|
|
1387
|
+
|
|
1388
|
+
try {
|
|
1389
|
+
const cached = await fs.readFile(cachePath);
|
|
1390
|
+
return { buffer: cached, mimetype: `image/${format}` };
|
|
1391
|
+
} catch {
|
|
1392
|
+
// Cache miss is the normal path on a cold pod; fall through and render.
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
try {
|
|
1396
|
+
const stream = await provider.readStream(providerPath);
|
|
1397
|
+
const chunks: Buffer[] = [];
|
|
1398
|
+
for await (const chunk of stream) {
|
|
1399
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1400
|
+
}
|
|
1401
|
+
const original = Buffer.concat(chunks);
|
|
1402
|
+
|
|
1403
|
+
const rendered = await this.imageOptimizationService.resizeBuffer(
|
|
1404
|
+
original,
|
|
1405
|
+
contentType,
|
|
1406
|
+
{ width: variant.width, format: variant.format, quality: variant.quality },
|
|
1407
|
+
);
|
|
1408
|
+
if (!rendered) return null;
|
|
1409
|
+
|
|
1410
|
+
try {
|
|
1411
|
+
await fs.mkdir(dirname(cachePath), { recursive: true });
|
|
1412
|
+
await fs.writeFile(cachePath, rendered.buffer);
|
|
1413
|
+
} catch (err) {
|
|
1414
|
+
// A read-only or full tmpdir must not break serving the image.
|
|
1415
|
+
this.logger.warn(
|
|
1416
|
+
`Could not cache image variant ${cachePath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
1417
|
+
);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
return { buffer: rendered.buffer, mimetype: rendered.mimetype };
|
|
1421
|
+
} catch (err) {
|
|
1422
|
+
this.logger.warn(
|
|
1423
|
+
`Could not render image variant for file ${id}: ${err instanceof Error ? err.message : String(err)}. Serving the original.`,
|
|
1424
|
+
);
|
|
1425
|
+
return null;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1007
1429
|
/**
|
|
1008
1430
|
* Serves any file by id with configurable HTTP caching (not immutable, shorter
|
|
1009
1431
|
* TTL than images). Used by the generic open endpoint's numeric-id branch.
|
|
@@ -1558,4 +1980,34 @@ export class FileService implements OnModuleInit {
|
|
|
1558
1980
|
},
|
|
1559
1981
|
);
|
|
1560
1982
|
}
|
|
1983
|
+
|
|
1984
|
+
/**
|
|
1985
|
+
* Base pública para URLs de arquivo devolvidas ao navegador.
|
|
1986
|
+
*
|
|
1987
|
+
* Não dá para derivar do `Host` da requisição: apps que falam com a API por
|
|
1988
|
+
* proxy interno (o class, via rewrite `/api` do Next) fazem o Nest enxergar o
|
|
1989
|
+
* Service do cluster, e a URL sai como `http://hub-api:3100/...` — inútil no
|
|
1990
|
+
* navegador. O setting `api-url` é a URL pública canônica da API no repo; o
|
|
1991
|
+
* `Host` fica só como fallback para ambientes sem o setting configurado.
|
|
1992
|
+
*/
|
|
1993
|
+
async resolvePublicBaseUrl(req: Request): Promise<string> {
|
|
1994
|
+
let configured = '';
|
|
1995
|
+
|
|
1996
|
+
try {
|
|
1997
|
+
const settings = await this.settingService.getSettingValues([
|
|
1998
|
+
'api-url',
|
|
1999
|
+
'url',
|
|
2000
|
+
]);
|
|
2001
|
+
const value = settings?.['api-url'] || settings?.['url'];
|
|
2002
|
+
configured = typeof value === 'string' ? value.trim() : '';
|
|
2003
|
+
} catch {
|
|
2004
|
+
configured = '';
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
if (/^https?:\/\/.+/i.test(configured)) {
|
|
2008
|
+
return configured.replace(/\/+$/, '');
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
return `${req.protocol}://${req.get('host')}`;
|
|
2012
|
+
}
|
|
1561
2013
|
}
|