@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
|
@@ -18,11 +18,25 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
18
18
|
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
19
19
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
20
20
|
};
|
|
21
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
22
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
23
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
24
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
25
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
26
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
27
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
28
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
29
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
30
|
+
function fulfill(value) { resume("next", value); }
|
|
31
|
+
function reject(value) { resume("throw", value); }
|
|
32
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
33
|
+
};
|
|
21
34
|
var _a;
|
|
22
35
|
var FileService_1;
|
|
23
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
37
|
exports.FileService = void 0;
|
|
25
38
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
39
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
26
40
|
const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
27
41
|
const client_sts_1 = require("@aws-sdk/client-sts");
|
|
28
42
|
const api_locale_1 = require("@hed-hog/api-locale");
|
|
@@ -30,6 +44,7 @@ const api_pagination_1 = require("@hed-hog/api-pagination");
|
|
|
30
44
|
const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
31
45
|
const common_1 = require("@nestjs/common");
|
|
32
46
|
const jwt_1 = require("@nestjs/jwt");
|
|
47
|
+
const crypto_1 = require("crypto");
|
|
33
48
|
const fs_1 = require("fs");
|
|
34
49
|
const os_1 = require("os");
|
|
35
50
|
const path_1 = require("path");
|
|
@@ -37,6 +52,8 @@ const promises_1 = require("stream/promises");
|
|
|
37
52
|
const uuid_1 = require("uuid");
|
|
38
53
|
const integration_profile_utils_1 = require("../integration-profile/integration-profile.utils");
|
|
39
54
|
const setting_service_1 = require("../setting/setting.service");
|
|
55
|
+
const filename_encoding_util_1 = require("./filename-encoding.util");
|
|
56
|
+
const mimetype_sniff_util_1 = require("./mimetype-sniff.util");
|
|
40
57
|
const image_optimization_service_1 = require("./image-optimization.service");
|
|
41
58
|
const abstract_provider_1 = require("./provider/abstract.provider");
|
|
42
59
|
const provider_factory_1 = require("./provider/provider.factory");
|
|
@@ -56,18 +73,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
56
73
|
}
|
|
57
74
|
return `${file.location}/${file.path}`;
|
|
58
75
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Nome que chegou com o encoding trocado (busboy entrega `originalname` em
|
|
78
|
+
* latin1, e a base ainda recebe nome importado com o mesmo defeito). A lógica
|
|
79
|
+
* mora no util porque a migration de backfill a reproduz em plpgsql.
|
|
80
|
+
*/
|
|
62
81
|
normalizeUploadedFilename(filename) {
|
|
63
|
-
|
|
64
|
-
return filename;
|
|
65
|
-
}
|
|
66
|
-
if (!this.hasMojibake(filename)) {
|
|
67
|
-
return filename;
|
|
68
|
-
}
|
|
69
|
-
const decoded = Buffer.from(filename, 'latin1').toString('utf8');
|
|
70
|
-
return this.hasMojibake(decoded) ? filename : decoded;
|
|
82
|
+
return filename ? (0, filename_encoding_util_1.fixMojibake)(filename) : filename;
|
|
71
83
|
}
|
|
72
84
|
constructor(prismaService, paginationService, settingService, jwtService, imageOptimizationService) {
|
|
73
85
|
this.prismaService = prismaService;
|
|
@@ -79,6 +91,8 @@ let FileService = FileService_1 = class FileService {
|
|
|
79
91
|
this.mimetypes = {};
|
|
80
92
|
this.cachedProvider = null;
|
|
81
93
|
this.providerResolution = null;
|
|
94
|
+
/** Cache curto de papéis, no mesmo espírito do McpPermissionService. */
|
|
95
|
+
this.fileAdminCache = new Map();
|
|
82
96
|
}
|
|
83
97
|
async onModuleInit() {
|
|
84
98
|
try {
|
|
@@ -397,7 +411,7 @@ let FileService = FileService_1 = class FileService {
|
|
|
397
411
|
// repassa este argumento, então não há como acioná-lo por HTTP.
|
|
398
412
|
// `isPrivate` tira o arquivo das rotas que servem por id sem autenticação.
|
|
399
413
|
options) {
|
|
400
|
-
var _a;
|
|
414
|
+
var _a, _b;
|
|
401
415
|
if (!fileBuffer) {
|
|
402
416
|
throw new common_1.BadRequestException(`No file provided`);
|
|
403
417
|
}
|
|
@@ -426,12 +440,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
426
440
|
mimetype_id: await this.getMimeType(optimized.mimetype),
|
|
427
441
|
size: optimized.buffer.length,
|
|
428
442
|
is_private: (_a = options === null || options === void 0 ? void 0 : options.isPrivate) !== null && _a !== void 0 ? _a : false,
|
|
443
|
+
created_by_user_id: (_b = options === null || options === void 0 ? void 0 : options.createdByUserId) !== null && _b !== void 0 ? _b : null,
|
|
429
444
|
},
|
|
430
445
|
});
|
|
431
446
|
return file;
|
|
432
447
|
}
|
|
433
448
|
async uploadFromPath(destination, filePath, metadata) {
|
|
434
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
449
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
435
450
|
if (!filePath) {
|
|
436
451
|
throw new common_1.BadRequestException(`No file path provided`);
|
|
437
452
|
}
|
|
@@ -446,7 +461,14 @@ let FileService = FileService_1 = class FileService {
|
|
|
446
461
|
const originalname = this.normalizeUploadedFilename((_c = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.originalname) !== null && _b !== void 0 ? _b : metadata === null || metadata === void 0 ? void 0 : metadata.filename) !== null && _c !== void 0 ? _c : (0, path_1.basename)(filePath));
|
|
447
462
|
// Recupera o tipo real quando o caller não informou o mimetype (default antigo era
|
|
448
463
|
// application/octet-stream, que fazia imagens caírem fora da otimização e do serve).
|
|
449
|
-
|
|
464
|
+
// Diferente de `upload`, aqui só existe um caminho no disco — e ler o arquivo inteiro
|
|
465
|
+
// é justamente o que o branch de streaming abaixo evita para SCORM/vídeo de vários GB.
|
|
466
|
+
// Por isso o sniffing recebe só o cabeçalho, e apenas quando o caller não declarou um
|
|
467
|
+
// tipo concreto: sem isso, uma imagem enviada como application/octet-stream sem
|
|
468
|
+
// extensão no nome escapava da otimização e era gravada byte a byte.
|
|
469
|
+
const declaredMimetype = metadata === null || metadata === void 0 ? void 0 : metadata.mimetype;
|
|
470
|
+
const isGenericMimetype = !declaredMimetype || declaredMimetype === 'application/octet-stream';
|
|
471
|
+
const mimetype = await this.resolveEffectiveMimetype(declaredMimetype, originalname, isGenericMimetype ? await this.readFileHeader(filePath) : undefined);
|
|
450
472
|
if (!(metadata === null || metadata === void 0 ? void 0 : metadata.skipMimeValidation) && !(await this.acceptMimetypes(mimetype))) {
|
|
451
473
|
throw new common_1.BadRequestException(`Invalid file type: ${mimetype}`);
|
|
452
474
|
}
|
|
@@ -473,19 +495,20 @@ let FileService = FileService_1 = class FileService {
|
|
|
473
495
|
mimetype_id: await this.getMimeType(mimetype),
|
|
474
496
|
size,
|
|
475
497
|
is_private: (_d = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _d !== void 0 ? _d : false,
|
|
498
|
+
created_by_user_id: (_e = metadata === null || metadata === void 0 ? void 0 : metadata.createdByUserId) !== null && _e !== void 0 ? _e : null,
|
|
476
499
|
},
|
|
477
500
|
});
|
|
478
501
|
}
|
|
479
502
|
// Read buffer to allow image optimization regardless of provider support
|
|
480
503
|
const rawBuffer = await fs_1.promises.readFile(filePath);
|
|
481
504
|
const optimized = await this.imageOptimizationService.optimizeBuffer(rawBuffer, mimetype, originalname, {
|
|
482
|
-
maxWidth: (
|
|
483
|
-
maxHeight: (
|
|
505
|
+
maxWidth: (_f = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _f === void 0 ? void 0 : _f.maxWidth,
|
|
506
|
+
maxHeight: (_g = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _g === void 0 ? void 0 : _g.maxHeight,
|
|
484
507
|
});
|
|
485
508
|
const url = await provider.upload(destination, {
|
|
486
509
|
fieldname: 'file',
|
|
487
510
|
originalname: optimized.originalname,
|
|
488
|
-
encoding: (
|
|
511
|
+
encoding: (_h = metadata === null || metadata === void 0 ? void 0 : metadata.encoding) !== null && _h !== void 0 ? _h : '7bit',
|
|
489
512
|
mimetype: optimized.mimetype,
|
|
490
513
|
size: optimized.buffer.length,
|
|
491
514
|
destination: '',
|
|
@@ -501,19 +524,68 @@ let FileService = FileService_1 = class FileService {
|
|
|
501
524
|
location: destination,
|
|
502
525
|
mimetype_id: await this.getMimeType(optimized.mimetype),
|
|
503
526
|
size: optimized.buffer.length,
|
|
504
|
-
is_private: (
|
|
527
|
+
is_private: (_j = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _j !== void 0 ? _j : false,
|
|
528
|
+
created_by_user_id: (_k = metadata === null || metadata === void 0 ? void 0 : metadata.createdByUserId) !== null && _k !== void 0 ? _k : null,
|
|
505
529
|
},
|
|
506
530
|
});
|
|
507
531
|
return file;
|
|
508
532
|
}
|
|
533
|
+
/**
|
|
534
|
+
* Lista as imagens armazenadas que valem uma passada por `reoptimizeFile`, para a
|
|
535
|
+
* operação em massa de reprocessamento do acervo.
|
|
536
|
+
*
|
|
537
|
+
* Devolve junto o total e a soma de bytes do filtro inteiro (não só da página), que é
|
|
538
|
+
* o que permite mostrar uma prévia antes de enfileirar dezenas de milhares de jobs.
|
|
539
|
+
* O core não conhece a fila — quem enfileira é a library `queue`, que depende deste
|
|
540
|
+
* pacote e não o contrário.
|
|
541
|
+
*/
|
|
542
|
+
async findOptimizableImages(params) {
|
|
543
|
+
var _a, _b, _c;
|
|
544
|
+
const minSize = Math.max(0, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.minSize) || 0));
|
|
545
|
+
const locations = ((_a = params === null || params === void 0 ? void 0 : params.locations) !== null && _a !== void 0 ? _a : [])
|
|
546
|
+
.map((location) => String(location).trim())
|
|
547
|
+
.filter(Boolean);
|
|
548
|
+
const where = {
|
|
549
|
+
size: { gte: minSize },
|
|
550
|
+
file_mimetype: {
|
|
551
|
+
name: {
|
|
552
|
+
startsWith: 'image/',
|
|
553
|
+
notIn: FileService_1.NON_OPTIMIZABLE_IMAGE_MIMETYPES,
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
};
|
|
557
|
+
if (locations.length) {
|
|
558
|
+
where.location = { in: locations };
|
|
559
|
+
}
|
|
560
|
+
const [aggregate, rows] = await Promise.all([
|
|
561
|
+
this.prismaService.file.aggregate({
|
|
562
|
+
where,
|
|
563
|
+
_count: { _all: true },
|
|
564
|
+
_sum: { size: true },
|
|
565
|
+
}),
|
|
566
|
+
this.prismaService.file.findMany({
|
|
567
|
+
where,
|
|
568
|
+
select: { id: true },
|
|
569
|
+
// Ordem estável para que o enfileiramento paginado não pule nem repita linhas.
|
|
570
|
+
orderBy: { id: 'asc' },
|
|
571
|
+
skip: Math.max(0, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.offset) || 0)),
|
|
572
|
+
take: Math.min(5000, Math.max(1, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.limit) || 1000))),
|
|
573
|
+
}),
|
|
574
|
+
]);
|
|
575
|
+
return {
|
|
576
|
+
ids: rows.map((row) => row.id),
|
|
577
|
+
total: (_b = aggregate._count._all) !== null && _b !== void 0 ? _b : 0,
|
|
578
|
+
totalBytes: Number((_c = aggregate._sum.size) !== null && _c !== void 0 ? _c : 0),
|
|
579
|
+
};
|
|
580
|
+
}
|
|
509
581
|
/**
|
|
510
582
|
* Re-applies the current image-optimization settings to an already-stored file,
|
|
511
583
|
* rewriting it in place: the `file` record keeps the same id, so every row that
|
|
512
584
|
* references it (course_image, course_lesson_video_frame, ...) stays valid without
|
|
513
|
-
* any FK juggling. Only replaces the stored object when the
|
|
514
|
-
*
|
|
515
|
-
* operation idempotent and avoids repeated
|
|
516
|
-
* left untouched.
|
|
585
|
+
* any FK juggling. Only replaces the stored object when the mimetype changed
|
|
586
|
+
* (e.g. PNG → WebP) or the result is smaller by a margin that justifies the rewrite —
|
|
587
|
+
* that margin is what actually makes the operation idempotent and avoids repeated
|
|
588
|
+
* lossy recompression. Non-image files are left untouched.
|
|
517
589
|
*/
|
|
518
590
|
async reoptimizeFile(fileId) {
|
|
519
591
|
var _a;
|
|
@@ -525,8 +597,13 @@ let FileService = FileService_1 = class FileService {
|
|
|
525
597
|
}
|
|
526
598
|
const optimized = await this.imageOptimizationService.optimizeBuffer(buffer, currentMimetype, file.filename);
|
|
527
599
|
const mimetypeChanged = optimized.mimetype !== currentMimetype;
|
|
528
|
-
|
|
529
|
-
|
|
600
|
+
// Mudança de formato é o ganho principal (PNG → WebP) e vale por si; sem ela, só
|
|
601
|
+
// regrava quando a economia passa do limiar. `optimizeBuffer` já garante que o
|
|
602
|
+
// resultado nunca é maior que a entrada neste caminho (sem crop de alvo exato).
|
|
603
|
+
const worthRewriting = oldSize > 0 &&
|
|
604
|
+
(oldSize - optimized.buffer.length) / oldSize >=
|
|
605
|
+
FileService_1.REOPTIMIZE_MIN_GAIN_RATIO;
|
|
606
|
+
if (!mimetypeChanged && !worthRewriting) {
|
|
530
607
|
return {
|
|
531
608
|
changed: false,
|
|
532
609
|
oldSize,
|
|
@@ -602,14 +679,181 @@ let FileService = FileService_1 = class FileService {
|
|
|
602
679
|
}
|
|
603
680
|
return files.map((file) => file.id);
|
|
604
681
|
}
|
|
605
|
-
|
|
682
|
+
/**
|
|
683
|
+
* `ownerUserId` restringe a listagem aos arquivos enviados por aquele usuário.
|
|
684
|
+
*
|
|
685
|
+
* Existe para as tools MCP: sem ele, `core.files.list` é um índice de tudo o que
|
|
686
|
+
* qualquer empresa já subiu, incluindo o que está gravado como `is_private`. O
|
|
687
|
+
* controller REST continua chamando sem o parâmetro, porque ali a rota já é `admin`
|
|
688
|
+
* e a tela de arquivos é justamente a visão global.
|
|
689
|
+
*/
|
|
690
|
+
/**
|
|
691
|
+
* Grava um stream em disco medindo, hasheando e guardando o cabeçalho de uma vez só.
|
|
692
|
+
*
|
|
693
|
+
* O upload assinado recebe o binário cru no corpo do PUT, e nada garante que venha com
|
|
694
|
+
* `Content-Length` — sem o contador abaixo, um corpo aberto encheria o disco do pod. O
|
|
695
|
+
* corte é feito em pleno voo, antes de o excedente chegar ao arquivo.
|
|
696
|
+
*
|
|
697
|
+
* Passa o cabeçalho adiante porque conferir o tipo real é obrigatório nesse caminho, e
|
|
698
|
+
* reler o arquivo depois seria uma segunda passada por nada.
|
|
699
|
+
*/
|
|
700
|
+
async writeStreamToPath(source, targetPath, maxBytes) {
|
|
701
|
+
const hash = (0, crypto_1.createHash)('sha256');
|
|
702
|
+
const headerChunks = [];
|
|
703
|
+
let headerLength = 0;
|
|
704
|
+
let bytes = 0;
|
|
705
|
+
const target = (0, fs_1.createWriteStream)(targetPath);
|
|
706
|
+
await (0, promises_1.pipeline)(source, function (chunks) {
|
|
707
|
+
return __asyncGenerator(this, arguments, function* () {
|
|
708
|
+
var _a, e_1, _b, _c;
|
|
709
|
+
try {
|
|
710
|
+
for (var _d = true, chunks_1 = __asyncValues(chunks), chunks_1_1; chunks_1_1 = yield __await(chunks_1.next()), _a = chunks_1_1.done, !_a; _d = true) {
|
|
711
|
+
_c = chunks_1_1.value;
|
|
712
|
+
_d = false;
|
|
713
|
+
const chunk = _c;
|
|
714
|
+
const buffer = Buffer.from(chunk);
|
|
715
|
+
bytes += buffer.length;
|
|
716
|
+
if (bytes > maxBytes) {
|
|
717
|
+
throw new common_1.BadRequestException(`Upload exceeds the declared size of ${maxBytes} bytes`);
|
|
718
|
+
}
|
|
719
|
+
hash.update(buffer);
|
|
720
|
+
if (headerLength < mimetype_sniff_util_1.MIMETYPE_SNIFF_BYTES) {
|
|
721
|
+
const slice = buffer.subarray(0, mimetype_sniff_util_1.MIMETYPE_SNIFF_BYTES - headerLength);
|
|
722
|
+
headerChunks.push(slice);
|
|
723
|
+
headerLength += slice.length;
|
|
724
|
+
}
|
|
725
|
+
yield yield __await(buffer);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
729
|
+
finally {
|
|
730
|
+
try {
|
|
731
|
+
if (!_d && !_a && (_b = chunks_1.return)) yield __await(_b.call(chunks_1));
|
|
732
|
+
}
|
|
733
|
+
finally { if (e_1) throw e_1.error; }
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
}, target);
|
|
737
|
+
return {
|
|
738
|
+
bytes,
|
|
739
|
+
sha256: hash.digest('hex'),
|
|
740
|
+
header: Buffer.concat(headerChunks),
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Conteúdo de um arquivo já armazenado, em memória.
|
|
745
|
+
*
|
|
746
|
+
* Existe para as tools que consomem os bytes sem persistir nada (importar extrato,
|
|
747
|
+
* extrair dados de uma nota com IA): elas recebem um `fileId` e precisam do arquivo,
|
|
748
|
+
* não de um stream. O teto evita que um `fileId` apontando para um SCORM de vários GB
|
|
749
|
+
* derrube o pod — quem serve arquivo grande usa `openReadStream` e não passa por aqui.
|
|
750
|
+
*/
|
|
751
|
+
async bufferById(fileId, maxBytes) {
|
|
752
|
+
var _a, e_2, _b, _c;
|
|
753
|
+
var _d, _e;
|
|
754
|
+
const { stream } = await this.openReadStreamById(fileId);
|
|
755
|
+
const chunks = [];
|
|
756
|
+
let total = 0;
|
|
757
|
+
try {
|
|
758
|
+
for (var _f = true, _g = __asyncValues(stream), _h; _h = await _g.next(), _a = _h.done, !_a; _f = true) {
|
|
759
|
+
_c = _h.value;
|
|
760
|
+
_f = false;
|
|
761
|
+
const chunk = _c;
|
|
762
|
+
total += chunk.length;
|
|
763
|
+
if (total > maxBytes) {
|
|
764
|
+
(_e = (_d = stream).destroy) === null || _e === void 0 ? void 0 : _e.call(_d);
|
|
765
|
+
throw new common_1.BadRequestException(`File ${fileId} is larger than the ${maxBytes} bytes this operation can load`);
|
|
766
|
+
}
|
|
767
|
+
chunks.push(Buffer.from(chunk));
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
771
|
+
finally {
|
|
772
|
+
try {
|
|
773
|
+
if (!_f && !_a && (_b = _g.return)) await _b.call(_g);
|
|
774
|
+
}
|
|
775
|
+
finally { if (e_2) throw e_2.error; }
|
|
776
|
+
}
|
|
777
|
+
return Buffer.concat(chunks);
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Nome do mimetype de um arquivo.
|
|
781
|
+
*
|
|
782
|
+
* `get()` e `upload()` devolvem a linha crua, sem a relação, e cada chamador que
|
|
783
|
+
* precisava do tipo vinha refazendo o `include` por conta. Como o cache de
|
|
784
|
+
* `getMimeType` é id-por-nome, este é o inverso dele e sai do mesmo mapa quando já
|
|
785
|
+
* tiver sido consultado.
|
|
786
|
+
*/
|
|
787
|
+
async mimetypeNameById(mimetypeId) {
|
|
788
|
+
const cached = Object.entries(this.mimetypes).find(([, id]) => id === mimetypeId);
|
|
789
|
+
if (cached) {
|
|
790
|
+
return cached[0];
|
|
791
|
+
}
|
|
792
|
+
const row = await this.prismaService.file_mimetype.findUnique({
|
|
793
|
+
where: { id: mimetypeId },
|
|
794
|
+
select: { name: true },
|
|
795
|
+
});
|
|
796
|
+
if (row === null || row === void 0 ? void 0 : row.name) {
|
|
797
|
+
this.mimetypes[row.name] = mimetypeId;
|
|
798
|
+
return row.name;
|
|
799
|
+
}
|
|
800
|
+
return 'application/octet-stream';
|
|
801
|
+
}
|
|
802
|
+
async getFiles(paginationParams, ownerUserId) {
|
|
606
803
|
const fields = ['filename', 'path'];
|
|
607
804
|
const OR = this.prismaService.createInsensitiveSearch(fields, paginationParams);
|
|
608
805
|
return this.paginationService.paginate(this.prismaService.file, paginationParams, {
|
|
806
|
+
where: Object.assign({ OR }, (ownerUserId ? { created_by_user_id: ownerUserId } : {})),
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
async isFileAdmin(userId) {
|
|
810
|
+
const cached = this.fileAdminCache.get(userId);
|
|
811
|
+
if (cached && Date.now() - cached.at < FileService_1.FILE_ADMIN_CACHE_TTL_MS) {
|
|
812
|
+
return cached.value;
|
|
813
|
+
}
|
|
814
|
+
const found = await this.prismaService.role_user.findFirst({
|
|
609
815
|
where: {
|
|
610
|
-
|
|
816
|
+
user_id: userId,
|
|
817
|
+
role: { slug: { in: FileService_1.FILE_ADMIN_ROLES } },
|
|
611
818
|
},
|
|
819
|
+
select: { role_id: true },
|
|
612
820
|
});
|
|
821
|
+
const value = Boolean(found);
|
|
822
|
+
this.fileAdminCache.set(userId, { value, at: Date.now() });
|
|
823
|
+
return value;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Porteiro do `fileId` vindo de fora: só o dono usa um arquivo, e quem administra o
|
|
827
|
+
* acervo usa qualquer um.
|
|
828
|
+
*
|
|
829
|
+
* Sem isto, apontar um `fileId` numa tool seria enumerar — id de arquivo é sequencial,
|
|
830
|
+
* exatamente o motivo pelo qual `is_private` existe. Arquivo anterior a esta coluna
|
|
831
|
+
* (ou gravado por cron/seed/webhook) fica com dono nulo e só o admin alcança: não dá
|
|
832
|
+
* para provar de quem ele é, e adivinhar a favor do chamador seria abrir a porta que
|
|
833
|
+
* este método fecha.
|
|
834
|
+
*/
|
|
835
|
+
async assertFileUsable(fileId, userId) {
|
|
836
|
+
if (!Number.isInteger(fileId) || fileId <= 0) {
|
|
837
|
+
throw new common_1.BadRequestException(`Invalid file id: ${fileId}`);
|
|
838
|
+
}
|
|
839
|
+
const file = await this.prismaService.file.findUnique({
|
|
840
|
+
where: { id: fileId },
|
|
841
|
+
include: { file_mimetype: true },
|
|
842
|
+
});
|
|
843
|
+
// Mesma resposta para inexistente e para alheio seria o ideal contra enumeração, mas
|
|
844
|
+
// `get()` já responde 404 com o id, e divergir aqui só confundiria quem integra.
|
|
845
|
+
if (!file) {
|
|
846
|
+
throw new common_1.NotFoundException(`File not found: ${fileId}`);
|
|
847
|
+
}
|
|
848
|
+
if (file.created_by_user_id === userId) {
|
|
849
|
+
return file;
|
|
850
|
+
}
|
|
851
|
+
if (await this.isFileAdmin(userId)) {
|
|
852
|
+
return file;
|
|
853
|
+
}
|
|
854
|
+
throw new common_1.ForbiddenException(file.created_by_user_id === null
|
|
855
|
+
? `File ${fileId} has no recorded owner and can only be used by an administrator`
|
|
856
|
+
: `File ${fileId} belongs to another user`);
|
|
613
857
|
}
|
|
614
858
|
async get(fileId) {
|
|
615
859
|
const file = await this.prismaService.file.findUnique({
|
|
@@ -743,19 +987,44 @@ let FileService = FileService_1 = class FileService {
|
|
|
743
987
|
}
|
|
744
988
|
return undefined;
|
|
745
989
|
}
|
|
990
|
+
/**
|
|
991
|
+
* Resolve o `file` cujo `resolveProviderPath` (location + path, ou path já combinado) bate com
|
|
992
|
+
* o `filepath` embutido no token de download — é o inverso de `resolveProviderPath`.
|
|
993
|
+
*
|
|
994
|
+
* Bug corrigido (relatado como "Token de download inválido ou expirado" no storage local):
|
|
995
|
+
* `tempURLById` assina o token com `resolveProviderPath(file)` (ex.:
|
|
996
|
+
* "class-assignment-tasks/abc123.pdf", já com o prefixo de `location`), mas o upload local/S3
|
|
997
|
+
* grava só o basename em `file.path` ("abc123.pdf") e o `location` separado em outra coluna.
|
|
998
|
+
* Um `findFirst({ where: { path: filepath } })` direto nunca batia para esses arquivos — sempre
|
|
999
|
+
* caía no `catch` abaixo e mostrava a mensagem genérica de token inválido, mesmo com o token
|
|
1000
|
+
* (e o arquivo) perfeitamente válidos. S3 mascarava isso porque `S3Provider.tempURL` devolve uma
|
|
1001
|
+
* URL assinada direto do bucket, sem passar por este método.
|
|
1002
|
+
*/
|
|
1003
|
+
async findFileByResolvedPath(filepath) {
|
|
1004
|
+
const bySameValue = await this.prismaService.file.findFirst({
|
|
1005
|
+
where: { path: filepath },
|
|
1006
|
+
include: { file_mimetype: true },
|
|
1007
|
+
});
|
|
1008
|
+
if (bySameValue)
|
|
1009
|
+
return bySameValue;
|
|
1010
|
+
const slashIndex = filepath.lastIndexOf('/');
|
|
1011
|
+
if (slashIndex === -1)
|
|
1012
|
+
return null;
|
|
1013
|
+
return this.prismaService.file.findFirst({
|
|
1014
|
+
where: {
|
|
1015
|
+
location: filepath.slice(0, slashIndex),
|
|
1016
|
+
path: filepath.slice(slashIndex + 1),
|
|
1017
|
+
},
|
|
1018
|
+
include: { file_mimetype: true },
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
746
1021
|
async download(locale, token) {
|
|
747
1022
|
var _a;
|
|
748
1023
|
try {
|
|
749
1024
|
const { filepath } = this.jwtService.verify(token, {
|
|
750
1025
|
secret: process.env.JWT_SECRET,
|
|
751
1026
|
});
|
|
752
|
-
|
|
753
|
-
const file = await this.prismaService.file.findFirst({
|
|
754
|
-
where: { path: filepath },
|
|
755
|
-
include: {
|
|
756
|
-
file_mimetype: true,
|
|
757
|
-
},
|
|
758
|
-
});
|
|
1027
|
+
const file = await this.findFileByResolvedPath(filepath);
|
|
759
1028
|
if (!file) {
|
|
760
1029
|
throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('file.download.not_found', locale, `Not found: ${filepath}`));
|
|
761
1030
|
}
|
|
@@ -879,6 +1148,28 @@ let FileService = FileService_1 = class FileService {
|
|
|
879
1148
|
};
|
|
880
1149
|
return (_a = map[ext]) !== null && _a !== void 0 ? _a : null;
|
|
881
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Lê só o começo do arquivo, o bastante para o sharp reconhecer o formato pelo
|
|
1153
|
+
* cabeçalho. Existe para o sniffing de `uploadFromPath`, que não pode chamar
|
|
1154
|
+
* `fs.readFile`: o mesmo caminho recebe pacotes SCORM e vídeos de vários GB, e
|
|
1155
|
+
* carregá-los inteiros estoura o limite de Buffer. Devolve `undefined` em qualquer
|
|
1156
|
+
* falha de leitura — quem chama já trata a ausência do buffer.
|
|
1157
|
+
*/
|
|
1158
|
+
async readFileHeader(filePath, bytes = 64 * 1024) {
|
|
1159
|
+
let handle;
|
|
1160
|
+
try {
|
|
1161
|
+
handle = await fs_1.promises.open(filePath, 'r');
|
|
1162
|
+
const buffer = Buffer.alloc(bytes);
|
|
1163
|
+
const { bytesRead } = await handle.read(buffer, 0, bytes, 0);
|
|
1164
|
+
return bytesRead > 0 ? buffer.subarray(0, bytesRead) : undefined;
|
|
1165
|
+
}
|
|
1166
|
+
catch (_a) {
|
|
1167
|
+
return undefined;
|
|
1168
|
+
}
|
|
1169
|
+
finally {
|
|
1170
|
+
await (handle === null || handle === void 0 ? void 0 : handle.close().catch(() => undefined));
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
882
1173
|
/**
|
|
883
1174
|
* Resolves the MIME type to persist for an upload. When the incoming mimetype is
|
|
884
1175
|
* generic (application/octet-stream or empty), recovers the real image type from
|
|
@@ -1000,7 +1291,7 @@ let FileService = FileService_1 = class FileService {
|
|
|
1000
1291
|
* which the storage layer does not normally do — cannot serve stale bytes.
|
|
1001
1292
|
*/
|
|
1002
1293
|
async renderImageVariant(provider, providerPath, contentType, id, size, variant) {
|
|
1003
|
-
var _a,
|
|
1294
|
+
var _a, e_3, _b, _c;
|
|
1004
1295
|
var _d;
|
|
1005
1296
|
const format = (_d = variant.format) !== null && _d !== void 0 ? _d : (contentType === 'image/png'
|
|
1006
1297
|
? 'png'
|
|
@@ -1028,12 +1319,12 @@ let FileService = FileService_1 = class FileService {
|
|
|
1028
1319
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1029
1320
|
}
|
|
1030
1321
|
}
|
|
1031
|
-
catch (
|
|
1322
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
1032
1323
|
finally {
|
|
1033
1324
|
try {
|
|
1034
1325
|
if (!_f && !_a && (_b = stream_1.return)) await _b.call(stream_1);
|
|
1035
1326
|
}
|
|
1036
|
-
finally { if (
|
|
1327
|
+
finally { if (e_3) throw e_3.error; }
|
|
1037
1328
|
}
|
|
1038
1329
|
const original = Buffer.concat(chunks);
|
|
1039
1330
|
const rendered = await this.imageOptimizationService.resizeBuffer(original, contentType, { width: variant.width, format: variant.format, quality: variant.quality });
|
|
@@ -1096,6 +1387,14 @@ let FileService = FileService_1 = class FileService {
|
|
|
1096
1387
|
}
|
|
1097
1388
|
return url;
|
|
1098
1389
|
}
|
|
1390
|
+
/** Par de `tempURLById`, pela mesma razão: `path` cru resolve para NoSuchKey no S3. */
|
|
1391
|
+
async tempOpenURLById(fileId, expires = 3600) {
|
|
1392
|
+
const url = await this.tempURLById(fileId, expires);
|
|
1393
|
+
if (typeof url === 'string') {
|
|
1394
|
+
return url.replace('/file/download/', '/file/open/');
|
|
1395
|
+
}
|
|
1396
|
+
return url;
|
|
1397
|
+
}
|
|
1099
1398
|
async getTemporaryCredentials(params) {
|
|
1100
1399
|
const stsClient = new client_sts_1.STSClient({
|
|
1101
1400
|
region: params.region,
|
|
@@ -1131,6 +1430,30 @@ let FileService = FileService_1 = class FileService {
|
|
|
1131
1430
|
ETag: result.ETag,
|
|
1132
1431
|
};
|
|
1133
1432
|
}
|
|
1433
|
+
/**
|
|
1434
|
+
* URL assinada de um objeto em bucket avulso.
|
|
1435
|
+
*
|
|
1436
|
+
* O `getFileUrl` do provider resolve arquivos do acervo, que vivem no destino
|
|
1437
|
+
* ativo do core. Este metodo serve para os buckets que outras libraries
|
|
1438
|
+
* configuram por conta propria — o Studio grava no perfil de armazenamento
|
|
1439
|
+
* dele, que pode nao ser o mesmo — e por isso recebe as credenciais e o bucket
|
|
1440
|
+
* de fora, como o `headS3Object` ao lado.
|
|
1441
|
+
*/
|
|
1442
|
+
async signS3Object(params) {
|
|
1443
|
+
var _a;
|
|
1444
|
+
const s3 = new client_s3_1.S3Client({
|
|
1445
|
+
region: params.region,
|
|
1446
|
+
credentials: Object.assign({ accessKeyId: params.accessKeyId, secretAccessKey: params.secretAccessKey }, (params.sessionToken ? { sessionToken: params.sessionToken } : {})),
|
|
1447
|
+
});
|
|
1448
|
+
const command = new client_s3_1.GetObjectCommand(Object.assign({ Bucket: params.bucket, Key: params.key }, (params.downloadFileName
|
|
1449
|
+
? {
|
|
1450
|
+
ResponseContentDisposition: `attachment; filename="${params.downloadFileName.replace(/"/g, '')}"`,
|
|
1451
|
+
}
|
|
1452
|
+
: {})));
|
|
1453
|
+
return (0, s3_request_presigner_1.getSignedUrl)(s3, command, {
|
|
1454
|
+
expiresIn: (_a = params.expiresInSeconds) !== null && _a !== void 0 ? _a : 900,
|
|
1455
|
+
});
|
|
1456
|
+
}
|
|
1134
1457
|
async headS3Bucket(params) {
|
|
1135
1458
|
const s3 = new client_s3_1.S3Client({
|
|
1136
1459
|
region: params.region,
|
|
@@ -1382,6 +1705,32 @@ let FileService = FileService_1 = class FileService {
|
|
|
1382
1705
|
}
|
|
1383
1706
|
};
|
|
1384
1707
|
exports.FileService = FileService;
|
|
1708
|
+
/**
|
|
1709
|
+
* Mimetypes de imagem que `optimizeBuffer` devolve intactos por decisão de projeto
|
|
1710
|
+
* (vetor não vira bitmap, GIF animado não vira quadro único). Enfileirá-los para
|
|
1711
|
+
* reotimização seria custo de download e reprocessamento com resultado garantidamente
|
|
1712
|
+
* nulo, então ficam fora da varredura.
|
|
1713
|
+
*/
|
|
1714
|
+
FileService.NON_OPTIMIZABLE_IMAGE_MIMETYPES = [
|
|
1715
|
+
'image/svg+xml',
|
|
1716
|
+
'image/gif',
|
|
1717
|
+
];
|
|
1718
|
+
/**
|
|
1719
|
+
* Ganho mínimo para valer a regravação de um arquivo que já está no formato final.
|
|
1720
|
+
*
|
|
1721
|
+
* Recomprimir WebP sobre WebP sempre devolve alguns bytes a menos, então um limiar de
|
|
1722
|
+
* "estritamente menor" nunca converge: cada passada da varredura trocaria o arquivo
|
|
1723
|
+
* por um ganho irrisório e mais uma geração de perda de qualidade. Medido aqui, três
|
|
1724
|
+
* passadas seguidas rendiam 10926 → 10664 → 10662 bytes — a última custou uma
|
|
1725
|
+
* recompressão inteira para economizar 2 bytes.
|
|
1726
|
+
*/
|
|
1727
|
+
FileService.REOPTIMIZE_MIN_GAIN_RATIO = 0.1;
|
|
1728
|
+
/**
|
|
1729
|
+
* Papéis que enxergam qualquer arquivo. Os mesmos que já governam as rotas de arquivo
|
|
1730
|
+
* em `route.yaml` — quem administra o acervo pela tela também o administra pelo MCP.
|
|
1731
|
+
*/
|
|
1732
|
+
FileService.FILE_ADMIN_ROLES = ['admin', 'admin-access'];
|
|
1733
|
+
FileService.FILE_ADMIN_CACHE_TTL_MS = 30000;
|
|
1385
1734
|
exports.FileService = FileService = FileService_1 = __decorate([
|
|
1386
1735
|
(0, common_1.Injectable)(),
|
|
1387
1736
|
__param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_prisma_1.PrismaService))),
|