From c7237da570dee9cb037bdd7306d11b71ae661f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Fri, 21 Aug 2026 08:44:58 -0600 Subject: [PATCH 1/5] feat[frontend](integrations): use entered tenant's domain in install commands under MSSP --- .../features/billing/services/billing.context.tsx | 3 +++ .../integrations/components/setup/AgentSetup.tsx | 5 ++--- .../components/setup/collector/ForwarderGuide.tsx | 14 +++++++++++--- .../src/features/tenants/components/TenantCard.tsx | 1 + .../features/tenants/components/TenantSwitcher.tsx | 1 + frontend/src/shared/lib/current-tenant.ts | 2 ++ frontend/src/shared/lib/license-flags.ts | 13 +++++++++++++ 7 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 frontend/src/shared/lib/license-flags.ts diff --git a/frontend/src/features/billing/services/billing.context.tsx b/frontend/src/features/billing/services/billing.context.tsx index bb9717f7c..3a60107c2 100644 --- a/frontend/src/features/billing/services/billing.context.tsx +++ b/frontend/src/features/billing/services/billing.context.tsx @@ -10,6 +10,7 @@ import { import { useAuth } from '@/features/auth' import { IS_FEDERATION } from '@/shared/config/mode' import { useCurrentInstanceId } from '@/shared/lib/current-instance' +import { setMsspFlag } from '@/shared/lib/license-flags' import { billingHttpService } from './billing-http.service' import type { License, VersionInfo } from '../types/billing.types' @@ -48,6 +49,7 @@ export function BillingProvider({ children }: { children: ReactNode }) { billingHttpService.getVersion(), ]) setLicense(lic) + setMsspFlag(lic?.mssp === true) setVersion(ver) } catch { setError(true) @@ -59,6 +61,7 @@ export function BillingProvider({ children }: { children: ReactNode }) { useEffect(() => { if (!ready) { setLicense(null) + setMsspFlag(false) setVersion(null) return } diff --git a/frontend/src/features/integrations/components/setup/AgentSetup.tsx b/frontend/src/features/integrations/components/setup/AgentSetup.tsx index 5c3477ce9..78ca1142a 100644 --- a/frontend/src/features/integrations/components/setup/AgentSetup.tsx +++ b/frontend/src/features/integrations/components/setup/AgentSetup.tsx @@ -6,6 +6,7 @@ import { AgentInstallSelector } from '@/features/integrations/components/setup/A import { AgentUninstallSection } from '@/features/integrations/components/setup/AgentUninstallSection' import { useConectionKey } from '@/features/integrations/hooks/useConnectionKey' import { buildAgentInstall } from '@/features/integrations/utils/agentInstallBuilder' +import { forwarderHost } from '@/features/integrations/components/setup/collector/ForwarderGuide' import type { Integration } from '@/features/integrations/types' interface AgentSetupProps { @@ -18,9 +19,7 @@ export function AgentSetup({ integration: i }: AgentSetupProps) { const { t } = useTranslation() const { key } = useConectionKey() - const host = window.location.host.includes(':') - ? window.location.host.split(':')[0] - : window.location.host + const host = forwarderHost() // Always render the command even before the key loads: fall back to a masked // placeholder (like the AS/400 and Forwarder guides) so the user never sees a diff --git a/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx b/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx index 870325b94..48856e513 100644 --- a/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx +++ b/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx @@ -6,6 +6,8 @@ import { Section } from '@/features/integrations/components/ui/Section' import { CodeBlock } from '@/features/integrations/components/ui/CodeBlock' import { useConectionKey } from '@/features/integrations/hooks/useConnectionKey' import { FlowNode, FlowEdge } from '@/shared/components/ui/flow-diagram' +import { getSupportTenant } from '@/shared/lib/current-tenant' +import { isMssp } from '@/shared/lib/license-flags' import { RemoteEnablePanel, type RemoteEnableSelection } from './RemoteEnablePanel' import { availableProtosFor, defaultPortFor, type Proto } from './protoCatalog' @@ -23,10 +25,16 @@ import { availableProtosFor, defaultPortFor, type Proto } from './protoCatalog' const SHARED = 'integrations.setup.collector.forwarder' const LOGINPUT_PORT = '50052' -// The Forwarder runs on the UTMStack host; default the address to where the user -// is browsing from (stripped of any port). +// The Forwarder runs on the UTMStack host; default the address to where the +// user is browsing from (stripped of any port). In MSSP mode, when the operator +// has entered a child tenant, use that tenant's domain instead — the child is +// reached at its own subdomain, not the default's. export function forwarderHost(): string { if (typeof window === 'undefined') return 'utmstack-host' + if (isMssp()) { + const support = getSupportTenant() + if (support?.domain) return support.domain + } const h = window.location.host return h.includes(':') ? h.split(':')[0] : h } @@ -76,7 +84,7 @@ function MasterCommandSection({ selection }: { selection: RemoteEnableSelection const { t } = useTranslation() const [tab, setTab] = useState<'simple' | 'batch'>('simple') if (!selection.apiKey) return null - const host = typeof window === 'undefined' ? 'utmstack-host' : window.location.host + const host = forwarderHost() const simpleCmd = `curl -k -X POST https://${host}:${LOGINPUT_PORT}/v1/ingest \\ -H "Content-Type: application/json" \\ -H "Utm-Api-Key: " \\ diff --git a/frontend/src/features/tenants/components/TenantCard.tsx b/frontend/src/features/tenants/components/TenantCard.tsx index 8782b2bdb..471a4eabf 100644 --- a/frontend/src/features/tenants/components/TenantCard.tsx +++ b/frontend/src/features/tenants/components/TenantCard.tsx @@ -30,6 +30,7 @@ function enterTenant(tenant: Tenant): void { id: tenant.id, name: tenant.name, access: tenant.supportAccess === 'FULL' ? 'FULL' : 'READ', + domain: tenant.domain, }) window.location.assign('/home') } diff --git a/frontend/src/features/tenants/components/TenantSwitcher.tsx b/frontend/src/features/tenants/components/TenantSwitcher.tsx index a9c6320c9..0a92de89d 100644 --- a/frontend/src/features/tenants/components/TenantSwitcher.tsx +++ b/frontend/src/features/tenants/components/TenantSwitcher.tsx @@ -86,6 +86,7 @@ export function TenantSwitcher() { id: tenant.id, name: tenant.name, access: tenant.supportAccess === 'FULL' ? 'FULL' : 'READ', + domain: tenant.domain, }) reloadAfterSwitch() } diff --git a/frontend/src/shared/lib/current-tenant.ts b/frontend/src/shared/lib/current-tenant.ts index fb13b9f96..9d7b156c1 100644 --- a/frontend/src/shared/lib/current-tenant.ts +++ b/frontend/src/shared/lib/current-tenant.ts @@ -18,6 +18,8 @@ export interface SupportTenant { name: string /** The level the tenant granted when we entered, for the banner to name it. */ access: 'READ' | 'FULL' + /** The tenant's routable domain. Used to build install/ingest URLs in MSSP mode. */ + domain?: string } function read(): SupportTenant | null { diff --git a/frontend/src/shared/lib/license-flags.ts b/frontend/src/shared/lib/license-flags.ts new file mode 100644 index 000000000..22518d485 --- /dev/null +++ b/frontend/src/shared/lib/license-flags.ts @@ -0,0 +1,13 @@ +// Module-level mirror of the MSSP license flag so non-React code (URL/host +// helpers used inside plain functions) can read it synchronously. Updated by +// BillingProvider on every license refresh. + +let mssp = false + +export function isMssp(): boolean { + return mssp +} + +export function setMsspFlag(value: boolean): void { + mssp = value +} From ed6ce46f567074b9cc038a11a99e412c6b5da97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Fri, 21 Aug 2026 09:41:31 -0600 Subject: [PATCH 2/5] fix[frontend](integrations): show default collector guide when clicking add collector --- .../components/setup/collector/RemoteEnablePanel.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx b/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx index dc4b5f825..240d7402c 100644 --- a/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx +++ b/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx @@ -344,6 +344,7 @@ export function RemoteEnablePanel({ value={collectorId} onChange={(id) => { if (id === ADD_COLLECTOR_ID) { + setCollectorId(null) onRequestAddCollector?.() return } From bc7b26781ab63dfd011af876cd9d23eb87af1d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Fri, 21 Aug 2026 09:49:06 -0600 Subject: [PATCH 3/5] feat[frontend](integrations): replace API key picker with add-key button in send-to-master --- .../components/setup/CustomSetup.tsx | 2 +- .../setup/collector/ApiKeyPicker.tsx | 66 ------------------- .../setup/collector/ForwarderGuide.tsx | 7 +- .../setup/collector/RemoteEnablePanel.tsx | 41 ++++-------- frontend/src/shared/i18n/locales/de.json | 3 +- frontend/src/shared/i18n/locales/en.json | 3 +- frontend/src/shared/i18n/locales/es.json | 3 +- frontend/src/shared/i18n/locales/fr.json | 3 +- frontend/src/shared/i18n/locales/it.json | 3 +- frontend/src/shared/i18n/locales/pt.json | 3 +- frontend/src/shared/i18n/locales/ru.json | 3 +- 11 files changed, 31 insertions(+), 106 deletions(-) delete mode 100644 frontend/src/features/integrations/components/setup/collector/ApiKeyPicker.tsx diff --git a/frontend/src/features/integrations/components/setup/CustomSetup.tsx b/frontend/src/features/integrations/components/setup/CustomSetup.tsx index 4a961c9f4..ac16083cc 100644 --- a/frontend/src/features/integrations/components/setup/CustomSetup.tsx +++ b/frontend/src/features/integrations/components/setup/CustomSetup.tsx @@ -37,7 +37,7 @@ export function CustomSetup({ integration }: { integration: Integration }) { // slug if the catalog row has no explicit data type. const name = integration.dataType || integration.moduleName?.toLowerCase() || 'my-integration' - const [selection, setSelection] = useState({ proto: 'udp', port: '7100', isMaster: false, apiKey: null }) + const [selection, setSelection] = useState({ proto: 'udp', port: '7100', isMaster: false }) const { proto, port } = selection const isHttp = proto === 'http' || proto === 'https' diff --git a/frontend/src/features/integrations/components/setup/collector/ApiKeyPicker.tsx b/frontend/src/features/integrations/components/setup/collector/ApiKeyPicker.tsx deleted file mode 100644 index b2afa7bba..000000000 --- a/frontend/src/features/integrations/components/setup/collector/ApiKeyPicker.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useEffect, useRef, useState } from 'react' -import { ChevronDown, Plus } from 'lucide-react' -import type { ApiKey } from '@/features/api-keys/types/api-key.types' - -export interface ApiKeyPickerProps { - keys: ApiKey[] - value: number | null - onChange: (id: number) => void - onAddNew: () => void - addLabel: string - placeholder: string - emptyLabel: string - disabled?: boolean -} - -export function ApiKeyPicker({ keys, value, onChange, onAddNew, addLabel, placeholder, emptyLabel, disabled }: ApiKeyPickerProps) { - const [open, setOpen] = useState(false) - const ref = useRef(null) - const selected = keys.find((k) => k.id === value) ?? null - - useEffect(() => { - if (!open) return - const onDoc = (e: MouseEvent) => ref.current && !ref.current.contains(e.target as Node) && setOpen(false) - document.addEventListener('mousedown', onDoc) - return () => document.removeEventListener('mousedown', onDoc) - }, [open]) - - return ( -
- - {open && ( -
- {keys.length === 0 && ( - {emptyLabel} - )} - {keys.map((k) => ( - - ))} - -
- )} -
- ) -} diff --git a/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx b/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx index 48856e513..eca141ecb 100644 --- a/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx +++ b/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx @@ -80,10 +80,9 @@ function FlowDiagram({ source, port, isMaster }: { source: string; port: string; // ── Master command (POST endpoint + auth header) ───────────────────────────── -function MasterCommandSection({ selection }: { selection: RemoteEnableSelection }) { +function MasterCommandSection(_: { selection: RemoteEnableSelection }) { const { t } = useTranslation() const [tab, setTab] = useState<'simple' | 'batch'>('simple') - if (!selection.apiKey) return null const host = forwarderHost() const simpleCmd = `curl -k -X POST https://${host}:${LOGINPUT_PORT}/v1/ingest \\ -H "Content-Type: application/json" \\ @@ -115,7 +114,7 @@ function MasterCommandSection({ selection }: { selection: RemoteEnableSelection }'` return (
-

{t(`${SHARED}.masterHeader.body`, { name: selection.apiKey.name })}

+

{t(`${SHARED}.masterHeader.body`)}

{(['simple', 'batch'] as const).map((v) => (
{isMaster && ( - +
+

{t(`${ROOT}.apiKeyHint`)}

+ +
)} {!isMaster && (<> diff --git a/frontend/src/shared/i18n/locales/de.json b/frontend/src/shared/i18n/locales/de.json index 927736c75..fc97f8677 100644 --- a/frontend/src/shared/i18n/locales/de.json +++ b/frontend/src/shared/i18n/locales/de.json @@ -2739,7 +2739,7 @@ }, "masterHeader": { "title": "Autorisierungs-Header", - "body": "Fügen Sie diesen Authorization-Header jeder Anfrage hinzu, die Sie an den Master senden. Das Geheimnis für \"{{name}}\" wird nur einmal bei der Erstellung des API-Schlüssels angezeigt — kopieren Sie es dann und fügen Sie es anstelle des Platzhalters unten ein.", + "body": "Fügen Sie diesen Authorization-Header jeder Anfrage hinzu, die Sie an den Master senden. Das Geheimnis des API-Schlüssels wird nur einmal bei seiner Erstellung angezeigt — kopieren Sie es dann und fügen Sie es anstelle des Platzhalters unten ein.", "tabSimple": "Einfach", "tabBatch": "Stapel" } @@ -3382,6 +3382,7 @@ "addCollector": "Collector hinzufügen", "addApiKey": "API-Schlüssel hinzufügen", "apiKeyLabel": "API-Schlüssel", + "apiKeyHint": "Zuerst benötigen Sie einen API-Schlüssel.", "apiKeyPlaceholder": "API-Schlüssel auswählen", "apiKeyAddNew": "API-Schlüssel hinzufügen…", "apiKeyNone": "Noch keine API-Schlüssel vorhanden" diff --git a/frontend/src/shared/i18n/locales/en.json b/frontend/src/shared/i18n/locales/en.json index e7c52f6a4..355a67ef3 100644 --- a/frontend/src/shared/i18n/locales/en.json +++ b/frontend/src/shared/i18n/locales/en.json @@ -2898,7 +2898,7 @@ }, "masterHeader": { "title": "Authorization header", - "body": "Include this Authorization header on every request you send to Master. The secret for \"{{name}}\" is only revealed once when the API key is generated — copy it then and paste it in place of the placeholder below.", + "body": "Include this Authorization header on every request you send to Master. The API key's secret is revealed only once when it is generated — copy it then and paste it in place of the placeholder below.", "tabSimple": "Simple", "tabBatch": "Batch" } @@ -3483,6 +3483,7 @@ "addCollector": "Add Collector", "addApiKey": "Add API key", "apiKeyLabel": "API key", + "apiKeyHint": "First you'll need an API key.", "apiKeyPlaceholder": "Select an API key", "apiKeyAddNew": "Add API key…", "apiKeyNone": "No API keys yet" diff --git a/frontend/src/shared/i18n/locales/es.json b/frontend/src/shared/i18n/locales/es.json index 7427876e2..29cca5bfb 100644 --- a/frontend/src/shared/i18n/locales/es.json +++ b/frontend/src/shared/i18n/locales/es.json @@ -1841,7 +1841,7 @@ }, "masterHeader": { "title": "Cabecera de autorización", - "body": "Incluye esta cabecera Authorization en cada solicitud que envíes al Master. El secreto de \"{{name}}\" solo se muestra una vez al generar la clave API — cópialo entonces y pégalo en lugar del marcador de posición de abajo.", + "body": "Incluye esta cabecera Authorization en cada solicitud que envíes al Master. El secreto de la clave API solo se muestra una vez al generarla — cópialo entonces y pégalo en lugar del marcador de posición de abajo.", "tabSimple": "Simple", "tabBatch": "Lote" } @@ -3344,6 +3344,7 @@ "addCollector": "Añadir Collector", "addApiKey": "Añadir clave API", "apiKeyLabel": "Clave API", + "apiKeyHint": "Primero necesitarás una clave API.", "apiKeyPlaceholder": "Selecciona una clave API", "apiKeyAddNew": "Añadir clave API…", "apiKeyNone": "Todavía no hay claves API" diff --git a/frontend/src/shared/i18n/locales/fr.json b/frontend/src/shared/i18n/locales/fr.json index 2df043ab0..c986ba98b 100644 --- a/frontend/src/shared/i18n/locales/fr.json +++ b/frontend/src/shared/i18n/locales/fr.json @@ -2739,7 +2739,7 @@ }, "masterHeader": { "title": "En-tête d'autorisation", - "body": "Incluez cet en-tête Authorization dans chaque requête envoyée au Master. Le secret de \"{{name}}\" n'est révélé qu'une seule fois à la génération de la clé API — copiez-le à ce moment et collez-le à la place du placeholder ci-dessous.", + "body": "Incluez cet en-tête Authorization dans chaque requête envoyée au Master. Le secret de la clé API n'est révélé qu'une seule fois à sa génération — copiez-le à ce moment et collez-le à la place du placeholder ci-dessous.", "tabSimple": "Simple", "tabBatch": "Lot" } @@ -3382,6 +3382,7 @@ "addCollector": "Ajouter un Collector", "addApiKey": "Ajouter une clé API", "apiKeyLabel": "Clé API", + "apiKeyHint": "Vous aurez d'abord besoin d'une clé API.", "apiKeyPlaceholder": "Sélectionner une clé API", "apiKeyAddNew": "Ajouter une clé API…", "apiKeyNone": "Aucune clé API pour l'instant" diff --git a/frontend/src/shared/i18n/locales/it.json b/frontend/src/shared/i18n/locales/it.json index 501372889..a1ef24d8a 100644 --- a/frontend/src/shared/i18n/locales/it.json +++ b/frontend/src/shared/i18n/locales/it.json @@ -2739,7 +2739,7 @@ }, "masterHeader": { "title": "Intestazione di autorizzazione", - "body": "Includi questa intestazione Authorization in ogni richiesta inviata al Master. Il segreto di \"{{name}}\" viene rivelato una sola volta al momento della generazione della chiave API — copialo allora e incollalo al posto del segnaposto qui sotto.", + "body": "Includi questa intestazione Authorization in ogni richiesta inviata al Master. Il segreto della chiave API viene rivelato una sola volta al momento della sua generazione — copialo allora e incollalo al posto del segnaposto qui sotto.", "tabSimple": "Semplice", "tabBatch": "Batch" } @@ -3382,6 +3382,7 @@ "addCollector": "Aggiungi Collector", "addApiKey": "Aggiungi chiave API", "apiKeyLabel": "Chiave API", + "apiKeyHint": "Prima ti servirà una chiave API.", "apiKeyPlaceholder": "Seleziona una chiave API", "apiKeyAddNew": "Aggiungi chiave API…", "apiKeyNone": "Nessuna chiave API ancora" diff --git a/frontend/src/shared/i18n/locales/pt.json b/frontend/src/shared/i18n/locales/pt.json index 60595f1fc..847d6e023 100644 --- a/frontend/src/shared/i18n/locales/pt.json +++ b/frontend/src/shared/i18n/locales/pt.json @@ -1841,7 +1841,7 @@ }, "masterHeader": { "title": "Cabeçalho de autorização", - "body": "Inclua este cabeçalho Authorization em cada requisição enviada ao Master. O segredo de \"{{name}}\" é revelado apenas uma vez ao gerar a chave de API — copie-o naquele momento e cole no lugar do marcador abaixo.", + "body": "Inclua este cabeçalho Authorization em cada requisição enviada ao Master. O segredo da chave de API é revelado apenas uma vez ao gerá-la — copie-o naquele momento e cole no lugar do marcador abaixo.", "tabSimple": "Simples", "tabBatch": "Lote" } @@ -3344,6 +3344,7 @@ "addCollector": "Adicionar Collector", "addApiKey": "Adicionar chave de API", "apiKeyLabel": "Chave de API", + "apiKeyHint": "Primeiro você precisará de uma chave de API.", "apiKeyPlaceholder": "Selecionar uma chave de API", "apiKeyAddNew": "Adicionar chave de API…", "apiKeyNone": "Nenhuma chave de API ainda" diff --git a/frontend/src/shared/i18n/locales/ru.json b/frontend/src/shared/i18n/locales/ru.json index 586d1fb21..4438a789d 100644 --- a/frontend/src/shared/i18n/locales/ru.json +++ b/frontend/src/shared/i18n/locales/ru.json @@ -2621,7 +2621,7 @@ }, "masterHeader": { "title": "Заголовок авторизации", - "body": "Включайте этот заголовок Authorization в каждый запрос, отправляемый на Master. Секрет ключа «{{name}}» отображается только один раз при его создании — скопируйте его тогда и вставьте вместо заполнителя ниже.", + "body": "Включайте этот заголовок Authorization в каждый запрос, отправляемый на Master. Секрет API-ключа отображается только один раз при его создании — скопируйте его тогда и вставьте вместо заполнителя ниже.", "tabSimple": "Одиночный", "tabBatch": "Пакетный" } @@ -3264,6 +3264,7 @@ "addCollector": "Добавить Collector", "addApiKey": "Добавить API-ключ", "apiKeyLabel": "API-ключ", + "apiKeyHint": "Сначала вам понадобится API-ключ.", "apiKeyPlaceholder": "Выберите API-ключ", "apiKeyAddNew": "Добавить API-ключ…", "apiKeyNone": "Нет ни одного API-ключа" From 59089e55dcd27a61c69118c4f1b6b446da96be45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Fri, 21 Aug 2026 09:57:31 -0600 Subject: [PATCH 4/5] chore[frontend](integrations): rename user-facing "master" to "instance" --- .../components/setup/collector/ForwarderGuide.tsx | 6 +++--- .../components/setup/collector/RemoteEnablePanel.tsx | 2 +- frontend/src/shared/i18n/locales/de.json | 6 +++--- frontend/src/shared/i18n/locales/en.json | 6 +++--- frontend/src/shared/i18n/locales/es.json | 6 +++--- frontend/src/shared/i18n/locales/fr.json | 6 +++--- frontend/src/shared/i18n/locales/it.json | 6 +++--- frontend/src/shared/i18n/locales/pt.json | 6 +++--- frontend/src/shared/i18n/locales/ru.json | 6 +++--- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx b/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx index eca141ecb..338a2fe84 100644 --- a/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx +++ b/frontend/src/features/integrations/components/setup/collector/ForwarderGuide.tsx @@ -113,8 +113,8 @@ function MasterCommandSection(_: { selection: RemoteEnableSelection }) { ] }'` return ( -
-

{t(`${SHARED}.masterHeader.body`)}

+
+

{t(`${SHARED}.instanceHeader.body`)}

{(['simple', 'batch'] as const).map((v) => ( ))}
diff --git a/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx b/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx index e02200c08..fa4580e94 100644 --- a/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx +++ b/frontend/src/features/integrations/components/setup/collector/RemoteEnablePanel.tsx @@ -173,7 +173,7 @@ export function RemoteEnablePanel({ const isMaster = collectorId === MASTER_ID const masterOption: ForwarderCollector = { id: MASTER_ID, - hostname: t(`${ROOT}.sendToMaster`), + hostname: t(`${ROOT}.sendToInstance`), ip: '', version: '', status: 'online', diff --git a/frontend/src/shared/i18n/locales/de.json b/frontend/src/shared/i18n/locales/de.json index fc97f8677..7de668419 100644 --- a/frontend/src/shared/i18n/locales/de.json +++ b/frontend/src/shared/i18n/locales/de.json @@ -2737,9 +2737,9 @@ "title": "Optional – Collector deinstallieren", "body": "Führen Sie diesen Befehl auf dem Host aus, auf dem der Collector installiert ist, um den Dienst zu beenden und alle zugehörigen Dateien zu entfernen." }, - "masterHeader": { + "instanceHeader": { "title": "Autorisierungs-Header", - "body": "Fügen Sie diesen Authorization-Header jeder Anfrage hinzu, die Sie an den Master senden. Das Geheimnis des API-Schlüssels wird nur einmal bei seiner Erstellung angezeigt — kopieren Sie es dann und fügen Sie es anstelle des Platzhalters unten ein.", + "body": "Fügen Sie diesen Authorization-Header jeder Anfrage hinzu, die Sie an die Instanz senden. Das Geheimnis des API-Schlüssels wird nur einmal bei seiner Erstellung angezeigt — kopieren Sie es dann und fügen Sie es anstelle des Platzhalters unten ein.", "tabSimple": "Einfach", "tabBatch": "Stapel" } @@ -3377,7 +3377,7 @@ "disableSuccess": "Integration deaktiviert.", "enableError": "Fehler beim Aktualisieren der Integration.", "secretWarning": "Speichern Sie dieses Token sicher — es wird danach nicht mehr angezeigt.", - "sendToMaster": "An Master senden", + "sendToInstance": "An Instanz senden", "enterpriseFeature": "Dies ist eine Enterprise-Funktion.", "addCollector": "Collector hinzufügen", "addApiKey": "API-Schlüssel hinzufügen", diff --git a/frontend/src/shared/i18n/locales/en.json b/frontend/src/shared/i18n/locales/en.json index 355a67ef3..2d23ecf25 100644 --- a/frontend/src/shared/i18n/locales/en.json +++ b/frontend/src/shared/i18n/locales/en.json @@ -2896,9 +2896,9 @@ "certStep": "1 · Load your certificate and key (once per Collector)", "enableStep": "2 · Enable the integration" }, - "masterHeader": { + "instanceHeader": { "title": "Authorization header", - "body": "Include this Authorization header on every request you send to Master. The API key's secret is revealed only once when it is generated — copy it then and paste it in place of the placeholder below.", + "body": "Include this Authorization header on every request you send to the instance. The API key's secret is revealed only once when it is generated — copy it then and paste it in place of the placeholder below.", "tabSimple": "Simple", "tabBatch": "Batch" } @@ -3478,7 +3478,7 @@ "disableSuccess": "Integration disabled.", "enableError": "Failed to update the integration.", "secretWarning": "Store this token securely — it won't be shown again.", - "sendToMaster": "Send to Master", + "sendToInstance": "Send to instance", "enterpriseFeature": "This is an Enterprise feature.", "addCollector": "Add Collector", "addApiKey": "Add API key", diff --git a/frontend/src/shared/i18n/locales/es.json b/frontend/src/shared/i18n/locales/es.json index 29cca5bfb..5712cc891 100644 --- a/frontend/src/shared/i18n/locales/es.json +++ b/frontend/src/shared/i18n/locales/es.json @@ -1839,9 +1839,9 @@ "title": "Opcional — Desinstalar el Collector", "body": "Ejecuta este comando en el host donde está instalado el Collector para detener el servicio y eliminar todos sus archivos." }, - "masterHeader": { + "instanceHeader": { "title": "Cabecera de autorización", - "body": "Incluye esta cabecera Authorization en cada solicitud que envíes al Master. El secreto de la clave API solo se muestra una vez al generarla — cópialo entonces y pégalo en lugar del marcador de posición de abajo.", + "body": "Incluye esta cabecera Authorization en cada solicitud que envíes a la instancia. El secreto de la clave API solo se muestra una vez al generarla — cópialo entonces y pégalo en lugar del marcador de posición de abajo.", "tabSimple": "Simple", "tabBatch": "Lote" } @@ -3339,7 +3339,7 @@ "disableSuccess": "Integración deshabilitada.", "enableError": "No se pudo actualizar la integración.", "secretWarning": "Almacena este token de forma segura — no se mostrará nuevamente.", - "sendToMaster": "Enviar al Master", + "sendToInstance": "Enviar a la instancia", "enterpriseFeature": "Esta es una función Enterprise.", "addCollector": "Añadir Collector", "addApiKey": "Añadir clave API", diff --git a/frontend/src/shared/i18n/locales/fr.json b/frontend/src/shared/i18n/locales/fr.json index c986ba98b..4e68a9be3 100644 --- a/frontend/src/shared/i18n/locales/fr.json +++ b/frontend/src/shared/i18n/locales/fr.json @@ -2737,9 +2737,9 @@ "title": "Optionnel — Désinstaller le Collector", "body": "Exécutez cette commande sur l'hôte où le Collector est installé pour arrêter le service et supprimer tous ses fichiers." }, - "masterHeader": { + "instanceHeader": { "title": "En-tête d'autorisation", - "body": "Incluez cet en-tête Authorization dans chaque requête envoyée au Master. Le secret de la clé API n'est révélé qu'une seule fois à sa génération — copiez-le à ce moment et collez-le à la place du placeholder ci-dessous.", + "body": "Incluez cet en-tête Authorization dans chaque requête envoyée à l'instance. Le secret de la clé API n'est révélé qu'une seule fois à sa génération — copiez-le à ce moment et collez-le à la place du placeholder ci-dessous.", "tabSimple": "Simple", "tabBatch": "Lot" } @@ -3377,7 +3377,7 @@ "disableSuccess": "Intégration désactivée.", "enableError": "Échec de la mise à jour de l'intégration.", "secretWarning": "Stockez ce jeton en toute sécurité — il ne sera pas affiché à nouveau.", - "sendToMaster": "Envoyer au Master", + "sendToInstance": "Envoyer à l'instance", "enterpriseFeature": "Ceci est une fonctionnalité Enterprise.", "addCollector": "Ajouter un Collector", "addApiKey": "Ajouter une clé API", diff --git a/frontend/src/shared/i18n/locales/it.json b/frontend/src/shared/i18n/locales/it.json index a1ef24d8a..eac6d405d 100644 --- a/frontend/src/shared/i18n/locales/it.json +++ b/frontend/src/shared/i18n/locales/it.json @@ -2737,9 +2737,9 @@ "title": "Facoltativo — Disinstalla il Collector", "body": "Esegui questo comando sull'host in cui è installato il Collector per interrompere il servizio e rimuovere tutti i suoi file." }, - "masterHeader": { + "instanceHeader": { "title": "Intestazione di autorizzazione", - "body": "Includi questa intestazione Authorization in ogni richiesta inviata al Master. Il segreto della chiave API viene rivelato una sola volta al momento della sua generazione — copialo allora e incollalo al posto del segnaposto qui sotto.", + "body": "Includi questa intestazione Authorization in ogni richiesta inviata all'istanza. Il segreto della chiave API viene rivelato una sola volta al momento della sua generazione — copialo allora e incollalo al posto del segnaposto qui sotto.", "tabSimple": "Semplice", "tabBatch": "Batch" } @@ -3377,7 +3377,7 @@ "disableSuccess": "Integrazione disabilitata.", "enableError": "Aggiornamento dell'integrazione non riuscito.", "secretWarning": "Archivia questo token in modo sicuro — non verrà visualizzato di nuovo.", - "sendToMaster": "Invia al Master", + "sendToInstance": "Invia all'istanza", "enterpriseFeature": "Questa è una funzionalità Enterprise.", "addCollector": "Aggiungi Collector", "addApiKey": "Aggiungi chiave API", diff --git a/frontend/src/shared/i18n/locales/pt.json b/frontend/src/shared/i18n/locales/pt.json index 847d6e023..e43687823 100644 --- a/frontend/src/shared/i18n/locales/pt.json +++ b/frontend/src/shared/i18n/locales/pt.json @@ -1839,9 +1839,9 @@ "title": "Opcional — Desinstalar o Collector", "body": "Execute este comando no host onde o Collector está instalado para parar o serviço e remover todos os seus arquivos." }, - "masterHeader": { + "instanceHeader": { "title": "Cabeçalho de autorização", - "body": "Inclua este cabeçalho Authorization em cada requisição enviada ao Master. O segredo da chave de API é revelado apenas uma vez ao gerá-la — copie-o naquele momento e cole no lugar do marcador abaixo.", + "body": "Inclua este cabeçalho Authorization em cada requisição enviada à instância. O segredo da chave de API é revelado apenas uma vez ao gerá-la — copie-o naquele momento e cole no lugar do marcador abaixo.", "tabSimple": "Simples", "tabBatch": "Lote" } @@ -3339,7 +3339,7 @@ "disableSuccess": "Integração desativada.", "enableError": "Falha ao atualizar a integração.", "secretWarning": "Armazene este token com segurança — não será exibido novamente.", - "sendToMaster": "Enviar para o Master", + "sendToInstance": "Enviar para a instância", "enterpriseFeature": "Este é um recurso Enterprise.", "addCollector": "Adicionar Collector", "addApiKey": "Adicionar chave de API", diff --git a/frontend/src/shared/i18n/locales/ru.json b/frontend/src/shared/i18n/locales/ru.json index 4438a789d..2d2bd6695 100644 --- a/frontend/src/shared/i18n/locales/ru.json +++ b/frontend/src/shared/i18n/locales/ru.json @@ -2619,9 +2619,9 @@ "title": "Дополнительно — Удалить Collector", "body": "Выполните эту команду на хосте, где установлен Collector, чтобы остановить службу и удалить все её файлы." }, - "masterHeader": { + "instanceHeader": { "title": "Заголовок авторизации", - "body": "Включайте этот заголовок Authorization в каждый запрос, отправляемый на Master. Секрет API-ключа отображается только один раз при его создании — скопируйте его тогда и вставьте вместо заполнителя ниже.", + "body": "Включайте этот заголовок Authorization в каждый запрос, отправляемый на инстанс. Секрет API-ключа отображается только один раз при его создании — скопируйте его тогда и вставьте вместо заполнителя ниже.", "tabSimple": "Одиночный", "tabBatch": "Пакетный" } @@ -3259,7 +3259,7 @@ "disableSuccess": "Интеграция отключена.", "enableError": "Не удалось обновить интеграцию.", "secretWarning": "Сохраните этот токен в безопасном месте — он больше не будет показан.", - "sendToMaster": "Отправить на Master", + "sendToInstance": "Отправить на инстанс", "enterpriseFeature": "Это функция Enterprise.", "addCollector": "Добавить Collector", "addApiKey": "Добавить API-ключ", From 817de974b878eba6416cab261f62f3903f249317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20S=C3=A1nchez?= Date: Fri, 21 Aug 2026 10:16:52 -0600 Subject: [PATCH 5/5] chore[frontend](integrations): rename cloud "tenant" concept to "config group" --- frontend/src/shared/i18n/locales/de.json | 28 ++++++++++----------- frontend/src/shared/i18n/locales/en.json | 32 ++++++++++++------------ frontend/src/shared/i18n/locales/es.json | 26 +++++++++---------- frontend/src/shared/i18n/locales/fr.json | 28 ++++++++++----------- frontend/src/shared/i18n/locales/it.json | 28 ++++++++++----------- frontend/src/shared/i18n/locales/pt.json | 26 +++++++++---------- frontend/src/shared/i18n/locales/ru.json | 28 ++++++++++----------- 7 files changed, 98 insertions(+), 98 deletions(-) diff --git a/frontend/src/shared/i18n/locales/de.json b/frontend/src/shared/i18n/locales/de.json index 7de668419..f118aaf4d 100644 --- a/frontend/src/shared/i18n/locales/de.json +++ b/frontend/src/shared/i18n/locales/de.json @@ -2074,7 +2074,7 @@ "credentialsSection": "Mit UTMStack verbinden", "credentials": { "title": "Sophos Central-Anmeldedaten hinzufügen", - "body": "Geben Sie die soeben erstellten Anmeldedaten ein. Sie können mehr als ein Sophos-Konto hinzufügen, indem Sie auf „Tenant hinzufügen“ klicken." + "body": "Geben Sie die soeben erstellten Anmeldedaten ein. Sie können mehr als ein Sophos-Konto hinzufügen, indem Sie auf „Konfigurationsgruppe hinzufügen“ klicken." }, "fields": { "clientId": { @@ -2109,7 +2109,7 @@ }, "fillForm": { "title": "6 · Formular ausfüllen", - "body": "Geben Sie die Client ID und das Client Secret an UTMStack weiter. Sie können bei Bedarf mehr als einen Webroot-Tenant hinzufügen." + "body": "Geben Sie die Client ID und das Client Secret an UTMStack weiter. Sie können bei Bedarf mehr als eine Webroot-Konfigurationsgruppe hinzufügen." }, "activate": { "title": "7 · Aktivieren", @@ -2193,7 +2193,7 @@ "credentialsSection": "Anmeldedaten", "credentials": { "title": "Ihren Microsoft 365-Tenant verbinden", - "body": "Geben Sie die Angaben aus den obigen Schritten ein. UTMStack überprüft die Anmeldedaten vor dem Speichern. Sie können mehrere Tenants hinzufügen." + "body": "Geben Sie die Angaben aus den obigen Schritten ein. UTMStack überprüft die Anmeldedaten vor dem Speichern. Sie können mehrere Konfigurationsgruppen hinzufügen." }, "fields": { "tenantId": { @@ -2890,13 +2890,13 @@ "after2": "Danach werden Ereignisse alle 1–5 Minuten abgerufen (abhängig von der API).", "after3": "Die Integration wird unter Datenquellen mit aktuellem Abrufstatus und Verzögerung angezeigt.", "tenants": { - "title": "Konfigurierte Mandanten", - "empty": "Noch keine Mandanten konfiguriert. Fügen Sie unten Ihren ersten hinzu.", - "loading": "Mandanten werden geladen…", - "nameLabel": "Mandantenname", + "title": "Konfigurierte Konfigurationsgruppen", + "empty": "Noch keine Konfigurationsgruppen konfiguriert. Fügen Sie unten Ihre erste hinzu.", + "loading": "Konfigurationsgruppen werden geladen…", + "nameLabel": "Name der Konfigurationsgruppe", "namePlaceholder": "z. B. acme-prod", - "add": "Mandant hinzufügen", - "update": "Mandant aktualisieren", + "add": "Konfigurationsgruppe hinzufügen", + "update": "Konfigurationsgruppe aktualisieren", "delete": "Löschen", "edit": "Bearbeiten", "cancel": "Abbrechen", @@ -2905,10 +2905,10 @@ "replaceFile": "Datei ersetzen", "fileLoaded": "Datei geladen", "invalidJson": "Die Datei konnte nicht als JSON gelesen werden.", - "createError": "Der Mandant konnte nicht erstellt werden. Bitte erneut versuchen.", - "updateError": "Der Mandant konnte nicht aktualisiert werden. Bitte erneut versuchen.", - "createSuccess": "Mandant erfolgreich erstellt.", - "updateSuccess": "Mandant erfolgreich aktualisiert." + "createError": "Die Konfigurationsgruppe konnte nicht erstellt werden. Bitte erneut versuchen.", + "updateError": "Die Konfigurationsgruppe konnte nicht aktualisiert werden. Bitte erneut versuchen.", + "createSuccess": "Konfigurationsgruppe erfolgreich erstellt.", + "updateSuccess": "Konfigurationsgruppe erfolgreich aktualisiert." }, "google": { "sections": { @@ -3084,7 +3084,7 @@ "sections": { "prerequisite": { "title": "Voraussetzung · IAM-Benutzer", - "body": "Damit diese Integration funktioniert, benötigen Sie einen IAM-Benutzer für UTMStack mit der Richtlinie CloudWatchLogsReadOnlyAccess. Notieren Sie sich Zugriffsschlüssel-ID und geheimen Zugriffsschlüssel — Sie fügen sie unten in das Mandantenformular ein." + "body": "Damit diese Integration funktioniert, benötigen Sie einen IAM-Benutzer für UTMStack mit der Richtlinie CloudWatchLogsReadOnlyAccess. Notieren Sie sich Zugriffsschlüssel-ID und geheimen Zugriffsschlüssel — Sie fügen sie unten in das Formular der Konfigurationsgruppe ein." }, "createTrail": { "title": "1 · Trail erstellen", diff --git a/frontend/src/shared/i18n/locales/en.json b/frontend/src/shared/i18n/locales/en.json index 2d23ecf25..6416bab2e 100644 --- a/frontend/src/shared/i18n/locales/en.json +++ b/frontend/src/shared/i18n/locales/en.json @@ -2227,7 +2227,7 @@ "credentialsSection": "Connect to UTMStack", "credentials": { "title": "Add Sophos Central credentials", - "body": "Enter the credentials you just created. You can add more than one Sophos account by clicking Add tenant." + "body": "Enter the credentials you just created. You can add more than one Sophos account by clicking Add config group." }, "fields": { "clientId": { @@ -2262,7 +2262,7 @@ }, "fillForm": { "title": "6 · Fill the form", - "body": "Provide the client ID and client secret to UTMStack. You can add more than one Webroot tenant if needed." + "body": "Provide the client ID and client secret to UTMStack. You can add more than one Webroot config group if needed." }, "activate": { "title": "7 · Activate", @@ -2346,7 +2346,7 @@ "credentialsSection": "Credentials", "credentials": { "title": "Connect your Microsoft 365 tenant", - "body": "Enter the details from the steps above. UTMStack verifies the credentials before saving. You can add multiple tenants." + "body": "Enter the details from the steps above. UTMStack verifies the credentials before saving. You can add multiple config groups." }, "fields": { "tenantId": { @@ -3049,13 +3049,13 @@ "after2": "From then on, events are pulled every 1–5 minutes (depends on the API).", "after3": "The integration appears under Data Sources with current pull status and lag.", "tenants": { - "title": "Configured tenants", - "empty": "No tenants configured yet. Add your first one below.", - "loading": "Loading tenants…", - "nameLabel": "Tenant name", + "title": "Configured config groups", + "empty": "No config groups configured yet. Add your first one below.", + "loading": "Loading config groups…", + "nameLabel": "Config group name", "namePlaceholder": "e.g. acme-prod", - "add": "Add tenant", - "update": "Update tenant", + "add": "Add config group", + "update": "Update config group", "delete": "Delete", "edit": "Edit", "cancel": "Cancel", @@ -3064,10 +3064,10 @@ "replaceFile": "Replace file", "fileLoaded": "File loaded", "invalidJson": "Could not parse the file as JSON.", - "createError": "Could not create the tenant. Please try again.", - "updateError": "Could not update the tenant. Please try again.", - "createSuccess": "Tenant created successfully.", - "updateSuccess": "Tenant updated successfully." + "createError": "Could not create the config group. Please try again.", + "updateError": "Could not update the config group. Please try again.", + "createSuccess": "Config group created successfully.", + "updateSuccess": "Config group updated successfully." }, "google": { "intro": { @@ -3167,11 +3167,11 @@ }, "connectionString": { "title": "Copy the primary connection string", - "body": "Open the Shared access policy you just created and copy the Connection string–primary key. You will use it to configure your tenant below." + "body": "Open the Shared access policy you just created and copy the Connection string–primary key. You will use it to configure your config group below." }, "consumerGroup": { "title": "Create a dedicated consumer group", - "body": "Get the Consumer Group name in: All services → Event Hubs → your namespace → Event Hubs → your instance → Consumer groups. You will use it to configure your tenant below.", + "body": "Get the Consumer Group name in: All services → Event Hubs → your namespace → Event Hubs → your instance → Consumer groups. You will use it to configure your config group below.", "warn": "Create a consumer group specifically for UTMStack. Do not use $Default or any other group already in use — reusing a consumer group across unrelated consumers can cause unexpected behavior and lost events. All UTMStack instances should share the same consumer group so they can process events together." }, "createStorageAccount": { @@ -3181,7 +3181,7 @@ }, "storageContainer": { "title": "Get the Storage Container name", - "body": "Get the Storage Container name in: All services → Storage accounts → your account → Containers. You will use it to configure your tenant below." + "body": "Get the Storage Container name in: All services → Storage accounts → your account → Containers. You will use it to configure your config group below." }, "storageConnection": { "title": "Copy the Storage Account connection string", diff --git a/frontend/src/shared/i18n/locales/es.json b/frontend/src/shared/i18n/locales/es.json index 5712cc891..76a42a31c 100644 --- a/frontend/src/shared/i18n/locales/es.json +++ b/frontend/src/shared/i18n/locales/es.json @@ -1952,7 +1952,7 @@ "credentialsSection": "Credenciales", "credentials": { "title": "Conectar tu tenant de Microsoft 365", - "body": "Introduce los datos de los pasos anteriores. UTMStack verifica las credenciales antes de guardarlas. Puedes añadir múltiples tenants." + "body": "Introduce los datos de los pasos anteriores. UTMStack verifica las credenciales antes de guardarlas. Puedes añadir múltiples grupos de configuración." }, "fields": { "tenantId": { @@ -2141,7 +2141,7 @@ "credentialsSection": "Conectar con UTMStack", "credentials": { "title": "Añadir credenciales de Sophos Central", - "body": "Introduce las credenciales que acabas de crear. Puedes añadir más de una cuenta de Sophos haciendo clic en Añadir tenant." + "body": "Introduce las credenciales que acabas de crear. Puedes añadir más de una cuenta de Sophos haciendo clic en Añadir grupo de configuración." }, "fields": { "clientId": { @@ -2331,7 +2331,7 @@ }, "fillForm": { "title": "6 · Completar el formulario", - "body": "Proporcione el client ID y el client secret a UTMStack. Puede agregar más de un tenant de Webroot si es necesario." + "body": "Proporcione el client ID y el client secret a UTMStack. Puede agregar más de un grupo de configuración de Webroot si es necesario." }, "activate": { "title": "7 · Activar", @@ -2890,13 +2890,13 @@ "after2": "Desde entonces, los eventos se extraen cada 1–5 minutos (depende de la API).", "after3": "La integración aparece bajo Fuentes de datos con el estado actual de extracción y retraso.", "tenants": { - "title": "Tenants configurados", - "empty": "Aún no hay tenants configurados. Añade el primero más abajo.", - "loading": "Cargando tenants…", - "nameLabel": "Nombre del tenant", + "title": "Grupos de configuración configurados", + "empty": "Aún no hay grupos de configuración. Añade el primero más abajo.", + "loading": "Cargando grupos de configuración…", + "nameLabel": "Nombre del grupo de configuración", "namePlaceholder": "p. ej. acme-prod", - "add": "Añadir tenant", - "update": "Actualizar tenant", + "add": "Añadir grupo de configuración", + "update": "Actualizar grupo de configuración", "delete": "Eliminar", "edit": "Editar", "cancel": "Cancelar", @@ -2905,10 +2905,10 @@ "replaceFile": "Reemplazar archivo", "fileLoaded": "Archivo cargado", "invalidJson": "No se pudo procesar el archivo como JSON.", - "createError": "No se pudo crear el tenant. Inténtalo de nuevo.", - "updateError": "No se pudo actualizar el tenant. Inténtalo de nuevo.", - "createSuccess": "Tenant creado correctamente.", - "updateSuccess": "Tenant actualizado correctamente." + "createError": "No se pudo crear el grupo de configuración. Inténtalo de nuevo.", + "updateError": "No se pudo actualizar el grupo de configuración. Inténtalo de nuevo.", + "createSuccess": "Grupo de configuración creado correctamente.", + "updateSuccess": "Grupo de configuración actualizado correctamente." }, "google": { "sections": { diff --git a/frontend/src/shared/i18n/locales/fr.json b/frontend/src/shared/i18n/locales/fr.json index 4e68a9be3..fdf5f3979 100644 --- a/frontend/src/shared/i18n/locales/fr.json +++ b/frontend/src/shared/i18n/locales/fr.json @@ -2074,7 +2074,7 @@ "credentialsSection": "Se connecter à UTMStack", "credentials": { "title": "Ajouter des identifiants Sophos Central", - "body": "Saisissez les identifiants que vous venez de créer. Vous pouvez ajouter plusieurs comptes Sophos en cliquant sur Ajouter un tenant." + "body": "Saisissez les identifiants que vous venez de créer. Vous pouvez ajouter plusieurs comptes Sophos en cliquant sur Ajouter un groupe de configuration." }, "fields": { "clientId": { @@ -2109,7 +2109,7 @@ }, "fillForm": { "title": "6 · Remplir le formulaire", - "body": "Fournissez le client ID et le client secret à UTMStack. Vous pouvez ajouter plusieurs tenants Webroot si nécessaire." + "body": "Fournissez le client ID et le client secret à UTMStack. Vous pouvez ajouter plusieurs groupes de configuration Webroot si nécessaire." }, "activate": { "title": "7 · Activer", @@ -2193,7 +2193,7 @@ "credentialsSection": "Identifiants", "credentials": { "title": "Connecter votre tenant Microsoft 365", - "body": "Saisissez les informations des étapes précédentes. UTMStack vérifie les identifiants avant l'enregistrement. Vous pouvez ajouter plusieurs tenants." + "body": "Saisissez les informations des étapes précédentes. UTMStack vérifie les identifiants avant l'enregistrement. Vous pouvez ajouter plusieurs groupes de configuration." }, "fields": { "tenantId": { @@ -2890,13 +2890,13 @@ "after2": "Ensuite, les événements sont extraits toutes les 1–5 minutes (dépend de l'API).", "after3": "L'intégration apparaît sous Sources de données avec l'état d'extraction et le décalage actuels.", "tenants": { - "title": "Tenants configurés", - "empty": "Aucun tenant configuré pour le moment. Ajoutez le premier ci-dessous.", - "loading": "Chargement des tenants…", - "nameLabel": "Nom du tenant", + "title": "Groupes de configuration configurés", + "empty": "Aucun groupe de configuration pour le moment. Ajoutez le premier ci-dessous.", + "loading": "Chargement des groupes de configuration…", + "nameLabel": "Nom du groupe de configuration", "namePlaceholder": "p. ex. acme-prod", - "add": "Ajouter un tenant", - "update": "Mettre à jour le tenant", + "add": "Ajouter un groupe de configuration", + "update": "Mettre à jour le groupe de configuration", "delete": "Supprimer", "edit": "Modifier", "cancel": "Annuler", @@ -2905,10 +2905,10 @@ "replaceFile": "Remplacer le fichier", "fileLoaded": "Fichier chargé", "invalidJson": "Impossible de lire le fichier comme JSON.", - "createError": "Impossible de créer le tenant. Veuillez réessayer.", - "updateError": "Impossible de mettre à jour le tenant. Veuillez réessayer.", - "createSuccess": "Tenant créé avec succès.", - "updateSuccess": "Tenant mis à jour avec succès." + "createError": "Impossible de créer le groupe de configuration. Veuillez réessayer.", + "updateError": "Impossible de mettre à jour le groupe de configuration. Veuillez réessayer.", + "createSuccess": "Groupe de configuration créé avec succès.", + "updateSuccess": "Groupe de configuration mis à jour avec succès." }, "google": { "sections": { @@ -3084,7 +3084,7 @@ "sections": { "prerequisite": { "title": "Prérequis · Utilisateur IAM", - "body": "Pour que cette intégration fonctionne, vous devez disposer d'un utilisateur IAM pour UTMStack avec la stratégie CloudWatchLogsReadOnlyAccess. Notez son ID de clé d'accès et sa clé d'accès secrète — vous les collerez dans le formulaire du tenant ci-dessous." + "body": "Pour que cette intégration fonctionne, vous devez disposer d'un utilisateur IAM pour UTMStack avec la stratégie CloudWatchLogsReadOnlyAccess. Notez son ID de clé d'accès et sa clé d'accès secrète — vous les collerez dans le formulaire du groupe de configuration ci-dessous." }, "createTrail": { "title": "1 · Créer un trail", diff --git a/frontend/src/shared/i18n/locales/it.json b/frontend/src/shared/i18n/locales/it.json index eac6d405d..36c656be2 100644 --- a/frontend/src/shared/i18n/locales/it.json +++ b/frontend/src/shared/i18n/locales/it.json @@ -2074,7 +2074,7 @@ "credentialsSection": "Connetti a UTMStack", "credentials": { "title": "Aggiungere le credenziali Sophos Central", - "body": "Inserire le credenziali appena create. È possibile aggiungere più di un account Sophos facendo clic su Add tenant." + "body": "Inserire le credenziali appena create. È possibile aggiungere più di un account Sophos facendo clic su Aggiungi gruppo di configurazione." }, "fields": { "clientId": { @@ -2109,7 +2109,7 @@ }, "fillForm": { "title": "6 · Compilare il modulo", - "body": "Fornire il client ID e il client secret a UTMStack. Se necessario, è possibile aggiungere più tenant Webroot." + "body": "Fornire il client ID e il client secret a UTMStack. Se necessario, è possibile aggiungere più gruppi di configurazione Webroot." }, "activate": { "title": "7 · Attivare", @@ -2193,7 +2193,7 @@ "credentialsSection": "Credenziali", "credentials": { "title": "Connettere il tenant Microsoft 365", - "body": "Inserire i dettagli dei passaggi precedenti. UTMStack verifica le credenziali prima del salvataggio. È possibile aggiungere più tenant." + "body": "Inserire i dettagli dei passaggi precedenti. UTMStack verifica le credenziali prima del salvataggio. È possibile aggiungere più gruppi di configurazione." }, "fields": { "tenantId": { @@ -2890,13 +2890,13 @@ "after2": "Da allora in poi, gli eventi vengono estratti ogni 1–5 minuti (dipende dall'API).", "after3": "L'integrazione appare sotto Origini dati con lo stato di estrazione attuale e il ritardo.", "tenants": { - "title": "Tenant configurati", - "empty": "Nessun tenant configurato. Aggiungi il primo qui sotto.", - "loading": "Caricamento tenant…", - "nameLabel": "Nome del tenant", + "title": "Gruppi di configurazione configurati", + "empty": "Nessun gruppo di configurazione. Aggiungi il primo qui sotto.", + "loading": "Caricamento gruppi di configurazione…", + "nameLabel": "Nome del gruppo di configurazione", "namePlaceholder": "es. acme-prod", - "add": "Aggiungi tenant", - "update": "Aggiorna tenant", + "add": "Aggiungi gruppo di configurazione", + "update": "Aggiorna gruppo di configurazione", "delete": "Elimina", "edit": "Modifica", "cancel": "Annulla", @@ -2905,10 +2905,10 @@ "replaceFile": "Sostituisci file", "fileLoaded": "File caricato", "invalidJson": "Impossibile interpretare il file come JSON.", - "createError": "Impossibile creare il tenant. Riprova.", - "updateError": "Impossibile aggiornare il tenant. Riprova.", - "createSuccess": "Tenant creato con successo.", - "updateSuccess": "Tenant aggiornato con successo." + "createError": "Impossibile creare il gruppo di configurazione. Riprova.", + "updateError": "Impossibile aggiornare il gruppo di configurazione. Riprova.", + "createSuccess": "Gruppo di configurazione creato con successo.", + "updateSuccess": "Gruppo di configurazione aggiornato con successo." }, "google": { "sections": { @@ -3084,7 +3084,7 @@ "sections": { "prerequisite": { "title": "Prerequisito · Utente IAM", - "body": "Per far funzionare questa integrazione, serve un utente IAM per UTMStack con la policy CloudWatchLogsReadOnlyAccess. Annota l'ID della chiave di accesso e la chiave segreta: le incollerai nel modulo del tenant qui sotto." + "body": "Per far funzionare questa integrazione, serve un utente IAM per UTMStack con la policy CloudWatchLogsReadOnlyAccess. Annota l'ID della chiave di accesso e la chiave segreta: le incollerai nel modulo del gruppo di configurazione qui sotto." }, "createTrail": { "title": "1 · Crea un trail", diff --git a/frontend/src/shared/i18n/locales/pt.json b/frontend/src/shared/i18n/locales/pt.json index e43687823..6ede9099b 100644 --- a/frontend/src/shared/i18n/locales/pt.json +++ b/frontend/src/shared/i18n/locales/pt.json @@ -1952,7 +1952,7 @@ "credentialsSection": "Credenciais", "credentials": { "title": "Conectar seu tenant do Microsoft 365", - "body": "Insira os dados das etapas acima. O UTMStack verifica as credenciais antes de salvá-las. Você pode adicionar múltiplos tenants." + "body": "Insira os dados das etapas acima. O UTMStack verifica as credenciais antes de salvá-las. Você pode adicionar múltiplos grupos de configuração." }, "fields": { "tenantId": { @@ -2141,7 +2141,7 @@ "credentialsSection": "Conectar ao UTMStack", "credentials": { "title": "Adicionar credenciais do Sophos Central", - "body": "Insira as credenciais que você acabou de criar. Você pode adicionar mais de uma conta Sophos clicando em Adicionar tenant." + "body": "Insira as credenciais que você acabou de criar. Você pode adicionar mais de uma conta Sophos clicando em Adicionar grupo de configuração." }, "fields": { "clientId": { @@ -2331,7 +2331,7 @@ }, "fillForm": { "title": "6 · Preencher o formulário", - "body": "Forneça o client ID e o client secret ao UTMStack. Você pode adicionar mais de um tenant do Webroot se necessário." + "body": "Forneça o client ID e o client secret ao UTMStack. Você pode adicionar mais de um grupo de configuração do Webroot se necessário." }, "activate": { "title": "7 · Ativar", @@ -2890,13 +2890,13 @@ "after2": "A partir de então, os eventos são buscados a cada 1–5 minutos (depende da API).", "after3": "A integração aparece em Fontes de dados com status atual de busca e atraso.", "tenants": { - "title": "Tenants configurados", - "empty": "Ainda não há tenants configurados. Adicione o primeiro abaixo.", - "loading": "Carregando tenants…", - "nameLabel": "Nome do tenant", + "title": "Grupos de configuração configurados", + "empty": "Ainda não há grupos de configuração. Adicione o primeiro abaixo.", + "loading": "Carregando grupos de configuração…", + "nameLabel": "Nome do grupo de configuração", "namePlaceholder": "p. ex. acme-prod", - "add": "Adicionar tenant", - "update": "Atualizar tenant", + "add": "Adicionar grupo de configuração", + "update": "Atualizar grupo de configuração", "delete": "Excluir", "edit": "Editar", "cancel": "Cancelar", @@ -2905,10 +2905,10 @@ "replaceFile": "Substituir arquivo", "fileLoaded": "Arquivo carregado", "invalidJson": "Não foi possível ler o arquivo como JSON.", - "createError": "Não foi possível criar o tenant. Tente novamente.", - "updateError": "Não foi possível atualizar o tenant. Tente novamente.", - "createSuccess": "Tenant criado com sucesso.", - "updateSuccess": "Tenant atualizado com sucesso." + "createError": "Não foi possível criar o grupo de configuração. Tente novamente.", + "updateError": "Não foi possível atualizar o grupo de configuração. Tente novamente.", + "createSuccess": "Grupo de configuração criado com sucesso.", + "updateSuccess": "Grupo de configuração atualizado com sucesso." }, "google": { "sections": { diff --git a/frontend/src/shared/i18n/locales/ru.json b/frontend/src/shared/i18n/locales/ru.json index 2d2bd6695..c64157ba9 100644 --- a/frontend/src/shared/i18n/locales/ru.json +++ b/frontend/src/shared/i18n/locales/ru.json @@ -1956,7 +1956,7 @@ "credentialsSection": "Подключение к UTMStack", "credentials": { "title": "Добавьте учётные данные Sophos Central", - "body": "Введите только что созданные учётные данные. Вы можете добавить несколько учётных записей Sophos, нажав «Add tenant»." + "body": "Введите только что созданные учётные данные. Вы можете добавить несколько учётных записей Sophos, нажав «Добавить группу конфигурации»." }, "fields": { "clientId": { @@ -1991,7 +1991,7 @@ }, "fillForm": { "title": "6 · Заполните форму", - "body": "Укажите Client ID и Client Secret в UTMStack. При необходимости вы можете добавить несколько тенантов Webroot." + "body": "Укажите Client ID и Client Secret в UTMStack. При необходимости вы можете добавить несколько групп конфигурации Webroot." }, "activate": { "title": "7 · Активация", @@ -2075,7 +2075,7 @@ "credentialsSection": "Учётные данные", "credentials": { "title": "Подключите тенант Microsoft 365", - "body": "Введите данные из шагов выше. UTMStack проверяет учётные данные перед сохранением. Вы можете добавить несколько тенантов." + "body": "Введите данные из шагов выше. UTMStack проверяет учётные данные перед сохранением. Вы можете добавить несколько групп конфигурации." }, "fields": { "tenantId": { @@ -2772,13 +2772,13 @@ "after2": "Впоследствии события извлекаются каждые 1–5 минут (зависит от API).", "after3": "Интеграция появляется в разделе Источники данных с текущим статусом извлечения и задержкой.", "tenants": { - "title": "Настроенные тенанты", - "empty": "Тенантов пока нет. Добавьте первый ниже.", - "loading": "Загрузка тенантов…", - "nameLabel": "Имя тенанта", + "title": "Настроенные группы конфигурации", + "empty": "Групп конфигурации пока нет. Добавьте первую ниже.", + "loading": "Загрузка групп конфигурации…", + "nameLabel": "Имя группы конфигурации", "namePlaceholder": "напр. acme-prod", - "add": "Добавить тенант", - "update": "Обновить тенант", + "add": "Добавить группу конфигурации", + "update": "Обновить группу конфигурации", "delete": "Удалить", "edit": "Изменить", "cancel": "Отмена", @@ -2787,10 +2787,10 @@ "replaceFile": "Заменить файл", "fileLoaded": "Файл загружен", "invalidJson": "Не удалось прочитать файл как JSON.", - "createError": "Не удалось создать тенант. Повторите попытку.", - "updateError": "Не удалось обновить тенант. Повторите попытку.", - "createSuccess": "Тенант успешно создан.", - "updateSuccess": "Тенант успешно обновлён." + "createError": "Не удалось создать группу конфигурации. Повторите попытку.", + "updateError": "Не удалось обновить группу конфигурации. Повторите попытку.", + "createSuccess": "Группа конфигурации успешно создана.", + "updateSuccess": "Группа конфигурации успешно обновлена." }, "google": { "sections": { @@ -2966,7 +2966,7 @@ "sections": { "prerequisite": { "title": "Требование · Пользователь IAM", - "body": "Чтобы эта интеграция работала, нужен пользователь IAM для UTMStack с политикой CloudWatchLogsReadOnlyAccess. Запишите ID ключа доступа и секретный ключ — вы вставите их в форму тенанта ниже." + "body": "Чтобы эта интеграция работала, нужен пользователь IAM для UTMStack с политикой CloudWatchLogsReadOnlyAccess. Запишите ID ключа доступа и секретный ключ — вы вставите их в форму группы конфигурации ниже." }, "createTrail": { "title": "1 · Создайте trail",