diff --git a/messages/bg-BG.json b/messages/bg-BG.json index a388c4d9..9208a18d 100644 --- a/messages/bg-BG.json +++ b/messages/bg-BG.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "An error occurred while adding user to the role.", "userSaved": "User saved", "userSavedDescription": "The user has been updated.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Manage what this user can access and do in the organization", "accessControlsSubmit": "Save Access Controls", "roles": "Roles", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Connected", "idpErrorConnectingTo": "There was a problem connecting to {name}. Please contact your administrator.", "idpErrorNotFound": "IdP not found", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Invalid Invite", "inviteInvalidDescription": "The invite link is invalid.", "inviteErrorWrongUser": "Invite is not for this user", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Professional Edition Required", "licenseTierProfessionalRequiredDescription": "This feature is only available in the Professional Edition.", "actionGetOrg": "Get Organization", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Update Organization", "actionUpdateUser": "Update User", "actionGetUser": "Get User", @@ -1496,5 +1502,7 @@ "convertButton": "Convert This Node to Managed Self-Hosted" }, "internationaldomaindetected": "International Domain Detected", - "willbestoredas": "Will be stored as:" + "willbestoredas": "Will be stored as:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/cs-CZ.json b/messages/cs-CZ.json index eae522ee..d1b2703e 100644 --- a/messages/cs-CZ.json +++ b/messages/cs-CZ.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "An error occurred while adding user to the role.", "userSaved": "User saved", "userSavedDescription": "The user has been updated.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Manage what this user can access and do in the organization", "accessControlsSubmit": "Save Access Controls", "roles": "Roles", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Connected", "idpErrorConnectingTo": "There was a problem connecting to {name}. Please contact your administrator.", "idpErrorNotFound": "IdP not found", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Invalid Invite", "inviteInvalidDescription": "The invite link is invalid.", "inviteErrorWrongUser": "Invite is not for this user", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Professional Edition Required", "licenseTierProfessionalRequiredDescription": "This feature is only available in the Professional Edition.", "actionGetOrg": "Get Organization", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Update Organization", "actionUpdateUser": "Update User", "actionGetUser": "Get User", @@ -1496,5 +1502,7 @@ "convertButton": "Convert This Node to Managed Self-Hosted" }, "internationaldomaindetected": "International Domain Detected", - "willbestoredas": "Will be stored as:" + "willbestoredas": "Will be stored as:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/de-DE.json b/messages/de-DE.json index 20e9e9ba..a3bc6be3 100644 --- a/messages/de-DE.json +++ b/messages/de-DE.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Beim Hinzufügen des Benutzers zur Rolle ist ein Fehler aufgetreten.", "userSaved": "Benutzer gespeichert", "userSavedDescription": "Der Benutzer wurde aktualisiert.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Verwalten Sie, worauf dieser Benutzer in der Organisation zugreifen und was er tun kann", "accessControlsSubmit": "Zugriffskontrollen speichern", "roles": "Rollen", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Verbunden", "idpErrorConnectingTo": "Es gab ein Problem bei der Verbindung zu {name}. Bitte kontaktieren Sie Ihren Administrator.", "idpErrorNotFound": "IdP nicht gefunden", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Ungültige Einladung", "inviteInvalidDescription": "Der Einladungslink ist ungültig.", "inviteErrorWrongUser": "Einladung ist nicht für diesen Benutzer", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Professional Edition erforderlich", "licenseTierProfessionalRequiredDescription": "Diese Funktion ist nur in der Professional Edition verfügbar.", "actionGetOrg": "Organisation abrufen", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Organisation aktualisieren", "actionUpdateUser": "Benutzer aktualisieren", "actionGetUser": "Benutzer abrufen", @@ -1496,5 +1502,7 @@ "convertButton": "Diesen Knoten in Managed Self-Hosted umwandeln" }, "internationaldomaindetected": "Internationale Domain erkannt", - "willbestoredas": "Wird gespeichert als:" + "willbestoredas": "Wird gespeichert als:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/es-ES.json b/messages/es-ES.json index a4fb0646..3be67893 100644 --- a/messages/es-ES.json +++ b/messages/es-ES.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Ocurrió un error mientras se añadía el usuario al rol.", "userSaved": "Usuario guardado", "userSavedDescription": "El usuario ha sido actualizado.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Administrar lo que este usuario puede acceder y hacer en la organización", "accessControlsSubmit": "Guardar controles de acceso", "roles": "Roles", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Conectado", "idpErrorConnectingTo": "Hubo un problema al conectar con {name}. Por favor, póngase en contacto con su administrador.", "idpErrorNotFound": "IdP no encontrado", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Invitación inválida", "inviteInvalidDescription": "El enlace de invitación no es válido.", "inviteErrorWrongUser": "La invitación no es para este usuario", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Edición Profesional requerida", "licenseTierProfessionalRequiredDescription": "Esta característica sólo está disponible en la Edición Profesional.", "actionGetOrg": "Obtener organización", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Actualizar organización", "actionUpdateUser": "Actualizar usuario", "actionGetUser": "Obtener usuario", @@ -1496,5 +1502,7 @@ "convertButton": "Convierte este nodo a autoalojado administrado" }, "internationaldomaindetected": "Dominio Internacional detectado", - "willbestoredas": "Se almacenará como:" + "willbestoredas": "Se almacenará como:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/fr-FR.json b/messages/fr-FR.json index a7d4a74f..eff4b2e8 100644 --- a/messages/fr-FR.json +++ b/messages/fr-FR.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Une erreur s'est produite lors de l'ajout de l'utilisateur au rôle.", "userSaved": "Utilisateur enregistré", "userSavedDescription": "L'utilisateur a été mis à jour.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Gérer ce que cet utilisateur peut accéder et faire dans l'organisation", "accessControlsSubmit": "Enregistrer les contrôles d'accès", "roles": "Rôles", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Connecté", "idpErrorConnectingTo": "Un problème est survenu lors de la connexion à {name}. Veuillez contacter votre administrateur.", "idpErrorNotFound": "IdP introuvable", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Invitation invalide", "inviteInvalidDescription": "Le lien d'invitation n'est pas valide.", "inviteErrorWrongUser": "L'invitation n'est pas pour cet utilisateur", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Édition Professionnelle Requise", "licenseTierProfessionalRequiredDescription": "Cette fonctionnalité n'est disponible que dans l'Édition Professionnelle.", "actionGetOrg": "Obtenir l'organisation", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Mettre à jour l'organisation", "actionUpdateUser": "Mettre à jour l'utilisateur", "actionGetUser": "Obtenir l'utilisateur", @@ -1496,5 +1502,7 @@ "convertButton": "Convertir ce noeud en auto-hébergé géré" }, "internationaldomaindetected": "Domaine international détecté", - "willbestoredas": "Sera stocké comme :" + "willbestoredas": "Sera stocké comme :", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/it-IT.json b/messages/it-IT.json index 489a5bcd..377fe4ce 100644 --- a/messages/it-IT.json +++ b/messages/it-IT.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Si è verificato un errore durante l'aggiunta dell'utente al ruolo.", "userSaved": "Utente salvato", "userSavedDescription": "L'utente è stato aggiornato.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Gestisci cosa questo utente può accedere e fare nell'organizzazione", "accessControlsSubmit": "Salva Controlli di Accesso", "roles": "Ruoli", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Connesso", "idpErrorConnectingTo": "Si è verificato un problema durante la connessione a {name}. Contatta il tuo amministratore.", "idpErrorNotFound": "IdP non trovato", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Invito Non Valido", "inviteInvalidDescription": "Il link di invito non è valido.", "inviteErrorWrongUser": "L'invito non è per questo utente", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Edizione Professional Richiesta", "licenseTierProfessionalRequiredDescription": "Questa funzionalità è disponibile solo nell'Edizione Professional.", "actionGetOrg": "Ottieni Organizzazione", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Aggiorna Organizzazione", "actionUpdateUser": "Aggiorna Utente", "actionGetUser": "Ottieni Utente", @@ -1496,5 +1502,7 @@ "convertButton": "Converti questo nodo in auto-ospitato gestito" }, "internationaldomaindetected": "Dominio Internazionale Rilevato", - "willbestoredas": "Verrà conservato come:" + "willbestoredas": "Verrà conservato come:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/ko-KR.json b/messages/ko-KR.json index 616456da..722e83ac 100644 --- a/messages/ko-KR.json +++ b/messages/ko-KR.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "사용자를 역할에 추가하는 동안 오류가 발생했습니다.", "userSaved": "사용자 저장됨", "userSavedDescription": "사용자가 업데이트되었습니다.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "이 사용자가 조직에서 접근하고 수행할 수 있는 작업을 관리하세요", "accessControlsSubmit": "접근 제어 저장", "roles": "역할", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "연결됨", "idpErrorConnectingTo": "{name}에 연결하는 데 문제가 발생했습니다. 관리자에게 문의하십시오.", "idpErrorNotFound": "IdP를 찾을 수 없습니다.", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "유효하지 않은 초대", "inviteInvalidDescription": "초대 링크가 유효하지 않습니다.", "inviteErrorWrongUser": "이 초대는 이 사용자에게 해당되지 않습니다", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "전문 에디션이 필요합니다.", "licenseTierProfessionalRequiredDescription": "이 기능은 Professional Edition에서만 사용할 수 있습니다.", "actionGetOrg": "조직 가져오기", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "조직 업데이트", "actionUpdateUser": "사용자 업데이트", "actionGetUser": "사용자 조회", @@ -1234,7 +1240,7 @@ "newtUpdateAvailable": "업데이트 가능", "newtUpdateAvailableInfo": "뉴트의 새 버전이 출시되었습니다. 최상의 경험을 위해 최신 버전으로 업데이트하세요.", "domainPickerEnterDomain": "도메인", - "domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com", + "domainPickerPlaceholder": "myapp.example.com", "domainPickerDescription": "리소스의 전체 도메인을 입력하여 사용 가능한 옵션을 확인하십시오.", "domainPickerDescriptionSaas": "전체 도메인, 서브도메인 또는 이름을 입력하여 사용 가능한 옵션을 확인하십시오.", "domainPickerTabAll": "모두", @@ -1496,5 +1502,7 @@ "convertButton": "이 노드를 관리 자체 호스팅으로 변환" }, "internationaldomaindetected": "국제 도메인 감지됨", - "willbestoredas": "다음으로 저장됩니다:" + "willbestoredas": "다음으로 저장됩니다:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/nb-NO.json b/messages/nb-NO.json index 6d1ae86a..ca2dec97 100644 --- a/messages/nb-NO.json +++ b/messages/nb-NO.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Det oppstod en feil under tilordning av brukeren til rollen.", "userSaved": "Bruker lagret", "userSavedDescription": "Brukeren har blitt oppdatert.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Administrer hva denne brukeren kan få tilgang til og gjøre i organisasjonen", "accessControlsSubmit": "Lagre tilgangskontroller", "roles": "Roller", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Tilkoblet", "idpErrorConnectingTo": "Det oppstod et problem med å koble til {name}. Vennligst kontakt din administrator.", "idpErrorNotFound": "IdP ikke funnet", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Ugyldig invitasjon", "inviteInvalidDescription": "Invitasjonslenken er ugyldig.", "inviteErrorWrongUser": "Invitasjonen er ikke for denne brukeren", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Profesjonell utgave påkrevd", "licenseTierProfessionalRequiredDescription": "Denne funksjonen er kun tilgjengelig i den profesjonelle utgaven.", "actionGetOrg": "Hent organisasjon", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Oppdater organisasjon", "actionUpdateUser": "Oppdater bruker", "actionGetUser": "Hent bruker", @@ -1234,7 +1240,7 @@ "newtUpdateAvailable": "Oppdatering tilgjengelig", "newtUpdateAvailableInfo": "En ny versjon av Newt er tilgjengelig. Vennligst oppdater til den nyeste versjonen for den beste opplevelsen.", "domainPickerEnterDomain": "Domene", - "domainPickerPlaceholder": "minapp.eksempel.com, api.v1.mittdomene.com, eller bare minapp", + "domainPickerPlaceholder": "myapp.example.com", "domainPickerDescription": "Skriv inn hele domenet til ressursen for å se tilgjengelige alternativer.", "domainPickerDescriptionSaas": "Skriv inn et fullt domene, underdomene eller bare et navn for å se tilgjengelige alternativer", "domainPickerTabAll": "Alle", @@ -1496,5 +1502,7 @@ "convertButton": "Konverter denne noden til manuelt bruk" }, "internationaldomaindetected": "Internasjonalt domene oppdaget", - "willbestoredas": "Vil bli lagret som:" + "willbestoredas": "Vil bli lagret som:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/nl-NL.json b/messages/nl-NL.json index 6252d752..4c209e09 100644 --- a/messages/nl-NL.json +++ b/messages/nl-NL.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Er is een fout opgetreden tijdens het toevoegen van de rol.", "userSaved": "Gebruiker opgeslagen", "userSavedDescription": "De gebruiker is bijgewerkt.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Beheer wat deze gebruiker toegang heeft tot en doet in de organisatie", "accessControlsSubmit": "Bewaar Toegangsbesturing", "roles": "Rollen", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Verbonden", "idpErrorConnectingTo": "Er was een probleem bij het verbinden met {name}. Neem contact op met uw beheerder.", "idpErrorNotFound": "IdP niet gevonden", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Ongeldige uitnodiging", "inviteInvalidDescription": "Uitnodigingslink is ongeldig.", "inviteErrorWrongUser": "Uitnodiging is niet voor deze gebruiker", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Professionele editie vereist", "licenseTierProfessionalRequiredDescription": "Deze functie is alleen beschikbaar in de Professional Edition.", "actionGetOrg": "Krijg Organisatie", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Organisatie bijwerken", "actionUpdateUser": "Gebruiker bijwerken", "actionGetUser": "Gebruiker ophalen", @@ -1234,7 +1240,7 @@ "newtUpdateAvailable": "Update beschikbaar", "newtUpdateAvailableInfo": "Er is een nieuwe versie van Newt beschikbaar. Update naar de nieuwste versie voor de beste ervaring.", "domainPickerEnterDomain": "Domein", - "domainPickerPlaceholder": "mijnapp.voorbeeld.com, api.v1.mijndomein.com, of gewoon mijnapp", + "domainPickerPlaceholder": "myapp.example.com", "domainPickerDescription": "Voer de volledige domein van de bron in om beschikbare opties te zien.", "domainPickerDescriptionSaas": "Voer een volledig domein, subdomein of gewoon een naam in om beschikbare opties te zien", "domainPickerTabAll": "Alles", @@ -1496,5 +1502,7 @@ "convertButton": "Converteer deze node naar Beheerde Zelf-Hosted" }, "internationaldomaindetected": "Internationaal Domein Gedetecteerd", - "willbestoredas": "Zal worden opgeslagen als:" + "willbestoredas": "Zal worden opgeslagen als:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/pl-PL.json b/messages/pl-PL.json index 5a8a1437..4ad81acc 100644 --- a/messages/pl-PL.json +++ b/messages/pl-PL.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Wystąpił błąd podczas dodawania użytkownika do roli.", "userSaved": "Użytkownik zapisany", "userSavedDescription": "Użytkownik został zaktualizowany.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Zarządzaj tym, do czego użytkownik ma dostęp i co może robić w organizacji", "accessControlsSubmit": "Zapisz kontrole dostępu", "roles": "Role", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Połączono", "idpErrorConnectingTo": "Wystąpił problem z połączeniem z {name}. Skontaktuj się z administratorem.", "idpErrorNotFound": "Nie znaleziono IdP", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Nieprawidłowe zaproszenie", "inviteInvalidDescription": "Link zapraszający jest nieprawidłowy.", "inviteErrorWrongUser": "Zaproszenie nie jest dla tego użytkownika", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Wymagana edycja Professional", "licenseTierProfessionalRequiredDescription": "Ta funkcja jest dostępna tylko w edycji Professional.", "actionGetOrg": "Pobierz organizację", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Aktualizuj organizację", "actionUpdateUser": "Zaktualizuj użytkownika", "actionGetUser": "Pobierz użytkownika", @@ -1496,5 +1502,7 @@ "convertButton": "Konwertuj ten węzeł do zarządzanego samodzielnie" }, "internationaldomaindetected": "Wykryto międzynarodową domenę", - "willbestoredas": "Będą przechowywane jako:" + "willbestoredas": "Będą przechowywane jako:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/pt-PT.json b/messages/pt-PT.json index 84afb6aa..585983d7 100644 --- a/messages/pt-PT.json +++ b/messages/pt-PT.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Ocorreu um erro ao adicionar usuário à função.", "userSaved": "Usuário salvo", "userSavedDescription": "O usuário foi atualizado.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Gerencie o que este usuário pode acessar e fazer na organização", "accessControlsSubmit": "Salvar Controles de Acesso", "roles": "Funções", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Conectado", "idpErrorConnectingTo": "Ocorreu um problema ao ligar a {name}. Por favor, contacte o seu administrador.", "idpErrorNotFound": "IdP não encontrado", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Convite Inválido", "inviteInvalidDescription": "O link do convite é inválido.", "inviteErrorWrongUser": "O convite não é para este usuário", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Edição Profissional Necessária", "licenseTierProfessionalRequiredDescription": "Esta funcionalidade só está disponível na Edição Profissional.", "actionGetOrg": "Obter Organização", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Atualizar Organização", "actionUpdateUser": "Atualizar Usuário", "actionGetUser": "Obter Usuário", @@ -1234,7 +1240,7 @@ "newtUpdateAvailable": "Nova Atualização Disponível", "newtUpdateAvailableInfo": "Uma nova versão do Newt está disponível. Atualize para a versão mais recente para uma melhor experiência.", "domainPickerEnterDomain": "Domínio", - "domainPickerPlaceholder": "meuapp.exemplo.com, api.v1.meudominio.com, ou apenas meuapp", + "domainPickerPlaceholder": "myapp.example.com", "domainPickerDescription": "Insira o domínio completo do recurso para ver as opções disponíveis.", "domainPickerDescriptionSaas": "Insira um domínio completo, subdomínio ou apenas um nome para ver as opções disponíveis", "domainPickerTabAll": "Todos", @@ -1496,5 +1502,7 @@ "convertButton": "Converter este nó para Auto-Hospedado Gerenciado" }, "internationaldomaindetected": "Domínio Internacional Detectado", - "willbestoredas": "Será armazenado como:" + "willbestoredas": "Será armazenado como:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/ru-RU.json b/messages/ru-RU.json index 284f4e63..7b8b2d67 100644 --- a/messages/ru-RU.json +++ b/messages/ru-RU.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Произошла ошибка при добавлении пользователя в роль.", "userSaved": "Пользователь сохранён", "userSavedDescription": "Пользователь был обновлён.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Управляйте тем, к чему этот пользователь может получить доступ и что делать в организации", "accessControlsSubmit": "Сохранить контроль доступа", "roles": "Роли", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Подключено", "idpErrorConnectingTo": "Возникла проблема при подключении к {name}. Пожалуйста, свяжитесь с вашим администратором.", "idpErrorNotFound": "IdP не найден", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Недействительное приглашение", "inviteInvalidDescription": "Ссылка на приглашение недействительна.", "inviteErrorWrongUser": "Приглашение не для этого пользователя", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Требуется профессиональная версия", "licenseTierProfessionalRequiredDescription": "Эта функция доступна только в профессиональной версии.", "actionGetOrg": "Получить организацию", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Обновить организацию", "actionUpdateUser": "Обновить пользователя", "actionGetUser": "Получить пользователя", @@ -1496,5 +1502,7 @@ "convertButton": "Конвертировать этот узел в управляемый себе-хост" }, "internationaldomaindetected": "Обнаружен международный домен", - "willbestoredas": "Будет храниться как:" + "willbestoredas": "Будет храниться как:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/tr-TR.json b/messages/tr-TR.json index 16ed968d..6008f2dc 100644 --- a/messages/tr-TR.json +++ b/messages/tr-TR.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "Kullanıcı role eklenirken bir hata oluştu.", "userSaved": "Kullanıcı kaydedildi", "userSavedDescription": "Kullanıcı güncellenmiştir.", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "Bu kullanıcının organizasyonda neleri erişebileceğini ve yapabileceğini yönetin", "accessControlsSubmit": "Erişim Kontrollerini Kaydet", "roles": "Roller", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "Bağlandı", "idpErrorConnectingTo": "{name} ile bağlantı kurarken bir sorun meydana geldi. Lütfen yöneticiye danışın.", "idpErrorNotFound": "IdP bulunamadı", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "Geçersiz Davet", "inviteInvalidDescription": "Davet bağlantısı geçersiz.", "inviteErrorWrongUser": "Davet bu kullanıcı için değil", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "Profesyonel Sürüme Gereklidir", "licenseTierProfessionalRequiredDescription": "Bu özellik yalnızca Professional Edition'da kullanılabilir.", "actionGetOrg": "Kuruluşu Al", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "Kuruluşu Güncelle", "actionUpdateUser": "Kullanıcıyı Güncelle", "actionGetUser": "Kullanıcıyı Getir", @@ -1496,5 +1502,7 @@ "convertButton": "Bu Düğümü Yönetilen Kendi Kendine Barındırma Dönüştürün" }, "internationaldomaindetected": "Uluslararası Alan Adı Tespit Edildi", - "willbestoredas": "Şu şekilde depolanacak:" + "willbestoredas": "Şu şekilde depolanacak:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/messages/zh-CN.json b/messages/zh-CN.json index 1eaa2263..25f09780 100644 --- a/messages/zh-CN.json +++ b/messages/zh-CN.json @@ -454,6 +454,8 @@ "accessRoleErrorAddDescription": "添加用户到角色时出错。", "userSaved": "用户已保存", "userSavedDescription": "用户已更新。", + "autoProvisioned": "Auto Provisioned", + "autoProvisionedDescription": "Allow this user to be automatically managed by identity provider", "accessControlsDescription": "管理此用户在组织中可以访问和做什么", "accessControlsSubmit": "保存访问控制", "roles": "角色", @@ -911,6 +913,8 @@ "idpConnectingToFinished": "已连接", "idpErrorConnectingTo": "无法连接到 {name},请联系管理员协助处理。", "idpErrorNotFound": "找不到 IdP", + "idpGoogleAlt": "Google", + "idpAzureAlt": "Azure", "inviteInvalid": "无效邀请", "inviteInvalidDescription": "邀请链接无效。", "inviteErrorWrongUser": "邀请不是该用户的", @@ -982,6 +986,8 @@ "licenseTierProfessionalRequired": "需要专业版", "licenseTierProfessionalRequiredDescription": "此功能仅在专业版可用。", "actionGetOrg": "获取组织", + "updateOrgUser": "Update Org User", + "createOrgUser": "Create Org User", "actionUpdateOrg": "更新组织", "actionUpdateUser": "更新用户", "actionGetUser": "获取用户", @@ -1234,7 +1240,7 @@ "newtUpdateAvailable": "更新可用", "newtUpdateAvailableInfo": "新版本的 Newt 已可用。请更新到最新版本以获得最佳体验。", "domainPickerEnterDomain": "域名", - "domainPickerPlaceholder": "myapp.example.com、api.v1.mydomain.com 或仅 myapp", + "domainPickerPlaceholder": "myapp.example.com", "domainPickerDescription": "输入资源的完整域名以查看可用选项。", "domainPickerDescriptionSaas": "输入完整域名、子域或名称以查看可用选项。", "domainPickerTabAll": "所有", @@ -1496,5 +1502,7 @@ "convertButton": "将此节点转换为管理自托管的" }, "internationaldomaindetected": "检测到国际域", - "willbestoredas": "储存为:" + "willbestoredas": "储存为:", + "idpGoogleDescription": "Google OAuth2/OIDC provider", + "idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider" } diff --git a/server/lib/domainUtils.ts b/server/lib/domainUtils.ts new file mode 100644 index 00000000..d043ca51 --- /dev/null +++ b/server/lib/domainUtils.ts @@ -0,0 +1,112 @@ +import { db } from "@server/db"; +import { domains, orgDomains } from "@server/db"; +import { eq, and } from "drizzle-orm"; +import { subdomainSchema } from "@server/lib/schemas"; +import { fromError } from "zod-validation-error"; + +export type DomainValidationResult = { + success: true; + fullDomain: string; + subdomain: string | null; +} | { + success: false; + error: string; +}; + +/** + * Validates a domain and constructs the full domain based on domain type and subdomain. + * + * @param domainId - The ID of the domain to validate + * @param orgId - The organization ID to check domain access + * @param subdomain - Optional subdomain to append (for ns and wildcard domains) + * @returns DomainValidationResult with success status and either fullDomain/subdomain or error message + */ +export async function validateAndConstructDomain( + domainId: string, + orgId: string, + subdomain?: string | null +): Promise { + try { + // Query domain with organization access check + const [domainRes] = await db + .select() + .from(domains) + .where(eq(domains.domainId, domainId)) + .leftJoin( + orgDomains, + and(eq(orgDomains.orgId, orgId), eq(orgDomains.domainId, domainId)) + ); + + // Check if domain exists + if (!domainRes || !domainRes.domains) { + return { + success: false, + error: `Domain with ID ${domainId} not found` + }; + } + + // Check if organization has access to domain + if (domainRes.orgDomains && domainRes.orgDomains.orgId !== orgId) { + return { + success: false, + error: `Organization does not have access to domain with ID ${domainId}` + }; + } + + // Check if domain is verified + if (!domainRes.domains.verified) { + return { + success: false, + error: `Domain with ID ${domainId} is not verified` + }; + } + + // Construct full domain based on domain type + let fullDomain = ""; + let finalSubdomain = subdomain; + + if (domainRes.domains.type === "ns") { + if (subdomain) { + fullDomain = `${subdomain}.${domainRes.domains.baseDomain}`; + } else { + fullDomain = domainRes.domains.baseDomain; + } + } else if (domainRes.domains.type === "cname") { + fullDomain = domainRes.domains.baseDomain; + finalSubdomain = null; // CNAME domains don't use subdomains + } else if (domainRes.domains.type === "wildcard") { + if (subdomain !== undefined && subdomain !== null) { + // Validate subdomain format for wildcard domains + const parsedSubdomain = subdomainSchema.safeParse(subdomain); + if (!parsedSubdomain.success) { + return { + success: false, + error: fromError(parsedSubdomain.error).toString() + }; + } + fullDomain = `${subdomain}.${domainRes.domains.baseDomain}`; + } else { + fullDomain = domainRes.domains.baseDomain; + } + } + + // If the full domain equals the base domain, set subdomain to null + if (fullDomain === domainRes.domains.baseDomain) { + finalSubdomain = null; + } + + // Convert to lowercase + fullDomain = fullDomain.toLowerCase(); + + return { + success: true, + fullDomain, + subdomain: finalSubdomain ?? null + }; + } catch (error) { + return { + success: false, + error: `An error occurred while validating domain: ${error instanceof Error ? error.message : 'Unknown error'}` + }; + } +} diff --git a/server/routers/resource/createResource.ts b/server/routers/resource/createResource.ts index 152b8f8c..c5f30f83 100644 --- a/server/routers/resource/createResource.ts +++ b/server/routers/resource/createResource.ts @@ -22,6 +22,7 @@ import config from "@server/lib/config"; import { OpenAPITags, registry } from "@server/openApi"; import { build } from "@server/build"; import { getUniqueResourceName } from "@server/db/names"; +import { validateAndConstructDomain } from "@server/lib/domainUtils"; const createResourceParamsSchema = z .object({ @@ -194,76 +195,21 @@ async function createHttpResource( } const { name, domainId } = parsedBody.data; - let subdomain = parsedBody.data.subdomain; + const subdomain = parsedBody.data.subdomain; - const [domainRes] = await db - .select() - .from(domains) - .where(eq(domains.domainId, domainId)) - .leftJoin( - orgDomains, - and(eq(orgDomains.orgId, orgId), eq(orgDomains.domainId, domainId)) - ); - - if (!domainRes || !domainRes.domains) { - return next( - createHttpError( - HttpCode.NOT_FOUND, - `Domain with ID ${domainId} not found` - ) - ); - } - - if (domainRes.orgDomains && domainRes.orgDomains.orgId !== orgId) { - return next( - createHttpError( - HttpCode.FORBIDDEN, - `Organization does not have access to domain with ID ${domainId}` - ) - ); - } - - if (!domainRes.domains.verified) { + // Validate domain and construct full domain + const domainResult = await validateAndConstructDomain(domainId, orgId, subdomain); + + if (!domainResult.success) { return next( createHttpError( HttpCode.BAD_REQUEST, - `Domain with ID ${domainRes.domains.domainId} is not verified` + domainResult.error ) ); } - let fullDomain = ""; - if (domainRes.domains.type == "ns") { - if (subdomain) { - fullDomain = `${subdomain}.${domainRes.domains.baseDomain}`; - } else { - fullDomain = domainRes.domains.baseDomain; - } - } else if (domainRes.domains.type == "cname") { - fullDomain = domainRes.domains.baseDomain; - } else if (domainRes.domains.type == "wildcard") { - if (subdomain) { - // the subdomain cant have a dot in it - const parsedSubdomain = subdomainSchema.safeParse(subdomain); - if (!parsedSubdomain.success) { - return next( - createHttpError( - HttpCode.BAD_REQUEST, - fromError(parsedSubdomain.error).toString() - ) - ); - } - fullDomain = `${subdomain}.${domainRes.domains.baseDomain}`; - } else { - fullDomain = domainRes.domains.baseDomain; - } - } - - if (fullDomain === domainRes.domains.baseDomain) { - subdomain = null; - } - - fullDomain = fullDomain.toLowerCase(); + const { fullDomain, subdomain: finalSubdomain } = domainResult; logger.debug(`Full domain: ${fullDomain}`); @@ -295,7 +241,7 @@ async function createHttpResource( domainId, orgId, name, - subdomain, + subdomain: finalSubdomain, http: true, protocol: "tcp", ssl: true diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts index 30acc0c1..05f1cf66 100644 --- a/server/routers/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -20,6 +20,7 @@ import { tlsNameSchema } from "@server/lib/schemas"; import { subdomainSchema } from "@server/lib/schemas"; import { registry } from "@server/openApi"; import { OpenAPITags } from "@server/openApi"; +import { validateAndConstructDomain } from "@server/lib/domainUtils"; const updateResourceParamsSchema = z .object({ @@ -230,78 +231,19 @@ async function updateHttpResource( if (updateData.domainId) { const domainId = updateData.domainId; - const [domainRes] = await db - .select() - .from(domains) - .where(eq(domains.domainId, domainId)) - .leftJoin( - orgDomains, - and( - eq(orgDomains.orgId, resource.orgId), - eq(orgDomains.domainId, domainId) - ) - ); - - if (!domainRes || !domainRes.domains) { - return next( - createHttpError( - HttpCode.NOT_FOUND, - `Domain with ID ${updateData.domainId} not found` - ) - ); - } - - if ( - domainRes.orgDomains && - domainRes.orgDomains.orgId !== resource.orgId - ) { - return next( - createHttpError( - HttpCode.FORBIDDEN, - `You do not have permission to use domain with ID ${updateData.domainId}` - ) - ); - } - - if (!domainRes.domains.verified) { + // Validate domain and construct full domain + const domainResult = await validateAndConstructDomain(domainId, resource.orgId, updateData.subdomain); + + if (!domainResult.success) { return next( createHttpError( HttpCode.BAD_REQUEST, - `Domain with ID ${updateData.domainId} is not verified` + domainResult.error ) ); } - let fullDomain = ""; - if (domainRes.domains.type == "ns") { - if (updateData.subdomain) { - fullDomain = `${updateData.subdomain}.${domainRes.domains.baseDomain}`; - } else { - fullDomain = domainRes.domains.baseDomain; - } - } else if (domainRes.domains.type == "cname") { - fullDomain = domainRes.domains.baseDomain; - } else if (domainRes.domains.type == "wildcard") { - if (updateData.subdomain !== undefined) { - // the subdomain cant have a dot in it - const parsedSubdomain = subdomainSchema.safeParse( - updateData.subdomain - ); - if (!parsedSubdomain.success) { - return next( - createHttpError( - HttpCode.BAD_REQUEST, - fromError(parsedSubdomain.error).toString() - ) - ); - } - fullDomain = `${updateData.subdomain}.${domainRes.domains.baseDomain}`; - } else { - fullDomain = domainRes.domains.baseDomain; - } - } - - fullDomain = fullDomain.toLowerCase(); + const { fullDomain, subdomain: finalSubdomain } = domainResult; logger.debug(`Full domain: ${fullDomain}`); @@ -332,9 +274,8 @@ async function updateHttpResource( .where(eq(resources.resourceId, resource.resourceId)); } - if (fullDomain === domainRes.domains.baseDomain) { - updateData.subdomain = null; - } + // Update the subdomain in the update data + updateData.subdomain = finalSubdomain; } const updatedResource = await db diff --git a/server/routers/siteResource/updateSiteResource.ts b/server/routers/siteResource/updateSiteResource.ts index 82e2fe68..f6f71124 100644 --- a/server/routers/siteResource/updateSiteResource.ts +++ b/server/routers/siteResource/updateSiteResource.ts @@ -28,7 +28,7 @@ const updateSiteResourceSchema = z protocol: z.enum(["tcp", "udp"]).optional(), proxyPort: z.number().int().positive().optional(), destinationPort: z.number().int().positive().optional(), - destinationIp: z.string().ip().optional(), + destinationIp: z.string().optional(), enabled: z.boolean().optional() }) .strict(); diff --git a/src/app/[orgId]/settings/resources/[niceId]/general/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/general/page.tsx index e2bab1cb..0f201a1a 100644 --- a/src/app/[orgId]/settings/resources/[niceId]/general/page.tsx +++ b/src/app/[orgId]/settings/resources/[niceId]/general/page.tsx @@ -471,15 +471,11 @@ export default function GeneralForm() { ? `${sanitizedSubdomain}.${selectedDomain.baseDomain}` : selectedDomain.baseDomain; - setResourceFullDomain(sanitizedFullDomain); + setResourceFullDomain(`${resource.ssl ? "https" : "http"}://${sanitizedFullDomain}`); form.setValue("domainId", selectedDomain.domainId); form.setValue("subdomain", sanitizedSubdomain); setEditDomainOpen(false); - - toast({ - description: `Final domain: ${sanitizedFullDomain}`, - }); } }} > diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts index edb281b7..5cef9f0e 100644 --- a/src/lib/api/index.ts +++ b/src/lib/api/index.ts @@ -22,7 +22,7 @@ export function createApiClient({ env }: { env: Env }): AxiosInstance { axios.defaults.withCredentials = true; } else { // user is accessing through a proxy - baseURL = window.location.origin + `/${suffix}`; + baseURL = `${env.app.dashboardUrl}/${suffix}`; } if (!baseURL) {