@hed-hog/core 0.0.385 → 0.0.387
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-command/app-command.registry.d.ts +2 -0
- package/dist/app-command/app-command.registry.d.ts.map +1 -1
- package/dist/app-command/app-command.registry.js.map +1 -1
- package/dist/auth/auth.controller.d.ts +24 -1
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +27 -0
- package/dist/auth/auth.controller.js.map +1 -1
- package/dist/auth/auth.service.d.ts +52 -1
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +108 -0
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/dto/complete-account.dto.d.ts +9 -0
- package/dist/auth/dto/complete-account.dto.d.ts.map +1 -0
- package/dist/auth/dto/complete-account.dto.js +43 -0
- package/dist/auth/dto/complete-account.dto.js.map +1 -0
- package/dist/authorize/authorize.controller.d.ts +45 -0
- package/dist/authorize/authorize.controller.d.ts.map +1 -0
- package/dist/authorize/authorize.controller.js +120 -0
- package/dist/authorize/authorize.controller.js.map +1 -0
- package/dist/authorize/authorize.module.d.ts +8 -0
- package/dist/authorize/authorize.module.d.ts.map +1 -0
- package/dist/authorize/authorize.module.js +36 -0
- package/dist/authorize/authorize.module.js.map +1 -0
- package/dist/authorize/authorize.service.d.ts +79 -0
- package/dist/authorize/authorize.service.d.ts.map +1 -0
- package/dist/authorize/authorize.service.js +196 -0
- package/dist/authorize/authorize.service.js.map +1 -0
- package/dist/authorize/dto/authorize-info.dto.d.ts +8 -0
- package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -0
- package/dist/authorize/dto/authorize-info.dto.js +42 -0
- package/dist/authorize/dto/authorize-info.dto.js.map +1 -0
- package/dist/authorize/dto/consent.dto.d.ts +8 -0
- package/dist/authorize/dto/consent.dto.d.ts.map +1 -0
- package/dist/authorize/dto/consent.dto.js +42 -0
- package/dist/authorize/dto/consent.dto.js.map +1 -0
- package/dist/authorize/dto/token.dto.d.ts +8 -0
- package/dist/authorize/dto/token.dto.d.ts.map +1 -0
- package/dist/authorize/dto/token.dto.js +42 -0
- package/dist/authorize/dto/token.dto.js.map +1 -0
- package/dist/challenge/challenge.service.d.ts +7 -0
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +22 -0
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +2 -0
- package/dist/core.module.js.map +1 -1
- package/dist/file/file.service.d.ts +7 -0
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +16 -0
- package/dist/file/file.service.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts +6 -2
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +14 -3
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +7 -0
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +91 -4
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +28 -0
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +40 -1
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/oauth/interfaces/OAuthProvider.d.ts +1 -1
- package/dist/oauth/interfaces/OAuthProvider.d.ts.map +1 -1
- package/dist/oauth/oauth.controller.d.ts +26 -0
- package/dist/oauth/oauth.controller.d.ts.map +1 -1
- package/dist/oauth/oauth.controller.js +94 -0
- package/dist/oauth/oauth.controller.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +39 -1
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +115 -7
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts +5 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +37 -6
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +4 -3
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.controller.js.map +1 -1
- package/dist/profile/profile.service.d.ts +5 -4
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.controller.d.ts +5 -8
- package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.controller.js +31 -8
- package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.module.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.module.js +5 -0
- package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.d.ts +33 -1
- package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.js +116 -5
- package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
- package/dist/webhook-integration/webhook-protocol.registry.d.ts +63 -0
- package/dist/webhook-integration/webhook-protocol.registry.d.ts.map +1 -0
- package/dist/webhook-integration/webhook-protocol.registry.js +51 -0
- package/dist/webhook-integration/webhook-protocol.registry.js.map +1 -0
- package/hedhog/data/integration_provider.yaml +8 -0
- package/hedhog/data/integration_type.yaml +6 -0
- package/hedhog/data/mail.yaml +39 -0
- package/hedhog/data/route.yaml +12 -0
- package/hedhog/data/setting_group.yaml +15 -1
- package/hedhog/frontend/app/account/components/regenerate-codes-dialog.tsx.ejs +11 -7
- package/hedhog/frontend/app/account/components/verify-before-add-dialog.tsx.ejs +9 -7
- package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +6 -2
- package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +130 -34
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +16 -8
- package/hedhog/frontend/messages/en.json +55 -1
- package/hedhog/frontend/messages/pt.json +55 -1
- package/hedhog/table/webhook_integration.yaml +64 -43
- package/package.json +10 -5
- package/src/app-command/app-command.registry.ts +2 -0
- package/src/auth/auth.controller.ts +23 -1
- package/src/auth/auth.service.ts +135 -1
- package/src/auth/dto/complete-account.dto.ts +24 -0
- package/src/authorize/authorize.controller.ts +99 -0
- package/src/authorize/authorize.module.ts +23 -0
- package/src/authorize/authorize.service.spec.ts +307 -0
- package/src/authorize/authorize.service.ts +245 -0
- package/src/authorize/dto/authorize-info.dto.ts +23 -0
- package/src/authorize/dto/consent.dto.ts +23 -0
- package/src/authorize/dto/token.dto.ts +23 -0
- package/src/challenge/challenge.service.ts +28 -0
- package/src/core.module.ts +2 -0
- package/src/file/file.service.ts +19 -0
- package/src/index.ts +1 -0
- package/src/integration-profile/integration-profile.secrets.spec.ts +114 -0
- package/src/integration-profile/integration-profile.secrets.ts +14 -3
- package/src/integration-profile/integration-profile.service.ts +129 -3
- package/src/integration-profile/integration-profile.utils.spec.ts +75 -0
- package/src/integration-profile/integration-profile.utils.ts +79 -0
- package/src/oauth/interfaces/OAuthProvider.ts +5 -1
- package/src/oauth/oauth.controller.ts +89 -0
- package/src/oauth/oauth.service.ts +190 -8
- package/src/oauth/providers/microsoft-entra-id.provider.ts +45 -5
- package/src/profile/profile.controller.ts +6 -2
- package/src/profile/profile.service.ts +5 -3
- package/src/webhook-integration/webhook-integration.controller.ts +40 -2
- package/src/webhook-integration/webhook-integration.module.ts +5 -0
- package/src/webhook-integration/webhook-integration.service.ts +151 -2
- package/src/webhook-integration/webhook-protocol.registry.spec.ts +70 -0
- package/src/webhook-integration/webhook-protocol.registry.ts +93 -0
package/hedhog/data/route.yaml
CHANGED
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
slug: admin
|
|
58
58
|
- where:
|
|
59
59
|
slug: admin-access
|
|
60
|
+
- where:
|
|
61
|
+
slug: user
|
|
60
62
|
- url: /sessions/:sessionId/revoke
|
|
61
63
|
method: DELETE
|
|
62
64
|
type: HTTP
|
|
@@ -66,6 +68,8 @@
|
|
|
66
68
|
slug: admin
|
|
67
69
|
- where:
|
|
68
70
|
slug: admin-access
|
|
71
|
+
- where:
|
|
72
|
+
slug: user
|
|
69
73
|
- url: /sessions/user
|
|
70
74
|
method: GET
|
|
71
75
|
type: HTTP
|
|
@@ -3228,6 +3232,10 @@
|
|
|
3228
3232
|
method: GET
|
|
3229
3233
|
type: HTTP
|
|
3230
3234
|
relations: *core_user_roles
|
|
3235
|
+
- url: /auth/authorize/consent
|
|
3236
|
+
method: POST
|
|
3237
|
+
type: HTTP
|
|
3238
|
+
relations: *core_user_roles
|
|
3231
3239
|
- url: /auth/roles
|
|
3232
3240
|
method: GET
|
|
3233
3241
|
type: HTTP
|
|
@@ -3244,6 +3252,10 @@
|
|
|
3244
3252
|
method: GET
|
|
3245
3253
|
type: HTTP
|
|
3246
3254
|
relations: *core_user_roles
|
|
3255
|
+
- url: /oauth/microsoft-entra-id/redeem/connect
|
|
3256
|
+
method: GET
|
|
3257
|
+
type: HTTP
|
|
3258
|
+
relations: *core_user_roles
|
|
3247
3259
|
- url: /oauth/:provider
|
|
3248
3260
|
method: DELETE
|
|
3249
3261
|
type: HTTP
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
description:
|
|
72
72
|
en: 'Base URLs for specific apps, formatted as "app=https://example.com" (one per tag). Used in transactional email links (e.g. password reset) when the request comes from that app, falling back to System URL otherwise.'
|
|
73
73
|
pt: 'URLs base de apps específicos, no formato "app=https://exemplo.com" (uma por tag). Usadas em links de e-mails transacionais (ex.: redefinição de senha) quando a solicitação vem desse app, usando a URL do Sistema como alternativa.'
|
|
74
|
-
value: '["training=http://localhost:3001"]'
|
|
74
|
+
value: '["training=http://localhost:3001","class=https://localhost:3002","partners=http://localhost:3003"]'
|
|
75
75
|
user_override: false
|
|
76
76
|
subgroup_id:
|
|
77
77
|
where:
|
|
@@ -517,6 +517,20 @@
|
|
|
517
517
|
subgroup_id:
|
|
518
518
|
where:
|
|
519
519
|
slug: mfa-general
|
|
520
|
+
- slug: account-invite-expiration-minutes
|
|
521
|
+
type: number
|
|
522
|
+
component: input-number
|
|
523
|
+
name:
|
|
524
|
+
en: Account Invite Link Expiration
|
|
525
|
+
pt: Expiração do Link de Convite de Conta
|
|
526
|
+
description:
|
|
527
|
+
en: Minutes before an account creation invite link expires and becomes invalid
|
|
528
|
+
pt: Minutos antes de um link de convite de criação de conta expirar e se tornar inválido
|
|
529
|
+
value: 10080
|
|
530
|
+
user_override: false
|
|
531
|
+
subgroup_id:
|
|
532
|
+
where:
|
|
533
|
+
slug: mfa-general
|
|
520
534
|
- slug: access-token-expiration-minutes
|
|
521
535
|
type: number
|
|
522
536
|
component: input-number
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';
|
|
1
2
|
import { Button } from '@/components/ui/button';
|
|
2
3
|
import {
|
|
3
4
|
Dialog,
|
|
@@ -214,14 +215,17 @@ export function RegenerateCodesDialog({
|
|
|
214
215
|
const { startAuthentication } =
|
|
215
216
|
await import('@simplewebauthn/browser');
|
|
216
217
|
|
|
217
|
-
const { data: optionsData } =
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
const { data: optionsData } =
|
|
219
|
+
await request<PublicKeyCredentialRequestOptionsJSON>(
|
|
220
|
+
{
|
|
221
|
+
url: '/profile/webauthn/authenticate/generate',
|
|
222
|
+
method: 'POST',
|
|
223
|
+
}
|
|
224
|
+
);
|
|
221
225
|
|
|
222
|
-
const assertion = await startAuthentication(
|
|
223
|
-
optionsData
|
|
224
|
-
);
|
|
226
|
+
const assertion = await startAuthentication({
|
|
227
|
+
optionsJSON: optionsData,
|
|
228
|
+
});
|
|
225
229
|
await onConfirm(
|
|
226
230
|
'',
|
|
227
231
|
undefined,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';
|
|
3
4
|
import { Button } from '@/components/ui/button';
|
|
4
5
|
import {
|
|
5
6
|
Dialog,
|
|
@@ -187,14 +188,15 @@ export function VerifyBeforeAddDialog({
|
|
|
187
188
|
const { startAuthentication } =
|
|
188
189
|
await import('@simplewebauthn/browser');
|
|
189
190
|
|
|
190
|
-
const { data: optionsData } =
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
const { data: optionsData } =
|
|
192
|
+
await request<PublicKeyCredentialRequestOptionsJSON>({
|
|
193
|
+
url: '/profile/webauthn/authenticate/generate',
|
|
194
|
+
method: 'POST',
|
|
195
|
+
});
|
|
194
196
|
|
|
195
|
-
const assertion = await startAuthentication(
|
|
196
|
-
optionsData
|
|
197
|
-
);
|
|
197
|
+
const assertion = await startAuthentication({
|
|
198
|
+
optionsJSON: optionsData,
|
|
199
|
+
});
|
|
198
200
|
await onVerify('', undefined, 'webauthn', assertion);
|
|
199
201
|
setCode('');
|
|
200
202
|
setLoading(false);
|
|
@@ -212,7 +212,9 @@ export function useMfaSetup() {
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
showToastHandler('success', t('authenticateToRemove'));
|
|
215
|
-
const assertion = await startAuthentication(
|
|
215
|
+
const assertion = await startAuthentication({
|
|
216
|
+
optionsJSON: optionsResponse.data,
|
|
217
|
+
});
|
|
216
218
|
await request({
|
|
217
219
|
url: '/profile/webauthn/authenticate/verify',
|
|
218
220
|
method: 'POST',
|
|
@@ -417,7 +419,9 @@ export function useMfaSetup() {
|
|
|
417
419
|
data: { name },
|
|
418
420
|
});
|
|
419
421
|
|
|
420
|
-
const attestationResponse = await startRegistration(
|
|
422
|
+
const attestationResponse = await startRegistration({
|
|
423
|
+
optionsJSON: options,
|
|
424
|
+
});
|
|
421
425
|
|
|
422
426
|
const { data }: any = await request({
|
|
423
427
|
url: '/profile/webauthn/verify',
|
|
@@ -28,6 +28,13 @@ import {
|
|
|
28
28
|
ContextMenuSeparator,
|
|
29
29
|
ContextMenuTrigger,
|
|
30
30
|
} from '@/components/ui/context-menu';
|
|
31
|
+
import {
|
|
32
|
+
DropdownMenu,
|
|
33
|
+
DropdownMenuContent,
|
|
34
|
+
DropdownMenuItem,
|
|
35
|
+
DropdownMenuSeparator,
|
|
36
|
+
DropdownMenuTrigger,
|
|
37
|
+
} from '@/components/ui/dropdown-menu';
|
|
31
38
|
import { Input } from '@/components/ui/input';
|
|
32
39
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
33
40
|
import {
|
|
@@ -51,6 +58,7 @@ import {
|
|
|
51
58
|
Home,
|
|
52
59
|
LayoutDashboard,
|
|
53
60
|
Loader2,
|
|
61
|
+
MoreHorizontal,
|
|
54
62
|
Palette,
|
|
55
63
|
Pencil,
|
|
56
64
|
Plus,
|
|
@@ -1032,42 +1040,130 @@ export function DashboardHomeTabs() {
|
|
|
1032
1040
|
{tabContent}
|
|
1033
1041
|
</div>
|
|
1034
1042
|
) : (
|
|
1035
|
-
<
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1043
|
+
<div className="group relative mt-1 shrink-0">
|
|
1044
|
+
<TabsTrigger
|
|
1045
|
+
value={dashboard.slug}
|
|
1046
|
+
draggable={!isBusy}
|
|
1047
|
+
onDragStart={(event) =>
|
|
1048
|
+
handleTabDragStart(event, dashboard.slug)
|
|
1049
|
+
}
|
|
1050
|
+
onDragOver={handleTabDragOver}
|
|
1051
|
+
onDrop={(event) =>
|
|
1052
|
+
void handleTabDrop(event, dashboard.slug)
|
|
1053
|
+
}
|
|
1054
|
+
onDragEnd={handleTabDragEnd}
|
|
1055
|
+
className={cn(
|
|
1056
|
+
'dashboard-tab-trigger -mb-px inline-flex h-9 shrink-0 cursor-pointer items-center justify-center gap-2 overflow-hidden rounded-b-none rounded-t-lg border-none pr-9 pl-3 py-2 shadow-none data-[state=active]:shadow-none',
|
|
1057
|
+
draggingDashboardSlug === dashboard.slug &&
|
|
1058
|
+
'opacity-70'
|
|
1059
|
+
)}
|
|
1060
|
+
style={
|
|
1061
|
+
isActiveTab
|
|
1062
|
+
? {
|
|
1063
|
+
backgroundColor: 'var(--background)',
|
|
1064
|
+
color: 'var(--primary)',
|
|
1065
|
+
}
|
|
1066
|
+
: {
|
|
1067
|
+
backgroundColor: 'transparent',
|
|
1068
|
+
color: 'var(--muted-foreground)',
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
onDoubleClick={() =>
|
|
1072
|
+
startRenameDashboard(dashboard)
|
|
1073
|
+
}
|
|
1074
|
+
onContextMenu={() =>
|
|
1075
|
+
setActiveSlug(dashboard.slug)
|
|
1076
|
+
}
|
|
1077
|
+
>
|
|
1078
|
+
{tabContent}
|
|
1079
|
+
</TabsTrigger>
|
|
1080
|
+
<DropdownMenu>
|
|
1081
|
+
<DropdownMenuTrigger asChild>
|
|
1082
|
+
<Button
|
|
1083
|
+
type="button"
|
|
1084
|
+
variant="ghost"
|
|
1085
|
+
size="icon"
|
|
1086
|
+
className={cn(
|
|
1087
|
+
'absolute top-1/2 right-1 z-10 size-7 -translate-y-1/2 rounded-md text-muted-foreground hover:text-foreground',
|
|
1088
|
+
isActiveTab
|
|
1089
|
+
? 'bg-background/80'
|
|
1090
|
+
: 'bg-transparent hover:bg-background/60'
|
|
1091
|
+
)}
|
|
1092
|
+
onClick={(event) => {
|
|
1093
|
+
event.stopPropagation();
|
|
1094
|
+
setActiveSlug(dashboard.slug);
|
|
1095
|
+
}}
|
|
1096
|
+
onPointerDown={(event) =>
|
|
1097
|
+
event.stopPropagation()
|
|
1056
1098
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1099
|
+
aria-label={t('tabActions')}
|
|
1100
|
+
title={t('tabActions')}
|
|
1101
|
+
>
|
|
1102
|
+
<MoreHorizontal className="size-4" />
|
|
1103
|
+
</Button>
|
|
1104
|
+
</DropdownMenuTrigger>
|
|
1105
|
+
<DropdownMenuContent
|
|
1106
|
+
align="end"
|
|
1107
|
+
className="w-56"
|
|
1108
|
+
onCloseAutoFocus={(event) =>
|
|
1109
|
+
event.preventDefault()
|
|
1110
|
+
}
|
|
1111
|
+
>
|
|
1112
|
+
<DropdownMenuItem
|
|
1113
|
+
onSelect={() =>
|
|
1114
|
+
openAddWidgetsForDashboard(dashboard)
|
|
1060
1115
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1116
|
+
>
|
|
1117
|
+
<Plus className="size-4" />
|
|
1118
|
+
{t('addWidgets')}
|
|
1119
|
+
</DropdownMenuItem>
|
|
1120
|
+
{!dashboard.is_home ? (
|
|
1121
|
+
<DropdownMenuItem
|
|
1122
|
+
onSelect={() =>
|
|
1123
|
+
void handleSetHomeDashboard(dashboard)
|
|
1124
|
+
}
|
|
1125
|
+
>
|
|
1126
|
+
<Home className="size-4" />
|
|
1127
|
+
{t('setAsHome')}
|
|
1128
|
+
</DropdownMenuItem>
|
|
1129
|
+
) : null}
|
|
1130
|
+
<DropdownMenuItem
|
|
1131
|
+
onSelect={() =>
|
|
1132
|
+
startRenameDashboard(dashboard)
|
|
1133
|
+
}
|
|
1134
|
+
>
|
|
1135
|
+
<Pencil className="size-4" />
|
|
1136
|
+
{t('rename')}
|
|
1137
|
+
</DropdownMenuItem>
|
|
1138
|
+
<DropdownMenuItem
|
|
1139
|
+
onSelect={() =>
|
|
1140
|
+
openIconForDashboard(dashboard)
|
|
1141
|
+
}
|
|
1142
|
+
>
|
|
1143
|
+
<Palette className="size-4" />
|
|
1144
|
+
{t('changeIcon')}
|
|
1145
|
+
</DropdownMenuItem>
|
|
1146
|
+
<DropdownMenuItem
|
|
1147
|
+
onSelect={() =>
|
|
1148
|
+
openShareForDashboard(dashboard)
|
|
1149
|
+
}
|
|
1150
|
+
>
|
|
1151
|
+
<Share2 className="size-4" />
|
|
1152
|
+
{t('share')}
|
|
1153
|
+
</DropdownMenuItem>
|
|
1154
|
+
<DropdownMenuSeparator />
|
|
1155
|
+
<DropdownMenuItem
|
|
1156
|
+
variant="destructive"
|
|
1157
|
+
onSelect={() =>
|
|
1158
|
+
openDeleteForDashboard(dashboard)
|
|
1159
|
+
}
|
|
1160
|
+
>
|
|
1161
|
+
<Trash2 className="size-4" />
|
|
1162
|
+
{t('delete')}
|
|
1163
|
+
</DropdownMenuItem>
|
|
1164
|
+
</DropdownMenuContent>
|
|
1165
|
+
</DropdownMenu>
|
|
1166
|
+
</div>
|
|
1071
1167
|
)}
|
|
1072
1168
|
</ContextMenuTrigger>
|
|
1073
1169
|
<ContextMenuContent className="w-56">
|
|
@@ -48,7 +48,8 @@ import {
|
|
|
48
48
|
TableRow,
|
|
49
49
|
} from '@/components/ui/table';
|
|
50
50
|
import { TableBodySkeleton } from '@/components/ui/skeletons';
|
|
51
|
-
import { Tabs, TabsContent
|
|
51
|
+
import { Tabs, TabsContent } from '@/components/ui/tabs';
|
|
52
|
+
import { TabsOverflowList } from '@/components/ui/tabs-overflow-list';
|
|
52
53
|
import { usePagination } from '@/hooks/use-pagination';
|
|
53
54
|
import { formatDate } from '@/lib/format-date';
|
|
54
55
|
import { useApp } from '@hed-hog/next-app-provider';
|
|
@@ -696,13 +697,20 @@ export default function IntegrationProfilesPage() {
|
|
|
696
697
|
/>
|
|
697
698
|
|
|
698
699
|
<Tabs value={activeTab} onValueChange={setActiveTab}>
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
)
|
|
705
|
-
|
|
700
|
+
{/* Colapsa as abas que não cabem num dropdown "Mais": há muitos tipos de
|
|
701
|
+
integração e em telas estreitas os TabsTrigger crus encolhiam e se
|
|
702
|
+
sobrepunham. triggerClassName replica o padding do TabsTrigger nos
|
|
703
|
+
spans de medição invisíveis do TabsOverflowList. */}
|
|
704
|
+
<TabsOverflowList
|
|
705
|
+
items={types.map((ty) => ({
|
|
706
|
+
value: ty.slug,
|
|
707
|
+
label: getLocaleName(ty.integration_type_locale, currentLocaleCode),
|
|
708
|
+
}))}
|
|
709
|
+
activeValue={activeTab}
|
|
710
|
+
onValueChange={setActiveTab}
|
|
711
|
+
moreLabel={t('tabsMore')}
|
|
712
|
+
triggerClassName="min-h-8 px-3 text-sm font-medium"
|
|
713
|
+
/>
|
|
706
714
|
|
|
707
715
|
{types.map((ty) => (
|
|
708
716
|
<TabsContent key={ty.slug} value={ty.slug} className="mt-4">
|
|
@@ -1399,6 +1399,7 @@
|
|
|
1399
1399
|
"shareDashboardError": "Could not share the dashboard.",
|
|
1400
1400
|
"shareRemoved": "Sharing removed.",
|
|
1401
1401
|
"revokeShareError": "Could not remove the sharing.",
|
|
1402
|
+
"tabActions": "Tab actions",
|
|
1402
1403
|
"addWidgets": "Add widgets",
|
|
1403
1404
|
"setAsHome": "Set as home",
|
|
1404
1405
|
"rename": "Rename",
|
|
@@ -2338,6 +2339,7 @@
|
|
|
2338
2339
|
"title": "Integration Profiles",
|
|
2339
2340
|
"description": "Manage credentials and connection settings for email, messaging, storage, AI, OAuth, and payment providers.",
|
|
2340
2341
|
"searchPlaceholder": "Search profiles by name or slug...",
|
|
2342
|
+
"tabsMore": "More",
|
|
2341
2343
|
"selectProfile": "Select profile",
|
|
2342
2344
|
"selectAllVisible": "Select all visible profiles",
|
|
2343
2345
|
"newProfile": "New Profile",
|
|
@@ -2425,11 +2427,33 @@
|
|
|
2425
2427
|
"fieldAccessKeyId": "Access Key ID",
|
|
2426
2428
|
"fieldSecretAccessKey": "Secret Access Key",
|
|
2427
2429
|
"fieldRegion": "Region",
|
|
2430
|
+
"fieldDomain": "Domain",
|
|
2428
2431
|
"fieldToken": "Token",
|
|
2429
2432
|
"fieldInstanceName": "Instance Name",
|
|
2430
2433
|
"fieldPhoneNumberId": "Phone Number ID",
|
|
2431
2434
|
"fieldAccessToken": "Access Token",
|
|
2432
2435
|
"fieldBusinessId": "Business ID",
|
|
2436
|
+
"fieldAppId": "Meta App ID",
|
|
2437
|
+
"fieldAppSecret": "Meta App Secret",
|
|
2438
|
+
"fieldWabaId": "WhatsApp Business Account ID (WABA)",
|
|
2439
|
+
"fieldVerifyToken": "Webhook Verify Token",
|
|
2440
|
+
"fieldGraphApiVersion": "Graph API Version",
|
|
2441
|
+
"fieldEnvironmentTest": "Test",
|
|
2442
|
+
"fieldEnvironmentProduction": "Production",
|
|
2443
|
+
"copiedToClipboard": "Copied to clipboard",
|
|
2444
|
+
"whatsappWebhookSectionTitle": "Meta Webhook",
|
|
2445
|
+
"whatsappWebhookDescription": "Register this webhook in your Meta app to receive WhatsApp messages.",
|
|
2446
|
+
"whatsappWebhookCallbackUrlLabel": "Callback URL",
|
|
2447
|
+
"whatsappWebhookVerifyTokenLabel": "Verify Token",
|
|
2448
|
+
"whatsappWebhookVerifyTokenHint": "Use the same value you set in the Verify Token field above.",
|
|
2449
|
+
"whatsappWebhookLoading": "Generating URL…",
|
|
2450
|
+
"whatsappWebhookUnavailable": "URL unavailable — check the API base URL setting.",
|
|
2451
|
+
"whatsappWebhookSaveFirst": "Save the profile to generate the webhook URL.",
|
|
2452
|
+
"whatsappWebhookStepsTitle": "In the Meta dashboard (WhatsApp → Configuration):",
|
|
2453
|
+
"whatsappWebhookStep1": "Paste the Callback URL and the Verify Token above.",
|
|
2454
|
+
"whatsappWebhookStep2": "Click \"Verify and save\".",
|
|
2455
|
+
"whatsappWebhookStep3": "Subscribe to the \"messages\" field.",
|
|
2456
|
+
"whatsappWebhookStep4": "Send a test message and confirm it arrives.",
|
|
2433
2457
|
"fieldBasePath": "Base Path",
|
|
2434
2458
|
"fieldBucket": "Bucket",
|
|
2435
2459
|
"fieldProjectId": "Project ID",
|
|
@@ -2481,6 +2505,36 @@
|
|
|
2481
2505
|
"nodePoolPlaceholder": "Select a node pool",
|
|
2482
2506
|
"nodePoolNoneFound": "No node pools found for this cluster.",
|
|
2483
2507
|
"nodePoolLoadError": "Failed to load node pools. Check the API token and cluster ID.",
|
|
2484
|
-
"nodePoolNeedCreds": "Fill in the API token and cluster ID first, then load the pools."
|
|
2508
|
+
"nodePoolNeedCreds": "Fill in the API token and cluster ID first, then load the pools.",
|
|
2509
|
+
"fieldEnvironment": "Environment",
|
|
2510
|
+
"optionHomologation": "Homologation (testing)",
|
|
2511
|
+
"optionProduction": "Production (real invoices)",
|
|
2512
|
+
"fieldTaxId": "Issuer tax ID (CNPJ)",
|
|
2513
|
+
"fieldLegalName": "Legal name",
|
|
2514
|
+
"fieldTradeName": "Trade name",
|
|
2515
|
+
"fieldMunicipalRegistration": "Municipal registration",
|
|
2516
|
+
"fieldIbgeCityCode": "IBGE city code",
|
|
2517
|
+
"fieldAddressStreet": "Street",
|
|
2518
|
+
"fieldAddressNumber": "Number",
|
|
2519
|
+
"fieldAddressComplement": "Complement",
|
|
2520
|
+
"fieldAddressDistrict": "District",
|
|
2521
|
+
"fieldAddressZip": "ZIP code",
|
|
2522
|
+
"fieldAddressState": "State",
|
|
2523
|
+
"fieldEmail": "Email",
|
|
2524
|
+
"fieldPhone": "Phone",
|
|
2525
|
+
"fieldTaxRegime": "Tax regime",
|
|
2526
|
+
"optionSimplesNacional": "Simples Nacional",
|
|
2527
|
+
"optionSimplesNacionalExcesso": "Simples Nacional (over the cap)",
|
|
2528
|
+
"optionRegimeNormal": "Regular regime",
|
|
2529
|
+
"optionMei": "MEI",
|
|
2530
|
+
"fieldSpecialTaxRegime": "Special tax regime",
|
|
2531
|
+
"fieldCulturalIncentive": "Cultural incentive",
|
|
2532
|
+
"fieldCertificatePfx": "A1 certificate (.pfx/.p12)",
|
|
2533
|
+
"fieldCertificatePassword": "Certificate password",
|
|
2534
|
+
"fieldBaseUrl": "API base URL",
|
|
2535
|
+
"fieldTimeoutMs": "Timeout (ms)",
|
|
2536
|
+
"fieldMaxRetries": "Max retries",
|
|
2537
|
+
"fileStored": "A file is stored and encrypted. Click to replace it.",
|
|
2538
|
+
"fileSelected": "New file selected. It will be encrypted on save."
|
|
2485
2539
|
}
|
|
2486
2540
|
}
|
|
@@ -1402,6 +1402,7 @@
|
|
|
1402
1402
|
"shareDashboardError": "Não foi possível compartilhar o dashboard.",
|
|
1403
1403
|
"shareRemoved": "Compartilhamento removido.",
|
|
1404
1404
|
"revokeShareError": "Não foi possível remover o compartilhamento.",
|
|
1405
|
+
"tabActions": "Ações da aba",
|
|
1405
1406
|
"addWidgets": "Adicionar widgets",
|
|
1406
1407
|
"setAsHome": "Definir como home",
|
|
1407
1408
|
"rename": "Renomear",
|
|
@@ -2393,6 +2394,7 @@
|
|
|
2393
2394
|
"title": "Perfis de Integração",
|
|
2394
2395
|
"description": "Gerencie credenciais para provedores de e-mail, mensagens, armazenamento, IA, OAuth e pagamentos.",
|
|
2395
2396
|
"searchPlaceholder": "Buscar perfis por nome ou slug...",
|
|
2397
|
+
"tabsMore": "Mais",
|
|
2396
2398
|
"selectProfile": "Selecionar perfil",
|
|
2397
2399
|
"selectAllVisible": "Selecionar todos os perfis visíveis",
|
|
2398
2400
|
"newProfile": "Novo Perfil",
|
|
@@ -2480,11 +2482,33 @@
|
|
|
2480
2482
|
"fieldAccessKeyId": "Access Key ID",
|
|
2481
2483
|
"fieldSecretAccessKey": "Secret Access Key",
|
|
2482
2484
|
"fieldRegion": "Região",
|
|
2485
|
+
"fieldDomain": "Domínio",
|
|
2483
2486
|
"fieldToken": "Token",
|
|
2484
2487
|
"fieldInstanceName": "Nome da Instância",
|
|
2485
2488
|
"fieldPhoneNumberId": "ID do Número de Telefone",
|
|
2486
2489
|
"fieldAccessToken": "Access Token",
|
|
2487
2490
|
"fieldBusinessId": "Business ID",
|
|
2491
|
+
"fieldAppId": "Meta App ID",
|
|
2492
|
+
"fieldAppSecret": "Meta App Secret",
|
|
2493
|
+
"fieldWabaId": "ID da Conta do WhatsApp Business (WABA)",
|
|
2494
|
+
"fieldVerifyToken": "Verify Token do Webhook",
|
|
2495
|
+
"fieldGraphApiVersion": "Versão da Graph API",
|
|
2496
|
+
"fieldEnvironmentTest": "Teste",
|
|
2497
|
+
"fieldEnvironmentProduction": "Produção",
|
|
2498
|
+
"copiedToClipboard": "Copiado para a área de transferência",
|
|
2499
|
+
"whatsappWebhookSectionTitle": "Webhook da Meta",
|
|
2500
|
+
"whatsappWebhookDescription": "Registre este webhook no seu app da Meta para receber mensagens do WhatsApp.",
|
|
2501
|
+
"whatsappWebhookCallbackUrlLabel": "URL de Callback",
|
|
2502
|
+
"whatsappWebhookVerifyTokenLabel": "Verify Token",
|
|
2503
|
+
"whatsappWebhookVerifyTokenHint": "Use o mesmo valor que você definiu no campo Verify Token acima.",
|
|
2504
|
+
"whatsappWebhookLoading": "Gerando URL…",
|
|
2505
|
+
"whatsappWebhookUnavailable": "URL indisponível — verifique a configuração de URL base da API.",
|
|
2506
|
+
"whatsappWebhookSaveFirst": "Salve o perfil para gerar a URL do webhook.",
|
|
2507
|
+
"whatsappWebhookStepsTitle": "No painel da Meta (WhatsApp → Configuração):",
|
|
2508
|
+
"whatsappWebhookStep1": "Cole a URL de Callback e o Verify Token acima.",
|
|
2509
|
+
"whatsappWebhookStep2": "Clique em \"Verificar e salvar\".",
|
|
2510
|
+
"whatsappWebhookStep3": "Assine o campo \"messages\".",
|
|
2511
|
+
"whatsappWebhookStep4": "Envie uma mensagem de teste e confirme que ela chega.",
|
|
2488
2512
|
"fieldBasePath": "Caminho Base",
|
|
2489
2513
|
"fieldBucket": "Bucket",
|
|
2490
2514
|
"fieldProjectId": "Project ID",
|
|
@@ -2536,6 +2560,36 @@
|
|
|
2536
2560
|
"nodePoolPlaceholder": "Selecione um node pool",
|
|
2537
2561
|
"nodePoolNoneFound": "Nenhum node pool encontrado para este cluster.",
|
|
2538
2562
|
"nodePoolLoadError": "Falha ao carregar os node pools. Verifique o token da API e o ID do cluster.",
|
|
2539
|
-
"nodePoolNeedCreds": "Preencha o token da API e o ID do cluster primeiro, depois carregue os pools."
|
|
2563
|
+
"nodePoolNeedCreds": "Preencha o token da API e o ID do cluster primeiro, depois carregue os pools.",
|
|
2564
|
+
"fieldEnvironment": "Ambiente",
|
|
2565
|
+
"optionHomologation": "Homologação (testes)",
|
|
2566
|
+
"optionProduction": "Produção (notas reais)",
|
|
2567
|
+
"fieldTaxId": "CNPJ do emitente",
|
|
2568
|
+
"fieldLegalName": "Razão social",
|
|
2569
|
+
"fieldTradeName": "Nome fantasia",
|
|
2570
|
+
"fieldMunicipalRegistration": "Inscrição municipal",
|
|
2571
|
+
"fieldIbgeCityCode": "Código IBGE do município",
|
|
2572
|
+
"fieldAddressStreet": "Logradouro",
|
|
2573
|
+
"fieldAddressNumber": "Número",
|
|
2574
|
+
"fieldAddressComplement": "Complemento",
|
|
2575
|
+
"fieldAddressDistrict": "Bairro",
|
|
2576
|
+
"fieldAddressZip": "CEP",
|
|
2577
|
+
"fieldAddressState": "Estado",
|
|
2578
|
+
"fieldEmail": "E-mail",
|
|
2579
|
+
"fieldPhone": "Telefone",
|
|
2580
|
+
"fieldTaxRegime": "Regime tributário",
|
|
2581
|
+
"optionSimplesNacional": "Simples Nacional",
|
|
2582
|
+
"optionSimplesNacionalExcesso": "Simples Nacional (excesso de sublimite)",
|
|
2583
|
+
"optionRegimeNormal": "Regime normal",
|
|
2584
|
+
"optionMei": "MEI",
|
|
2585
|
+
"fieldSpecialTaxRegime": "Regime especial de tributação",
|
|
2586
|
+
"fieldCulturalIncentive": "Incentivador cultural",
|
|
2587
|
+
"fieldCertificatePfx": "Certificado A1 (.pfx/.p12)",
|
|
2588
|
+
"fieldCertificatePassword": "Senha do certificado",
|
|
2589
|
+
"fieldBaseUrl": "URL base da API",
|
|
2590
|
+
"fieldTimeoutMs": "Timeout (ms)",
|
|
2591
|
+
"fieldMaxRetries": "Máximo de tentativas",
|
|
2592
|
+
"fileStored": "Arquivo armazenado e cifrado. Clique para substituir.",
|
|
2593
|
+
"fileSelected": "Novo arquivo selecionado. Será cifrado ao salvar."
|
|
2540
2594
|
}
|
|
2541
2595
|
}
|