@hed-hog/core 0.0.387 → 0.0.390
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
- package/dist/access-log/access-log.interceptor.js +4 -2
- package/dist/access-log/access-log.interceptor.js.map +1 -1
- package/dist/ai/ai-attachment.fragments.d.ts +23 -0
- package/dist/ai/ai-attachment.fragments.d.ts.map +1 -0
- package/dist/ai/ai-attachment.fragments.js +34 -0
- package/dist/ai/ai-attachment.fragments.js.map +1 -0
- package/dist/ai/ai.controller.d.ts +7 -16
- package/dist/ai/ai.controller.d.ts.map +1 -1
- package/dist/ai/ai.prompts.d.ts +16 -0
- package/dist/ai/ai.prompts.d.ts.map +1 -0
- package/dist/ai/ai.prompts.js +37 -0
- package/dist/ai/ai.prompts.js.map +1 -0
- package/dist/ai/ai.service.d.ts +63 -12
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +215 -88
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai/dto/chat.dto.d.ts +4 -1
- package/dist/ai/dto/chat.dto.d.ts.map +1 -1
- package/dist/ai/dto/chat.dto.js +23 -1
- package/dist/ai/dto/chat.dto.js.map +1 -1
- package/dist/ai/dto/create-agent.dto.d.ts +1 -1
- package/dist/ai/dto/create-agent.dto.d.ts.map +1 -1
- package/dist/ai/dto/create-agent.dto.js +1 -1
- package/dist/ai/dto/create-agent.dto.js.map +1 -1
- package/dist/ai/dto/update-agent.dto.d.ts +1 -1
- package/dist/ai/dto/update-agent.dto.d.ts.map +1 -1
- package/dist/ai/dto/update-agent.dto.js +1 -1
- package/dist/ai/dto/update-agent.dto.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.controller.d.ts +61 -7
- package/dist/ai-instruction/ai-instruction.controller.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.controller.js +63 -20
- package/dist/ai-instruction/ai-instruction.controller.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.module.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.module.js +13 -2
- package/dist/ai-instruction/ai-instruction.module.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.d.ts +131 -6
- package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.js +533 -60
- package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
- package/dist/ai-instruction/ai-prompt-builder.service.d.ts +8 -0
- package/dist/ai-instruction/ai-prompt-builder.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-prompt-builder.service.js +10 -1
- package/dist/ai-instruction/ai-prompt-builder.service.js.map +1 -1
- package/dist/ai-instruction/ai-prompt-registry.d.ts +45 -0
- package/dist/ai-instruction/ai-prompt-registry.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-registry.js +49 -0
- package/dist/ai-instruction/ai-prompt-registry.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +89 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js +222 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-template.util.d.ts +70 -0
- package/dist/ai-instruction/ai-prompt-template.util.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-template.util.js +154 -0
- package/dist/ai-instruction/ai-prompt-template.util.js.map +1 -0
- package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts +5 -0
- package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts.map +1 -1
- package/dist/ai-instruction/dto/create-ai-instruction.dto.js +27 -1
- package/dist/ai-instruction/dto/create-ai-instruction.dto.js.map +1 -1
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts +14 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts.map +1 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.js +42 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.js.map +1 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts +11 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts.map +1 -1
- package/dist/ai-instruction/dto/update-ai-instruction.dto.js +34 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.js.map +1 -1
- package/dist/ai-instruction/types/ai-instruction.types.d.ts +13 -1
- package/dist/ai-instruction/types/ai-instruction.types.d.ts.map +1 -1
- package/dist/ai-instruction/types/ai-instruction.types.js +10 -0
- package/dist/ai-instruction/types/ai-instruction.types.js.map +1 -1
- package/dist/auth/auth.controller.d.ts +24 -9
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +49 -21
- package/dist/auth/auth.controller.js.map +1 -1
- package/dist/auth/auth.service.d.ts +33 -8
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +78 -29
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/captcha/captcha.module.d.ts +3 -0
- package/dist/captcha/captcha.module.d.ts.map +1 -0
- package/dist/captcha/captcha.module.js +23 -0
- package/dist/captcha/captcha.module.js.map +1 -0
- package/dist/captcha/captcha.service.d.ts +38 -0
- package/dist/captcha/captcha.service.d.ts.map +1 -0
- package/dist/captcha/captcha.service.js +144 -0
- package/dist/captcha/captcha.service.js.map +1 -0
- package/dist/challenge/challenge.service.d.ts +16 -7
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +64 -16
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/core.module.d.ts +3 -1
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +29 -2
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +15 -15
- package/dist/dashboard/dashboard/dashboard.service.d.ts +15 -15
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +6 -6
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +6 -6
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +20 -20
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +20 -20
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +13 -13
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +13 -13
- package/dist/file/file.service.d.ts +6 -0
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +44 -4
- package/dist/file/file.service.js.map +1 -1
- package/dist/incident/incident-notifier.service.d.ts +36 -0
- package/dist/incident/incident-notifier.service.d.ts.map +1 -0
- package/dist/incident/incident-notifier.service.js +208 -0
- package/dist/incident/incident-notifier.service.js.map +1 -0
- package/dist/incident/incident.controller.d.ts +23 -0
- package/dist/incident/incident.controller.d.ts.map +1 -0
- package/dist/incident/incident.controller.js +75 -0
- package/dist/incident/incident.controller.js.map +1 -0
- package/dist/incident/incident.module.d.ts +7 -0
- package/dist/incident/incident.module.d.ts.map +1 -0
- package/dist/incident/incident.module.js +32 -0
- package/dist/incident/incident.module.js.map +1 -0
- package/dist/incident/incident.service.d.ts +72 -0
- package/dist/incident/incident.service.d.ts.map +1 -0
- package/dist/incident/incident.service.js +184 -0
- package/dist/incident/incident.service.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-profile/dto/test.dto.d.ts +13 -0
- package/dist/integration-profile/dto/test.dto.d.ts.map +1 -0
- package/dist/integration-profile/dto/test.dto.js +26 -0
- package/dist/integration-profile/dto/test.dto.js.map +1 -0
- package/dist/integration-profile/integration-profile.controller.d.ts +12 -1
- package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.controller.js +9 -1
- package/dist/integration-profile/integration-profile.controller.js.map +1 -1
- package/dist/integration-profile/integration-profile.module.d.ts +6 -1
- package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.module.js +26 -3
- package/dist/integration-profile/integration-profile.module.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +9 -1
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +26 -7
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +94 -91
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +13 -1
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +20 -5
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/ai.testers.d.ts +3 -0
- package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/ai.testers.js +125 -0
- package/dist/integration-profile/testers/ai.testers.js.map +1 -0
- package/dist/integration-profile/testers/captcha.testers.d.ts +3 -0
- package/dist/integration-profile/testers/captcha.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/captcha.testers.js +121 -0
- package/dist/integration-profile/testers/captcha.testers.js.map +1 -0
- package/dist/integration-profile/testers/email.testers.d.ts +3 -0
- package/dist/integration-profile/testers/email.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/email.testers.js +128 -0
- package/dist/integration-profile/testers/email.testers.js.map +1 -0
- package/dist/integration-profile/testers/http-probe.d.ts +57 -0
- package/dist/integration-profile/testers/http-probe.d.ts.map +1 -0
- package/dist/integration-profile/testers/http-probe.js +140 -0
- package/dist/integration-profile/testers/http-probe.js.map +1 -0
- package/dist/integration-profile/testers/index.d.ts +12 -0
- package/dist/integration-profile/testers/index.d.ts.map +1 -0
- package/dist/integration-profile/testers/index.js +45 -0
- package/dist/integration-profile/testers/index.js.map +1 -0
- package/dist/integration-profile/testers/infrastructure.testers.d.ts +3 -0
- package/dist/integration-profile/testers/infrastructure.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/infrastructure.testers.js +105 -0
- package/dist/integration-profile/testers/infrastructure.testers.js.map +1 -0
- package/dist/integration-profile/testers/integration-tester.registry.d.ts +17 -0
- package/dist/integration-profile/testers/integration-tester.registry.d.ts.map +1 -0
- package/dist/integration-profile/testers/integration-tester.registry.js +52 -0
- package/dist/integration-profile/testers/integration-tester.registry.js.map +1 -0
- package/dist/integration-profile/testers/integration-tester.types.d.ts +55 -0
- package/dist/integration-profile/testers/integration-tester.types.d.ts.map +1 -0
- package/dist/integration-profile/testers/integration-tester.types.js +16 -0
- package/dist/integration-profile/testers/integration-tester.types.js.map +1 -0
- package/dist/integration-profile/testers/messaging.testers.d.ts +3 -0
- package/dist/integration-profile/testers/messaging.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/messaging.testers.js +70 -0
- package/dist/integration-profile/testers/messaging.testers.js.map +1 -0
- package/dist/integration-profile/testers/oauth.testers.d.ts +3 -0
- package/dist/integration-profile/testers/oauth.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/oauth.testers.js +285 -0
- package/dist/integration-profile/testers/oauth.testers.js.map +1 -0
- package/dist/integration-profile/testers/payment.testers.d.ts +3 -0
- package/dist/integration-profile/testers/payment.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/payment.testers.js +169 -0
- package/dist/integration-profile/testers/payment.testers.js.map +1 -0
- package/dist/integration-profile/testers/storage.testers.d.ts +3 -0
- package/dist/integration-profile/testers/storage.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/storage.testers.js +208 -0
- package/dist/integration-profile/testers/storage.testers.js.map +1 -0
- package/dist/language/en.json +4 -2
- package/dist/language/pt.json +4 -2
- package/dist/leaked-password/leaked-password.controller.d.ts +24 -0
- package/dist/leaked-password/leaked-password.controller.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.controller.js +78 -0
- package/dist/leaked-password/leaked-password.controller.js.map +1 -0
- package/dist/leaked-password/leaked-password.module.d.ts +8 -0
- package/dist/leaked-password/leaked-password.module.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.module.js +31 -0
- package/dist/leaked-password/leaked-password.module.js.map +1 -0
- package/dist/leaked-password/leaked-password.service.d.ts +64 -0
- package/dist/leaked-password/leaked-password.service.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.service.js +218 -0
- package/dist/leaked-password/leaked-password.service.js.map +1 -0
- package/dist/locale/locale.controller.d.ts +1 -1
- package/dist/locale/locale.service.d.ts +1 -1
- package/dist/mail/dto/preview.dto.d.ts +18 -0
- package/dist/mail/dto/preview.dto.d.ts.map +1 -0
- package/dist/mail/dto/preview.dto.js +66 -0
- package/dist/mail/dto/preview.dto.js.map +1 -0
- package/dist/mail/dto/send.dto.d.ts +7 -0
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js +10 -0
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.controller.d.ts +4 -0
- package/dist/mail/mail.controller.d.ts.map +1 -1
- package/dist/mail/mail.controller.js +16 -2
- package/dist/mail/mail.controller.js.map +1 -1
- package/dist/mail/mail.service.d.ts +23 -2
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +102 -13
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mail-layout/dto/update.dto.d.ts +17 -0
- package/dist/mail-layout/dto/update.dto.d.ts.map +1 -0
- package/dist/mail-layout/dto/update.dto.js +27 -0
- package/dist/mail-layout/dto/update.dto.js.map +1 -0
- package/dist/mail-layout/mail-layout.controller.d.ts +15 -0
- package/dist/mail-layout/mail-layout.controller.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.controller.js +71 -0
- package/dist/mail-layout/mail-layout.controller.js.map +1 -0
- package/dist/mail-layout/mail-layout.module.d.ts +3 -0
- package/dist/mail-layout/mail-layout.module.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.module.js +35 -0
- package/dist/mail-layout/mail-layout.module.js.map +1 -0
- package/dist/mail-layout/mail-layout.service.d.ts +27 -0
- package/dist/mail-layout/mail-layout.service.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.service.js +80 -0
- package/dist/mail-layout/mail-layout.service.js.map +1 -0
- package/dist/mcp-chat/mcp-chat.controller.d.ts +2 -2
- package/dist/mcp-chat/mcp-chat.service.d.ts +24 -2
- package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +80 -24
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/menu/menu.controller.d.ts +3 -3
- package/dist/menu/menu.service.d.ts +3 -3
- package/dist/notification/notification.controller.d.ts +12 -12
- package/dist/notification/notification.service.d.ts +12 -12
- package/dist/oauth/oauth-token-broker.service.d.ts +72 -0
- package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -0
- package/dist/oauth/oauth-token-broker.service.js +258 -0
- package/dist/oauth/oauth-token-broker.service.js.map +1 -0
- package/dist/oauth/oauth.module.d.ts.map +1 -1
- package/dist/oauth/oauth.module.js +3 -1
- package/dist/oauth/oauth.module.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +2 -0
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +6 -3
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/pdf/pdf.service.d.ts +8 -0
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +52 -0
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/presence/presence.controller.d.ts +16 -0
- package/dist/presence/presence.controller.d.ts.map +1 -0
- package/dist/presence/presence.controller.js +60 -0
- package/dist/presence/presence.controller.js.map +1 -0
- package/dist/presence/presence.listener.d.ts +29 -0
- package/dist/presence/presence.listener.d.ts.map +1 -0
- package/dist/presence/presence.listener.js +82 -0
- package/dist/presence/presence.listener.js.map +1 -0
- package/dist/presence/presence.module.d.ts +3 -0
- package/dist/presence/presence.module.d.ts.map +1 -0
- package/dist/presence/presence.module.js +32 -0
- package/dist/presence/presence.module.js.map +1 -0
- package/dist/presence/presence.service.d.ts +42 -0
- package/dist/presence/presence.service.d.ts.map +1 -0
- package/dist/presence/presence.service.js +147 -0
- package/dist/presence/presence.service.js.map +1 -0
- package/dist/profile/dto/delete-account.dto.d.ts +8 -0
- package/dist/profile/dto/delete-account.dto.d.ts.map +1 -0
- package/dist/profile/dto/delete-account.dto.js +22 -0
- package/dist/profile/dto/delete-account.dto.js.map +1 -0
- package/dist/profile/events/profile-account-deleted.event.d.ts +12 -0
- package/dist/profile/events/profile-account-deleted.event.d.ts.map +1 -0
- package/dist/profile/events/profile-account-deleted.event.js +17 -0
- package/dist/profile/events/profile-account-deleted.event.js.map +1 -0
- package/dist/profile/profile.controller.d.ts +21 -15
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.controller.js +75 -46
- package/dist/profile/profile.controller.js.map +1 -1
- package/dist/profile/profile.service.d.ts +30 -18
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +113 -37
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/realtime/realtime.gateway.d.ts +48 -0
- package/dist/realtime/realtime.gateway.d.ts.map +1 -0
- package/dist/realtime/realtime.gateway.js +156 -0
- package/dist/realtime/realtime.gateway.js.map +1 -0
- package/dist/realtime/realtime.module.d.ts +8 -0
- package/dist/realtime/realtime.module.d.ts.map +1 -0
- package/dist/realtime/realtime.module.js +29 -0
- package/dist/realtime/realtime.module.js.map +1 -0
- package/dist/realtime/realtime.service.d.ts +51 -0
- package/dist/realtime/realtime.service.d.ts.map +1 -0
- package/dist/realtime/realtime.service.js +177 -0
- package/dist/realtime/realtime.service.js.map +1 -0
- package/dist/redis/redis-pubsub.d.ts +27 -0
- package/dist/redis/redis-pubsub.d.ts.map +1 -0
- package/dist/redis/redis-pubsub.js +140 -0
- package/dist/redis/redis-pubsub.js.map +1 -0
- package/dist/role/role.controller.d.ts +3 -3
- package/dist/role/role.service.d.ts +3 -3
- package/dist/setting/dto/create.dto.d.ts.map +1 -1
- package/dist/setting/dto/create.dto.js +9 -2
- package/dist/setting/dto/create.dto.js.map +1 -1
- package/dist/setting/setting.controller.d.ts +5 -5
- package/dist/setting/setting.service.d.ts +8 -5
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +25 -1
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/user/dto/create-with-email-and-password.dto.d.ts +2 -0
- package/dist/user/dto/create-with-email-and-password.dto.d.ts.map +1 -1
- package/dist/user/dto/create-with-email-and-password.dto.js +5 -0
- package/dist/user/dto/create-with-email-and-password.dto.js.map +1 -1
- package/dist/user/dto/query-user-mail-list.dto.d.ts +5 -0
- package/dist/user/dto/query-user-mail-list.dto.d.ts.map +1 -0
- package/dist/user/dto/query-user-mail-list.dto.js +25 -0
- package/dist/user/dto/query-user-mail-list.dto.js.map +1 -0
- package/dist/user/user-credential.util.d.ts +19 -0
- package/dist/user/user-credential.util.d.ts.map +1 -0
- package/dist/user/user-credential.util.js +32 -0
- package/dist/user/user-credential.util.js.map +1 -0
- package/dist/user/user.controller.d.ts +17 -5
- package/dist/user/user.controller.d.ts.map +1 -1
- package/dist/user/user.controller.js +18 -3
- package/dist/user/user.controller.js.map +1 -1
- package/dist/user/user.service.d.ts +28 -6
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +204 -13
- package/dist/user/user.service.js.map +1 -1
- package/dist/validators/is-strong-password-with-settings.validator.d.ts.map +1 -1
- package/dist/validators/is-strong-password-with-settings.validator.js +11 -0
- package/dist/validators/is-strong-password-with-settings.validator.js.map +1 -1
- package/dist/validators/service-locator.d.ts +9 -0
- package/dist/validators/service-locator.d.ts.map +1 -1
- package/dist/validators/service-locator.js +12 -0
- package/dist/validators/service-locator.js.map +1 -1
- package/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
- package/hedhog/data/integration_provider.yaml +16 -0
- package/hedhog/data/mail.yaml +88 -61
- package/hedhog/data/mail_layout.yaml +188 -0
- package/hedhog/data/menu.yaml +67 -3
- package/hedhog/data/route.yaml +135 -0
- package/hedhog/data/setting_group.yaml +139 -1
- package/hedhog/frontend/app/account/components/mfa-setup-dialog.tsx.ejs +36 -0
- package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
- package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +10 -7
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
- package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
- package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
- package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
- package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
- package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
- package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
- package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +51 -4
- package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +153 -84
- package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +155 -121
- package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
- package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
- package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
- package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
- package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
- package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
- package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
- package/hedhog/frontend/app/users/page.tsx.ejs +119 -13
- package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +231 -0
- package/hedhog/frontend/app/users/user-mails.tsx.ejs +399 -0
- package/hedhog/frontend/app/users/user-sheet.tsx.ejs +60 -75
- package/hedhog/frontend/messages/en.json +499 -3
- package/hedhog/frontend/messages/pt.json +499 -3
- package/hedhog/table/ai_agent.yaml +1 -0
- package/hedhog/table/ai_instruction.yaml +15 -0
- package/hedhog/table/leaked_password.yaml +18 -0
- package/hedhog/table/mail_layout.yaml +35 -0
- package/hedhog/table/mail_var.yaml +4 -0
- package/hedhog/table/setting.yaml +1 -0
- package/hedhog/table/system_incident.yaml +59 -0
- package/hedhog/table/user_presence.yaml +36 -0
- package/package.json +8 -4
- package/src/access-log/access-log.interceptor.ts +4 -2
- package/src/ai/ai-attachment.fragments.spec.ts +319 -0
- package/src/ai/ai-attachment.fragments.ts +35 -0
- package/src/ai/ai.prompts.ts +38 -0
- package/src/ai/ai.service.spec.ts +280 -0
- package/src/ai/ai.service.ts +338 -82
- package/src/ai/dto/chat.dto.ts +33 -3
- package/src/ai/dto/create-agent.dto.ts +2 -2
- package/src/ai/dto/update-agent.dto.ts +2 -2
- package/src/ai-instruction/ai-instruction.controller.ts +40 -9
- package/src/ai-instruction/ai-instruction.module.ts +13 -2
- package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
- package/src/ai-instruction/ai-instruction.service.ts +661 -62
- package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
- package/src/ai-instruction/ai-prompt-registry.ts +87 -0
- package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
- package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
- package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
- package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
- package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
- package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
- package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
- package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
- package/src/auth/auth.controller.ts +31 -5
- package/src/auth/auth.service.spec.ts +3 -1
- package/src/auth/auth.service.ts +101 -36
- package/src/captcha/captcha.module.ts +10 -0
- package/src/captcha/captcha.service.spec.ts +210 -0
- package/src/captcha/captcha.service.ts +191 -0
- package/src/challenge/challenge.service.spec.ts +39 -4
- package/src/challenge/challenge.service.ts +72 -17
- package/src/core.module.ts +27 -1
- package/src/file/file.service.spec.ts +105 -0
- package/src/file/file.service.ts +60 -3
- package/src/incident/incident-notifier.service.spec.ts +205 -0
- package/src/incident/incident-notifier.service.ts +241 -0
- package/src/incident/incident.controller.ts +38 -0
- package/src/incident/incident.module.ts +19 -0
- package/src/incident/incident.service.spec.ts +150 -0
- package/src/incident/incident.service.ts +209 -0
- package/src/index.ts +37 -0
- package/src/integration-profile/dto/test.dto.ts +19 -0
- package/src/integration-profile/integration-profile.controller.ts +10 -1
- package/src/integration-profile/integration-profile.module.spec.ts +51 -0
- package/src/integration-profile/integration-profile.module.ts +23 -4
- package/src/integration-profile/integration-profile.secrets.ts +9 -1
- package/src/integration-profile/integration-profile.service.spec.ts +279 -0
- package/src/integration-profile/integration-profile.service.ts +120 -124
- package/src/integration-profile/integration-profile.utils.spec.ts +22 -0
- package/src/integration-profile/integration-profile.utils.ts +40 -3
- package/src/integration-profile/testers/ai.testers.ts +165 -0
- package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
- package/src/integration-profile/testers/captcha.testers.ts +139 -0
- package/src/integration-profile/testers/email.testers.ts +161 -0
- package/src/integration-profile/testers/http-probe.spec.ts +153 -0
- package/src/integration-profile/testers/http-probe.ts +171 -0
- package/src/integration-profile/testers/index.ts +30 -0
- package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
- package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
- package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
- package/src/integration-profile/testers/integration-tester.types.ts +61 -0
- package/src/integration-profile/testers/messaging.testers.ts +102 -0
- package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
- package/src/integration-profile/testers/oauth.testers.ts +305 -0
- package/src/integration-profile/testers/payment.testers.ts +185 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
- package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
- package/src/integration-profile/testers/storage.testers.ts +226 -0
- package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
- package/src/language/en.json +4 -2
- package/src/language/pt.json +4 -2
- package/src/leaked-password/README.md +83 -0
- package/src/leaked-password/leaked-password.controller.ts +52 -0
- package/src/leaked-password/leaked-password.module.ts +18 -0
- package/src/leaked-password/leaked-password.service.ts +242 -0
- package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
- package/src/leaked-password/seed/common-passwords.txt +335 -0
- package/src/mail/dto/preview.dto.ts +50 -0
- package/src/mail/dto/send.dto.ts +14 -1
- package/src/mail/mail-template.spec.ts +197 -0
- package/src/mail/mail.controller.ts +9 -2
- package/src/mail/mail.service.spec.ts +116 -1
- package/src/mail/mail.service.ts +118 -12
- package/src/mail-layout/dto/update.dto.ts +19 -0
- package/src/mail-layout/mail-layout.controller.ts +47 -0
- package/src/mail-layout/mail-layout.module.ts +22 -0
- package/src/mail-layout/mail-layout.service.ts +94 -0
- package/src/mcp-chat/mcp-chat.service.spec.ts +236 -0
- package/src/mcp-chat/mcp-chat.service.ts +122 -26
- package/src/oauth/oauth-token-broker.service.spec.ts +172 -0
- package/src/oauth/oauth-token-broker.service.ts +363 -0
- package/src/oauth/oauth.module.ts +3 -1
- package/src/oauth/oauth.service.ts +8 -2
- package/src/pdf/pdf.service.ts +75 -0
- package/src/presence/presence.controller.ts +29 -0
- package/src/presence/presence.listener.ts +53 -0
- package/src/presence/presence.module.ts +19 -0
- package/src/presence/presence.service.spec.ts +97 -0
- package/src/presence/presence.service.ts +160 -0
- package/src/profile/dto/delete-account.dto.ts +11 -0
- package/src/profile/events/profile-account-deleted.event.ts +13 -0
- package/src/profile/profile.controller.ts +46 -34
- package/src/profile/profile.service.ts +138 -38
- package/src/realtime/realtime.gateway.ts +138 -0
- package/src/realtime/realtime.module.ts +16 -0
- package/src/realtime/realtime.service.spec.ts +50 -0
- package/src/realtime/realtime.service.ts +187 -0
- package/src/redis/redis-pubsub.ts +179 -0
- package/src/setting/dto/create.dto.ts +13 -2
- package/src/setting/setting.service.spec.ts +56 -0
- package/src/setting/setting.service.ts +29 -1
- package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
- package/src/user/dto/query-user-mail-list.dto.ts +10 -0
- package/src/user/user-credential.util.ts +35 -0
- package/src/user/user.controller.ts +17 -2
- package/src/user/user.service.spec.ts +153 -0
- package/src/user/user.service.ts +255 -12
- package/src/validators/is-strong-password-with-settings.validator.ts +12 -0
- package/src/validators/service-locator.ts +15 -0
- package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +313 -0
|
@@ -10,6 +10,7 @@ const makeDeps = () => {
|
|
|
10
10
|
findMany: jest.fn(),
|
|
11
11
|
update: jest.fn(),
|
|
12
12
|
deleteMany: jest.fn(),
|
|
13
|
+
count: jest.fn(),
|
|
13
14
|
},
|
|
14
15
|
role: { findUnique: jest.fn(), findMany: jest.fn() },
|
|
15
16
|
role_user: { findFirst: jest.fn(), create: jest.fn(), delete: jest.fn(), findMany: jest.fn() },
|
|
@@ -237,6 +238,158 @@ describe('UserService', () => {
|
|
|
237
238
|
});
|
|
238
239
|
});
|
|
239
240
|
|
|
241
|
+
describe('list', () => {
|
|
242
|
+
const makeListService = () => {
|
|
243
|
+
const { service, deps } = makeService();
|
|
244
|
+
deps.prismaService.$transaction.mockResolvedValue([0, 0, 0]);
|
|
245
|
+
deps.paginationService.paginatePrismaModel.mockResolvedValue({
|
|
246
|
+
total: 0,
|
|
247
|
+
data: [],
|
|
248
|
+
});
|
|
249
|
+
return { service, deps };
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const whereOf = (deps: ReturnType<typeof makeDeps>) =>
|
|
253
|
+
(deps.paginationService.paginatePrismaModel.mock.calls[0][1] as any).where;
|
|
254
|
+
|
|
255
|
+
it('não filtra quando o filtro é ausente ou desconhecido', async () => {
|
|
256
|
+
const { service, deps } = makeListService();
|
|
257
|
+
await service.list({});
|
|
258
|
+
expect(whereOf(deps)).toEqual({});
|
|
259
|
+
|
|
260
|
+
deps.paginationService.paginatePrismaModel.mockClear();
|
|
261
|
+
await service.list({}, 'inexistente');
|
|
262
|
+
expect(whereOf(deps)).toEqual({});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('filtra bloqueados por suspended_until futuro', async () => {
|
|
266
|
+
const { service, deps } = makeListService();
|
|
267
|
+
await service.list({}, 'blocked');
|
|
268
|
+
expect(whereOf(deps).suspended_until.gt).toBeInstanceOf(Date);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('filtra novos pelos últimos 7 dias', async () => {
|
|
272
|
+
const { service, deps } = makeListService();
|
|
273
|
+
await service.list({}, 'new');
|
|
274
|
+
const gte = whereOf(deps).created_at.gte as Date;
|
|
275
|
+
const diffInDays = (Date.now() - gte.getTime()) / (24 * 60 * 60 * 1000);
|
|
276
|
+
expect(Math.round(diffInDays)).toBe(7);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('filtra por credencial de senha com reset pendente', async () => {
|
|
280
|
+
const { service, deps } = makeListService();
|
|
281
|
+
await service.list({}, 'password-reset');
|
|
282
|
+
expect(whereOf(deps)).toEqual({
|
|
283
|
+
user_credential: {
|
|
284
|
+
some: { type: 'password', requires_reset: true, revoked_at: null },
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('busca por nome e por qualquer identificador do usuário', async () => {
|
|
290
|
+
const { service, deps } = makeListService();
|
|
291
|
+
await service.list({ search: 'joao@hedhog.com' });
|
|
292
|
+
|
|
293
|
+
expect(whereOf(deps)).toEqual({
|
|
294
|
+
OR: [
|
|
295
|
+
{ name: { contains: 'joao@hedhog.com', mode: 'insensitive' } },
|
|
296
|
+
{
|
|
297
|
+
user_identifier: {
|
|
298
|
+
some: {
|
|
299
|
+
value: { contains: 'joao@hedhog.com', mode: 'insensitive' },
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('ignora busca vazia ou só com espaços', async () => {
|
|
308
|
+
const { service, deps } = makeListService();
|
|
309
|
+
await service.list({ search: ' ' });
|
|
310
|
+
expect(whereOf(deps)).toEqual({});
|
|
311
|
+
|
|
312
|
+
deps.paginationService.paginatePrismaModel.mockClear();
|
|
313
|
+
await service.list({ search: '' });
|
|
314
|
+
expect(whereOf(deps)).toEqual({});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('combina busca e filtro com AND', async () => {
|
|
318
|
+
const { service, deps } = makeListService();
|
|
319
|
+
await service.list({ search: 'joao' }, 'blocked');
|
|
320
|
+
|
|
321
|
+
const where = whereOf(deps);
|
|
322
|
+
expect(where.OR).toBeUndefined();
|
|
323
|
+
expect(where.AND).toHaveLength(2);
|
|
324
|
+
expect(where.AND[0].suspended_until.gt).toBeInstanceOf(Date);
|
|
325
|
+
expect(where.AND[1].OR).toHaveLength(2);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('não delega a busca ao searchFields da paginação', async () => {
|
|
329
|
+
const { service, deps } = makeListService();
|
|
330
|
+
await service.list({ search: 'joao' });
|
|
331
|
+
|
|
332
|
+
const options = deps.paginationService.paginatePrismaModel.mock
|
|
333
|
+
.calls[0][1] as any;
|
|
334
|
+
expect(options.searchFields).toBeUndefined();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('deriva requires_password_reset e last_login_at', async () => {
|
|
338
|
+
const { service, deps } = makeListService();
|
|
339
|
+
const lastLogin = new Date('2026-07-01T10:00:00Z');
|
|
340
|
+
deps.paginationService.paginatePrismaModel.mockResolvedValue({
|
|
341
|
+
total: 3,
|
|
342
|
+
data: [
|
|
343
|
+
{
|
|
344
|
+
id: 1,
|
|
345
|
+
user_credential: [
|
|
346
|
+
{ type: 'password', requires_reset: true, revoked_at: null },
|
|
347
|
+
],
|
|
348
|
+
user_activity: [{ action: 'login', created_at: lastLogin }],
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
id: 2,
|
|
352
|
+
user_credential: [
|
|
353
|
+
{ type: 'password', requires_reset: true, revoked_at: new Date() },
|
|
354
|
+
],
|
|
355
|
+
user_activity: [],
|
|
356
|
+
},
|
|
357
|
+
{ id: 3, user_credential: [], user_activity: [] },
|
|
358
|
+
],
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
const { paginate } = await service.list({});
|
|
362
|
+
|
|
363
|
+
expect(paginate.total).toBe(3);
|
|
364
|
+
expect(paginate.data.map((u: any) => u.requires_password_reset)).toEqual([
|
|
365
|
+
true,
|
|
366
|
+
false,
|
|
367
|
+
false,
|
|
368
|
+
]);
|
|
369
|
+
expect(paginate.data.map((u: any) => u.last_login_at)).toEqual([
|
|
370
|
+
lastLogin,
|
|
371
|
+
null,
|
|
372
|
+
null,
|
|
373
|
+
]);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('traz apenas o último login e credenciais sem hash', async () => {
|
|
377
|
+
const { service, deps } = makeListService();
|
|
378
|
+
await service.list({});
|
|
379
|
+
const { include } = deps.paginationService.paginatePrismaModel.mock
|
|
380
|
+
.calls[0][1] as any;
|
|
381
|
+
|
|
382
|
+
expect(include.user_activity).toEqual({
|
|
383
|
+
where: { action: 'login' },
|
|
384
|
+
orderBy: { created_at: 'desc' },
|
|
385
|
+
take: 1,
|
|
386
|
+
});
|
|
387
|
+
expect(include.user_credential.select.hash).toBeUndefined();
|
|
388
|
+
expect(include.user_credential.select.requires_reset).toBe(true);
|
|
389
|
+
expect(include.user_session.select.hash).toBeUndefined();
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
|
|
240
393
|
describe('listUserActivities', () => {
|
|
241
394
|
it('mapeia atividades com createdAt ISO', async () => {
|
|
242
395
|
const { service, deps } = makeService();
|
package/src/user/user.service.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
BadRequestException,
|
|
7
7
|
Inject,
|
|
8
8
|
Injectable,
|
|
9
|
+
Logger,
|
|
9
10
|
NotFoundException,
|
|
10
11
|
forwardRef,
|
|
11
12
|
} from '@nestjs/common';
|
|
@@ -20,6 +21,10 @@ import { USER_AVATAR_UPLOAD_DESTINATION } from './constants/user.constants';
|
|
|
20
21
|
import { CreateWithEmailAndPasswordDTO } from './dto/create-with-email-and-password.dto';
|
|
21
22
|
import { ResetPasswordDTO } from './dto/reset-password.dto';
|
|
22
23
|
import { UpdateDTO } from './dto/update.dto';
|
|
24
|
+
import {
|
|
25
|
+
PENDING_PASSWORD_RESET_WHERE,
|
|
26
|
+
hasPendingPasswordReset,
|
|
27
|
+
} from './user-credential.util';
|
|
23
28
|
|
|
24
29
|
// Constants
|
|
25
30
|
const IDENTIFIER_TYPE = {
|
|
@@ -54,8 +59,6 @@ const USER_SORT_FIELDS = [
|
|
|
54
59
|
'updated_at',
|
|
55
60
|
] as const;
|
|
56
61
|
|
|
57
|
-
const USER_SEARCH_FIELDS = ['name'] as const;
|
|
58
|
-
|
|
59
62
|
type UserChangeLog = user_change_log;
|
|
60
63
|
type UserChangeLogActor = Prisma.userGetPayload<{
|
|
61
64
|
select: {
|
|
@@ -70,6 +73,8 @@ type UserChangeLogActor = Prisma.userGetPayload<{
|
|
|
70
73
|
|
|
71
74
|
@Injectable()
|
|
72
75
|
export class UserService {
|
|
76
|
+
private readonly logger = new Logger(UserService.name);
|
|
77
|
+
|
|
73
78
|
constructor(
|
|
74
79
|
@Inject(forwardRef(() => PrismaService))
|
|
75
80
|
private readonly prismaService: PrismaService,
|
|
@@ -154,20 +159,30 @@ export class UserService {
|
|
|
154
159
|
// CRUD Operations
|
|
155
160
|
// ==========================================
|
|
156
161
|
|
|
157
|
-
async list(paginationParams) {
|
|
162
|
+
async list(paginationParams, filter?: string) {
|
|
158
163
|
const paginate = await this.paginationService.paginatePrismaModel(
|
|
159
164
|
this.prismaService.user,
|
|
160
165
|
{
|
|
161
166
|
...paginationParams,
|
|
162
167
|
validSortFields: USER_SORT_FIELDS,
|
|
163
|
-
|
|
168
|
+
where: this.buildUserListWhere(filter, paginationParams?.search),
|
|
164
169
|
include: this.getUserIncludeClause(),
|
|
165
170
|
}
|
|
166
171
|
);
|
|
167
172
|
|
|
168
173
|
const stats = await this.getUserStatistics();
|
|
169
174
|
|
|
170
|
-
return {
|
|
175
|
+
return {
|
|
176
|
+
paginate: {
|
|
177
|
+
...paginate,
|
|
178
|
+
data: (paginate?.data ?? []).map((user: any) => ({
|
|
179
|
+
...user,
|
|
180
|
+
requires_password_reset: hasPendingPasswordReset(user),
|
|
181
|
+
last_login_at: user?.user_activity?.[0]?.created_at ?? null,
|
|
182
|
+
})),
|
|
183
|
+
},
|
|
184
|
+
stats,
|
|
185
|
+
};
|
|
171
186
|
}
|
|
172
187
|
|
|
173
188
|
async get(locale: string, userId: number) {
|
|
@@ -176,7 +191,7 @@ export class UserService {
|
|
|
176
191
|
|
|
177
192
|
async createWithEmailAndPassword(
|
|
178
193
|
locale: string,
|
|
179
|
-
{ email, name, password }: CreateWithEmailAndPasswordDTO,
|
|
194
|
+
{ email, name, password, app }: CreateWithEmailAndPasswordDTO,
|
|
180
195
|
) {
|
|
181
196
|
await this.validateEmailAvailable(locale, email);
|
|
182
197
|
|
|
@@ -185,7 +200,7 @@ export class UserService {
|
|
|
185
200
|
const user = await this.prismaService.$transaction(async (tx) => {
|
|
186
201
|
const role = await this.getDefaultUserRole(locale, tx);
|
|
187
202
|
|
|
188
|
-
const
|
|
203
|
+
const created = await tx.user.create({
|
|
189
204
|
data: {
|
|
190
205
|
name,
|
|
191
206
|
user_identifier: {
|
|
@@ -209,10 +224,25 @@ export class UserService {
|
|
|
209
224
|
},
|
|
210
225
|
});
|
|
211
226
|
|
|
212
|
-
return
|
|
227
|
+
return created;
|
|
228
|
+
}).catch((error: any) => {
|
|
229
|
+
if (error?.code === 'P2002') {
|
|
230
|
+
throw new BadRequestException(
|
|
231
|
+
getLocaleText('signup.emailExists', locale, 'Email already in use.')
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
throw error;
|
|
213
236
|
});
|
|
214
237
|
|
|
215
|
-
|
|
238
|
+
try {
|
|
239
|
+
await this.challenge.verifyEmail(locale, user.id, email, app);
|
|
240
|
+
} catch (error: any) {
|
|
241
|
+
this.logger.warn(
|
|
242
|
+
`Signup confirmation email failed for user ${user.id}: ${error?.message ?? error}`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
216
246
|
await this.registerUserActivity(user.id, 'register');
|
|
217
247
|
|
|
218
248
|
await this.integrationApi.publishEvent({
|
|
@@ -223,7 +253,7 @@ export class UserService {
|
|
|
223
253
|
payload: { id: user.id, name: user.name, email },
|
|
224
254
|
}).catch(() => null);
|
|
225
255
|
|
|
226
|
-
return { user,
|
|
256
|
+
return { user, hasChallenge: true };
|
|
227
257
|
}
|
|
228
258
|
|
|
229
259
|
async update(
|
|
@@ -424,7 +454,10 @@ export class UserService {
|
|
|
424
454
|
include: {
|
|
425
455
|
user_identifier: true,
|
|
426
456
|
user_credential: true,
|
|
427
|
-
user_activity:
|
|
457
|
+
user_activity: {
|
|
458
|
+
orderBy: { created_at: 'desc' },
|
|
459
|
+
take: 20,
|
|
460
|
+
},
|
|
428
461
|
user_session: true,
|
|
429
462
|
user_account: true,
|
|
430
463
|
role_user: {
|
|
@@ -749,6 +782,139 @@ export class UserService {
|
|
|
749
782
|
};
|
|
750
783
|
}
|
|
751
784
|
|
|
785
|
+
// ==========================================
|
|
786
|
+
// Sent Mails (delivery history per user)
|
|
787
|
+
// ==========================================
|
|
788
|
+
|
|
789
|
+
async listUserMails(
|
|
790
|
+
locale: string,
|
|
791
|
+
userId: number,
|
|
792
|
+
params: {
|
|
793
|
+
page?: number;
|
|
794
|
+
pageSize?: number;
|
|
795
|
+
search?: string;
|
|
796
|
+
sortField?: string;
|
|
797
|
+
sortOrder?: 'asc' | 'desc';
|
|
798
|
+
status?: 'all' | 'received' | 'read' | 'error';
|
|
799
|
+
},
|
|
800
|
+
) {
|
|
801
|
+
await this.validateUserExists(locale, userId);
|
|
802
|
+
|
|
803
|
+
const identifiers = await this.prismaService.user_identifier.findMany({
|
|
804
|
+
where: { user_id: userId, type: IDENTIFIER_TYPE.EMAIL },
|
|
805
|
+
select: { value: true },
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
const emails = [
|
|
809
|
+
...new Set(
|
|
810
|
+
identifiers
|
|
811
|
+
.map((identifier) => identifier.value?.trim().toLowerCase())
|
|
812
|
+
.filter((value): value is string => Boolean(value)),
|
|
813
|
+
),
|
|
814
|
+
];
|
|
815
|
+
|
|
816
|
+
// Tracked deliveries plus a fallback over the raw recipient fields, so
|
|
817
|
+
// mails sent before the tracking table existed still show up here.
|
|
818
|
+
const OR: any[] = [{ mail_sent_user: { some: { user_id: userId } } }];
|
|
819
|
+
|
|
820
|
+
for (const email of emails) {
|
|
821
|
+
OR.push({ to: { contains: email, mode: 'insensitive' } });
|
|
822
|
+
OR.push({ cc: { contains: email, mode: 'insensitive' } });
|
|
823
|
+
OR.push({ bcc: { contains: email, mode: 'insensitive' } });
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
const AND: any[] = [];
|
|
827
|
+
|
|
828
|
+
const status = params?.status;
|
|
829
|
+
if (status && status !== 'all') {
|
|
830
|
+
AND.push({ mail_sent_user: { some: { user_id: userId, status } } });
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const search = params?.search?.trim();
|
|
834
|
+
if (search) {
|
|
835
|
+
AND.push({ subject: { contains: search, mode: 'insensitive' } });
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const paginated = await this.paginationService.paginatePrismaModel(
|
|
839
|
+
this.prismaService.mail_sent,
|
|
840
|
+
{
|
|
841
|
+
page: params?.page,
|
|
842
|
+
pageSize: params?.pageSize,
|
|
843
|
+
sortField: params?.sortField || 'created_at',
|
|
844
|
+
sortOrder: params?.sortOrder || 'desc',
|
|
845
|
+
validSortFields: ['id', 'created_at', 'subject'],
|
|
846
|
+
where: {
|
|
847
|
+
OR,
|
|
848
|
+
...(AND.length > 0 ? { AND } : {}),
|
|
849
|
+
},
|
|
850
|
+
include: {
|
|
851
|
+
mail: { select: { id: true, slug: true } },
|
|
852
|
+
mail_sent_user: {
|
|
853
|
+
where: { user_id: userId },
|
|
854
|
+
select: {
|
|
855
|
+
id: true,
|
|
856
|
+
recipient_email: true,
|
|
857
|
+
status: true,
|
|
858
|
+
read_at: true,
|
|
859
|
+
error_code: true,
|
|
860
|
+
error_message: true,
|
|
861
|
+
},
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
},
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
// `total` conta o mesmo universo da lista (rastreados + fallback), para o
|
|
868
|
+
// KPI não divergir da quantidade de itens exibidos. Os demais contadores só
|
|
869
|
+
// existem para envios rastreados.
|
|
870
|
+
const [totalMails, grouped] = await Promise.all([
|
|
871
|
+
this.prismaService.mail_sent.count({ where: { OR } }),
|
|
872
|
+
this.prismaService.mail_sent_user.groupBy({
|
|
873
|
+
by: ['status'],
|
|
874
|
+
where: { user_id: userId },
|
|
875
|
+
_count: { _all: true },
|
|
876
|
+
}),
|
|
877
|
+
]);
|
|
878
|
+
|
|
879
|
+
const stats = grouped.reduce(
|
|
880
|
+
(acc, group) => {
|
|
881
|
+
const count = group._count?._all ?? 0;
|
|
882
|
+
if (group.status === 'received') acc.received += count;
|
|
883
|
+
if (group.status === 'read') acc.read += count;
|
|
884
|
+
if (group.status === 'error') acc.error += count;
|
|
885
|
+
return acc;
|
|
886
|
+
},
|
|
887
|
+
{ total: totalMails, received: 0, read: 0, error: 0 },
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
return {
|
|
891
|
+
...paginated,
|
|
892
|
+
stats,
|
|
893
|
+
data: (paginated.data || []).map((mailSent: any) => {
|
|
894
|
+
const tracking = mailSent.mail_sent_user?.[0] ?? null;
|
|
895
|
+
|
|
896
|
+
return {
|
|
897
|
+
id: mailSent.id,
|
|
898
|
+
mailId: mailSent.mail_id,
|
|
899
|
+
mailSlug: mailSent.mail?.slug ?? null,
|
|
900
|
+
subject: mailSent.subject,
|
|
901
|
+
from: mailSent.from,
|
|
902
|
+
to: mailSent.to,
|
|
903
|
+
cc: mailSent.cc,
|
|
904
|
+
bcc: mailSent.bcc,
|
|
905
|
+
body: mailSent.body,
|
|
906
|
+
createdAt: mailSent.created_at?.toISOString?.() || null,
|
|
907
|
+
tracked: Boolean(tracking),
|
|
908
|
+
recipientEmail: tracking?.recipient_email ?? null,
|
|
909
|
+
status: tracking?.status ?? null,
|
|
910
|
+
readAt: tracking?.read_at?.toISOString?.() || null,
|
|
911
|
+
errorCode: tracking?.error_code ?? null,
|
|
912
|
+
errorMessage: tracking?.error_message ?? null,
|
|
913
|
+
};
|
|
914
|
+
}),
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
|
|
752
918
|
async listUserActivities(locale: string, userId: number, paginationParams) {
|
|
753
919
|
await this.validateUserExists(locale, userId);
|
|
754
920
|
|
|
@@ -859,10 +1025,74 @@ export class UserService {
|
|
|
859
1025
|
return passwordChars.slice(0, length).join('');
|
|
860
1026
|
}
|
|
861
1027
|
|
|
1028
|
+
private buildUserFilterWhere(filter?: string) {
|
|
1029
|
+
switch (filter) {
|
|
1030
|
+
case 'new':
|
|
1031
|
+
return {
|
|
1032
|
+
created_at: {
|
|
1033
|
+
gte: new Date(Date.now() - NEW_USERS_PERIOD_DAYS * DAYS_IN_MS),
|
|
1034
|
+
},
|
|
1035
|
+
};
|
|
1036
|
+
case 'blocked':
|
|
1037
|
+
return { suspended_until: { gt: new Date() } };
|
|
1038
|
+
case 'password-reset':
|
|
1039
|
+
return { user_credential: PENDING_PASSWORD_RESET_WHERE };
|
|
1040
|
+
default:
|
|
1041
|
+
return {};
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// O e-mail não é coluna de `user`: mora em `user_identifier`, junto de
|
|
1046
|
+
// username, telefone e cpf. Por isso a busca é montada aqui, e não via
|
|
1047
|
+
// `searchFields` da paginação, que só sabe filtrar colunas escalares.
|
|
1048
|
+
private buildUserSearchWhere(search?: string) {
|
|
1049
|
+
const term = typeof search === 'string' ? search.trim() : '';
|
|
1050
|
+
|
|
1051
|
+
if (!term) {
|
|
1052
|
+
return null;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
return {
|
|
1056
|
+
OR: [
|
|
1057
|
+
{ name: { contains: term, mode: 'insensitive' as const } },
|
|
1058
|
+
{
|
|
1059
|
+
user_identifier: {
|
|
1060
|
+
some: { value: { contains: term, mode: 'insensitive' as const } },
|
|
1061
|
+
},
|
|
1062
|
+
},
|
|
1063
|
+
],
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
private buildUserListWhere(filter?: string, search?: string) {
|
|
1068
|
+
const filterWhere = this.buildUserFilterWhere(filter);
|
|
1069
|
+
const searchWhere = this.buildUserSearchWhere(search);
|
|
1070
|
+
|
|
1071
|
+
if (!searchWhere) {
|
|
1072
|
+
return filterWhere;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
if (!Object.keys(filterWhere).length) {
|
|
1076
|
+
return searchWhere;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
return { AND: [filterWhere, searchWhere] };
|
|
1080
|
+
}
|
|
1081
|
+
|
|
862
1082
|
private getUserIncludeClause() {
|
|
863
1083
|
return {
|
|
864
1084
|
user_account: true,
|
|
865
|
-
user_credential:
|
|
1085
|
+
user_credential: {
|
|
1086
|
+
select: {
|
|
1087
|
+
id: true,
|
|
1088
|
+
type: true,
|
|
1089
|
+
requires_reset: true,
|
|
1090
|
+
revoked_at: true,
|
|
1091
|
+
expires_at: true,
|
|
1092
|
+
created_at: true,
|
|
1093
|
+
updated_at: true,
|
|
1094
|
+
},
|
|
1095
|
+
},
|
|
866
1096
|
user_identifier: {
|
|
867
1097
|
where: { enabled: true },
|
|
868
1098
|
},
|
|
@@ -870,9 +1100,22 @@ export class UserService {
|
|
|
870
1100
|
where: { verified_at: { not: null } },
|
|
871
1101
|
},
|
|
872
1102
|
user_activity: {
|
|
1103
|
+
where: { action: 'login' },
|
|
873
1104
|
orderBy: { created_at: 'desc' },
|
|
1105
|
+
take: 1,
|
|
874
1106
|
},
|
|
875
1107
|
user_session: {
|
|
1108
|
+
select: {
|
|
1109
|
+
id: true,
|
|
1110
|
+
user_id: true,
|
|
1111
|
+
ip_address: true,
|
|
1112
|
+
user_agent: true,
|
|
1113
|
+
browser_id: true,
|
|
1114
|
+
revoked_at: true,
|
|
1115
|
+
expires_at: true,
|
|
1116
|
+
created_at: true,
|
|
1117
|
+
updated_at: true,
|
|
1118
|
+
},
|
|
876
1119
|
where: {
|
|
877
1120
|
revoked_at: null,
|
|
878
1121
|
expires_at: { gt: new Date() },
|
|
@@ -68,6 +68,18 @@ export class IsStrongPasswordWithSettingsConstraint
|
|
|
68
68
|
return false;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
// Senha vazada por ultimo: e a checagem mais cara (bate no banco) e nao faz
|
|
72
|
+
// sentido pagar por ela se a senha ja falhou na politica. Aqui a senha em
|
|
73
|
+
// claro passa pelo servidor de qualquer forma; a do cofre nunca passa, e por
|
|
74
|
+
// isso o cofre usa o bloom filter no cliente em vez deste caminho.
|
|
75
|
+
if (this.settings.setting['password-block-leaked'] !== false) {
|
|
76
|
+
const leakedService = ValidatorServiceLocator.getLeakedPasswordService();
|
|
77
|
+
if (leakedService && (await leakedService.isLeaked(password))) {
|
|
78
|
+
this.failedRule = 'password.leaked';
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
return true;
|
|
72
84
|
} catch (error) {
|
|
73
85
|
console.warn('[IsStrongPasswordWithSettingsConstraint] Error getting SettingService:', error);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LeakedPasswordService } from '../leaked-password/leaked-password.service';
|
|
1
2
|
import { SettingService } from '../setting/setting.service';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -6,6 +7,7 @@ import { SettingService } from '../setting/setting.service';
|
|
|
6
7
|
*/
|
|
7
8
|
export class ValidatorServiceLocator {
|
|
8
9
|
private static settingService: SettingService;
|
|
10
|
+
private static leakedPasswordService: LeakedPasswordService;
|
|
9
11
|
|
|
10
12
|
static setSettingService(service: SettingService): void {
|
|
11
13
|
this.settingService = service;
|
|
@@ -17,4 +19,17 @@ export class ValidatorServiceLocator {
|
|
|
17
19
|
}
|
|
18
20
|
return this.settingService;
|
|
19
21
|
}
|
|
22
|
+
|
|
23
|
+
static setLeakedPasswordService(service: LeakedPasswordService): void {
|
|
24
|
+
this.leakedPasswordService = service;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Diferente do SettingService, devolve null em vez de lançar: a checagem de
|
|
29
|
+
* senha vazada é uma camada extra, e um bootstrap sem ela deve deixar a
|
|
30
|
+
* validação de política seguir funcionando.
|
|
31
|
+
*/
|
|
32
|
+
static getLeakedPasswordService(): LeakedPasswordService | null {
|
|
33
|
+
return this.leakedPasswordService ?? null;
|
|
34
|
+
}
|
|
20
35
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PrismaModule } from '@hed-hog/api-prisma';
|
|
2
|
+
import { forwardRef, Module } from '@nestjs/common';
|
|
3
|
+
import { WhatsappSenderService } from './whatsapp-sender.service';
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
imports: [forwardRef(() => PrismaModule)],
|
|
7
|
+
providers: [WhatsappSenderService],
|
|
8
|
+
exports: [WhatsappSenderService],
|
|
9
|
+
})
|
|
10
|
+
export class WhatsappSenderModule {}
|