Merge branch 'dev' into feat/geoip-country-is-not-rule

This commit is contained in:
Fred KISSIE
2026-06-27 02:05:02 +02:00
28 changed files with 4251 additions and 465 deletions
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Локална", "local": "Локална",
"edit": "Редактиране", "edit": "Редактиране",
"siteConfirmDelete": "Потвърждение на изтриване на сайта", "siteConfirmDelete": "Потвърждение на изтриване на сайта",
"siteConfirmDeleteAndResources": "Потвърдете изтриването на сайта и ресурсите",
"siteDelete": "Изтриване на сайта", "siteDelete": "Изтриване на сайта",
"siteDeleteAndResources": "Изтриване на сайта и ресурсите",
"siteMessageRemove": "След премахване, сайтът вече няма да бъде достъпен. Всички цели, свързани със сайта, също ще бъдат премахнати.", "siteMessageRemove": "След премахване, сайтът вече няма да бъде достъпен. Всички цели, свързани със сайта, също ще бъдат премахнати.",
"siteMessageRemoveAndResources": "Това ще изтрие окончателно всички публични и частни ресурси, свързани с този сайт, дори ако ресурсът е асоцииран и с други сайтове.",
"siteQuestionRemove": "Сигурни ли сте, че искате да премахнете сайта от организацията?", "siteQuestionRemove": "Сигурни ли сте, че искате да премахнете сайта от организацията?",
"siteQuestionRemoveAndResources": "Наистина ли желаете да изтриете този сайт и всички свързани ресурси?",
"sitesTableDeleteSite": "Изтриване на сайта",
"sitesTableDeleteSiteAndResources": "Изтриване на сайта и ресурсите",
"siteManageSites": "Управление на сайтове", "siteManageSites": "Управление на сайтове",
"siteDescription": "Създайте и управлявайте сайтове, за да осигурите свързаност със частни мрежи", "siteDescription": "Създайте и управлявайте сайтове, за да осигурите свързаност със частни мрежи",
"sitesBannerTitle": "Свържете се с мрежа.", "sitesBannerTitle": "Свържете се с мрежа.",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "CIDR диапазонът на ресурса в мрежата на сайта.", "createInternalResourceDialogDestinationCidrDescription": "CIDR диапазонът на ресурса в мрежата на сайта.",
"createInternalResourceDialogAlias": "Псевдоним", "createInternalResourceDialogAlias": "Псевдоним",
"createInternalResourceDialogAliasDescription": "По избор вътрешен DNS псевдоним за този ресурс.", "createInternalResourceDialogAliasDescription": "По избор вътрешен DNS псевдоним за този ресурс.",
"internalResourceAliasLocalWarning": "Синоними с окончание .local могат да причинят проблеми с резолюцията поради mDNS в някои мрежи.",
"internalResourceDownstreamSchemeRequired": "Методът е задължителен за HTTP ресурси", "internalResourceDownstreamSchemeRequired": "Методът е задължителен за HTTP ресурси",
"internalResourceHttpPortRequired": "Портът към целта е задължителен за HTTP ресурси", "internalResourceHttpPortRequired": "Портът към целта е задължителен за HTTP ресурси",
"siteConfiguration": "Конфигурация", "siteConfiguration": "Конфигурация",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Липсва идентификатор на организация или домейн", "orgOrDomainIdMissing": "Липсва идентификатор на организация или домейн",
"loadingDNSRecords": "Зареждане на DNS записи...", "loadingDNSRecords": "Зареждане на DNS записи...",
"olmUpdateAvailableInfo": "Налична е актуализирана версия на Olm. Моля, актуализирайте до най-новата версия за най-добро преживяване.", "olmUpdateAvailableInfo": "Налична е актуализирана версия на Olm. Моля, актуализирайте до най-новата версия за най-добро преживяване.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "На разположение е обновена версия. Моля, обновете до най-новата версия за най-добър опит.",
"client": "Клиент", "client": "Клиент",
"proxyProtocol": "Настройки на прокси протокол", "proxyProtocol": "Настройки на прокси протокол",
"proxyProtocolDescription": "Конфигурирайте Proxy Protocol, за да запазите IP адресите на клиентите за TCP услуги.", "proxyProtocolDescription": "Конфигурирайте Proxy Protocol, за да запазите IP адресите на клиентите за TCP услуги.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Místní", "local": "Místní",
"edit": "Upravit", "edit": "Upravit",
"siteConfirmDelete": "Potvrdit odstranění lokality", "siteConfirmDelete": "Potvrdit odstranění lokality",
"siteConfirmDeleteAndResources": "Potvrdit odstranění lokality a zdrojů",
"siteDelete": "Odstranění lokality", "siteDelete": "Odstranění lokality",
"siteDeleteAndResources": "Odstranit lokalitu a zdroje",
"siteMessageRemove": "Po odstranění webu již nebude přístupný. Všechny cíle spojené s webem budou také odstraněny.", "siteMessageRemove": "Po odstranění webu již nebude přístupný. Všechny cíle spojené s webem budou také odstraněny.",
"siteMessageRemoveAndResources": "Toto trvale odstraní všechny veřejné a soukromé zdroje spojené s touto lokalitou, i když je zdroj také přiřazen k jiným lokalitám.",
"siteQuestionRemove": "Jste si jisti, že chcete odstranit tuto stránku z organizace?", "siteQuestionRemove": "Jste si jisti, že chcete odstranit tuto stránku z organizace?",
"siteQuestionRemoveAndResources": "Opravdu chcete odstranit tuto lokalitu a všechny přidružené zdroje?",
"sitesTableDeleteSite": "Odstranění lokality",
"sitesTableDeleteSiteAndResources": "Odstranit lokalitu a zdroje",
"siteManageSites": "Správa lokalit", "siteManageSites": "Správa lokalit",
"siteDescription": "Vytvořte a spravujte stránky pro povolení připojení k soukromým sítím", "siteDescription": "Vytvořte a spravujte stránky pro povolení připojení k soukromým sítím",
"sitesBannerTitle": "Připojit jakoukoli síť", "sitesBannerTitle": "Připojit jakoukoli síť",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "Rozsah zdrojů CIDR v síti webu.", "createInternalResourceDialogDestinationCidrDescription": "Rozsah zdrojů CIDR v síti webu.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Volitelný interní DNS alias pro tento dokument.", "createInternalResourceDialogAliasDescription": "Volitelný interní DNS alias pro tento dokument.",
"internalResourceAliasLocalWarning": "Aliasy končící na .local mohou způsobit problémy s vyřešením díky mDNS v některých sítích.",
"internalResourceDownstreamSchemeRequired": "HTTP metoda je vyžadována pro HTTP zdroje", "internalResourceDownstreamSchemeRequired": "HTTP metoda je vyžadována pro HTTP zdroje",
"internalResourceHttpPortRequired": "Přípoječný port je nutný pro HTTP zdroj", "internalResourceHttpPortRequired": "Přípoječný port je nutný pro HTTP zdroj",
"siteConfiguration": "Konfigurace", "siteConfiguration": "Konfigurace",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Chybí ID organizace nebo domény", "orgOrDomainIdMissing": "Chybí ID organizace nebo domény",
"loadingDNSRecords": "Načítání DNS záznamů...", "loadingDNSRecords": "Načítání DNS záznamů...",
"olmUpdateAvailableInfo": "Je k dispozici aktualizovaná verze Olm. Pro nejlepší zážitek prosím aktualizujte na nejnovější verzi.", "olmUpdateAvailableInfo": "Je k dispozici aktualizovaná verze Olm. Pro nejlepší zážitek prosím aktualizujte na nejnovější verzi.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Je k dispozici aktualizovaná verze. Aktualizujte prosím na nejnovější verzi pro nejlepší zážitek.",
"client": "Zákazník", "client": "Zákazník",
"proxyProtocol": "Nastavení proxy protokolu", "proxyProtocol": "Nastavení proxy protokolu",
"proxyProtocolDescription": "Konfigurace Proxy protokolu pro zachování klientských IP adres pro služby TCP.", "proxyProtocolDescription": "Konfigurace Proxy protokolu pro zachování klientských IP adres pro služby TCP.",
+3608
View File
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Lokal", "local": "Lokal",
"edit": "Bearbeiten", "edit": "Bearbeiten",
"siteConfirmDelete": "Löschen des Standorts bestätigen", "siteConfirmDelete": "Löschen des Standorts bestätigen",
"siteConfirmDeleteAndResources": "Löschen von Standort und Ressourcen bestätigen",
"siteDelete": "Standort löschen", "siteDelete": "Standort löschen",
"siteDeleteAndResources": "Standort und Ressourcen löschen",
"siteMessageRemove": "Sobald der Standort entfernt ist, wird er nicht mehr zugänglich sein. Alle mit dem Standort verbundenen Ziele werden ebenfalls entfernt.", "siteMessageRemove": "Sobald der Standort entfernt ist, wird er nicht mehr zugänglich sein. Alle mit dem Standort verbundenen Ziele werden ebenfalls entfernt.",
"siteMessageRemoveAndResources": "Dies wird dauerhaft alle öffentlichen und privaten Ressourcen, die mit diesem Standort verknüpft sind, löschen, selbst wenn eine Ressource auch mit anderen Standorten verbunden ist.",
"siteQuestionRemove": "Sind Sie sicher, dass Sie den Standort aus der Organisation entfernen möchten?", "siteQuestionRemove": "Sind Sie sicher, dass Sie den Standort aus der Organisation entfernen möchten?",
"siteQuestionRemoveAndResources": "Sind Sie sicher, dass Sie diesen Standort und alle zugehörigen Ressourcen löschen möchten?",
"sitesTableDeleteSite": "Standort löschen",
"sitesTableDeleteSiteAndResources": "Standort und Ressourcen löschen",
"siteManageSites": "Standorte verwalten", "siteManageSites": "Standorte verwalten",
"siteDescription": "Erstellen und Verwalten von Standorten, um die Verbindung zu privaten Netzwerken zu ermöglichen", "siteDescription": "Erstellen und Verwalten von Standorten, um die Verbindung zu privaten Netzwerken zu ermöglichen",
"sitesBannerTitle": "Verbinde ein beliebiges Netzwerk", "sitesBannerTitle": "Verbinde ein beliebiges Netzwerk",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "Der CIDR-Bereich der Ressource im Netzwerk der Website.", "createInternalResourceDialogDestinationCidrDescription": "Der CIDR-Bereich der Ressource im Netzwerk der Website.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Ein optionaler interner DNS-Alias für diese Ressource.", "createInternalResourceDialogAliasDescription": "Ein optionaler interner DNS-Alias für diese Ressource.",
"internalResourceAliasLocalWarning": "Aliasse, die auf .local enden, können aufgrund von mDNS in einigen Netzwerken zu Auflösungsproblemen führen.",
"internalResourceDownstreamSchemeRequired": "Schema ist für HTTP-Ressourcen erforderlich", "internalResourceDownstreamSchemeRequired": "Schema ist für HTTP-Ressourcen erforderlich",
"internalResourceHttpPortRequired": "Zielport ist für HTTP-Ressourcen erforderlich", "internalResourceHttpPortRequired": "Zielport ist für HTTP-Ressourcen erforderlich",
"siteConfiguration": "Konfiguration", "siteConfiguration": "Konfiguration",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Organisation oder Domänen-ID fehlt", "orgOrDomainIdMissing": "Organisation oder Domänen-ID fehlt",
"loadingDNSRecords": "Lade DNS-Einträge...", "loadingDNSRecords": "Lade DNS-Einträge...",
"olmUpdateAvailableInfo": "Eine aktualisierte Version von Olm ist verfügbar. Bitte aktualisieren Sie auf die neueste Version für die beste Erfahrung.", "olmUpdateAvailableInfo": "Eine aktualisierte Version von Olm ist verfügbar. Bitte aktualisieren Sie auf die neueste Version für die beste Erfahrung.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Eine aktualisierte Version ist verfügbar. Bitte aktualisieren Sie auf die neueste Version für das beste Erlebnis.",
"client": "Client", "client": "Client",
"proxyProtocol": "Proxy-Protokoll-Einstellungen", "proxyProtocol": "Proxy-Protokoll-Einstellungen",
"proxyProtocolDescription": "Konfigurieren Sie das Proxy-Protokoll, um die IP-Adressen des Clients für TCP-Dienste zu erhalten.", "proxyProtocolDescription": "Konfigurieren Sie das Proxy-Protokoll, um die IP-Adressen des Clients für TCP-Dienste zu erhalten.",
+1
View File
@@ -2557,6 +2557,7 @@
"idpGoogleDescription": "Google OAuth2/OIDC provider", "idpGoogleDescription": "Google OAuth2/OIDC provider",
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider", "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
"subnet": "Subnet", "subnet": "Subnet",
"utilitySubnet": "Utility Subnet",
"subnetDescription": "The subnet for this organization's network configuration.", "subnetDescription": "The subnet for this organization's network configuration.",
"customDomain": "Custom Domain", "customDomain": "Custom Domain",
"authPage": "Authentication Pages", "authPage": "Authentication Pages",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Local", "local": "Local",
"edit": "Editar", "edit": "Editar",
"siteConfirmDelete": "Confirmar Borrar Sitio", "siteConfirmDelete": "Confirmar Borrar Sitio",
"siteConfirmDeleteAndResources": "Confirmar eliminación del sitio y recursos",
"siteDelete": "Eliminar sitio", "siteDelete": "Eliminar sitio",
"siteDeleteAndResources": "Eliminar sitio y recursos",
"siteMessageRemove": "Una vez eliminado, el sitio ya no será accesible. Todos los objetivos asociados con el sitio también serán eliminados.", "siteMessageRemove": "Una vez eliminado, el sitio ya no será accesible. Todos los objetivos asociados con el sitio también serán eliminados.",
"siteMessageRemoveAndResources": "Esto eliminará permanentemente todos los recursos públicos y privados vinculados a este sitio, incluso si un recurso también está asociado con otros sitios.",
"siteQuestionRemove": "¿Está seguro que desea eliminar el sitio de la organización?", "siteQuestionRemove": "¿Está seguro que desea eliminar el sitio de la organización?",
"siteQuestionRemoveAndResources": "¿Está seguro de que desea eliminar este sitio y todos los recursos asociados?",
"sitesTableDeleteSite": "Eliminar sitio",
"sitesTableDeleteSiteAndResources": "Eliminar sitio y recursos",
"siteManageSites": "Administrar Sitios", "siteManageSites": "Administrar Sitios",
"siteDescription": "Crear y administrar sitios para permitir la conectividad a redes privadas", "siteDescription": "Crear y administrar sitios para permitir la conectividad a redes privadas",
"sitesBannerTitle": "Conectar cualquier red", "sitesBannerTitle": "Conectar cualquier red",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "El rango CIDR del recurso en la red del sitio.", "createInternalResourceDialogDestinationCidrDescription": "El rango CIDR del recurso en la red del sitio.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Un alias DNS interno opcional para este recurso.", "createInternalResourceDialogAliasDescription": "Un alias DNS interno opcional para este recurso.",
"internalResourceAliasLocalWarning": "Los alias que terminan en .local pueden causar problemas de resolución debido a mDNS en algunas redes.",
"internalResourceDownstreamSchemeRequired": "Se requiere el método para recursos HTTP", "internalResourceDownstreamSchemeRequired": "Se requiere el método para recursos HTTP",
"internalResourceHttpPortRequired": "Se requiere el puerto de destino para recursos HTTP", "internalResourceHttpPortRequired": "Se requiere el puerto de destino para recursos HTTP",
"siteConfiguration": "Configuración", "siteConfiguration": "Configuración",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Falta el ID de organización o dominio", "orgOrDomainIdMissing": "Falta el ID de organización o dominio",
"loadingDNSRecords": "Cargando registros DNS...", "loadingDNSRecords": "Cargando registros DNS...",
"olmUpdateAvailableInfo": "Una versión actualizada de Olm está disponible. Por favor, actualice a la última versión para obtener la mejor experiencia.", "olmUpdateAvailableInfo": "Una versión actualizada de Olm está disponible. Por favor, actualice a la última versión para obtener la mejor experiencia.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Hay una versión actualizada disponible. Actualice a la última versión para obtener la mejor experiencia.",
"client": "Cliente", "client": "Cliente",
"proxyProtocol": "Configuración del Protocolo Proxy", "proxyProtocol": "Configuración del Protocolo Proxy",
"proxyProtocolDescription": "Configurar el protocolo de proxy para preservar las direcciones IP del cliente para los servicios TCP.", "proxyProtocolDescription": "Configurar el protocolo de proxy para preservar las direcciones IP del cliente para los servicios TCP.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Locale", "local": "Locale",
"edit": "Modifier", "edit": "Modifier",
"siteConfirmDelete": "Confirmer la suppression du nœud", "siteConfirmDelete": "Confirmer la suppression du nœud",
"siteConfirmDeleteAndResources": "Confirmer la suppression du site et des ressources",
"siteDelete": "Supprimer le nœud", "siteDelete": "Supprimer le nœud",
"siteDeleteAndResources": "Supprimer le site et les ressources",
"siteMessageRemove": "Une fois supprimé, le nœud ne sera plus accessible. Toutes les cibles associées au nœud seront également supprimées.", "siteMessageRemove": "Une fois supprimé, le nœud ne sera plus accessible. Toutes les cibles associées au nœud seront également supprimées.",
"siteMessageRemoveAndResources": "Cela supprimera définitivement toutes les ressources publiques et privées liées à ce site, même si une ressource est également associée à d'autres sites.",
"siteQuestionRemove": "Êtes-vous sûr de vouloir supprimer ce nœud de l'organisation ?", "siteQuestionRemove": "Êtes-vous sûr de vouloir supprimer ce nœud de l'organisation ?",
"siteQuestionRemoveAndResources": "Êtes-vous sûr de vouloir supprimer ce site et toutes les ressources associées?",
"sitesTableDeleteSite": "Supprimer le site",
"sitesTableDeleteSiteAndResources": "Supprimer le site et les ressources",
"siteManageSites": "Gérer les nœuds", "siteManageSites": "Gérer les nœuds",
"siteDescription": "Créer et gérer des sites pour activer la connectivité aux réseaux privés", "siteDescription": "Créer et gérer des sites pour activer la connectivité aux réseaux privés",
"sitesBannerTitle": "Se connecter à n'importe quel réseau", "sitesBannerTitle": "Se connecter à n'importe quel réseau",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "La gamme CIDR de la ressource sur le réseau du site.", "createInternalResourceDialogDestinationCidrDescription": "La gamme CIDR de la ressource sur le réseau du site.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Un alias DNS interne optionnel pour cette ressource.", "createInternalResourceDialogAliasDescription": "Un alias DNS interne optionnel pour cette ressource.",
"internalResourceAliasLocalWarning": "Les alias se terminant par .local peuvent causer des problèmes de résolution dus au mDNS sur certains réseaux.",
"internalResourceDownstreamSchemeRequired": "Un schéma est requis pour les ressources HTTP", "internalResourceDownstreamSchemeRequired": "Un schéma est requis pour les ressources HTTP",
"internalResourceHttpPortRequired": "Le port de destination est requis pour les ressources HTTP", "internalResourceHttpPortRequired": "Le port de destination est requis pour les ressources HTTP",
"siteConfiguration": "Configuration", "siteConfiguration": "Configuration",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "L'organisation ou l'identifiant de domaine est manquant", "orgOrDomainIdMissing": "L'organisation ou l'identifiant de domaine est manquant",
"loadingDNSRecords": "Chargement des enregistrements DNS...", "loadingDNSRecords": "Chargement des enregistrements DNS...",
"olmUpdateAvailableInfo": "Une version mise à jour de Olm est disponible. Veuillez mettre à jour vers la dernière version pour la meilleure expérience.", "olmUpdateAvailableInfo": "Une version mise à jour de Olm est disponible. Veuillez mettre à jour vers la dernière version pour la meilleure expérience.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Une version mise à jour est disponible. Veuillez mettre à jour vers la dernière version pour une meilleure expérience.",
"client": "Client", "client": "Client",
"proxyProtocol": "Paramètres du protocole proxy", "proxyProtocol": "Paramètres du protocole proxy",
"proxyProtocolDescription": "Configurer le protocole Proxy pour préserver les adresses IP du client pour les services TCP.", "proxyProtocolDescription": "Configurer le protocole Proxy pour préserver les adresses IP du client pour les services TCP.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Locale", "local": "Locale",
"edit": "Modifica", "edit": "Modifica",
"siteConfirmDelete": "Conferma Eliminazione Sito", "siteConfirmDelete": "Conferma Eliminazione Sito",
"siteConfirmDeleteAndResources": "Conferma Eliminazione Sito e Risorse",
"siteDelete": "Elimina Sito", "siteDelete": "Elimina Sito",
"siteDeleteAndResources": "Elimina Sito e Risorse",
"siteMessageRemove": "Una volta rimosso il sito non sarà più accessibile. Tutti gli oggetti associati al sito verranno rimossi.", "siteMessageRemove": "Una volta rimosso il sito non sarà più accessibile. Tutti gli oggetti associati al sito verranno rimossi.",
"siteMessageRemoveAndResources": "Questo eliminerà permanentemente tutte le risorse pubbliche e private collegate a questo sito, anche se una risorsa è anche associata ad altri siti.",
"siteQuestionRemove": "Sei sicuro di voler rimuovere il sito dall'organizzazione?", "siteQuestionRemove": "Sei sicuro di voler rimuovere il sito dall'organizzazione?",
"siteQuestionRemoveAndResources": "Sei sicuro di voler eliminare questo sito e tutte le risorse associate?",
"sitesTableDeleteSite": "Elimina Sito",
"sitesTableDeleteSiteAndResources": "Elimina Sito e Risorse",
"siteManageSites": "Gestisci Siti", "siteManageSites": "Gestisci Siti",
"siteDescription": "Creare e gestire siti per abilitare la connettività a reti private", "siteDescription": "Creare e gestire siti per abilitare la connettività a reti private",
"sitesBannerTitle": "Connetti Qualsiasi Rete", "sitesBannerTitle": "Connetti Qualsiasi Rete",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "La gamma CIDR della risorsa sulla rete del sito.", "createInternalResourceDialogDestinationCidrDescription": "La gamma CIDR della risorsa sulla rete del sito.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Un alias DNS interno opzionale per questa risorsa.", "createInternalResourceDialogAliasDescription": "Un alias DNS interno opzionale per questa risorsa.",
"internalResourceAliasLocalWarning": "Gli alias che terminano in .local possono causare problemi di risoluzione a causa di mDNS su alcune reti.",
"internalResourceDownstreamSchemeRequired": "Il metodo è richiesto per risorse HTTP", "internalResourceDownstreamSchemeRequired": "Il metodo è richiesto per risorse HTTP",
"internalResourceHttpPortRequired": "Porta di destinazione richiesta per risorse HTTP", "internalResourceHttpPortRequired": "Porta di destinazione richiesta per risorse HTTP",
"siteConfiguration": "Configurazione", "siteConfiguration": "Configurazione",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Manca l'ID dell'organizzazione o del dominio", "orgOrDomainIdMissing": "Manca l'ID dell'organizzazione o del dominio",
"loadingDNSRecords": "Caricamento record DNS...", "loadingDNSRecords": "Caricamento record DNS...",
"olmUpdateAvailableInfo": "È disponibile una versione aggiornata di Olm. Si prega di aggiornare all'ultima versione per la migliore esperienza.", "olmUpdateAvailableInfo": "È disponibile una versione aggiornata di Olm. Si prega di aggiornare all'ultima versione per la migliore esperienza.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "È disponibile una versione aggiornata. Si prega di aggiornare all'ultima versione per la migliore esperienza.",
"client": "Client", "client": "Client",
"proxyProtocol": "Impostazioni Protocollo Proxy", "proxyProtocol": "Impostazioni Protocollo Proxy",
"proxyProtocolDescription": "Configurare il protocollo proxy per preservare gli indirizzi IP client per i servizi TCP.", "proxyProtocolDescription": "Configurare il protocollo proxy per preservare gli indirizzi IP client per i servizi TCP.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "로컬", "local": "로컬",
"edit": "편집", "edit": "편집",
"siteConfirmDelete": "사이트 삭제 확인", "siteConfirmDelete": "사이트 삭제 확인",
"siteConfirmDeleteAndResources": "사이트 및 리소스 삭제 확인",
"siteDelete": "사이트 삭제", "siteDelete": "사이트 삭제",
"siteDeleteAndResources": "사이트 및 리소스 삭제",
"siteMessageRemove": "삭제되면 사이트에 더 이상 액세스할 수 없습니다. 사이트와 연결된 모든 대상도 삭제됩니다.", "siteMessageRemove": "삭제되면 사이트에 더 이상 액세스할 수 없습니다. 사이트와 연결된 모든 대상도 삭제됩니다.",
"siteMessageRemoveAndResources": "이 사이트와 연결된 모든 공용 및 개인 리소스는 다른 사이트에도 연결되어 있더라도 영구적으로 삭제됩니다.",
"siteQuestionRemove": "조직에서 사이트를 제거하시겠습니까?", "siteQuestionRemove": "조직에서 사이트를 제거하시겠습니까?",
"siteQuestionRemoveAndResources": "이 사이트와 모든 관련 리소스를 삭제하시겠습니까?",
"sitesTableDeleteSite": "사이트 삭제",
"sitesTableDeleteSiteAndResources": "사이트 및 리소스 삭제",
"siteManageSites": "사이트 관리", "siteManageSites": "사이트 관리",
"siteDescription": "프라이빗 네트워크로의 연결을 활성화하려면 사이트를 생성하고 관리하세요.", "siteDescription": "프라이빗 네트워크로의 연결을 활성화하려면 사이트를 생성하고 관리하세요.",
"sitesBannerTitle": "모든 네트워크 연결", "sitesBannerTitle": "모든 네트워크 연결",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "사이트 네트워크의 자원 IP 주소입니다.", "createInternalResourceDialogDestinationCidrDescription": "사이트 네트워크의 자원 IP 주소입니다.",
"createInternalResourceDialogAlias": "별칭", "createInternalResourceDialogAlias": "별칭",
"createInternalResourceDialogAliasDescription": "이 리소스에 대한 선택적 내부 DNS 별칭입니다.", "createInternalResourceDialogAliasDescription": "이 리소스에 대한 선택적 내부 DNS 별칭입니다.",
"internalResourceAliasLocalWarning": ".local로 끝나는 별칭은 일부 네트워크에서 mDNS로 인해 해결 문제가 발생할 수 있습니다.",
"internalResourceDownstreamSchemeRequired": "HTTP 리소스에 스킴이 필요합니다", "internalResourceDownstreamSchemeRequired": "HTTP 리소스에 스킴이 필요합니다",
"internalResourceHttpPortRequired": "HTTP 리소스에 목적지 포트가 필요합니다", "internalResourceHttpPortRequired": "HTTP 리소스에 목적지 포트가 필요합니다",
"siteConfiguration": "설정", "siteConfiguration": "설정",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "조직 ID 또는 도메인 ID가 누락되었습니다", "orgOrDomainIdMissing": "조직 ID 또는 도메인 ID가 누락되었습니다",
"loadingDNSRecords": "DNS 레코드를 로드하는 중...", "loadingDNSRecords": "DNS 레코드를 로드하는 중...",
"olmUpdateAvailableInfo": "올름의 새 버전이 이용 가능합니다. 최상의 경험을 위해 최신 버전으로 업데이트하세요.", "olmUpdateAvailableInfo": "올름의 새 버전이 이용 가능합니다. 최상의 경험을 위해 최신 버전으로 업데이트하세요.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "업데이트된 버전이 있습니다. 최상의 경험을 위해 최신 버전으로 업데이트하세요.",
"client": "클라이언트", "client": "클라이언트",
"proxyProtocol": "프록시 프로토콜 설정", "proxyProtocol": "프록시 프로토콜 설정",
"proxyProtocolDescription": "TCP 서비스에 대한 클라이언트 IP 주소를 유지하도록 프록시 프로토콜을 구성하세요.", "proxyProtocolDescription": "TCP 서비스에 대한 클라이언트 IP 주소를 유지하도록 프록시 프로토콜을 구성하세요.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Lokal", "local": "Lokal",
"edit": "Rediger", "edit": "Rediger",
"siteConfirmDelete": "Bekreft Sletting av Område", "siteConfirmDelete": "Bekreft Sletting av Område",
"siteConfirmDeleteAndResources": "Bekreft sletting av nettsted og ressurser",
"siteDelete": "Slett Område", "siteDelete": "Slett Område",
"siteDeleteAndResources": "Slett nettsted og ressurser",
"siteMessageRemove": "Når nettstedet er fjernet, vil det ikke lenger være tilgjengelig. Alle målene for nettstedet vil også bli fjernet.", "siteMessageRemove": "Når nettstedet er fjernet, vil det ikke lenger være tilgjengelig. Alle målene for nettstedet vil også bli fjernet.",
"siteMessageRemoveAndResources": "Dette vil permanent slette alle offentlige og private ressurser tilknyttet dette nettstedet, selv om en ressurs også er tilknyttet andre nettsteder.",
"siteQuestionRemove": "Er du sikker på at du vil fjerne nettstedet fra organisasjonen?", "siteQuestionRemove": "Er du sikker på at du vil fjerne nettstedet fra organisasjonen?",
"siteQuestionRemoveAndResources": "Er du sikker på at du vil slette dette nettstedet og alle tilknyttede ressurser?",
"sitesTableDeleteSite": "Slett nettsted",
"sitesTableDeleteSiteAndResources": "Slett nettsted og ressurser",
"siteManageSites": "Administrer Områder", "siteManageSites": "Administrer Områder",
"siteDescription": "Opprette og administrere nettsteder for å aktivere tilkobling til private nettverk", "siteDescription": "Opprette og administrere nettsteder for å aktivere tilkobling til private nettverk",
"sitesBannerTitle": "Koble til alle nettverk", "sitesBannerTitle": "Koble til alle nettverk",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "CIDR-rekkevidden til ressursen på nettstedets nettverk.", "createInternalResourceDialogDestinationCidrDescription": "CIDR-rekkevidden til ressursen på nettstedets nettverk.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Et valgfritt internt DNS-alias for denne ressursen.", "createInternalResourceDialogAliasDescription": "Et valgfritt internt DNS-alias for denne ressursen.",
"internalResourceAliasLocalWarning": "Alias som slutter på .local kan forårsake oppløsningsproblemer på grunn av mDNS på enkelte nettverk.",
"internalResourceDownstreamSchemeRequired": "Skjema er påkrevd for HTTP-ressurser", "internalResourceDownstreamSchemeRequired": "Skjema er påkrevd for HTTP-ressurser",
"internalResourceHttpPortRequired": "Destinasjonsport er nødvendig for HTTP-ressurser", "internalResourceHttpPortRequired": "Destinasjonsport er nødvendig for HTTP-ressurser",
"siteConfiguration": "Konfigurasjon", "siteConfiguration": "Konfigurasjon",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "ID for organisasjon eller domene mangler", "orgOrDomainIdMissing": "ID for organisasjon eller domene mangler",
"loadingDNSRecords": "Laster DNS-poster...", "loadingDNSRecords": "Laster DNS-poster...",
"olmUpdateAvailableInfo": "En oppdatert versjon av Olm er tilgjengelig. Oppdater til den nyeste versjonen for å få den beste opplevelsen.", "olmUpdateAvailableInfo": "En oppdatert versjon av Olm er tilgjengelig. Oppdater til den nyeste versjonen for å få den beste opplevelsen.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "En oppdatert versjon er tilgjengelig. Vennligst oppdater til den nyeste versjonen for den beste opplevelsen.",
"client": "Klient", "client": "Klient",
"proxyProtocol": "Protokoll innstillinger for Protokoll", "proxyProtocol": "Protokoll innstillinger for Protokoll",
"proxyProtocolDescription": "Konfigurer Proxy-protokoll for å bevare klientens IP-adresser til TCP-tjenester.", "proxyProtocolDescription": "Konfigurer Proxy-protokoll for å bevare klientens IP-adresser til TCP-tjenester.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Lokaal", "local": "Lokaal",
"edit": "Bewerken", "edit": "Bewerken",
"siteConfirmDelete": "Verwijderen van site bevestigen", "siteConfirmDelete": "Verwijderen van site bevestigen",
"siteConfirmDeleteAndResources": "Bevestig Verwijderen van Site en Bronnen",
"siteDelete": "Site verwijderen", "siteDelete": "Site verwijderen",
"siteDeleteAndResources": "Site en Bronnen verwijderen",
"siteMessageRemove": "Eenmaal verwijderd zal de site niet langer toegankelijk zijn. Alle aan de site gekoppelde doelen zullen ook worden verwijderd.", "siteMessageRemove": "Eenmaal verwijderd zal de site niet langer toegankelijk zijn. Alle aan de site gekoppelde doelen zullen ook worden verwijderd.",
"siteMessageRemoveAndResources": "Dit zal permanent alle publieke en private resources gekoppeld aan deze site verwijderen, zelfs als een resource ook aan andere sites is gekoppeld.",
"siteQuestionRemove": "Weet u zeker dat u de site wilt verwijderen uit de organisatie?", "siteQuestionRemove": "Weet u zeker dat u de site wilt verwijderen uit de organisatie?",
"siteQuestionRemoveAndResources": "Weet u zeker dat u deze site en alle gekoppelde resources wilt verwijderen?",
"sitesTableDeleteSite": "Site verwijderen",
"sitesTableDeleteSiteAndResources": "Site en Bronnen verwijderen",
"siteManageSites": "Sites beheren", "siteManageSites": "Sites beheren",
"siteDescription": "Maak en beheer sites om verbinding met privénetwerken in te schakelen", "siteDescription": "Maak en beheer sites om verbinding met privénetwerken in te schakelen",
"sitesBannerTitle": "Verbind elk netwerk", "sitesBannerTitle": "Verbind elk netwerk",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "Het CIDR-bereik van het document op het netwerk van de site.", "createInternalResourceDialogDestinationCidrDescription": "Het CIDR-bereik van het document op het netwerk van de site.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Een optionele interne DNS-alias voor dit document.", "createInternalResourceDialogAliasDescription": "Een optionele interne DNS-alias voor dit document.",
"internalResourceAliasLocalWarning": "Aliassen die eindigen op .local kunnen resolutieproblemen veroorzaken vanwege mDNS op sommige netwerken.",
"internalResourceDownstreamSchemeRequired": "Schema is vereist voor HTTP-bronnen", "internalResourceDownstreamSchemeRequired": "Schema is vereist voor HTTP-bronnen",
"internalResourceHttpPortRequired": "Bestemmingspoort is vereist voor HTTP-bronnen", "internalResourceHttpPortRequired": "Bestemmingspoort is vereist voor HTTP-bronnen",
"siteConfiguration": "Configuratie", "siteConfiguration": "Configuratie",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Organisatie of domein ID ontbreekt", "orgOrDomainIdMissing": "Organisatie of domein ID ontbreekt",
"loadingDNSRecords": "DNS-records laden...", "loadingDNSRecords": "DNS-records laden...",
"olmUpdateAvailableInfo": "Er is een bijgewerkte versie van Olm beschikbaar. Update alstublieft naar de nieuwste versie voor de beste ervaring.", "olmUpdateAvailableInfo": "Er is een bijgewerkte versie van Olm beschikbaar. Update alstublieft naar de nieuwste versie voor de beste ervaring.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Er is een bijgewerkte versie beschikbaar. Update naar de nieuwste versie voor de beste ervaring.",
"client": "Klant", "client": "Klant",
"proxyProtocol": "Proxy Protocol Instellingen", "proxyProtocol": "Proxy Protocol Instellingen",
"proxyProtocolDescription": "Proxyprotocol configureren om de IP-adressen van de client voor TCP-diensten te bewaren.", "proxyProtocolDescription": "Proxyprotocol configureren om de IP-adressen van de client voor TCP-diensten te bewaren.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Lokalny", "local": "Lokalny",
"edit": "Edytuj", "edit": "Edytuj",
"siteConfirmDelete": "Potwierdź usunięcie witryny", "siteConfirmDelete": "Potwierdź usunięcie witryny",
"siteConfirmDeleteAndResources": "Potwierdź usunięcie witryny i zasobów",
"siteDelete": "Usuń witrynę", "siteDelete": "Usuń witrynę",
"siteDeleteAndResources": "Usuń witrynę i zasoby",
"siteMessageRemove": "Po usunięciu witryna nie będzie już dostępna. Wszystkie cele związane z witryną zostaną również usunięte.", "siteMessageRemove": "Po usunięciu witryna nie będzie już dostępna. Wszystkie cele związane z witryną zostaną również usunięte.",
"siteMessageRemoveAndResources": "To spowoduje trwałe usunięcie wszystkich zasobów publicznych i prywatnych powiązanych z tą witryną, nawet jeśli zasób jest także powiązany z innymi witrynami.",
"siteQuestionRemove": "Czy na pewno chcesz usunąć witrynę z organizacji?", "siteQuestionRemove": "Czy na pewno chcesz usunąć witrynę z organizacji?",
"siteQuestionRemoveAndResources": "Czy na pewno chcesz usunąć tę witrynę i wszystkie powiązane zasoby?",
"sitesTableDeleteSite": "Usuń witrynę",
"sitesTableDeleteSiteAndResources": "Usuń witrynę i zasoby",
"siteManageSites": "Zarządzaj stronami", "siteManageSites": "Zarządzaj stronami",
"siteDescription": "Tworzenie stron i zarządzanie nimi, aby włączyć połączenia z prywatnymi sieciami", "siteDescription": "Tworzenie stron i zarządzanie nimi, aby włączyć połączenia z prywatnymi sieciami",
"sitesBannerTitle": "Połącz dowolną sieć", "sitesBannerTitle": "Połącz dowolną sieć",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "Zakres CIDR zasobu w sieci witryny.", "createInternalResourceDialogDestinationCidrDescription": "Zakres CIDR zasobu w sieci witryny.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Opcjonalny wewnętrzny alias DNS dla tego zasobu.", "createInternalResourceDialogAliasDescription": "Opcjonalny wewnętrzny alias DNS dla tego zasobu.",
"internalResourceAliasLocalWarning": "Alias kończący się na .local może powodować problemy z rozpoznawaniem z powodu mDNS w niektórych sieciach.",
"internalResourceDownstreamSchemeRequired": "Schemat jest wymagany dla zasobów HTTP", "internalResourceDownstreamSchemeRequired": "Schemat jest wymagany dla zasobów HTTP",
"internalResourceHttpPortRequired": "Port docelowy jest wymagany dla zasobów HTTP", "internalResourceHttpPortRequired": "Port docelowy jest wymagany dla zasobów HTTP",
"siteConfiguration": "Konfiguracja", "siteConfiguration": "Konfiguracja",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Brakuje identyfikatora organizacji lub domeny", "orgOrDomainIdMissing": "Brakuje identyfikatora organizacji lub domeny",
"loadingDNSRecords": "Ładowanie rekordów DNS...", "loadingDNSRecords": "Ładowanie rekordów DNS...",
"olmUpdateAvailableInfo": "Dostępna jest zaktualizowana wersja Olm. Zaktualizuj do najnowszej wersji, aby uzyskać najlepsze doświadczenia.", "olmUpdateAvailableInfo": "Dostępna jest zaktualizowana wersja Olm. Zaktualizuj do najnowszej wersji, aby uzyskać najlepsze doświadczenia.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Dostępna jest zaktualizowana wersja. Zaktualizuj do najnowszej wersji, aby uzyskać najlepsze wrażenia z użytkowania.",
"client": "Klient", "client": "Klient",
"proxyProtocol": "Ustawienia protokołu proxy", "proxyProtocol": "Ustawienia protokołu proxy",
"proxyProtocolDescription": "Skonfiguruj protokół Proxy aby zachować adresy IP klienta dla usług TCP.", "proxyProtocolDescription": "Skonfiguruj protokół Proxy aby zachować adresy IP klienta dla usług TCP.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Localização", "local": "Localização",
"edit": "Alterar", "edit": "Alterar",
"siteConfirmDelete": "Confirmar que pretende apagar o site", "siteConfirmDelete": "Confirmar que pretende apagar o site",
"siteConfirmDeleteAndResources": "Confirmar Exclusão do Site e Recursos",
"siteDelete": "Excluir site", "siteDelete": "Excluir site",
"siteDeleteAndResources": "Excluir Site e Recursos",
"siteMessageRemove": "Uma vez removido, o site não estará mais acessível. Todas as metas associadas ao site também serão removidas.", "siteMessageRemove": "Uma vez removido, o site não estará mais acessível. Todas as metas associadas ao site também serão removidas.",
"siteMessageRemoveAndResources": "Isso excluirá permanentemente todos os recursos públicos e privados vinculados a este site, mesmo que um recurso também esteja associado a outros sites.",
"siteQuestionRemove": "Você tem certeza que deseja remover este site da organização?", "siteQuestionRemove": "Você tem certeza que deseja remover este site da organização?",
"siteQuestionRemoveAndResources": "Tem certeza de que deseja excluir este site e todos os recursos associados?",
"sitesTableDeleteSite": "Excluir Site",
"sitesTableDeleteSiteAndResources": "Excluir Site e Recursos",
"siteManageSites": "Gerir sites", "siteManageSites": "Gerir sites",
"siteDescription": "Criar e gerenciar sites para ativar a conectividade a redes privadas", "siteDescription": "Criar e gerenciar sites para ativar a conectividade a redes privadas",
"sitesBannerTitle": "Conectar a Qualquer Rede", "sitesBannerTitle": "Conectar a Qualquer Rede",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "A faixa CIDR do recurso na rede do site.", "createInternalResourceDialogDestinationCidrDescription": "A faixa CIDR do recurso na rede do site.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Um alias de DNS interno opcional para este recurso.", "createInternalResourceDialogAliasDescription": "Um alias de DNS interno opcional para este recurso.",
"internalResourceAliasLocalWarning": "Os aliases terminando em .local podem causar problemas de resolução devido ao mDNS em algumas redes.",
"internalResourceDownstreamSchemeRequired": "Esquema é obrigatório para recursos HTTP", "internalResourceDownstreamSchemeRequired": "Esquema é obrigatório para recursos HTTP",
"internalResourceHttpPortRequired": "Porta de destino é obrigatória para recursos HTTP", "internalResourceHttpPortRequired": "Porta de destino é obrigatória para recursos HTTP",
"siteConfiguration": "Configuração", "siteConfiguration": "Configuração",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "ID da organização ou domínio está faltando", "orgOrDomainIdMissing": "ID da organização ou domínio está faltando",
"loadingDNSRecords": "Carregando registros DNS...", "loadingDNSRecords": "Carregando registros DNS...",
"olmUpdateAvailableInfo": "Uma versão atualizada do Olm está disponível. Atualize para a versão mais recente para ter a melhor experiência.", "olmUpdateAvailableInfo": "Uma versão atualizada do Olm está disponível. Atualize para a versão mais recente para ter a melhor experiência.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Uma versão atualizada está disponível. Por favor, atualize para a versão mais recente para uma melhor experiência.",
"client": "Cliente", "client": "Cliente",
"proxyProtocol": "Configurações de Protocolo Proxy", "proxyProtocol": "Configurações de Protocolo Proxy",
"proxyProtocolDescription": "Configurar o protocolo proxy para preservar endereços IP do cliente para serviços TCP.", "proxyProtocolDescription": "Configurar o protocolo proxy para preservar endereços IP do cliente para serviços TCP.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Локальный", "local": "Локальный",
"edit": "Редактировать", "edit": "Редактировать",
"siteConfirmDelete": "Подтвердить удаление сайта", "siteConfirmDelete": "Подтвердить удаление сайта",
"siteConfirmDeleteAndResources": "Подтвердите удаление сайта и ресурсов",
"siteDelete": "Удалить сайт", "siteDelete": "Удалить сайт",
"siteDeleteAndResources": "Удалить сайт и ресурсы",
"siteMessageRemove": "После удаления сайт больше не будет доступен. Все цели, связанные с сайтом, также будут удалены.", "siteMessageRemove": "После удаления сайт больше не будет доступен. Все цели, связанные с сайтом, также будут удалены.",
"siteMessageRemoveAndResources": "Это навсегда удалит все общественные и частные ресурсы, связанные с этим сайтом, даже если ресурс также связан с другими сайтами.",
"siteQuestionRemove": "Вы уверены, что хотите удалить сайт из организации?", "siteQuestionRemove": "Вы уверены, что хотите удалить сайт из организации?",
"siteQuestionRemoveAndResources": "Вы уверены, что хотите удалить этот сайт и все связанные с ним ресурсы?",
"sitesTableDeleteSite": "Удалить сайт",
"sitesTableDeleteSiteAndResources": "Удалить сайт и ресурсы",
"siteManageSites": "Управление сайтами", "siteManageSites": "Управление сайтами",
"siteDescription": "Создание и управление сайтами, чтобы включить подключение к приватным сетям", "siteDescription": "Создание и управление сайтами, чтобы включить подключение к приватным сетям",
"sitesBannerTitle": "Подключить любую сеть", "sitesBannerTitle": "Подключить любую сеть",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "Диапазон CIDR ресурса в сети сайта.", "createInternalResourceDialogDestinationCidrDescription": "Диапазон CIDR ресурса в сети сайта.",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "Дополнительный внутренний DNS псевдоним для этого ресурса.", "createInternalResourceDialogAliasDescription": "Дополнительный внутренний DNS псевдоним для этого ресурса.",
"internalResourceAliasLocalWarning": "Псевдонимы, оканчивающиеся на .local, могут вызывать проблемы с разрешением из-за mDNS в некоторых сетях.",
"internalResourceDownstreamSchemeRequired": "Схема обязательна для HTTP ресурсов", "internalResourceDownstreamSchemeRequired": "Схема обязательна для HTTP ресурсов",
"internalResourceHttpPortRequired": "Порт назначения обязателен для HTTP ресурсов", "internalResourceHttpPortRequired": "Порт назначения обязателен для HTTP ресурсов",
"siteConfiguration": "Конфигурация", "siteConfiguration": "Конфигурация",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Отсутствует организация или ID домена", "orgOrDomainIdMissing": "Отсутствует организация или ID домена",
"loadingDNSRecords": "Загрузка записей DNS...", "loadingDNSRecords": "Загрузка записей DNS...",
"olmUpdateAvailableInfo": "Доступна обновленная версия Олма. Пожалуйста, обновитесь до последней версии.", "olmUpdateAvailableInfo": "Доступна обновленная версия Олма. Пожалуйста, обновитесь до последней версии.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Доступна обновленная версия. Пожалуйста, обновитесь до последней версии для получения лучшего опыта.",
"client": "Клиент", "client": "Клиент",
"proxyProtocol": "Настройки протокола прокси", "proxyProtocol": "Настройки протокола прокси",
"proxyProtocolDescription": "Настроить Прокси-протокол для сохранения IP-адресов клиента для служб TCP.", "proxyProtocolDescription": "Настроить Прокси-протокол для сохранения IP-адресов клиента для служб TCP.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "Yerel", "local": "Yerel",
"edit": "Düzenle", "edit": "Düzenle",
"siteConfirmDelete": "Site Silmeyi Onayla", "siteConfirmDelete": "Site Silmeyi Onayla",
"siteConfirmDeleteAndResources": "Site ve Kaynakları Silmeyi Onayla",
"siteDelete": "Siteyi Sil", "siteDelete": "Siteyi Sil",
"siteDeleteAndResources": "Site ve Kaynakları Sil",
"siteMessageRemove": "Kaldırıldıktan sonra site artık erişilebilir olmayacaktır. Siteyle ilişkilendirilmiş tüm hedefler de kaldırılacaktır.", "siteMessageRemove": "Kaldırıldıktan sonra site artık erişilebilir olmayacaktır. Siteyle ilişkilendirilmiş tüm hedefler de kaldırılacaktır.",
"siteMessageRemoveAndResources": "Bu işlem, diğer sitelerle de ilişkilendirilmiş olsa bile, bu siteye bağlı tüm genel ve özel kaynakları kalıcı olarak silecektir.",
"siteQuestionRemove": "Siteyi organizasyondan kaldırmak istediğinizden emin misiniz?", "siteQuestionRemove": "Siteyi organizasyondan kaldırmak istediğinizden emin misiniz?",
"siteQuestionRemoveAndResources": "Bu siteyi ve tüm ilişkili kaynakları silmek istediğinizden emin misiniz?",
"sitesTableDeleteSite": "Siteyi Sil",
"sitesTableDeleteSiteAndResources": "Site ve Kaynakları Sil",
"siteManageSites": "Siteleri Yönet", "siteManageSites": "Siteleri Yönet",
"siteDescription": "Özel ağlara erişimi etkinleştirmek için siteler oluşturun ve yönetin", "siteDescription": "Özel ağlara erişimi etkinleştirmek için siteler oluşturun ve yönetin",
"sitesBannerTitle": "Herhangi Bir Ağa Bağlan", "sitesBannerTitle": "Herhangi Bir Ağa Bağlan",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "Site ağındaki kaynağın CIDR aralığı.", "createInternalResourceDialogDestinationCidrDescription": "Site ağındaki kaynağın CIDR aralığı.",
"createInternalResourceDialogAlias": "Takma Ad", "createInternalResourceDialogAlias": "Takma Ad",
"createInternalResourceDialogAliasDescription": "Bu kaynak için isteğe bağlı dahili DNS takma adı.", "createInternalResourceDialogAliasDescription": "Bu kaynak için isteğe bağlı dahili DNS takma adı.",
"internalResourceAliasLocalWarning": "Bazı ağlarda mDNS nedeniyle .local ile biten takma adlar çözümleme sorunlarına neden olabilir.",
"internalResourceDownstreamSchemeRequired": "HTTP kaynakları için şema gereklidir", "internalResourceDownstreamSchemeRequired": "HTTP kaynakları için şema gereklidir",
"internalResourceHttpPortRequired": "HTTP kaynakları için hedef bağlantı noktası gereklidir", "internalResourceHttpPortRequired": "HTTP kaynakları için hedef bağlantı noktası gereklidir",
"siteConfiguration": "Yapılandırma", "siteConfiguration": "Yapılandırma",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "Organizasyon veya Alan Adı Kimliği eksik", "orgOrDomainIdMissing": "Organizasyon veya Alan Adı Kimliği eksik",
"loadingDNSRecords": "DNS kayıtları yükleniyor...", "loadingDNSRecords": "DNS kayıtları yükleniyor...",
"olmUpdateAvailableInfo": "Olm'nin güncellenmiş bir sürümü mevcut. En iyi deneyim için lütfen en son sürüme güncelleyin.", "olmUpdateAvailableInfo": "Olm'nin güncellenmiş bir sürümü mevcut. En iyi deneyim için lütfen en son sürüme güncelleyin.",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "Güncellenmiş bir sürüm mevcut. En iyi deneyim için lütfen en son sürüme güncelleyin.",
"client": "İstemci", "client": "İstemci",
"proxyProtocol": "Proxy Protokol Ayarları", "proxyProtocol": "Proxy Protokol Ayarları",
"proxyProtocolDescription": "TCP hizmetleri için istemci IP adreslerini korumak amacıyla Proxy Protokolünü yapılandırın.", "proxyProtocolDescription": "TCP hizmetleri için istemci IP adreslerini korumak amacıyla Proxy Protokolünü yapılandırın.",
+8 -1
View File
@@ -66,9 +66,15 @@
"local": "本地的", "local": "本地的",
"edit": "编辑", "edit": "编辑",
"siteConfirmDelete": "确认删除节点", "siteConfirmDelete": "确认删除节点",
"siteConfirmDeleteAndResources": "确认删除站点及资源",
"siteDelete": "删除节点", "siteDelete": "删除节点",
"siteDeleteAndResources": "删除站点及资源",
"siteMessageRemove": "一旦移除,节点将无法访问。与节点相关的所有目标也将被移除。", "siteMessageRemove": "一旦移除,节点将无法访问。与节点相关的所有目标也将被移除。",
"siteMessageRemoveAndResources": "这将永久删除与该站点关联的所有公共和私人资源,即使资源也与其他站点相关联。",
"siteQuestionRemove": "您确定要从组织中删除该节点吗?", "siteQuestionRemove": "您确定要从组织中删除该节点吗?",
"siteQuestionRemoveAndResources": "您确定要删除此站点及所有关联资源吗?",
"sitesTableDeleteSite": "删除站点",
"sitesTableDeleteSiteAndResources": "删除站点及资源",
"siteManageSites": "管理站点", "siteManageSites": "管理站点",
"siteDescription": "创建和管理站点,启用与私人网络的连接", "siteDescription": "创建和管理站点,启用与私人网络的连接",
"sitesBannerTitle": "连接任何网络", "sitesBannerTitle": "连接任何网络",
@@ -2338,6 +2344,7 @@
"createInternalResourceDialogDestinationCidrDescription": "站点网络上资源的 CIDR 范围。", "createInternalResourceDialogDestinationCidrDescription": "站点网络上资源的 CIDR 范围。",
"createInternalResourceDialogAlias": "Alias", "createInternalResourceDialogAlias": "Alias",
"createInternalResourceDialogAliasDescription": "此资源可选的内部DNS别名。", "createInternalResourceDialogAliasDescription": "此资源可选的内部DNS别名。",
"internalResourceAliasLocalWarning": "以 .local 结尾的别名可能会因某些网络上的 mDNS 而导致解析问题。",
"internalResourceDownstreamSchemeRequired": "HTTP 资源需要方案", "internalResourceDownstreamSchemeRequired": "HTTP 资源需要方案",
"internalResourceHttpPortRequired": "HTTP 资源需要目的端口", "internalResourceHttpPortRequired": "HTTP 资源需要目的端口",
"siteConfiguration": "配置", "siteConfiguration": "配置",
@@ -2967,7 +2974,7 @@
"orgOrDomainIdMissing": "缺少机构或域 ID", "orgOrDomainIdMissing": "缺少机构或域 ID",
"loadingDNSRecords": "正在载入DNS记录...", "loadingDNSRecords": "正在载入DNS记录...",
"olmUpdateAvailableInfo": "有最新版本的 Olm 可用。请更新到最新版本以获取最佳体验。", "olmUpdateAvailableInfo": "有最新版本的 Olm 可用。请更新到最新版本以获取最佳体验。",
"updateAvailableInfo": "An updated version is available. Please update to the latest version for the best experience.", "updateAvailableInfo": "有新版本可用。请更新到最新版本以获得最佳体验。",
"client": "客户端:", "client": "客户端:",
"proxyProtocol": "代理协议设置", "proxyProtocol": "代理协议设置",
"proxyProtocolDescription": "配置代理协议以保留TCP服务的客户端 IP 地址。", "proxyProtocolDescription": "配置代理协议以保留TCP服务的客户端 IP 地址。",
+7 -4
View File
@@ -795,10 +795,13 @@ export const COUNTRIES = [
name: "Serbia", name: "Serbia",
code: "RS" code: "RS"
}, },
{ // Removed as this is a deprecated ISO country code, not supported anymore
name: "Serbia and Montenegro", // Also the individual flags for Serbia & Montenegro are already included in the list
code: "CS" // more details: https://en.wikipedia.org/wiki/ISO_3166-2:CS
}, // {
// name: "Serbia and Montenegro",
// code: "CS"
// },
{ {
name: "Seychelles", name: "Seychelles",
code: "SC" code: "SC"
+3 -1
View File
@@ -172,7 +172,9 @@ export async function applyBlueprint({
} catch (err) { } catch (err) {
blueprintSucceeded = false; blueprintSucceeded = false;
blueprintMessage = `Blueprint applied with errors: ${err}`; blueprintMessage = `Blueprint applied with errors: ${err}`;
logger.error(blueprintMessage); logger.debug(
`Org ${orgId} blueprint apply issues: ${blueprintMessage}`
);
error = err; error = err;
} }
+31 -53
View File
@@ -29,7 +29,7 @@ type ClientRow = typeof clients.$inferSelect;
function runQueuedClientAssociationRebuilds( function runQueuedClientAssociationRebuilds(
userId: string, userId: string,
queuedClients: ClientRow[] queuedClients: ClientRow[]
): void { ) {
if (queuedClients.length === 0) { if (queuedClients.length === 0) {
return; return;
} }
@@ -39,35 +39,29 @@ function runQueuedClientAssociationRebuilds(
uniqueClientsById.set(client.clientId, client); uniqueClientsById.set(client.clientId, client);
} }
void (async () => {
for (const client of uniqueClientsById.values()) { for (const client of uniqueClientsById.values()) {
try { rebuildClientAssociationsFromClient(client).catch((error) => {
await rebuildClientAssociationsFromClient(client);
} catch (error) {
logger.error( logger.error(
`Failed rebuilding associations for client ${client.clientId} (user ${userId}): ${String(error)}` `Error rebuilding client associations for client ${client.clientId} (user ${userId}): ${String(
error
)}`
); );
} });
} }
logger.debug( logger.debug(
`Queued association rebuild completed for ${uniqueClientsById.size} client(s) (user ${userId})` `Queued association rebuild completed for ${uniqueClientsById.size} client(s) (user ${userId})`
); );
})();
} }
export async function calculateUserClientsForOrgs( export async function calculateUserClientsForOrgs(
userId: string userId: string
): Promise<void> { ): Promise<void> {
const trx = primaryDb; const trx = primaryDb;
const queuedAssociationRebuilds: ClientRow[] = [];
const execute = async (transaction: Transaction | typeof db) => { const queuedAssociationRebuilds: ClientRow[] = [];
const orgCache = new Map<string, typeof orgs.$inferSelect | null>(); const orgCache = new Map<string, typeof orgs.$inferSelect | null>();
const adminRoleCache = new Map< const adminRoleCache = new Map<string, typeof roles.$inferSelect | null>();
string,
typeof roles.$inferSelect | null
>();
const exitNodesCache = new Map< const exitNodesCache = new Map<
string, string,
Awaited<ReturnType<typeof listExitNodes>> Awaited<ReturnType<typeof listExitNodes>>
@@ -80,8 +74,7 @@ export async function calculateUserClientsForOrgs(
const roleClientAccessCache = new Map<string, boolean>(); const roleClientAccessCache = new Map<string, boolean>();
const userClientAccessCache = new Map<string, boolean>(); const userClientAccessCache = new Map<string, boolean>();
const getOrgOlmKey = (orgId: string, olmId: string) => const getOrgOlmKey = (orgId: string, olmId: string) => `${orgId}:${olmId}`;
`${orgId}:${olmId}`;
const getRoleClientKey = (roleId: number, clientId: number) => const getRoleClientKey = (roleId: number, clientId: number) =>
`${roleId}:${clientId}`; `${roleId}:${clientId}`;
const getUserClientKey = (cachedUserId: string, clientId: number) => const getUserClientKey = (cachedUserId: string, clientId: number) =>
@@ -92,7 +85,7 @@ export async function calculateUserClientsForOrgs(
return orgCache.get(orgId) ?? null; return orgCache.get(orgId) ?? null;
} }
const [org] = await transaction const [org] = await trx
.select() .select()
.from(orgs) .from(orgs)
.where(eq(orgs.orgId, orgId)); .where(eq(orgs.orgId, orgId));
@@ -106,7 +99,7 @@ export async function calculateUserClientsForOrgs(
return adminRoleCache.get(orgId) ?? null; return adminRoleCache.get(orgId) ?? null;
} }
const [adminRole] = await transaction const [adminRole] = await trx
.select() .select()
.from(roles) .from(roles)
.where(and(eq(roles.isAdmin, true), eq(roles.orgId, orgId))) .where(and(eq(roles.isAdmin, true), eq(roles.orgId, orgId)))
@@ -147,7 +140,7 @@ export async function calculateUserClientsForOrgs(
return existingClientCache.get(key) ?? null; return existingClientCache.get(key) ?? null;
} }
const [existingClient] = await transaction const [existingClient] = await trx
.select() .select()
.from(clients) .from(clients)
.where( .where(
@@ -164,16 +157,13 @@ export async function calculateUserClientsForOrgs(
return existingClient ?? null; return existingClient ?? null;
}; };
const hasRoleClientAccess = async ( const hasRoleClientAccess = async (roleId: number, clientId: number) => {
roleId: number,
clientId: number
) => {
const key = getRoleClientKey(roleId, clientId); const key = getRoleClientKey(roleId, clientId);
if (roleClientAccessCache.has(key)) { if (roleClientAccessCache.has(key)) {
return roleClientAccessCache.get(key)!; return roleClientAccessCache.get(key)!;
} }
const [existingRoleClient] = await transaction const [existingRoleClient] = await trx
.select() .select()
.from(roleClients) .from(roleClients)
.where( .where(
@@ -199,7 +189,7 @@ export async function calculateUserClientsForOrgs(
return userClientAccessCache.get(key)!; return userClientAccessCache.get(key)!;
} }
const [existingUserClient] = await transaction const [existingUserClient] = await trx
.select() .select()
.from(userClients) .from(userClients)
.where( .where(
@@ -217,7 +207,7 @@ export async function calculateUserClientsForOrgs(
}; };
// Get all OLMs for this user // Get all OLMs for this user
const userOlms = await transaction const userOlms = await trx
.select() .select()
.from(olms) .from(olms)
.where(eq(olms.userId, userId)); .where(eq(olms.userId, userId));
@@ -226,7 +216,7 @@ export async function calculateUserClientsForOrgs(
// No OLMs for this user, but we should still clean up any orphaned clients // No OLMs for this user, but we should still clean up any orphaned clients
await cleanupOrphanedClients( await cleanupOrphanedClients(
userId, userId,
transaction, trx,
[], [],
queuedAssociationRebuilds queuedAssociationRebuilds
); );
@@ -234,7 +224,7 @@ export async function calculateUserClientsForOrgs(
} }
// Get all user orgs with all roles (for org list and role-based logic) // Get all user orgs with all roles (for org list and role-based logic)
const userOrgRoleRows = await transaction const userOrgRoleRows = await trx
.select() .select()
.from(userOrgs) .from(userOrgs)
.innerJoin( .innerJoin(
@@ -250,10 +240,7 @@ export async function calculateUserClientsForOrgs(
const userOrgIds = [ const userOrgIds = [
...new Set(userOrgRoleRows.map((r) => r.userOrgs.orgId)) ...new Set(userOrgRoleRows.map((r) => r.userOrgs.orgId))
]; ];
const orgIdToRoleRows = new Map< const orgIdToRoleRows = new Map<string, (typeof userOrgRoleRows)[0][]>();
string,
(typeof userOrgRoleRows)[0][]
>();
for (const r of userOrgRoleRows) { for (const r of userOrgRoleRows) {
const list = orgIdToRoleRows.get(r.userOrgs.orgId) ?? []; const list = orgIdToRoleRows.get(r.userOrgs.orgId) ?? [];
list.push(r); list.push(r);
@@ -300,10 +287,7 @@ export async function calculateUserClientsForOrgs(
} }
// Check if a client already exists for this OLM+user+org combination // Check if a client already exists for this OLM+user+org combination
const existingClient = await getExistingClient( const existingClient = await getExistingClient(orgId, olm.olmId);
orgId,
olm.olmId
);
if (existingClient) { if (existingClient) {
// Ensure admin role has access to the client // Ensure admin role has access to the client
@@ -313,7 +297,7 @@ export async function calculateUserClientsForOrgs(
); );
if (!hasRoleAccess) { if (!hasRoleAccess) {
await transaction.insert(roleClients).values({ await trx.insert(roleClients).values({
roleId: adminRole.roleId, roleId: adminRole.roleId,
clientId: existingClient.clientId clientId: existingClient.clientId
}); });
@@ -336,7 +320,7 @@ export async function calculateUserClientsForOrgs(
); );
if (!hasUserAccess) { if (!hasUserAccess) {
await transaction.insert(userClients).values({ await trx.insert(userClients).values({
userId, userId,
clientId: existingClient.clientId clientId: existingClient.clientId
}); });
@@ -366,13 +350,11 @@ export async function calculateUserClientsForOrgs(
} }
const randomExitNode = const randomExitNode =
exitNodesList[ exitNodesList[Math.floor(Math.random() * exitNodesList.length)];
Math.floor(Math.random() * exitNodesList.length)
];
// Get next available subnet // Get next available subnet
const { value: newSubnet, release: releaseSubnetLock } = const { value: newSubnet, release: releaseSubnetLock } =
await getNextAvailableClientSubnet(orgId, transaction); await getNextAvailableClientSubnet(orgId, trx);
const subnet = newSubnet.split("/")[0]; const subnet = newSubnet.split("/")[0];
const updatedSubnet = `${subnet}/${org.subnet.split("/")[1]}`; const updatedSubnet = `${subnet}/${org.subnet.split("/")[1]}`;
@@ -398,19 +380,16 @@ export async function calculateUserClientsForOrgs(
}; };
// Create the client // Create the client
const [newClient] = await transaction const [newClient] = await trx
.insert(clients) .insert(clients)
.values(newClientData) .values(newClientData)
.returning(); .returning();
await releaseSubnetLock(); await releaseSubnetLock();
existingClientCache.set( existingClientCache.set(getOrgOlmKey(orgId, olm.olmId), newClient);
getOrgOlmKey(orgId, olm.olmId),
newClient
);
// create approval request // create approval request
if (requireApproval) { if (requireApproval) {
await transaction await trx
.insert(approvals) .insert(approvals)
.values({ .values({
timestamp: Math.floor(new Date().getTime() / 1000), timestamp: Math.floor(new Date().getTime() / 1000),
@@ -425,7 +404,7 @@ export async function calculateUserClientsForOrgs(
queuedAssociationRebuilds.push(newClient); queuedAssociationRebuilds.push(newClient);
// Grant admin role access to the client // Grant admin role access to the client
await transaction.insert(roleClients).values({ await trx.insert(roleClients).values({
roleId: adminRole.roleId, roleId: adminRole.roleId,
clientId: newClient.clientId clientId: newClient.clientId
}); });
@@ -435,7 +414,7 @@ export async function calculateUserClientsForOrgs(
); );
// Grant user access to the client // Grant user access to the client
await transaction.insert(userClients).values({ await trx.insert(userClients).values({
userId, userId,
clientId: newClient.clientId clientId: newClient.clientId
}); });
@@ -453,11 +432,10 @@ export async function calculateUserClientsForOrgs(
// Clean up clients in orgs the user is no longer in // Clean up clients in orgs the user is no longer in
await cleanupOrphanedClients( await cleanupOrphanedClients(
userId, userId,
transaction, trx,
userOrgIds, userOrgIds,
queuedAssociationRebuilds queuedAssociationRebuilds
); );
};
runQueuedClientAssociationRebuilds(userId, queuedAssociationRebuilds); runQueuedClientAssociationRebuilds(userId, queuedAssociationRebuilds);
} }
@@ -496,7 +474,7 @@ async function cleanupOrphanedClients(
) )
.returning(); .returning();
// Queue deleted clients for post-transaction association cleanup. // Queue deleted clients for post-trx association cleanup.
for (const deletedClient of deletedClients) { for (const deletedClient of deletedClients) {
queuedAssociationRebuilds.push(deletedClient); queuedAssociationRebuilds.push(deletedClient);
+1 -10
View File
@@ -197,15 +197,6 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
policyCheck policyCheck
}); });
if (policyCheck?.error) {
logger.error(
`[handleOlmRegisterMessage] Error checking access policies for olm user ${olm.userId} in org ${orgId}: ${policyCheck?.error}`,
{ orgId: client.orgId, clientId: client.clientId }
);
sendOlmError(OlmErrorCodes.ORG_ACCESS_POLICY_DENIED, olm.olmId);
return;
}
if (policyCheck.policies?.passwordAge?.compliant === false) { if (policyCheck.policies?.passwordAge?.compliant === false) {
logger.warn( logger.warn(
`[handleOlmRegisterMessage] Olm user ${olm.userId} has non-compliant password age for org ${orgId}`, `[handleOlmRegisterMessage] Olm user ${olm.userId} has non-compliant password age for org ${orgId}`,
@@ -238,7 +229,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
olm.olmId olm.olmId
); );
return; return;
} else if (!policyCheck.allowed) { } else if (!policyCheck.allowed || policyCheck.error) {
logger.warn( logger.warn(
`[handleOlmRegisterMessage] Olm user ${olm.userId} does not pass access policies for org ${orgId}: ${policyCheck.error}`, `[handleOlmRegisterMessage] Olm user ${olm.userId} does not pass access policies for org ${orgId}: ${policyCheck.error}`,
{ orgId: client.orgId, clientId: client.clientId } { orgId: client.orgId, clientId: client.clientId }
@@ -76,6 +76,15 @@ export async function setResourcePolicyHeaderAuth(
const { resourcePolicyId } = parsedParams.data; const { resourcePolicyId } = parsedParams.data;
const { headerAuth } = parsedBody.data; const { headerAuth } = parsedBody.data;
const headerAuthHash =
headerAuth !== null
? await hashPassword(
Buffer.from(
`${headerAuth.user}:${headerAuth.password}`
).toString("base64")
)
: null;
await db.transaction(async (trx) => { await db.transaction(async (trx) => {
await trx await trx
.delete(resourcePolicyHeaderAuth) .delete(resourcePolicyHeaderAuth)
@@ -86,13 +95,7 @@ export async function setResourcePolicyHeaderAuth(
) )
); );
if (headerAuth !== null) { if (headerAuth !== null && headerAuthHash !== null) {
const headerAuthHash = await hashPassword(
Buffer.from(
`${headerAuth.user}:${headerAuth.password}`
).toString("base64")
);
await trx.insert(resourcePolicyHeaderAuth).values({ await trx.insert(resourcePolicyHeaderAuth).values({
resourcePolicyId, resourcePolicyId,
headerAuthHash, headerAuthHash,
@@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db, resourcePolicyRules, resourcePolicies } from "@server/db"; import { db, resourcePolicyRules, resourcePolicies } from "@server/db";
import { eq } from "drizzle-orm"; import { and, eq, notInArray } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
@@ -14,6 +14,7 @@ import {
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
const ruleSchema = z.strictObject({ const ruleSchema = z.strictObject({
ruleId: z.int().positive().optional(),
action: z.enum(["ACCEPT", "DROP", "PASS"]).openapi({ action: z.enum(["ACCEPT", "DROP", "PASS"]).openapi({
type: "string", type: "string",
enum: ["ACCEPT", "DROP", "PASS"], enum: ["ACCEPT", "DROP", "PASS"],
@@ -121,17 +122,74 @@ export async function setResourcePolicyRules(
.set({ applyRules }) .set({ applyRules })
.where(eq(resourcePolicies.resourcePolicyId, resourcePolicyId)); .where(eq(resourcePolicies.resourcePolicyId, resourcePolicyId));
const incomingRuleIds = rules
.map((r) => r.ruleId)
.filter((id): id is number => id !== undefined);
// Delete rules that are no longer in the incoming list
if (incomingRuleIds.length > 0) {
await trx await trx
.delete(resourcePolicyRules) .delete(resourcePolicyRules)
.where( .where(
eq(resourcePolicyRules.resourcePolicyId, resourcePolicyId) and(
eq(
resourcePolicyRules.resourcePolicyId,
resourcePolicyId
),
notInArray(
resourcePolicyRules.ruleId,
incomingRuleIds
)
)
); );
} else {
await trx
.delete(resourcePolicyRules)
.where(
eq(
resourcePolicyRules.resourcePolicyId,
resourcePolicyId
)
);
}
if (rules.length > 0) { // Update existing rules (those with a ruleId)
const existingRules = rules.filter(
(r): r is typeof r & { ruleId: number } =>
r.ruleId !== undefined
);
for (const rule of existingRules) {
await trx
.update(resourcePolicyRules)
.set({
action: rule.action,
match: rule.match,
value: rule.value,
priority: rule.priority,
enabled: rule.enabled
})
.where(
and(
eq(resourcePolicyRules.ruleId, rule.ruleId),
eq(
resourcePolicyRules.resourcePolicyId,
resourcePolicyId
)
)
);
}
// Insert new rules (those without a ruleId)
const newRules = rules.filter((r) => r.ruleId === undefined);
if (newRules.length > 0) {
await trx.insert(resourcePolicyRules).values( await trx.insert(resourcePolicyRules).values(
rules.map((rule) => ({ newRules.map((rule) => ({
resourcePolicyId, resourcePolicyId,
...rule action: rule.action,
match: rule.match,
value: rule.value,
priority: rule.priority,
enabled: rule.enabled
})) }))
); );
} }
@@ -107,6 +107,13 @@ export async function setResourceHeaderAuth(
resource.resourcePolicyId === null && resource.resourcePolicyId === null &&
resource.defaultResourcePolicyId !== null; resource.defaultResourcePolicyId !== null;
const headerAuthHash =
user && password && extendedCompatibility !== null
? await hashPassword(
Buffer.from(`${user}:${password}`).toString("base64")
)
: null;
await db.transaction(async (trx) => { await db.transaction(async (trx) => {
if (isInlinePolicy) { if (isInlinePolicy) {
const policyId = resource.defaultResourcePolicyId!; const policyId = resource.defaultResourcePolicyId!;
@@ -116,11 +123,7 @@ export async function setResourceHeaderAuth(
eq(resourcePolicyHeaderAuth.resourcePolicyId, policyId) eq(resourcePolicyHeaderAuth.resourcePolicyId, policyId)
); );
if (user && password && extendedCompatibility !== null) { if (headerAuthHash !== null && extendedCompatibility !== null) {
const headerAuthHash = await hashPassword(
Buffer.from(`${user}:${password}`).toString("base64")
);
await trx.insert(resourcePolicyHeaderAuth).values({ await trx.insert(resourcePolicyHeaderAuth).values({
resourcePolicyId: policyId, resourcePolicyId: policyId,
headerAuthHash, headerAuthHash,
@@ -140,11 +143,7 @@ export async function setResourceHeaderAuth(
) )
); );
if (user && password && extendedCompatibility !== null) { if (headerAuthHash !== null && extendedCompatibility !== null) {
const headerAuthHash = await hashPassword(
Buffer.from(`${user}:${password}`).toString("base64")
);
await Promise.all([ await Promise.all([
trx trx
.insert(resourceHeaderAuth) .insert(resourceHeaderAuth)
+6 -1
View File
@@ -10,6 +10,7 @@ import logger from "@server/logger";
import stoi from "@server/lib/stoi"; import stoi from "@server/lib/stoi";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { getCountryCodeForIp } from "@server/lib/geoip";
const getSiteSchema = z.strictObject({ const getSiteSchema = z.strictObject({
siteId: z siteId: z
@@ -47,6 +48,7 @@ type SiteQueryRow = NonNullable<Awaited<ReturnType<typeof query>>>;
export type GetSiteResponse = SiteQueryRow["sites"] & { export type GetSiteResponse = SiteQueryRow["sites"] & {
newtId: string | null; newtId: string | null;
newtVersion: string | null; newtVersion: string | null;
countryCode: string | null;
}; };
registry.registerPath({ registry.registerPath({
@@ -134,7 +136,10 @@ export async function getSite(
const data: GetSiteResponse = { const data: GetSiteResponse = {
...site.sites, ...site.sites,
newtId: site.newt ? site.newt.newtId : null, newtId: site.newt ? site.newt.newtId : null,
newtVersion: site.newt?.version ?? null newtVersion: site.newt?.version ?? null,
countryCode: site.sites.endpoint
? ((await getCountryCodeForIp(site.sites.endpoint)) ?? null)
: null
}; };
return response<GetSiteResponse>(res, { return response<GetSiteResponse>(res, {
+9 -1
View File
@@ -19,7 +19,7 @@ export default function OrgInfoCard({}: OrgInfoCardProps) {
return ( return (
<Alert> <Alert>
<AlertDescription> <AlertDescription>
<InfoSections cols={3}> <InfoSections cols={4}>
<InfoSection> <InfoSection>
<InfoSectionTitle>{t("name")}</InfoSectionTitle> <InfoSectionTitle>{t("name")}</InfoSectionTitle>
<InfoSectionContent>{org.org.name}</InfoSectionContent> <InfoSectionContent>{org.org.name}</InfoSectionContent>
@@ -34,6 +34,14 @@ export default function OrgInfoCard({}: OrgInfoCardProps) {
{org.org.subnet || t("none")} {org.org.subnet || t("none")}
</InfoSectionContent> </InfoSectionContent>
</InfoSection> </InfoSection>
<InfoSection>
<InfoSectionTitle>
{t("utilitySubnet")}
</InfoSectionTitle>
<InfoSectionContent>
{org.org.utilitySubnet || t("none")}
</InfoSectionContent>
</InfoSection>
</InfoSections> </InfoSections>
</AlertDescription> </AlertDescription>
</Alert> </Alert>
+6 -1
View File
@@ -9,6 +9,7 @@ import {
InfoSectionTitle InfoSectionTitle
} from "@app/components/InfoSection"; } from "@app/components/InfoSection";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
type SiteInfoCardProps = {}; type SiteInfoCardProps = {};
@@ -52,7 +53,11 @@ export default function SiteInfoCard({}: SiteInfoCardProps) {
<InfoSection> <InfoSection>
<InfoSectionTitle>{t("publicIpEndpoint")}</InfoSectionTitle> <InfoSectionTitle>{t("publicIpEndpoint")}</InfoSectionTitle>
<InfoSectionContent> <InfoSectionContent>
{formatPublicEndpoint(site.endpoint)} {formatPublicEndpoint(site.endpoint)}&nbsp;
<span className="text-lg">
{site.countryCode &&
countryCodeToFlagEmoji(site.countryCode)}
</span>
</InfoSectionContent> </InfoSectionContent>
</InfoSection> </InfoSection>
) : null; ) : null;
@@ -340,7 +340,8 @@ function PolicyAccessRulesSectionEdit({
? rules.filter((rule) => !rule.fromPolicy) ? rules.filter((rule) => !rule.fromPolicy)
: rules; : rules;
const rulesPayload = rulesToValidate.map( const rulesPayload = rulesToValidate.map(
({ action, match, value, priority, enabled }) => ({ ({ ruleId, action, match, value, priority, enabled, new: isNew }) => ({
...(isNew ? {} : { ruleId }),
action, action,
match, match,
value, value,
@@ -74,6 +74,8 @@ import {
sortPolicyRulesForResourceOverlay, sortPolicyRulesForResourceOverlay,
type PolicyAccessRule type PolicyAccessRule
} from "./policy-access-rule-utils"; } from "./policy-access-rule-utils";
import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji";
import type { readonly } from "zod";
export type PolicyAccessRulesTableProps = { export type PolicyAccessRulesTableProps = {
rules: PolicyAccessRule[]; rules: PolicyAccessRule[];
@@ -498,8 +500,17 @@ export function PolicyAccessRulesTable({
{ {
accessorKey: "value", accessorKey: "value",
header: () => <span className="p-3">{t("value")}</span>, header: () => <span className="p-3">{t("value")}</span>,
cell: ({ row }) => cell: ({ row }) => {
row.original.match === "COUNTRY" || let selectedCountry: (typeof COUNTRIES)[number] | undefined;
if (
row.original.match === "COUNTRY" &&
row.original.value
) {
selectedCountry = COUNTRIES.find(
(c) => c.code === row.original.value
);
}
return row.original.match === "COUNTRY" ||
row.original.match === "COUNTRY_IS_NOT" ? ( row.original.match === "COUNTRY_IS_NOT" ? (
<Popover> <Popover>
<PopoverTrigger asChild> <PopoverTrigger asChild>
@@ -511,15 +522,22 @@ export function PolicyAccessRulesTable({
} }
className="w-full min-w-0 justify-between" className="w-full min-w-0 justify-between"
> >
{row.original.value {selectedCountry ? (
? COUNTRIES.find( <>
(c) => <span>
c.code === row.original.value {selectedCountry.code === "ALL"
)?.name + ? "🌍"
" (" + : countryCodeToFlagEmoji(
row.original.value + selectedCountry.code
")" )}
: t("selectCountry")} &nbsp;&nbsp;
{selectedCountry.name} (
{selectedCountry.code})
</span>
</>
) : (
t("selectCountry")
)}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" /> <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
@@ -549,6 +567,13 @@ export function PolicyAccessRulesTable({
<Check <Check
className={`mr-2 h-4 w-4 ${row.original.value === country.code ? "opacity-100" : "opacity-0"}`} className={`mr-2 h-4 w-4 ${row.original.value === country.code ? "opacity-100" : "opacity-0"}`}
/> />
<span>
{country.code === "ALL"
? "🌍"
: countryCodeToFlagEmoji(
country.code
)}
</span>
{country.name} ( {country.name} (
{country.code}) {country.code})
</CommandItem> </CommandItem>
@@ -776,7 +801,8 @@ export function PolicyAccessRulesTable({
}); });
}} }}
/> />
) );
}
}, },
{ {
accessorKey: "enabled", accessorKey: "enabled",