mirror of
https://github.com/fosrl/pangolin.git
synced 2026-09-02 01:09:03 +02:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c162fee910 | |||
| 55e1c6c270 | |||
| d33c7565bb | |||
| 4ad978d68a | |||
| 6f8a235630 | |||
| f26ba15b37 | |||
| 5d7c6449e1 | |||
| 1d0b65571a | |||
| a94107ccd1 | |||
| 72979d362a | |||
| c119104b6e | |||
| 1f0365eb27 | |||
| e51d4c98ac | |||
| be44c0606b | |||
| 140b08098b | |||
| 4c4c2fc249 | |||
| 0b92108f41 | |||
| 30321774e7 | |||
| 60ecc56841 | |||
| 261bd5fc29 | |||
| d54973ab4b | |||
| d126c73a51 | |||
| 487ff70ec6 | |||
| cb0fba5cad | |||
| 6cd818038c | |||
| 26c9d6941f | |||
| 0e17e5be97 | |||
| 8675ac44b7 | |||
| 1c6b62673b | |||
| 6eb5c75be1 | |||
| cda9ff0b4e | |||
| 5f38178154 | |||
| ab55e0a87f | |||
| 41f4cf66f8 | |||
| 6c8247b6c0 | |||
| 07c09ec617 | |||
| 573922c0b6 | |||
| ae516e57bf | |||
| c9b4776a07 | |||
| a0f0228d10 | |||
| a1066709c4 | |||
| 46a9ccc979 | |||
| 180b8236a6 | |||
| 96ca6c2d20 | |||
| 47c34f88b4 | |||
| 780d767a65 | |||
| c36cf698c1 | |||
| 22db0319c2 | |||
| 39722d30af | |||
| 8aef14cf9f | |||
| 7f94d99455 | |||
| 1f9e99219d | |||
| d00b9478a2 | |||
| 4ddf36ebcc | |||
| 28b32fe6f7 | |||
| adfb6003d9 | |||
| 6a5ecab013 | |||
| 2c197fab9f | |||
| 65e4fe91b9 | |||
| 52c078a489 | |||
| 195f67c6eb | |||
| 668a04bcd2 |
@@ -16,7 +16,7 @@ experimental:
|
|||||||
version: "{{.BadgerVersion}}"
|
version: "{{.BadgerVersion}}"
|
||||||
crowdsec: # CrowdSec plugin configuration added
|
crowdsec: # CrowdSec plugin configuration added
|
||||||
moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
|
moduleName: "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
|
||||||
version: "v1.4.4"
|
version: "v1.7.1"
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: "INFO"
|
level: "INFO"
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Научете повече за JMESPath",
|
"idpJmespathAboutDescriptionLink": "Научете повече за JMESPath",
|
||||||
"idpJmespathLabel": "Идентификатор на пътя",
|
"idpJmespathLabel": "Идентификатор на пътя",
|
||||||
"idpJmespathLabelDescription": "Пътят към идентификатора на потребителя в ID токена",
|
"idpJmespathLabelDescription": "Пътят към идентификатора на потребителя в ID токена",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Път за имейл (по избор)",
|
"idpJmespathEmailPathOptional": "Път за имейл (по избор)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Пътят до имейла на потребителя в ID токена",
|
"idpJmespathEmailPathOptionalDescription": "Пътят до имейла на потребителя в ID токена",
|
||||||
"idpJmespathNamePathOptional": "Път (по избор) на име",
|
"idpJmespathNamePathOptional": "Път (по избор) на име",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Търси…",
|
"search": "Търси…",
|
||||||
"searchPlaceholder": "Търсене...",
|
"searchPlaceholder": "Търсене...",
|
||||||
"emptySearchOptions": "Няма намерени опции",
|
"emptySearchOptions": "Няма намерени опции",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Създаване",
|
"create": "Създаване",
|
||||||
"orgs": "Организации",
|
"orgs": "Организации",
|
||||||
"loginError": "Възникна неочаквана грешка. Моля, опитайте отново.",
|
"loginError": "Възникна неочаквана грешка. Моля, опитайте отново.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Тип:",
|
"createDomainType": "Тип:",
|
||||||
"createDomainName": "Име:",
|
"createDomainName": "Име:",
|
||||||
"createDomainValue": "Стойност:",
|
"createDomainValue": "Стойност:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME записи",
|
"createDomainCnameRecords": "CNAME записи",
|
||||||
"createDomainARecords": "A записи",
|
"createDomainARecords": "A записи",
|
||||||
"createDomainRecordNumber": "Запис {number}",
|
"createDomainRecordNumber": "Запис {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Добавете CIDR диапазон (напр. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Добавете CIDR диапазон (напр. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Неуспешно зареждане на подмрежи",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Неуспешно зареждане на подмрежи",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Етикети за Предпочитания",
|
"remoteExitNodeNetworkingLabelsTitle": "Етикети за Предпочитания",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Сайтове с тези етикети ще бъдат принудени да се свържат чрез този отдалечен край.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Изберете етикети...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Изберете етикети...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Търсене на етикети...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Търсене на етикети...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Неуспешно зареждане на етикети",
|
"remoteExitNodeNetworkingLabelsLoadError": "Неуспешно зареждане на етикети",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Další informace o cestě JMESPath",
|
"idpJmespathAboutDescriptionLink": "Další informace o cestě JMESPath",
|
||||||
"idpJmespathLabel": "Cesta identifikátoru",
|
"idpJmespathLabel": "Cesta identifikátoru",
|
||||||
"idpJmespathLabelDescription": "Cesta k identifikátoru uživatele v tokenu ID",
|
"idpJmespathLabelDescription": "Cesta k identifikátoru uživatele v tokenu ID",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Cesta e-mailu (volitelné)",
|
"idpJmespathEmailPathOptional": "Cesta e-mailu (volitelné)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Cesta k e-mailu uživatele v ID tokenu",
|
"idpJmespathEmailPathOptionalDescription": "Cesta k e-mailu uživatele v ID tokenu",
|
||||||
"idpJmespathNamePathOptional": "Cesta k názvu (volitelné)",
|
"idpJmespathNamePathOptional": "Cesta k názvu (volitelné)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Vyhledávání…",
|
"search": "Vyhledávání…",
|
||||||
"searchPlaceholder": "Hledat...",
|
"searchPlaceholder": "Hledat...",
|
||||||
"emptySearchOptions": "Nebyly nalezeny žádné možnosti",
|
"emptySearchOptions": "Nebyly nalezeny žádné možnosti",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Vytvořit",
|
"create": "Vytvořit",
|
||||||
"orgs": "Organizace",
|
"orgs": "Organizace",
|
||||||
"loginError": "Došlo k neočekávané chybě. Zkuste to prosím znovu.",
|
"loginError": "Došlo k neočekávané chybě. Zkuste to prosím znovu.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Typ:",
|
"createDomainType": "Typ:",
|
||||||
"createDomainName": "Jméno:",
|
"createDomainName": "Jméno:",
|
||||||
"createDomainValue": "Hodnota:",
|
"createDomainValue": "Hodnota:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "Záznamy CNAME",
|
"createDomainCnameRecords": "Záznamy CNAME",
|
||||||
"createDomainARecords": "Záznamy",
|
"createDomainARecords": "Záznamy",
|
||||||
"createDomainRecordNumber": "Nahrát {number}",
|
"createDomainRecordNumber": "Nahrát {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Přidejte rozsah CIDR (např. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Přidejte rozsah CIDR (např. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Nepodařilo se načíst podsítě",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Nepodařilo se načíst podsítě",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Názvy preferencí",
|
"remoteExitNodeNetworkingLabelsTitle": "Názvy preferencí",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Weby s těmito názvy budou nuceny připojit se tímto vzdáleným výstupním uzlem.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Vyberte názvy...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Vyberte názvy...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Hledat názvy...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Hledat názvy...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Nepodařilo se načíst názvy",
|
"remoteExitNodeNetworkingLabelsLoadError": "Nepodařilo se načíst názvy",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Læs mere om JMESPath",
|
"idpJmespathAboutDescriptionLink": "Læs mere om JMESPath",
|
||||||
"idpJmespathLabel": "Identifikatorsti",
|
"idpJmespathLabel": "Identifikatorsti",
|
||||||
"idpJmespathLabelDescription": "Stien til brugeridentifikatoren i ID-tokenet",
|
"idpJmespathLabelDescription": "Stien til brugeridentifikatoren i ID-tokenet",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "E-mailsti (Valgfrit)",
|
"idpJmespathEmailPathOptional": "E-mailsti (Valgfrit)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Stien til brugerens e-mailadresse i ID-tokenet",
|
"idpJmespathEmailPathOptionalDescription": "Stien til brugerens e-mailadresse i ID-tokenet",
|
||||||
"idpJmespathNamePathOptional": "Navn Sti (Valgfrit)",
|
"idpJmespathNamePathOptional": "Navn Sti (Valgfrit)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Søg…",
|
"search": "Søg…",
|
||||||
"searchPlaceholder": "Søg...",
|
"searchPlaceholder": "Søg...",
|
||||||
"emptySearchOptions": "Ingen valg fundet",
|
"emptySearchOptions": "Ingen valg fundet",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Opret",
|
"create": "Opret",
|
||||||
"orgs": "Organisationer",
|
"orgs": "Organisationer",
|
||||||
"loginError": "Der opstod en uventet fejl. Prøv venligst igen.",
|
"loginError": "Der opstod en uventet fejl. Prøv venligst igen.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Type:",
|
"createDomainType": "Type:",
|
||||||
"createDomainName": "Navn:",
|
"createDomainName": "Navn:",
|
||||||
"createDomainValue": "Værdi:",
|
"createDomainValue": "Værdi:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME-poster",
|
"createDomainCnameRecords": "CNAME-poster",
|
||||||
"createDomainARecords": "A-poster",
|
"createDomainARecords": "A-poster",
|
||||||
"createDomainRecordNumber": "Post {number}",
|
"createDomainRecordNumber": "Post {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Tilføj et CIDR-område (f.eks. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Tilføj et CIDR-område (f.eks. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Kunne ikke indlæse subnets",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Kunne ikke indlæse subnets",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Præference Etiketter",
|
"remoteExitNodeNetworkingLabelsTitle": "Præference Etiketter",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Sites med disse etiketter vil blive tvunget til at oprette forbindelse gennem denne fjerne exit-node.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Vælg etiketter...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Vælg etiketter...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Søg efter etiketter...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Søg efter etiketter...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Kunne ikke indlæse etiketter",
|
"remoteExitNodeNetworkingLabelsLoadError": "Kunne ikke indlæse etiketter",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Mehr über JMESPath erfahren",
|
"idpJmespathAboutDescriptionLink": "Mehr über JMESPath erfahren",
|
||||||
"idpJmespathLabel": "Identifikationspfad",
|
"idpJmespathLabel": "Identifikationspfad",
|
||||||
"idpJmespathLabelDescription": "Der JMESPath zum Benutzeridentifikator im ID-Token",
|
"idpJmespathLabelDescription": "Der JMESPath zum Benutzeridentifikator im ID-Token",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "E-Mail-Pfad (Optional)",
|
"idpJmespathEmailPathOptional": "E-Mail-Pfad (Optional)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Der JMESPath zur E-Mail-Adresse des Benutzers im ID-Token",
|
"idpJmespathEmailPathOptionalDescription": "Der JMESPath zur E-Mail-Adresse des Benutzers im ID-Token",
|
||||||
"idpJmespathNamePathOptional": "Namenspfad (Optional)",
|
"idpJmespathNamePathOptional": "Namenspfad (Optional)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Suche…",
|
"search": "Suche…",
|
||||||
"searchPlaceholder": "Suche...",
|
"searchPlaceholder": "Suche...",
|
||||||
"emptySearchOptions": "Keine Optionen gefunden",
|
"emptySearchOptions": "Keine Optionen gefunden",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Erstellen",
|
"create": "Erstellen",
|
||||||
"orgs": "Organisationen",
|
"orgs": "Organisationen",
|
||||||
"loginError": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.",
|
"loginError": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Typ:",
|
"createDomainType": "Typ:",
|
||||||
"createDomainName": "Name:",
|
"createDomainName": "Name:",
|
||||||
"createDomainValue": "Wert:",
|
"createDomainValue": "Wert:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME-Einträge",
|
"createDomainCnameRecords": "CNAME-Einträge",
|
||||||
"createDomainARecords": "A-Aufzeichnungen",
|
"createDomainARecords": "A-Aufzeichnungen",
|
||||||
"createDomainRecordNumber": "Eintrag {number}",
|
"createDomainRecordNumber": "Eintrag {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Fügen Sie einen CIDR-Bereich hinzu (z.B. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Fügen Sie einen CIDR-Bereich hinzu (z.B. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Fehler beim Laden der Subnetze",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Fehler beim Laden der Subnetze",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Präferenzetiketten",
|
"remoteExitNodeNetworkingLabelsTitle": "Präferenzetiketten",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Standorte mit diesen Etiketten werden gezwungen, über diesen Remote Exit Node zu verbinden.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Etiketten auswählen...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Etiketten auswählen...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Etiketten suchen...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Etiketten suchen...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Fehler beim Laden der Etiketten",
|
"remoteExitNodeNetworkingLabelsLoadError": "Fehler beim Laden der Etiketten",
|
||||||
|
|||||||
@@ -1573,6 +1573,8 @@
|
|||||||
"search": "Search…",
|
"search": "Search…",
|
||||||
"searchPlaceholder": "Search...",
|
"searchPlaceholder": "Search...",
|
||||||
"emptySearchOptions": "No options found",
|
"emptySearchOptions": "No options found",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Create",
|
"create": "Create",
|
||||||
"orgs": "Organizations",
|
"orgs": "Organizations",
|
||||||
"loginError": "An unexpected error occurred. Please try again.",
|
"loginError": "An unexpected error occurred. Please try again.",
|
||||||
@@ -2596,6 +2598,7 @@
|
|||||||
"createDomainType": "Type:",
|
"createDomainType": "Type:",
|
||||||
"createDomainName": "Name:",
|
"createDomainName": "Name:",
|
||||||
"createDomainValue": "Value:",
|
"createDomainValue": "Value:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME Records",
|
"createDomainCnameRecords": "CNAME Records",
|
||||||
"createDomainARecords": "A Records",
|
"createDomainARecords": "A Records",
|
||||||
"createDomainRecordNumber": "Record {number}",
|
"createDomainRecordNumber": "Record {number}",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Más información sobre JMESPath",
|
"idpJmespathAboutDescriptionLink": "Más información sobre JMESPath",
|
||||||
"idpJmespathLabel": "Ruta del identificador",
|
"idpJmespathLabel": "Ruta del identificador",
|
||||||
"idpJmespathLabelDescription": "La ruta al identificador de usuario en el token de ID",
|
"idpJmespathLabelDescription": "La ruta al identificador de usuario en el token de ID",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Ruta de correo (opcional)",
|
"idpJmespathEmailPathOptional": "Ruta de correo (opcional)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "La ruta al correo electrónico del usuario en el token de ID",
|
"idpJmespathEmailPathOptionalDescription": "La ruta al correo electrónico del usuario en el token de ID",
|
||||||
"idpJmespathNamePathOptional": "Ruta del nombre (opcional)",
|
"idpJmespathNamePathOptional": "Ruta del nombre (opcional)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Buscar…",
|
"search": "Buscar…",
|
||||||
"searchPlaceholder": "Buscar...",
|
"searchPlaceholder": "Buscar...",
|
||||||
"emptySearchOptions": "No se encontraron opciones",
|
"emptySearchOptions": "No se encontraron opciones",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Crear",
|
"create": "Crear",
|
||||||
"orgs": "Organizaciones",
|
"orgs": "Organizaciones",
|
||||||
"loginError": "Ocurrió un error inesperado. Por favor, inténtelo de nuevo.",
|
"loginError": "Ocurrió un error inesperado. Por favor, inténtelo de nuevo.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Tipo:",
|
"createDomainType": "Tipo:",
|
||||||
"createDomainName": "Nombre:",
|
"createDomainName": "Nombre:",
|
||||||
"createDomainValue": "Valor:",
|
"createDomainValue": "Valor:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "Registros CNAME",
|
"createDomainCnameRecords": "Registros CNAME",
|
||||||
"createDomainARecords": "Registros A",
|
"createDomainARecords": "Registros A",
|
||||||
"createDomainRecordNumber": "Registro {number}",
|
"createDomainRecordNumber": "Registro {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Añadir un rango CIDR (e.g. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Añadir un rango CIDR (e.g. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Error al cargar las subredes",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Error al cargar las subredes",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Etiquetas de Preferencias",
|
"remoteExitNodeNetworkingLabelsTitle": "Etiquetas de Preferencias",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Los sitios con estas etiquetas se verán obligados a conectarse a través de este nodo de salida remoto.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Seleccionar etiquetas...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Seleccionar etiquetas...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Buscar etiquetas...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Buscar etiquetas...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Error al cargar las etiquetas",
|
"remoteExitNodeNetworkingLabelsLoadError": "Error al cargar las etiquetas",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "En savoir plus sur JMESPath",
|
"idpJmespathAboutDescriptionLink": "En savoir plus sur JMESPath",
|
||||||
"idpJmespathLabel": "Chemin d'identification",
|
"idpJmespathLabel": "Chemin d'identification",
|
||||||
"idpJmespathLabelDescription": "Le JMESPath vers l'identifiant de l'utilisateur dans le jeton ID",
|
"idpJmespathLabelDescription": "Le JMESPath vers l'identifiant de l'utilisateur dans le jeton ID",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Chemin de l'email (Optionnel)",
|
"idpJmespathEmailPathOptional": "Chemin de l'email (Optionnel)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Le JMESPath vers l'email de l'utilisateur dans le jeton ID",
|
"idpJmespathEmailPathOptionalDescription": "Le JMESPath vers l'email de l'utilisateur dans le jeton ID",
|
||||||
"idpJmespathNamePathOptional": "Chemin du nom (Optionnel)",
|
"idpJmespathNamePathOptional": "Chemin du nom (Optionnel)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Rechercher…",
|
"search": "Rechercher…",
|
||||||
"searchPlaceholder": "Recherche...",
|
"searchPlaceholder": "Recherche...",
|
||||||
"emptySearchOptions": "Aucune option trouvée",
|
"emptySearchOptions": "Aucune option trouvée",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Créer",
|
"create": "Créer",
|
||||||
"orgs": "Organisations",
|
"orgs": "Organisations",
|
||||||
"loginError": "Une erreur inattendue s'est produite. Veuillez réessayer.",
|
"loginError": "Une erreur inattendue s'est produite. Veuillez réessayer.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Type :",
|
"createDomainType": "Type :",
|
||||||
"createDomainName": "Nom :",
|
"createDomainName": "Nom :",
|
||||||
"createDomainValue": "Valeur :",
|
"createDomainValue": "Valeur :",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "Enregistrements CNAME",
|
"createDomainCnameRecords": "Enregistrements CNAME",
|
||||||
"createDomainARecords": "Enregistrements A",
|
"createDomainARecords": "Enregistrements A",
|
||||||
"createDomainRecordNumber": "Enregistrement {number}",
|
"createDomainRecordNumber": "Enregistrement {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Ajouter une plage CIDR (par exemple 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Ajouter une plage CIDR (par exemple 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Échec du chargement des sous-réseaux",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Échec du chargement des sous-réseaux",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Étiquettes de préférences",
|
"remoteExitNodeNetworkingLabelsTitle": "Étiquettes de préférences",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Les sites avec ces étiquettes devront se connecter via ce nœud de sortie distant.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Sélectionner des étiquettes...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Sélectionner des étiquettes...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Chercher des étiquettes...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Chercher des étiquettes...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Échec du chargement des étiquettes",
|
"remoteExitNodeNetworkingLabelsLoadError": "Échec du chargement des étiquettes",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Scopri di più su JMESPath",
|
"idpJmespathAboutDescriptionLink": "Scopri di più su JMESPath",
|
||||||
"idpJmespathLabel": "Percorso Identificativo",
|
"idpJmespathLabel": "Percorso Identificativo",
|
||||||
"idpJmespathLabelDescription": "Il JMESPath per l'identificatore dell'utente nel token ID",
|
"idpJmespathLabelDescription": "Il JMESPath per l'identificatore dell'utente nel token ID",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Percorso Email (Opzionale)",
|
"idpJmespathEmailPathOptional": "Percorso Email (Opzionale)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Il JMESPath per l'email dell'utente nel token ID",
|
"idpJmespathEmailPathOptionalDescription": "Il JMESPath per l'email dell'utente nel token ID",
|
||||||
"idpJmespathNamePathOptional": "Percorso Nome (Opzionale)",
|
"idpJmespathNamePathOptional": "Percorso Nome (Opzionale)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Cerca…",
|
"search": "Cerca…",
|
||||||
"searchPlaceholder": "Cerca...",
|
"searchPlaceholder": "Cerca...",
|
||||||
"emptySearchOptions": "Nessuna opzione trovata",
|
"emptySearchOptions": "Nessuna opzione trovata",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Crea",
|
"create": "Crea",
|
||||||
"orgs": "Organizzazioni",
|
"orgs": "Organizzazioni",
|
||||||
"loginError": "Si è verificato un errore imprevisto. Riprova.",
|
"loginError": "Si è verificato un errore imprevisto. Riprova.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Tipo:",
|
"createDomainType": "Tipo:",
|
||||||
"createDomainName": "Nome:",
|
"createDomainName": "Nome:",
|
||||||
"createDomainValue": "Valore:",
|
"createDomainValue": "Valore:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "Record CNAME",
|
"createDomainCnameRecords": "Record CNAME",
|
||||||
"createDomainARecords": "Record A",
|
"createDomainARecords": "Record A",
|
||||||
"createDomainRecordNumber": "Record {number}",
|
"createDomainRecordNumber": "Record {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Aggiungi un intervallo CIDR (ad esempio 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Aggiungi un intervallo CIDR (ad esempio 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Caricamento sottoreti fallito",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Caricamento sottoreti fallito",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Etichette Preferenze",
|
"remoteExitNodeNetworkingLabelsTitle": "Etichette Preferenze",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "I siti con queste etichette saranno collegati attraverso questo nodo di uscita remoto.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Seleziona etichette...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Seleziona etichette...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Cerca etichette...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Cerca etichette...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Caricamento etichette fallito",
|
"remoteExitNodeNetworkingLabelsLoadError": "Caricamento etichette fallito",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "JMESPath에 대해 더 알아보기",
|
"idpJmespathAboutDescriptionLink": "JMESPath에 대해 더 알아보기",
|
||||||
"idpJmespathLabel": "식별자 경로",
|
"idpJmespathLabel": "식별자 경로",
|
||||||
"idpJmespathLabelDescription": "ID 토큰에서 사용자 식별자에 대한 경로",
|
"idpJmespathLabelDescription": "ID 토큰에서 사용자 식별자에 대한 경로",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "이메일 경로 (선택 사항)",
|
"idpJmespathEmailPathOptional": "이메일 경로 (선택 사항)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "ID 토큰에서 사용자의 이메일 경로",
|
"idpJmespathEmailPathOptionalDescription": "ID 토큰에서 사용자의 이메일 경로",
|
||||||
"idpJmespathNamePathOptional": "이름 경로 (선택 사항)",
|
"idpJmespathNamePathOptional": "이름 경로 (선택 사항)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "검색…",
|
"search": "검색…",
|
||||||
"searchPlaceholder": "검색...",
|
"searchPlaceholder": "검색...",
|
||||||
"emptySearchOptions": "옵션이 없습니다",
|
"emptySearchOptions": "옵션이 없습니다",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "생성",
|
"create": "생성",
|
||||||
"orgs": "조직",
|
"orgs": "조직",
|
||||||
"loginError": "예기치 않은 오류가 발생했습니다. 다시 시도해주세요.",
|
"loginError": "예기치 않은 오류가 발생했습니다. 다시 시도해주세요.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "유형:",
|
"createDomainType": "유형:",
|
||||||
"createDomainName": "이름:",
|
"createDomainName": "이름:",
|
||||||
"createDomainValue": "값:",
|
"createDomainValue": "값:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME 레코드",
|
"createDomainCnameRecords": "CNAME 레코드",
|
||||||
"createDomainARecords": "A 레코드",
|
"createDomainARecords": "A 레코드",
|
||||||
"createDomainRecordNumber": "레코드 {number}",
|
"createDomainRecordNumber": "레코드 {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "CIDR 범위 추가 (예: 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "CIDR 범위 추가 (예: 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "서브넷 로드 실패",
|
"remoteExitNodeNetworkingSubnetsLoadError": "서브넷 로드 실패",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "우선순위 레이블",
|
"remoteExitNodeNetworkingLabelsTitle": "우선순위 레이블",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "이 레이블이 있는 사이트는 이 원격 출구 노드를 통해 연결됩니다.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "레이블 선택...",
|
"remoteExitNodeNetworkingLabelsButtonText": "레이블 선택...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "레이블 검색...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "레이블 검색...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "레이블 로드 실패",
|
"remoteExitNodeNetworkingLabelsLoadError": "레이블 로드 실패",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Lær mer om JMESPath",
|
"idpJmespathAboutDescriptionLink": "Lær mer om JMESPath",
|
||||||
"idpJmespathLabel": "Identifikatorsti",
|
"idpJmespathLabel": "Identifikatorsti",
|
||||||
"idpJmespathLabelDescription": "Stien til brukeridentifikatoren i ID-tokenet",
|
"idpJmespathLabelDescription": "Stien til brukeridentifikatoren i ID-tokenet",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "E-poststi (Valgfritt)",
|
"idpJmespathEmailPathOptional": "E-poststi (Valgfritt)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Stien til brukerens e-postadresse i ID-tokenet",
|
"idpJmespathEmailPathOptionalDescription": "Stien til brukerens e-postadresse i ID-tokenet",
|
||||||
"idpJmespathNamePathOptional": "Navn Sti (Valgfritt)",
|
"idpJmespathNamePathOptional": "Navn Sti (Valgfritt)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Søk…",
|
"search": "Søk…",
|
||||||
"searchPlaceholder": "Søk...",
|
"searchPlaceholder": "Søk...",
|
||||||
"emptySearchOptions": "Ingen valg funnet",
|
"emptySearchOptions": "Ingen valg funnet",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Opprett",
|
"create": "Opprett",
|
||||||
"orgs": "Organisasjoner",
|
"orgs": "Organisasjoner",
|
||||||
"loginError": "En uventet feil oppstod. Vennligst prøv igjen.",
|
"loginError": "En uventet feil oppstod. Vennligst prøv igjen.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Type:",
|
"createDomainType": "Type:",
|
||||||
"createDomainName": "Navn:",
|
"createDomainName": "Navn:",
|
||||||
"createDomainValue": "Verdi:",
|
"createDomainValue": "Verdi:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME-oppføringer",
|
"createDomainCnameRecords": "CNAME-oppføringer",
|
||||||
"createDomainARecords": "A-oppføringer",
|
"createDomainARecords": "A-oppføringer",
|
||||||
"createDomainRecordNumber": "Oppføring {number}",
|
"createDomainRecordNumber": "Oppføring {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Legg til et CIDR-område (f.eks. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Legg til et CIDR-område (f.eks. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Feil ved lasting av subnett",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Feil ved lasting av subnett",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Preferanseetiketter",
|
"remoteExitNodeNetworkingLabelsTitle": "Preferanseetiketter",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Områder med disse etikettene vil bli tvunget til å koble gjennom denne fjerne utgangsnoden.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Velg etiketter...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Velg etiketter...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Søk etiketter...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Søk etiketter...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Feil ved lasting av etiketter",
|
"remoteExitNodeNetworkingLabelsLoadError": "Feil ved lasting av etiketter",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Meer informatie over JMESPath",
|
"idpJmespathAboutDescriptionLink": "Meer informatie over JMESPath",
|
||||||
"idpJmespathLabel": "ID pad",
|
"idpJmespathLabel": "ID pad",
|
||||||
"idpJmespathLabelDescription": "Het pad naar het gebruiker-id in het ID-token",
|
"idpJmespathLabelDescription": "Het pad naar het gebruiker-id in het ID-token",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "E-mail pad (optioneel)",
|
"idpJmespathEmailPathOptional": "E-mail pad (optioneel)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Het pad naar het e-mailadres van de gebruiker in het ID-token",
|
"idpJmespathEmailPathOptionalDescription": "Het pad naar het e-mailadres van de gebruiker in het ID-token",
|
||||||
"idpJmespathNamePathOptional": "Naam pad (optioneel)",
|
"idpJmespathNamePathOptional": "Naam pad (optioneel)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Zoeken…",
|
"search": "Zoeken…",
|
||||||
"searchPlaceholder": "Zoeken...",
|
"searchPlaceholder": "Zoeken...",
|
||||||
"emptySearchOptions": "Geen opties gevonden",
|
"emptySearchOptions": "Geen opties gevonden",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Aanmaken",
|
"create": "Aanmaken",
|
||||||
"orgs": "Organisaties",
|
"orgs": "Organisaties",
|
||||||
"loginError": "Er is een onverwachte fout opgetreden. Probeer het opnieuw.",
|
"loginError": "Er is een onverwachte fout opgetreden. Probeer het opnieuw.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Type:",
|
"createDomainType": "Type:",
|
||||||
"createDomainName": "Naam:",
|
"createDomainName": "Naam:",
|
||||||
"createDomainValue": "Waarde:",
|
"createDomainValue": "Waarde:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME-records",
|
"createDomainCnameRecords": "CNAME-records",
|
||||||
"createDomainARecords": "A Records",
|
"createDomainARecords": "A Records",
|
||||||
"createDomainRecordNumber": "Record {number}",
|
"createDomainRecordNumber": "Record {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Voeg een CIDR-bereik toe (bijv. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Voeg een CIDR-bereik toe (bijv. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Kon subnets niet laden",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Kon subnets niet laden",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Voorkeurslabels",
|
"remoteExitNodeNetworkingLabelsTitle": "Voorkeurslabels",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Sites met deze labels worden verplicht om verbinding te maken via dit externe exit-knooppunt.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Selecteer labels...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Selecteer labels...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Labels zoeken...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Labels zoeken...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Kon labels niet laden",
|
"remoteExitNodeNetworkingLabelsLoadError": "Kon labels niet laden",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Dowiedz się więcej o JMESPath",
|
"idpJmespathAboutDescriptionLink": "Dowiedz się więcej o JMESPath",
|
||||||
"idpJmespathLabel": "Ścieżka identyfikatora",
|
"idpJmespathLabel": "Ścieżka identyfikatora",
|
||||||
"idpJmespathLabelDescription": "JMESPath do identyfikatora użytkownika w tokenie ID",
|
"idpJmespathLabelDescription": "JMESPath do identyfikatora użytkownika w tokenie ID",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Ścieżka email (Opcjonalnie)",
|
"idpJmespathEmailPathOptional": "Ścieżka email (Opcjonalnie)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "JMESPath do emaila użytkownika w tokenie ID",
|
"idpJmespathEmailPathOptionalDescription": "JMESPath do emaila użytkownika w tokenie ID",
|
||||||
"idpJmespathNamePathOptional": "Ścieżka nazwy (Opcjonalnie)",
|
"idpJmespathNamePathOptional": "Ścieżka nazwy (Opcjonalnie)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Szukaj…",
|
"search": "Szukaj…",
|
||||||
"searchPlaceholder": "Szukaj...",
|
"searchPlaceholder": "Szukaj...",
|
||||||
"emptySearchOptions": "Nie znaleziono opcji",
|
"emptySearchOptions": "Nie znaleziono opcji",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Utwórz",
|
"create": "Utwórz",
|
||||||
"orgs": "Organizacje",
|
"orgs": "Organizacje",
|
||||||
"loginError": "Wystąpił nieoczekiwany błąd. Spróbuj ponownie.",
|
"loginError": "Wystąpił nieoczekiwany błąd. Spróbuj ponownie.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Typ:",
|
"createDomainType": "Typ:",
|
||||||
"createDomainName": "Nazwa:",
|
"createDomainName": "Nazwa:",
|
||||||
"createDomainValue": "Wartość:",
|
"createDomainValue": "Wartość:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "Rekordy CNAME",
|
"createDomainCnameRecords": "Rekordy CNAME",
|
||||||
"createDomainARecords": "Rekordy A",
|
"createDomainARecords": "Rekordy A",
|
||||||
"createDomainRecordNumber": "Rekord {number}",
|
"createDomainRecordNumber": "Rekord {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Dodaj zakres CIDR (np. 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Dodaj zakres CIDR (np. 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Nie udało się załadować podsieci",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Nie udało się załadować podsieci",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Etykiety preferencji",
|
"remoteExitNodeNetworkingLabelsTitle": "Etykiety preferencji",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Strony z tymi etykietami będą zmuszone do połączenia się przez ten zdalny węzeł wyjściowy.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Wybierz etykiety...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Wybierz etykiety...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Szukaj etykiet...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Szukaj etykiet...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Nie udało się załadować etykiet",
|
"remoteExitNodeNetworkingLabelsLoadError": "Nie udało się załadować etykiet",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Saiba mais sobre JMESPath",
|
"idpJmespathAboutDescriptionLink": "Saiba mais sobre JMESPath",
|
||||||
"idpJmespathLabel": "Caminho do Identificador",
|
"idpJmespathLabel": "Caminho do Identificador",
|
||||||
"idpJmespathLabelDescription": "O JMESPath para o identificador do utilizador no token ID",
|
"idpJmespathLabelDescription": "O JMESPath para o identificador do utilizador no token ID",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Caminho do Email (Opcional)",
|
"idpJmespathEmailPathOptional": "Caminho do Email (Opcional)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "O JMESPath para o email do utilizador no token ID",
|
"idpJmespathEmailPathOptionalDescription": "O JMESPath para o email do utilizador no token ID",
|
||||||
"idpJmespathNamePathOptional": "Caminho do Nome (Opcional)",
|
"idpJmespathNamePathOptional": "Caminho do Nome (Opcional)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Pesquisar…",
|
"search": "Pesquisar…",
|
||||||
"searchPlaceholder": "Buscar...",
|
"searchPlaceholder": "Buscar...",
|
||||||
"emptySearchOptions": "Nenhuma opção encontrada",
|
"emptySearchOptions": "Nenhuma opção encontrada",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Criar",
|
"create": "Criar",
|
||||||
"orgs": "Organizações",
|
"orgs": "Organizações",
|
||||||
"loginError": "Ocorreu um erro inesperado. Por favor, tente novamente.",
|
"loginError": "Ocorreu um erro inesperado. Por favor, tente novamente.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Tipo:",
|
"createDomainType": "Tipo:",
|
||||||
"createDomainName": "Nome:",
|
"createDomainName": "Nome:",
|
||||||
"createDomainValue": "Valor:",
|
"createDomainValue": "Valor:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "Registros CNAME",
|
"createDomainCnameRecords": "Registros CNAME",
|
||||||
"createDomainARecords": "Registros A",
|
"createDomainARecords": "Registros A",
|
||||||
"createDomainRecordNumber": "Registrar {number}",
|
"createDomainRecordNumber": "Registrar {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Adicione um intervalo de CIDR (por exemplo, 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Adicione um intervalo de CIDR (por exemplo, 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Falha ao carregar sub-redes",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Falha ao carregar sub-redes",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Etiquetas de Preferência",
|
"remoteExitNodeNetworkingLabelsTitle": "Etiquetas de Preferência",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Os sites com essas etiquetas serão forçados a se conectar através deste nó de saída remoto.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Selecionar etiquetas...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Selecionar etiquetas...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Pesquisar etiquetas...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Pesquisar etiquetas...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Falha ao carregar etiquetas",
|
"remoteExitNodeNetworkingLabelsLoadError": "Falha ao carregar etiquetas",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "Узнать больше о JMESPath",
|
"idpJmespathAboutDescriptionLink": "Узнать больше о JMESPath",
|
||||||
"idpJmespathLabel": "Путь идентификатора",
|
"idpJmespathLabel": "Путь идентификатора",
|
||||||
"idpJmespathLabelDescription": "Путь к идентификатору пользователя в ID токене",
|
"idpJmespathLabelDescription": "Путь к идентификатору пользователя в ID токене",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "Путь к email (необязательно)",
|
"idpJmespathEmailPathOptional": "Путь к email (необязательно)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "Путь к email пользователя в ID токене",
|
"idpJmespathEmailPathOptionalDescription": "Путь к email пользователя в ID токене",
|
||||||
"idpJmespathNamePathOptional": "Путь к имени (необязательно)",
|
"idpJmespathNamePathOptional": "Путь к имени (необязательно)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Поиск…",
|
"search": "Поиск…",
|
||||||
"searchPlaceholder": "Поиск...",
|
"searchPlaceholder": "Поиск...",
|
||||||
"emptySearchOptions": "Опции не найдены",
|
"emptySearchOptions": "Опции не найдены",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Создать",
|
"create": "Создать",
|
||||||
"orgs": "Организации",
|
"orgs": "Организации",
|
||||||
"loginError": "Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз.",
|
"loginError": "Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Тип:",
|
"createDomainType": "Тип:",
|
||||||
"createDomainName": "Имя:",
|
"createDomainName": "Имя:",
|
||||||
"createDomainValue": "Значение:",
|
"createDomainValue": "Значение:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME Записи",
|
"createDomainCnameRecords": "CNAME Записи",
|
||||||
"createDomainARecords": "A Записи",
|
"createDomainARecords": "A Записи",
|
||||||
"createDomainRecordNumber": "Запись {number}",
|
"createDomainRecordNumber": "Запись {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Добавить диапазон CIDR (например, 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Добавить диапазон CIDR (например, 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Не удалось загрузить подсети",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Не удалось загрузить подсети",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Этикетки предпочтений",
|
"remoteExitNodeNetworkingLabelsTitle": "Этикетки предпочтений",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Сайты с этими метками будут обязаны подключаться через этот удаленный узел выхода.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Выберите метки...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Выберите метки...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Поиск меток...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Поиск меток...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Не удалось загрузить метки",
|
"remoteExitNodeNetworkingLabelsLoadError": "Не удалось загрузить метки",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "JMESPath hakkında daha fazla bilgi edinin",
|
"idpJmespathAboutDescriptionLink": "JMESPath hakkında daha fazla bilgi edinin",
|
||||||
"idpJmespathLabel": "Tanımlayıcı Yolu",
|
"idpJmespathLabel": "Tanımlayıcı Yolu",
|
||||||
"idpJmespathLabelDescription": "The JMESPath to the user identifier in the ID token",
|
"idpJmespathLabelDescription": "The JMESPath to the user identifier in the ID token",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "E-posta Yolu (İsteğe Bağlı)",
|
"idpJmespathEmailPathOptional": "E-posta Yolu (İsteğe Bağlı)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "The JMESPath to the user's email in the ID token",
|
"idpJmespathEmailPathOptionalDescription": "The JMESPath to the user's email in the ID token",
|
||||||
"idpJmespathNamePathOptional": "Ad Yolu (İsteğe Bağlı)",
|
"idpJmespathNamePathOptional": "Ad Yolu (İsteğe Bağlı)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "Ara…",
|
"search": "Ara…",
|
||||||
"searchPlaceholder": "Ara...",
|
"searchPlaceholder": "Ara...",
|
||||||
"emptySearchOptions": "Seçenek bulunamadı",
|
"emptySearchOptions": "Seçenek bulunamadı",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "Oluştur",
|
"create": "Oluştur",
|
||||||
"orgs": "Organizasyonlar",
|
"orgs": "Organizasyonlar",
|
||||||
"loginError": "Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin.",
|
"loginError": "Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin.",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "Tür:",
|
"createDomainType": "Tür:",
|
||||||
"createDomainName": "Ad:",
|
"createDomainName": "Ad:",
|
||||||
"createDomainValue": "Değer:",
|
"createDomainValue": "Değer:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME Kayıtları",
|
"createDomainCnameRecords": "CNAME Kayıtları",
|
||||||
"createDomainARecords": "A Kayıtları",
|
"createDomainARecords": "A Kayıtları",
|
||||||
"createDomainRecordNumber": "Kayıt {number}",
|
"createDomainRecordNumber": "Kayıt {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "Bir CIDR aralığı ekle (örneğin, 10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "Bir CIDR aralığı ekle (örneğin, 10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "Alt ağlar yüklenemedi",
|
"remoteExitNodeNetworkingSubnetsLoadError": "Alt ağlar yüklenemedi",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "Tercih Etiketleri",
|
"remoteExitNodeNetworkingLabelsTitle": "Tercih Etiketleri",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "Bu etiketlere sahip siteler, bu uzak çıkış düğümü üzerinden bağlantı kurmaya zorlanacaktır.",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "Etiketleri seç...",
|
"remoteExitNodeNetworkingLabelsButtonText": "Etiketleri seç...",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Etiketleri ara...",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "Etiketleri ara...",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "Etiketler yüklenemedi",
|
"remoteExitNodeNetworkingLabelsLoadError": "Etiketler yüklenemedi",
|
||||||
|
|||||||
+8
-1
@@ -1176,6 +1176,10 @@
|
|||||||
"idpJmespathAboutDescriptionLink": "了解更多 JMESPath 信息",
|
"idpJmespathAboutDescriptionLink": "了解更多 JMESPath 信息",
|
||||||
"idpJmespathLabel": "标识符路径",
|
"idpJmespathLabel": "标识符路径",
|
||||||
"idpJmespathLabelDescription": "ID 令牌中用户标识符的路径",
|
"idpJmespathLabelDescription": "ID 令牌中用户标识符的路径",
|
||||||
|
"idpIdentifierChangeTitle": "Identifier Path Change Warning",
|
||||||
|
"idpIdentifierChangeDescription": "You are about to change the identifier path. This will affect how existing users are mapped. Users who previously signed in through this identity provider may no longer be recognized as the same users.",
|
||||||
|
"idpIdentifierChangeConfirmMessage": "I confirm",
|
||||||
|
"idpIdentifierChangeWarningText": "This will affect how existing users are mapped",
|
||||||
"idpJmespathEmailPathOptional": "邮箱路径(可选)",
|
"idpJmespathEmailPathOptional": "邮箱路径(可选)",
|
||||||
"idpJmespathEmailPathOptionalDescription": "ID 令牌中用户邮箱的路径",
|
"idpJmespathEmailPathOptionalDescription": "ID 令牌中用户邮箱的路径",
|
||||||
"idpJmespathNamePathOptional": "用户名路径(可选)",
|
"idpJmespathNamePathOptional": "用户名路径(可选)",
|
||||||
@@ -1573,6 +1577,8 @@
|
|||||||
"search": "搜索…",
|
"search": "搜索…",
|
||||||
"searchPlaceholder": "搜索...",
|
"searchPlaceholder": "搜索...",
|
||||||
"emptySearchOptions": "未找到选项",
|
"emptySearchOptions": "未找到选项",
|
||||||
|
"ipFilterSearchPlaceholder": "Enter an IP address…",
|
||||||
|
"ipFilterEmptyMessage": "Enter an IP address to filter by",
|
||||||
"create": "创建",
|
"create": "创建",
|
||||||
"orgs": "组织",
|
"orgs": "组织",
|
||||||
"loginError": "发生意外错误。请重试。",
|
"loginError": "发生意外错误。请重试。",
|
||||||
@@ -2596,6 +2602,7 @@
|
|||||||
"createDomainType": "类型:",
|
"createDomainType": "类型:",
|
||||||
"createDomainName": "名称:",
|
"createDomainName": "名称:",
|
||||||
"createDomainValue": "值:",
|
"createDomainValue": "值:",
|
||||||
|
"multiSelectFilterCount": "{count} selected",
|
||||||
"createDomainCnameRecords": "CNAME 记录",
|
"createDomainCnameRecords": "CNAME 记录",
|
||||||
"createDomainARecords": "A记录",
|
"createDomainARecords": "A记录",
|
||||||
"createDomainRecordNumber": "记录 {number}",
|
"createDomainRecordNumber": "记录 {number}",
|
||||||
@@ -2993,7 +3000,7 @@
|
|||||||
"remoteExitNodeNetworkingSubnetsPlaceholder": "添加CIDR范围(例如10.0.0.0/8)",
|
"remoteExitNodeNetworkingSubnetsPlaceholder": "添加CIDR范围(例如10.0.0.0/8)",
|
||||||
"remoteExitNodeNetworkingSubnetsLoadError": "无法加载子网",
|
"remoteExitNodeNetworkingSubnetsLoadError": "无法加载子网",
|
||||||
"remoteExitNodeNetworkingLabelsTitle": "首选标签",
|
"remoteExitNodeNetworkingLabelsTitle": "首选标签",
|
||||||
"remoteExitNodeNetworkingLabelsDescription": "拥有这些标签的站点将强制通过此远程出口节点连接。",
|
"remoteExitNodeNetworkingLabelsDescription": "Sites with these labels will prefer to connect through this remote exit node.",
|
||||||
"remoteExitNodeNetworkingLabelsButtonText": "选择标签……",
|
"remoteExitNodeNetworkingLabelsButtonText": "选择标签……",
|
||||||
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "搜索标签……",
|
"remoteExitNodeNetworkingLabelsSearchPlaceholder": "搜索标签……",
|
||||||
"remoteExitNodeNetworkingLabelsLoadError": "无法加载标签",
|
"remoteExitNodeNetworkingLabelsLoadError": "无法加载标签",
|
||||||
|
|||||||
@@ -88,7 +88,27 @@ export const queryAccessAuditLogsQuery = z.object({
|
|||||||
.optional()
|
.optional()
|
||||||
.default("0")
|
.default("0")
|
||||||
.transform(Number)
|
.transform(Number)
|
||||||
.pipe(z.int().nonnegative())
|
.pipe(z.int().nonnegative()),
|
||||||
|
ip: z
|
||||||
|
.preprocess((val) => {
|
||||||
|
if (val === undefined || val === null || val === "") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
// the array is returned as this
|
||||||
|
if (typeof val === "string") {
|
||||||
|
return val.split(",");
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, z.array(z.string()))
|
||||||
|
.optional()
|
||||||
|
.catch([])
|
||||||
|
.openapi({
|
||||||
|
type: "array",
|
||||||
|
description: "Filter by IP adresses"
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const queryAccessAuditLogsParams = z.object({
|
export const queryAccessAuditLogsParams = z.object({
|
||||||
@@ -134,6 +154,9 @@ function getWhere(data: Q) {
|
|||||||
data.type ? eq(accessAuditLog.type, data.type) : undefined,
|
data.type ? eq(accessAuditLog.type, data.type) : undefined,
|
||||||
data.action !== undefined
|
data.action !== undefined
|
||||||
? eq(accessAuditLog.action, data.action)
|
? eq(accessAuditLog.action, data.action)
|
||||||
|
: undefined,
|
||||||
|
data.ip && data.ip.length > 0
|
||||||
|
? inArray(accessAuditLog.ip, data.ip)
|
||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,10 @@ import {
|
|||||||
handleRemoteExitNodePingMessage
|
handleRemoteExitNodePingMessage
|
||||||
} from "#private/routers/remoteExitNode";
|
} from "#private/routers/remoteExitNode";
|
||||||
import { MessageHandler } from "@server/routers/ws";
|
import { MessageHandler } from "@server/routers/ws";
|
||||||
import {
|
import { handleConnectionLogMessage } from "#private/routers/newt";
|
||||||
handleConnectionLogMessage,
|
|
||||||
} from "#private/routers/newt";
|
|
||||||
|
|
||||||
export const messageHandlers: Record<string, MessageHandler> = {
|
export const messageHandlers: Record<string, MessageHandler> = {
|
||||||
"remoteExitNode/register": handleRemoteExitNodeRegisterMessage,
|
"remoteExitNode/register": handleRemoteExitNodeRegisterMessage,
|
||||||
"remoteExitNode/ping": handleRemoteExitNodePingMessage,
|
"remoteExitNode/ping": handleRemoteExitNodePingMessage,
|
||||||
"newt/access-log": handleConnectionLogMessage,
|
"newt/access-log": handleConnectionLogMessage
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,7 +81,27 @@ export const queryAccessAuditLogsQuery = z.strictObject({
|
|||||||
.optional()
|
.optional()
|
||||||
.default("0")
|
.default("0")
|
||||||
.transform(Number)
|
.transform(Number)
|
||||||
.pipe(z.int().nonnegative())
|
.pipe(z.int().nonnegative()),
|
||||||
|
ip: z
|
||||||
|
.preprocess((val) => {
|
||||||
|
if (val === undefined || val === null || val === "") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
// the array is returned as this
|
||||||
|
if (typeof val === "string") {
|
||||||
|
return val.split(",");
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, z.array(z.string()))
|
||||||
|
.optional()
|
||||||
|
.catch([])
|
||||||
|
.openapi({
|
||||||
|
type: "array",
|
||||||
|
description: "Filter by IP adresses"
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const queryRequestAuditLogsParams = z.object({
|
export const queryRequestAuditLogsParams = z.object({
|
||||||
@@ -126,6 +146,9 @@ function getWhere(data: Q) {
|
|||||||
data.path ? eq(requestAuditLog.path, data.path) : undefined,
|
data.path ? eq(requestAuditLog.path, data.path) : undefined,
|
||||||
data.action !== undefined
|
data.action !== undefined
|
||||||
? eq(requestAuditLog.action, data.action)
|
? eq(requestAuditLog.action, data.action)
|
||||||
|
: undefined,
|
||||||
|
data.ip && data.ip.length > 0
|
||||||
|
? inArray(requestAuditLog.ip, data.ip)
|
||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -533,18 +533,23 @@ export async function startAuthentication(
|
|||||||
|
|
||||||
// If email is provided, get security keys for that specific user
|
// If email is provided, get security keys for that specific user
|
||||||
if (email) {
|
if (email) {
|
||||||
const [user] = await db
|
const matchingUsers = await db
|
||||||
.select()
|
.select()
|
||||||
.from(users)
|
.from(users)
|
||||||
.where(eq(users.email, email))
|
.where(
|
||||||
.limit(1);
|
and(
|
||||||
|
eq(users.email, email.toLowerCase()),
|
||||||
|
eq(users.type, UserType.Internal)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if (!user || user.type !== UserType.Internal) {
|
if (matchingUsers.length !== 1) {
|
||||||
return next(
|
return next(
|
||||||
createHttpError(HttpCode.BAD_REQUEST, "Invalid credentials")
|
createHttpError(HttpCode.BAD_REQUEST, "Invalid credentials")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const user = matchingUsers[0];
|
||||||
userId = user.userId;
|
userId = user.userId;
|
||||||
|
|
||||||
const userSecurityKeys = await db
|
const userSecurityKeys = await db
|
||||||
|
|||||||
@@ -42,54 +42,62 @@ export async function setServerAdmin(
|
|||||||
|
|
||||||
const { email, password, setupToken } = parsedBody.data;
|
const { email, password, setupToken } = parsedBody.data;
|
||||||
|
|
||||||
// Validate setup token
|
|
||||||
const [validToken] = await db
|
|
||||||
.select()
|
|
||||||
.from(setupTokens)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(setupTokens.token, setupToken),
|
|
||||||
eq(setupTokens.used, false)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validToken) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.BAD_REQUEST,
|
|
||||||
"Invalid or expired setup token"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [existing] = await db
|
|
||||||
.select()
|
|
||||||
.from(users)
|
|
||||||
.where(eq(users.serverAdmin, true));
|
|
||||||
|
|
||||||
if (existing) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.BAD_REQUEST,
|
|
||||||
"Server admin already exists"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const passwordHash = await hashPassword(password);
|
const passwordHash = await hashPassword(password);
|
||||||
const userId = generateId(15);
|
const userId = generateId(15);
|
||||||
|
|
||||||
await db.transaction(async (trx) => {
|
await db.transaction(async (trx) => {
|
||||||
// Mark the token as used
|
const consumed = await trx
|
||||||
await trx
|
|
||||||
.update(setupTokens)
|
.update(setupTokens)
|
||||||
.set({
|
.set({
|
||||||
used: true,
|
used: true,
|
||||||
dateUsed: moment().toISOString()
|
dateUsed: moment().toISOString()
|
||||||
})
|
})
|
||||||
.where(eq(setupTokens.tokenId, validToken.tokenId));
|
.where(
|
||||||
|
and(
|
||||||
|
eq(setupTokens.token, setupToken),
|
||||||
|
eq(setupTokens.used, false)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.returning({ tokenId: setupTokens.tokenId });
|
||||||
|
|
||||||
|
if (!consumed.length) {
|
||||||
|
throw createHttpError(
|
||||||
|
HttpCode.BAD_REQUEST,
|
||||||
|
"Invalid setup token"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [existingAdmin] = await trx
|
||||||
|
.select({ userId: users.userId })
|
||||||
|
.from(users)
|
||||||
|
.where(eq(users.serverAdmin, true))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (existingAdmin) {
|
||||||
|
throw createHttpError(
|
||||||
|
HttpCode.BAD_REQUEST,
|
||||||
|
"Server admin already exists"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [existingUser] = await trx
|
||||||
|
.select({ userId: users.userId })
|
||||||
|
.from(users)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(users.email, email),
|
||||||
|
eq(users.type, UserType.Internal)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (existingUser) {
|
||||||
|
throw createHttpError(
|
||||||
|
HttpCode.BAD_REQUEST,
|
||||||
|
"A user with that email address already exists"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the server admin user
|
|
||||||
await trx.insert(users).values({
|
await trx.insert(users).values({
|
||||||
userId: userId,
|
userId: userId,
|
||||||
email: email,
|
email: email,
|
||||||
@@ -111,6 +119,9 @@ export async function setServerAdmin(
|
|||||||
status: HttpCode.OK
|
status: HttpCode.OK
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (createHttpError.isHttpError(e)) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export async function validateSetupToken(
|
|||||||
return response<ValidateSetupTokenResponse>(res, {
|
return response<ValidateSetupTokenResponse>(res, {
|
||||||
data: {
|
data: {
|
||||||
valid: false,
|
valid: false,
|
||||||
message: "Invalid or expired setup token"
|
message: "Invalid setup token"
|
||||||
},
|
},
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { DateTimeValue } from "@app/components/DateTimePicker";
|
|||||||
import { ArrowUpRight, Key, User } from "lucide-react";
|
import { ArrowUpRight, Key, User } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ColumnFilterButton } from "@app/components/ColumnFilterButton";
|
import { ColumnFilterButton } from "@app/components/ColumnFilterButton";
|
||||||
|
import { ColumnMultiFilterButton } from "@app/components/ColumnMultiFilterButton";
|
||||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo";
|
import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo";
|
||||||
@@ -26,6 +27,7 @@ import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
|||||||
import { logQueries } from "@app/lib/queries";
|
import { logQueries } from "@app/lib/queries";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import type { QueryAccessAuditLogResponse } from "@server/routers/auditLogs/types";
|
import type { QueryAccessAuditLogResponse } from "@server/routers/auditLogs/types";
|
||||||
|
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
|
||||||
|
|
||||||
export default function GeneralPage() {
|
export default function GeneralPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -45,12 +47,14 @@ export default function GeneralPage() {
|
|||||||
resourceId?: string;
|
resourceId?: string;
|
||||||
location?: string;
|
location?: string;
|
||||||
actor?: string;
|
actor?: string;
|
||||||
|
ip?: string[];
|
||||||
}>({
|
}>({
|
||||||
action: searchParams.get("action") || undefined,
|
action: searchParams.get("action") || undefined,
|
||||||
type: searchParams.get("type") || undefined,
|
type: searchParams.get("type") || undefined,
|
||||||
resourceId: searchParams.get("resourceId") || undefined,
|
resourceId: searchParams.get("resourceId") || undefined,
|
||||||
location: searchParams.get("location") || undefined,
|
location: searchParams.get("location") || undefined,
|
||||||
actor: searchParams.get("actor") || undefined
|
actor: searchParams.get("actor") || undefined,
|
||||||
|
ip: searchParams.getAll("ip") || undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState<number>(0);
|
const [currentPage, setCurrentPage] = useState<number>(0);
|
||||||
@@ -176,7 +180,7 @@ export default function GeneralPage() {
|
|||||||
|
|
||||||
const handleFilterChange = (
|
const handleFilterChange = (
|
||||||
filterType: keyof typeof filters,
|
filterType: keyof typeof filters,
|
||||||
value: string | undefined
|
value: string | string[] | undefined
|
||||||
) => {
|
) => {
|
||||||
const newFilters = { ...filters, [filterType]: value };
|
const newFilters = { ...filters, [filterType]: value };
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
@@ -194,10 +198,13 @@ export default function GeneralPage() {
|
|||||||
) => {
|
) => {
|
||||||
const params = new URLSearchParams(searchParams);
|
const params = new URLSearchParams(searchParams);
|
||||||
Object.entries(newFilters).forEach(([key, value]) => {
|
Object.entries(newFilters).forEach(([key, value]) => {
|
||||||
if (value) {
|
params.delete(key);
|
||||||
|
if (typeof value === "string") {
|
||||||
params.set(key, value);
|
params.set(key, value);
|
||||||
} else {
|
} else if (typeof value !== "undefined" && "length" in value) {
|
||||||
params.delete(key);
|
for (const element of value) {
|
||||||
|
params.append(key, element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
router.replace(`?${params.toString()}`, { scroll: false });
|
router.replace(`?${params.toString()}`, { scroll: false });
|
||||||
@@ -205,6 +212,7 @@ export default function GeneralPage() {
|
|||||||
|
|
||||||
const exportData = async () => {
|
const exportData = async () => {
|
||||||
try {
|
try {
|
||||||
|
const { ip, ...restFilters } = filters;
|
||||||
const params: any = {
|
const params: any = {
|
||||||
timeStart: dateRange.startDate?.date
|
timeStart: dateRange.startDate?.date
|
||||||
? new Date(dateRange.startDate.date).toISOString()
|
? new Date(dateRange.startDate.date).toISOString()
|
||||||
@@ -212,13 +220,20 @@ export default function GeneralPage() {
|
|||||||
timeEnd: dateRange.endDate?.date
|
timeEnd: dateRange.endDate?.date
|
||||||
? new Date(dateRange.endDate.date).toISOString()
|
? new Date(dateRange.endDate.date).toISOString()
|
||||||
: undefined,
|
: undefined,
|
||||||
...filters
|
...restFilters
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await api.get(`/org/${orgId}/logs/access/export`, {
|
// axios serializes arrays as `ip[]=…`, which express's query
|
||||||
responseType: "blob",
|
// parser does not read back as `ip`, so pass them in the URL
|
||||||
params
|
const sp = new URLSearchParams((ip ?? []).map((ip) => ["ip", ip]));
|
||||||
});
|
|
||||||
|
const response = await api.get(
|
||||||
|
`/org/${orgId}/logs/access/export?${sp.toString()}`,
|
||||||
|
{
|
||||||
|
responseType: "blob",
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
@@ -297,7 +312,24 @@ export default function GeneralPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "ip",
|
accessorKey: "ip",
|
||||||
header: () => <span className="px-2">{t("ip")}</span>,
|
header: () => (
|
||||||
|
<span className="px-2">
|
||||||
|
<ColumnMultiFilterButton
|
||||||
|
options={(filters.ip ?? []).map((ip) => ({
|
||||||
|
label: ip,
|
||||||
|
value: ip
|
||||||
|
}))}
|
||||||
|
label={t("ip")}
|
||||||
|
allowArbitraryValues
|
||||||
|
searchPlaceholder={t("ipFilterSearchPlaceholder")}
|
||||||
|
emptyMessage={t("ipFilterEmptyMessage")}
|
||||||
|
selectedValues={filters.ip ?? []}
|
||||||
|
onSelectedValuesChange={(value) =>
|
||||||
|
handleFilterChange("ip", value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
return row.original.ip ? (
|
return row.original.ip ? (
|
||||||
row.original.ip
|
row.original.ip
|
||||||
@@ -315,7 +347,7 @@ export default function GeneralPage() {
|
|||||||
options={filterAttributes.locations.map(
|
options={filterAttributes.locations.map(
|
||||||
(location) => ({
|
(location) => ({
|
||||||
value: location,
|
value: location,
|
||||||
label: location
|
label: `${location} ${countryCodeToFlagEmoji(location)}`
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
label={t("location")}
|
label={t("location")}
|
||||||
@@ -334,7 +366,8 @@ export default function GeneralPage() {
|
|||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
{row.original.location ? (
|
{row.original.location ? (
|
||||||
<span className="text-muted-foreground text-xs">
|
<span className="text-muted-foreground text-xs">
|
||||||
{row.original.location}
|
{row.original.location}{" "}
|
||||||
|
{countryCodeToFlagEmoji(row.original.location)}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-muted-foreground text-xs">
|
<span className="text-muted-foreground text-xs">
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import { useMemo, useState, useTransition } from "react";
|
|||||||
import { useStoredPageSize } from "@app/hooks/useStoredPageSize";
|
import { useStoredPageSize } from "@app/hooks/useStoredPageSize";
|
||||||
import type { QueryRequestAuditLogResponse } from "@server/routers/auditLogs/types";
|
import type { QueryRequestAuditLogResponse } from "@server/routers/auditLogs/types";
|
||||||
import { ColumnFilterButton } from "@app/components/ColumnFilterButton";
|
import { ColumnFilterButton } from "@app/components/ColumnFilterButton";
|
||||||
|
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
|
||||||
|
import { ColumnMultiFilterButton } from "@app/components/ColumnMultiFilterButton";
|
||||||
|
|
||||||
export default function GeneralPage() {
|
export default function GeneralPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -47,6 +49,7 @@ export default function GeneralPage() {
|
|||||||
method?: string;
|
method?: string;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
path?: string;
|
path?: string;
|
||||||
|
ip?: string[];
|
||||||
}>({
|
}>({
|
||||||
action: searchParams.get("action") || undefined,
|
action: searchParams.get("action") || undefined,
|
||||||
host: searchParams.get("host") || undefined,
|
host: searchParams.get("host") || undefined,
|
||||||
@@ -55,7 +58,8 @@ export default function GeneralPage() {
|
|||||||
actor: searchParams.get("actor") || undefined,
|
actor: searchParams.get("actor") || undefined,
|
||||||
method: searchParams.get("method") || undefined,
|
method: searchParams.get("method") || undefined,
|
||||||
reason: searchParams.get("reason") || undefined,
|
reason: searchParams.get("reason") || undefined,
|
||||||
path: searchParams.get("path") || undefined
|
path: searchParams.get("path") || undefined,
|
||||||
|
ip: searchParams.getAll("ip") || undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
const getDefaultDateRange = () => {
|
const getDefaultDateRange = () => {
|
||||||
@@ -179,7 +183,7 @@ export default function GeneralPage() {
|
|||||||
|
|
||||||
const handleFilterChange = (
|
const handleFilterChange = (
|
||||||
filterType: keyof typeof filters,
|
filterType: keyof typeof filters,
|
||||||
value: string | undefined
|
value: string | string[] | undefined
|
||||||
) => {
|
) => {
|
||||||
const newFilters = { ...filters, [filterType]: value };
|
const newFilters = { ...filters, [filterType]: value };
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
@@ -197,10 +201,13 @@ export default function GeneralPage() {
|
|||||||
) => {
|
) => {
|
||||||
const params = new URLSearchParams(searchParams);
|
const params = new URLSearchParams(searchParams);
|
||||||
Object.entries(newFilters).forEach(([key, value]) => {
|
Object.entries(newFilters).forEach(([key, value]) => {
|
||||||
if (value) {
|
params.delete(key);
|
||||||
|
if (typeof value === "string") {
|
||||||
params.set(key, value);
|
params.set(key, value);
|
||||||
} else {
|
} else if (typeof value !== "undefined" && "length" in value) {
|
||||||
params.delete(key);
|
for (const element of value) {
|
||||||
|
params.append(key, element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
router.replace(`?${params.toString()}`, { scroll: false });
|
router.replace(`?${params.toString()}`, { scroll: false });
|
||||||
@@ -209,6 +216,7 @@ export default function GeneralPage() {
|
|||||||
const exportData = async () => {
|
const exportData = async () => {
|
||||||
try {
|
try {
|
||||||
// Prepare query params for export
|
// Prepare query params for export
|
||||||
|
const { ip, ...restFilters } = filters;
|
||||||
const params: any = {
|
const params: any = {
|
||||||
timeStart: dateRange.startDate?.date
|
timeStart: dateRange.startDate?.date
|
||||||
? new Date(dateRange.startDate.date).toISOString()
|
? new Date(dateRange.startDate.date).toISOString()
|
||||||
@@ -216,11 +224,15 @@ export default function GeneralPage() {
|
|||||||
timeEnd: dateRange.endDate?.date
|
timeEnd: dateRange.endDate?.date
|
||||||
? new Date(dateRange.endDate.date).toISOString()
|
? new Date(dateRange.endDate.date).toISOString()
|
||||||
: undefined,
|
: undefined,
|
||||||
...filters
|
...restFilters
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// axios serializes arrays as `ip[]=…`, which express's query
|
||||||
|
// parser does not read back as `ip`, so pass them in the URL
|
||||||
|
const sp = new URLSearchParams((ip ?? []).map((ip) => ["ip", ip]));
|
||||||
|
|
||||||
const response = await api.get(
|
const response = await api.get(
|
||||||
`/org/${orgId}/logs/request/export`,
|
`/org/${orgId}/logs/request/export?${sp.toString()}`,
|
||||||
{
|
{
|
||||||
responseType: "blob",
|
responseType: "blob",
|
||||||
params
|
params
|
||||||
@@ -351,7 +363,24 @@ export default function GeneralPage() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "ip",
|
accessorKey: "ip",
|
||||||
header: ({ column }) => <span className="px-2">{t("ip")}</span>,
|
header: ({ column }) => (
|
||||||
|
<span className="px-2">
|
||||||
|
<ColumnMultiFilterButton
|
||||||
|
options={(filters.ip ?? []).map((ip) => ({
|
||||||
|
label: ip,
|
||||||
|
value: ip
|
||||||
|
}))}
|
||||||
|
label={t("ip")}
|
||||||
|
allowArbitraryValues
|
||||||
|
searchPlaceholder={t("ipFilterSearchPlaceholder")}
|
||||||
|
emptyMessage={t("ipFilterEmptyMessage")}
|
||||||
|
selectedValues={filters.ip ?? []}
|
||||||
|
onSelectedValuesChange={(value) =>
|
||||||
|
handleFilterChange("ip", value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
return row.original.ip ? (
|
return row.original.ip ? (
|
||||||
row.original.ip
|
row.original.ip
|
||||||
@@ -369,7 +398,7 @@ export default function GeneralPage() {
|
|||||||
options={filterAttributes.locations.map(
|
options={filterAttributes.locations.map(
|
||||||
(location) => ({
|
(location) => ({
|
||||||
value: location,
|
value: location,
|
||||||
label: location
|
label: `${location} ${countryCodeToFlagEmoji(location)}`
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
selectedValue={filters.location}
|
selectedValue={filters.location}
|
||||||
@@ -389,7 +418,8 @@ export default function GeneralPage() {
|
|||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
{row.original.location ? (
|
{row.original.location ? (
|
||||||
<span className="text-muted-foreground text-xs">
|
<span className="text-muted-foreground text-xs">
|
||||||
{row.original.location}
|
{row.original.location}{" "}
|
||||||
|
{countryCodeToFlagEmoji(row.original.location)}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-muted-foreground text-xs">
|
<span className="text-muted-foreground text-xs">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { useTranslations } from "next-intl";
|
|||||||
|
|
||||||
interface FilterOption {
|
interface FilterOption {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ColumnFilterButtonProps {
|
interface ColumnFilterButtonProps {
|
||||||
@@ -32,6 +32,7 @@ interface ColumnFilterButtonProps {
|
|||||||
emptyMessage?: string;
|
emptyMessage?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
allowArbitraryValues?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ColumnFilterButton({
|
export function ColumnFilterButton({
|
||||||
@@ -41,7 +42,8 @@ export function ColumnFilterButton({
|
|||||||
searchPlaceholder = "Search...",
|
searchPlaceholder = "Search...",
|
||||||
emptyMessage = "No options found",
|
emptyMessage = "No options found",
|
||||||
className,
|
className,
|
||||||
label
|
label,
|
||||||
|
allowArbitraryValues
|
||||||
}: ColumnFilterButtonProps) {
|
}: ColumnFilterButtonProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
@@ -101,7 +103,7 @@ export function ColumnFilterButton({
|
|||||||
{options.map((option) => (
|
{options.map((option) => (
|
||||||
<CommandItem
|
<CommandItem
|
||||||
key={option.value}
|
key={option.value}
|
||||||
value={option.label}
|
value={option.value}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
onValueChange(
|
onValueChange(
|
||||||
selectedValue === option.value
|
selectedValue === option.value
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type ColumnMultiFilterButtonProps = {
|
|||||||
emptyMessage?: string;
|
emptyMessage?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
allowArbitraryValues?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ColumnMultiFilterButton({
|
export function ColumnMultiFilterButton({
|
||||||
@@ -44,11 +45,26 @@ export function ColumnMultiFilterButton({
|
|||||||
searchPlaceholder = "Search...",
|
searchPlaceholder = "Search...",
|
||||||
emptyMessage = "No options found",
|
emptyMessage = "No options found",
|
||||||
className,
|
className,
|
||||||
label
|
label,
|
||||||
|
allowArbitraryValues
|
||||||
}: ColumnMultiFilterButtonProps) {
|
}: ColumnMultiFilterButtonProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
|
const visibleOptions = useMemo<FilterOption[]>(() => {
|
||||||
|
const newOptions = [...options];
|
||||||
|
|
||||||
|
if (allowArbitraryValues && searchQuery.trim().length > 0) {
|
||||||
|
newOptions.push({
|
||||||
|
label: searchQuery,
|
||||||
|
value: searchQuery
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return newOptions;
|
||||||
|
}, [options, allowArbitraryValues, searchQuery]);
|
||||||
|
|
||||||
const selectedSet = useMemo(
|
const selectedSet = useMemo(
|
||||||
() => new Set(selectedValues),
|
() => new Set(selectedValues),
|
||||||
[selectedValues]
|
[selectedValues]
|
||||||
@@ -64,7 +80,7 @@ export function ColumnMultiFilterButton({
|
|||||||
selectedValues[0]
|
selectedValues[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return t("accessUsersRoleFilterCount", {
|
return t("multiSelectFilterCount", {
|
||||||
count: selectedValues.length
|
count: selectedValues.length
|
||||||
});
|
});
|
||||||
}, [selectedValues, options, t]);
|
}, [selectedValues, options, t]);
|
||||||
@@ -108,7 +124,11 @@ export function ColumnMultiFilterButton({
|
|||||||
align="start"
|
align="start"
|
||||||
>
|
>
|
||||||
<Command>
|
<Command>
|
||||||
<CommandInput placeholder={searchPlaceholder} />
|
<CommandInput
|
||||||
|
placeholder={searchPlaceholder}
|
||||||
|
value={searchQuery}
|
||||||
|
onValueChange={setSearchQuery}
|
||||||
|
/>
|
||||||
<CommandList>
|
<CommandList>
|
||||||
<CommandEmpty>{emptyMessage}</CommandEmpty>
|
<CommandEmpty>{emptyMessage}</CommandEmpty>
|
||||||
<CommandGroup>
|
<CommandGroup>
|
||||||
@@ -123,7 +143,7 @@ export function ColumnMultiFilterButton({
|
|||||||
{t("accessFilterClear")}
|
{t("accessFilterClear")}
|
||||||
</CommandItem>
|
</CommandItem>
|
||||||
)}
|
)}
|
||||||
{options.map((option) => (
|
{visibleOptions.map((option) => (
|
||||||
<CommandItem
|
<CommandItem
|
||||||
key={option.value}
|
key={option.value}
|
||||||
value={option.label}
|
value={option.label}
|
||||||
|
|||||||
+30
-22
@@ -1,3 +1,8 @@
|
|||||||
|
import {
|
||||||
|
getAiBudgetScopeListPath,
|
||||||
|
type AiBudgetScope
|
||||||
|
} from "@app/lib/aiBudgetScope";
|
||||||
|
import type { AiProviderType } from "@app/lib/aiProviderDefaults";
|
||||||
import type { LauncherQueryFilters } from "@app/lib/launcherSearchParams";
|
import type { LauncherQueryFilters } from "@app/lib/launcherSearchParams";
|
||||||
import { buildLauncherSearchParams } from "@app/lib/launcherSearchParams";
|
import { buildLauncherSearchParams } from "@app/lib/launcherSearchParams";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
@@ -5,15 +10,21 @@ import {
|
|||||||
StatusHistoryResponse,
|
StatusHistoryResponse,
|
||||||
type BatchedStatusHistoryResponse
|
type BatchedStatusHistoryResponse
|
||||||
} from "@server/lib/statusHistory";
|
} from "@server/lib/statusHistory";
|
||||||
|
import type { ListAiBudgetsByScopeResponse } from "@server/routers/aiBudget/types";
|
||||||
|
import type {
|
||||||
|
ListAiModelsResponse,
|
||||||
|
ListAiProvidersResponse,
|
||||||
|
ListCatalogModelsResponse
|
||||||
|
} from "@server/routers/aiProvider/types";
|
||||||
import type { ListAlertRulesResponse } from "@server/routers/alertRule/types";
|
import type { ListAlertRulesResponse } from "@server/routers/alertRule/types";
|
||||||
import type {
|
import type {
|
||||||
QueryRequestAnalyticsResponse,
|
|
||||||
QueryAiUsageFilterOptionsResponse,
|
QueryAiUsageFilterOptionsResponse,
|
||||||
QueryAiUsageOverviewResponse,
|
QueryAiUsageOverviewResponse,
|
||||||
QueryAiUsageProvidersResponse,
|
QueryAiUsageProvidersResponse,
|
||||||
QueryAiUsageResourcesResponse,
|
QueryAiUsageResourcesResponse,
|
||||||
QueryAiUsageUsersRolesResponse,
|
QueryAiUsageUsersRolesResponse,
|
||||||
QueryAiUsageVirtualApiKeysResponse
|
QueryAiUsageVirtualApiKeysResponse,
|
||||||
|
QueryRequestAnalyticsResponse
|
||||||
} from "@server/routers/auditLogs";
|
} from "@server/routers/auditLogs";
|
||||||
import type {
|
import type {
|
||||||
QueryAccessAuditLogResponse,
|
QueryAccessAuditLogResponse,
|
||||||
@@ -34,6 +45,7 @@ import type {
|
|||||||
import type { GetDomainResponse } from "@server/routers/domain/getDomain";
|
import type { GetDomainResponse } from "@server/routers/domain/getDomain";
|
||||||
import { ListHealthChecksResponse } from "@server/routers/healthChecks/types";
|
import { ListHealthChecksResponse } from "@server/routers/healthChecks/types";
|
||||||
import type { ListOrgLabelsResponse } from "@server/routers/labels/types";
|
import type { ListOrgLabelsResponse } from "@server/routers/labels/types";
|
||||||
|
import type { ListLauncherAiModelsResponse } from "@server/routers/launcher/listLauncherAiModels";
|
||||||
import type {
|
import type {
|
||||||
LauncherResource,
|
LauncherResource,
|
||||||
ListLauncherGroupsResponse,
|
ListLauncherGroupsResponse,
|
||||||
@@ -43,9 +55,8 @@ import type {
|
|||||||
ListLauncherSitesResponse,
|
ListLauncherSitesResponse,
|
||||||
ListLauncherViewsResponse
|
ListLauncherViewsResponse
|
||||||
} from "@server/routers/launcher/types";
|
} from "@server/routers/launcher/types";
|
||||||
import type { ListLauncherAiModelsResponse } from "@server/routers/launcher/listLauncherAiModels";
|
|
||||||
import type { ListMyVirtualApiKeysResponse } from "@server/routers/virtualApiKey/types";
|
|
||||||
import type { GetResourcePolicyResponse } from "@server/routers/policy";
|
import type { GetResourcePolicyResponse } from "@server/routers/policy";
|
||||||
|
import type { ListRemoteExitNodesResponse } from "@server/routers/remoteExitNode/types";
|
||||||
import type {
|
import type {
|
||||||
GetResourcePoliciesResponse,
|
GetResourcePoliciesResponse,
|
||||||
GetResourceWhitelistResponse,
|
GetResourceWhitelistResponse,
|
||||||
@@ -59,7 +70,6 @@ import type {
|
|||||||
import type { GetResourceResponse } from "@server/routers/resource/getResource";
|
import type { GetResourceResponse } from "@server/routers/resource/getResource";
|
||||||
import type { GetResourceAuthInfoResponse } from "@server/routers/resource/getResourceAuthInfo";
|
import type { GetResourceAuthInfoResponse } from "@server/routers/resource/getResourceAuthInfo";
|
||||||
import type { ListResourcePoliciesResponse } from "@server/routers/resource/types";
|
import type { ListResourcePoliciesResponse } from "@server/routers/resource/types";
|
||||||
import type { ListRemoteExitNodesResponse } from "@server/routers/remoteExitNode/types";
|
|
||||||
import type { ListRolesResponse } from "@server/routers/role";
|
import type { ListRolesResponse } from "@server/routers/role";
|
||||||
import type { ListSitesResponse } from "@server/routers/site";
|
import type { ListSitesResponse } from "@server/routers/site";
|
||||||
import type {
|
import type {
|
||||||
@@ -71,18 +81,8 @@ import type {
|
|||||||
} from "@server/routers/siteResource";
|
} from "@server/routers/siteResource";
|
||||||
import type { GetSiteResourceResponse } from "@server/routers/siteResource/getSiteResource";
|
import type { GetSiteResourceResponse } from "@server/routers/siteResource/getSiteResource";
|
||||||
import type { ListTargetsResponse } from "@server/routers/target";
|
import type { ListTargetsResponse } from "@server/routers/target";
|
||||||
import type {
|
|
||||||
ListAiModelsResponse,
|
|
||||||
ListAiProvidersResponse,
|
|
||||||
ListCatalogModelsResponse
|
|
||||||
} from "@server/routers/aiProvider/types";
|
|
||||||
import type { AiProviderType } from "@app/lib/aiProviderDefaults";
|
|
||||||
import type { ListAiBudgetsByScopeResponse } from "@server/routers/aiBudget/types";
|
|
||||||
import {
|
|
||||||
getAiBudgetScopeListPath,
|
|
||||||
type AiBudgetScope
|
|
||||||
} from "@app/lib/aiBudgetScope";
|
|
||||||
import type { ListUsersResponse } from "@server/routers/user";
|
import type { ListUsersResponse } from "@server/routers/user";
|
||||||
|
import type { ListMyVirtualApiKeysResponse } from "@server/routers/virtualApiKey/types";
|
||||||
import type ResponseT from "@server/types/Response";
|
import type ResponseT from "@server/types/Response";
|
||||||
import {
|
import {
|
||||||
infiniteQueryOptions,
|
infiniteQueryOptions,
|
||||||
@@ -1000,7 +1000,8 @@ export const httpLogsFiltersSchema = z.object({
|
|||||||
actor: z.string().optional().catch(undefined),
|
actor: z.string().optional().catch(undefined),
|
||||||
method: z.string().optional().catch(undefined),
|
method: z.string().optional().catch(undefined),
|
||||||
reason: z.string().optional().catch(undefined),
|
reason: z.string().optional().catch(undefined),
|
||||||
path: z.string().optional().catch(undefined)
|
path: z.string().optional().catch(undefined),
|
||||||
|
ip: z.array(z.string()).optional().catch(undefined)
|
||||||
});
|
});
|
||||||
|
|
||||||
export type HttpLogFilters = z.output<typeof httpLogsFiltersSchema>;
|
export type HttpLogFilters = z.output<typeof httpLogsFiltersSchema>;
|
||||||
@@ -1026,7 +1027,8 @@ export const accessLogsFiltersSchema = z.object({
|
|||||||
action: z.string().optional().catch(undefined),
|
action: z.string().optional().catch(undefined),
|
||||||
location: z.string().optional().catch(undefined),
|
location: z.string().optional().catch(undefined),
|
||||||
actor: z.string().optional().catch(undefined),
|
actor: z.string().optional().catch(undefined),
|
||||||
type: z.string().optional().catch(undefined)
|
type: z.string().optional().catch(undefined),
|
||||||
|
ip: z.array(z.string()).optional().catch(undefined)
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AccessLogFilters = z.output<typeof accessLogsFiltersSchema>;
|
export type AccessLogFilters = z.output<typeof accessLogsFiltersSchema>;
|
||||||
@@ -1139,10 +1141,13 @@ export const logQueries = {
|
|||||||
queryOptions({
|
queryOptions({
|
||||||
queryKey: ["REQUEST_LOGS", orgId, "ALL", filters] as const,
|
queryKey: ["REQUEST_LOGS", orgId, "ALL", filters] as const,
|
||||||
queryFn: async ({ signal, meta }) => {
|
queryFn: async ({ signal, meta }) => {
|
||||||
const { page, pageSize, ...rest } = filters;
|
const { page, pageSize, ip, ...rest } = filters;
|
||||||
|
const sp = new URLSearchParams(
|
||||||
|
(ip ?? []).map((ip) => ["ip", ip])
|
||||||
|
);
|
||||||
const res = await meta!.api.get<
|
const res = await meta!.api.get<
|
||||||
AxiosResponse<QueryRequestAuditLogResponse>
|
AxiosResponse<QueryRequestAuditLogResponse>
|
||||||
>(`/org/${orgId}/logs/request`, {
|
>(`/org/${orgId}/logs/request?${sp.toString()}`, {
|
||||||
params: {
|
params: {
|
||||||
...rest,
|
...rest,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
@@ -1164,10 +1169,13 @@ export const logQueries = {
|
|||||||
queryOptions({
|
queryOptions({
|
||||||
queryKey: ["ACCESS_LOGS", orgId, "ALL", filters] as const,
|
queryKey: ["ACCESS_LOGS", orgId, "ALL", filters] as const,
|
||||||
queryFn: async ({ signal, meta }) => {
|
queryFn: async ({ signal, meta }) => {
|
||||||
const { page, pageSize, ...rest } = filters;
|
const { page, pageSize, ip, ...rest } = filters;
|
||||||
|
const sp = new URLSearchParams(
|
||||||
|
(ip ?? []).map((ip) => ["ip", ip])
|
||||||
|
);
|
||||||
const res = await meta!.api.get<
|
const res = await meta!.api.get<
|
||||||
AxiosResponse<QueryAccessAuditLogResponse>
|
AxiosResponse<QueryAccessAuditLogResponse>
|
||||||
>(`/org/${orgId}/logs/access`, {
|
>(`/org/${orgId}/logs/access?${sp.toString()}`, {
|
||||||
params: {
|
params: {
|
||||||
...rest,
|
...rest,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
|
|||||||
Reference in New Issue
Block a user