@hed-hog/core 0.0.356 → 0.0.359

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 (250) hide show
  1. package/dist/auth/guards/auth.guard.d.ts +6 -1
  2. package/dist/auth/guards/auth.guard.d.ts.map +1 -1
  3. package/dist/auth/guards/auth.guard.js +33 -2
  4. package/dist/auth/guards/auth.guard.js.map +1 -1
  5. package/dist/file/file.controller.d.ts +4 -2
  6. package/dist/file/file.controller.d.ts.map +1 -1
  7. package/dist/file/file.controller.js +44 -38
  8. package/dist/file/file.controller.js.map +1 -1
  9. package/dist/file/file.service.d.ts +2 -2
  10. package/dist/file/file.service.d.ts.map +1 -1
  11. package/dist/file/file.service.js +25 -42
  12. package/dist/file/file.service.js.map +1 -1
  13. package/dist/file/provider/azure.provider.d.ts.map +1 -1
  14. package/dist/file/provider/azure.provider.js +10 -15
  15. package/dist/file/provider/azure.provider.js.map +1 -1
  16. package/dist/file/provider/gcs.provider.d.ts.map +1 -1
  17. package/dist/file/provider/gcs.provider.js +8 -9
  18. package/dist/file/provider/gcs.provider.js.map +1 -1
  19. package/dist/file/provider/local.provider.d.ts.map +1 -1
  20. package/dist/file/provider/local.provider.js +11 -10
  21. package/dist/file/provider/local.provider.js.map +1 -1
  22. package/dist/file/provider/provider.factory.d.ts +1 -1
  23. package/dist/file/provider/provider.factory.d.ts.map +1 -1
  24. package/dist/file/provider/provider.factory.js +16 -6
  25. package/dist/file/provider/provider.factory.js.map +1 -1
  26. package/dist/file/provider/s3.provider.d.ts.map +1 -1
  27. package/dist/file/provider/s3.provider.js +4 -20
  28. package/dist/file/provider/s3.provider.js.map +1 -1
  29. package/dist/file/provider/spaces.provider.d.ts.map +1 -1
  30. package/dist/file/provider/spaces.provider.js +4 -19
  31. package/dist/file/provider/spaces.provider.js.map +1 -1
  32. package/dist/integration-profile/integration-profile.controller.d.ts +1 -1
  33. package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
  34. package/dist/integration-profile/integration-profile.controller.js +4 -3
  35. package/dist/integration-profile/integration-profile.controller.js.map +1 -1
  36. package/dist/integration-profile/integration-profile.service.d.ts +1 -1
  37. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  38. package/dist/integration-profile/integration-profile.service.js +7 -4
  39. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  40. package/dist/integration-profile/integration-profile.utils.d.ts +6 -0
  41. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
  42. package/dist/integration-profile/integration-profile.utils.js +9 -0
  43. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  44. package/dist/mail/mail.module.d.ts.map +1 -1
  45. package/dist/mail/mail.module.js +9 -4
  46. package/dist/mail/mail.module.js.map +1 -1
  47. package/dist/mail/mail.service.d.ts +2 -1
  48. package/dist/mail/mail.service.d.ts.map +1 -1
  49. package/dist/mail/mail.service.js +11 -7
  50. package/dist/mail/mail.service.js.map +1 -1
  51. package/dist/mcp/guards/mcp-auth.guard.js +1 -1
  52. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
  53. package/dist/mcp/mcp-api-key.controller.d.ts +2 -0
  54. package/dist/mcp/mcp-api-key.controller.d.ts.map +1 -1
  55. package/dist/mcp/mcp-api-key.controller.js +1 -1
  56. package/dist/mcp/mcp-api-key.controller.js.map +1 -1
  57. package/dist/mcp/mcp-api-key.service.d.ts +2 -1
  58. package/dist/mcp/mcp-api-key.service.d.ts.map +1 -1
  59. package/dist/mcp/mcp-api-key.service.js +6 -2
  60. package/dist/mcp/mcp-api-key.service.js.map +1 -1
  61. package/dist/mcp/mcp.module.d.ts.map +1 -1
  62. package/dist/mcp/mcp.module.js +1 -3
  63. package/dist/mcp/mcp.module.js.map +1 -1
  64. package/dist/oauth/interfaces/OAuthProvider.d.ts +1 -1
  65. package/dist/oauth/interfaces/OAuthProvider.d.ts.map +1 -1
  66. package/dist/oauth/oauth.controller.d.ts +4 -1
  67. package/dist/oauth/oauth.controller.d.ts.map +1 -1
  68. package/dist/oauth/oauth.controller.js +31 -5
  69. package/dist/oauth/oauth.controller.js.map +1 -1
  70. package/dist/oauth/oauth.service.d.ts +12 -1
  71. package/dist/oauth/oauth.service.d.ts.map +1 -1
  72. package/dist/oauth/oauth.service.js +125 -23
  73. package/dist/oauth/oauth.service.js.map +1 -1
  74. package/dist/oauth/providers/abstract.provider.d.ts +1 -1
  75. package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
  76. package/dist/oauth/providers/facebook.provider.d.ts +5 -2
  77. package/dist/oauth/providers/facebook.provider.d.ts.map +1 -1
  78. package/dist/oauth/providers/facebook.provider.js +34 -19
  79. package/dist/oauth/providers/facebook.provider.js.map +1 -1
  80. package/dist/oauth/providers/github.provider.d.ts +6 -2
  81. package/dist/oauth/providers/github.provider.d.ts.map +1 -1
  82. package/dist/oauth/providers/github.provider.js +43 -20
  83. package/dist/oauth/providers/github.provider.js.map +1 -1
  84. package/dist/oauth/providers/google.provider.d.ts +5 -2
  85. package/dist/oauth/providers/google.provider.d.ts.map +1 -1
  86. package/dist/oauth/providers/google.provider.js +34 -19
  87. package/dist/oauth/providers/google.provider.js.map +1 -1
  88. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts +5 -2
  89. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
  90. package/dist/oauth/providers/microsoft-entra-id.provider.js +43 -40
  91. package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
  92. package/dist/oauth/providers/microsoft.provider.d.ts +5 -2
  93. package/dist/oauth/providers/microsoft.provider.d.ts.map +1 -1
  94. package/dist/oauth/providers/microsoft.provider.js +34 -19
  95. package/dist/oauth/providers/microsoft.provider.js.map +1 -1
  96. package/dist/profile/profile.controller.js +1 -1
  97. package/dist/profile/profile.controller.js.map +1 -1
  98. package/dist/security/security.service.d.ts +2 -0
  99. package/dist/security/security.service.d.ts.map +1 -1
  100. package/dist/security/security.service.js +21 -0
  101. package/dist/security/security.service.js.map +1 -1
  102. package/dist/setting/setting.service.d.ts +26 -1
  103. package/dist/setting/setting.service.d.ts.map +1 -1
  104. package/dist/setting/setting.service.js +240 -5
  105. package/dist/setting/setting.service.js.map +1 -1
  106. package/dist/user/user.controller.d.ts +2 -1
  107. package/dist/user/user.controller.d.ts.map +1 -1
  108. package/dist/user/user.controller.js +5 -4
  109. package/dist/user/user.controller.js.map +1 -1
  110. package/dist/user/user.service.d.ts +4 -2
  111. package/dist/user/user.service.d.ts.map +1 -1
  112. package/dist/user/user.service.js +19 -4
  113. package/dist/user/user.service.js.map +1 -1
  114. package/dist/webhook-integration/dto/webhook-action.dto.d.ts +17 -2
  115. package/dist/webhook-integration/dto/webhook-action.dto.d.ts.map +1 -1
  116. package/dist/webhook-integration/dto/webhook-action.dto.js +93 -2
  117. package/dist/webhook-integration/dto/webhook-action.dto.js.map +1 -1
  118. package/dist/webhook-integration/webhook-command.registry.d.ts +15 -0
  119. package/dist/webhook-integration/webhook-command.registry.d.ts.map +1 -0
  120. package/dist/webhook-integration/webhook-command.registry.js +36 -0
  121. package/dist/webhook-integration/webhook-command.registry.js.map +1 -0
  122. package/dist/webhook-integration/webhook-integration.controller.d.ts +19 -0
  123. package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
  124. package/dist/webhook-integration/webhook-integration.controller.js +38 -0
  125. package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
  126. package/dist/webhook-integration/webhook-integration.module.d.ts.map +1 -1
  127. package/dist/webhook-integration/webhook-integration.module.js +5 -0
  128. package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
  129. package/dist/webhook-integration/webhook-integration.service.d.ts +25 -1
  130. package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
  131. package/dist/webhook-integration/webhook-integration.service.js +332 -23
  132. package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
  133. package/hedhog/data/integration_provider.yaml +16 -0
  134. package/hedhog/data/menu.yaml +0 -16
  135. package/hedhog/data/route.yaml +32 -383
  136. package/hedhog/data/setting_group.yaml +179 -174
  137. package/hedhog/data/setting_subgroup.yaml +16 -0
  138. package/hedhog/frontend/app/account/components/tokens.tsx.ejs +421 -0
  139. package/hedhog/frontend/app/account/layout.tsx.ejs +6 -3
  140. package/hedhog/frontend/app/account/mcp-tokens/page.tsx.ejs +2 -2
  141. package/hedhog/frontend/app/account/tokens/page.tsx.ejs +5 -0
  142. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +414 -76
  143. package/hedhog/frontend/app/configurations/layout.tsx.ejs +1 -1
  144. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +3 -1
  145. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +186 -18
  146. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +597 -21
  147. package/hedhog/frontend/app/mail/profiles/page.tsx.ejs +2 -2
  148. package/hedhog/frontend/app/setting-list/page.tsx.ejs +229 -395
  149. package/hedhog/frontend/messages/en.json +67 -3
  150. package/hedhog/frontend/messages/pt.json +67 -3
  151. package/hedhog/table/file.yaml +1 -1
  152. package/hedhog/table/mcp_api_key.yaml +4 -0
  153. package/hedhog/table/webhook_action.yaml +57 -1
  154. package/package.json +5 -4
  155. package/src/auth/guards/auth.guard.ts +32 -0
  156. package/src/file/file.controller.ts +51 -42
  157. package/src/file/file.service.ts +31 -52
  158. package/src/file/provider/azure.provider.ts +14 -28
  159. package/src/file/provider/gcs.provider.ts +9 -9
  160. package/src/file/provider/local.provider.ts +10 -13
  161. package/src/file/provider/provider.factory.ts +19 -7
  162. package/src/file/provider/s3.provider.ts +4 -20
  163. package/src/file/provider/spaces.provider.ts +4 -19
  164. package/src/integration-profile/integration-profile.controller.ts +2 -0
  165. package/src/integration-profile/integration-profile.service.ts +7 -2
  166. package/src/integration-profile/integration-profile.utils.ts +17 -0
  167. package/src/mail/mail.module.ts +14 -4
  168. package/src/mail/mail.service.ts +12 -7
  169. package/src/mcp/guards/mcp-auth.guard.ts +1 -1
  170. package/src/mcp/mcp-api-key.controller.ts +2 -2
  171. package/src/mcp/mcp-api-key.service.ts +6 -2
  172. package/src/mcp/mcp.module.ts +1 -3
  173. package/src/oauth/interfaces/OAuthProvider.ts +1 -1
  174. package/src/oauth/oauth.controller.ts +30 -2
  175. package/src/oauth/oauth.service.ts +194 -35
  176. package/src/oauth/providers/abstract.provider.ts +1 -1
  177. package/src/oauth/providers/facebook.provider.ts +36 -20
  178. package/src/oauth/providers/github.provider.ts +46 -23
  179. package/src/oauth/providers/google.provider.ts +36 -20
  180. package/src/oauth/providers/microsoft-entra-id.provider.ts +42 -46
  181. package/src/oauth/providers/microsoft.provider.ts +36 -21
  182. package/src/profile/profile.controller.ts +2 -2
  183. package/src/security/security.service.ts +34 -1
  184. package/src/setting/setting.service.ts +307 -7
  185. package/src/user/user.controller.ts +4 -1
  186. package/src/user/user.service.ts +20 -2
  187. package/src/webhook-integration/dto/webhook-action.dto.ts +85 -4
  188. package/src/webhook-integration/webhook-command.registry.ts +42 -0
  189. package/src/webhook-integration/webhook-integration.controller.ts +20 -0
  190. package/src/webhook-integration/webhook-integration.module.ts +50 -45
  191. package/src/webhook-integration/webhook-integration.service.ts +374 -11
  192. package/dist/mail-profile/dto/create.dto.d.ts +0 -23
  193. package/dist/mail-profile/dto/create.dto.d.ts.map +0 -1
  194. package/dist/mail-profile/dto/create.dto.js +0 -139
  195. package/dist/mail-profile/dto/create.dto.js.map +0 -1
  196. package/dist/mail-profile/dto/update.dto.d.ts +0 -6
  197. package/dist/mail-profile/dto/update.dto.d.ts.map +0 -1
  198. package/dist/mail-profile/dto/update.dto.js +0 -9
  199. package/dist/mail-profile/dto/update.dto.js.map +0 -1
  200. package/dist/mail-profile/mail-profile.controller.d.ts +0 -94
  201. package/dist/mail-profile/mail-profile.controller.d.ts.map +0 -1
  202. package/dist/mail-profile/mail-profile.controller.js +0 -95
  203. package/dist/mail-profile/mail-profile.controller.js.map +0 -1
  204. package/dist/mail-profile/mail-profile.module.d.ts +0 -3
  205. package/dist/mail-profile/mail-profile.module.d.ts.map +0 -1
  206. package/dist/mail-profile/mail-profile.module.js +0 -31
  207. package/dist/mail-profile/mail-profile.module.js.map +0 -1
  208. package/dist/mail-profile/mail-profile.service.d.ts +0 -109
  209. package/dist/mail-profile/mail-profile.service.d.ts.map +0 -1
  210. package/dist/mail-profile/mail-profile.service.js +0 -278
  211. package/dist/mail-profile/mail-profile.service.js.map +0 -1
  212. package/dist/mcp/tools/core-mail-profile.mcp-tools.d.ts +0 -20
  213. package/dist/mcp/tools/core-mail-profile.mcp-tools.d.ts.map +0 -1
  214. package/dist/mcp/tools/core-mail-profile.mcp-tools.js +0 -96
  215. package/dist/mcp/tools/core-mail-profile.mcp-tools.js.map +0 -1
  216. package/dist/whatsapp-profile/dto/create.dto.d.ts +0 -11
  217. package/dist/whatsapp-profile/dto/create.dto.d.ts.map +0 -1
  218. package/dist/whatsapp-profile/dto/create.dto.js +0 -55
  219. package/dist/whatsapp-profile/dto/create.dto.js.map +0 -1
  220. package/dist/whatsapp-profile/dto/update.dto.d.ts +0 -6
  221. package/dist/whatsapp-profile/dto/update.dto.d.ts.map +0 -1
  222. package/dist/whatsapp-profile/dto/update.dto.js +0 -9
  223. package/dist/whatsapp-profile/dto/update.dto.js.map +0 -1
  224. package/dist/whatsapp-profile/whatsapp-profile.controller.d.ts +0 -54
  225. package/dist/whatsapp-profile/whatsapp-profile.controller.d.ts.map +0 -1
  226. package/dist/whatsapp-profile/whatsapp-profile.controller.js +0 -85
  227. package/dist/whatsapp-profile/whatsapp-profile.controller.js.map +0 -1
  228. package/dist/whatsapp-profile/whatsapp-profile.module.d.ts +0 -3
  229. package/dist/whatsapp-profile/whatsapp-profile.module.d.ts.map +0 -1
  230. package/dist/whatsapp-profile/whatsapp-profile.module.js +0 -26
  231. package/dist/whatsapp-profile/whatsapp-profile.module.js.map +0 -1
  232. package/dist/whatsapp-profile/whatsapp-profile.service.d.ts +0 -63
  233. package/dist/whatsapp-profile/whatsapp-profile.service.d.ts.map +0 -1
  234. package/dist/whatsapp-profile/whatsapp-profile.service.js +0 -138
  235. package/dist/whatsapp-profile/whatsapp-profile.service.js.map +0 -1
  236. package/hedhog/data/mail_profile.yaml +0 -18
  237. package/hedhog/data/whatsapp_profile.yaml +0 -6
  238. package/hedhog/table/mail_profile.yaml +0 -75
  239. package/hedhog/table/whatsapp_profile.yaml +0 -26
  240. package/src/mail-profile/dto/create.dto.ts +0 -145
  241. package/src/mail-profile/dto/update.dto.ts +0 -4
  242. package/src/mail-profile/mail-profile.controller.ts +0 -56
  243. package/src/mail-profile/mail-profile.module.ts +0 -18
  244. package/src/mail-profile/mail-profile.service.ts +0 -308
  245. package/src/mcp/tools/core-mail-profile.mcp-tools.ts +0 -69
  246. package/src/whatsapp-profile/dto/create.dto.ts +0 -36
  247. package/src/whatsapp-profile/dto/update.dto.ts +0 -4
  248. package/src/whatsapp-profile/whatsapp-profile.controller.ts +0 -51
  249. package/src/whatsapp-profile/whatsapp-profile.module.ts +0 -13
  250. package/src/whatsapp-profile/whatsapp-profile.service.ts +0 -160
@@ -61,7 +61,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
61
61
  import { usePagination } from '@/hooks/use-pagination';
62
62
  import { formatDate } from '@/lib/format-date';
63
63
  import { useApp } from '@hed-hog/next-app-provider';
64
- import { Eye, EyeOff, Pencil, PlugZap, Trash2 } from 'lucide-react';
64
+ import { Check, Copy, Eye, EyeOff, Pencil, PlugZap, Plus, Trash2, X } from 'lucide-react';
65
65
  import { useTranslations } from 'next-intl';
66
66
  import { useEffect, useRef, useState } from 'react';
67
67
  import { toast } from 'sonner';
@@ -104,7 +104,7 @@ type ProfileForm = {
104
104
  slug: string;
105
105
  type_id: string;
106
106
  provider_id: string;
107
- config: Record<string, string | boolean | number>;
107
+ config: Record<string, string | boolean | number | string[]>;
108
108
  is_active: boolean;
109
109
  };
110
110
 
@@ -452,13 +452,6 @@ const PROVIDER_FIELDS: Record<string, FieldDef[]> = {
452
452
  type: 'password',
453
453
  required: true,
454
454
  },
455
- {
456
- key: 'redirect_uri',
457
- labelKey: 'fieldRedirectUri',
458
- type: 'url',
459
- required: true,
460
- colSpan: true,
461
- },
462
455
  ],
463
456
  'github-oauth': [
464
457
  {
@@ -494,12 +487,39 @@ const PROVIDER_FIELDS: Record<string, FieldDef[]> = {
494
487
  required: true,
495
488
  placeholder: 'common',
496
489
  },
490
+ ],
491
+ 'facebook-oauth': [
497
492
  {
498
- key: 'redirect_uri',
499
- labelKey: 'fieldRedirectUri',
500
- type: 'url',
493
+ key: 'client_id',
494
+ labelKey: 'fieldClientId',
495
+ type: 'text',
496
+ required: true,
497
+ },
498
+ {
499
+ key: 'client_secret',
500
+ labelKey: 'fieldClientSecret',
501
+ type: 'password',
502
+ required: true,
503
+ },
504
+ ],
505
+ 'microsoft-entra-id-oauth': [
506
+ {
507
+ key: 'client_id',
508
+ labelKey: 'fieldClientId',
509
+ type: 'text',
510
+ required: true,
511
+ },
512
+ {
513
+ key: 'client_secret',
514
+ labelKey: 'fieldClientSecret',
515
+ type: 'password',
516
+ required: true,
517
+ },
518
+ {
519
+ key: 'tenant_id',
520
+ labelKey: 'fieldTenantId',
521
+ type: 'text',
501
522
  required: true,
502
- colSpan: true,
503
523
  },
504
524
  ],
505
525
  };
@@ -797,6 +817,7 @@ export default function IntegrationProfilesPage() {
797
817
  const [visibleFields, setVisibleFields] = useState<Record<string, boolean>>(
798
818
  {}
799
819
  );
820
+ const [copiedUrlIndex, setCopiedUrlIndex] = useState<number | null>(null);
800
821
  const [selectedProfileIds, setSelectedProfileIds] = useState<Set<number>>(
801
822
  new Set()
802
823
  );
@@ -826,6 +847,28 @@ export default function IntegrationProfilesPage() {
826
847
  ? (PROVIDER_FIELDS[selectedProvider.slug] ?? [])
827
848
  : [];
828
849
 
850
+ const isOAuthProvider = (selectedProvider?.slug ?? '').endsWith('-oauth');
851
+ const oauthProviderName = isOAuthProvider
852
+ ? selectedProvider!.slug.replace(/-oauth$/, '')
853
+ : '';
854
+ const appUrl =
855
+ typeof window !== 'undefined'
856
+ ? window.location.origin
857
+ : String(getSettingValue?.('url') ?? '').replace(/\/+$/, '');
858
+ const defaultCallbackUrls =
859
+ isOAuthProvider && appUrl
860
+ ? [
861
+ `${appUrl}/callback/${oauthProviderName}/login`,
862
+ `${appUrl}/callback/${oauthProviderName}/register`,
863
+ `${appUrl}/callback/${oauthProviderName}/connect`,
864
+ ]
865
+ : [];
866
+ const callbackUrls: string[] = (() => {
867
+ const saved = formData.config.callback_urls;
868
+ if (Array.isArray(saved)) return saved as string[];
869
+ return defaultCallbackUrls;
870
+ })();
871
+
829
872
  useEffect(() => {
830
873
  request<IntegrationType[]>({
831
874
  url: '/integration-profile/types',
@@ -868,13 +911,32 @@ export default function IntegrationProfilesPage() {
868
911
  url: `/integration-profile/${profile.id}`,
869
912
  method: 'GET',
870
913
  });
914
+ const loadedConfig =
915
+ (data.config as Record<
916
+ string,
917
+ string | boolean | number | string[]
918
+ >) ?? {};
919
+ const providerSlug =
920
+ providers.find((p) => p.id === data.provider_id)?.slug ?? '';
921
+ if (
922
+ providerSlug.endsWith('-oauth') &&
923
+ !Array.isArray(loadedConfig.callback_urls)
924
+ ) {
925
+ const pName = providerSlug.replace(/-oauth$/, '');
926
+ if (appUrl) {
927
+ loadedConfig.callback_urls = [
928
+ `${appUrl}/callback/${pName}/login`,
929
+ `${appUrl}/callback/${pName}/register`,
930
+ `${appUrl}/callback/${pName}/connect`,
931
+ ];
932
+ }
933
+ }
871
934
  setFormData({
872
935
  name: data.name,
873
936
  slug: data.slug,
874
937
  type_id: String(data.type_id),
875
938
  provider_id: String(data.provider_id),
876
- config:
877
- (data.config as Record<string, string | boolean | number>) ?? {},
939
+ config: loadedConfig,
878
940
  is_active: data.is_active,
879
941
  });
880
942
  } catch {
@@ -1082,14 +1144,49 @@ export default function IntegrationProfilesPage() {
1082
1144
  };
1083
1145
 
1084
1146
  const handleProviderChange = (provider_id: string) => {
1085
- setFormData((p) => ({ ...p, provider_id, config: {} }));
1147
+ const provider = formTypeProviders.find((p) => String(p.id) === provider_id);
1148
+ const initialConfig: Record<string, string | boolean | number | string[]> = {};
1149
+ if (provider?.slug?.endsWith('-oauth')) {
1150
+ const pName = provider.slug.replace(/-oauth$/, '');
1151
+ initialConfig.callback_urls = appUrl
1152
+ ? [
1153
+ `${appUrl}/callback/${pName}/login`,
1154
+ `${appUrl}/callback/${pName}/register`,
1155
+ `${appUrl}/callback/${pName}/connect`,
1156
+ ]
1157
+ : [];
1158
+ }
1159
+ setFormData((p) => ({ ...p, provider_id, config: initialConfig }));
1086
1160
  setVisibleFields({});
1087
1161
  };
1088
1162
 
1089
- const updateConfig = (key: string, value: string | boolean | number) => {
1163
+ const updateConfig = (key: string, value: string | boolean | number | string[]) => {
1090
1164
  setFormData((p) => ({ ...p, config: { ...p.config, [key]: value } }));
1091
1165
  };
1092
1166
 
1167
+ const updateCallbackUrl = (index: number, value: string) => {
1168
+ const urls = [...callbackUrls];
1169
+ urls[index] = value;
1170
+ setFormData((p) => ({ ...p, config: { ...p.config, callback_urls: urls } }));
1171
+ };
1172
+
1173
+ const addCallbackUrl = () => {
1174
+ setFormData((p) => ({
1175
+ ...p,
1176
+ config: { ...p.config, callback_urls: [...callbackUrls, ''] },
1177
+ }));
1178
+ };
1179
+
1180
+ const removeCallbackUrl = (index: number) => {
1181
+ setFormData((p) => ({
1182
+ ...p,
1183
+ config: {
1184
+ ...p.config,
1185
+ callback_urls: callbackUrls.filter((_, i) => i !== index),
1186
+ },
1187
+ }));
1188
+ };
1189
+
1093
1190
  const handleSubmit = async (event: React.FormEvent) => {
1094
1191
  event.preventDefault();
1095
1192
  if (!formData.type_id || !formData.provider_id) return;
@@ -1100,7 +1197,9 @@ export default function IntegrationProfilesPage() {
1100
1197
  name: formData.name,
1101
1198
  type_id: Number(formData.type_id),
1102
1199
  provider_id: Number(formData.provider_id),
1103
- config: formData.config,
1200
+ config: isOAuthProvider
1201
+ ? { ...formData.config, callback_urls: callbackUrls }
1202
+ : formData.config,
1104
1203
  is_active: formData.is_active,
1105
1204
  };
1106
1205
 
@@ -1608,6 +1707,75 @@ export default function IntegrationProfilesPage() {
1608
1707
  </div>
1609
1708
  )}
1610
1709
 
1710
+ {/* ── Callback URLs (OAuth only) ── */}
1711
+ {isOAuthProvider && (
1712
+ <div className="rounded-lg border">
1713
+ <div className="flex items-center justify-between border-b px-4 py-3">
1714
+ <div>
1715
+ <p className="text-sm font-semibold">
1716
+ {t('callbackUrlsSectionTitle')}
1717
+ </p>
1718
+ <p className="mt-0.5 text-xs text-muted-foreground">
1719
+ {t('callbackUrlsDescription')}
1720
+ </p>
1721
+ </div>
1722
+ <Button
1723
+ type="button"
1724
+ variant="outline"
1725
+ size="sm"
1726
+ onClick={addCallbackUrl}
1727
+ >
1728
+ <Plus className="mr-1.5 h-3.5 w-3.5" />
1729
+ {t('addCallbackUrl')}
1730
+ </Button>
1731
+ </div>
1732
+ <div className="space-y-2 p-4">
1733
+ {callbackUrls.length === 0 && (
1734
+ <p className="py-1 text-center text-sm text-muted-foreground">
1735
+ {t('noCallbackUrls')}
1736
+ </p>
1737
+ )}
1738
+ {callbackUrls.map((url, index) => (
1739
+ <div key={index} className="flex gap-2">
1740
+ <Input
1741
+ value={url}
1742
+ onChange={(e) => updateCallbackUrl(index, e.target.value)}
1743
+ placeholder={t('callbackUrlPlaceholder')}
1744
+ className="font-mono text-sm"
1745
+ />
1746
+ <Button
1747
+ type="button"
1748
+ variant="ghost"
1749
+ size="icon"
1750
+ className="shrink-0"
1751
+ disabled={!url}
1752
+ onClick={() => {
1753
+ navigator.clipboard.writeText(url);
1754
+ setCopiedUrlIndex(index);
1755
+ setTimeout(() => setCopiedUrlIndex(null), 1500);
1756
+ }}
1757
+ >
1758
+ {copiedUrlIndex === index ? (
1759
+ <Check className="h-4 w-4 text-green-500" />
1760
+ ) : (
1761
+ <Copy className="h-4 w-4" />
1762
+ )}
1763
+ </Button>
1764
+ <Button
1765
+ type="button"
1766
+ variant="ghost"
1767
+ size="icon"
1768
+ onClick={() => removeCallbackUrl(index)}
1769
+ className="shrink-0"
1770
+ >
1771
+ <X className="h-4 w-4" />
1772
+ </Button>
1773
+ </div>
1774
+ ))}
1775
+ </div>
1776
+ </div>
1777
+ )}
1778
+
1611
1779
  {/* ── Active ── */}
1612
1780
  <div className="flex items-center justify-between rounded-md border px-4 py-3">
1613
1781
  <p className="text-sm font-medium">{t('isActiveLabel')}</p>