@hed-hog/core 0.0.355 → 0.0.358

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.
Files changed (287) hide show
  1. package/dist/ai/ai.service.d.ts +3 -12
  2. package/dist/ai/ai.service.d.ts.map +1 -1
  3. package/dist/ai/ai.service.js +34 -125
  4. package/dist/ai/ai.service.js.map +1 -1
  5. package/dist/auth/guards/auth.guard.d.ts +6 -1
  6. package/dist/auth/guards/auth.guard.d.ts.map +1 -1
  7. package/dist/auth/guards/auth.guard.js +33 -2
  8. package/dist/auth/guards/auth.guard.js.map +1 -1
  9. package/dist/core.module.d.ts.map +1 -1
  10. package/dist/core.module.js +3 -3
  11. package/dist/core.module.js.map +1 -1
  12. package/dist/file/file.controller.d.ts +4 -2
  13. package/dist/file/file.controller.d.ts.map +1 -1
  14. package/dist/file/file.controller.js +44 -38
  15. package/dist/file/file.controller.js.map +1 -1
  16. package/dist/file/file.service.d.ts +2 -2
  17. package/dist/file/file.service.d.ts.map +1 -1
  18. package/dist/file/file.service.js +58 -89
  19. package/dist/file/file.service.js.map +1 -1
  20. package/dist/file/provider/azure.provider.d.ts.map +1 -1
  21. package/dist/file/provider/azure.provider.js +10 -15
  22. package/dist/file/provider/azure.provider.js.map +1 -1
  23. package/dist/file/provider/gcs.provider.d.ts.map +1 -1
  24. package/dist/file/provider/gcs.provider.js +8 -9
  25. package/dist/file/provider/gcs.provider.js.map +1 -1
  26. package/dist/file/provider/local.provider.d.ts.map +1 -1
  27. package/dist/file/provider/local.provider.js +11 -10
  28. package/dist/file/provider/local.provider.js.map +1 -1
  29. package/dist/file/provider/provider.enum.d.ts +2 -1
  30. package/dist/file/provider/provider.enum.d.ts.map +1 -1
  31. package/dist/file/provider/provider.enum.js +1 -0
  32. package/dist/file/provider/provider.enum.js.map +1 -1
  33. package/dist/file/provider/provider.factory.d.ts +1 -1
  34. package/dist/file/provider/provider.factory.d.ts.map +1 -1
  35. package/dist/file/provider/provider.factory.js +18 -5
  36. package/dist/file/provider/provider.factory.js.map +1 -1
  37. package/dist/file/provider/s3.provider.d.ts.map +1 -1
  38. package/dist/file/provider/s3.provider.js +4 -20
  39. package/dist/file/provider/s3.provider.js.map +1 -1
  40. package/dist/file/provider/spaces.provider.d.ts +27 -0
  41. package/dist/file/provider/spaces.provider.d.ts.map +1 -0
  42. package/dist/file/provider/spaces.provider.js +203 -0
  43. package/dist/file/provider/spaces.provider.js.map +1 -0
  44. package/dist/index.d.ts +4 -3
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +4 -3
  47. package/dist/index.js.map +1 -1
  48. package/dist/integration-profile/dto/create.dto.d.ts +9 -0
  49. package/dist/integration-profile/dto/create.dto.d.ts.map +1 -0
  50. package/dist/integration-profile/dto/create.dto.js +54 -0
  51. package/dist/integration-profile/dto/create.dto.js.map +1 -0
  52. package/dist/integration-profile/dto/export.dto.d.ts +5 -0
  53. package/dist/integration-profile/dto/export.dto.d.ts.map +1 -0
  54. package/dist/integration-profile/dto/export.dto.js +29 -0
  55. package/dist/integration-profile/dto/export.dto.js.map +1 -0
  56. package/dist/integration-profile/dto/import-confirm.dto.d.ts +17 -0
  57. package/dist/integration-profile/dto/import-confirm.dto.d.ts.map +1 -0
  58. package/dist/integration-profile/dto/import-confirm.dto.js +77 -0
  59. package/dist/integration-profile/dto/import-confirm.dto.js.map +1 -0
  60. package/dist/integration-profile/dto/update.dto.d.ts.map +1 -0
  61. package/dist/integration-profile/dto/update.dto.js.map +1 -0
  62. package/dist/integration-profile/integration-profile.controller.d.ts +142 -0
  63. package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -0
  64. package/dist/integration-profile/integration-profile.controller.js +166 -0
  65. package/dist/integration-profile/integration-profile.controller.js.map +1 -0
  66. package/dist/integration-profile/integration-profile.module.d.ts +3 -0
  67. package/dist/integration-profile/integration-profile.module.d.ts.map +1 -0
  68. package/dist/{mail-profile/mail-profile.module.js → integration-profile/integration-profile.module.js} +11 -13
  69. package/dist/integration-profile/integration-profile.module.js.map +1 -0
  70. package/dist/integration-profile/integration-profile.service.d.ts +160 -0
  71. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -0
  72. package/dist/integration-profile/integration-profile.service.js +609 -0
  73. package/dist/integration-profile/integration-profile.service.js.map +1 -0
  74. package/dist/integration-profile/integration-profile.utils.d.ts +30 -0
  75. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -0
  76. package/dist/integration-profile/integration-profile.utils.js +156 -0
  77. package/dist/integration-profile/integration-profile.utils.js.map +1 -0
  78. package/dist/mail/mail.module.d.ts.map +1 -1
  79. package/dist/mail/mail.module.js +36 -23
  80. package/dist/mail/mail.module.js.map +1 -1
  81. package/dist/mail/mail.service.d.ts +4 -2
  82. package/dist/mail/mail.service.d.ts.map +1 -1
  83. package/dist/mail/mail.service.js +33 -51
  84. package/dist/mail/mail.service.js.map +1 -1
  85. package/dist/mcp/guards/mcp-auth.guard.js +1 -1
  86. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
  87. package/dist/mcp/mcp-api-key.controller.d.ts +2 -0
  88. package/dist/mcp/mcp-api-key.controller.d.ts.map +1 -1
  89. package/dist/mcp/mcp-api-key.controller.js +1 -1
  90. package/dist/mcp/mcp-api-key.controller.js.map +1 -1
  91. package/dist/mcp/mcp-api-key.service.d.ts +2 -1
  92. package/dist/mcp/mcp-api-key.service.d.ts.map +1 -1
  93. package/dist/mcp/mcp-api-key.service.js +6 -2
  94. package/dist/mcp/mcp-api-key.service.js.map +1 -1
  95. package/dist/mcp/mcp.module.d.ts.map +1 -1
  96. package/dist/mcp/mcp.module.js +3 -5
  97. package/dist/mcp/mcp.module.js.map +1 -1
  98. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  99. package/dist/mcp-chat/mcp-chat.service.js +17 -16
  100. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  101. package/dist/oauth/interfaces/OAuthProvider.d.ts +1 -1
  102. package/dist/oauth/interfaces/OAuthProvider.d.ts.map +1 -1
  103. package/dist/oauth/oauth.controller.d.ts +4 -1
  104. package/dist/oauth/oauth.controller.d.ts.map +1 -1
  105. package/dist/oauth/oauth.controller.js +31 -5
  106. package/dist/oauth/oauth.controller.js.map +1 -1
  107. package/dist/oauth/oauth.service.d.ts +12 -1
  108. package/dist/oauth/oauth.service.d.ts.map +1 -1
  109. package/dist/oauth/oauth.service.js +125 -23
  110. package/dist/oauth/oauth.service.js.map +1 -1
  111. package/dist/oauth/providers/abstract.provider.d.ts +1 -1
  112. package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
  113. package/dist/oauth/providers/facebook.provider.d.ts +5 -2
  114. package/dist/oauth/providers/facebook.provider.d.ts.map +1 -1
  115. package/dist/oauth/providers/facebook.provider.js +34 -19
  116. package/dist/oauth/providers/facebook.provider.js.map +1 -1
  117. package/dist/oauth/providers/github.provider.d.ts +6 -2
  118. package/dist/oauth/providers/github.provider.d.ts.map +1 -1
  119. package/dist/oauth/providers/github.provider.js +43 -20
  120. package/dist/oauth/providers/github.provider.js.map +1 -1
  121. package/dist/oauth/providers/google.provider.d.ts +5 -2
  122. package/dist/oauth/providers/google.provider.d.ts.map +1 -1
  123. package/dist/oauth/providers/google.provider.js +34 -19
  124. package/dist/oauth/providers/google.provider.js.map +1 -1
  125. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts +5 -2
  126. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
  127. package/dist/oauth/providers/microsoft-entra-id.provider.js +43 -40
  128. package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
  129. package/dist/oauth/providers/microsoft.provider.d.ts +5 -2
  130. package/dist/oauth/providers/microsoft.provider.d.ts.map +1 -1
  131. package/dist/oauth/providers/microsoft.provider.js +34 -19
  132. package/dist/oauth/providers/microsoft.provider.js.map +1 -1
  133. package/dist/profile/profile.controller.js +1 -1
  134. package/dist/profile/profile.controller.js.map +1 -1
  135. package/dist/security/security.service.d.ts +2 -0
  136. package/dist/security/security.service.d.ts.map +1 -1
  137. package/dist/security/security.service.js +21 -0
  138. package/dist/security/security.service.js.map +1 -1
  139. package/dist/setting/setting.service.d.ts +26 -1
  140. package/dist/setting/setting.service.d.ts.map +1 -1
  141. package/dist/setting/setting.service.js +240 -7
  142. package/dist/setting/setting.service.js.map +1 -1
  143. package/dist/user/user.controller.d.ts +2 -1
  144. package/dist/user/user.controller.d.ts.map +1 -1
  145. package/dist/user/user.controller.js +5 -4
  146. package/dist/user/user.controller.js.map +1 -1
  147. package/dist/user/user.service.d.ts +4 -2
  148. package/dist/user/user.service.d.ts.map +1 -1
  149. package/dist/user/user.service.js +19 -4
  150. package/dist/user/user.service.js.map +1 -1
  151. package/dist/webhook-integration/dto/webhook-action.dto.d.ts +17 -2
  152. package/dist/webhook-integration/dto/webhook-action.dto.d.ts.map +1 -1
  153. package/dist/webhook-integration/dto/webhook-action.dto.js +93 -2
  154. package/dist/webhook-integration/dto/webhook-action.dto.js.map +1 -1
  155. package/dist/webhook-integration/event-webhook.controller.d.ts +1 -0
  156. package/dist/webhook-integration/event-webhook.controller.d.ts.map +1 -1
  157. package/dist/webhook-integration/event-webhook.controller.js +10 -0
  158. package/dist/webhook-integration/event-webhook.controller.js.map +1 -1
  159. package/dist/webhook-integration/event-webhook.service.d.ts +2 -0
  160. package/dist/webhook-integration/event-webhook.service.d.ts.map +1 -1
  161. package/dist/webhook-integration/event-webhook.service.js +30 -0
  162. package/dist/webhook-integration/event-webhook.service.js.map +1 -1
  163. package/dist/webhook-integration/webhook-command.registry.d.ts +15 -0
  164. package/dist/webhook-integration/webhook-command.registry.d.ts.map +1 -0
  165. package/dist/webhook-integration/webhook-command.registry.js +36 -0
  166. package/dist/webhook-integration/webhook-command.registry.js.map +1 -0
  167. package/dist/webhook-integration/webhook-integration.controller.d.ts +20 -0
  168. package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
  169. package/dist/webhook-integration/webhook-integration.controller.js +48 -0
  170. package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
  171. package/dist/webhook-integration/webhook-integration.module.d.ts.map +1 -1
  172. package/dist/webhook-integration/webhook-integration.module.js +5 -0
  173. package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
  174. package/dist/webhook-integration/webhook-integration.service.d.ts +27 -2
  175. package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
  176. package/dist/webhook-integration/webhook-integration.service.js +377 -50
  177. package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
  178. package/hedhog/data/file_provider.yaml +9 -1
  179. package/hedhog/data/integration_provider.yaml +148 -0
  180. package/hedhog/data/integration_type.yaml +29 -0
  181. package/hedhog/data/menu.yaml +6 -21
  182. package/hedhog/data/role.yaml +8 -0
  183. package/hedhog/data/route.yaml +73 -373
  184. package/hedhog/data/setting_group.yaml +209 -365
  185. package/hedhog/data/setting_subgroup.yaml +21 -13
  186. package/hedhog/frontend/app/account/components/connected-accounts.tsx.ejs +25 -20
  187. package/hedhog/frontend/app/account/components/tokens.tsx.ejs +421 -0
  188. package/hedhog/frontend/app/account/layout.tsx.ejs +6 -3
  189. package/hedhog/frontend/app/account/mcp-tokens/page.tsx.ejs +2 -2
  190. package/hedhog/frontend/app/account/tokens/page.tsx.ejs +5 -0
  191. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +938 -225
  192. package/hedhog/frontend/app/configurations/layout.tsx.ejs +1 -1
  193. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +3 -1
  194. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +1830 -0
  195. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +829 -128
  196. package/hedhog/frontend/app/mail/profiles/page.tsx.ejs +1 -820
  197. package/hedhog/frontend/app/setting-list/page.tsx.ejs +229 -395
  198. package/hedhog/frontend/app/users/permissions.tsx.ejs +79 -2
  199. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +7 -2
  200. package/hedhog/frontend/messages/en.json +239 -3
  201. package/hedhog/frontend/messages/pt.json +239 -3
  202. package/hedhog/table/file.yaml +1 -1
  203. package/hedhog/table/integration_profile.yaml +34 -0
  204. package/hedhog/table/integration_provider.yaml +23 -0
  205. package/hedhog/table/integration_type.yaml +19 -0
  206. package/hedhog/table/mcp_api_key.yaml +4 -0
  207. package/hedhog/table/webhook_action.yaml +141 -85
  208. package/package.json +4 -3
  209. package/src/ai/ai.service.ts +35 -153
  210. package/src/auth/guards/auth.guard.ts +32 -0
  211. package/src/core.module.ts +3 -3
  212. package/src/file/file.controller.ts +51 -42
  213. package/src/file/file.service.ts +67 -104
  214. package/src/file/provider/azure.provider.ts +14 -28
  215. package/src/file/provider/gcs.provider.ts +9 -9
  216. package/src/file/provider/local.provider.ts +10 -13
  217. package/src/file/provider/provider.enum.ts +1 -0
  218. package/src/file/provider/provider.factory.ts +21 -6
  219. package/src/file/provider/s3.provider.ts +4 -20
  220. package/src/file/provider/spaces.provider.ts +246 -0
  221. package/src/index.ts +6 -3
  222. package/src/integration-profile/dto/create.dto.ts +44 -0
  223. package/src/integration-profile/dto/export.dto.ts +15 -0
  224. package/src/integration-profile/dto/import-confirm.dto.ts +61 -0
  225. package/src/integration-profile/integration-profile.controller.ts +131 -0
  226. package/src/integration-profile/integration-profile.module.ts +16 -0
  227. package/src/integration-profile/integration-profile.service.ts +793 -0
  228. package/src/integration-profile/integration-profile.utils.ts +173 -0
  229. package/src/mail/mail.module.ts +41 -22
  230. package/src/mail/mail.service.ts +40 -64
  231. package/src/mcp/guards/mcp-auth.guard.ts +1 -1
  232. package/src/mcp/mcp-api-key.controller.ts +2 -2
  233. package/src/mcp/mcp-api-key.service.ts +6 -2
  234. package/src/mcp/mcp.module.ts +3 -5
  235. package/src/mcp-chat/mcp-chat.service.ts +23 -20
  236. package/src/oauth/interfaces/OAuthProvider.ts +1 -1
  237. package/src/oauth/oauth.controller.ts +30 -2
  238. package/src/oauth/oauth.service.ts +194 -35
  239. package/src/oauth/providers/abstract.provider.ts +1 -1
  240. package/src/oauth/providers/facebook.provider.ts +36 -20
  241. package/src/oauth/providers/github.provider.ts +46 -23
  242. package/src/oauth/providers/google.provider.ts +36 -20
  243. package/src/oauth/providers/microsoft-entra-id.provider.ts +42 -46
  244. package/src/oauth/providers/microsoft.provider.ts +36 -21
  245. package/src/profile/profile.controller.ts +2 -2
  246. package/src/security/security.service.ts +34 -1
  247. package/src/setting/setting.service.ts +307 -9
  248. package/src/user/user.controller.ts +4 -1
  249. package/src/user/user.service.ts +20 -2
  250. package/src/webhook-integration/dto/webhook-action.dto.ts +85 -4
  251. package/src/webhook-integration/event-webhook.controller.ts +55 -50
  252. package/src/webhook-integration/event-webhook.service.ts +422 -384
  253. package/src/webhook-integration/webhook-command.registry.ts +42 -0
  254. package/src/webhook-integration/webhook-integration.controller.ts +25 -0
  255. package/src/webhook-integration/webhook-integration.module.ts +50 -45
  256. package/src/webhook-integration/webhook-integration.service.ts +444 -53
  257. package/dist/mail-profile/dto/create.dto.d.ts +0 -23
  258. package/dist/mail-profile/dto/create.dto.d.ts.map +0 -1
  259. package/dist/mail-profile/dto/create.dto.js +0 -139
  260. package/dist/mail-profile/dto/create.dto.js.map +0 -1
  261. package/dist/mail-profile/dto/update.dto.d.ts.map +0 -1
  262. package/dist/mail-profile/dto/update.dto.js.map +0 -1
  263. package/dist/mail-profile/mail-profile.controller.d.ts +0 -94
  264. package/dist/mail-profile/mail-profile.controller.d.ts.map +0 -1
  265. package/dist/mail-profile/mail-profile.controller.js +0 -95
  266. package/dist/mail-profile/mail-profile.controller.js.map +0 -1
  267. package/dist/mail-profile/mail-profile.module.d.ts +0 -3
  268. package/dist/mail-profile/mail-profile.module.d.ts.map +0 -1
  269. package/dist/mail-profile/mail-profile.module.js.map +0 -1
  270. package/dist/mail-profile/mail-profile.service.d.ts +0 -109
  271. package/dist/mail-profile/mail-profile.service.d.ts.map +0 -1
  272. package/dist/mail-profile/mail-profile.service.js +0 -278
  273. package/dist/mail-profile/mail-profile.service.js.map +0 -1
  274. package/dist/mcp/tools/core-mail-profile.mcp-tools.d.ts +0 -32
  275. package/dist/mcp/tools/core-mail-profile.mcp-tools.d.ts.map +0 -1
  276. package/dist/mcp/tools/core-mail-profile.mcp-tools.js +0 -178
  277. package/dist/mcp/tools/core-mail-profile.mcp-tools.js.map +0 -1
  278. package/hedhog/data/mail_profile.yaml +0 -18
  279. package/hedhog/table/mail_profile.yaml +0 -75
  280. package/src/mail-profile/dto/create.dto.ts +0 -145
  281. package/src/mail-profile/mail-profile.controller.ts +0 -56
  282. package/src/mail-profile/mail-profile.module.ts +0 -18
  283. package/src/mail-profile/mail-profile.service.ts +0 -308
  284. package/src/mcp/tools/core-mail-profile.mcp-tools.ts +0 -128
  285. /package/dist/{mail-profile → integration-profile}/dto/update.dto.d.ts +0 -0
  286. /package/dist/{mail-profile → integration-profile}/dto/update.dto.js +0 -0
  287. /package/src/{mail-profile → integration-profile}/dto/update.dto.ts +0 -0
@@ -12,12 +12,19 @@ import {
12
12
  import { EventEmitter } from 'events';
13
13
  import { Request, Response } from 'express';
14
14
  import { firstValueFrom } from 'rxjs';
15
+ import {
16
+ buildMailConfigFromIntegration,
17
+ getFromAddress,
18
+ getReplyToAddress,
19
+ } from '../integration-profile/integration-profile.utils';
15
20
  import { MailService } from '../mail/mail.service';
21
+ import { McpApiKeyService } from '../mcp/mcp-api-key.service';
16
22
  import { SettingService } from '../setting/setting.service';
17
23
  import {
18
- CreateWebhookActionDTO,
19
- UpdateWebhookActionDTO,
24
+ CreateWebhookActionDTO,
25
+ UpdateWebhookActionDTO,
20
26
  } from './dto/webhook-action.dto';
27
+ import { WebhookCommandRegistry } from './webhook-command.registry';
21
28
  import {
22
29
  createPlainToken,
23
30
  createPublicUuid,
@@ -31,7 +38,12 @@ import {
31
38
  type ActionExecutionLog = {
32
39
  webhookActionId: number;
33
40
  actionName: string;
34
- actionType: 'email' | 'whatsapp_evolution';
41
+ actionType:
42
+ | 'email'
43
+ | 'whatsapp_evolution'
44
+ | 'http_request'
45
+ | 'internal_api'
46
+ | 'app_command';
35
47
  status: 'success' | 'failed';
36
48
  durationMs: number;
37
49
  requestPayload?: unknown;
@@ -47,6 +59,42 @@ type WebhookActionPayload =
47
59
  @Injectable()
48
60
  export class WebhookIntegrationService {
49
61
  private readonly logEmitter = new EventEmitter();
62
+ private readonly webhookActionSelect = {
63
+ id: true,
64
+ webhook_integration_id: true,
65
+ type: true,
66
+ name: true,
67
+ order: true,
68
+ status: true,
69
+ integration_profile_id: true,
70
+ mail_id: true,
71
+ email_to: true,
72
+ email_cc: true,
73
+ email_bcc: true,
74
+ whatsapp_target_type: true,
75
+ whatsapp_target: true,
76
+ whatsapp_template: true,
77
+ whatsapp_instance: true,
78
+ whatsapp_base_url: true,
79
+ whatsapp_token: true,
80
+ http_url: true,
81
+ http_method: true,
82
+ http_headers: true,
83
+ http_query: true,
84
+ http_body: true,
85
+ http_timeout_ms: true,
86
+ http_retry_count: true,
87
+ internal_api_path: true,
88
+ internal_api_method: true,
89
+ internal_api_query: true,
90
+ internal_api_body: true,
91
+ internal_api_token: true,
92
+ internal_api_user_id: true,
93
+ app_command_slug: true,
94
+ app_command_params: true,
95
+ created_at: true,
96
+ updated_at: true,
97
+ } as const;
50
98
 
51
99
  constructor(
52
100
  private readonly prisma: PrismaService,
@@ -55,6 +103,8 @@ export class WebhookIntegrationService {
55
103
  private readonly mailMainService: MailMainService,
56
104
  private readonly coreMailService: MailService,
57
105
  private readonly settingService: SettingService,
106
+ private readonly commandRegistry: WebhookCommandRegistry,
107
+ private readonly mcpApiKeyService: McpApiKeyService,
58
108
  ) {}
59
109
 
60
110
  private get integrations() {
@@ -84,6 +134,7 @@ export class WebhookIntegrationService {
84
134
  where: OR.length > 0 ? { OR } : {},
85
135
  include: {
86
136
  webhook_action: {
137
+ select: this.webhookActionSelect,
87
138
  orderBy: [{ order: 'asc' }, { id: 'asc' }],
88
139
  },
89
140
  },
@@ -102,6 +153,7 @@ export class WebhookIntegrationService {
102
153
  where: { id },
103
154
  include: {
104
155
  webhook_action: {
156
+ select: this.webhookActionSelect,
105
157
  orderBy: [{ order: 'asc' }, { id: 'asc' }],
106
158
  },
107
159
  },
@@ -203,6 +255,82 @@ export class WebhookIntegrationService {
203
255
  };
204
256
  }
205
257
 
258
+ async duplicate(id: number) {
259
+ const original = await this.get(id);
260
+
261
+ const newSlug = await this.generateUniqueSlug(original.slug, this.integrations);
262
+
263
+ let plainToken: string | null = null;
264
+ let tokenHash: string | null = null;
265
+ if (original.require_token) {
266
+ plainToken = createPlainToken();
267
+ tokenHash = hashToken(plainToken);
268
+ }
269
+
270
+ const record = await this.integrations.create({
271
+ data: {
272
+ slug: newSlug,
273
+ name: `${original.name} (copy)`,
274
+ description: original.description,
275
+ public_uuid: createPublicUuid(),
276
+ status: original.status,
277
+ require_token: original.require_token,
278
+ token_hash: tokenHash,
279
+ allowed_ips: original.allowed_ips,
280
+ body_schema: original.body_schema,
281
+ webhook_action: {
282
+ create: (original.webhook_action ?? []).map((a: any) => ({
283
+ type: a.type,
284
+ name: a.name,
285
+ order: a.order,
286
+ status: a.status,
287
+ integration_profile_id:
288
+ a.integration_profile_id ?? null,
289
+ mail_id: a.mail_id,
290
+ email_to: a.email_to,
291
+ email_cc: a.email_cc,
292
+ email_bcc: a.email_bcc,
293
+ whatsapp_target_type: a.whatsapp_target_type,
294
+ whatsapp_target: a.whatsapp_target,
295
+ whatsapp_template: a.whatsapp_template,
296
+ whatsapp_instance: a.whatsapp_instance,
297
+ whatsapp_base_url: a.whatsapp_base_url,
298
+ whatsapp_token: a.whatsapp_token,
299
+ http_url: a.http_url,
300
+ http_method: a.http_method,
301
+ http_headers: a.http_headers,
302
+ http_query: a.http_query,
303
+ http_body: a.http_body,
304
+ http_timeout_ms: a.http_timeout_ms,
305
+ http_retry_count: a.http_retry_count,
306
+ internal_api_path: a.internal_api_path,
307
+ internal_api_method: a.internal_api_method,
308
+ internal_api_query: a.internal_api_query,
309
+ internal_api_body: a.internal_api_body,
310
+ internal_api_token: a.internal_api_token,
311
+ internal_api_user_id: a.internal_api_user_id,
312
+ app_command_slug: a.app_command_slug,
313
+ app_command_params: a.app_command_params,
314
+ })),
315
+ },
316
+ },
317
+ });
318
+
319
+ return { ...(await this.withPublicUrl(record)), plainToken };
320
+ }
321
+
322
+ private async generateUniqueSlug(base: string, table: any): Promise<string> {
323
+ const candidate = `${base}-copy`;
324
+ const existing = await table.findUnique({ where: { slug: candidate } });
325
+ if (!existing) return candidate;
326
+
327
+ for (let i = 2; ; i++) {
328
+ const next = `${base}-copy-${i}`;
329
+ const taken = await table.findUnique({ where: { slug: next } });
330
+ if (!taken) return next;
331
+ }
332
+ }
333
+
206
334
  private async getApplicationBaseUrl() {
207
335
  const settings = await this.settingService.getSettingValues([
208
336
  'api-url',
@@ -293,6 +421,48 @@ export class WebhookIntegrationService {
293
421
  });
294
422
  }
295
423
 
424
+ async listUserApiTokens(userId: number) {
425
+ return (this.prisma as any).mcp_api_key.findMany({
426
+ where: { user_id: userId, type: 'api', revoked_at: null },
427
+ select: {
428
+ id: true,
429
+ name: true,
430
+ token_prefix: true,
431
+ last_used_at: true,
432
+ created_at: true,
433
+ },
434
+ orderBy: { created_at: 'desc' },
435
+ });
436
+ }
437
+
438
+ async createUserApiToken(userId: number, name: string) {
439
+ return this.mcpApiKeyService.create(userId, name, 'api');
440
+ }
441
+
442
+ async listInternalRoutes() {
443
+ return (this.prisma as any).route.findMany({
444
+ select: {
445
+ id: true,
446
+ url: true,
447
+ method: true,
448
+ },
449
+ where: {
450
+ url: { not: null },
451
+ method: { not: null },
452
+ },
453
+ orderBy: [{ url: 'asc' }, { method: 'asc' }],
454
+ });
455
+ }
456
+
457
+ async listAppCommands() {
458
+ return this.commandRegistry.list().map((cmd) => ({
459
+ slug: cmd.slug,
460
+ name: cmd.name,
461
+ description: cmd.description,
462
+ inputSchema: cmd.inputSchema,
463
+ }));
464
+ }
465
+
296
466
  async listLogs(
297
467
  integrationId: number,
298
468
  paginationParams: PaginationDTO,
@@ -391,6 +561,7 @@ export class WebhookIntegrationService {
391
561
  where: { public_uuid: uuid },
392
562
  include: {
393
563
  webhook_action: {
564
+ select: this.webhookActionSelect,
394
565
  where: { status: 'active' },
395
566
  orderBy: [{ order: 'asc' }, { id: 'asc' }],
396
567
  },
@@ -533,14 +704,27 @@ export class WebhookIntegrationService {
533
704
  return this.executeWhatsappAction(action, body);
534
705
  }
535
706
 
707
+ if (action.type === 'http_request') {
708
+ return this.executeHttpRequestAction(action, body);
709
+ }
710
+
711
+ if (action.type === 'internal_api') {
712
+ return this.executeInternalApiAction(action, body);
713
+ }
714
+
715
+ if (action.type === 'app_command') {
716
+ return this.executeAppCommandAction(action, body);
717
+ }
718
+
536
719
  throw new BadRequestException(`Unsupported action type: ${action.type}`);
537
720
  }
538
721
 
539
722
  private async executeEmailAction(action: any, body: any) {
540
723
  this.validateActionConfiguration(action);
541
724
 
542
- const profile = await (this.prisma as any).mail_profile.findUnique({
543
- where: { id: Number(action.mail_profile_id) },
725
+ const profile = await (this.prisma as any).integration_profile.findUnique({
726
+ where: { id: Number(action.integration_profile_id) },
727
+ include: { integration_provider: { select: { slug: true } } },
544
728
  });
545
729
  const mail = await (this.prisma as any).mail.findUnique({
546
730
  where: { id: Number(action.mail_id) },
@@ -558,15 +742,12 @@ export class WebhookIntegrationService {
558
742
  }
559
743
 
560
744
  const template = mail.mail_locale[0];
561
- const config = this.buildMailConfig(profile);
562
- const sender = profile.from_name
563
- ? `${profile.from_name} <${profile.from_email}>`
564
- : profile.from_email;
565
- const replyTo = profile.reply_to_email
566
- ? profile.reply_to_name
567
- ? `${profile.reply_to_name} <${profile.reply_to_email}>`
568
- : profile.reply_to_email
569
- : undefined;
745
+ const config = buildMailConfigFromIntegration(
746
+ profile.integration_provider.slug,
747
+ profile.config,
748
+ );
749
+ const sender = getFromAddress(profile.config);
750
+ const replyTo = getReplyToAddress(profile.config);
570
751
 
571
752
  const renderedTo = String(renderTemplate(action.email_to, body) ?? '').trim();
572
753
  const renderedCc = action.email_cc
@@ -686,6 +867,193 @@ export class WebhookIntegrationService {
686
867
  };
687
868
  }
688
869
 
870
+ private async executeHttpRequestAction(action: any, body: any) {
871
+ this.validateActionConfiguration(action);
872
+
873
+ const method = String(action.http_method || 'POST').toUpperCase();
874
+ const rawUrl = String(action.http_url || '').trim();
875
+ const timeoutMs = Number(action.http_timeout_ms || 30000);
876
+ const maxAttempts = Math.max(1, Number(action.http_retry_count || 0) + 1);
877
+
878
+ const renderedUrl = String(renderTemplate(rawUrl, body) ?? rawUrl).trim();
879
+
880
+ const rawHeaders = normalizeJsonObject(action.http_headers) || {};
881
+ const renderedHeaders: Record<string, string> = {};
882
+ for (const [k, v] of Object.entries(rawHeaders)) {
883
+ renderedHeaders[k] = String(renderTemplate(String(v), body) ?? v);
884
+ }
885
+
886
+ const rawQuery = normalizeJsonObject(action.http_query) || {};
887
+ const renderedQuery: Record<string, string> = {};
888
+ for (const [k, v] of Object.entries(rawQuery)) {
889
+ renderedQuery[k] = String(renderTemplate(String(v), body) ?? v);
890
+ }
891
+
892
+ const rawBody = String(action.http_body || '').trim();
893
+ const renderedBody = rawBody
894
+ ? (renderTemplate(rawBody, body) as string)
895
+ : undefined;
896
+
897
+ let parsedBody: unknown = renderedBody;
898
+ if (renderedBody) {
899
+ try {
900
+ parsedBody = JSON.parse(renderedBody);
901
+ } catch {
902
+ parsedBody = renderedBody;
903
+ }
904
+ }
905
+
906
+ const requestPayload = {
907
+ method,
908
+ url: renderedUrl,
909
+ headers: renderedHeaders,
910
+ query: renderedQuery,
911
+ body: parsedBody,
912
+ };
913
+
914
+ let lastError: unknown;
915
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
916
+ try {
917
+ const response = await firstValueFrom(
918
+ this.http.request({
919
+ method,
920
+ url: renderedUrl,
921
+ headers: renderedHeaders,
922
+ params: Object.keys(renderedQuery).length ? renderedQuery : undefined,
923
+ data: parsedBody,
924
+ timeout: timeoutMs,
925
+ }),
926
+ );
927
+
928
+ return {
929
+ requestPayload,
930
+ responsePayload: {
931
+ status: response?.status || null,
932
+ statusText: response?.statusText || null,
933
+ data: response?.data || null,
934
+ },
935
+ };
936
+ } catch (error) {
937
+ lastError = error;
938
+ if (attempt === maxAttempts - 1) {
939
+ this.attachErrorRequestPayload(error, requestPayload);
940
+ throw error;
941
+ }
942
+ }
943
+ }
944
+
945
+ this.attachErrorRequestPayload(lastError, requestPayload);
946
+ throw lastError;
947
+ }
948
+
949
+ private async executeInternalApiAction(action: any, body: any) {
950
+ this.validateActionConfiguration(action);
951
+
952
+ const baseUrl = await this.getApplicationBaseUrl();
953
+ if (!baseUrl) {
954
+ throw new BadRequestException(
955
+ 'Internal API action requires the api-url setting to be configured.',
956
+ );
957
+ }
958
+
959
+ const method = String(action.internal_api_method || 'POST').toUpperCase();
960
+ const rawPath = String(action.internal_api_path || '').trim();
961
+ const token = String(action.internal_api_token || '').trim();
962
+
963
+ const renderedPath = String(renderTemplate(rawPath, body) ?? rawPath).trim();
964
+
965
+ const rawQuery = normalizeJsonObject(action.internal_api_query) || {};
966
+ const renderedQuery: Record<string, string> = {};
967
+ for (const [k, v] of Object.entries(rawQuery)) {
968
+ renderedQuery[k] = String(renderTemplate(String(v), body) ?? v);
969
+ }
970
+
971
+ const rawBody = normalizeJsonObject(action.internal_api_body) || {};
972
+ const renderedBodyObj: Record<string, unknown> = {};
973
+ for (const [k, v] of Object.entries(rawBody)) {
974
+ renderedBodyObj[k] = typeof v === 'string' ? renderTemplate(v, body) : v;
975
+ }
976
+
977
+ const url = `${baseUrl}${renderedPath.startsWith('/') ? '' : '/'}${renderedPath}`;
978
+
979
+ const requestPayload = {
980
+ method,
981
+ url,
982
+ query: renderedQuery,
983
+ body: renderedBodyObj,
984
+ };
985
+
986
+ let response: any;
987
+ try {
988
+ response = await firstValueFrom(
989
+ this.http.request({
990
+ method,
991
+ url,
992
+ headers: {
993
+ Authorization: `Bearer ${token}`,
994
+ 'Content-Type': 'application/json',
995
+ },
996
+ params: Object.keys(renderedQuery).length ? renderedQuery : undefined,
997
+ data: Object.keys(renderedBodyObj).length ? renderedBodyObj : undefined,
998
+ timeout: 30000,
999
+ }),
1000
+ );
1001
+ } catch (error) {
1002
+ this.attachErrorRequestPayload(error, requestPayload);
1003
+ throw error;
1004
+ }
1005
+
1006
+ return {
1007
+ requestPayload,
1008
+ responsePayload: {
1009
+ status: response?.status || null,
1010
+ statusText: response?.statusText || null,
1011
+ data: response?.data || null,
1012
+ },
1013
+ };
1014
+ }
1015
+
1016
+ private async executeAppCommandAction(action: any, body: any) {
1017
+ this.validateActionConfiguration(action);
1018
+
1019
+ const slug = String(action.app_command_slug || '').trim();
1020
+ const command = this.commandRegistry.find(slug);
1021
+ if (!command) {
1022
+ throw new BadRequestException(`app_command: unknown command slug "${slug}".`);
1023
+ }
1024
+
1025
+ const rawParams = normalizeJsonObject(action.app_command_params) || {};
1026
+ const renderedParams: Record<string, unknown> = {};
1027
+ for (const [k, v] of Object.entries(rawParams)) {
1028
+ renderedParams[k] = typeof v === 'string' ? renderTemplate(v, body) : v;
1029
+ }
1030
+
1031
+ const schemaErrors = this.validateJsonSchema(command.inputSchema, renderedParams);
1032
+ if (schemaErrors.length) {
1033
+ throw new BadRequestException({
1034
+ message: `app_command "${slug}" params do not match expected schema.`,
1035
+ errors: schemaErrors,
1036
+ });
1037
+ }
1038
+
1039
+ const requestPayload = { slug, params: renderedParams };
1040
+
1041
+ let result: unknown;
1042
+ try {
1043
+ result = await this.commandRegistry.dispatch(slug, renderedParams, {
1044
+ webhookBody: body,
1045
+ });
1046
+ } catch (error) {
1047
+ this.attachErrorRequestPayload(error, requestPayload);
1048
+ throw error;
1049
+ }
1050
+
1051
+ return {
1052
+ requestPayload,
1053
+ responsePayload: result,
1054
+ };
1055
+ }
1056
+
689
1057
  private validateToken(integration: any, headers: any) {
690
1058
  if (!integration.require_token) {
691
1059
  return;
@@ -719,8 +1087,8 @@ export class WebhookIntegrationService {
719
1087
  if (action?.type === 'email') {
720
1088
  const missing: string[] = [];
721
1089
 
722
- if (!this.nullableNumber(action.mail_profile_id)) {
723
- missing.push('mail_profile_id');
1090
+ if (!this.nullableNumber(action.integration_profile_id)) {
1091
+ missing.push('integration_profile_id');
724
1092
  }
725
1093
 
726
1094
  if (!this.nullableNumber(action.mail_id)) {
@@ -755,6 +1123,40 @@ export class WebhookIntegrationService {
755
1123
  );
756
1124
  }
757
1125
  }
1126
+
1127
+ if (action?.type === 'http_request') {
1128
+ if (!this.nullableString(action.http_url)) {
1129
+ throw new BadRequestException(
1130
+ 'HTTP request action is missing required configuration: http_url.',
1131
+ );
1132
+ }
1133
+ }
1134
+
1135
+ if (action?.type === 'internal_api') {
1136
+ const missing: string[] = [];
1137
+ if (!this.nullableString(action.internal_api_path)) {
1138
+ missing.push('internal_api_path');
1139
+ }
1140
+ if (!this.nullableNumber(action.internal_api_user_id)) {
1141
+ missing.push('internal_api_user_id');
1142
+ }
1143
+ if (!this.nullableString(action.internal_api_token)) {
1144
+ missing.push('internal_api_token');
1145
+ }
1146
+ if (missing.length) {
1147
+ throw new BadRequestException(
1148
+ `Internal API action is missing required configuration: ${missing.join(', ')}.`,
1149
+ );
1150
+ }
1151
+ }
1152
+
1153
+ if (action?.type === 'app_command') {
1154
+ if (!this.nullableString(action.app_command_slug)) {
1155
+ throw new BadRequestException(
1156
+ 'App command action is missing required configuration: app_command_slug.',
1157
+ );
1158
+ }
1159
+ }
758
1160
  }
759
1161
 
760
1162
  private validateBodySchema(integration: any, body: any) {
@@ -1046,7 +1448,10 @@ export class WebhookIntegrationService {
1046
1448
  assign('name', String(data.name ?? '').trim());
1047
1449
  assign('order', Number(data.order ?? 0));
1048
1450
  assign('status', data.status === 'inactive' ? 'inactive' : 'active');
1049
- assign('mail_profile_id', this.nullableNumber(data.mail_profile_id, partial));
1451
+ assign(
1452
+ 'integration_profile_id',
1453
+ this.nullableNumber((data as any).integration_profile_id, partial),
1454
+ );
1050
1455
  assign('mail_id', this.nullableNumber(data.mail_id, partial));
1051
1456
  assign('email_to', this.nullableString(data.email_to, partial));
1052
1457
  assign('email_cc', this.nullableString(data.email_cc, partial));
@@ -1069,6 +1474,27 @@ export class WebhookIntegrationService {
1069
1474
  this.nullableString(data.whatsapp_base_url, partial),
1070
1475
  );
1071
1476
  assign('whatsapp_token', this.nullableString(data.whatsapp_token, partial));
1477
+ assign('http_url', this.nullableString(data.http_url, partial));
1478
+ assign('http_method', this.nullableString(data.http_method, partial));
1479
+ assign('http_headers', normalizeJsonObject(data.http_headers));
1480
+ assign('http_query', normalizeJsonObject(data.http_query));
1481
+ assign('http_body', this.nullableString(data.http_body, partial));
1482
+ assign('http_timeout_ms', this.nullableNumber(data.http_timeout_ms, partial));
1483
+ assign('http_retry_count', this.nullableNumber(data.http_retry_count, partial));
1484
+ assign('internal_api_path', this.nullableString(data.internal_api_path, partial));
1485
+ assign(
1486
+ 'internal_api_method',
1487
+ this.nullableString(data.internal_api_method, partial),
1488
+ );
1489
+ assign('internal_api_query', normalizeJsonObject(data.internal_api_query));
1490
+ assign('internal_api_body', normalizeJsonObject(data.internal_api_body));
1491
+ assign('internal_api_token', this.nullableString(data.internal_api_token, partial));
1492
+ assign(
1493
+ 'internal_api_user_id',
1494
+ this.nullableNumber(data.internal_api_user_id, partial),
1495
+ );
1496
+ assign('app_command_slug', this.nullableString(data.app_command_slug, partial));
1497
+ assign('app_command_params', normalizeJsonObject(data.app_command_params));
1072
1498
 
1073
1499
  return normalized;
1074
1500
  }
@@ -1098,40 +1524,5 @@ export class WebhookIntegrationService {
1098
1524
  return Number(value);
1099
1525
  }
1100
1526
 
1101
- private buildMailConfig(profile: any) {
1102
- switch (profile.provider) {
1103
- case 'SMTP':
1104
- return {
1105
- global: true,
1106
- type: 'SMTP',
1107
- host: profile.smtp_host,
1108
- port: Number(profile.smtp_port || 587),
1109
- secure: Boolean(profile.smtp_secure),
1110
- username: profile.smtp_username || '',
1111
- password: profile.smtp_password || '',
1112
- };
1113
- case 'GMAIL':
1114
- return {
1115
- global: true,
1116
- type: 'GMAIL',
1117
- clientId: profile.gmail_client_id,
1118
- clientSecret: profile.gmail_client_secret,
1119
- refreshToken: profile.gmail_refresh_token,
1120
- from: profile.from_email,
1121
- };
1122
- case 'SES':
1123
- return {
1124
- global: true,
1125
- type: 'SES',
1126
- region: profile.ses_region,
1127
- accessKeyId: profile.ses_access_key_id,
1128
- secretAccessKey: profile.ses_secret_access_key,
1129
- from: profile.from_email,
1130
- };
1131
- default:
1132
- throw new BadRequestException(
1133
- `Invalid mail profile provider: ${profile.provider}`,
1134
- );
1135
- }
1136
- }
1137
1527
  }
1528
+
@@ -1,23 +0,0 @@
1
- declare const providerOptions: readonly ["SMTP", "GMAIL", "SES"];
2
- export declare class CreateDTO {
3
- slug: string;
4
- name: string;
5
- provider: (typeof providerOptions)[number];
6
- from_name?: string;
7
- from_email: string;
8
- reply_to_name?: string;
9
- reply_to_email?: string;
10
- smtp_host?: string;
11
- smtp_port?: number;
12
- smtp_secure?: boolean;
13
- smtp_username?: string;
14
- smtp_password?: string;
15
- gmail_client_id?: string;
16
- gmail_client_secret?: string;
17
- gmail_refresh_token?: string;
18
- ses_access_key_id?: string;
19
- ses_secret_access_key?: string;
20
- ses_region?: string;
21
- }
22
- export {};
23
- //# sourceMappingURL=create.dto.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create.dto.d.ts","sourceRoot":"","sources":["../../../src/mail-profile/dto/create.dto.ts"],"names":[],"mappings":"AAaA,QAAA,MAAM,eAAe,mCAAoC,CAAC;AAE1D,qBAAa,SAAS;IAIpB,IAAI,EAAE,MAAM,CAAC;IAKb,IAAI,EAAE,MAAM,CAAC;IAIb,QAAQ,EAAE,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;IAQ3C,SAAS,CAAC,EAAE,MAAM,CAAC;IAKnB,UAAU,EAAE,MAAM,CAAC;IAQnB,aAAa,CAAC,EAAE,MAAM,CAAC;IAQvB,cAAc,CAAC,EAAE,MAAM,CAAC;IAQxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAQnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAOnB,WAAW,CAAC,EAAE,OAAO,CAAC;IAQtB,aAAa,CAAC,EAAE,MAAM,CAAC;IAQvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAQvB,eAAe,CAAC,EAAE,MAAM,CAAC;IAQzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAO7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAQ7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAQ3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAQ/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}