@hed-hog/core 0.0.398 → 0.0.400
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/dist/ai/ai-agent.sort.d.ts +6 -0
- package/dist/ai/ai-agent.sort.d.ts.map +1 -0
- package/dist/ai/ai-agent.sort.js +21 -0
- package/dist/ai/ai-agent.sort.js.map +1 -0
- package/dist/ai/ai.controller.d.ts +4 -4
- package/dist/ai/ai.service.d.ts +35 -4
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +51 -137
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.js +26 -23
- package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.sort.d.ts +16 -0
- package/dist/ai-instruction/ai-instruction.sort.d.ts.map +1 -0
- package/dist/ai-instruction/ai-instruction.sort.js +32 -0
- package/dist/ai-instruction/ai-instruction.sort.js.map +1 -0
- package/dist/auth/auth.controller.d.ts +24 -8
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +8 -1
- package/dist/auth/auth.module.js.map +1 -1
- package/dist/auth/auth.service.d.ts +72 -25
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +41 -4
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/guards/auth.guard.d.ts +3 -1
- package/dist/auth/guards/auth.guard.d.ts.map +1 -1
- package/dist/auth/guards/auth.guard.js +12 -3
- package/dist/auth/guards/auth.guard.js.map +1 -1
- package/dist/authorize/authorize.controller.d.ts +30 -6
- package/dist/authorize/authorize.controller.d.ts.map +1 -1
- package/dist/authorize/authorize.controller.js +120 -13
- package/dist/authorize/authorize.controller.js.map +1 -1
- package/dist/authorize/authorize.errors.d.ts +34 -0
- package/dist/authorize/authorize.errors.d.ts.map +1 -0
- package/dist/authorize/authorize.errors.js +37 -0
- package/dist/authorize/authorize.errors.js.map +1 -0
- package/dist/authorize/authorize.module.d.ts.map +1 -1
- package/dist/authorize/authorize.module.js +6 -1
- package/dist/authorize/authorize.module.js.map +1 -1
- package/dist/authorize/authorize.service.d.ts +78 -4
- package/dist/authorize/authorize.service.d.ts.map +1 -1
- package/dist/authorize/authorize.service.js +212 -21
- package/dist/authorize/authorize.service.js.map +1 -1
- package/dist/authorize/dto/authorize-info.dto.d.ts +10 -1
- package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -1
- package/dist/authorize/dto/authorize-info.dto.js +16 -1
- package/dist/authorize/dto/authorize-info.dto.js.map +1 -1
- package/dist/authorize/dto/consent.dto.d.ts +10 -1
- package/dist/authorize/dto/consent.dto.d.ts.map +1 -1
- package/dist/authorize/dto/consent.dto.js +16 -1
- package/dist/authorize/dto/consent.dto.js.map +1 -1
- package/dist/authorize/dto/token.dto.d.ts +12 -0
- package/dist/authorize/dto/token.dto.d.ts.map +1 -1
- package/dist/authorize/dto/token.dto.js +21 -1
- package/dist/authorize/dto/token.dto.js.map +1 -1
- package/dist/authorize/oauth-exception.filter.d.ts +17 -0
- package/dist/authorize/oauth-exception.filter.d.ts.map +1 -0
- package/dist/authorize/oauth-exception.filter.js +54 -0
- package/dist/authorize/oauth-exception.filter.js.map +1 -0
- package/dist/authorize/oauth-metadata.service.d.ts +39 -0
- package/dist/authorize/oauth-metadata.service.d.ts.map +1 -0
- package/dist/authorize/oauth-metadata.service.js +81 -0
- package/dist/authorize/oauth-metadata.service.js.map +1 -0
- package/dist/authorize/well-known.controller.d.ts +67 -0
- package/dist/authorize/well-known.controller.d.ts.map +1 -0
- package/dist/authorize/well-known.controller.js +126 -0
- package/dist/authorize/well-known.controller.js.map +1 -0
- package/dist/captcha/captcha.service.d.ts +32 -2
- package/dist/captcha/captcha.service.d.ts.map +1 -1
- package/dist/captcha/captcha.service.js +85 -12
- package/dist/captcha/captcha.service.js.map +1 -1
- package/dist/challenge/challenge.service.d.ts +2 -2
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +6 -0
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -9
- package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -9
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +2 -4
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts +8 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js +18 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js.map +1 -0
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.service.js +2 -4
- package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts +9 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.js +19 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.js.map +1 -0
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +3 -3
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.service.js +2 -4
- package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts +8 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.js +16 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.js.map +1 -0
- package/dist/file/file-upload-ticket.service.d.ts +160 -0
- package/dist/file/file-upload-ticket.service.d.ts.map +1 -0
- package/dist/file/file-upload-ticket.service.js +382 -0
- package/dist/file/file-upload-ticket.service.js.map +1 -0
- package/dist/file/file.controller.d.ts +24 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +63 -2
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.module.d.ts.map +1 -1
- package/dist/file/file.module.js +14 -2
- package/dist/file/file.module.js.map +1 -1
- package/dist/file/file.service.d.ts +182 -6
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +385 -36
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/filename-encoding.util.d.ts +24 -0
- package/dist/file/filename-encoding.util.d.ts.map +1 -0
- package/dist/file/filename-encoding.util.js +63 -0
- package/dist/file/filename-encoding.util.js.map +1 -0
- package/dist/file/image-optimization.service.d.ts +27 -0
- package/dist/file/image-optimization.service.d.ts.map +1 -1
- package/dist/file/image-optimization.service.js +63 -14
- package/dist/file/image-optimization.service.js.map +1 -1
- package/dist/file/mcp-file-source.schema.d.ts +33 -0
- package/dist/file/mcp-file-source.schema.d.ts.map +1 -0
- package/dist/file/mcp-file-source.schema.js +75 -0
- package/dist/file/mcp-file-source.schema.js.map +1 -0
- package/dist/file/mcp-file-source.service.d.ts +124 -0
- package/dist/file/mcp-file-source.service.d.ts.map +1 -0
- package/dist/file/mcp-file-source.service.js +262 -0
- package/dist/file/mcp-file-source.service.js.map +1 -0
- package/dist/file/mimetype-sniff.util.d.ts +62 -0
- package/dist/file/mimetype-sniff.util.d.ts.map +1 -0
- package/dist/file/mimetype-sniff.util.js +226 -0
- package/dist/file/mimetype-sniff.util.js.map +1 -0
- package/dist/file/remote-fetch.util.d.ts +35 -0
- package/dist/file/remote-fetch.util.d.ts.map +1 -0
- package/dist/file/remote-fetch.util.js +236 -0
- package/dist/file/remote-fetch.util.js.map +1 -0
- package/dist/impersonation/dto/start-impersonation.dto.d.ts +4 -1
- package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -1
- package/dist/impersonation/dto/start-impersonation.dto.js +1 -1
- package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -1
- package/dist/impersonation/impersonation.service.d.ts +8 -3
- package/dist/impersonation/impersonation.service.d.ts.map +1 -1
- package/dist/impersonation/impersonation.service.js +14 -4
- package/dist/impersonation/impersonation.service.js.map +1 -1
- package/dist/incident/incident.controller.d.ts +2 -1
- package/dist/incident/incident.controller.d.ts.map +1 -1
- package/dist/incident/incident.controller.js +10 -6
- package/dist/incident/incident.controller.js.map +1 -1
- package/dist/incident/incident.service.d.ts +2 -0
- package/dist/incident/incident.service.d.ts.map +1 -1
- package/dist/incident/incident.service.js +4 -0
- package/dist/incident/incident.service.js.map +1 -1
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +7 -0
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +0 -13
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +5 -40
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +5 -5
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/index.d.ts.map +1 -1
- package/dist/integration-profile/testers/index.js +2 -0
- package/dist/integration-profile/testers/index.js.map +1 -1
- package/dist/integration-profile/testers/shipping.testers.d.ts +3 -0
- package/dist/integration-profile/testers/shipping.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/shipping.testers.js +71 -0
- package/dist/integration-profile/testers/shipping.testers.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/send.dto.d.ts +6 -1
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.service.d.ts +9 -0
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +34 -14
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mail-sent/mail-sent.controller.d.ts +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
- package/dist/mail-sent/mail-sent.service.js +2 -1
- package/dist/mail-sent/mail-sent.service.js.map +1 -1
- package/dist/mail-sent/mail-sent.sort.d.ts +9 -0
- package/dist/mail-sent/mail-sent.sort.d.ts.map +1 -0
- package/dist/mail-sent/mail-sent.sort.js +19 -0
- package/dist/mail-sent/mail-sent.sort.js.map +1 -0
- package/dist/mcp/filters/mcp-challenge.filter.d.ts +20 -0
- package/dist/mcp/filters/mcp-challenge.filter.d.ts.map +1 -0
- package/dist/mcp/filters/mcp-challenge.filter.js +69 -0
- package/dist/mcp/filters/mcp-challenge.filter.js.map +1 -0
- package/dist/mcp/guards/mcp-auth.guard.d.ts +4 -1
- package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
- package/dist/mcp/guards/mcp-auth.guard.js +19 -5
- package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
- package/dist/mcp/guards/mcp-permission.guard.d.ts +25 -3
- package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -1
- package/dist/mcp/guards/mcp-permission.guard.js +46 -26
- package/dist/mcp/guards/mcp-permission.guard.js.map +1 -1
- package/dist/mcp/mcp-audit.service.d.ts +17 -0
- package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
- package/dist/mcp/mcp-audit.service.js +32 -3
- package/dist/mcp/mcp-audit.service.js.map +1 -1
- package/dist/mcp/mcp-permission.service.d.ts +64 -0
- package/dist/mcp/mcp-permission.service.d.ts.map +1 -0
- package/dist/mcp/mcp-permission.service.js +178 -0
- package/dist/mcp/mcp-permission.service.js.map +1 -0
- package/dist/mcp/mcp-server.service.d.ts +3 -1
- package/dist/mcp/mcp-server.service.d.ts.map +1 -1
- package/dist/mcp/mcp-server.service.js +36 -15
- package/dist/mcp/mcp-server.service.js.map +1 -1
- package/dist/mcp/mcp.controller.d.ts.map +1 -1
- package/dist/mcp/mcp.controller.js +10 -2
- package/dist/mcp/mcp.controller.js.map +1 -1
- package/dist/mcp/mcp.module.d.ts.map +1 -1
- package/dist/mcp/mcp.module.js +5 -1
- package/dist/mcp/mcp.module.js.map +1 -1
- package/dist/mcp/tools/core-ai.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +1 -1
- package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-dashboard.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-files.mcp-tools.d.ts +17 -5
- package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-files.mcp-tools.js +186 -24
- package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-integration-events.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-mail-sent.mcp-tools.js +2 -14
- package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-mail.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-menus.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.js +0 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-roles.mcp-tools.js +2 -13
- package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-routes.mcp-tools.js +2 -11
- package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-screens.mcp-tools.js +2 -11
- package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-sessions.mcp-tools.js +0 -2
- package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-settings.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-users.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-webhooks.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -1
- package/dist/mcp/types/mcp-context.type.d.ts +9 -0
- package/dist/mcp/types/mcp-context.type.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +8 -0
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/meeting/meeting-provider.registry.d.ts +115 -0
- package/dist/meeting/meeting-provider.registry.d.ts.map +1 -1
- package/dist/meeting/meeting-provider.registry.js.map +1 -1
- package/dist/meeting/meeting.constants.d.ts +70 -0
- package/dist/meeting/meeting.constants.d.ts.map +1 -1
- package/dist/meeting/meeting.constants.js +9 -1
- package/dist/meeting/meeting.constants.js.map +1 -1
- package/dist/menu/menu.service.d.ts.map +1 -1
- package/dist/menu/menu.service.js +29 -9
- package/dist/menu/menu.service.js.map +1 -1
- package/dist/message-template/dto/update-message-template.dto.d.ts +18 -0
- package/dist/message-template/dto/update-message-template.dto.d.ts.map +1 -0
- package/dist/message-template/dto/update-message-template.dto.js +38 -0
- package/dist/message-template/dto/update-message-template.dto.js.map +1 -0
- package/dist/message-template/message-template-admin.service.d.ts +70 -0
- package/dist/message-template/message-template-admin.service.d.ts.map +1 -0
- package/dist/message-template/message-template-admin.service.js +226 -0
- package/dist/message-template/message-template-admin.service.js.map +1 -0
- package/dist/message-template/message-template.controller.d.ts +29 -0
- package/dist/message-template/message-template.controller.d.ts.map +1 -0
- package/dist/message-template/message-template.controller.js +101 -0
- package/dist/message-template/message-template.controller.js.map +1 -0
- package/dist/message-template/message-template.module.d.ts +10 -0
- package/dist/message-template/message-template.module.d.ts.map +1 -0
- package/dist/message-template/message-template.module.js +33 -0
- package/dist/message-template/message-template.module.js.map +1 -0
- package/dist/message-template/message-template.registry.d.ts +55 -0
- package/dist/message-template/message-template.registry.d.ts.map +1 -0
- package/dist/message-template/message-template.registry.js +64 -0
- package/dist/message-template/message-template.registry.js.map +1 -0
- package/dist/message-template/message-template.service.d.ts +59 -0
- package/dist/message-template/message-template.service.d.ts.map +1 -0
- package/dist/message-template/message-template.service.js +166 -0
- package/dist/message-template/message-template.service.js.map +1 -0
- package/dist/notification/notification.constants.d.ts +11 -0
- package/dist/notification/notification.constants.d.ts.map +1 -0
- package/dist/notification/notification.constants.js +14 -0
- package/dist/notification/notification.constants.js.map +1 -0
- package/dist/notification/notification.controller.d.ts +20 -20
- package/dist/notification/notification.module.d.ts.map +1 -1
- package/dist/notification/notification.module.js +3 -0
- package/dist/notification/notification.module.js.map +1 -1
- package/dist/notification/notification.service.d.ts +33 -21
- package/dist/notification/notification.service.d.ts.map +1 -1
- package/dist/notification/notification.service.js +36 -2
- package/dist/notification/notification.service.js.map +1 -1
- package/dist/oauth/oauth.controller.d.ts +4 -6
- package/dist/oauth/oauth.controller.d.ts.map +1 -1
- package/dist/oauth/oauth.controller.js +0 -1
- package/dist/oauth/oauth.controller.js.map +1 -1
- package/dist/oauth/oauth.errors.d.ts +15 -1
- package/dist/oauth/oauth.errors.d.ts.map +1 -1
- package/dist/oauth/oauth.errors.js +9 -1
- package/dist/oauth/oauth.errors.js.map +1 -1
- package/dist/oauth/oauth.module.d.ts.map +1 -1
- package/dist/oauth/oauth.module.js +6 -1
- package/dist/oauth/oauth.module.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +25 -5
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +63 -27
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/oauth/providers/abstract.provider.d.ts +10 -0
- package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
- package/dist/oauth/providers/abstract.provider.js +39 -12
- package/dist/oauth/providers/abstract.provider.js.map +1 -1
- package/dist/oauth/providers/github.provider.d.ts +1 -1
- package/dist/oauth/providers/github.provider.d.ts.map +1 -1
- package/dist/oauth/providers/github.provider.js +48 -22
- package/dist/oauth/providers/github.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +6 -0
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/observability/monitored-cron.d.ts +29 -12
- package/dist/observability/monitored-cron.d.ts.map +1 -1
- package/dist/observability/monitored-cron.js +131 -46
- package/dist/observability/monitored-cron.js.map +1 -1
- package/dist/pairing/pairing.controller.d.ts +9 -9
- package/dist/pairing/pairing.service.d.ts +15 -11
- package/dist/pairing/pairing.service.d.ts.map +1 -1
- package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
- package/dist/profile/dto/change-password.dto.js +4 -6
- package/dist/profile/dto/change-password.dto.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +1 -1
- package/dist/profile/profile.service.d.ts +1 -1
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +9 -3
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
- package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
- package/dist/realtime/realtime-tick.coalescer.js +60 -0
- package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
- package/dist/realtime/realtime.service.d.ts +2 -0
- package/dist/realtime/realtime.service.d.ts.map +1 -1
- package/dist/realtime/realtime.service.js +22 -2
- package/dist/realtime/realtime.service.js.map +1 -1
- package/dist/redis/redis-kv.service.d.ts +90 -0
- package/dist/redis/redis-kv.service.d.ts.map +1 -0
- package/dist/redis/redis-kv.service.js +247 -0
- package/dist/redis/redis-kv.service.js.map +1 -0
- package/dist/redis/redis-master.d.ts +29 -0
- package/dist/redis/redis-master.d.ts.map +1 -0
- package/dist/redis/redis-master.js +81 -0
- package/dist/redis/redis-master.js.map +1 -0
- package/dist/redis/redis-pubsub.d.ts +12 -0
- package/dist/redis/redis-pubsub.d.ts.map +1 -1
- package/dist/redis/redis-pubsub.js +25 -2
- package/dist/redis/redis-pubsub.js.map +1 -1
- package/dist/redis/redis.module.d.ts +11 -0
- package/dist/redis/redis.module.d.ts.map +1 -0
- package/dist/redis/redis.module.js +30 -0
- package/dist/redis/redis.module.js.map +1 -0
- package/dist/session/session.controller.d.ts +6 -2
- package/dist/session/session.controller.d.ts.map +1 -1
- package/dist/session/session.service.d.ts +118 -15
- package/dist/session/session.service.d.ts.map +1 -1
- package/dist/session/session.service.js +251 -77
- package/dist/session/session.service.js.map +1 -1
- package/dist/setting/setting.controller.d.ts +5 -0
- package/dist/setting/setting.controller.d.ts.map +1 -1
- package/dist/setting/setting.service.d.ts +7 -0
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +38 -3
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/task/task.service.d.ts +17 -0
- package/dist/task/task.service.d.ts.map +1 -1
- package/dist/task/task.service.js +48 -13
- package/dist/task/task.service.js.map +1 -1
- package/dist/token/token.service.d.ts +19 -1
- package/dist/token/token.service.d.ts.map +1 -1
- package/dist/token/token.service.js +39 -2
- package/dist/token/token.service.js.map +1 -1
- package/dist/user/user-credential.util.d.ts +10 -0
- package/dist/user/user-credential.util.d.ts.map +1 -1
- package/dist/user/user-credential.util.js +14 -1
- package/dist/user/user-credential.util.js.map +1 -1
- package/dist/user/user.service.d.ts +12 -4
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +2 -11
- package/dist/user/user.service.js.map +1 -1
- package/dist/user/user.sort.d.ts +16 -0
- package/dist/user/user.sort.d.ts.map +1 -0
- package/dist/user/user.sort.js +25 -0
- package/dist/user/user.sort.js.map +1 -0
- package/dist/utils/abbreviate-name.d.ts +13 -0
- package/dist/utils/abbreviate-name.d.ts.map +1 -0
- package/dist/utils/abbreviate-name.js +42 -0
- package/dist/utils/abbreviate-name.js.map +1 -0
- package/dist/utils/date-range-query.dto.d.ts +11 -0
- package/dist/utils/date-range-query.dto.d.ts.map +1 -0
- package/dist/utils/date-range-query.dto.js +63 -0
- package/dist/utils/date-range-query.dto.js.map +1 -0
- package/dist/utils/date-range.d.ts +96 -0
- package/dist/utils/date-range.d.ts.map +1 -0
- package/dist/utils/date-range.js +172 -0
- package/dist/utils/date-range.js.map +1 -0
- package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-utils.js +24 -0
- package/dist/webhook-integration/webhook-utils.js.map +1 -1
- package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
- package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
- package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
- package/dist/whatsapp-sender/whatsapp-sender.service.js +46 -5
- package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
- package/hedhog/data/integration_provider.yaml +9 -0
- package/hedhog/data/integration_type.yaml +6 -0
- package/hedhog/data/locale.yaml +0 -1
- package/hedhog/data/mail.yaml +2 -2
- package/hedhog/data/mail_layout.yaml +6 -3
- package/hedhog/data/menu.yaml +25 -5
- package/hedhog/data/route.yaml +140 -0
- package/hedhog/data/setting_group.yaml +137 -3
- package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
- package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
- package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
- package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
- package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
- package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
- package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
- package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
- package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
- package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
- package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
- package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
- package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
- package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
- package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
- package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
- package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
- package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
- package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
- package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
- package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
- package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
- package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
- package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
- package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
- package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
- package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
- package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
- package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
- package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
- package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
- package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
- package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
- package/hedhog/frontend/messages/en.json +183 -36
- package/hedhog/frontend/messages/pt.json +183 -36
- package/hedhog/table/cron_lock.yaml +17 -0
- package/hedhog/table/file.yaml +13 -1
- package/hedhog/table/file_upload_chunk.yaml +23 -0
- package/hedhog/table/file_upload_ticket.yaml +67 -0
- package/hedhog/table/mcp_tool_call_log.yaml +30 -22
- package/hedhog/table/message_template.yaml +33 -0
- package/hedhog/table/setting.yaml +8 -0
- package/hedhog/table/user_session.yaml +36 -1
- package/package.json +8 -6
- package/src/ai/ai-agent.sort.ts +21 -0
- package/src/ai/ai.service.spec.ts +173 -1
- package/src/ai/ai.service.ts +64 -193
- package/src/ai-instruction/ai-instruction.service.ts +32 -28
- package/src/ai-instruction/ai-instruction.sort.ts +32 -0
- package/src/auth/auth.module.ts +8 -1
- package/src/auth/auth.service.spec.ts +108 -1
- package/src/auth/auth.service.ts +59 -5
- package/src/auth/guards/auth.guard.ts +9 -1
- package/src/authorize/authorize.controller.ts +126 -11
- package/src/authorize/authorize.errors.ts +55 -0
- package/src/authorize/authorize.module.ts +6 -1
- package/src/authorize/authorize.service.spec.ts +379 -7
- package/src/authorize/authorize.service.ts +309 -23
- package/src/authorize/dto/authorize-info.dto.ts +21 -3
- package/src/authorize/dto/consent.dto.ts +21 -3
- package/src/authorize/dto/token.dto.ts +24 -2
- package/src/authorize/oauth-exception.filter.ts +58 -0
- package/src/authorize/oauth-metadata.service.ts +67 -0
- package/src/authorize/well-known.controller.spec.ts +84 -0
- package/src/authorize/well-known.controller.ts +96 -0
- package/src/captcha/captcha.service.spec.ts +211 -4
- package/src/captcha/captcha.service.ts +127 -10
- package/src/core.module.ts +6 -0
- package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
- package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
- package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
- package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
- package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
- package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
- package/src/file/file-upload-ticket.service.spec.ts +422 -0
- package/src/file/file-upload-ticket.service.ts +513 -0
- package/src/file/file.controller.ts +65 -0
- package/src/file/file.module.ts +14 -2
- package/src/file/file.service.spec.ts +94 -0
- package/src/file/file.service.ts +432 -30
- package/src/file/filename-encoding.util.spec.ts +54 -0
- package/src/file/filename-encoding.util.ts +67 -0
- package/src/file/image-optimization.service.spec.ts +156 -19
- package/src/file/image-optimization.service.ts +106 -21
- package/src/file/mcp-file-source.schema.ts +83 -0
- package/src/file/mcp-file-source.service.spec.ts +473 -0
- package/src/file/mcp-file-source.service.ts +445 -0
- package/src/file/mimetype-sniff.util.spec.ts +126 -0
- package/src/file/mimetype-sniff.util.ts +265 -0
- package/src/file/remote-fetch.util.spec.ts +117 -0
- package/src/file/remote-fetch.util.ts +330 -0
- package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
- package/src/impersonation/impersonation.service.spec.ts +24 -1
- package/src/impersonation/impersonation.service.ts +14 -4
- package/src/incident/incident.controller.ts +9 -1
- package/src/incident/incident.service.ts +7 -0
- package/src/index.ts +17 -0
- package/src/integration-profile/integration-profile.secrets.ts +7 -0
- package/src/integration-profile/integration-profile.service.ts +7 -64
- package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
- package/src/integration-profile/integration-profile.utils.ts +5 -5
- package/src/integration-profile/testers/index.ts +2 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +79 -0
- package/src/integration-profile/testers/shipping.testers.ts +94 -0
- package/src/mail/dto/send.dto.ts +6 -1
- package/src/mail/mail-template.spec.ts +58 -1
- package/src/mail/mail.service.spec.ts +112 -0
- package/src/mail/mail.service.ts +42 -4
- package/src/mail-sent/mail-sent.service.ts +3 -0
- package/src/mail-sent/mail-sent.sort.ts +19 -0
- package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
- package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
- package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
- package/src/mcp/guards/mcp-auth.guard.ts +24 -1
- package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
- package/src/mcp/guards/mcp-permission.guard.ts +76 -51
- package/src/mcp/mcp-audit.service.spec.ts +107 -0
- package/src/mcp/mcp-audit.service.ts +37 -1
- package/src/mcp/mcp-permission.service.spec.ts +197 -0
- package/src/mcp/mcp-permission.service.ts +184 -0
- package/src/mcp/mcp-server.service.spec.ts +84 -2
- package/src/mcp/mcp-server.service.ts +111 -87
- package/src/mcp/mcp.controller.ts +8 -1
- package/src/mcp/mcp.module.ts +5 -1
- package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
- package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
- package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
- package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
- package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
- package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
- package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
- package/src/mcp/types/mcp-context.type.ts +15 -6
- package/src/mcp-chat/mcp-chat.service.ts +8 -0
- package/src/meeting/meeting-provider.registry.ts +121 -0
- package/src/meeting/meeting.constants.ts +74 -0
- package/src/menu/menu.service.spec.ts +89 -0
- package/src/menu/menu.service.ts +29 -11
- package/src/message-template/dto/update-message-template.dto.ts +22 -0
- package/src/message-template/message-template-admin.service.spec.ts +163 -0
- package/src/message-template/message-template-admin.service.ts +239 -0
- package/src/message-template/message-template.controller.ts +52 -0
- package/src/message-template/message-template.module.ts +21 -0
- package/src/message-template/message-template.registry.spec.ts +62 -0
- package/src/message-template/message-template.registry.ts +125 -0
- package/src/message-template/message-template.service.spec.ts +149 -0
- package/src/message-template/message-template.service.ts +149 -0
- package/src/notification/notification.constants.ts +10 -0
- package/src/notification/notification.module.ts +3 -0
- package/src/notification/notification.service.spec.ts +75 -1
- package/src/notification/notification.service.ts +39 -1
- package/src/oauth/oauth.controller.ts +0 -1
- package/src/oauth/oauth.errors.ts +7 -0
- package/src/oauth/oauth.module.ts +6 -1
- package/src/oauth/oauth.service.spec.ts +58 -7
- package/src/oauth/oauth.service.ts +71 -32
- package/src/oauth/providers/abstract.provider.spec.ts +192 -0
- package/src/oauth/providers/abstract.provider.ts +46 -14
- package/src/oauth/providers/github.provider.ts +57 -34
- package/src/oauth/providers/microsoft-entra-id.provider.ts +8 -1
- package/src/observability/monitored-cron.spec.ts +164 -31
- package/src/observability/monitored-cron.ts +154 -62
- package/src/profile/dto/change-password.dto.ts +25 -7
- package/src/profile/profile.service.spec.ts +97 -0
- package/src/profile/profile.service.ts +9 -3
- package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
- package/src/realtime/realtime-tick.coalescer.ts +60 -0
- package/src/realtime/realtime.service.spec.ts +33 -0
- package/src/realtime/realtime.service.ts +28 -2
- package/src/redis/redis-kv.service.ts +261 -0
- package/src/redis/redis-master.spec.ts +111 -0
- package/src/redis/redis-master.ts +86 -0
- package/src/redis/redis-pubsub.ts +27 -3
- package/src/redis/redis.module.ts +17 -0
- package/src/session/session.service.spec.ts +121 -42
- package/src/session/session.service.ts +279 -82
- package/src/setting/setting.service.ts +44 -3
- package/src/task/task.service.spec.ts +41 -0
- package/src/task/task.service.ts +53 -13
- package/src/token/token.service.spec.ts +90 -0
- package/src/token/token.service.ts +48 -2
- package/src/user/user-credential.util.ts +14 -5
- package/src/user/user.service.ts +2 -12
- package/src/user/user.sort.ts +25 -0
- package/src/utils/abbreviate-name.spec.ts +50 -0
- package/src/utils/abbreviate-name.ts +44 -0
- package/src/utils/date-range-query.dto.ts +56 -0
- package/src/utils/date-range.spec.ts +175 -0
- package/src/utils/date-range.ts +246 -0
- package/src/webhook-integration/webhook-utils.spec.ts +67 -0
- package/src/webhook-integration/webhook-utils.ts +26 -0
- package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
- package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
- package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +112 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +58 -5
|
@@ -27,7 +27,7 @@ export function buildMailConfigFromIntegration(
|
|
|
27
27
|
clientId: String(cfg.client_id ?? ''),
|
|
28
28
|
clientSecret: String(cfg.client_secret ?? ''),
|
|
29
29
|
refreshToken: String(cfg.refresh_token ?? ''),
|
|
30
|
-
from: String(cfg.from_email ?? ''),
|
|
30
|
+
from: String(cfg.from_email ?? '').trim(),
|
|
31
31
|
};
|
|
32
32
|
case 'ses':
|
|
33
33
|
return {
|
|
@@ -36,7 +36,7 @@ export function buildMailConfigFromIntegration(
|
|
|
36
36
|
region: String(cfg.region ?? ''),
|
|
37
37
|
accessKeyId: String(cfg.access_key_id ?? ''),
|
|
38
38
|
secretAccessKey: String(cfg.secret_access_key ?? ''),
|
|
39
|
-
from: String(cfg.from_email ?? ''),
|
|
39
|
+
from: String(cfg.from_email ?? '').trim(),
|
|
40
40
|
};
|
|
41
41
|
case 'resend':
|
|
42
42
|
// Resend usa a API HTTP própria (não nodemailer). Retornamos um marcador
|
|
@@ -48,7 +48,7 @@ export function buildMailConfigFromIntegration(
|
|
|
48
48
|
apiToken: String(cfg.api_token ?? ''),
|
|
49
49
|
domain: String(cfg.domain ?? ''),
|
|
50
50
|
region: String(cfg.region ?? ''),
|
|
51
|
-
from: String(cfg.from_email ?? ''),
|
|
51
|
+
from: String(cfg.from_email ?? '').trim(),
|
|
52
52
|
};
|
|
53
53
|
case 'imap':
|
|
54
54
|
// Sem este caso o operador que apontasse o perfil de envio para uma caixa
|
|
@@ -123,8 +123,8 @@ export function buildResendConfigFromIntegration(
|
|
|
123
123
|
|
|
124
124
|
export function getFromAddress(config: unknown): string {
|
|
125
125
|
const cfg = (config as Cfg) ?? {};
|
|
126
|
-
const fromEmail = String(cfg.from_email ?? '');
|
|
127
|
-
const fromName = String(cfg.from_name ?? '');
|
|
126
|
+
const fromEmail = String(cfg.from_email ?? '').trim();
|
|
127
|
+
const fromName = String(cfg.from_name ?? '').trim();
|
|
128
128
|
return fromName ? `${fromName} <${fromEmail}>` : fromEmail;
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -6,6 +6,7 @@ import { IntegrationTester } from './integration-tester.types';
|
|
|
6
6
|
import { MESSAGING_TESTERS } from './messaging.testers';
|
|
7
7
|
import { OAUTH_TESTERS } from './oauth.testers';
|
|
8
8
|
import { PAYMENT_TESTERS } from './payment.testers';
|
|
9
|
+
import { SHIPPING_TESTERS } from './shipping.testers';
|
|
9
10
|
import { STORAGE_TESTERS } from './storage.testers';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -23,6 +24,7 @@ export const BUILTIN_INTEGRATION_TESTERS: IntegrationTester[] = [
|
|
|
23
24
|
...PAYMENT_TESTERS,
|
|
24
25
|
...CAPTCHA_TESTERS,
|
|
25
26
|
...INFRASTRUCTURE_TESTERS,
|
|
27
|
+
...SHIPPING_TESTERS,
|
|
26
28
|
];
|
|
27
29
|
|
|
28
30
|
export * from './http-probe';
|
|
@@ -5,6 +5,7 @@ import { EMAIL_TESTERS } from './email.testers';
|
|
|
5
5
|
import { INFRASTRUCTURE_TESTERS } from './infrastructure.testers';
|
|
6
6
|
import { MESSAGING_TESTERS } from './messaging.testers';
|
|
7
7
|
import { PAYMENT_TESTERS } from './payment.testers';
|
|
8
|
+
import { SHIPPING_TESTERS } from './shipping.testers';
|
|
8
9
|
import { IntegrationTestContext, IntegrationTester } from './integration-tester.types';
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -19,6 +20,7 @@ const all = [
|
|
|
19
20
|
...AI_TESTERS,
|
|
20
21
|
...PAYMENT_TESTERS,
|
|
21
22
|
...INFRASTRUCTURE_TESTERS,
|
|
23
|
+
...SHIPPING_TESTERS,
|
|
22
24
|
];
|
|
23
25
|
|
|
24
26
|
const bySlug = (slug: string): IntegrationTester =>
|
|
@@ -444,3 +446,80 @@ describe('digitalocean tester', () => {
|
|
|
444
446
|
});
|
|
445
447
|
});
|
|
446
448
|
});
|
|
449
|
+
|
|
450
|
+
describe('melhor-envio tester', () => {
|
|
451
|
+
const tester = bySlug('melhor-envio');
|
|
452
|
+
const account = { firstname: 'Ana', lastname: 'Souza', email: 'ana@acme.com' };
|
|
453
|
+
|
|
454
|
+
it('identifica a conta e o ambiente de produção', async () => {
|
|
455
|
+
fetchMock.mockResolvedValue(jsonResponse(account));
|
|
456
|
+
|
|
457
|
+
await expect(tester.test({ access_token: 'tok' }, ctx())).resolves.toEqual({
|
|
458
|
+
ok: true,
|
|
459
|
+
info: 'Ana Souza — ana@acme.com (production)',
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit];
|
|
463
|
+
expect(url).toBe('https://melhorenvio.com.br/api/v2/me');
|
|
464
|
+
const headers = init.headers as Record<string, string>;
|
|
465
|
+
expect(headers.Authorization).toBe('Bearer tok');
|
|
466
|
+
// Sem User-Agent identificável o Melhor Envio recusa a requisição.
|
|
467
|
+
expect(headers['User-Agent']).toBe('HedHog Commerce');
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('usa a base de sandbox e avisa que o preço não é real', async () => {
|
|
471
|
+
fetchMock.mockResolvedValue(jsonResponse(account));
|
|
472
|
+
|
|
473
|
+
const outcome = await tester.test(
|
|
474
|
+
{ access_token: 'tok', sandbox: true, user_agent: 'Loja (contato@acme.com)' },
|
|
475
|
+
ctx(),
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
expect(outcome.ok).toBe(true);
|
|
479
|
+
expect(outcome.info).toContain('(sandbox)');
|
|
480
|
+
expect(outcome.warning).toContain('not real prices');
|
|
481
|
+
|
|
482
|
+
const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit];
|
|
483
|
+
expect(url).toBe('https://sandbox.melhorenvio.com.br/api/v2/me');
|
|
484
|
+
expect((init.headers as Record<string, string>)['User-Agent']).toBe(
|
|
485
|
+
'Loja (contato@acme.com)',
|
|
486
|
+
);
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it('aceita a string "true" que o formulário do admin grava', async () => {
|
|
490
|
+
fetchMock.mockResolvedValue(jsonResponse(account));
|
|
491
|
+
|
|
492
|
+
await tester.test({ access_token: 'tok', sandbox: 'true' }, ctx());
|
|
493
|
+
|
|
494
|
+
const [url] = fetchMock.mock.calls[0] as [string];
|
|
495
|
+
expect(url).toBe('https://sandbox.melhorenvio.com.br/api/v2/me');
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
it('aponta o switch de sandbox no 401, que é o erro mais comum', async () => {
|
|
499
|
+
fetchMock.mockResolvedValue(jsonResponse({}, 401));
|
|
500
|
+
|
|
501
|
+
const outcome = await tester.test({ access_token: 'tok' }, ctx());
|
|
502
|
+
|
|
503
|
+
expect(outcome.ok).toBe(false);
|
|
504
|
+
expect(outcome.error).toContain('in production');
|
|
505
|
+
expect(outcome.error).toContain('sandbox switch');
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
it('distingue falta de escopo (403) de token inválido', async () => {
|
|
509
|
+
fetchMock.mockResolvedValue(jsonResponse({}, 403));
|
|
510
|
+
|
|
511
|
+
await expect(tester.test({ access_token: 'tok' }, ctx())).resolves.toEqual({
|
|
512
|
+
ok: false,
|
|
513
|
+
error:
|
|
514
|
+
'The Melhor Envio token has no permission to read the account. Reissue it including the shipping scopes.',
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it('exige o token antes de ir à rede', async () => {
|
|
519
|
+
await expect(tester.test({}, ctx())).resolves.toEqual({
|
|
520
|
+
ok: false,
|
|
521
|
+
error: 'Access token is required.',
|
|
522
|
+
});
|
|
523
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
524
|
+
});
|
|
525
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describeHttpError,
|
|
3
|
+
fail,
|
|
4
|
+
pass,
|
|
5
|
+
probeJson,
|
|
6
|
+
requireFields,
|
|
7
|
+
str,
|
|
8
|
+
} from './http-probe';
|
|
9
|
+
import { IntegrationTester } from './integration-tester.types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Testadores das transportadoras / intermediadores de frete.
|
|
13
|
+
*
|
|
14
|
+
* Só leitura da conta: nada aqui gera etiqueta, compra postagem ou mexe no saldo
|
|
15
|
+
* da carteira — mesmo princípio dos testers de pagamento.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Sandbox e produção são contas SEPARADAS no Melhor Envio, cada uma com o seu
|
|
20
|
+
* token. Trocar o switch sem trocar o token devolve 401, então a resolução da
|
|
21
|
+
* base tem que ser idêntica à do consumidor
|
|
22
|
+
* (libraries/commerce/src/commerce-shipping/melhor-envio.provider.ts) — senão o
|
|
23
|
+
* teste valida um ambiente e a loja cota no outro.
|
|
24
|
+
*/
|
|
25
|
+
function resolveBaseUrl(config: Record<string, unknown>): {
|
|
26
|
+
baseUrl: string;
|
|
27
|
+
sandbox: boolean;
|
|
28
|
+
} {
|
|
29
|
+
// Aceita boolean do JSON e a string do formulário do admin.
|
|
30
|
+
const sandbox = config.sandbox === true || String(config.sandbox ?? '') === 'true';
|
|
31
|
+
return {
|
|
32
|
+
sandbox,
|
|
33
|
+
baseUrl: sandbox
|
|
34
|
+
? 'https://sandbox.melhorenvio.com.br'
|
|
35
|
+
: 'https://melhorenvio.com.br',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const melhorEnvioTester: IntegrationTester = {
|
|
40
|
+
providerSlug: 'melhor-envio',
|
|
41
|
+
test: async (config, ctx) => {
|
|
42
|
+
const missing = requireFields(config, [['access_token', 'Access token']]);
|
|
43
|
+
if (missing) return missing;
|
|
44
|
+
|
|
45
|
+
const { baseUrl, sandbox } = resolveBaseUrl(config);
|
|
46
|
+
const environment = sandbox ? 'sandbox' : 'production';
|
|
47
|
+
|
|
48
|
+
const result = await probeJson(
|
|
49
|
+
`${baseUrl}/api/v2/me`,
|
|
50
|
+
{
|
|
51
|
+
headers: {
|
|
52
|
+
Authorization: `Bearer ${str(config, 'access_token')}`,
|
|
53
|
+
Accept: 'application/json',
|
|
54
|
+
// Sem User-Agent identificável o Melhor Envio recusa a requisição, e o
|
|
55
|
+
// teste falharia por etiqueta faltando em vez de credencial errada.
|
|
56
|
+
'User-Agent': str(config, 'user_agent') || 'HedHog Commerce',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
ctx.signal,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (result.status === 401) {
|
|
63
|
+
// O erro mais comum não é token digitado errado: é token de sandbox num
|
|
64
|
+
// perfil de produção (ou o contrário), porque são contas diferentes.
|
|
65
|
+
return fail(
|
|
66
|
+
`Melhor Envio rejected the access token in ${environment}. Check the token and the sandbox switch — sandbox and production are separate accounts.`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (result.status === 403) {
|
|
70
|
+
return fail(
|
|
71
|
+
'The Melhor Envio token has no permission to read the account. Reissue it including the shipping scopes.',
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (!result.ok) {
|
|
75
|
+
return fail(describeHttpError(result, 'Melhor Envio rejected the credentials.'));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const name = [result.body?.firstname, result.body?.lastname]
|
|
79
|
+
.map((part) => String(part ?? '').trim())
|
|
80
|
+
.filter(Boolean)
|
|
81
|
+
.join(' ');
|
|
82
|
+
const email = String(result.body?.email ?? '').trim();
|
|
83
|
+
const account = [name, email].filter(Boolean).join(' — ') || 'Melhor Envio account';
|
|
84
|
+
|
|
85
|
+
return pass(
|
|
86
|
+
`${account} (${environment})`,
|
|
87
|
+
// Cotação de sandbox tem preço fictício: passar despercebido significa loja
|
|
88
|
+
// no ar vendendo frete que não existe.
|
|
89
|
+
sandbox ? 'This profile points to the sandbox, so quotes are not real prices.' : undefined,
|
|
90
|
+
);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const SHIPPING_TESTERS: IntegrationTester[] = [melhorEnvioTester];
|
package/src/mail/dto/send.dto.ts
CHANGED
|
@@ -10,8 +10,13 @@ export class SendTemplatedMailDTO {
|
|
|
10
10
|
@IsNotEmpty({ message: (args) => getLocaleText('validation.fieldRequired', args.value) })
|
|
11
11
|
slug: string;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Contexto do Handlebars. Nao e so string: o corpo do e-mail e compilado com
|
|
15
|
+
* Handlebars de verdade, entao um array aqui alimenta `{{#each}}` no template
|
|
16
|
+
* (e o resumo do aluno usa isso para a grade de sequencia da semana).
|
|
17
|
+
*/
|
|
13
18
|
@IsObject({ message: (args) => getLocaleText('validation.objectRequired', args.value) })
|
|
14
|
-
variables: Record<string,
|
|
19
|
+
variables: Record<string, unknown>;
|
|
15
20
|
|
|
16
21
|
/**
|
|
17
22
|
* Slug do perfil de integração de e-mail a usar neste envio.
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_MAIL_LAYOUT,
|
|
4
|
+
renderMailTemplate,
|
|
5
|
+
resolveMailAssetUrl,
|
|
6
|
+
sanitizeAccentColor,
|
|
7
|
+
} from '@hed-hog/api-mail';
|
|
3
8
|
|
|
4
9
|
// Testes do renderizador de e-mail moram aqui (e nao em packages/api-mail)
|
|
5
10
|
// porque o api-mail nao tem jest configurado; o jest do core resolve o pacote.
|
|
@@ -249,6 +254,58 @@ describe('renderMailTemplate', () => {
|
|
|
249
254
|
});
|
|
250
255
|
});
|
|
251
256
|
|
|
257
|
+
describe('cor da etapa (accentColor)', () => {
|
|
258
|
+
// O commerce manda uma cor por etapa da compra; as demais libraries nao
|
|
259
|
+
// mandam nada e precisam continuar exatamente como estavam.
|
|
260
|
+
it('pinta a barra de destaque com a cor da etapa', () => {
|
|
261
|
+
const html = renderMailTemplate({
|
|
262
|
+
subject: 'Pagamento confirmado',
|
|
263
|
+
body: '<p>Ola</p>',
|
|
264
|
+
primaryColor: '#111827',
|
|
265
|
+
accentColor: '#16a34a',
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
expect(html).toContain('background:#16a34a;');
|
|
269
|
+
expect(html).toContain('background: #16a34a;');
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('cai na cor da marca quando nenhuma etapa e informada', () => {
|
|
273
|
+
const html = renderMailTemplate({
|
|
274
|
+
subject: 'Recuperar senha',
|
|
275
|
+
body: '<p>Ola</p>',
|
|
276
|
+
primaryColor: '#1465b8',
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
expect(html).toContain('background:#1465b8;');
|
|
280
|
+
expect(html).not.toContain('{{accentColor}}');
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// O valor e interpolado dentro do bloco <style> do wrapper: string livre ali
|
|
284
|
+
// fecharia a regra e reescreveria o layout inteiro.
|
|
285
|
+
it('ignora cor fora do formato #rrggbb', () => {
|
|
286
|
+
const html = renderMailTemplate({
|
|
287
|
+
subject: 'Oi',
|
|
288
|
+
body: '<p>Ola</p>',
|
|
289
|
+
primaryColor: '#1465b8',
|
|
290
|
+
accentColor: 'red;} body { display:none } .x {',
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
expect(html).not.toContain('display:none');
|
|
294
|
+
expect(html).toContain('background:#1465b8;');
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('sanitizeAccentColor aceita so hexadecimal de 6 digitos', () => {
|
|
298
|
+
expect(sanitizeAccentColor('#16a34a')).toBe('#16a34a');
|
|
299
|
+
expect(sanitizeAccentColor(' #ABCDEF ')).toBe('#ABCDEF');
|
|
300
|
+
expect(sanitizeAccentColor('#abc')).toBeUndefined();
|
|
301
|
+
expect(sanitizeAccentColor('green')).toBeUndefined();
|
|
302
|
+
expect(sanitizeAccentColor('#16a34a;')).toBeUndefined();
|
|
303
|
+
expect(sanitizeAccentColor('')).toBeUndefined();
|
|
304
|
+
expect(sanitizeAccentColor(undefined)).toBeUndefined();
|
|
305
|
+
expect(sanitizeAccentColor(null)).toBeUndefined();
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
252
309
|
describe('resolveMailAssetUrl', () => {
|
|
253
310
|
it('mantem URLs ja absolutas ou data: intactas', () => {
|
|
254
311
|
expect(resolveMailAssetUrl('https://cdn.example.com/logo.svg', 'http://localhost:3100')).toBe(
|
|
@@ -82,11 +82,45 @@ describe('MailService', () => {
|
|
|
82
82
|
expect(call('A\r\nB', {})).toBe('A<br/>B');
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
it('preserva as quebras de linha de um documento HTML completo (não injeta <br/> dentro de <style>/<head>)', () => {
|
|
86
|
+
// Bug real: um HTML completo colado em Templates de e-mail (que
|
|
87
|
+
// funciona no preview cru de Campanhas) aparecia quebrado aqui porque
|
|
88
|
+
// toda quebra de linha virava "<br/>" literal mesmo dentro de <style>,
|
|
89
|
+
// invalidando o CSS antes de chegar em renderMailTemplate.
|
|
90
|
+
const fullHtml =
|
|
91
|
+
'<!DOCTYPE html>\n<html>\n<head>\n<style>\n.foo {\n color: red;\n}\n</style>\n</head>\n<body>{{name}}</body>\n</html>';
|
|
92
|
+
const result = call(fullHtml, { name: 'Bob' });
|
|
93
|
+
expect(result).not.toContain('<br/>');
|
|
94
|
+
expect(result).toContain('.foo {\n color: red;\n}');
|
|
95
|
+
expect(result).toContain('Bob');
|
|
96
|
+
});
|
|
97
|
+
|
|
85
98
|
it('lança BadRequestException em sintaxe inválida', () => {
|
|
86
99
|
expect(() => call('{{#if foo}}sem fechar', {})).toThrow(
|
|
87
100
|
BadRequestException,
|
|
88
101
|
);
|
|
89
102
|
});
|
|
103
|
+
|
|
104
|
+
// Bug real: o assunto e texto puro (vira o header `subject:` do e-mail),
|
|
105
|
+
// mas o Handlebars padrao escapa `& < > " ' `` `` como se fosse HTML —
|
|
106
|
+
// uma crase no titulo da tarefa saia como ``` cru na caixa de
|
|
107
|
+
// entrada, e escapava DE NOVO no `<h1>` do corpo (renderMailTemplate),
|
|
108
|
+
// virando `&#x60;`. `escapeHtml: false` e o que os call sites do
|
|
109
|
+
// assunto passam pra evitar isso.
|
|
110
|
+
it('com escapeHtml:false, nao escapa nada — usado no assunto (texto puro)', () => {
|
|
111
|
+
const src = 'Tarefa `{{title}}` & <urgente> "importante"';
|
|
112
|
+
const result = (makeService().service as any).interpolateTemplate(
|
|
113
|
+
src,
|
|
114
|
+
{ title: 'status' },
|
|
115
|
+
{ escapeHtml: false },
|
|
116
|
+
);
|
|
117
|
+
expect(result).toBe('Tarefa `status` & <urgente> "importante"');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('por padrao (sem a opcao) continua escapando — usado no corpo, que e HTML de verdade', () => {
|
|
121
|
+
const result = call('Nome: {{name}}', { name: 'A & B <b>' });
|
|
122
|
+
expect(result).toBe('Nome: A & B <b>');
|
|
123
|
+
});
|
|
90
124
|
});
|
|
91
125
|
|
|
92
126
|
describe('isSettingEnabled', () => {
|
|
@@ -331,6 +365,54 @@ describe('MailService', () => {
|
|
|
331
365
|
).resolves.toEqual({ sent: true, providerMessageId: 'ses-abc' });
|
|
332
366
|
});
|
|
333
367
|
|
|
368
|
+
it('assunto com crase, & e aspas chega cru no e-mail — sem `/& vazando (corpo continua escapando)', async () => {
|
|
369
|
+
const { service, deps } = makeService();
|
|
370
|
+
deps.setting.getSettingValues.mockResolvedValue({
|
|
371
|
+
'configured-mail': 'true',
|
|
372
|
+
} as any);
|
|
373
|
+
// `resolveUserLocale` diferente de 'en' evita o fallback que chama
|
|
374
|
+
// `normalizeLocaleCode(callerLocale)` — sem relação com o bug desta
|
|
375
|
+
// task, só contorna o pacote @hed-hog/api-locale com dist desatualizado
|
|
376
|
+
// neste ambiente (falta o export, dist nao republicado).
|
|
377
|
+
deps.setting.resolveUserLocale.mockResolvedValue('pt');
|
|
378
|
+
jest
|
|
379
|
+
.spyOn(service, 'reloadConfig')
|
|
380
|
+
.mockResolvedValue({ success: true, provider: 'ses', from: 'a@b.com', config: {} });
|
|
381
|
+
deps.prismaService.locale.findUnique.mockResolvedValue({ id: 1, code: 'en' });
|
|
382
|
+
deps.prismaService.mail.findUnique.mockResolvedValue({
|
|
383
|
+
id: 7,
|
|
384
|
+
mail_locale: [
|
|
385
|
+
{
|
|
386
|
+
// A crase literal no template (fora de {{}}) nunca foi escapada
|
|
387
|
+
// pelo Handlebars — quem escapava era o VALOR interpolado da
|
|
388
|
+
// variavel. O bug real tinha a crase dentro do dado (nome da
|
|
389
|
+
// tarefa), entao o teste reproduz isso: a crase mora em `title`,
|
|
390
|
+
// nao no texto fixo do template.
|
|
391
|
+
subject: 'Você foi atribuído à tarefa {{title}} & "urgente"',
|
|
392
|
+
body: 'Título: {{title}}',
|
|
393
|
+
locale: { code: 'en' },
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
mail_var: [],
|
|
397
|
+
});
|
|
398
|
+
deps.mailMainService.send.mockResolvedValue({ result: { MessageId: 'ses-abc' } });
|
|
399
|
+
|
|
400
|
+
await service.sendTemplatedMail('en', {
|
|
401
|
+
email: 'a@b.com',
|
|
402
|
+
slug: 's',
|
|
403
|
+
variables: { title: '`status`' },
|
|
404
|
+
} as any);
|
|
405
|
+
|
|
406
|
+
const sentArgs = deps.mailMainService.send.mock.calls[0][0] as { subject: string; body: string };
|
|
407
|
+
expect(sentArgs.subject).toBe('Você foi atribuído à tarefa `status` & "urgente"');
|
|
408
|
+
expect(sentArgs.subject).not.toContain('`');
|
|
409
|
+
expect(sentArgs.subject).not.toContain('&');
|
|
410
|
+
// O corpo e HTML de verdade — a mesma crase, vinda do mesmo dado,
|
|
411
|
+
// continua escapando normalmente ali (nao é dupla checagem à toa: prova
|
|
412
|
+
// que `escapeHtml:false` ficou restrito ao assunto).
|
|
413
|
+
expect(sentArgs.body).toContain('`status`');
|
|
414
|
+
});
|
|
415
|
+
|
|
334
416
|
// O bug que originou esta mudanca: o e-mail saia no idioma do header (ou no
|
|
335
417
|
// `en` de quem nao manda header), ignorando a preferencia do destinatario.
|
|
336
418
|
describe('idioma do destinatario', () => {
|
|
@@ -579,6 +661,36 @@ describe('MailService', () => {
|
|
|
579
661
|
expect(html).toContain('lang="pt"');
|
|
580
662
|
});
|
|
581
663
|
|
|
664
|
+
// Regressao do bug real: assunto com crase saia como ``` cru no
|
|
665
|
+
// assunto do e-mail e `&#x60;` (escape duplo) no <h1> do corpo. O
|
|
666
|
+
// fluxo completo (interpolateTemplate -> renderMailTemplate) precisa
|
|
667
|
+
// produzir cada caractere especial escapado NO MAXIMO uma vez, e so pelo
|
|
668
|
+
// renderMailTemplate — sem o <script> escapando pra HTML executavel.
|
|
669
|
+
it('assunto com crase, &, aspas e <script> nao vaza entidade e nao escapa duas vezes no <h1>', async () => {
|
|
670
|
+
const { service } = makePreviewService();
|
|
671
|
+
|
|
672
|
+
const { html } = await service.preview('pt', {
|
|
673
|
+
subject: 'Tarefa `{{title}}` & "urgente" <script>alert(1)</script>',
|
|
674
|
+
body: '<p>Corpo</p>',
|
|
675
|
+
variables: { title: 'status' },
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
// Crase nunca vira entidade (renderMailTemplate/escapeHtml nem trata
|
|
679
|
+
// crase como caractere especial) — nem ` nem, pior, &#x60;.
|
|
680
|
+
expect(html).not.toContain('#x60;');
|
|
681
|
+
// & e " escapados exatamente uma vez (não &amp; / &quot;).
|
|
682
|
+
expect(html).toContain('&');
|
|
683
|
+
expect(html).not.toContain('&amp;');
|
|
684
|
+
expect(html).not.toContain('&quot;');
|
|
685
|
+
// <script> chega escapado, nunca como tag executável.
|
|
686
|
+
expect(html).not.toContain('<script>alert(1)</script>');
|
|
687
|
+
expect(html).toContain('<script>');
|
|
688
|
+
|
|
689
|
+
expect(html).toContain(
|
|
690
|
+
'<h1>Tarefa `status` & "urgente" <script>alert(1)</script></h1>',
|
|
691
|
+
);
|
|
692
|
+
});
|
|
693
|
+
|
|
582
694
|
it('produz exatamente o mesmo corpo que o envio real', async () => {
|
|
583
695
|
// Esta é a asserção que justifica o endpoint: o preview do admin não pode
|
|
584
696
|
// divergir do e-mail que sai. Os dois caminhos passam pelo mesmo
|
package/src/mail/mail.service.ts
CHANGED
|
@@ -8,9 +8,11 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_PRIMARY_COLOR,
|
|
10
10
|
DEFAULT_PRIMARY_FOREGROUND,
|
|
11
|
+
isFullHtmlDocument,
|
|
11
12
|
MailLayout,
|
|
12
13
|
MailService as MailMainService,
|
|
13
14
|
renderMailTemplate,
|
|
15
|
+
sanitizeAccentColor,
|
|
14
16
|
} from '@hed-hog/api-mail';
|
|
15
17
|
import { PaginationDTO } from '@hed-hog/api-pagination';
|
|
16
18
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
@@ -508,8 +510,14 @@ export class MailService implements OnModuleInit {
|
|
|
508
510
|
const brandName = await this.mailMainService.getBrandName(app, templateLocale);
|
|
509
511
|
const { primaryColor, primaryForeground } = await this.getThemeVariables();
|
|
510
512
|
const mergedVariables = { brandName, primaryColor, primaryForeground, ...variables };
|
|
511
|
-
const parsedSubject = this.interpolateTemplate(subject, mergedVariables);
|
|
513
|
+
const parsedSubject = this.interpolateTemplate(subject, mergedVariables, { escapeHtml: false });
|
|
512
514
|
const parsedBody = this.interpolateTemplate(body, mergedVariables);
|
|
515
|
+
// A cor da etapa vem do remetente (o commerce manda uma por slug) e chega
|
|
516
|
+
// ate o wrapper, que pinta a barra de destaque. `sanitizeAccentColor`
|
|
517
|
+
// descarta o que nao for `#rrggbb` porque o valor entra num bloco <style>.
|
|
518
|
+
const accentColor = sanitizeAccentColor(
|
|
519
|
+
typeof variables?.accentColor === 'string' ? variables.accentColor : undefined,
|
|
520
|
+
);
|
|
513
521
|
|
|
514
522
|
const sendResult: any = await this.mailMainService.send({
|
|
515
523
|
to: email,
|
|
@@ -517,6 +525,7 @@ export class MailService implements OnModuleInit {
|
|
|
517
525
|
...(resolvedReplyTo ? { replyTo: resolvedReplyTo } : {}),
|
|
518
526
|
subject: parsedSubject,
|
|
519
527
|
body: parsedBody,
|
|
528
|
+
...(accentColor ? { accentColor } : {}),
|
|
520
529
|
mail_id: mail.id,
|
|
521
530
|
// O layout (header/footer) e escolhido por este locale la no api-mail,
|
|
522
531
|
// entao tem que ser o do template escolhido, nao o cru do request.
|
|
@@ -662,12 +671,31 @@ export class MailService implements OnModuleInit {
|
|
|
662
671
|
return mail;
|
|
663
672
|
}
|
|
664
673
|
|
|
674
|
+
/**
|
|
675
|
+
* `escapeHtml` (default true) controla o escape padrao do Handlebars pra
|
|
676
|
+
* `&`, `<`, `>`, `"`, `'` e crase. O corpo e HTML de verdade e precisa dele;
|
|
677
|
+
* o assunto e texto puro (vira o header `subject:` do e-mail e, no corpo,
|
|
678
|
+
* passa de novo por `renderMailTemplate`/`escapeHtml` do `@hed-hog/api-mail`
|
|
679
|
+
* pra virar o `<h1>`) — escapar aqui tambem faria uma crase no assunto virar
|
|
680
|
+
* ``` cru na caixa de entrada, e depois `&#x60;` no `<h1>` (escape
|
|
681
|
+
* duplo). Quem chama pro assunto passa `{ escapeHtml: false }`.
|
|
682
|
+
*/
|
|
665
683
|
private interpolateTemplate(
|
|
666
684
|
source: string,
|
|
667
685
|
data: any,
|
|
686
|
+
{ escapeHtml = true }: { escapeHtml?: boolean } = {},
|
|
668
687
|
): string {
|
|
669
688
|
try {
|
|
670
|
-
|
|
689
|
+
// Um documento HTML completo (<style>/<head>/<script>) tem quebra de
|
|
690
|
+
// linha significativa dentro dessas tags — trocar por <br/> às cegas
|
|
691
|
+
// quebra o CSS/HTML (renderMailTemplate já pula o wrapper pra esse
|
|
692
|
+
// caso; aqui só espelhamos a mesma detecção pra não mutilar antes
|
|
693
|
+
// disso). Emails simples (sem <html>) continuam ganhando <br/> pra
|
|
694
|
+
// preservar quebras de linha digitadas pelo usuário.
|
|
695
|
+
const normalized = isFullHtmlDocument(source)
|
|
696
|
+
? source
|
|
697
|
+
: source.replace(/(\r\n|\n|\r)/g, '<br/>');
|
|
698
|
+
const template = Handlebars.compile(normalized, { noEscape: !escapeHtml });
|
|
671
699
|
return template(data);
|
|
672
700
|
} catch (error: any) {
|
|
673
701
|
this.logger.error('Handlebars template compilation error:', error);
|
|
@@ -741,7 +769,7 @@ export class MailService implements OnModuleInit {
|
|
|
741
769
|
? (await this.brandAsset.resolveAssetUrl(rawLogoUrl)) || undefined
|
|
742
770
|
: undefined;
|
|
743
771
|
const data = { brandName, primaryColor, primaryForeground, ...(variables || {}) };
|
|
744
|
-
const parsedSubject = subject ? this.interpolateTemplate(subject, data) : '';
|
|
772
|
+
const parsedSubject = subject ? this.interpolateTemplate(subject, data, { escapeHtml: false }) : '';
|
|
745
773
|
const parsedBody = body ? this.interpolateTemplate(body, data) : '';
|
|
746
774
|
|
|
747
775
|
let resolvedLayout: MailLayout | null = null;
|
|
@@ -765,6 +793,11 @@ export class MailService implements OnModuleInit {
|
|
|
765
793
|
brandName,
|
|
766
794
|
primaryColor,
|
|
767
795
|
primaryForeground,
|
|
796
|
+
// Mesma leitura do envio: sem isto a pre-visualizacao do admin mostraria a
|
|
797
|
+
// barra na cor da marca e o e-mail sairia na cor da etapa.
|
|
798
|
+
accentColor: sanitizeAccentColor(
|
|
799
|
+
typeof variables?.accentColor === 'string' ? variables.accentColor : undefined,
|
|
800
|
+
),
|
|
768
801
|
logoUrl,
|
|
769
802
|
lang: locale,
|
|
770
803
|
});
|
|
@@ -792,13 +825,18 @@ export class MailService implements OnModuleInit {
|
|
|
792
825
|
const brandName = await this.mailMainService.getBrandName(undefined, locale);
|
|
793
826
|
const { primaryColor, primaryForeground } = await this.getThemeVariables();
|
|
794
827
|
const mergedVariables = { brandName, primaryColor, primaryForeground, ...(variables || {}) };
|
|
795
|
-
const parsedSubject = this.interpolateTemplate(subject, mergedVariables);
|
|
828
|
+
const parsedSubject = this.interpolateTemplate(subject, mergedVariables, { escapeHtml: false });
|
|
796
829
|
const parsedBody = this.interpolateTemplate(body, mergedVariables);
|
|
797
830
|
|
|
831
|
+
const accentColor = sanitizeAccentColor(
|
|
832
|
+
typeof variables?.accentColor === 'string' ? variables.accentColor : undefined,
|
|
833
|
+
);
|
|
834
|
+
|
|
798
835
|
return this.mailMainService.send({
|
|
799
836
|
to: email,
|
|
800
837
|
subject: parsedSubject,
|
|
801
838
|
body: parsedBody,
|
|
839
|
+
...(accentColor ? { accentColor } : {}),
|
|
802
840
|
mail_id: mail.id,
|
|
803
841
|
from,
|
|
804
842
|
locale,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { CreateDTO } from './dto/create.dto';
|
|
13
13
|
import { QueryMailSentListDTO } from './dto/query-mail-sent-list.dto';
|
|
14
14
|
import { UpdateDTO } from './dto/update.dto';
|
|
15
|
+
import { MAIL_SENT_SORT } from './mail-sent.sort';
|
|
15
16
|
|
|
16
17
|
type MailSentUserStatus = 'received' | 'read' | 'error';
|
|
17
18
|
|
|
@@ -186,6 +187,8 @@ export class MailSentService {
|
|
|
186
187
|
},
|
|
187
188
|
},
|
|
188
189
|
},
|
|
190
|
+
undefined,
|
|
191
|
+
{ sort: MAIL_SENT_SORT },
|
|
189
192
|
);
|
|
190
193
|
|
|
191
194
|
const data = (result.data as MailSentWithUsers[]).map((item) => {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineSortable } from '@hed-hog/api-pagination';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Campos ordenáveis de `mail_sent`.
|
|
5
|
+
*
|
|
6
|
+
* "Delivery" (o badge exibido na listagem) fica de fora: é um resumo agregado
|
|
7
|
+
* calculado no service a partir de `mail_sent_user` (to-many), não uma coluna
|
|
8
|
+
* — o Prisma não tem como ordenar por ele.
|
|
9
|
+
*/
|
|
10
|
+
export const MAIL_SENT_SORT = defineSortable(
|
|
11
|
+
{
|
|
12
|
+
subject: true,
|
|
13
|
+
from: true,
|
|
14
|
+
to: true,
|
|
15
|
+
created_at: { initialOrder: 'desc' },
|
|
16
|
+
id: { initialOrder: 'desc' },
|
|
17
|
+
},
|
|
18
|
+
{ default: 'created_at', defaultOrder: 'desc' },
|
|
19
|
+
);
|