diff --git a/packages/clerk-js/src/core/resources/Organization.ts b/packages/clerk-js/src/core/resources/Organization.ts index c3c91cb4b73..6775aa8a93d 100644 --- a/packages/clerk-js/src/core/resources/Organization.ts +++ b/packages/clerk-js/src/core/resources/Organization.ts @@ -134,11 +134,17 @@ export class Organization extends BaseResource implements OrganizationResource { getDomains = async ( getDomainParams?: GetDomainsParams, ): Promise> => { + const { enrollmentMode, ...rest } = getDomainParams || {}; + const search = convertPageToOffsetSearchParams(rest); + if (enrollmentMode) { + search.set('enrollment_mode', enrollmentMode); + } + return await BaseResource._fetch( { path: `/organizations/${this.id}/domains`, method: 'GET', - search: convertPageToOffsetSearchParams(getDomainParams), + search, }, { forceUpdateClient: true, diff --git a/packages/clerk-js/src/core/resources/OrganizationDomain.ts b/packages/clerk-js/src/core/resources/OrganizationDomain.ts index 9200f31388e..9bb81cab3df 100644 --- a/packages/clerk-js/src/core/resources/OrganizationDomain.ts +++ b/packages/clerk-js/src/core/resources/OrganizationDomain.ts @@ -1,6 +1,7 @@ import type { AttemptAffiliationVerificationParams, OrganizationDomainJSON, + OrganizationDomainOwnershipVerification, OrganizationDomainResource, OrganizationDomainVerification, OrganizationEnrollmentMode, @@ -17,6 +18,8 @@ export class OrganizationDomain extends BaseResource implements OrganizationDoma organizationId!: string; enrollmentMode!: OrganizationEnrollmentMode; verification!: OrganizationDomainVerification | null; + affiliationVerification!: OrganizationDomainVerification | null; + ownershipVerification!: OrganizationDomainOwnershipVerification | null; affiliationEmailAddress!: string | null; createdAt!: Date; updatedAt!: Date; @@ -59,6 +62,20 @@ export class OrganizationDomain extends BaseResource implements OrganizationDoma }); }; + prepareOwnershipVerification = async (): Promise => { + return this._basePost({ + path: `/organizations/${this.organizationId}/domains/${this.id}/prepare_ownership_verification`, + method: 'POST', + }); + }; + + attemptOwnershipVerification = async (): Promise => { + return this._basePost({ + path: `/organizations/${this.organizationId}/domains/${this.id}/attempt_ownership_verification`, + method: 'POST', + }); + }; + updateEnrollmentMode = (params: UpdateEnrollmentModeParams): Promise => { return this._basePost({ path: `/organizations/${this.organizationId}/domains/${this.id}/update_enrollment_mode`, @@ -81,16 +98,40 @@ export class OrganizationDomain extends BaseResource implements OrganizationDoma this.affiliationEmailAddress = data.affiliation_email_address; this.totalPendingSuggestions = data.total_pending_suggestions; this.totalPendingInvitations = data.total_pending_invitations; - if (data.verification) { - this.verification = { - status: data.verification.status, - strategy: data.verification.strategy, - attempts: data.verification.attempts, - expiresAt: unixEpochToDate(data.verification.expires_at), + + const affiliationVerificationJSON = data.affiliation_verification ?? data.verification; + if (affiliationVerificationJSON) { + const affiliationVerification: OrganizationDomainVerification = { + status: affiliationVerificationJSON.status, + strategy: affiliationVerificationJSON.strategy, + attempts: affiliationVerificationJSON.attempts, + expiresAt: unixEpochToDate(affiliationVerificationJSON.expires_at), }; + this.affiliationVerification = affiliationVerification; + // Deprecated alias, kept in sync for backwards compatibility. + this.verification = affiliationVerification; } else { + this.affiliationVerification = null; this.verification = null; } + + if (data.ownership_verification) { + this.ownershipVerification = { + status: data.ownership_verification.status, + strategy: data.ownership_verification.strategy, + attempts: data.ownership_verification.attempts, + expiresAt: data.ownership_verification.expire_at + ? unixEpochToDate(data.ownership_verification.expire_at) + : null, + verifiedAt: data.ownership_verification.verified_at + ? unixEpochToDate(data.ownership_verification.verified_at) + : null, + txtRecordName: data.ownership_verification.txt_record_name ?? null, + txtRecordValue: data.ownership_verification.txt_record_value ?? null, + }; + } else { + this.ownershipVerification = null; + } } return this; } diff --git a/packages/localizations/src/ar-SA.ts b/packages/localizations/src/ar-SA.ts index bc77a14870a..bbb640f4924 100644 --- a/packages/localizations/src/ar-SA.ts +++ b/packages/localizations/src/ar-SA.ts @@ -196,29 +196,25 @@ export const arSA: LocalizationResource = { }, warning: 'بمجرد اختيار المزود لا يمكنك التغيير مرة أخرى حتى انتهاء التكوين', }, - verifyEmailDomainStep: { - title: 'التحقق من البريد الإلكتروني', - subtitle: 'تحقق من عنوان البريد الإلكتروني الذي تريد تفعيل اتصال المؤسسة عليه.', - addEmailAddress: { - formTitle: 'نحتاج إلى بريدك الإلكتروني', - formSubtitle: 'للبدء، نحتاج إلى عنوان بريدك الإلكتروني', - inputPlaceholder: 'name@company.com', - inputLabel: 'عنوان البريد الإلكتروني', - }, - emailCode: { - formTitle: 'تحقق من عنوان بريدك الإلكتروني', - formSubtitle: 'أدخل رمز التحقق المرسل إلى {{identifier}}', - resendButton: 'لم تتلقَّ الرمز؟ إعادة الإرسال', - verified: { - title: 'لقد تلقينا بريدك الإلكتروني', - subtitle: 'لقد تحققت من عنوان بريدك الإلكتروني التالي', - inputLabel: 'عنوان البريد الإلكتروني الذي تم التحقق منه', + verifyDomainsStep: { + title: 'التحقق من النطاق', + subtitle: 'حدد النطاق وتحقق منه لإعداد الدخول الموحّد (SSO).', + formFieldLabel__domain: 'النطاقات', + formFieldInputPlaceholder__domain: 'اكتب نطاقك هنا وانقر على إضافة للبدء', + formButtonPrimary__add: 'إضافة', + txtRecordInstructions: { + paragraph1: 'أضف سجل TXT هذا إلى موفّر DNS الخاص بك.', + paragraph2: + 'سنتحقق تلقائيًا بمجرد أن يصبح السجل نشطًا. عادةً ما يستغرق ذلك أقل من دقيقة، رغم أن تحديث سجل TXT موجود قد يستغرق وقتًا أطول قليلاً.', + }, + txtRecordTable: { + columns: { + domain: 'النطاق', + type: 'النوع', + hostName: 'المضيف / الاسم', + value: 'القيمة', }, }, - domainTaken: { - title: 'هذا النطاق ({{domain}}) لديه بالفعل اتصال SSO', - subtitle: 'تواصل مع مسؤول التطبيق للحصول على الوصول من خلال الاتصال الحالي.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/be-BY.ts b/packages/localizations/src/be-BY.ts index b24fe2a2a0e..887d2432fea 100644 --- a/packages/localizations/src/be-BY.ts +++ b/packages/localizations/src/be-BY.ts @@ -196,29 +196,25 @@ export const beBY: LocalizationResource = { }, warning: 'Пасля выбару правайдэра вы не зможаце змяніць яго, пакуль не скончыце канфігурацыю', }, - verifyEmailDomainStep: { - title: 'Пацвердзіць адрас электроннай пошты', - subtitle: 'Пацвердзіце адрас электроннай пошты, на якім вы хочаце ўключыць карпаратыўнае падключэнне.', - addEmailAddress: { - formTitle: 'Нам патрэбна ваша пошта', - formSubtitle: 'Каб пачаць, нам спатрэбіцца ваш адрас электроннай пошты', - inputPlaceholder: 'name@company.com', - inputLabel: 'Адрас электроннай пошты', - }, - emailCode: { - formTitle: 'Пацвердзіце ваш адрас электроннай пошты', - formSubtitle: 'Увядзіце код пацверджання, дасланы на {{identifier}}', - resendButton: 'Не атрымалі код? Адправіць паўторна', - verified: { - title: 'Мы атрымалі вашу пошту', - subtitle: 'Вы пацвердзілі свой адрас электроннай пошты з наступнай поштай', - inputLabel: 'Пацверджаны адрас электроннай пошты', + verifyDomainsStep: { + title: 'Пацвердзіць дамен', + subtitle: 'Укажыце і пацвердзіце дамен для наладжвання SSO.', + formFieldLabel__domain: 'Дамены', + formFieldInputPlaceholder__domain: 'Увядзіце свой дамен тут і націсніце «Дадаць», каб пачаць', + formButtonPrimary__add: 'Дадаць', + txtRecordInstructions: { + paragraph1: 'Дадайце гэты TXT-запіс да вашага DNS-правайдара.', + paragraph2: + 'Мы праверым аўтаматычна, як толькі запіс стане актыўным. Звычайна гэта займае менш за хвіліну, хаця абнаўленне існуючага TXT-запісу можа заняць крыху больш часу.', + }, + txtRecordTable: { + columns: { + domain: 'Дамен', + type: 'Тып', + hostName: 'Хост / Імя', + value: 'Значэнне', }, }, - domainTaken: { - title: 'Гэты дамен ({{domain}}) ужо мае SSO-падключэнне', - subtitle: 'Звяжыцеся з адміністратарам прыкладання, каб атрымаць доступ праз існуючае падключэнне.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/bg-BG.ts b/packages/localizations/src/bg-BG.ts index 1f4fd93ba1e..6c3a3cafa59 100644 --- a/packages/localizations/src/bg-BG.ts +++ b/packages/localizations/src/bg-BG.ts @@ -197,29 +197,25 @@ export const bgBG: LocalizationResource = { }, warning: 'След като изберете доставчик, не можете да го промените, докато конфигурацията не приключи', }, - verifyEmailDomainStep: { - title: 'Потвърди имейл адреса', - subtitle: 'Потвърдете имейл адреса, на който искате да активирате корпоративната връзка.', - addEmailAddress: { - formTitle: 'Нуждаем се от вашия имейл', - formSubtitle: 'За да започнем, ще ни е необходим вашият имейл адрес', - inputPlaceholder: 'name@company.com', - inputLabel: 'Имейл адрес', - }, - emailCode: { - formTitle: 'Потвърдете имейл адреса си', - formSubtitle: 'Въведете кода за потвърждение, изпратен на {{identifier}}', - resendButton: 'Не получихте код? Изпрати отново', - verified: { - title: 'Получихме имейла ви', - subtitle: 'Потвърдихте имейл адреса си със следния имейл', - inputLabel: 'Потвърден имейл адрес', + verifyDomainsStep: { + title: 'Потвърди домейна', + subtitle: 'Посочете и потвърдете домейна, за който да конфигурирате SSO.', + formFieldLabel__domain: 'Домейни', + formFieldInputPlaceholder__domain: 'Въведете домейна си тук и щракнете върху добавяне, за да започнете', + formButtonPrimary__add: 'Добави', + txtRecordInstructions: { + paragraph1: 'Добавете този TXT запис при своя DNS доставчик.', + paragraph2: + 'Ще го потвърдим автоматично, щом записът се активира. Това обикновено отнема под минута, въпреки че актуализирането на съществуващ TXT запис може да отнеме малко повече време.', + }, + txtRecordTable: { + columns: { + domain: 'Домейн', + type: 'Тип', + hostName: 'Хост / Име', + value: 'Стойност', }, }, - domainTaken: { - title: 'Този домейн ({{domain}}) вече има SSO връзка', - subtitle: 'Свържете се с администратора на приложението, за да получите достъп чрез съществуващата връзка.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/bn-IN.ts b/packages/localizations/src/bn-IN.ts index 4b962b33ef1..2e69512a057 100644 --- a/packages/localizations/src/bn-IN.ts +++ b/packages/localizations/src/bn-IN.ts @@ -202,29 +202,25 @@ export const bnIN: LocalizationResource = { }, warning: 'একবার প্রদানকারী নির্বাচন করার পরে, কনফিগারেশন শেষ না হওয়া পর্যন্ত আপনি আবার পরিবর্তন করতে পারবেন না', }, - verifyEmailDomainStep: { - title: 'ইমেইল ঠিকানা যাচাই করুন', - subtitle: 'যে ইমেইল ঠিকানায় আপনি এন্টারপ্রাইজ সংযোগ সক্রিয় করতে চান তা যাচাই করুন।', - addEmailAddress: { - formTitle: 'আমাদের আপনার ইমেইল প্রয়োজন', - formSubtitle: 'শুরু করতে আমাদের আপনার ইমেইল ঠিকানা প্রয়োজন হবে', - inputPlaceholder: 'name@company.com', - inputLabel: 'ইমেইল ঠিকানা', - }, - emailCode: { - formTitle: 'আপনার ইমেইল ঠিকানা যাচাই করুন', - formSubtitle: '{{identifier}} এ পাঠানো যাচাইকরণ কোড লিখুন', - resendButton: 'কোড পাননি? পুনরায় পাঠান', - verified: { - title: 'আমরা আপনার ইমেইল পেয়েছি', - subtitle: 'আপনি নিম্নলিখিত ইমেইল দিয়ে আপনার ইমেইল ঠিকানা যাচাই করেছেন', - inputLabel: 'যাচাইকৃত ইমেইল ঠিকানা', + verifyDomainsStep: { + title: 'ডোমেইন যাচাই করুন', + subtitle: 'SSO কনফিগার করার জন্য ডোমেইনটি নির্দিষ্ট করুন এবং যাচাই করুন।', + formFieldLabel__domain: 'ডোমেইন', + formFieldInputPlaceholder__domain: 'আপনার ডোমেইন এখানে টাইপ করুন এবং শুরু করতে যোগ করুন-এ ক্লিক করুন', + formButtonPrimary__add: 'যোগ করুন', + txtRecordInstructions: { + paragraph1: 'এই TXT রেকর্ডটি আপনার DNS প্রদানকারীতে যোগ করুন।', + paragraph2: + 'রেকর্ডটি সক্রিয় হলে আমরা স্বয়ংক্রিয়ভাবে যাচাই করব। এটি সাধারণত এক মিনিটেরও কম সময় নেয়, তবে কোনো বিদ্যমান TXT রেকর্ড আপডেট করতে কিছুটা বেশি সময় লাগতে পারে।', + }, + txtRecordTable: { + columns: { + domain: 'ডোমেইন', + type: 'ধরন', + hostName: 'হোস্ট / নাম', + value: 'মান', }, }, - domainTaken: { - title: 'এই ডোমেইনে ({{domain}}) ইতিমধ্যে একটি SSO সংযোগ রয়েছে', - subtitle: 'বিদ্যমান সংযোগের মাধ্যমে অ্যাক্সেস পেতে অ্যাপ্লিকেশন প্রশাসকের সাথে যোগাযোগ করুন।', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ca-ES.ts b/packages/localizations/src/ca-ES.ts index 3b5339884e9..011fc7a28c9 100644 --- a/packages/localizations/src/ca-ES.ts +++ b/packages/localizations/src/ca-ES.ts @@ -203,29 +203,25 @@ export const caES: LocalizationResource = { }, warning: 'Un cop seleccionat un proveïdor no podreu canviar-lo fins que la configuració hagi finalitzat', }, - verifyEmailDomainStep: { - title: 'Verifica el correu electrònic', - subtitle: "Verifica l'adreça de correu electrònic on vols habilitar la connexió empresarial.", - addEmailAddress: { - formTitle: 'Necessitem el teu correu', - formSubtitle: 'Per començar necessitem la teva adreça de correu electrònic', - inputPlaceholder: 'name@company.com', - inputLabel: 'Adreça de correu electrònic', - }, - emailCode: { - formTitle: "Verifica l'adreça de correu electrònic", - formSubtitle: 'Introdueix el codi de verificació enviat a {{identifier}}', - resendButton: 'No has rebut el codi? Reenvia', - verified: { - title: 'Hem rebut el teu correu', - subtitle: 'Has verificat la teva adreça de correu electrònic amb el següent correu', - inputLabel: 'Adreça de correu electrònic verificada', + verifyDomainsStep: { + title: 'Verifica el domini', + subtitle: "Especifica i verifica el domini per configurar l'SSO.", + formFieldLabel__domain: 'Dominis', + formFieldInputPlaceholder__domain: 'Escriu aquí el teu domini i fes clic a Afegeix per començar', + formButtonPrimary__add: 'Afegeix', + txtRecordInstructions: { + paragraph1: 'Afegeix aquest registre TXT al teu proveïdor de DNS.', + paragraph2: + "Ho verificarem automàticament un cop el registre estigui actiu. Normalment triga menys d'un minut, tot i que actualitzar un registre TXT existent pot trigar una mica més.", + }, + txtRecordTable: { + columns: { + domain: 'Domini', + type: 'Tipus', + hostName: 'Amfitrió / Nom', + value: 'Valor', }, }, - domainTaken: { - title: 'Aquest domini ({{domain}}) ja té una connexió SSO', - subtitle: "Contacta amb l'administrador de l'aplicació per obtenir accés a través de la connexió existent.", - }, }, }, createOrganization: { diff --git a/packages/localizations/src/cs-CZ.ts b/packages/localizations/src/cs-CZ.ts index 3a5c09c266f..41afdf02723 100644 --- a/packages/localizations/src/cs-CZ.ts +++ b/packages/localizations/src/cs-CZ.ts @@ -200,29 +200,25 @@ export const csCZ: LocalizationResource = { }, warning: 'Jakmile vyberete poskytovatele, nelze ho změnit, dokud nebude konfigurace dokončena', }, - verifyEmailDomainStep: { - title: 'Ověřit e-mailovou adresu', - subtitle: 'Ověřte e-mailovou adresu, na které chcete povolit podnikové připojení.', - addEmailAddress: { - formTitle: 'Potřebujeme váš e-mail', - formSubtitle: 'K zahájení budeme potřebovat vaši e-mailovou adresu', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mailová adresa', - }, - emailCode: { - formTitle: 'Ověřte svou e-mailovou adresu', - formSubtitle: 'Zadejte ověřovací kód odeslaný na {{identifier}}', - resendButton: 'Neobdrželi jste kód? Odeslat znovu', - verified: { - title: 'Máme váš e-mail', - subtitle: 'Ověřili jste svou e-mailovou adresu pomocí následujícího e-mailu', - inputLabel: 'Ověřená e-mailová adresa', + verifyDomainsStep: { + title: 'Ověřit doménu', + subtitle: 'Zadejte a ověřte doménu, pro kterou chcete nakonfigurovat SSO.', + formFieldLabel__domain: 'Domény', + formFieldInputPlaceholder__domain: 'Zde zadejte svou doménu a kliknutím na přidat začněte', + formButtonPrimary__add: 'Přidat', + txtRecordInstructions: { + paragraph1: 'Přidejte tento záznam TXT u svého poskytovatele DNS.', + paragraph2: + 'Jakmile bude záznam aktivní, ověříme jej automaticky. Obvykle to trvá méně než minutu, i když aktualizace stávajícího záznamu TXT může chvíli trvat déle.', + }, + txtRecordTable: { + columns: { + domain: 'Doména', + type: 'Typ', + hostName: 'Host / Název', + value: 'Hodnota', }, }, - domainTaken: { - title: 'Tato doména ({{domain}}) již má SSO připojení', - subtitle: 'Kontaktujte administrátora aplikace, abyste získali přístup prostřednictvím stávajícího připojení.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/da-DK.ts b/packages/localizations/src/da-DK.ts index 53f74d0a66f..47cd325efbb 100644 --- a/packages/localizations/src/da-DK.ts +++ b/packages/localizations/src/da-DK.ts @@ -196,29 +196,25 @@ export const daDK: LocalizationResource = { }, warning: 'Når en udbyder er valgt, kan du ikke ændre den, før konfigurationen er færdig', }, - verifyEmailDomainStep: { - title: 'Bekræft e-mailadresse', - subtitle: 'Bekræft den e-mailadresse, du vil aktivere virksomhedsforbindelsen på.', - addEmailAddress: { - formTitle: 'Vi har brug for din e-mail', - formSubtitle: 'For at starte har vi brug for din e-mailadresse', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mailadresse', - }, - emailCode: { - formTitle: 'Bekræft din e-mailadresse', - formSubtitle: 'Indtast bekræftelseskoden sendt til {{identifier}}', - resendButton: 'Modtog du ingen kode? Send igen', - verified: { - title: 'Vi har modtaget din e-mail', - subtitle: 'Du har bekræftet din e-mailadresse med følgende e-mail', - inputLabel: 'Bekræftet e-mailadresse', + verifyDomainsStep: { + title: 'Bekræft domæne', + subtitle: 'Angiv og bekræft det domæne, du vil konfigurere SSO for.', + formFieldLabel__domain: 'Domæner', + formFieldInputPlaceholder__domain: 'Skriv dit domæne her, og klik på tilføj for at starte', + formButtonPrimary__add: 'Tilføj', + txtRecordInstructions: { + paragraph1: 'Tilføj denne TXT-post hos din DNS-udbyder.', + paragraph2: + 'Vi verificerer automatisk, når posten er aktiv. Dette tager normalt under et minut, men opdatering af en eksisterende TXT-post kan tage lidt længere tid.', + }, + txtRecordTable: { + columns: { + domain: 'Domæne', + type: 'Type', + hostName: 'Host / Navn', + value: 'Værdi', }, }, - domainTaken: { - title: 'Dette domæne ({{domain}}) har allerede en SSO-forbindelse', - subtitle: 'Kontakt applikationens administrator for at få adgang via den eksisterende forbindelse.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/de-DE.ts b/packages/localizations/src/de-DE.ts index 5ebc5a9025c..7c94bcfad58 100644 --- a/packages/localizations/src/de-DE.ts +++ b/packages/localizations/src/de-DE.ts @@ -203,30 +203,25 @@ export const deDE: LocalizationResource = { warning: 'Sobald ein Anbieter ausgewählt ist, können Sie ihn nicht mehr ändern, bis die Konfiguration abgeschlossen ist', }, - verifyEmailDomainStep: { - title: 'E-Mail-Adresse verifizieren', - subtitle: 'Verifizieren Sie die E-Mail-Adresse, für die Sie die Unternehmensverbindung aktivieren möchten.', - addEmailAddress: { - formTitle: 'Wir benötigen Ihre E-Mail', - formSubtitle: 'Um zu beginnen, benötigen wir Ihre E-Mail-Adresse', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-Mail-Adresse', - }, - emailCode: { - formTitle: 'Verifizieren Sie Ihre E-Mail-Adresse', - formSubtitle: 'Geben Sie den an {{identifier}} gesendeten Verifizierungscode ein', - resendButton: 'Keinen Code erhalten? Erneut senden', - verified: { - title: 'Wir haben Ihre E-Mail erhalten', - subtitle: 'Sie haben Ihre E-Mail-Adresse mit der folgenden E-Mail verifiziert', - inputLabel: 'Verifizierte E-Mail-Adresse', + verifyDomainsStep: { + title: 'Domain verifizieren', + subtitle: 'Geben Sie die Domain an und verifizieren Sie sie, um SSO zu konfigurieren.', + formFieldLabel__domain: 'Domains', + formFieldInputPlaceholder__domain: 'Geben Sie hier Ihre Domain ein und klicken Sie zum Starten auf „Hinzufügen"', + formButtonPrimary__add: 'Hinzufügen', + txtRecordInstructions: { + paragraph1: 'Fügen Sie diesen TXT-Eintrag bei Ihrem DNS-Anbieter hinzu.', + paragraph2: + 'Wir verifizieren automatisch, sobald der Eintrag aktiv ist. Dies dauert in der Regel weniger als eine Minute, das Aktualisieren eines bestehenden TXT-Eintrags kann jedoch etwas länger dauern.', + }, + txtRecordTable: { + columns: { + domain: 'Domain', + type: 'Typ', + hostName: 'Host / Name', + value: 'Wert', }, }, - domainTaken: { - title: 'Diese Domain ({{domain}}) hat bereits eine SSO-Verbindung', - subtitle: - 'Wenden Sie sich an den Administrator der Anwendung, um über die bestehende Verbindung Zugriff zu erhalten.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/el-GR.ts b/packages/localizations/src/el-GR.ts index 0ae1f413953..68c7e6493d9 100644 --- a/packages/localizations/src/el-GR.ts +++ b/packages/localizations/src/el-GR.ts @@ -196,30 +196,26 @@ export const elGR: LocalizationResource = { }, warning: 'Μόλις επιλεγεί ένας πάροχος δεν μπορείτε να τον αλλάξετε μέχρι να ολοκληρωθεί η ρύθμιση', }, - verifyEmailDomainStep: { - title: 'Επαλήθευση διεύθυνσης email', - subtitle: 'Επαληθεύστε τη διεύθυνση email στην οποία θέλετε να ενεργοποιήσετε τη σύνδεση επιχείρησης.', - addEmailAddress: { - formTitle: 'Χρειαζόμαστε το email σας', - formSubtitle: 'Για να ξεκινήσουμε, θα χρειαστούμε τη διεύθυνση email σας', - inputPlaceholder: 'name@company.com', - inputLabel: 'Διεύθυνση email', - }, - emailCode: { - formTitle: 'Επαληθεύστε τη διεύθυνση email σας', - formSubtitle: 'Εισαγάγετε τον κωδικό επαλήθευσης που στάλθηκε στο {{identifier}}', - resendButton: 'Δεν λάβατε κωδικό; Επαναποστολή', - verified: { - title: 'Λάβαμε το email σας', - subtitle: 'Έχετε επαληθεύσει τη διεύθυνση email σας με το ακόλουθο email', - inputLabel: 'Επαληθευμένη διεύθυνση email', + verifyDomainsStep: { + title: 'Επαλήθευση τομέα', + subtitle: 'Καθορίστε και επαληθεύστε τον τομέα για τη διαμόρφωση του SSO.', + formFieldLabel__domain: 'Τομείς', + formFieldInputPlaceholder__domain: + 'Πληκτρολογήστε τον τομέα σας εδώ και κάντε κλικ στο «Προσθήκη» για να ξεκινήσετε', + formButtonPrimary__add: 'Προσθήκη', + txtRecordInstructions: { + paragraph1: 'Προσθέστε αυτήν την εγγραφή TXT στον πάροχο DNS σας.', + paragraph2: + 'Θα επαληθεύσουμε αυτόματα μόλις η εγγραφή τεθεί σε ισχύ. Αυτό συνήθως διαρκεί λιγότερο από ένα λεπτό, αν και η ενημέρωση μιας υπάρχουσας εγγραφής TXT ενδέχεται να διαρκέσει λίγο περισσότερο.', + }, + txtRecordTable: { + columns: { + domain: 'Τομέας', + type: 'Τύπος', + hostName: 'Κεντρικός υπολογιστής / Όνομα', + value: 'Τιμή', }, }, - domainTaken: { - title: 'Αυτός ο τομέας ({{domain}}) διαθέτει ήδη σύνδεση SSO', - subtitle: - 'Επικοινωνήστε με τον διαχειριστή της εφαρμογής για να αποκτήσετε πρόσβαση μέσω της υπάρχουσας σύνδεσης.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/en-GB.ts b/packages/localizations/src/en-GB.ts index e3123b6333a..ffe93a3dadd 100644 --- a/packages/localizations/src/en-GB.ts +++ b/packages/localizations/src/en-GB.ts @@ -196,29 +196,25 @@ export const enGB: LocalizationResource = { }, warning: 'Once a provider is selected you cannot change again until the configuration is over', }, - verifyEmailDomainStep: { - title: 'Verify email address', - subtitle: 'Verify the domain you want to enable the enterprise connection on.', - addEmailAddress: { - formTitle: 'We need your email', - formSubtitle: 'In order to start we will need your email address', - inputPlaceholder: 'name@company.com', - inputLabel: 'Email address', - }, - emailCode: { - formTitle: 'Verify your email address', - formSubtitle: 'Enter the verification code sent to {{identifier}}', - resendButton: "Didn't receive a code? Resend", - verified: { - title: 'We got your email', - subtitle: "You've verified your email address with the following email", - inputLabel: 'Verified email address', + verifyDomainsStep: { + title: 'Verify domains', + subtitle: 'Specify and verify the domains to configure SSO for.', + formFieldLabel__domain: 'Domains', + formFieldInputPlaceholder__domain: 'Type your domain here and click add to start', + formButtonPrimary__add: 'Add', + txtRecordInstructions: { + paragraph1: 'Add this TXT record to your DNS provider.', + paragraph2: + "We'll verify automatically once the record is live. This usually takes under a minute, though updating an existing TXT record may take a bit longer.", + }, + txtRecordTable: { + columns: { + domain: 'Domain', + type: 'Type', + hostName: 'Host / Name', + value: 'Value', }, }, - domainTaken: { - title: 'This domain ({{domain}}) already has an SSO connection', - subtitle: "Contact the application's administrator to get access through the existing connection.", - }, }, }, createOrganization: { @@ -540,7 +536,7 @@ export const enGB: LocalizationResource = { resendButton: "Didn't receive a code? Resend", subtitle: 'The domain {{domainName}} needs to be verified via email.', subtitleVerificationCodeScreen: 'A verification code was sent to {{emailAddress}}. Enter the code to continue.', - title: 'Verify domain', + title: 'Verify domains', }, }, organizationSwitcher: { diff --git a/packages/localizations/src/en-US.ts b/packages/localizations/src/en-US.ts index 5ac237a6cd2..8ddc66513c7 100644 --- a/packages/localizations/src/en-US.ts +++ b/packages/localizations/src/en-US.ts @@ -259,29 +259,25 @@ export const enUS: LocalizationResource = { }, warning: 'Once a provider is selected you cannot change again until the configuration is over', }, - verifyEmailDomainStep: { - title: 'Verify email address', - subtitle: 'Verify the domain you want to enable the enterprise connection on.', - addEmailAddress: { - formTitle: 'We need your email', - formSubtitle: 'In order to start we will need your email address', - inputPlaceholder: 'name@company.com', - inputLabel: 'Email address', - }, - emailCode: { - formTitle: 'Verify your email address', - formSubtitle: 'Enter the verification code sent to {{identifier}}', - resendButton: "Didn't receive a code? Resend", - verified: { - title: 'We got your email', - subtitle: "You've verified your email address with the following email", - inputLabel: 'Verified email address', + verifyDomainsStep: { + title: 'Verify domains', + subtitle: 'Specify and verify the domains to configure SSO for.', + formFieldLabel__domain: 'Domains', + formFieldInputPlaceholder__domain: 'Type your domain here and click add to start', + formButtonPrimary__add: 'Add', + txtRecordInstructions: { + paragraph1: 'Add this TXT record to your DNS provider.', + paragraph2: + "We'll verify automatically once the record is live. This usually takes under a minute, though updating an existing TXT record may take a bit longer.", + }, + txtRecordTable: { + columns: { + domain: 'Domain', + type: 'Type', + hostName: 'Host / Name', + value: 'Value', }, }, - domainTaken: { - title: 'This domain ({{domain}}) already has an SSO connection', - subtitle: "Contact the application's administrator to get access through the existing connection.", - }, }, testConfigurationStep: { title: 'Test your SSO connection', @@ -872,6 +868,7 @@ export const enUS: LocalizationResource = { badge__automaticInvitation: 'Automatic invitations', badge__automaticSuggestion: 'Automatic suggestions', badge__manualInvitation: 'No automatic enrollment', + badge__enterpriseSso: 'Enterprise SSO', badge__unverified: 'Unverified', billingPage: { paymentHistorySection: { @@ -1094,7 +1091,7 @@ export const enUS: LocalizationResource = { resendButton: "Didn't receive a code? Resend", subtitle: 'The domain {{domainName}} needs to be verified via email.', subtitleVerificationCodeScreen: 'A verification code was sent to {{emailAddress}}. Enter the code to continue.', - title: 'Verify domain', + title: 'Verify domains', }, }, organizationSwitcher: { diff --git a/packages/localizations/src/es-CR.ts b/packages/localizations/src/es-CR.ts index 5c193ce8b3d..a018ec06025 100644 --- a/packages/localizations/src/es-CR.ts +++ b/packages/localizations/src/es-CR.ts @@ -196,29 +196,25 @@ export const esCR: LocalizationResource = { }, warning: 'Una vez que se selecciona un proveedor no puedes cambiarlo hasta que termine la configuración', }, - verifyEmailDomainStep: { - title: 'Verificar correo electrónico', - subtitle: 'Verifica la dirección de correo electrónico en la que deseas habilitar la conexión empresarial.', - addEmailAddress: { - formTitle: 'Necesitamos tu correo electrónico', - formSubtitle: 'Para empezar, necesitaremos tu dirección de correo electrónico', - inputPlaceholder: 'name@company.com', - inputLabel: 'Dirección de correo electrónico', - }, - emailCode: { - formTitle: 'Verifica tu dirección de correo electrónico', - formSubtitle: 'Ingresa el código de verificación enviado a {{identifier}}', - resendButton: '¿No recibiste un código? Reenviar', - verified: { - title: 'Recibimos tu correo electrónico', - subtitle: 'Has verificado tu dirección de correo electrónico con el siguiente correo', - inputLabel: 'Dirección de correo electrónico verificada', + verifyDomainsStep: { + title: 'Verificar dominio', + subtitle: 'Especifica y verifica el dominio para configurar el SSO.', + formFieldLabel__domain: 'Dominios', + formFieldInputPlaceholder__domain: 'Escribe aquí tu dominio y haz clic en Agregar para empezar', + formButtonPrimary__add: 'Agregar', + txtRecordInstructions: { + paragraph1: 'Agrega este registro TXT a tu proveedor de DNS.', + paragraph2: + 'Lo verificaremos automáticamente en cuanto el registro esté activo. Esto suele tardar menos de un minuto, aunque actualizar un registro TXT existente puede tardar un poco más.', + }, + txtRecordTable: { + columns: { + domain: 'Dominio', + type: 'Tipo', + hostName: 'Host / Nombre', + value: 'Valor', }, }, - domainTaken: { - title: 'Este dominio ({{domain}}) ya tiene una conexión SSO', - subtitle: 'Contacta al administrador de la aplicación para obtener acceso a través de la conexión existente.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/es-ES.ts b/packages/localizations/src/es-ES.ts index 2ffb8d21c1b..deea37f3498 100644 --- a/packages/localizations/src/es-ES.ts +++ b/packages/localizations/src/es-ES.ts @@ -202,30 +202,25 @@ export const esES: LocalizationResource = { }, warning: 'Una vez seleccionado un proveedor no podrás cambiarlo hasta que finalice la configuración', }, - verifyEmailDomainStep: { - title: 'Verificar correo electrónico', - subtitle: 'Verifica la dirección de correo electrónico en la que deseas habilitar la conexión empresarial.', - addEmailAddress: { - formTitle: 'Necesitamos tu correo electrónico', - formSubtitle: 'Para empezar, necesitaremos tu dirección de correo electrónico', - inputPlaceholder: 'name@company.com', - inputLabel: 'Dirección de correo electrónico', - }, - emailCode: { - formTitle: 'Verifica tu dirección de correo electrónico', - formSubtitle: 'Introduce el código de verificación enviado a {{identifier}}', - resendButton: '¿No has recibido un código? Reenviar', - verified: { - title: 'Hemos recibido tu correo electrónico', - subtitle: 'Has verificado tu dirección de correo electrónico con el siguiente correo', - inputLabel: 'Dirección de correo electrónico verificada', + verifyDomainsStep: { + title: 'Verificar dominio', + subtitle: 'Especifica y verifica el dominio para configurar el SSO.', + formFieldLabel__domain: 'Dominios', + formFieldInputPlaceholder__domain: 'Escribe aquí tu dominio y haz clic en Añadir para empezar', + formButtonPrimary__add: 'Añadir', + txtRecordInstructions: { + paragraph1: 'Añade este registro TXT a tu proveedor de DNS.', + paragraph2: + 'Lo verificaremos automáticamente en cuanto el registro esté activo. Esto suele tardar menos de un minuto, aunque actualizar un registro TXT existente puede tardar un poco más.', + }, + txtRecordTable: { + columns: { + domain: 'Dominio', + type: 'Tipo', + hostName: 'Host / Nombre', + value: 'Valor', }, }, - domainTaken: { - title: 'Este dominio ({{domain}}) ya tiene una conexión SSO', - subtitle: - 'Contacta con el administrador de la aplicación para obtener acceso a través de la conexión existente.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/es-MX.ts b/packages/localizations/src/es-MX.ts index 1b1fa64ac67..423a0eb7234 100644 --- a/packages/localizations/src/es-MX.ts +++ b/packages/localizations/src/es-MX.ts @@ -197,29 +197,25 @@ export const esMX: LocalizationResource = { }, warning: 'Una vez que se selecciona un proveedor no puedes cambiarlo hasta que termine la configuración', }, - verifyEmailDomainStep: { - title: 'Verificar correo electrónico', - subtitle: 'Verifica la dirección de correo electrónico en la que deseas habilitar la conexión empresarial.', - addEmailAddress: { - formTitle: 'Necesitamos tu correo electrónico', - formSubtitle: 'Para empezar, necesitaremos tu dirección de correo electrónico', - inputPlaceholder: 'name@company.com', - inputLabel: 'Dirección de correo electrónico', - }, - emailCode: { - formTitle: 'Verifica tu dirección de correo electrónico', - formSubtitle: 'Ingresa el código de verificación enviado a {{identifier}}', - resendButton: '¿No recibiste un código? Reenviar', - verified: { - title: 'Recibimos tu correo electrónico', - subtitle: 'Has verificado tu dirección de correo electrónico con el siguiente correo', - inputLabel: 'Dirección de correo electrónico verificada', + verifyDomainsStep: { + title: 'Verificar dominio', + subtitle: 'Especifica y verifica el dominio para configurar el SSO.', + formFieldLabel__domain: 'Dominios', + formFieldInputPlaceholder__domain: 'Escribe aquí tu dominio y haz clic en Agregar para empezar', + formButtonPrimary__add: 'Agregar', + txtRecordInstructions: { + paragraph1: 'Agrega este registro TXT a tu proveedor de DNS.', + paragraph2: + 'Lo verificaremos automáticamente en cuanto el registro esté activo. Esto suele tardar menos de un minuto, aunque actualizar un registro TXT existente puede tardar un poco más.', + }, + txtRecordTable: { + columns: { + domain: 'Dominio', + type: 'Tipo', + hostName: 'Host / Nombre', + value: 'Valor', }, }, - domainTaken: { - title: 'Este dominio ({{domain}}) ya tiene una conexión SSO', - subtitle: 'Contacta al administrador de la aplicación para obtener acceso a través de la conexión existente.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/es-UY.ts b/packages/localizations/src/es-UY.ts index bd16067ed07..dcf9ad9b1c7 100644 --- a/packages/localizations/src/es-UY.ts +++ b/packages/localizations/src/es-UY.ts @@ -196,29 +196,25 @@ export const esUY: LocalizationResource = { }, warning: 'Una vez que se selecciona un proveedor no podés cambiarlo hasta que termine la configuración', }, - verifyEmailDomainStep: { - title: 'Verificar correo electrónico', - subtitle: 'Verificá la dirección de correo electrónico en la que querés habilitar la conexión empresarial.', - addEmailAddress: { - formTitle: 'Necesitamos tu correo electrónico', - formSubtitle: 'Para empezar, necesitaremos tu dirección de correo electrónico', - inputPlaceholder: 'name@company.com', - inputLabel: 'Dirección de correo electrónico', - }, - emailCode: { - formTitle: 'Verificá tu dirección de correo electrónico', - formSubtitle: 'Ingresá el código de verificación enviado a {{identifier}}', - resendButton: '¿No recibiste un código? Reenviar', - verified: { - title: 'Recibimos tu correo electrónico', - subtitle: 'Verificaste tu dirección de correo electrónico con el siguiente correo', - inputLabel: 'Dirección de correo electrónico verificada', + verifyDomainsStep: { + title: 'Verificar dominio', + subtitle: 'Especificá y verificá el dominio para configurar el SSO.', + formFieldLabel__domain: 'Dominios', + formFieldInputPlaceholder__domain: 'Escribí aquí tu dominio y hacé clic en Agregar para empezar', + formButtonPrimary__add: 'Agregar', + txtRecordInstructions: { + paragraph1: 'Agregá este registro TXT a tu proveedor de DNS.', + paragraph2: + 'Lo verificaremos automáticamente una vez que el registro esté activo. Esto suele tardar menos de un minuto, aunque actualizar un registro TXT existente puede tardar un poco más.', + }, + txtRecordTable: { + columns: { + domain: 'Dominio', + type: 'Tipo', + hostName: 'Host / Nombre', + value: 'Valor', }, }, - domainTaken: { - title: 'Este dominio ({{domain}}) ya tiene una conexión SSO', - subtitle: 'Contactá al administrador de la aplicación para obtener acceso a través de la conexión existente.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/fa-IR.ts b/packages/localizations/src/fa-IR.ts index 16b8afa5448..e033d4da5f6 100644 --- a/packages/localizations/src/fa-IR.ts +++ b/packages/localizations/src/fa-IR.ts @@ -201,29 +201,25 @@ export const faIR: LocalizationResource = { }, warning: 'پس از انتخاب یک ارائه‌دهنده، نمی‌توانید آن را تا پایان پیکربندی تغییر دهید', }, - verifyEmailDomainStep: { - title: 'تأیید آدرس ایمیل', - subtitle: 'آدرس ایمیلی را که می‌خواهید اتصال سازمانی روی آن فعال شود، تأیید کنید.', - addEmailAddress: { - formTitle: 'به ایمیل شما نیاز داریم', - formSubtitle: 'برای شروع به آدرس ایمیل شما نیاز داریم', - inputPlaceholder: 'name@company.com', - inputLabel: 'آدرس ایمیل', - }, - emailCode: { - formTitle: 'آدرس ایمیل خود را تأیید کنید', - formSubtitle: 'کد تأیید ارسال شده به {{identifier}} را وارد کنید', - resendButton: 'کد را دریافت نکردید؟ ارسال مجدد', - verified: { - title: 'ایمیل شما را دریافت کردیم', - subtitle: 'شما آدرس ایمیل خود را با ایمیل زیر تأیید کرده‌اید', - inputLabel: 'آدرس ایمیل تأیید شده', + verifyDomainsStep: { + title: 'تأیید دامنه', + subtitle: 'دامنه‌ای را که می‌خواهید SSO برای آن پیکربندی شود، مشخص و تأیید کنید.', + formFieldLabel__domain: 'دامنه‌ها', + formFieldInputPlaceholder__domain: 'دامنه خود را اینجا تایپ کنید و برای شروع روی افزودن کلیک کنید', + formButtonPrimary__add: 'افزودن', + txtRecordInstructions: { + paragraph1: 'این رکورد TXT را به ارائه‌دهنده DNS خود اضافه کنید.', + paragraph2: + 'به محض فعال شدن رکورد، به‌طور خودکار آن را تأیید می‌کنیم. این کار معمولاً کمتر از یک دقیقه طول می‌کشد، هرچند به‌روزرسانی یک رکورد TXT موجود ممکن است کمی بیشتر زمان ببرد.', + }, + txtRecordTable: { + columns: { + domain: 'دامنه', + type: 'نوع', + hostName: 'میزبان / نام', + value: 'مقدار', }, }, - domainTaken: { - title: 'این دامنه ({{domain}}) قبلاً یک اتصال SSO دارد', - subtitle: 'برای دسترسی از طریق اتصال موجود، با مدیر برنامه تماس بگیرید.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/fi-FI.ts b/packages/localizations/src/fi-FI.ts index 7f5fa9eeb14..8df75dcf490 100644 --- a/packages/localizations/src/fi-FI.ts +++ b/packages/localizations/src/fi-FI.ts @@ -224,30 +224,25 @@ export const fiFI: LocalizationResource = { }, warning: 'Kun palveluntarjoaja on valittu, et voi vaihtaa sitä ennen kuin määritys on valmis', }, - verifyEmailDomainStep: { - title: 'Vahvista sähköpostiosoite', - subtitle: 'Vahvista sähköpostiosoite, jolle haluat ottaa yritysyhteyden käyttöön.', - addEmailAddress: { - formTitle: 'Tarvitsemme sähköpostiosi', - formSubtitle: 'Aloittaaksemme tarvitsemme sähköpostiosoitteesi', - inputPlaceholder: 'name@company.com', - inputLabel: 'Sähköpostiosoite', - }, - emailCode: { - formTitle: 'Vahvista sähköpostiosoitteesi', - formSubtitle: 'Anna vahvistuskoodi, joka lähetettiin osoitteeseen {{identifier}}', - resendButton: 'Etkö saanut koodia? Lähetä uudelleen', - verified: { - title: 'Saimme sähköpostisi', - subtitle: 'Olet vahvistanut sähköpostiosoitteesi seuraavalla sähköpostilla', - inputLabel: 'Vahvistettu sähköpostiosoite', + verifyDomainsStep: { + title: 'Vahvista verkkotunnus', + subtitle: 'Määritä ja vahvista verkkotunnus, jolle SSO määritetään.', + formFieldLabel__domain: 'Verkkotunnukset', + formFieldInputPlaceholder__domain: 'Kirjoita verkkotunnuksesi tähän ja aloita napsauttamalla Lisää', + formButtonPrimary__add: 'Lisää', + txtRecordInstructions: { + paragraph1: 'Lisää tämä TXT-tietue DNS-palveluntarjoajallesi.', + paragraph2: + 'Vahvistamme sen automaattisesti, kun tietue on aktiivinen. Tämä kestää yleensä alle minuutin, mutta olemassa olevan TXT-tietueen päivittäminen voi kestää hieman kauemmin.', + }, + txtRecordTable: { + columns: { + domain: 'Verkkotunnus', + type: 'Tyyppi', + hostName: 'Isäntä / Nimi', + value: 'Arvo', }, }, - domainTaken: { - title: 'Tällä verkkotunnuksella ({{domain}}) on jo SSO-yhteys', - subtitle: - 'Ota yhteyttä sovelluksen järjestelmänvalvojaan saadaksesi käyttöoikeudet olemassa olevan yhteyden kautta.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/fr-FR.ts b/packages/localizations/src/fr-FR.ts index a33f1289508..55aa09dbceb 100644 --- a/packages/localizations/src/fr-FR.ts +++ b/packages/localizations/src/fr-FR.ts @@ -205,29 +205,25 @@ export const frFR: LocalizationResource = { warning: "Une fois un fournisseur sélectionné, vous ne pourrez plus en changer jusqu'à la fin de la configuration", }, - verifyEmailDomainStep: { - title: "Vérifier l'adresse e-mail", - subtitle: "Vérifiez l'adresse e-mail sur laquelle vous souhaitez activer la connexion entreprise.", - addEmailAddress: { - formTitle: 'Nous avons besoin de votre e-mail', - formSubtitle: 'Pour commencer, nous aurons besoin de votre adresse e-mail', - inputPlaceholder: 'name@company.com', - inputLabel: 'Adresse e-mail', - }, - emailCode: { - formTitle: 'Vérifiez votre adresse e-mail', - formSubtitle: 'Entrez le code de vérification envoyé à {{identifier}}', - resendButton: "Vous n'avez pas reçu de code ? Renvoyer", - verified: { - title: 'Nous avons reçu votre e-mail', - subtitle: "Vous avez vérifié votre adresse e-mail avec l'e-mail suivant", - inputLabel: 'Adresse e-mail vérifiée', + verifyDomainsStep: { + title: 'Vérifier le domaine', + subtitle: 'Spécifiez et vérifiez le domaine pour lequel configurer le SSO.', + formFieldLabel__domain: 'Domaines', + formFieldInputPlaceholder__domain: 'Saisissez votre domaine ici et cliquez sur Ajouter pour commencer', + formButtonPrimary__add: 'Ajouter', + txtRecordInstructions: { + paragraph1: 'Ajoutez cet enregistrement TXT à votre fournisseur DNS.', + paragraph2: + "Nous vérifierons automatiquement une fois l'enregistrement actif. Cela prend généralement moins d'une minute, bien que la mise à jour d'un enregistrement TXT existant puisse prendre un peu plus de temps.", + }, + txtRecordTable: { + columns: { + domain: 'Domaine', + type: 'Type', + hostName: 'Hôte / Nom', + value: 'Valeur', }, }, - domainTaken: { - title: "Ce domaine ({{domain}}) dispose déjà d'une connexion SSO", - subtitle: "Contactez l'administrateur de l'application pour obtenir l'accès via la connexion existante.", - }, }, }, createOrganization: { diff --git a/packages/localizations/src/he-IL.ts b/packages/localizations/src/he-IL.ts index 6dbf545ab7e..2f9ece206fc 100644 --- a/packages/localizations/src/he-IL.ts +++ b/packages/localizations/src/he-IL.ts @@ -196,29 +196,25 @@ export const heIL: LocalizationResource = { }, warning: 'לאחר בחירת ספק לא ניתן לשנות אותו עד לסיום ההגדרה', }, - verifyEmailDomainStep: { - title: 'אימות כתובת אימייל', - subtitle: 'אמת את כתובת האימייל שעליה ברצונך להפעיל את חיבור הארגון.', - addEmailAddress: { - formTitle: 'אנחנו צריכים את האימייל שלך', - formSubtitle: 'כדי להתחיל, נצטרך את כתובת האימייל שלך', - inputPlaceholder: 'name@company.com', - inputLabel: 'כתובת אימייל', - }, - emailCode: { - formTitle: 'אמת את כתובת האימייל שלך', - formSubtitle: 'הזן את קוד האימות שנשלח אל {{identifier}}', - resendButton: 'לא קיבלת קוד? שלח שוב', - verified: { - title: 'קיבלנו את האימייל שלך', - subtitle: 'אימתת את כתובת האימייל שלך עם האימייל הבא', - inputLabel: 'כתובת אימייל מאומתת', + verifyDomainsStep: { + title: 'אימות דומיין', + subtitle: 'ציין ואמת את הדומיין שעבורו ברצונך להגדיר SSO.', + formFieldLabel__domain: 'דומיינים', + formFieldInputPlaceholder__domain: 'הקלד את הדומיין שלך כאן ולחץ על הוסף כדי להתחיל', + formButtonPrimary__add: 'הוסף', + txtRecordInstructions: { + paragraph1: 'הוסף רשומת TXT זו לספק ה-DNS שלך.', + paragraph2: + 'אנו נאמת באופן אוטומטי ברגע שהרשומה תהיה פעילה. בדרך כלל זה לוקח פחות מדקה, אם כי עדכון רשומת TXT קיימת עשוי להימשך מעט יותר.', + }, + txtRecordTable: { + columns: { + domain: 'דומיין', + type: 'סוג', + hostName: 'מארח / שם', + value: 'ערך', }, }, - domainTaken: { - title: 'לדומיין הזה ({{domain}}) כבר יש חיבור SSO', - subtitle: 'צור קשר עם מנהל היישום כדי לקבל גישה דרך החיבור הקיים.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/hi-IN.ts b/packages/localizations/src/hi-IN.ts index 66a57251752..20fbbd1a16f 100644 --- a/packages/localizations/src/hi-IN.ts +++ b/packages/localizations/src/hi-IN.ts @@ -202,29 +202,25 @@ export const hiIN: LocalizationResource = { }, warning: 'एक बार प्रदाता का चयन करने के बाद आप कॉन्फ़िगरेशन समाप्त होने तक इसे बदल नहीं सकते', }, - verifyEmailDomainStep: { - title: 'ईमेल पता सत्यापित करें', - subtitle: 'उस ईमेल पते को सत्यापित करें जिस पर आप एंटरप्राइज़ कनेक्शन सक्षम करना चाहते हैं।', - addEmailAddress: { - formTitle: 'हमें आपके ईमेल की आवश्यकता है', - formSubtitle: 'शुरू करने के लिए हमें आपके ईमेल पते की आवश्यकता होगी', - inputPlaceholder: 'name@company.com', - inputLabel: 'ईमेल पता', - }, - emailCode: { - formTitle: 'अपना ईमेल पता सत्यापित करें', - formSubtitle: '{{identifier}} पर भेजा गया सत्यापन कोड दर्ज करें', - resendButton: 'कोड नहीं मिला? पुनः भेजें', - verified: { - title: 'हमें आपका ईमेल मिल गया', - subtitle: 'आपने निम्नलिखित ईमेल के साथ अपना ईमेल पता सत्यापित किया है', - inputLabel: 'सत्यापित ईमेल पता', + verifyDomainsStep: { + title: 'डोमेन सत्यापित करें', + subtitle: 'SSO कॉन्फ़िगर करने के लिए डोमेन निर्दिष्ट करें और सत्यापित करें।', + formFieldLabel__domain: 'डोमेन', + formFieldInputPlaceholder__domain: 'अपना डोमेन यहाँ टाइप करें और शुरू करने के लिए जोड़ें पर क्लिक करें', + formButtonPrimary__add: 'जोड़ें', + txtRecordInstructions: { + paragraph1: 'इस TXT रिकॉर्ड को अपने DNS प्रदाता में जोड़ें।', + paragraph2: + 'रिकॉर्ड सक्रिय होते ही हम स्वचालित रूप से सत्यापित कर देंगे। इसमें आमतौर पर एक मिनट से कम समय लगता है, हालाँकि किसी मौजूदा TXT रिकॉर्ड को अपडेट करने में थोड़ा अधिक समय लग सकता है।', + }, + txtRecordTable: { + columns: { + domain: 'डोमेन', + type: 'प्रकार', + hostName: 'होस्ट / नाम', + value: 'मान', }, }, - domainTaken: { - title: 'इस डोमेन ({{domain}}) में पहले से ही एक SSO कनेक्शन है', - subtitle: 'मौजूदा कनेक्शन के माध्यम से एक्सेस प्राप्त करने के लिए एप्लिकेशन के व्यवस्थापक से संपर्क करें।', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/hr-HR.ts b/packages/localizations/src/hr-HR.ts index 1b31cfebbfa..a27a44db574 100644 --- a/packages/localizations/src/hr-HR.ts +++ b/packages/localizations/src/hr-HR.ts @@ -225,29 +225,25 @@ export const hrHR: LocalizationResource = { }, warning: 'Nakon odabira pružatelja ne možete ga ponovno mijenjati dok konfiguracija ne završi', }, - verifyEmailDomainStep: { - title: 'Potvrdi e-mail adresu', - subtitle: 'Potvrdite e-mail adresu na kojoj želite omogućiti poslovnu vezu.', - addEmailAddress: { - formTitle: 'Treba nam vaš e-mail', - formSubtitle: 'Za početak ćemo trebati vašu e-mail adresu', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mail adresa', - }, - emailCode: { - formTitle: 'Potvrdite svoju e-mail adresu', - formSubtitle: 'Unesite verifikacijski kod poslan na {{identifier}}', - resendButton: 'Niste primili kod? Pošalji ponovno', - verified: { - title: 'Primili smo vaš e-mail', - subtitle: 'Potvrdili ste svoju e-mail adresu sljedećim e-mailom', - inputLabel: 'Potvrđena e-mail adresa', + verifyDomainsStep: { + title: 'Potvrdi domenu', + subtitle: 'Navedite i potvrdite domenu za koju želite konfigurirati SSO.', + formFieldLabel__domain: 'Domene', + formFieldInputPlaceholder__domain: 'Ovdje upišite svoju domenu i kliknite dodaj za početak', + formButtonPrimary__add: 'Dodaj', + txtRecordInstructions: { + paragraph1: 'Dodajte ovaj TXT zapis kod svog DNS pružatelja.', + paragraph2: + 'Automatski ćemo ga provjeriti čim zapis postane aktivan. To obično traje manje od minute, iako ažuriranje postojećeg TXT zapisa može potrajati nešto dulje.', + }, + txtRecordTable: { + columns: { + domain: 'Domena', + type: 'Vrsta', + hostName: 'Host / Naziv', + value: 'Vrijednost', }, }, - domainTaken: { - title: 'Ova domena ({{domain}}) već ima SSO vezu', - subtitle: 'Kontaktirajte administratora aplikacije kako biste dobili pristup putem postojeće veze.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/hu-HU.ts b/packages/localizations/src/hu-HU.ts index 3714f35e4a0..a34f8f0a266 100644 --- a/packages/localizations/src/hu-HU.ts +++ b/packages/localizations/src/hu-HU.ts @@ -225,29 +225,25 @@ export const huHU: LocalizationResource = { }, warning: 'Miután kiválasztotta a szolgáltatót, nem módosíthatja, amíg a konfiguráció be nem fejeződik', }, - verifyEmailDomainStep: { - title: 'E-mail-cím megerősítése', - subtitle: 'Erősítse meg azt az e-mail-címet, amelyen engedélyezni szeretné a vállalati kapcsolatot.', - addEmailAddress: { - formTitle: 'Szükségünk van az e-mail-címére', - formSubtitle: 'A kezdéshez szükségünk lesz az e-mail-címére', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mail-cím', - }, - emailCode: { - formTitle: 'Erősítse meg az e-mail-címét', - formSubtitle: 'Adja meg a {{identifier}} címre küldött ellenőrző kódot', - resendButton: 'Nem kapott kódot? Küldés újra', - verified: { - title: 'Megkaptuk az e-mailjét', - subtitle: 'Megerősítette az e-mail-címét az alábbi e-maillel', - inputLabel: 'Megerősített e-mail-cím', + verifyDomainsStep: { + title: 'Tartomány megerősítése', + subtitle: 'Adja meg és erősítse meg a tartományt, amelyhez az SSO-t szeretné beállítani.', + formFieldLabel__domain: 'Tartományok', + formFieldInputPlaceholder__domain: 'Írja be ide a tartományát, majd kattintson a Hozzáadás gombra a kezdéshez', + formButtonPrimary__add: 'Hozzáadás', + txtRecordInstructions: { + paragraph1: 'Adja hozzá ezt a TXT-rekordot a DNS-szolgáltatójához.', + paragraph2: + 'Automatikusan ellenőrizzük, amint a rekord élesedik. Ez általában kevesebb mint egy percet vesz igénybe, bár egy meglévő TXT-rekord frissítése egy kicsit tovább tarthat.', + }, + txtRecordTable: { + columns: { + domain: 'Tartomány', + type: 'Típus', + hostName: 'Gazdagép / Név', + value: 'Érték', }, }, - domainTaken: { - title: 'Ez a domain ({{domain}}) már rendelkezik SSO-kapcsolattal', - subtitle: 'A meglévő kapcsolaton keresztüli hozzáférés érdekében forduljon az alkalmazás rendszergazdájához.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/id-ID.ts b/packages/localizations/src/id-ID.ts index 1483a6307e2..b521e646b23 100644 --- a/packages/localizations/src/id-ID.ts +++ b/packages/localizations/src/id-ID.ts @@ -196,29 +196,25 @@ export const idID: LocalizationResource = { }, warning: 'Setelah penyedia dipilih, Anda tidak dapat mengubahnya lagi sampai konfigurasi selesai', }, - verifyEmailDomainStep: { - title: 'Verifikasi alamat email', - subtitle: 'Verifikasi alamat email yang ingin Anda aktifkan koneksi enterprise-nya.', - addEmailAddress: { - formTitle: 'Kami membutuhkan email Anda', - formSubtitle: 'Untuk memulai, kami membutuhkan alamat email Anda', - inputPlaceholder: 'name@company.com', - inputLabel: 'Alamat email', - }, - emailCode: { - formTitle: 'Verifikasi alamat email Anda', - formSubtitle: 'Masukkan kode verifikasi yang dikirim ke {{identifier}}', - resendButton: 'Tidak menerima kode? Kirim ulang', - verified: { - title: 'Kami mendapatkan email Anda', - subtitle: 'Anda telah memverifikasi alamat email Anda dengan email berikut', - inputLabel: 'Alamat email terverifikasi', + verifyDomainsStep: { + title: 'Verifikasi domain', + subtitle: 'Tentukan dan verifikasi domain untuk mengonfigurasi SSO.', + formFieldLabel__domain: 'Domain', + formFieldInputPlaceholder__domain: 'Ketik domain Anda di sini dan klik tambah untuk memulai', + formButtonPrimary__add: 'Tambah', + txtRecordInstructions: { + paragraph1: 'Tambahkan rekaman TXT ini ke penyedia DNS Anda.', + paragraph2: + 'Kami akan memverifikasi secara otomatis setelah rekaman aktif. Ini biasanya memerlukan waktu kurang dari satu menit, meskipun memperbarui rekaman TXT yang sudah ada mungkin memerlukan waktu sedikit lebih lama.', + }, + txtRecordTable: { + columns: { + domain: 'Domain', + type: 'Tipe', + hostName: 'Host / Nama', + value: 'Nilai', }, }, - domainTaken: { - title: 'Domain ini ({{domain}}) sudah memiliki koneksi SSO', - subtitle: 'Hubungi administrator aplikasi untuk mendapatkan akses melalui koneksi yang ada.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/is-IS.ts b/packages/localizations/src/is-IS.ts index 304827137bb..3a5073b64a6 100644 --- a/packages/localizations/src/is-IS.ts +++ b/packages/localizations/src/is-IS.ts @@ -224,29 +224,25 @@ export const isIS: LocalizationResource = { }, warning: 'Þegar þjónustuaðili hefur verið valinn er ekki hægt að breyta aftur fyrr en stillingu er lokið', }, - verifyEmailDomainStep: { - title: 'Staðfesta tölvupóstfang', - subtitle: 'Staðfestu tölvupóstfangið sem þú vilt virkja fyrirtækjatenginguna á.', - addEmailAddress: { - formTitle: 'Við þurfum tölvupóstinn þinn', - formSubtitle: 'Til að byrja þurfum við tölvupóstfangið þitt', - inputPlaceholder: 'name@company.com', - inputLabel: 'Tölvupóstfang', - }, - emailCode: { - formTitle: 'Staðfestu tölvupóstfangið þitt', - formSubtitle: 'Sláðu inn staðfestingarkóðann sem var sendur á {{identifier}}', - resendButton: 'Fékkstu engan kóða? Senda aftur', - verified: { - title: 'Við fengum tölvupóstinn þinn', - subtitle: 'Þú hefur staðfest tölvupóstfangið þitt með eftirfarandi tölvupósti', - inputLabel: 'Staðfest tölvupóstfang', + verifyDomainsStep: { + title: 'Staðfesta lén', + subtitle: 'Tilgreindu og staðfestu lénið sem þú vilt stilla SSO fyrir.', + formFieldLabel__domain: 'Lén', + formFieldInputPlaceholder__domain: 'Skrifaðu lénið þitt hér og smelltu á bæta við til að byrja', + formButtonPrimary__add: 'Bæta við', + txtRecordInstructions: { + paragraph1: 'Bættu þessari TXT-færslu við hjá DNS-þjónustuaðilanum þínum.', + paragraph2: + 'Við staðfestum sjálfkrafa um leið og færslan er virk. Þetta tekur yfirleitt innan við mínútu, en það getur tekið aðeins lengri tíma að uppfæra TXT-færslu sem fyrir er.', + }, + txtRecordTable: { + columns: { + domain: 'Lén', + type: 'Tegund', + hostName: 'Hýsill / Nafn', + value: 'Gildi', }, }, - domainTaken: { - title: 'Þetta lén ({{domain}}) er þegar með SSO-tengingu', - subtitle: 'Hafðu samband við stjórnanda forritsins til að fá aðgang í gegnum núverandi tengingu.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/it-IT.ts b/packages/localizations/src/it-IT.ts index 619225ef990..4dd5b8c0e45 100644 --- a/packages/localizations/src/it-IT.ts +++ b/packages/localizations/src/it-IT.ts @@ -202,30 +202,25 @@ export const itIT: LocalizationResource = { }, warning: 'Una volta selezionato un provider non potrai cambiarlo fino al termine della configurazione', }, - verifyEmailDomainStep: { - title: 'Verifica indirizzo email', - subtitle: "Verifica l'indirizzo email su cui vuoi abilitare la connessione aziendale.", - addEmailAddress: { - formTitle: 'Abbiamo bisogno della tua email', - formSubtitle: 'Per iniziare avremo bisogno del tuo indirizzo email', - inputPlaceholder: 'name@company.com', - inputLabel: 'Indirizzo email', - }, - emailCode: { - formTitle: 'Verifica il tuo indirizzo email', - formSubtitle: 'Inserisci il codice di verifica inviato a {{identifier}}', - resendButton: 'Non hai ricevuto il codice? Invia di nuovo', - verified: { - title: 'Abbiamo ricevuto la tua email', - subtitle: 'Hai verificato il tuo indirizzo email con la seguente email', - inputLabel: 'Indirizzo email verificato', + verifyDomainsStep: { + title: 'Verifica dominio', + subtitle: "Specifica e verifica il dominio per cui configurare l'SSO.", + formFieldLabel__domain: 'Domini', + formFieldInputPlaceholder__domain: 'Digita qui il tuo dominio e clicca su Aggiungi per iniziare', + formButtonPrimary__add: 'Aggiungi', + txtRecordInstructions: { + paragraph1: 'Aggiungi questo record TXT al tuo provider DNS.', + paragraph2: + "Verificheremo automaticamente una volta che il record sarà attivo. Di solito richiede meno di un minuto, anche se l'aggiornamento di un record TXT esistente potrebbe richiedere un po' più di tempo.", + }, + txtRecordTable: { + columns: { + domain: 'Dominio', + type: 'Tipo', + hostName: 'Host / Nome', + value: 'Valore', }, }, - domainTaken: { - title: 'Questo dominio ({{domain}}) ha già una connessione SSO', - subtitle: - "Contatta l'amministratore dell'applicazione per ottenere l'accesso tramite la connessione esistente.", - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ja-JP.ts b/packages/localizations/src/ja-JP.ts index 35ecb633605..25c237a8a60 100644 --- a/packages/localizations/src/ja-JP.ts +++ b/packages/localizations/src/ja-JP.ts @@ -207,29 +207,25 @@ export const jaJP: LocalizationResource = { }, warning: 'プロバイダーを選択すると、設定が完了するまで変更できません', }, - verifyEmailDomainStep: { - title: 'メールアドレスを確認', - subtitle: 'エンタープライズ接続を有効にしたいメールアドレスを確認します。', - addEmailAddress: { - formTitle: 'メールアドレスが必要です', - formSubtitle: '開始するにはメールアドレスが必要です', - inputPlaceholder: 'name@company.com', - inputLabel: 'メールアドレス', - }, - emailCode: { - formTitle: 'メールアドレスを確認', - formSubtitle: '{{identifier}} に送信された確認コードを入力してください', - resendButton: 'コードを受け取っていませんか?再送信', - verified: { - title: 'メールを受け取りました', - subtitle: '次のメールでメールアドレスを確認しました', - inputLabel: '確認済みメールアドレス', + verifyDomainsStep: { + title: 'ドメインを確認', + subtitle: 'SSO を設定するドメインを指定して確認します。', + formFieldLabel__domain: 'ドメイン', + formFieldInputPlaceholder__domain: 'ここにドメインを入力し、「追加」をクリックして開始します', + formButtonPrimary__add: '追加', + txtRecordInstructions: { + paragraph1: 'この TXT レコードを DNS プロバイダーに追加します。', + paragraph2: + 'レコードが有効になると、自動的に確認します。通常は 1 分以内に完了しますが、既存の TXT レコードを更新する場合は少し時間がかかることがあります。', + }, + txtRecordTable: { + columns: { + domain: 'ドメイン', + type: 'タイプ', + hostName: 'ホスト / 名前', + value: '値', }, }, - domainTaken: { - title: 'このドメイン ({{domain}}) にはすでに SSO 接続が存在します', - subtitle: '既存の接続を通じてアクセスを取得するには、アプリケーションの管理者にお問い合わせください。', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/kk-KZ.ts b/packages/localizations/src/kk-KZ.ts index ce4c0f5a143..74d0588b1b0 100644 --- a/packages/localizations/src/kk-KZ.ts +++ b/packages/localizations/src/kk-KZ.ts @@ -196,29 +196,25 @@ export const kkKZ: LocalizationResource = { }, warning: 'Провайдер таңдалғаннан кейін, конфигурация аяқталғанша өзгерте алмайсыз', }, - verifyEmailDomainStep: { - title: 'Электрондық пошта мекенжайын растау', - subtitle: 'Кәсіпорын байланысын іске қосқыңыз келетін электрондық пошта мекенжайын растаңыз.', - addEmailAddress: { - formTitle: 'Бізге электрондық поштаңыз қажет', - formSubtitle: 'Бастау үшін электрондық пошта мекенжайыңыз қажет болады', - inputPlaceholder: 'name@company.com', - inputLabel: 'Электрондық пошта мекенжайы', - }, - emailCode: { - formTitle: 'Электрондық пошта мекенжайыңызды растаңыз', - formSubtitle: '{{identifier}} мекенжайына жіберілген растау кодын енгізіңіз', - resendButton: 'Код алмадыңыз ба? Қайта жіберу', - verified: { - title: 'Электрондық поштаңызды алдық', - subtitle: 'Электрондық пошта мекенжайыңызды келесі поштамен растадыңыз', - inputLabel: 'Расталған электрондық пошта мекенжайы', + verifyDomainsStep: { + title: 'Доменді растау', + subtitle: 'SSO теңшеу үшін доменді көрсетіп, растаңыз.', + formFieldLabel__domain: 'Домендер', + formFieldInputPlaceholder__domain: 'Доменіңізді осы жерге енгізіп, бастау үшін «Қосу» түймесін басыңыз', + formButtonPrimary__add: 'Қосу', + txtRecordInstructions: { + paragraph1: 'Бұл TXT жазбасын DNS провайдеріңізге қосыңыз.', + paragraph2: + 'Жазба белсенді болған бойда біз оны автоматты түрде тексереміз. Әдетте бұл бір минуттан аз уақыт алады, бірақ бар TXT жазбасын жаңарту сәл көбірек уақыт алуы мүмкін.', + }, + txtRecordTable: { + columns: { + domain: 'Домен', + type: 'Түрі', + hostName: 'Хост / Атау', + value: 'Мән', }, }, - domainTaken: { - title: 'Бұл доменде ({{domain}}) бұрыннан SSO байланысы бар', - subtitle: 'Қолданыстағы байланыс арқылы кіруге қол жеткізу үшін қолданба әкімшісіне хабарласыңыз.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ko-KR.ts b/packages/localizations/src/ko-KR.ts index 38e8112a117..bc182fdcdba 100644 --- a/packages/localizations/src/ko-KR.ts +++ b/packages/localizations/src/ko-KR.ts @@ -203,29 +203,25 @@ export const koKR: LocalizationResource = { }, warning: '공급자를 선택하면 구성이 완료될 때까지 다시 변경할 수 없습니다', }, - verifyEmailDomainStep: { - title: '이메일 주소 확인', - subtitle: '엔터프라이즈 연결을 활성화하려는 이메일 주소를 확인하세요.', - addEmailAddress: { - formTitle: '이메일이 필요합니다', - formSubtitle: '시작하려면 이메일 주소가 필요합니다', - inputPlaceholder: 'name@company.com', - inputLabel: '이메일 주소', - }, - emailCode: { - formTitle: '이메일 주소를 확인하세요', - formSubtitle: '{{identifier}}(으)로 전송된 인증 코드를 입력하세요', - resendButton: '코드를 받지 못하셨나요? 다시 보내기', - verified: { - title: '이메일을 받았습니다', - subtitle: '다음 이메일로 이메일 주소를 확인했습니다', - inputLabel: '확인된 이메일 주소', + verifyDomainsStep: { + title: '도메인 확인', + subtitle: 'SSO를 구성할 도메인을 지정하고 확인하세요.', + formFieldLabel__domain: '도메인', + formFieldInputPlaceholder__domain: '여기에 도메인을 입력하고 추가를 클릭하여 시작하세요', + formButtonPrimary__add: '추가', + txtRecordInstructions: { + paragraph1: '이 TXT 레코드를 DNS 공급자에 추가하세요.', + paragraph2: + '레코드가 활성화되면 자동으로 확인합니다. 일반적으로 1분 이내에 완료되지만, 기존 TXT 레코드를 업데이트하는 경우 다소 시간이 걸릴 수 있습니다.', + }, + txtRecordTable: { + columns: { + domain: '도메인', + type: '유형', + hostName: '호스트 / 이름', + value: '값', }, }, - domainTaken: { - title: '이 도메인 ({{domain}}) 에는 이미 SSO 연결이 있습니다', - subtitle: '기존 연결을 통해 접근 권한을 받으려면 애플리케이션 관리자에게 문의하세요.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/mn-MN.ts b/packages/localizations/src/mn-MN.ts index 4935f8b22aa..34e08f36a0e 100644 --- a/packages/localizations/src/mn-MN.ts +++ b/packages/localizations/src/mn-MN.ts @@ -196,29 +196,25 @@ export const mnMN: LocalizationResource = { }, warning: 'Үйлчилгээ үзүүлэгчийг сонгосны дараа тохиргоо дуустал өөрчлөх боломжгүй', }, - verifyEmailDomainStep: { - title: 'И-мэйл хаягийг баталгаажуулах', - subtitle: 'Та байгууллагын холболтыг идэвхжүүлэхийг хүсэж буй и-мэйл хаягийг баталгаажуулна уу.', - addEmailAddress: { - formTitle: 'Бид таны и-мэйл хэрэгтэй', - formSubtitle: 'Эхлэхийн тулд бид таны и-мэйл хаягийг авах шаардлагатай', - inputPlaceholder: 'name@company.com', - inputLabel: 'И-мэйл хаяг', - }, - emailCode: { - formTitle: 'И-мэйл хаягаа баталгаажуулна уу', - formSubtitle: '{{identifier}} рүү илгээсэн баталгаажуулах кодыг оруулна уу', - resendButton: 'Код хүлээж аваагүй юу? Дахин илгээх', - verified: { - title: 'Бид таны и-мэйлийг хүлээн авлаа', - subtitle: 'Та доорх и-мэйлээр и-мэйл хаягаа баталгаажуулсан', - inputLabel: 'Баталгаажсан и-мэйл хаяг', + verifyDomainsStep: { + title: 'Домэйныг баталгаажуулах', + subtitle: 'SSO тохируулах домэйныг зааж, баталгаажуулна уу.', + formFieldLabel__domain: 'Домэйн', + formFieldInputPlaceholder__domain: 'Домэйнээ энд бичээд эхлэхийн тулд нэмэх дээр дарна уу', + formButtonPrimary__add: 'Нэмэх', + txtRecordInstructions: { + paragraph1: 'Энэ TXT бичлэгийг DNS үйлчилгээ үзүүлэгчдээ нэмнэ үү.', + paragraph2: + 'Бичлэг идэвхэжсэн даруйд бид автоматаар баталгаажуулна. Энэ нь ихэвчлэн нэг минутаас бага хугацаа авдаг ч одоо байгаа TXT бичлэгийг шинэчлэхэд арай удаан хугацаа шаардагдаж магадгүй.', + }, + txtRecordTable: { + columns: { + domain: 'Домэйн', + type: 'Төрөл', + hostName: 'Хост / Нэр', + value: 'Утга', }, }, - domainTaken: { - title: 'Энэ домейн ({{domain}}) аль хэдийн SSO холболттой байна', - subtitle: 'Одоо байгаа холболтоор дамжуулан хандах эрх авахын тулд програмын администратортой холбогдоно уу.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ms-MY.ts b/packages/localizations/src/ms-MY.ts index 4d2afdf435b..e72769b5a34 100644 --- a/packages/localizations/src/ms-MY.ts +++ b/packages/localizations/src/ms-MY.ts @@ -204,29 +204,25 @@ export const msMY: LocalizationResource = { }, warning: 'Setelah pembekal dipilih anda tidak boleh menukar lagi sehingga konfigurasi selesai', }, - verifyEmailDomainStep: { - title: 'Sahkan alamat e-mel', - subtitle: 'Sahkan alamat e-mel yang anda ingin dayakan sambungan enterprise.', - addEmailAddress: { - formTitle: 'Kami memerlukan e-mel anda', - formSubtitle: 'Untuk memulakan kami memerlukan alamat e-mel anda', - inputPlaceholder: 'name@company.com', - inputLabel: 'Alamat e-mel', - }, - emailCode: { - formTitle: 'Sahkan alamat e-mel anda', - formSubtitle: 'Masukkan kod pengesahan yang dihantar ke {{identifier}}', - resendButton: 'Tidak menerima kod? Hantar semula', - verified: { - title: 'Kami menerima e-mel anda', - subtitle: 'Anda telah mengesahkan alamat e-mel anda dengan e-mel berikut', - inputLabel: 'Alamat e-mel disahkan', + verifyDomainsStep: { + title: 'Sahkan domain', + subtitle: 'Nyatakan dan sahkan domain untuk mengkonfigurasi SSO.', + formFieldLabel__domain: 'Domain', + formFieldInputPlaceholder__domain: 'Taip domain anda di sini dan klik tambah untuk bermula', + formButtonPrimary__add: 'Tambah', + txtRecordInstructions: { + paragraph1: 'Tambahkan rekod TXT ini kepada penyedia DNS anda.', + paragraph2: + 'Kami akan mengesahkan secara automatik sebaik sahaja rekod aktif. Ini biasanya mengambil masa kurang daripada seminit, walaupun mengemas kini rekod TXT sedia ada mungkin mengambil masa sedikit lebih lama.', + }, + txtRecordTable: { + columns: { + domain: 'Domain', + type: 'Jenis', + hostName: 'Hos / Nama', + value: 'Nilai', }, }, - domainTaken: { - title: 'Domain ini ({{domain}}) sudah mempunyai sambungan SSO', - subtitle: 'Hubungi pentadbir aplikasi untuk mendapatkan akses melalui sambungan sedia ada.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/nb-NO.ts b/packages/localizations/src/nb-NO.ts index 0833499c8f4..923e353473b 100644 --- a/packages/localizations/src/nb-NO.ts +++ b/packages/localizations/src/nb-NO.ts @@ -225,29 +225,25 @@ export const nbNO: LocalizationResource = { }, warning: 'Når en leverandør er valgt, kan du ikke endre igjen før konfigurasjonen er ferdig', }, - verifyEmailDomainStep: { - title: 'Verifiser e-postadresse', - subtitle: 'Verifiser e-postadressen du vil aktivere virksomhetstilkoblingen på.', - addEmailAddress: { - formTitle: 'Vi trenger e-posten din', - formSubtitle: 'For å starte trenger vi e-postadressen din', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-postadresse', - }, - emailCode: { - formTitle: 'Verifiser e-postadressen din', - formSubtitle: 'Skriv inn verifiseringskoden som ble sendt til {{identifier}}', - resendButton: 'Mottok du ingen kode? Send på nytt', - verified: { - title: 'Vi mottok e-posten din', - subtitle: 'Du har verifisert e-postadressen din med følgende e-post', - inputLabel: 'Verifisert e-postadresse', + verifyDomainsStep: { + title: 'Verifiser domene', + subtitle: 'Angi og verifiser domenet du vil konfigurere SSO for.', + formFieldLabel__domain: 'Domener', + formFieldInputPlaceholder__domain: 'Skriv inn domenet ditt her, og klikk på legg til for å starte', + formButtonPrimary__add: 'Legg til', + txtRecordInstructions: { + paragraph1: 'Legg til denne TXT-posten hos DNS-leverandøren din.', + paragraph2: + 'Vi verifiserer automatisk når posten er aktiv. Dette tar vanligvis under ett minutt, men oppdatering av en eksisterende TXT-post kan ta litt lengre tid.', + }, + txtRecordTable: { + columns: { + domain: 'Domene', + type: 'Type', + hostName: 'Vert / Navn', + value: 'Verdi', }, }, - domainTaken: { - title: 'Dette domenet ({{domain}}) har allerede en SSO-tilkobling', - subtitle: 'Kontakt programmets administrator for å få tilgang via den eksisterende tilkoblingen.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/nl-BE.ts b/packages/localizations/src/nl-BE.ts index f836c45b447..6966050ce15 100644 --- a/packages/localizations/src/nl-BE.ts +++ b/packages/localizations/src/nl-BE.ts @@ -196,30 +196,25 @@ export const nlBE: LocalizationResource = { }, warning: 'Zodra een provider is geselecteerd, kun je deze niet meer wijzigen totdat de configuratie is voltooid', }, - verifyEmailDomainStep: { - title: 'E-mailadres verifiëren', - subtitle: 'Verifieer het e-mailadres waarop u de enterprise-verbinding wilt inschakelen.', - addEmailAddress: { - formTitle: 'We hebben uw e-mail nodig', - formSubtitle: 'Om te beginnen hebben we uw e-mailadres nodig', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mailadres', - }, - emailCode: { - formTitle: 'Verifieer uw e-mailadres', - formSubtitle: 'Voer de verificatiecode in die is verzonden naar {{identifier}}', - resendButton: 'Geen code ontvangen? Opnieuw verzenden', - verified: { - title: 'We hebben uw e-mail ontvangen', - subtitle: 'U heeft uw e-mailadres geverifieerd met de volgende e-mail', - inputLabel: 'Geverifieerd e-mailadres', + verifyDomainsStep: { + title: 'Domein verifiëren', + subtitle: 'Geef het domein op en verifieer het om SSO te configureren.', + formFieldLabel__domain: 'Domeinen', + formFieldInputPlaceholder__domain: 'Typ hier uw domein en klik op toevoegen om te beginnen', + formButtonPrimary__add: 'Toevoegen', + txtRecordInstructions: { + paragraph1: 'Voeg dit TXT-record toe aan uw DNS-provider.', + paragraph2: + 'We verifiëren automatisch zodra het record actief is. Dit duurt meestal minder dan een minuut, hoewel het bijwerken van een bestaand TXT-record iets langer kan duren.', + }, + txtRecordTable: { + columns: { + domain: 'Domein', + type: 'Type', + hostName: 'Host / Naam', + value: 'Waarde', }, }, - domainTaken: { - title: 'Dit domein ({{domain}}) heeft al een SSO-verbinding', - subtitle: - 'Neem contact op met de beheerder van de applicatie om toegang te krijgen via de bestaande verbinding.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/nl-NL.ts b/packages/localizations/src/nl-NL.ts index 1ce7af52f1f..d20db1842d9 100644 --- a/packages/localizations/src/nl-NL.ts +++ b/packages/localizations/src/nl-NL.ts @@ -196,30 +196,25 @@ export const nlNL: LocalizationResource = { }, warning: 'Zodra een provider is geselecteerd, kun je deze niet meer wijzigen totdat de configuratie is voltooid', }, - verifyEmailDomainStep: { - title: 'E-mailadres verifiëren', - subtitle: 'Verifieer het e-mailadres waarop je de enterprise-verbinding wilt inschakelen.', - addEmailAddress: { - formTitle: 'We hebben je e-mail nodig', - formSubtitle: 'Om te beginnen hebben we je e-mailadres nodig', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mailadres', - }, - emailCode: { - formTitle: 'Verifieer je e-mailadres', - formSubtitle: 'Voer de verificatiecode in die is verzonden naar {{identifier}}', - resendButton: 'Geen code ontvangen? Opnieuw verzenden', - verified: { - title: 'We hebben je e-mail ontvangen', - subtitle: 'Je hebt je e-mailadres geverifieerd met de volgende e-mail', - inputLabel: 'Geverifieerd e-mailadres', + verifyDomainsStep: { + title: 'Domein verifiëren', + subtitle: 'Geef het domein op en verifieer het om SSO te configureren.', + formFieldLabel__domain: 'Domeinen', + formFieldInputPlaceholder__domain: 'Typ hier uw domein en klik op toevoegen om te beginnen', + formButtonPrimary__add: 'Toevoegen', + txtRecordInstructions: { + paragraph1: 'Voeg dit TXT-record toe aan uw DNS-provider.', + paragraph2: + 'We verifiëren automatisch zodra het record actief is. Dit duurt meestal minder dan een minuut, hoewel het bijwerken van een bestaand TXT-record iets langer kan duren.', + }, + txtRecordTable: { + columns: { + domain: 'Domein', + type: 'Type', + hostName: 'Host / Naam', + value: 'Waarde', }, }, - domainTaken: { - title: 'Dit domein ({{domain}}) heeft al een SSO-verbinding', - subtitle: - 'Neem contact op met de beheerder van de applicatie om toegang te krijgen via de bestaande verbinding.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/pl-PL.ts b/packages/localizations/src/pl-PL.ts index ad5cad86f3e..6c811b31115 100644 --- a/packages/localizations/src/pl-PL.ts +++ b/packages/localizations/src/pl-PL.ts @@ -196,29 +196,25 @@ export const plPL: LocalizationResource = { }, warning: 'Po wybraniu dostawcy nie można go ponownie zmienić aż do zakończenia konfiguracji', }, - verifyEmailDomainStep: { - title: 'Zweryfikuj adres e-mail', - subtitle: 'Zweryfikuj adres e-mail, na którym chcesz włączyć połączenie firmowe.', - addEmailAddress: { - formTitle: 'Potrzebujemy Twojego e-maila', - formSubtitle: 'Aby rozpocząć, potrzebujemy Twojego adresu e-mail', - inputPlaceholder: 'name@company.com', - inputLabel: 'Adres e-mail', - }, - emailCode: { - formTitle: 'Zweryfikuj swój adres e-mail', - formSubtitle: 'Wprowadź kod weryfikacyjny wysłany na adres {{identifier}}', - resendButton: 'Nie otrzymałeś kodu? Wyślij ponownie', - verified: { - title: 'Otrzymaliśmy Twój e-mail', - subtitle: 'Zweryfikowałeś swój adres e-mail za pomocą następującego e-maila', - inputLabel: 'Zweryfikowany adres e-mail', + verifyDomainsStep: { + title: 'Zweryfikuj domenę', + subtitle: 'Określ i zweryfikuj domenę, dla której chcesz skonfigurować SSO.', + formFieldLabel__domain: 'Domeny', + formFieldInputPlaceholder__domain: 'Wpisz tutaj swoją domenę i kliknij dodaj, aby rozpocząć', + formButtonPrimary__add: 'Dodaj', + txtRecordInstructions: { + paragraph1: 'Dodaj ten rekord TXT u swojego dostawcy DNS.', + paragraph2: + 'Zweryfikujemy go automatycznie, gdy rekord będzie aktywny. Zwykle trwa to krócej niż minutę, choć aktualizacja istniejącego rekordu TXT może potrwać nieco dłużej.', + }, + txtRecordTable: { + columns: { + domain: 'Domena', + type: 'Typ', + hostName: 'Host / Nazwa', + value: 'Wartość', }, }, - domainTaken: { - title: 'Ta domena ({{domain}}) ma już połączenie SSO', - subtitle: 'Skontaktuj się z administratorem aplikacji, aby uzyskać dostęp przez istniejące połączenie.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/pt-BR.ts b/packages/localizations/src/pt-BR.ts index 10fac051b9e..74b2cedff37 100644 --- a/packages/localizations/src/pt-BR.ts +++ b/packages/localizations/src/pt-BR.ts @@ -203,29 +203,25 @@ export const ptBR: LocalizationResource = { warning: 'Depois que um provedor for selecionado, você não poderá alterá-lo até que a configuração seja concluída', }, - verifyEmailDomainStep: { - title: 'Verificar endereço de e-mail', - subtitle: 'Verifique o endereço de e-mail no qual deseja habilitar a conexão empresarial.', - addEmailAddress: { - formTitle: 'Precisamos do seu e-mail', - formSubtitle: 'Para começar, precisaremos do seu endereço de e-mail', - inputPlaceholder: 'name@company.com', - inputLabel: 'Endereço de e-mail', - }, - emailCode: { - formTitle: 'Verifique seu endereço de e-mail', - formSubtitle: 'Digite o código de verificação enviado para {{identifier}}', - resendButton: 'Não recebeu um código? Reenviar', - verified: { - title: 'Recebemos seu e-mail', - subtitle: 'Você verificou seu endereço de e-mail com o seguinte e-mail', - inputLabel: 'Endereço de e-mail verificado', + verifyDomainsStep: { + title: 'Verificar domínio', + subtitle: 'Especifique e verifique o domínio para configurar o SSO.', + formFieldLabel__domain: 'Domínios', + formFieldInputPlaceholder__domain: 'Digite seu domínio aqui e clique em Adicionar para começar', + formButtonPrimary__add: 'Adicionar', + txtRecordInstructions: { + paragraph1: 'Adicione este registro TXT ao seu provedor de DNS.', + paragraph2: + 'Verificaremos automaticamente assim que o registro estiver ativo. Isso geralmente leva menos de um minuto, embora atualizar um registro TXT existente possa demorar um pouco mais.', + }, + txtRecordTable: { + columns: { + domain: 'Domínio', + type: 'Tipo', + hostName: 'Host / Nome', + value: 'Valor', }, }, - domainTaken: { - title: 'Este domínio ({{domain}}) já possui uma conexão SSO', - subtitle: 'Entre em contato com o administrador da aplicação para obter acesso por meio da conexão existente.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/pt-PT.ts b/packages/localizations/src/pt-PT.ts index 959a9b93ef9..a7877ef48c9 100644 --- a/packages/localizations/src/pt-PT.ts +++ b/packages/localizations/src/pt-PT.ts @@ -204,29 +204,25 @@ export const ptPT: LocalizationResource = { }, warning: 'Depois de um fornecedor ser selecionado não pode ser alterado até que a configuração esteja terminada', }, - verifyEmailDomainStep: { - title: 'Verificar endereço de e-mail', - subtitle: 'Verifique o endereço de e-mail no qual pretende ativar a ligação empresarial.', - addEmailAddress: { - formTitle: 'Precisamos do seu e-mail', - formSubtitle: 'Para começar, precisaremos do seu endereço de e-mail', - inputPlaceholder: 'name@company.com', - inputLabel: 'Endereço de e-mail', - }, - emailCode: { - formTitle: 'Verifique o seu endereço de e-mail', - formSubtitle: 'Introduza o código de verificação enviado para {{identifier}}', - resendButton: 'Não recebeu um código? Reenviar', - verified: { - title: 'Recebemos o seu e-mail', - subtitle: 'Verificou o seu endereço de e-mail com o seguinte e-mail', - inputLabel: 'Endereço de e-mail verificado', + verifyDomainsStep: { + title: 'Verificar domínio', + subtitle: 'Especifique e verifique o domínio para configurar o SSO.', + formFieldLabel__domain: 'Domínios', + formFieldInputPlaceholder__domain: 'Escreva aqui o seu domínio e clique em adicionar para começar', + formButtonPrimary__add: 'Adicionar', + txtRecordInstructions: { + paragraph1: 'Adicione este registo TXT ao seu fornecedor de DNS.', + paragraph2: + 'Verificaremos automaticamente assim que o registo estiver ativo. Normalmente demora menos de um minuto, embora a atualização de um registo TXT existente possa demorar um pouco mais.', + }, + txtRecordTable: { + columns: { + domain: 'Domínio', + type: 'Tipo', + hostName: 'Anfitrião / Nome', + value: 'Valor', }, }, - domainTaken: { - title: 'Este domínio ({{domain}}) já possui uma ligação SSO', - subtitle: 'Contacte o administrador da aplicação para obter acesso através da ligação existente.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ro-RO.ts b/packages/localizations/src/ro-RO.ts index 8ed87bb076a..dba19204a0f 100644 --- a/packages/localizations/src/ro-RO.ts +++ b/packages/localizations/src/ro-RO.ts @@ -202,29 +202,25 @@ export const roRO: LocalizationResource = { }, warning: 'Odată ce un furnizor este selectat, nu îl puteți schimba până când configurația nu este finalizată', }, - verifyEmailDomainStep: { - title: 'Verifică adresa de e-mail', - subtitle: 'Verifică adresa de e-mail pe care dorești să activezi conexiunea enterprise.', - addEmailAddress: { - formTitle: 'Avem nevoie de e-mailul tău', - formSubtitle: 'Pentru a începe, vom avea nevoie de adresa ta de e-mail', - inputPlaceholder: 'name@company.com', - inputLabel: 'Adresă de e-mail', - }, - emailCode: { - formTitle: 'Verifică adresa ta de e-mail', - formSubtitle: 'Introdu codul de verificare trimis la {{identifier}}', - resendButton: 'Nu ai primit un cod? Retrimite', - verified: { - title: 'Am primit e-mailul tău', - subtitle: 'Ai verificat adresa ta de e-mail cu următorul e-mail', - inputLabel: 'Adresă de e-mail verificată', + verifyDomainsStep: { + title: 'Verifică domeniul', + subtitle: 'Specifică și verifică domeniul pentru care configurezi SSO.', + formFieldLabel__domain: 'Domenii', + formFieldInputPlaceholder__domain: 'Scrie aici domeniul tău și fă clic pe adaugă pentru a începe', + formButtonPrimary__add: 'Adaugă', + txtRecordInstructions: { + paragraph1: 'Adaugă această înregistrare TXT la furnizorul tău DNS.', + paragraph2: + 'Vom verifica automat de îndată ce înregistrarea este activă. De obicei durează mai puțin de un minut, deși actualizarea unei înregistrări TXT existente poate dura puțin mai mult.', + }, + txtRecordTable: { + columns: { + domain: 'Domeniu', + type: 'Tip', + hostName: 'Gazdă / Nume', + value: 'Valoare', }, }, - domainTaken: { - title: 'Acest domeniu ({{domain}}) are deja o conexiune SSO', - subtitle: 'Contactează administratorul aplicației pentru a obține acces prin conexiunea existentă.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ru-RU.ts b/packages/localizations/src/ru-RU.ts index 8988d668748..3098e5e51ab 100644 --- a/packages/localizations/src/ru-RU.ts +++ b/packages/localizations/src/ru-RU.ts @@ -196,29 +196,25 @@ export const ruRU: LocalizationResource = { }, warning: 'После выбора поставщика вы не сможете изменить его до завершения настройки', }, - verifyEmailDomainStep: { - title: 'Подтвердить адрес электронной почты', - subtitle: 'Подтвердите адрес электронной почты, для которого вы хотите включить корпоративное подключение.', - addEmailAddress: { - formTitle: 'Нам нужна ваша электронная почта', - formSubtitle: 'Чтобы начать, нам потребуется ваш адрес электронной почты', - inputPlaceholder: 'name@company.com', - inputLabel: 'Адрес электронной почты', - }, - emailCode: { - formTitle: 'Подтвердите ваш адрес электронной почты', - formSubtitle: 'Введите код подтверждения, отправленный на {{identifier}}', - resendButton: 'Не получили код? Отправить повторно', - verified: { - title: 'Мы получили вашу электронную почту', - subtitle: 'Вы подтвердили свой адрес электронной почты с помощью следующего письма', - inputLabel: 'Подтверждённый адрес электронной почты', + verifyDomainsStep: { + title: 'Подтвердить домен', + subtitle: 'Укажите и подтвердите домен для настройки SSO.', + formFieldLabel__domain: 'Домены', + formFieldInputPlaceholder__domain: 'Введите домен здесь и нажмите «Добавить», чтобы начать', + formButtonPrimary__add: 'Добавить', + txtRecordInstructions: { + paragraph1: 'Добавьте эту TXT-запись к вашему DNS-провайдеру.', + paragraph2: + 'Мы выполним проверку автоматически, как только запись станет активной. Обычно это занимает менее минуты, хотя обновление существующей TXT-записи может занять немного больше времени.', + }, + txtRecordTable: { + columns: { + domain: 'Домен', + type: 'Тип', + hostName: 'Хост / Имя', + value: 'Значение', }, }, - domainTaken: { - title: 'Этот домен ({{domain}}) уже имеет SSO-подключение', - subtitle: 'Свяжитесь с администратором приложения, чтобы получить доступ через существующее подключение.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/sk-SK.ts b/packages/localizations/src/sk-SK.ts index a8c250279c4..0b7f70b9c20 100644 --- a/packages/localizations/src/sk-SK.ts +++ b/packages/localizations/src/sk-SK.ts @@ -196,30 +196,25 @@ export const skSK: LocalizationResource = { }, warning: 'Po výbere poskytovateľa ho nemôžete zmeniť, kým sa konfigurácia neukončí', }, - verifyEmailDomainStep: { - title: 'Overiť e-mailovú adresu', - subtitle: 'Overte e-mailovú adresu, na ktorej chcete povoliť podnikové pripojenie.', - addEmailAddress: { - formTitle: 'Potrebujeme váš e-mail', - formSubtitle: 'Na začiatok budeme potrebovať vašu e-mailovú adresu', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-mailová adresa', - }, - emailCode: { - formTitle: 'Overte svoju e-mailovú adresu', - formSubtitle: 'Zadajte overovací kód odoslaný na {{identifier}}', - resendButton: 'Nedostali ste kód? Odoslať znova', - verified: { - title: 'Máme váš e-mail', - subtitle: 'Overili ste svoju e-mailovú adresu nasledujúcim e-mailom', - inputLabel: 'Overená e-mailová adresa', + verifyDomainsStep: { + title: 'Overiť doménu', + subtitle: 'Zadajte a overte doménu, pre ktorú chcete nakonfigurovať SSO.', + formFieldLabel__domain: 'Domény', + formFieldInputPlaceholder__domain: 'Sem zadajte svoju doménu a kliknutím na pridať začnite', + formButtonPrimary__add: 'Pridať', + txtRecordInstructions: { + paragraph1: 'Pridajte tento záznam TXT u svojho poskytovateľa DNS.', + paragraph2: + 'Po sprístupnení záznamu ho overíme automaticky. Zvyčajne to trvá menej než minútu, hoci aktualizácia existujúceho záznamu TXT môže trvať o niečo dlhšie.', + }, + txtRecordTable: { + columns: { + domain: 'Doména', + type: 'Typ', + hostName: 'Hostiteľ / Názov', + value: 'Hodnota', }, }, - domainTaken: { - title: 'Táto doména ({{domain}}) už má SSO pripojenie', - subtitle: - 'Kontaktujte administrátora aplikácie, aby ste získali prístup prostredníctvom existujúceho pripojenia.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/sr-RS.ts b/packages/localizations/src/sr-RS.ts index db6dcdb34b4..bfcc567079f 100644 --- a/packages/localizations/src/sr-RS.ts +++ b/packages/localizations/src/sr-RS.ts @@ -196,29 +196,25 @@ export const srRS: LocalizationResource = { }, warning: 'Kada se provajder izabere, ne možete ga ponovo menjati dok se konfiguracija ne završi', }, - verifyEmailDomainStep: { - title: 'Potvrdi adresu e-pošte', - subtitle: 'Potvrdite adresu e-pošte na kojoj želite da omogućite enterprise konekciju.', - addEmailAddress: { - formTitle: 'Potrebna nam je vaša e-pošta', - formSubtitle: 'Da bismo započeli, biće nam potrebna vaša adresa e-pošte', - inputPlaceholder: 'name@company.com', - inputLabel: 'Adresa e-pošte', - }, - emailCode: { - formTitle: 'Potvrdite svoju adresu e-pošte', - formSubtitle: 'Unesite verifikacioni kod poslat na {{identifier}}', - resendButton: 'Niste primili kod? Pošalji ponovo', - verified: { - title: 'Primili smo vašu e-poštu', - subtitle: 'Potvrdili ste svoju adresu e-pošte sledećom e-poštom', - inputLabel: 'Potvrđena adresa e-pošte', + verifyDomainsStep: { + title: 'Potvrdi domen', + subtitle: 'Navedite i potvrdite domen za koji želite da konfigurišete SSO.', + formFieldLabel__domain: 'Domeni', + formFieldInputPlaceholder__domain: 'Ovde unesite svoj domen i kliknite na dodaj da biste počeli', + formButtonPrimary__add: 'Dodaj', + txtRecordInstructions: { + paragraph1: 'Dodajte ovaj TXT zapis kod svog DNS provajdera.', + paragraph2: + 'Automatski ćemo ga proveriti čim zapis postane aktivan. To obično traje manje od minuta, iako ažuriranje postojećeg TXT zapisa može potrajati malo duže.', + }, + txtRecordTable: { + columns: { + domain: 'Domen', + type: 'Tip', + hostName: 'Host / Naziv', + value: 'Vrednost', }, }, - domainTaken: { - title: 'Ovaj domen ({{domain}}) već ima SSO konekciju', - subtitle: 'Kontaktirajte administratora aplikacije da biste dobili pristup putem postojeće konekcije.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/sv-SE.ts b/packages/localizations/src/sv-SE.ts index 986421ecbc5..08e5384ee7f 100644 --- a/packages/localizations/src/sv-SE.ts +++ b/packages/localizations/src/sv-SE.ts @@ -196,29 +196,25 @@ export const svSE: LocalizationResource = { }, warning: 'När en leverantör har valts kan du inte ändra igen förrän konfigurationen är klar', }, - verifyEmailDomainStep: { - title: 'Verifiera e-postadress', - subtitle: 'Verifiera e-postadressen som du vill aktivera företagsanslutningen för.', - addEmailAddress: { - formTitle: 'Vi behöver din e-post', - formSubtitle: 'För att börja behöver vi din e-postadress', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-postadress', - }, - emailCode: { - formTitle: 'Verifiera din e-postadress', - formSubtitle: 'Ange verifieringskoden som skickats till {{identifier}}', - resendButton: 'Fick du ingen kod? Skicka igen', - verified: { - title: 'Vi har fått din e-post', - subtitle: 'Du har verifierat din e-postadress med följande e-post', - inputLabel: 'Verifierad e-postadress', + verifyDomainsStep: { + title: 'Verifiera domän', + subtitle: 'Ange och verifiera domänen som du vill konfigurera SSO för.', + formFieldLabel__domain: 'Domäner', + formFieldInputPlaceholder__domain: 'Skriv din domän här och klicka på lägg till för att börja', + formButtonPrimary__add: 'Lägg till', + txtRecordInstructions: { + paragraph1: 'Lägg till den här TXT-posten hos din DNS-leverantör.', + paragraph2: + 'Vi verifierar automatiskt när posten är aktiv. Detta tar vanligtvis under en minut, men att uppdatera en befintlig TXT-post kan ta lite längre tid.', + }, + txtRecordTable: { + columns: { + domain: 'Domän', + type: 'Typ', + hostName: 'Värd / Namn', + value: 'Värde', }, }, - domainTaken: { - title: 'Denna domän ({{domain}}) har redan en SSO-anslutning', - subtitle: 'Kontakta applikationens administratör för att få åtkomst via den befintliga anslutningen.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/ta-IN.ts b/packages/localizations/src/ta-IN.ts index f4557c462e4..35a98cc6891 100644 --- a/packages/localizations/src/ta-IN.ts +++ b/packages/localizations/src/ta-IN.ts @@ -204,29 +204,25 @@ export const taIN: LocalizationResource = { }, warning: 'வழங்குநரைத் தேர்ந்தெடுத்த பிறகு, கட்டமைப்பு முடியும் வரை மீண்டும் மாற்ற முடியாது', }, - verifyEmailDomainStep: { - title: 'மின்னஞ்சல் முகவரியை சரிபார்க்கவும்', - subtitle: 'நீங்கள் நிறுவன இணைப்பை இயக்க விரும்பும் மின்னஞ்சல் முகவரியை சரிபார்க்கவும்.', - addEmailAddress: { - formTitle: 'எங்களுக்கு உங்கள் மின்னஞ்சல் தேவை', - formSubtitle: 'தொடங்க உங்கள் மின்னஞ்சல் முகவரி தேவைப்படும்', - inputPlaceholder: 'name@company.com', - inputLabel: 'மின்னஞ்சல் முகவரி', - }, - emailCode: { - formTitle: 'உங்கள் மின்னஞ்சல் முகவரியை சரிபார்க்கவும்', - formSubtitle: '{{identifier}} க்கு அனுப்பப்பட்ட சரிபார்ப்பு குறியீட்டை உள்ளிடவும்', - resendButton: 'குறியீடு கிடைக்கவில்லையா? மீண்டும் அனுப்பு', - verified: { - title: 'உங்கள் மின்னஞ்சல் கிடைத்தது', - subtitle: 'பின்வரும் மின்னஞ்சலுடன் உங்கள் மின்னஞ்சல் முகவரியை சரிபார்த்துள்ளீர்கள்', - inputLabel: 'சரிபார்க்கப்பட்ட மின்னஞ்சல் முகவரி', + verifyDomainsStep: { + title: 'டொமைனை சரிபார்க்கவும்', + subtitle: 'SSO ஐ உள்ளமைக்க டொமைனைக் குறிப்பிட்டு சரிபார்க்கவும்.', + formFieldLabel__domain: 'டொமைன்கள்', + formFieldInputPlaceholder__domain: 'உங்கள் டொமைனை இங்கே தட்டச்சு செய்து, தொடங்க சேர் என்பதைக் கிளிக் செய்யவும்', + formButtonPrimary__add: 'சேர்', + txtRecordInstructions: { + paragraph1: 'இந்த TXT பதிவை உங்கள் DNS வழங்குநரில் சேர்க்கவும்.', + paragraph2: + 'பதிவு செயலில் வந்தவுடன் நாங்கள் தானாகவே சரிபார்ப்போம். இது பொதுவாக ஒரு நிமிடத்திற்குள் முடிந்துவிடும், இருப்பினும் ஏற்கனவே உள்ள TXT பதிவைப் புதுப்பிக்க சற்று அதிக நேரம் ஆகலாம்.', + }, + txtRecordTable: { + columns: { + domain: 'டொமைன்', + type: 'வகை', + hostName: 'ஹோஸ்ட் / பெயர்', + value: 'மதிப்பு', }, }, - domainTaken: { - title: 'இந்த டொமைனுக்கு ({{domain}}) ஏற்கனவே SSO இணைப்பு உள்ளது', - subtitle: 'ஏற்கனவே உள்ள இணைப்பின் வழியாக அணுகலைப் பெற, பயன்பாட்டின் நிர்வாகியைத் தொடர்பு கொள்ளவும்.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/te-IN.ts b/packages/localizations/src/te-IN.ts index b13243dfab6..de47ef06a74 100644 --- a/packages/localizations/src/te-IN.ts +++ b/packages/localizations/src/te-IN.ts @@ -203,29 +203,25 @@ export const teIN: LocalizationResource = { }, warning: 'ఒకసారి ప్రొవైడర్ ఎంచుకున్న తర్వాత, కాన్ఫిగరేషన్ ముగిసే వరకు మీరు మళ్లీ మార్చలేరు', }, - verifyEmailDomainStep: { - title: 'ఇమెయిల్ చిరునామా ధృవీకరించండి', - subtitle: 'మీరు ఎంటర్‌ప్రైజ్ కనెక్షన్‌ను ప్రారంభించాలనుకుంటున్న ఇమెయిల్ చిరునామాను ధృవీకరించండి.', - addEmailAddress: { - formTitle: 'మాకు మీ ఇమెయిల్ అవసరం', - formSubtitle: 'ప్రారంభించడానికి మాకు మీ ఇమెయిల్ చిరునామా అవసరం', - inputPlaceholder: 'name@company.com', - inputLabel: 'ఇమెయిల్ చిరునామా', - }, - emailCode: { - formTitle: 'మీ ఇమెయిల్ చిరునామాను ధృవీకరించండి', - formSubtitle: '{{identifier}} కు పంపిన ధృవీకరణ కోడ్‌ను నమోదు చేయండి', - resendButton: 'కోడ్ అందలేదా? మళ్లీ పంపండి', - verified: { - title: 'మాకు మీ ఇమెయిల్ వచ్చింది', - subtitle: 'మీరు కింది ఇమెయిల్‌తో మీ ఇమెయిల్ చిరునామాను ధృవీకరించారు', - inputLabel: 'ధృవీకరించబడిన ఇమెయిల్ చిరునామా', + verifyDomainsStep: { + title: 'డొమైన్‌ను ధృవీకరించండి', + subtitle: 'SSOని కాన్ఫిగర్ చేయడానికి డొమైన్‌ను పేర్కొని ధృవీకరించండి.', + formFieldLabel__domain: 'డొమైన్‌లు', + formFieldInputPlaceholder__domain: 'మీ డొమైన్‌ను ఇక్కడ టైప్ చేసి, ప్రారంభించడానికి జోడించు క్లిక్ చేయండి', + formButtonPrimary__add: 'జోడించు', + txtRecordInstructions: { + paragraph1: 'ఈ TXT రికార్డ్‌ను మీ DNS ప్రొవైడర్‌కు జోడించండి.', + paragraph2: + 'రికార్డ్ లైవ్ అయిన వెంటనే మేము స్వయంచాలకంగా ధృవీకరిస్తాము. ఇది సాధారణంగా ఒక నిమిషం కంటే తక్కువ సమయం పడుతుంది, అయితే ఇప్పటికే ఉన్న TXT రికార్డ్‌ను అప్‌డేట్ చేయడానికి కొంచెం ఎక్కువ సమయం పట్టవచ్చు.', + }, + txtRecordTable: { + columns: { + domain: 'డొమైన్', + type: 'రకం', + hostName: 'హోస్ట్ / పేరు', + value: 'విలువ', }, }, - domainTaken: { - title: 'ఈ డొమైన్‌కి ({{domain}}) ఇప్పటికే SSO కనెక్షన్ ఉంది', - subtitle: 'ఇప్పటికే ఉన్న కనెక్షన్ ద్వారా యాక్సెస్ పొందడానికి అప్లికేషన్ నిర్వాహకుడిని సంప్రదించండి.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/th-TH.ts b/packages/localizations/src/th-TH.ts index 6a8ca5f679e..43f3de76bcb 100644 --- a/packages/localizations/src/th-TH.ts +++ b/packages/localizations/src/th-TH.ts @@ -200,29 +200,25 @@ export const thTH: LocalizationResource = { }, warning: 'เมื่อเลือกผู้ให้บริการแล้วคุณไม่สามารถเปลี่ยนได้อีกจนกว่าการกำหนดค่าจะเสร็จสิ้น', }, - verifyEmailDomainStep: { - title: 'ยืนยันที่อยู่อีเมล', - subtitle: 'ยืนยันที่อยู่อีเมลที่คุณต้องการเปิดใช้งานการเชื่อมต่อองค์กร', - addEmailAddress: { - formTitle: 'เราต้องการอีเมลของคุณ', - formSubtitle: 'เพื่อเริ่มต้น เราต้องการที่อยู่อีเมลของคุณ', - inputPlaceholder: 'name@company.com', - inputLabel: 'ที่อยู่อีเมล', - }, - emailCode: { - formTitle: 'ยืนยันที่อยู่อีเมลของคุณ', - formSubtitle: 'ป้อนรหัสยืนยันที่ส่งไปยัง {{identifier}}', - resendButton: 'ไม่ได้รับรหัส? ส่งใหม่', - verified: { - title: 'เราได้รับอีเมลของคุณแล้ว', - subtitle: 'คุณได้ยืนยันที่อยู่อีเมลของคุณด้วยอีเมลต่อไปนี้', - inputLabel: 'ที่อยู่อีเมลที่ยืนยันแล้ว', + verifyDomainsStep: { + title: 'ยืนยันโดเมน', + subtitle: 'ระบุและยืนยันโดเมนที่ต้องการกำหนดค่า SSO', + formFieldLabel__domain: 'โดเมน', + formFieldInputPlaceholder__domain: 'พิมพ์โดเมนของคุณที่นี่แล้วคลิกเพิ่มเพื่อเริ่มต้น', + formButtonPrimary__add: 'เพิ่ม', + txtRecordInstructions: { + paragraph1: 'เพิ่มระเบียน TXT นี้ไปยังผู้ให้บริการ DNS ของคุณ', + paragraph2: + 'เราจะยืนยันโดยอัตโนมัติเมื่อระเบียนใช้งานได้แล้ว โดยปกติจะใช้เวลาไม่ถึงหนึ่งนาที แม้ว่าการอัปเดตระเบียน TXT ที่มีอยู่อาจใช้เวลานานขึ้นเล็กน้อย', + }, + txtRecordTable: { + columns: { + domain: 'โดเมน', + type: 'ประเภท', + hostName: 'โฮสต์ / ชื่อ', + value: 'ค่า', }, }, - domainTaken: { - title: 'โดเมนนี้ ({{domain}}) มีการเชื่อมต่อ SSO อยู่แล้ว', - subtitle: 'ติดต่อผู้ดูแลระบบของแอปพลิเคชันเพื่อขอเข้าถึงผ่านการเชื่อมต่อที่มีอยู่', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/tr-TR.ts b/packages/localizations/src/tr-TR.ts index 939380a2176..8a62df0036a 100644 --- a/packages/localizations/src/tr-TR.ts +++ b/packages/localizations/src/tr-TR.ts @@ -196,29 +196,25 @@ export const trTR: LocalizationResource = { }, warning: 'Bir sağlayıcı seçildikten sonra yapılandırma bitene kadar tekrar değiştiremezsiniz', }, - verifyEmailDomainStep: { - title: 'E-posta adresini doğrula', - subtitle: 'Kurumsal bağlantıyı etkinleştirmek istediğiniz e-posta adresini doğrulayın.', - addEmailAddress: { - formTitle: 'E-postanıza ihtiyacımız var', - formSubtitle: 'Başlamak için e-posta adresinize ihtiyacımız olacak', - inputPlaceholder: 'name@company.com', - inputLabel: 'E-posta adresi', - }, - emailCode: { - formTitle: 'E-posta adresinizi doğrulayın', - formSubtitle: '{{identifier}} adresine gönderilen doğrulama kodunu girin', - resendButton: 'Kod almadınız mı? Tekrar gönder', - verified: { - title: 'E-postanızı aldık', - subtitle: 'E-posta adresinizi aşağıdaki e-posta ile doğruladınız', - inputLabel: 'Doğrulanmış e-posta adresi', + verifyDomainsStep: { + title: 'Alan adını doğrula', + subtitle: "SSO'yu yapılandırmak için alan adını belirtin ve doğrulayın.", + formFieldLabel__domain: 'Alan adları', + formFieldInputPlaceholder__domain: 'Alan adınızı buraya yazın ve başlamak için Ekle düğmesine tıklayın', + formButtonPrimary__add: 'Ekle', + txtRecordInstructions: { + paragraph1: 'Bu TXT kaydını DNS sağlayıcınıza ekleyin.', + paragraph2: + 'Kayıt yayına girer girmez otomatik olarak doğrulayacağız. Bu genellikle bir dakikadan kısa sürer, ancak mevcut bir TXT kaydını güncellemek biraz daha uzun sürebilir.', + }, + txtRecordTable: { + columns: { + domain: 'Alan adı', + type: 'Tür', + hostName: 'Ana bilgisayar / Ad', + value: 'Değer', }, }, - domainTaken: { - title: 'Bu alan adı ({{domain}}) zaten bir SSO bağlantısına sahip', - subtitle: 'Mevcut bağlantı üzerinden erişim sağlamak için uygulamanın yöneticisiyle iletişime geçin.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/uk-UA.ts b/packages/localizations/src/uk-UA.ts index 9a036c44183..f0ca4a28bb9 100644 --- a/packages/localizations/src/uk-UA.ts +++ b/packages/localizations/src/uk-UA.ts @@ -196,29 +196,25 @@ export const ukUA: LocalizationResource = { }, warning: 'Після вибору постачальника ви не зможете змінити його, доки не буде завершено налаштування', }, - verifyEmailDomainStep: { - title: 'Підтвердити адресу електронної пошти', - subtitle: "Підтвердьте адресу електронної пошти, на якій ви хочете увімкнути корпоративне з'єднання.", - addEmailAddress: { - formTitle: 'Нам потрібна ваша електронна пошта', - formSubtitle: 'Щоб почати, нам знадобиться ваша адреса електронної пошти', - inputPlaceholder: 'name@company.com', - inputLabel: 'Адреса електронної пошти', - }, - emailCode: { - formTitle: 'Підтвердьте вашу адресу електронної пошти', - formSubtitle: 'Введіть код підтвердження, надісланий на {{identifier}}', - resendButton: 'Не отримали код? Надіслати повторно', - verified: { - title: 'Ми отримали вашу електронну пошту', - subtitle: 'Ви підтвердили адресу електронної пошти за допомогою наступного листа', - inputLabel: 'Підтверджена адреса електронної пошти', + verifyDomainsStep: { + title: 'Підтвердити домен', + subtitle: 'Вкажіть і підтвердьте домен для налаштування SSO.', + formFieldLabel__domain: 'Домени', + formFieldInputPlaceholder__domain: 'Введіть свій домен тут і натисніть «Додати», щоб почати', + formButtonPrimary__add: 'Додати', + txtRecordInstructions: { + paragraph1: 'Додайте цей TXT-запис до вашого DNS-провайдера.', + paragraph2: + 'Ми перевіримо автоматично, щойно запис стане активним. Зазвичай це займає менше хвилини, хоча оновлення наявного TXT-запису може зайняти трохи більше часу.', + }, + txtRecordTable: { + columns: { + domain: 'Домен', + type: 'Тип', + hostName: "Хост / Ім'я", + value: 'Значення', }, }, - domainTaken: { - title: "Цей домен ({{domain}}) уже має з'єднання SSO", - subtitle: "Зверніться до адміністратора програми, щоб отримати доступ через існуюче з'єднання.", - }, }, }, createOrganization: { @@ -539,7 +535,7 @@ export const ukUA: LocalizationResource = { resendButton: "Didn't receive a code? Resend", subtitle: 'The domain {{domainName}} needs to be verified via email.', subtitleVerificationCodeScreen: 'A verification code was sent to {{emailAddress}}. Enter the code to continue.', - title: 'Verify domain', + title: 'Verify domains', }, }, organizationSwitcher: { diff --git a/packages/localizations/src/utils/enUS_v4.ts b/packages/localizations/src/utils/enUS_v4.ts index a2958700f55..549e3aac013 100644 --- a/packages/localizations/src/utils/enUS_v4.ts +++ b/packages/localizations/src/utils/enUS_v4.ts @@ -548,6 +548,7 @@ export const enUS_v4: any = { badge__automaticInvitation: 'Automatic invitations', badge__automaticSuggestion: 'Automatic suggestions', badge__manualInvitation: 'No automatic enrollment', + badge__enterpriseSso: 'Enterprise SSO', start: { headerTitle__members: 'Members', headerTitle__settings: 'Settings', @@ -581,7 +582,7 @@ export const enUS_v4: any = { subtitle: 'Allow users to join the organization automatically or request to join based on a verified email domain.', primaryButton: 'Add domain', - unverifiedDomain_menuAction__verify: 'Verify domain', + unverifiedDomain_menuAction__verify: 'Verify domains', unverifiedDomain_menuAction__remove: 'Delete domain', }, }, @@ -591,7 +592,7 @@ export const enUS_v4: any = { 'Add the domain to verify. Users with email addresses at this domain can join the organization automatically or request to join.', }, verifyDomainPage: { - title: 'Verify domain', + title: 'Verify domains', subtitle: 'The domain {{domainName}} needs to be verified via email.', subtitleVerificationCodeScreen: 'A verification code was sent to {{emailAddress}}. Enter the code to continue.', formTitle: 'Verification code', diff --git a/packages/localizations/src/vi-VN.ts b/packages/localizations/src/vi-VN.ts index 683236376df..fca7ec2d42d 100644 --- a/packages/localizations/src/vi-VN.ts +++ b/packages/localizations/src/vi-VN.ts @@ -202,29 +202,25 @@ export const viVN: LocalizationResource = { }, warning: 'Khi đã chọn nhà cung cấp, bạn không thể thay đổi cho đến khi cấu hình hoàn tất', }, - verifyEmailDomainStep: { - title: 'Xác minh địa chỉ email', - subtitle: 'Xác minh địa chỉ email mà bạn muốn kích hoạt kết nối doanh nghiệp.', - addEmailAddress: { - formTitle: 'Chúng tôi cần email của bạn', - formSubtitle: 'Để bắt đầu, chúng tôi sẽ cần địa chỉ email của bạn', - inputPlaceholder: 'name@company.com', - inputLabel: 'Địa chỉ email', - }, - emailCode: { - formTitle: 'Xác minh địa chỉ email của bạn', - formSubtitle: 'Nhập mã xác minh đã được gửi tới {{identifier}}', - resendButton: 'Không nhận được mã? Gửi lại', - verified: { - title: 'Chúng tôi đã nhận được email của bạn', - subtitle: 'Bạn đã xác minh địa chỉ email của mình với email sau', - inputLabel: 'Địa chỉ email đã xác minh', + verifyDomainsStep: { + title: 'Xác minh tên miền', + subtitle: 'Chỉ định và xác minh tên miền để cấu hình SSO.', + formFieldLabel__domain: 'Tên miền', + formFieldInputPlaceholder__domain: 'Nhập tên miền của bạn vào đây và nhấp vào thêm để bắt đầu', + formButtonPrimary__add: 'Thêm', + txtRecordInstructions: { + paragraph1: 'Thêm bản ghi TXT này vào nhà cung cấp DNS của bạn.', + paragraph2: + 'Chúng tôi sẽ tự động xác minh khi bản ghi hoạt động. Việc này thường mất chưa đến một phút, mặc dù việc cập nhật bản ghi TXT hiện có có thể mất thêm một chút thời gian.', + }, + txtRecordTable: { + columns: { + domain: 'Tên miền', + type: 'Loại', + hostName: 'Máy chủ / Tên', + value: 'Giá trị', }, }, - domainTaken: { - title: 'Tên miền này ({{domain}}) đã có kết nối SSO', - subtitle: 'Liên hệ với quản trị viên của ứng dụng để có quyền truy cập thông qua kết nối hiện có.', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/zh-CN.ts b/packages/localizations/src/zh-CN.ts index ba3034405f5..8d72b5b80f0 100644 --- a/packages/localizations/src/zh-CN.ts +++ b/packages/localizations/src/zh-CN.ts @@ -196,29 +196,24 @@ export const zhCN: LocalizationResource = { }, warning: '选择提供商后,在配置完成之前无法再次更改', }, - verifyEmailDomainStep: { - title: '验证电子邮件地址', - subtitle: '验证您想要启用企业连接的电子邮件地址。', - addEmailAddress: { - formTitle: '我们需要您的电子邮件', - formSubtitle: '为了开始,我们需要您的电子邮件地址', - inputPlaceholder: 'name@company.com', - inputLabel: '电子邮件地址', - }, - emailCode: { - formTitle: '验证您的电子邮件地址', - formSubtitle: '输入发送到 {{identifier}} 的验证码', - resendButton: '没有收到验证码?重新发送', - verified: { - title: '我们已收到您的电子邮件', - subtitle: '您已使用以下电子邮件验证了您的电子邮件地址', - inputLabel: '已验证的电子邮件地址', + verifyDomainsStep: { + title: '验证域名', + subtitle: '指定并验证要配置 SSO 的域名。', + formFieldLabel__domain: '域名', + formFieldInputPlaceholder__domain: '在此输入您的域名,然后点击添加即可开始', + formButtonPrimary__add: '添加', + txtRecordInstructions: { + paragraph1: '将此 TXT 记录添加到您的 DNS 提供商。', + paragraph2: '记录生效后,我们会自动进行验证。这通常不到一分钟,但更新现有的 TXT 记录可能需要稍长时间。', + }, + txtRecordTable: { + columns: { + domain: '域名', + type: '类型', + hostName: '主机 / 名称', + value: '值', }, }, - domainTaken: { - title: '此域名 ({{domain}}) 已存在 SSO 连接', - subtitle: '请联系应用程序管理员,通过现有连接获取访问权限。', - }, }, }, createOrganization: { diff --git a/packages/localizations/src/zh-TW.ts b/packages/localizations/src/zh-TW.ts index 3740bc4fc6f..d719748696e 100644 --- a/packages/localizations/src/zh-TW.ts +++ b/packages/localizations/src/zh-TW.ts @@ -202,29 +202,24 @@ export const zhTW: LocalizationResource = { }, warning: '選擇提供者後,在設定完成之前無法再次變更', }, - verifyEmailDomainStep: { - title: '驗證電子郵件地址', - subtitle: '驗證您想要啟用企業連線的電子郵件地址。', - addEmailAddress: { - formTitle: '我們需要您的電子郵件', - formSubtitle: '為了開始,我們需要您的電子郵件地址', - inputPlaceholder: 'name@company.com', - inputLabel: '電子郵件地址', - }, - emailCode: { - formTitle: '驗證您的電子郵件地址', - formSubtitle: '輸入發送到 {{identifier}} 的驗證碼', - resendButton: '沒有收到驗證碼?重新發送', - verified: { - title: '我們已收到您的電子郵件', - subtitle: '您已使用以下電子郵件驗證了您的電子郵件地址', - inputLabel: '已驗證的電子郵件地址', + verifyDomainsStep: { + title: '驗證網域', + subtitle: '指定並驗證要設定 SSO 的網域。', + formFieldLabel__domain: '網域', + formFieldInputPlaceholder__domain: '在此輸入您的網域,然後點選新增即可開始', + formButtonPrimary__add: '新增', + txtRecordInstructions: { + paragraph1: '將此 TXT 記錄新增至您的 DNS 提供商。', + paragraph2: '記錄生效後,我們會自動進行驗證。這通常不到一分鐘,但更新現有的 TXT 記錄可能需要稍長時間。', + }, + txtRecordTable: { + columns: { + domain: '網域', + type: '類型', + hostName: '主機 / 名稱', + value: '值', }, }, - domainTaken: { - title: '此網域 ({{domain}}) 已存在 SSO 連線', - subtitle: '請聯絡應用程式管理員,透過現有連線取得存取權限。', - }, }, }, createOrganization: { diff --git a/packages/shared/src/react/hooks/index.ts b/packages/shared/src/react/hooks/index.ts index e4ab76177bb..34b1f771e1b 100644 --- a/packages/shared/src/react/hooks/index.ts +++ b/packages/shared/src/react/hooks/index.ts @@ -43,6 +43,8 @@ export type { UseOrganizationEnterpriseConnectionsParams, UseOrganizationEnterpriseConnectionsReturn, } from './useOrganizationEnterpriseConnections'; +export { __internal_useOrganizationDomains } from './useOrganizationDomains'; +export type { UseOrganizationDomainsParams, UseOrganizationDomainsReturn } from './useOrganizationDomains'; export { __internal_useOrganizationEnterpriseConnectionTestRuns } from './useOrganizationEnterpriseConnectionTestRuns'; export type { UseOrganizationEnterpriseConnectionTestRunsParams, diff --git a/packages/shared/src/react/hooks/useOrganizationDomains.shared.ts b/packages/shared/src/react/hooks/useOrganizationDomains.shared.ts new file mode 100644 index 00000000000..83992c840b1 --- /dev/null +++ b/packages/shared/src/react/hooks/useOrganizationDomains.shared.ts @@ -0,0 +1,24 @@ +import { useMemo } from 'react'; + +import { INTERNAL_STABLE_KEYS } from '../stable-keys'; +import { createCacheKeys } from './createCacheKeys'; + +/** + * @internal + */ +export function useOrganizationDomainsCacheKeys(params: { organizationId: string | null; enrollmentMode?: string }) { + const { organizationId, enrollmentMode } = params; + return useMemo(() => { + return createCacheKeys({ + stablePrefix: INTERNAL_STABLE_KEYS.ORGANIZATION_DOMAINS_KEY, + authenticated: Boolean(organizationId), + tracked: { + organizationId: organizationId ?? null, + enrollmentMode: enrollmentMode ?? null, + }, + untracked: { + args: {}, + }, + }); + }, [organizationId, enrollmentMode]); +} diff --git a/packages/shared/src/react/hooks/useOrganizationDomains.tsx b/packages/shared/src/react/hooks/useOrganizationDomains.tsx new file mode 100644 index 00000000000..5d73b525c74 --- /dev/null +++ b/packages/shared/src/react/hooks/useOrganizationDomains.tsx @@ -0,0 +1,132 @@ +import { useCallback } from 'react'; + +import type { GetDomainsParams } from '../../types/organization'; +import type { OrganizationDomainResource, OrganizationEnrollmentMode } from '../../types/organizationDomain'; +import { useClerkInstanceContext } from '../contexts'; +import { defineKeepPreviousDataFn } from '../query/keep-previous-data'; +import { useClerkQueryClient } from '../query/use-clerk-query-client'; +import { useClerkQuery } from '../query/useQuery'; +import { useOrganizationBase } from './base/useOrganizationBase'; +import { useClearQueriesOnSignOut } from './useClearQueriesOnSignOut'; +import { useOrganizationDomainsCacheKeys } from './useOrganizationDomains.shared'; + +export type UseOrganizationDomainsParams = { + enabled?: boolean; + keepPreviousData?: boolean; + /** + * Filter the returned domains by enrollment mode. + */ + enrollmentMode?: OrganizationEnrollmentMode; +}; + +export type UseOrganizationDomainsReturn = { + data: OrganizationDomainResource[] | undefined; + totalCount: number | undefined; + error: Error | null; + isLoading: boolean; + isFetching: boolean; + /** + * Creates a new domain for the active organization, derived from the given name. + */ + createDomain: (name: string) => Promise; + /** + * Issues a fresh TXT challenge for the given domain. The resolved domain's + * `ownershipVerification` carries the `txtRecordName` and `txtRecordValue`. + */ + prepareOwnershipVerification: (domain: OrganizationDomainResource) => Promise; + /** + * Resolves the published TXT record for the given domain to complete ownership verification. + */ + attemptOwnershipVerification: (domain: OrganizationDomainResource) => Promise; + revalidate: () => Promise; +}; + +/** + * Domains for the active organization. + * + * @internal + */ +function useOrganizationDomains(params: UseOrganizationDomainsParams = {}): UseOrganizationDomainsReturn { + const { keepPreviousData = true, enabled = true, enrollmentMode } = params; + const clerk = useClerkInstanceContext(); + const organization = useOrganizationBase(); + const [queryClient] = useClerkQueryClient(); + + const { queryKey, stableKey, authenticated } = useOrganizationDomainsCacheKeys({ + organizationId: organization?.id ?? null, + enrollmentMode, + }); + + const queryEnabled = enabled && clerk.loaded && Boolean(organization); + + useClearQueriesOnSignOut({ + isSignedOut: organization === null, + authenticated, + stableKeys: stableKey, + }); + + const fetchParams: GetDomainsParams | undefined = enrollmentMode ? { enrollmentMode } : undefined; + + const query = useClerkQuery({ + queryKey, + queryFn: () => organization?.getDomains(fetchParams), + enabled: queryEnabled, + placeholderData: defineKeepPreviousDataFn(keepPreviousData), + }); + + const revalidate = useCallback( + () => queryClient.invalidateQueries({ queryKey: [stableKey] }), + [queryClient, stableKey], + ); + + const createDomain = useCallback( + async (name: string) => { + let created = await organization?.createDomain(name); + + // When organization gets created with enterprise_sso enrollment mode + // then promote the new domain and issue a TXT ownership challenge so it can be verified over DNS + if (created && enrollmentMode === 'enterprise_sso') { + created = await created.updateEnrollmentMode({ enrollmentMode: 'enterprise_sso' }); + created = await created.prepareOwnershipVerification(); + } + + await revalidate(); + return created; + }, + [organization, revalidate, enrollmentMode], + ); + + const prepareOwnershipVerification = useCallback( + async (domain: OrganizationDomainResource) => { + const prepared = await domain.prepareOwnershipVerification(); + await revalidate(); + return prepared; + }, + [revalidate], + ); + + const attemptOwnershipVerification = useCallback( + async (domain: OrganizationDomainResource) => { + const attempted = await domain.attemptOwnershipVerification(); + await revalidate(); + return attempted; + }, + [revalidate], + ); + + const response = query.data; + + return { + data: response?.data, + totalCount: response?.total_count, + error: query.error ?? null, + isLoading: query.isLoading, + isFetching: query.isFetching, + createDomain, + prepareOwnershipVerification, + attemptOwnershipVerification, + revalidate, + }; +} + +export { useOrganizationDomains as __internal_useOrganizationDomains }; diff --git a/packages/shared/src/react/stable-keys.ts b/packages/shared/src/react/stable-keys.ts index 628b3640824..eeab3cd627e 100644 --- a/packages/shared/src/react/stable-keys.ts +++ b/packages/shared/src/react/stable-keys.ts @@ -76,6 +76,7 @@ const USER_ENTERPRISE_CONNECTIONS_KEY = 'userEnterpriseConnections'; const ENTERPRISE_CONNECTION_TEST_RUNS_KEY = 'enterpriseConnectionTestRuns'; const ORGANIZATION_ENTERPRISE_CONNECTIONS_KEY = 'organizationEnterpriseConnections'; const ORGANIZATION_ENTERPRISE_CONNECTION_TEST_RUNS_KEY = 'organizationEnterpriseConnectionTestRuns'; +const ORGANIZATION_DOMAINS_KEY = 'organizationDomains'; export const INTERNAL_STABLE_KEYS = { PAYMENT_ATTEMPT_KEY, @@ -85,6 +86,7 @@ export const INTERNAL_STABLE_KEYS = { ENTERPRISE_CONNECTION_TEST_RUNS_KEY, ORGANIZATION_ENTERPRISE_CONNECTIONS_KEY, ORGANIZATION_ENTERPRISE_CONNECTION_TEST_RUNS_KEY, + ORGANIZATION_DOMAINS_KEY, } as const; export type __internal_ResourceCacheStableKey = (typeof INTERNAL_STABLE_KEYS)[keyof typeof INTERNAL_STABLE_KEYS]; diff --git a/packages/shared/src/types/elementIds.ts b/packages/shared/src/types/elementIds.ts index 336279a9a07..94f41a515fc 100644 --- a/packages/shared/src/types/elementIds.ts +++ b/packages/shared/src/types/elementIds.ts @@ -33,7 +33,8 @@ export type FieldId = | 'idpSsoUrl' | 'acsUrl' | 'spEntityId' - | 'web3WalletName'; + | 'web3WalletName' + | 'domain'; export type ProfileSectionId = | 'profile' | 'username' diff --git a/packages/shared/src/types/json.ts b/packages/shared/src/types/json.ts index 4b39d9cf8a3..c0e0e7e950b 100644 --- a/packages/shared/src/types/json.ts +++ b/packages/shared/src/types/json.ts @@ -19,7 +19,11 @@ import type { ClerkAPIErrorJSON } from './errors'; import type { EmailAddressIdentifier, UsernameIdentifier } from './identifiers'; import type { ActClaim } from './jwtv2'; import type { OAuthProvider } from './oauth'; -import type { OrganizationDomainVerificationStatus, OrganizationEnrollmentMode } from './organizationDomain'; +import type { + OrganizationDomainOwnershipVerificationStrategy, + OrganizationDomainVerificationStatus, + OrganizationEnrollmentMode, +} from './organizationDomain'; import type { OrganizationInvitationStatus } from './organizationInvitation'; import type { OrganizationCustomRoleKey, OrganizationPermissionKey } from './organizationMembership'; import type { OrganizationSettingsJSON } from './organizationSettings'; @@ -427,6 +431,27 @@ export interface OrganizationDomainVerificationJSON { strategy: 'email_code'; // only available value for now attempts: number; expires_at: number; + verified_at?: number | null; +} + +export interface OrganizationDomainOwnershipVerificationJSON { + status: OrganizationDomainVerificationStatus; + strategy: OrganizationDomainOwnershipVerificationStrategy; + attempts: number | null; + expire_at: number | null; + verified_at: number | null; + /** + * Present only on ownership verification responses immediately after + * `prepare_ownership_verification`. The fully qualified DNS name the org admin + * must publish the TXT record under. + */ + txt_record_name?: string | null; + /** + * Present only on ownership verification responses immediately after + * `prepare_ownership_verification`. The exact value the org admin must publish + * in the TXT record. + */ + txt_record_value?: string | null; } export interface OrganizationDomainJSON extends ClerkResourceJSON { @@ -435,7 +460,12 @@ export interface OrganizationDomainJSON extends ClerkResourceJSON { name: string; organization_id: string; enrollment_mode: OrganizationEnrollmentMode; + /** + * @deprecated Use `affiliation_verification` instead. + */ verification: OrganizationDomainVerificationJSON | null; + affiliation_verification: OrganizationDomainVerificationJSON | null; + ownership_verification: OrganizationDomainOwnershipVerificationJSON | null; affiliation_email_address: string | null; created_at: number; updated_at: number; diff --git a/packages/shared/src/types/localization.ts b/packages/shared/src/types/localization.ts index ba4e114c4b9..7379763425a 100644 --- a/packages/shared/src/types/localization.ts +++ b/packages/shared/src/types/localization.ts @@ -1027,6 +1027,7 @@ export type __internal_LocalizationResource = { badge__automaticInvitation: LocalizationValue; badge__automaticSuggestion: LocalizationValue; badge__manualInvitation: LocalizationValue; + badge__enterpriseSso: LocalizationValue; start: { headerTitle__members: LocalizationValue; membershipSeatUsageLabel: LocalizationValue<'count' | 'limit'>; @@ -1321,29 +1322,24 @@ export type __internal_LocalizationResource = { }; warning: LocalizationValue; }; - verifyEmailDomainStep: { + verifyDomainsStep: { title: LocalizationValue; subtitle: LocalizationValue; - addEmailAddress: { - formTitle: LocalizationValue; - formSubtitle: LocalizationValue; - inputPlaceholder: LocalizationValue; - inputLabel: LocalizationValue; - }; - emailCode: { - formTitle: LocalizationValue; - formSubtitle: LocalizationValue<'identifier'>; - resendButton: LocalizationValue; - verified: { - title: LocalizationValue; - subtitle: LocalizationValue; - inputLabel: LocalizationValue; + formFieldLabel__domain: LocalizationValue; + formFieldInputPlaceholder__domain: LocalizationValue; + formButtonPrimary__add: LocalizationValue; + txtRecordInstructions: { + paragraph1: LocalizationValue; + paragraph2: LocalizationValue; + }; + txtRecordTable: { + columns: { + domain: LocalizationValue; + type: LocalizationValue; + hostName: LocalizationValue; + value: LocalizationValue; }; }; - domainTaken: { - title: LocalizationValue<'domain'>; - subtitle: LocalizationValue; - }; }; testConfigurationStep: { title: LocalizationValue; diff --git a/packages/shared/src/types/organizationDomain.ts b/packages/shared/src/types/organizationDomain.ts index d9d72746975..5d4a5d92441 100644 --- a/packages/shared/src/types/organizationDomain.ts +++ b/packages/shared/src/types/organizationDomain.ts @@ -28,8 +28,54 @@ type OrganizationDomainVerificationStrategy = 'email_code'; /** @inline */ export type OrganizationDomainVerificationStatus = 'unverified' | 'verified'; +/** + * The strategy used to verify ownership of an Organization's domain. + * + * @inline + */ +export type OrganizationDomainOwnershipVerificationStrategy = 'txt' | 'legacy' | 'manual_override'; + +/** + * Holds the ownership verification details of an Organization's domain, including + * the TXT record an admin must publish to prove ownership. + */ +export interface OrganizationDomainOwnershipVerification { + /** + * The current status of the domain ownership verification. + */ + status: OrganizationDomainVerificationStatus; + /** + * The strategy used to verify ownership of the domain. + */ + strategy: OrganizationDomainOwnershipVerificationStrategy; + /** + * The number of verification attempts that have been made, or `null` if none. + */ + attempts: number | null; + /** + * The date and time when the current verification attempt expires, or `null`. + */ + expiresAt: Date | null; + /** + * The date and time when ownership of the domain was verified, or `null` if it has not been verified. + */ + verifiedAt: Date | null; + /** + * The fully qualified DNS name the org admin must publish the TXT record under. Present only immediately after `prepareOwnershipVerification`. + */ + txtRecordName: string | null; + /** + * The exact value the org admin must publish in the TXT record. Present only immediately after `prepareOwnershipVerification`. + */ + txtRecordValue: string | null; +} + /** @inline */ -export type OrganizationEnrollmentMode = 'manual_invitation' | 'automatic_invitation' | 'automatic_suggestion'; +export type OrganizationEnrollmentMode = + | 'manual_invitation' + | 'automatic_invitation' + | 'automatic_suggestion' + | 'enterprise_sso'; /** * The `OrganizationDomain` object is the model around an Organization's [Verified Domain](https://clerk.com/docs/guides/organizations/add-members/verified-domains). @@ -61,8 +107,18 @@ export interface OrganizationDomainResource extends ClerkResource { enrollmentMode: OrganizationEnrollmentMode; /** * The verification details for the domain, or `null` if the domain has not been verified. + * + * @deprecated Use `affiliationVerification` instead. */ verification: OrganizationDomainVerification | null; + /** + * The affiliation verification details for the domain, or `null` if the domain has not been verified. + */ + affiliationVerification: OrganizationDomainVerification | null; + /** + * The ownership verification details for the domain, or `null` if ownership has not been verified. + */ + ownershipVerification: OrganizationDomainOwnershipVerification | null; /** * The date and time when the domain was created. */ @@ -98,6 +154,18 @@ export interface OrganizationDomainResource extends ClerkResource { * @returns A promise that resolves to the updated `OrganizationDomain` object. */ attemptAffiliationVerification: (params: AttemptAffiliationVerificationParams) => Promise; + /** + * Begins the ownership verification flow by issuing a fresh TXT challenge for the domain. The returned domain's `ownershipVerification` carries the `txtRecordName` and `txtRecordValue` the org admin must publish. + * + * @returns A promise that resolves to the updated `OrganizationDomain` object. + */ + prepareOwnershipVerification: () => Promise; + /** + * Completes the ownership verification flow by resolving the published TXT record for the domain. + * + * @returns A promise that resolves to the updated `OrganizationDomain` object. + */ + attemptOwnershipVerification: () => Promise; /** * Deletes the Verified Domain. * diff --git a/packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx b/packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx index 05aaffd7cc4..5235158ac50 100644 --- a/packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx +++ b/packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx @@ -1,4 +1,4 @@ -import { useSession } from '@clerk/shared/react'; +import { __internal_useOrganizationDomains, useSession } from '@clerk/shared/react'; import type { ConfigureSSOProps } from '@clerk/shared/types'; import React from 'react'; @@ -10,7 +10,7 @@ import { ProfileCard } from '@/elements/ProfileCard'; import { ExclamationTriangle } from '@/icons'; import { Route, Switch } from '@/router'; -import { ConfigureSSOProvider } from './ConfigureSSOContext'; +import { ConfigureSSOProvider, type OrganizationDomainMutations } from './ConfigureSSOContext'; import { ConfigureSSONavbar } from './ConfigureSSONavbar'; import { ConfigureSSOSkeleton } from './ConfigureSSOSkeleton'; import { ConfigureSSOSteps } from './ConfigureSSOSteps'; @@ -46,18 +46,30 @@ const AuthenticatedContent = withCoreUserGuard(() => { export const ConfigureSSOContent = ({ contentRef }: { contentRef: React.RefObject }) => { const { - isLoading, + isLoading: isLoadingEnterpriseConnection, enterpriseConnection, organizationEnterpriseConnection, testRuns, - mutations, - primaryEmailAddress, + enterpriseConnectionMutations, } = useOrganizationEnterpriseConnection(); - // Gate loading one level above the provider so the context never observes a - // loading state. The single test-run source is part of this initial fetch - // when a connection exists at load, so a cold landing on the test step is - // covered by the full skeleton here. + const { + isLoading: isLoadingOrganizationDomains, + data: organizationDomains, + createDomain, + prepareOwnershipVerification, + attemptOwnershipVerification, + revalidate, + } = __internal_useOrganizationDomains({ + enrollmentMode: 'enterprise_sso', + }); + + const organizationDomainMutations = React.useMemo( + () => ({ createDomain, prepareOwnershipVerification, attemptOwnershipVerification, revalidate }), + [createDomain, prepareOwnershipVerification, attemptOwnershipVerification, revalidate], + ); + + const isLoading = isLoadingEnterpriseConnection || isLoadingOrganizationDomains; if (isLoading) { return ; } @@ -69,8 +81,9 @@ export const ConfigureSSOContent = ({ contentRef }: { contentRef: React.RefObjec testRuns={testRuns} enterpriseConnection={enterpriseConnection} contentRef={contentRef} - mutations={mutations} - primaryEmailAddress={primaryEmailAddress} + enterpriseConnectionMutations={enterpriseConnectionMutations} + organizationDomainMutations={organizationDomainMutations} + organizationDomains={organizationDomains} > diff --git a/packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx b/packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx index f40526d138a..023dc72c13e 100644 --- a/packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx +++ b/packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx @@ -1,9 +1,16 @@ -import type { EmailAddressResource, EnterpriseConnectionResource } from '@clerk/shared/types'; +import type { EnterpriseConnectionResource, OrganizationDomainResource } from '@clerk/shared/types'; import React, { type PropsWithChildren } from 'react'; import type { OrganizationEnterpriseConnection } from './domain/organizationEnterpriseConnection'; import type { EnterpriseConnectionMutations, TestRunsView } from './hooks/useOrganizationEnterpriseConnection'; +export interface OrganizationDomainMutations { + createDomain: (name: string) => Promise; + prepareOwnershipVerification: (domain: OrganizationDomainResource) => Promise; + attemptOwnershipVerification: (domain: OrganizationDomainResource) => Promise; + revalidate: () => Promise; +} + /** * Shared state for the ConfigureSSO wizard, persisted across steps. Everything * is sourced from the umbrella `useOrganizationEnterpriseConnection` hook one @@ -14,19 +21,21 @@ export interface ConfigureSSOData { enterpriseConnection: EnterpriseConnectionResource | undefined; /** Ref to the wizard's scrollable content container. */ contentRef: React.RefObject; - mutations: EnterpriseConnectionMutations; + enterpriseConnectionMutations: EnterpriseConnectionMutations; + organizationDomainMutations: OrganizationDomainMutations; organizationEnterpriseConnection: OrganizationEnterpriseConnection; testRuns: TestRunsView; - primaryEmailAddress: EmailAddressResource | undefined; + organizationDomains: OrganizationDomainResource[] | undefined; } interface ConfigureSSOProviderProps { enterpriseConnection: EnterpriseConnectionResource | undefined; organizationEnterpriseConnection: OrganizationEnterpriseConnection; testRuns: TestRunsView; + organizationDomains: OrganizationDomainResource[] | undefined; contentRef: React.RefObject; - mutations: EnterpriseConnectionMutations; - primaryEmailAddress: EmailAddressResource | undefined; + enterpriseConnectionMutations: EnterpriseConnectionMutations; + organizationDomainMutations: OrganizationDomainMutations; } const ConfigureSSOContext = React.createContext(null); @@ -36,9 +45,10 @@ export const ConfigureSSOProvider = ({ enterpriseConnection, organizationEnterpriseConnection, testRuns, + organizationDomains, contentRef, - mutations, - primaryEmailAddress, + enterpriseConnectionMutations, + organizationDomainMutations, children, }: PropsWithChildren): JSX.Element => { const value = React.useMemo( @@ -47,10 +57,19 @@ export const ConfigureSSOProvider = ({ enterpriseConnection, organizationEnterpriseConnection, testRuns, - mutations, - primaryEmailAddress, + organizationDomains, + enterpriseConnectionMutations, + organizationDomainMutations, }), - [contentRef, enterpriseConnection, mutations, organizationEnterpriseConnection, testRuns, primaryEmailAddress], + [ + contentRef, + enterpriseConnectionMutations, + organizationDomainMutations, + organizationEnterpriseConnection, + testRuns, + organizationDomains, + enterpriseConnection, + ], ); return {children}; diff --git a/packages/ui/src/components/ConfigureSSO/ConfigureSSOSteps.tsx b/packages/ui/src/components/ConfigureSSO/ConfigureSSOSteps.tsx index b43e766f14f..67ac84f8c29 100644 --- a/packages/ui/src/components/ConfigureSSO/ConfigureSSOSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/ConfigureSSOSteps.tsx @@ -4,23 +4,29 @@ import { CardStateProvider } from '@/elements/contexts'; import { useConfigureSSO } from './ConfigureSSOContext'; import { ConfigureSSOHeader } from './ConfigureSSOHeader'; -import { type WizardStepConfig } from './elements/Wizard'; -import { Wizard } from './elements/Wizard'; -import { ConfigureStep, ConfirmationStep, SelectProviderStep, TestConfigurationStep, VerifyDomainStep } from './steps'; +import { Wizard, type WizardStepConfig } from './elements/Wizard'; +import { ConfigureStep, ConfirmationStep, SelectProviderStep, TestConfigurationStep, VerifyDomainsStep } from './steps'; /** The ConfigureSSO step graph the entry-guard `` derives its machine from. */ export const ConfigureSSOSteps = (): JSX.Element => { - const { organizationEnterpriseConnection: c } = useConfigureSSO(); + const { organizationEnterpriseConnection: c, organizationDomains } = useConfigureSSO(); + + const allDomainsVerified = + !!organizationDomains?.length && + organizationDomains.every(domain => domain.ownershipVerification?.status === 'verified'); const steps = React.useMemo( () => [ - { id: 'verify-domain', label: 'Verify domain' }, - { id: 'select-provider', guard: () => c.isPrimaryEmailVerified }, - { id: 'configure', label: 'Configure', guard: () => c.isPrimaryEmailVerified && c.hasConnection }, + { id: 'verify-domain', label: 'Verify domains' }, + { + id: 'select-provider', + guard: () => allDomainsVerified, + }, + { id: 'configure', label: 'Configure', guard: () => c.hasConnection }, { id: 'test', label: 'Test', guard: () => c.hasMinimumConfiguration || c.isActive }, { id: 'confirmation', label: 'Confirmation', guard: () => c.hasSuccessfulTestRun || c.isActive }, ], - [c], + [c, allDomainsVerified], ); // Reset does NOT remount the wizard. Deleting the connection breaks the active @@ -43,7 +49,7 @@ export const ConfigureSSOSteps = (): JSX.Element => { - + diff --git a/packages/ui/src/components/ConfigureSSO/ResetConnectionDialog.tsx b/packages/ui/src/components/ConfigureSSO/ResetConnectionDialog.tsx index c35bbf9bb46..eed17c9121c 100644 --- a/packages/ui/src/components/ConfigureSSO/ResetConnectionDialog.tsx +++ b/packages/ui/src/components/ConfigureSSO/ResetConnectionDialog.tsx @@ -46,7 +46,7 @@ export const ResetConnectionDialog = (props: ResetConnectionDialogProps): JSX.El const ResetConnectionDialogContent = withCardStateProvider((props: ResetConnectionDialogProps) => { const { onClose, confirmationValue } = props; const card = useCardState(); - const { enterpriseConnection, mutations } = useConfigureSSO(); + const { enterpriseConnection, enterpriseConnectionMutations } = useConfigureSSO(); const confirmationField = useFormControl('deleteConfirmation', '', { type: 'text', @@ -65,13 +65,7 @@ const ResetConnectionDialogContent = withCardStateProvider((props: ResetConnecti } try { - // Reset is a pure delete — no navigation. Dropping `hasConnection` breaks - // the active step's entry guard, so the wizard self-corrects to the - // furthest-reachable step. The mutation is already reverification-wrapped. - // No `useWizard()` here — that lets this dialog be triggered from ANY - // footer (including the nested SAML configure footers) without binding to - // a nested wizard. - await mutations.deleteConnection(enterpriseConnection.id); + await enterpriseConnectionMutations.deleteConnection(enterpriseConnection.id); onClose(); } catch (err) { handleError(err as Error, [confirmationField], card.setError); diff --git a/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.navigation.test.tsx b/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.navigation.test.tsx index eb6b7a91cf8..a626ac5f1e0 100644 --- a/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.navigation.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.navigation.test.tsx @@ -5,15 +5,6 @@ import { render, waitFor } from '@/test/utils'; import { ConfigureSSO } from '../ConfigureSSO'; -// Integration coverage for the wizard's navigation contract at the rendered- -// component level — the real `ConfigureSSO` → `useOrganizationEnterpriseConnection` -// → `ConfigureSSOSteps` → `` → `useWizardMachine` → step wiring, driven -// only through the connection data the (auto-mocked) FAPI handles return. The -// machine-level behaviours (defer/resolve, clamp) are unit-tested in -// `useWizardMachine.test.tsx`; these tests prove those behaviours hold when the -// connection state changes through the real query/revalidate path that the steps -// actually use, not just a hand-driven config rerender. - const { createFixtures } = bindCreateFixtures('ConfigureSSO'); /** A connection created on the fresh-start path: present but not yet configured. */ @@ -52,7 +43,35 @@ const withAdminOrgUser = (f: any) => { }); }; +const verifiedDomain = { + id: 'dmn_verified', + name: 'clerk.com', + organizationId: 'Org1', + enrollmentMode: 'enterprise_sso', + ownershipVerification: { status: 'verified', strategy: 'txt' }, +} as any; + +const mockVerifiedDomains = (fixtures: any) => + fixtures.clerk.organization?.getDomains.mockResolvedValue({ data: [verifiedDomain], total_count: 1 } as any); + describe('ConfigureSSO wizard navigation (integration)', () => { + it('lands on select-provider when all organization domains are verified (skips verify-domain)', async () => { + const { wrapper, fixtures } = await createFixtures(withAdminOrgUser); + + fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]); + fixtures.clerk.organization?.getEnterpriseConnectionTestRuns.mockResolvedValue({ + data: [], + total_count: 0, + } as any); + mockVerifiedDomains(fixtures); + + const { findByText, queryByText } = render(, { wrapper }); + + await findByText(/select your identity provider/i); + // verify-domain was skipped, so its subtitle never renders + expect(queryByText(/specify and verify the domains/i)).not.toBeInTheDocument(); + }); + // Contract rules 2 + 8: goNext defers when the next guard is not yet satisfied // (the create has fired but the connection has not landed), then completes on // the render after the data lands — here select-provider → configure on the @@ -71,6 +90,7 @@ describe('ConfigureSSO wizard navigation (integration)', () => { data: [], total_count: 0, } as any); + mockVerifiedDomains(fixtures); const { findByText, findByRole, getByRole, userEvent, queryByText } = render(, { wrapper }); @@ -105,6 +125,7 @@ describe('ConfigureSSO wizard navigation (integration)', () => { data: [], total_count: 0, } as any); + mockVerifiedDomains(fixtures); const { findByText, getByRole, getByLabelText, findByRole, userEvent, queryByText } = render(, { wrapper, @@ -138,6 +159,7 @@ describe('ConfigureSSO wizard navigation (integration)', () => { data: [], total_count: 0, } as any); + mockVerifiedDomains(fixtures); const { findByText, findByRole, getByRole, userEvent, queryByText } = render(, { wrapper }); @@ -175,6 +197,7 @@ describe('ConfigureSSO wizard navigation (integration)', () => { data: [], total_count: 0, } as any); + mockVerifiedDomains(fixtures); const { findByText, getByRole, getByLabelText, findByRole, userEvent, queryByText } = render(, { wrapper, diff --git a/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx b/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx index 5ef98d8a20d..90383bef5b8 100644 --- a/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx @@ -7,6 +7,25 @@ import { ConfigureSSO } from '../ConfigureSSO'; const { createFixtures } = bindCreateFixtures('ConfigureSSO'); +const verifiedDomain = { + id: 'dmn_verified', + name: 'clerk.com', + organizationId: 'Org1', + enrollmentMode: 'enterprise_sso', + ownershipVerification: { status: 'verified', strategy: 'txt' }, +} as any; + +const unverifiedDomain = { + id: 'dmn_unverified', + name: 'clerk.com', + organizationId: 'Org1', + enrollmentMode: 'enterprise_sso', + ownershipVerification: { status: 'unverified', strategy: 'txt' }, +} as any; + +const mockOrganizationDomains = (fixtures: any, domains: any[]) => + fixtures.clerk.organization?.getDomains.mockResolvedValue({ data: domains, total_count: domains.length } as any); + describe('ConfigureSSO', () => { describe('within an organization', () => { it('shows a warning if the active organization membership lacks the manage enterprise connections permission', async () => { @@ -41,6 +60,7 @@ describe('ConfigureSSO', () => { }); fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]); + mockOrganizationDomains(fixtures, [verifiedDomain]); const { findByText, queryByText } = render(, { wrapper }); @@ -63,38 +83,37 @@ describe('ConfigureSSO', () => { const { findByText, queryByText } = render(, { wrapper }); - await findByText(/select your identity provider/i); + // No active organization ⇒ no organization domains to verify, so the wizard + // renders its first step (verify-domain). The point of this test is that the + // wizard renders at all without the manage-permission gate. + await findByText(/specify and verify the domains/i); expect(queryByText(/you do not have permission to manage single sign-on/i)).not.toBeInTheDocument(); }); }); describe('state machine mounts on the right step', () => { - it('mounts on verify-domain when the primary email is unverified and there is no connection', async () => { + it('mounts on select-provider when all organization domains are verified and there is no connection', async () => { const { wrapper, fixtures } = await createFixtures(f => { f.withEnterpriseSso({ selfServeSSO: true }); f.withEmailAddress(); f.withOrganizations(); f.withUser({ - // An unverified primary email fails `select-provider`'s guard - // (`isPrimaryEmailVerified`), so the furthest-reachable step is the - // verify-domain entry step rather than select-provider. - email_addresses: [{ email_address: 'test@clerk.com', verification: { status: 'unverified' } }], + email_addresses: ['test@clerk.com'], organization_memberships: [{ name: 'Org1', permissions: ['org:sys_entconns:manage'] }], }); }); fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]); + mockOrganizationDomains(fixtures, [verifiedDomain]); - const { findByRole, queryByText } = render(, { wrapper }); + const { findByText } = render(, { wrapper }); - // The verify-domain step header is the only step rendered; select-provider - // is gated out behind the unverified email. - await findByRole('heading', { name: /verify email address/i }); - expect(queryByText(/select your identity provider/i)).not.toBeInTheDocument(); + // verify-domain is fulfilled by the verified domains, so the machine skips + // it and lands on select-provider — the first non-fulfilled enabled step. + await findByText(/select your identity provider/i); }); - // TODO: replace with a TXT domain-verification case (ORGS-1594) - it('mounts on select-provider with a verified email and no connection', async () => { + it('stays on verify-domain when not all organization domains are verified', async () => { const { wrapper, fixtures } = await createFixtures(f => { f.withEnterpriseSso({ selfServeSSO: true }); f.withEmailAddress(); @@ -106,12 +125,12 @@ describe('ConfigureSSO', () => { }); fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]); + mockOrganizationDomains(fixtures, [unverifiedDomain]); - const { findByText } = render(, { wrapper }); + const { findByText, queryByText } = render(, { wrapper }); - // Verified primary email fulfills verify-domain, so the machine skips it - // and lands on select-provider — the first non-fulfilled enabled step. - await findByText(/select your identity provider/i); + await findByText(/specify and verify the domains/i); + expect(queryByText(/select your identity provider/i)).not.toBeInTheDocument(); }); it('short-circuits to the confirmation step for an active connection', async () => { @@ -143,6 +162,7 @@ describe('ConfigureSSO', () => { }, } as any, ]); + mockOrganizationDomains(fixtures, [verifiedDomain]); fixtures.clerk.organization?.getEnterpriseConnectionTestRuns.mockResolvedValue({ data: [], total_count: 0, @@ -183,6 +203,7 @@ describe('ConfigureSSO', () => { }, } as any, ]); + mockOrganizationDomains(fixtures, [verifiedDomain]); // No successful run yet, so the confirmation guard fails and the // furthest-reachable step is `test`. fixtures.clerk.organization?.getEnterpriseConnectionTestRuns.mockResolvedValue({ @@ -225,6 +246,7 @@ describe('ConfigureSSO', () => { }, } as any, ]); + mockOrganizationDomains(fixtures, [verifiedDomain]); // A successful run satisfies the confirmation guard (`hasSuccessfulTestRun`) // even though the connection is still inactive — the success-filtered probe // returns a row, so the furthest-reachable step clears `test` and lands on diff --git a/packages/ui/src/components/ConfigureSSO/__tests__/ResetConnectionDialog.test.tsx b/packages/ui/src/components/ConfigureSSO/__tests__/ResetConnectionDialog.test.tsx index d16271cd6fe..419ca900c4e 100644 --- a/packages/ui/src/components/ConfigureSSO/__tests__/ResetConnectionDialog.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/__tests__/ResetConnectionDialog.test.tsx @@ -5,12 +5,6 @@ import { bindCreateFixtures } from '@/test/create-fixtures'; import { render, screen, waitFor } from '@/test/utils'; import { CardStateProvider } from '@/ui/elements/contexts'; -// The dialog no longer touches the wizard. On confirm it calls the -// reverification-wrapped `mutations.deleteConnection(id)` directly — a pure -// delete, no navigation — and the wizard self-corrects to the -// furthest-reachable step once the active step's guard breaks. That lets the -// dialog be triggered from ANY footer (including nested SAML configure footers) -// without binding to a nested wizard. const deleteConnection = vi.fn(); const connectionMockState = vi.hoisted(() => ({ @@ -23,7 +17,7 @@ vi.mock('../ConfigureSSOContext', () => ({ contentRef: { current: null }, // The dialog's confirm calls the reverification-wrapped `deleteConnection` // mutation directly. No navigation — the wizard self-corrects. - mutations: { deleteConnection }, + enterpriseConnectionMutations: { deleteConnection }, }), })); diff --git a/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts b/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts index 867c53d5506..1665d8b4b32 100644 --- a/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts +++ b/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts @@ -122,21 +122,6 @@ describe('organizationEnterpriseConnection', () => { }); }); - describe('isPrimaryEmailVerified', () => { - it('undefined email → false', () => { - expect(derive({ primaryEmail: undefined }).isPrimaryEmailVerified).toBe(false); - }); - it('null email → false', () => { - expect(derive({ primaryEmail: null }).isPrimaryEmailVerified).toBe(false); - }); - it('unverified email → false', () => { - expect(derive({ primaryEmail: makeEmail('unverified') }).isPrimaryEmailVerified).toBe(false); - }); - it('verified email → true', () => { - expect(derive({ primaryEmail: makeEmail('verified') }).isPrimaryEmailVerified).toBe(true); - }); - }); - describe('hasSuccessfulTestRun', () => { it('false input → false', () => { expect(derive({ hasSuccessfulTestRun: false }).hasSuccessfulTestRun).toBe(false); @@ -148,8 +133,7 @@ describe('organizationEnterpriseConnection', () => { it('is pure: identical inputs produce a deep-equal entity', () => { const connection = makeConnection({ samlConnection: fullyConfiguredSaml, active: true }); - const primaryEmail = makeEmail('verified'); - const inputs = { connection, primaryEmail, hasSuccessfulTestRun: true } as const; + const inputs = { connection, hasSuccessfulTestRun: true } as const; expect(organizationEnterpriseConnection(inputs)).toEqual(organizationEnterpriseConnection(inputs)); }); @@ -166,7 +150,6 @@ describe('organizationEnterpriseConnection', () => { hasConnection: true, isActive: true, hasMinimumConfiguration: true, - isPrimaryEmailVerified: true, hasSuccessfulTestRun: true, }); }); diff --git a/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts b/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts index b334f08772d..63f4470c5f7 100644 --- a/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts +++ b/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts @@ -23,8 +23,6 @@ export const connectionBackingEmail = (user: UserResource | null | undefined): E export interface OrganizationEnterpriseConnectionInput { /** FAPI currently supports a single connection per organization. */ connection: EnterpriseConnectionResource | null | undefined; - /** The email address whose domain backs the connection. */ - primaryEmail: EmailAddressResource | null | undefined; /** Probed upstream — not a property of the connection resource itself. */ hasSuccessfulTestRun: boolean; } @@ -38,7 +36,6 @@ export interface OrganizationEnterpriseConnection { readonly hasConnection: boolean; readonly isActive: boolean; readonly hasMinimumConfiguration: boolean; - readonly isPrimaryEmailVerified: boolean; readonly hasSuccessfulTestRun: boolean; } @@ -49,13 +46,11 @@ export const isEnterpriseConnectionConfigured = ( export const organizationEnterpriseConnection = ({ connection, - primaryEmail, hasSuccessfulTestRun, }: OrganizationEnterpriseConnectionInput): OrganizationEnterpriseConnection => ({ provider: connection?.provider as ProviderType | undefined, hasConnection: Boolean(connection), isActive: Boolean(connection?.active), hasMinimumConfiguration: isEnterpriseConnectionConfigured(connection), - isPrimaryEmailVerified: primaryEmail?.verification?.status === 'verified', hasSuccessfulTestRun, }); diff --git a/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx b/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx index b01422fefaf..105dd8b8831 100644 --- a/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx @@ -176,7 +176,7 @@ describe('useOrganizationEnterpriseConnection — mutations', () => { it('createConnection derives name + domains from the email domain and forwards them (no organizationId in body)', async () => { const { result } = renderHook(() => useOrganizationEnterpriseConnection()); - await result.current.mutations.createConnection('saml_okta', emailAddress('admin@acme.com')); + await result.current.enterpriseConnectionMutations.createConnection('saml_okta', emailAddress('admin@acme.com')); expect(mutationSpies.create).toHaveBeenCalledTimes(1); expect(mutationSpies.create).toHaveBeenCalledWith({ @@ -189,14 +189,16 @@ describe('useOrganizationEnterpriseConnection — mutations', () => { it('createConnection resolves to undefined without creating when no email is available', async () => { const { result } = renderHook(() => useOrganizationEnterpriseConnection()); - await expect(result.current.mutations.createConnection('saml_okta', undefined)).resolves.toBeUndefined(); + await expect( + result.current.enterpriseConnectionMutations.createConnection('saml_okta', undefined), + ).resolves.toBeUndefined(); expect(mutationSpies.create).not.toHaveBeenCalled(); }); it('setConnectionActive forwards only the active flag to update', async () => { const { result } = renderHook(() => useOrganizationEnterpriseConnection()); - await result.current.mutations.setConnectionActive('ent_1', true); + await result.current.enterpriseConnectionMutations.setConnectionActive('ent_1', true); expect(mutationSpies.update).toHaveBeenCalledWith('ent_1', { active: true }); }); diff --git a/packages/ui/src/components/ConfigureSSO/hooks/useOrganizationEnterpriseConnection.ts b/packages/ui/src/components/ConfigureSSO/hooks/useOrganizationEnterpriseConnection.ts index 12d20b33be8..b22459992fd 100644 --- a/packages/ui/src/components/ConfigureSSO/hooks/useOrganizationEnterpriseConnection.ts +++ b/packages/ui/src/components/ConfigureSSO/hooks/useOrganizationEnterpriseConnection.ts @@ -6,7 +6,6 @@ import { } from '@clerk/shared/react'; import type { DeletedObjectResource, - EmailAddressResource, EnterpriseConnectionResource, EnterpriseConnectionTestRunInitResource, EnterpriseConnectionTestRunResource, @@ -18,10 +17,9 @@ import type { import { useMemo, useRef } from 'react'; import { - connectionBackingEmail, + organizationEnterpriseConnection as buildOrganizationEnterpriseConnection, isEnterpriseConnectionConfigured, type OrganizationEnterpriseConnection, - organizationEnterpriseConnection as buildOrganizationEnterpriseConnection, } from '../domain/organizationEnterpriseConnection'; import type { ProviderType } from '../types'; import { type RefreshTestRunsOptions, useEnterpriseConnectionTestRuns } from './useEnterpriseConnectionTestRuns'; @@ -40,13 +38,9 @@ import { type RefreshTestRunsOptions, useEnterpriseConnectionTestRuns } from './ */ export interface EnterpriseConnectionMutations { /** - * Derives the connection name from the email domain; resolves to `undefined` - * without creating when no primary email is available. + * Creates a new enterprise connection for the active organization. */ - createConnection: ( - provider: ProviderType, - primaryEmailAddress?: EmailAddressResource, - ) => Promise; + createConnection: (provider: ProviderType, domains?: string[]) => Promise; updateConnection: ( id: string, params: UpdateOrganizationEnterpriseConnectionParams, @@ -70,11 +64,9 @@ export interface UseOrganizationEnterpriseConnectionResult { organization: OrganizationResource | null | undefined; /** FAPI currently supports a single connection per organization. */ enterpriseConnection: EnterpriseConnectionResource | undefined; - /** Used to derive the connection name on create. */ - primaryEmailAddress: EmailAddressResource | undefined; /** The domain entity the wizard makes every flow decision from. */ organizationEnterpriseConnection: OrganizationEnterpriseConnection; - mutations: EnterpriseConnectionMutations; + enterpriseConnectionMutations: EnterpriseConnectionMutations; testRuns: TestRunsView; } @@ -164,26 +156,19 @@ export const useOrganizationEnterpriseConnection = (): UseOrganizationEnterprise const { session } = useSession(); const { organization } = useOrganization(); - const primaryEmailAddress = user?.primaryEmailAddress ?? undefined; + const enterpriseConnectionMutations = useMemo(() => { + const createConnection: EnterpriseConnectionMutations['createConnection'] = (provider, domains) => { + const primaryEmailAddress = user?.primaryEmailAddress; + const emailDomain = primaryEmailAddress?.emailAddress.split('@')[1]; - // The connection-domain mutations, defined inline here so the umbrella hook - // owns the single mutation surface. The org-scoped FAPI endpoints have no - // reverification middleware, so these call the underlying handles directly. - const mutations = useMemo(() => { - const createConnection: EnterpriseConnectionMutations['createConnection'] = (provider, primaryEmail) => { - const emailDomain = primaryEmail?.emailAddress.split('@')[1]; + // Connection name will always be defined due to the organization name + // Soon this logic will be moved to the Frontend API + const connectionName = emailDomain ?? organization?.name ?? ''; - if (!emailDomain) { - return Promise.resolve(undefined); - } - - // The organization is inferred from the URL path on the org-scoped - // endpoint, so we don't pass `organizationId` in the body. `domains` is - // required by the create endpoint and is derived from the email domain. return createEnterpriseConnection({ provider, - name: emailDomain, - domains: [emailDomain], + name: connectionName, + domains, }); }; @@ -239,20 +224,15 @@ export const useOrganizationEnterpriseConnection = (): UseOrganizationEnterprise ], ); - // The email whose domain backs the connection — the single domain rule, shared - // with the verify-domain step so the guards and the UI never disagree. - const primaryEmail = connectionBackingEmail(user); - // The single domain entity everything downstream reads decisions from, keyed // on the raw inputs so it is only rebuilt when one of them changes. const organizationEnterpriseConnection = useMemo( () => buildOrganizationEnterpriseConnection({ connection: enterpriseConnection, - primaryEmail, hasSuccessfulTestRun, }), - [enterpriseConnection, primaryEmail, hasSuccessfulTestRun], + [enterpriseConnection, hasSuccessfulTestRun], ); return { @@ -266,9 +246,8 @@ export const useOrganizationEnterpriseConnection = (): UseOrganizationEnterprise // skeleton. isLoading: isLoadingEnterpriseConnections || (hadInitialConnection && isLoadingTestRuns), enterpriseConnection, - primaryEmailAddress, organizationEnterpriseConnection, - mutations, + enterpriseConnectionMutations, testRuns, }; }; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx index 0d697f7f50e..db88083bb80 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx @@ -330,7 +330,7 @@ const SamlCustomIdentityProviderMetadataStep = (): JSX.Element => { const { goNext, goPrev, isFirstStep } = useWizard(); const { enterpriseConnection, - mutations: { updateConnection }, + enterpriseConnectionMutations: { updateConnection }, } = useConfigureSSO(); const samlConnection = enterpriseConnection?.samlConnection; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx index 28fb692f5a3..3fa2c619763 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx @@ -159,7 +159,7 @@ const SamlGoogleIdentityProviderMetadataStep = (): JSX.Element => { const { goNext, goPrev, isFirstStep } = useWizard(); const { enterpriseConnection, - mutations: { updateConnection }, + enterpriseConnectionMutations: { updateConnection }, } = useConfigureSSO(); const samlConnection = enterpriseConnection?.samlConnection; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx index 4c273a0c4c1..1fa9a3e491f 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx @@ -628,7 +628,7 @@ const SamlMicrosoftIdentityProviderMetadataStep = (): JSX.Element => { const { goNext, goPrev, isFirstStep } = useWizard(); const { enterpriseConnection, - mutations: { updateConnection }, + enterpriseConnectionMutations: { updateConnection }, } = useConfigureSSO(); const samlConnection = enterpriseConnection?.samlConnection; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx index 5d9b3b307fa..b1f1d4d8996 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx @@ -517,7 +517,7 @@ const SamlOktaIdentityProviderMetadataStep = (): JSX.Element => { const { goNext, goPrev, isFirstStep } = useWizard(); const { enterpriseConnection, - mutations: { updateConnection }, + enterpriseConnectionMutations: { updateConnection }, } = useConfigureSSO(); const samlConnection = enterpriseConnection?.samlConnection; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/__tests__/SamlConfigureSteps.test.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/__tests__/SamlConfigureSteps.test.tsx index a15f2e8d35e..44b8a909db0 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/__tests__/SamlConfigureSteps.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/__tests__/SamlConfigureSteps.test.tsx @@ -14,7 +14,7 @@ vi.mock('../../../../ConfigureSSOContext', () => ({ enterpriseConnection: undefined, organizationEnterpriseConnection: { hasConnection: false }, provider: 'saml_google', - mutations: {}, + enterpriseConnectionMutations: {}, }), })); diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfirmationStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfirmationStep.tsx index 6e1a29d3fea..59987b8ab51 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfirmationStep.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfirmationStep.tsx @@ -76,7 +76,7 @@ export const ConfirmationStep = (): JSX.Element => { const EnableSsoSection = (): JSX.Element => { const { enterpriseConnection, - mutations: { setConnectionActive }, + enterpriseConnectionMutations: { setConnectionActive }, } = useConfigureSSO(); const card = useCardState(); diff --git a/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx index b9316321e15..0f74e46f6f1 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx @@ -24,13 +24,7 @@ import { Step } from '../elements/Step'; import { useWizard } from '../elements/Wizard'; import type { ProviderType } from '../types'; -/** - * Provider icons whose SVGs are monochromatic and should flip with the - * theme. Mirrors the SUPPORTS_MASK_IMAGE list in `common/ProviderIcon.tsx` - * — keep in sync if either grows. - */ const MONOCHROMATIC_PROVIDER_ICONS: ReadonlySet = new Set(['okta']); - const PROVIDER_GROUPS: ReadonlyArray<{ id: 'saml'; label: LocalizationKey; @@ -62,43 +56,29 @@ const PROVIDER_GROUPS: ReadonlyArray<{ export const SelectProviderStep = (): JSX.Element => { const { - primaryEmailAddress, organizationEnterpriseConnection: c, - mutations: { createConnection }, + enterpriseConnectionMutations: { createConnection }, + organizationDomains, } = useConfigureSSO(); const { goNext } = useWizard(); - // Re-hydrate from context so users returning from another step don't have to - // re-click their provider. const [selected, setSelected] = React.useState(c.provider ?? null); const card = useCardState(); - // Step-LOCAL submit state for the Continue button. `goNext` now DEFERS the - // advance until the next step's guard catches up to the just-resolved create - // (the wizard machine resolves it on the next render), so the shared card - // loading would otherwise leak into the next step as an idle flash. Keeping - // the loading local — and NOT resetting it on success — holds the button in - // its loading state straight through the transition; the deferred advance - // unmounts this step, which ends the loading visually with no idle frame. const [isSubmitting, setIsSubmitting] = React.useState(false); const handleSelect = (next: ProviderType) => { setSelected(next); }; - // On a fresh start the create is unconditional, then `goNext` lands `configure` - // because the resolved create flips `hasConnection`, satisfying its guard. On - // revisit a connection already exists, so we never re-create — `goNext` alone. const handleContinue = async (): Promise => { if (!selected) { return; } - // Connection already created on a prior visit: don't re-create, just - // advance — `configure`'s guard already holds, so this advances immediately - // (no submit, no loading). if (c.hasConnection) { - goNext(); + // TODO ORGS-1607 - Support changing the provider + void goNext(); return; } @@ -106,13 +86,11 @@ export const SelectProviderStep = (): JSX.Element => { setIsSubmitting(true); try { - await createConnection(selected, primaryEmailAddress); - // `goNext` defers; the button STAYS loading and this step unmounts when - // the deferred advance lands. Do NOT reset `isSubmitting` on success. - goNext(); + const domains = organizationDomains?.map(domain => domain.name) ?? []; + await createConnection(selected, domains); + void goNext(); } catch (err) { handleError(err as Error, [], card.setError); - // Re-enable the button ONLY on error — there is no advance to unmount it. setIsSubmitting(false); } }; diff --git a/packages/ui/src/components/ConfigureSSO/steps/TestConfigurationStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/TestConfigurationStep.tsx index cda6522f0b7..4aa243a6dd0 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/TestConfigurationStep.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/TestConfigurationStep.tsx @@ -696,7 +696,7 @@ const OpenTestUrlButton = ({ onTestRunCreated }: OpenTestUrlButtonProps): JSX.El const card = useCardState(); const { enterpriseConnection, - mutations: { createTestRun }, + enterpriseConnectionMutations: { createTestRun }, } = useConfigureSSO(); const [isCreatingTestRun, setIsCreatingTestRun] = useState(false); diff --git a/packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx deleted file mode 100644 index 6ae0e689004..00000000000 --- a/packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx +++ /dev/null @@ -1,486 +0,0 @@ -import { useReverification, useUser } from '@clerk/shared/react'; -import type { EmailAddressResource } from '@clerk/shared/types'; -import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react'; - -import { - Col, - descriptors, - Flow, - Heading, - Icon, - Input, - localizationKeys, - Text, - useLocalizations, -} from '@/customizables'; -import { useFieldOTP } from '@/elements/CodeControl'; -import { useCardState } from '@/elements/contexts'; -import { Form } from '@/elements/Form'; -import { DuotoneAtSymbol } from '@/icons'; -import { handleError } from '@/utils/errorHandler'; - -import { connectionBackingEmail } from '../domain/organizationEnterpriseConnection'; -import { Step } from '../elements/Step'; -import { useWizard, Wizard, type WizardStepConfig } from '../elements/Wizard'; -import { InnerStepCounter } from '../elements/Wizard/InnerStepCounter'; - -/** - * The per-instance refs the two inner sub-step bodies share, carried via context - * so the bodies can stay module-scope (stable identity avoids remounting the - * active step on every parent render). - */ -type VerifyDomainRefs = { - emailAddressRef: React.MutableRefObject; - preExistingEmailIdRef: React.MutableRefObject; -}; - -const VerifyDomainRefsContext = createContext(null); - -const useVerifyDomainRefs = (): VerifyDomainRefs => { - const ctx = useContext(VerifyDomainRefsContext); - if (!ctx) { - throw new Error('useVerifyDomainRefs called outside of VerifyDomainStep'); - } - return ctx; -}; - -const ProvideEmailBody = (): JSX.Element => { - const { emailAddressRef, preExistingEmailIdRef } = useVerifyDomainRefs(); - return ( - - - - ); -}; - -const EnterVerificationCodeBody = (): JSX.Element | null => { - const { emailAddressRef } = useVerifyDomainRefs(); - return ( - - - - ); -}; - -// Body-less inner-step graph; the bodies are rendered declaratively via -// `` below. Each body wraps its content in `Step.Body` and reads -// its per-instance refs from context. -const INNER_STEPS: WizardStepConfig[] = [{ id: 'provide-email' }, { id: 'verify-email-address' }]; - -export const VerifyDomainStep = (): JSX.Element => { - const { user } = useUser(); - const { t } = useLocalizations(); - // The nested provide-email → verify-email bubbles its final `goNext` - // up to this top-level wizard; the already-verified branch advances it - // directly via `completeStep`. - const { goNext: completeStep } = useWizard(); - - const emailToVerify = connectionBackingEmail(user); - const isVerified = emailToVerify?.verification.status === 'verified'; - - const wasVerifiedOnMountRef = useRef(isVerified); - const emailAddressRef = useRef(emailToVerify); - const preExistingEmailIdRef = useRef(emailToVerify?.id); - const initialInnerStepIdRef = useRef<'provide-email' | 'verify-email-address'>( - emailToVerify ? 'verify-email-address' : 'provide-email', - ); - - // Memoized so the provider value identity is stable; declared before the - // early returns to keep the hook order unconditional. - const refs = React.useMemo( - () => ({ emailAddressRef, preExistingEmailIdRef }), - [emailAddressRef, preExistingEmailIdRef], - ); - - if (wasVerifiedOnMountRef.current && emailToVerify?.emailAddress) { - return ( - - - - - - - - - - - - - - - - ); - } - - return ( - - - - - - - - - - - - - - - - - - ); -}; - -const isEmail = (str: string) => /^\S+@\S+\.\S+$/.test(str); - -type ProvideEmailStepProps = { - emailAddressRef: React.MutableRefObject; - preExistingEmailIdRef: React.MutableRefObject; -}; - -const normalizeEmail = (value: string): string => value.trim().toLowerCase(); - -export const ProvideEmailStep = ({ emailAddressRef, preExistingEmailIdRef }: ProvideEmailStepProps): JSX.Element => { - const { goNext, goPrev } = useWizard(); - const { user } = useUser(); - const card = useCardState(); - const { t } = useLocalizations(); - // Pre-fill from the parent's tracked email so navigating back from the verify - // step shows what was previously submitted instead of an empty field. - const [email, setEmail] = useState(() => emailAddressRef.current?.emailAddress ?? ''); - const createEmailAddress = useReverification((value: string) => user?.createEmailAddress({ email: value })); - - const canSubmit = isEmail(email) && !card.isLoading; - const handleSubmit = useCallback(async () => { - if (!canSubmit) { - return; - } - - const current = emailAddressRef.current; - const submittedEmail = email.trim(); - - // Same email address as previously submitted, skip the flow - if (current && normalizeEmail(current.emailAddress) === normalizeEmail(submittedEmail)) { - goNext(); - return; - } - - card.setError(undefined); - card.setLoading(); - - try { - const created = await createEmailAddress(submittedEmail); - const previous = current; - emailAddressRef.current = created ?? undefined; - - // Clean up the previous in-flight address so the user doesn't accumulate orphans on - // their account - if (previous && previous.id !== preExistingEmailIdRef.current && previous.id !== created?.id) { - try { - await previous.destroy(); - } catch { - // A leftover unverified address is preferable to surfacing a cleanup - // error after a successful create. - } - } - - goNext(); - } catch (err) { - handleError(err as Error, [], card.setError); - } finally { - card.setIdle(); - } - }, [canSubmit, email, createEmailAddress, card, goNext, emailAddressRef, preExistingEmailIdRef]); - - return ( - <> - - ({ - display: 'flex', - maxWidth: t.sizes.$66, - textAlign: 'center', - flexDirection: 'column', - alignItems: 'center', - })} - > - ({ - width: t.sizes.$8, - height: t.sizes.$8, - color: t.colors.$neutralAlpha600, - })} - /> - - ({ fontSize: t.fontSizes.$lg, fontWeight: t.fontWeights.$bold })} - localizationKey={localizationKeys('configureSSO.verifyEmailDomainStep.addEmailAddress.formTitle')} - /> - - - - - setEmail(e.currentTarget.value)} - hasError={Boolean(card.error)} - isDisabled={card.isLoading} - // eslint-disable-next-line jsx-a11y/no-autofocus - autoFocus - /> - {card.error ? ( - ({ color: t.colors.$danger500, fontSize: t.fontSizes.$sm, textAlign: 'start' })} - > - {card.error} - - ) : null} - - - - - - goPrev()} - isDisabled - /> - - - - ); -}; - -export const EnterVerificationCodeStep = ({ - emailAddressRef, -}: { - emailAddressRef: React.MutableRefObject; -}): JSX.Element | null => { - const { user } = useUser(); - const card = useCardState(); - const { goNext, goPrev } = useWizard(); - const primaryEmailAddress = user?.primaryEmailAddress; - - const emailToVerify = emailAddressRef.current; - const isVerified = emailToVerify?.verification.status === 'verified'; - const isPrimary = emailToVerify?.id === user?.primaryEmailAddressId; - - const prepareEmailVerification = useReverification(() => - emailAddressRef.current?.prepareVerification({ strategy: 'email_code' }), - ); - const attemptEmailVerification = useReverification((code: string) => - emailAddressRef.current?.attemptVerification({ code }), - ); - const setPrimaryEmailAddress = useReverification((emailAddressId: string) => - user?.update({ primaryEmailAddressId: emailAddressId }), - ); - - const prepare = useCallback( - () => prepareEmailVerification()?.catch(err => handleError(err, [], card.setError)), - [prepareEmailVerification, card], - ); - - const otp = useFieldOTP({ - onCodeEntryFinished: (code, resolve, reject) => { - attemptEmailVerification(code) - .then(() => resolve()) - .catch(reject); - }, - onResendCodeClicked: () => { - void prepare(); - }, - onResolve: async () => { - const target = emailAddressRef.current; - if (target && !isPrimary) { - try { - await setPrimaryEmailAddress(target.id); - } catch (err) { - handleError(err as Error, [], card.setError); - return; - } - } - - void goNext(); - }, - }); - - // Send a code on mount, but only when the target address is not already verified - useEffect(() => { - if (emailToVerify && !isVerified) { - void prepare(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - if (!emailToVerify) { - return null; - } - - return ( - <> - - - - ({ fontSize: t.fontSizes.$sm })} - localizationKey={localizationKeys('configureSSO.verifyEmailDomainStep.emailCode.formTitle')} - /> - - - - - - - - goPrev()} - isDisabled={!!primaryEmailAddress} - /> - goNext()} - isLoading={otp.isLoading || card.isLoading} - isDisabled={!isVerified} - /> - - - ); -}; - -const EmailAlreadyVerified = ({ emailAddress }: { emailAddress: string }): JSX.Element => { - const { t } = useLocalizations(); - - return ( - - ({ - width: t.sizes.$8, - height: t.sizes.$8, - color: t.colors.$neutralAlpha600, - })} - /> - ({ textAlign: 'center', maxWidth: t.sizes.$66 })} - > - ({ fontSize: t.fontSizes.$lg, fontWeight: t.fontWeights.$bold })} - localizationKey={localizationKeys('configureSSO.verifyEmailDomainStep.emailCode.verified.title')} - /> - - - - ({ backgroundColor: t.colors.$neutralAlpha50 })} - /> - - - ); -}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/VerifyDomainsStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/VerifyDomainsStep.tsx new file mode 100644 index 00000000000..be37571c8d2 --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/VerifyDomainsStep.tsx @@ -0,0 +1,330 @@ +import type { OrganizationDomainResource } from '@clerk/shared/types'; +import type React from 'react'; +import { useState } from 'react'; + +import { + Box, + Button, + Col, + descriptors, + Flex, + Flow, + Icon, + localizationKeys, + Spinner, + Table, + Tbody, + Td, + Text, + Th, + Thead, + Tr, + useLocalizations, +} from '@/customizables'; +import { Alert } from '@/elements/Alert'; +import { useCardState } from '@/elements/contexts'; +import { Field } from '@/elements/FieldControl'; +import { Form } from '@/elements/Form'; +import { TagPill } from '@/elements/TagInput'; +import { useClipboard } from '@/hooks'; +import { Checkmark, Clipboard } from '@/icons'; +import { useFormControl } from '@/ui/utils/useFormControl'; +import { handleError } from '@/utils/errorHandler'; + +import { useConfigureSSO } from '../ConfigureSSOContext'; +import { Step } from '../elements/Step'; +import { InnerStepCounter } from '../elements/Wizard/InnerStepCounter'; +import { useWizard } from '../elements/Wizard/WizardContext'; + +export const VerifyDomainsStep = (): JSX.Element => { + const { t } = useLocalizations(); + const { + organizationDomains, + organizationDomainMutations: { createDomain, revalidate }, + } = useConfigureSSO(); + const { goPrev, goNext, isFirstStep, isLastStep } = useWizard(); + const card = useCardState(); + + const handleCreateDomain = async (domain: string) => { + card.setError(undefined); + + try { + await createDomain(domain); + } catch (err: any) { + handleError(err, [], card.setError); + } + }; + + const hasAllDomainsVerified = + organizationDomains?.length && + organizationDomains?.every(domain => domain.ownershipVerification?.status === 'verified'); + + return ( + + + + + + + + ({ gap: t.space.$5 })}> + + + + {!!organizationDomains?.length && ( + ({ gap: t.space.$2, marginTop: t.space.$4 })} + > + {organizationDomains.map(domain => ( + { + // TODO ORGS-1623 - Add dialog for domain deletion confirmation + void domain.delete().then(() => revalidate()); + }} + > + {domain.name} + + ))} + + )} + + {card.error && ( + ({ marginTop: t.space.$4 })} + /> + )} + + + {!!organizationDomains?.length && ( + ({ gap: t.space.$3 })}> + ({ gap: t.space.$4 })}> + + + + + + + )} + + + + + goPrev()} + isDisabled={isFirstStep} + /> + goNext()} + isDisabled={isLastStep || !hasAllDomainsVerified} + /> + + + + ); +}; + +/** + * Matches a bare domain such as `example.com` or `sub.example.co.uk`. + * Each label must start and end with an alphanumeric character and a valid + * TLD of at least two letters is required. Protocols, paths, ports, spaces + * and single-label hostnames are rejected. + */ +const DOMAIN_REGEX = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i; +const isValidDomain = (value: string): boolean => DOMAIN_REGEX.test(value); + +const DomainsField = ({ + onSubmit, + organizationDomains, +}: { + onSubmit: (domain: string) => Promise; + organizationDomains: OrganizationDomainResource[] | undefined; +}): JSX.Element => { + const [isSubmitting, setIsSubmitting] = useState(false); + const domainField = useFormControl('domain', '', { + type: 'text', + label: localizationKeys('configureSSO.verifyDomainsStep.formFieldLabel__domain'), + placeholder: localizationKeys('configureSSO.verifyDomainsStep.formFieldInputPlaceholder__domain'), + }); + + const domain = domainField.value.trim().toLowerCase(); + const canSubmit = isValidDomain(domain) && !organizationDomains?.some(d => d.name === domain) && !isSubmitting; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + if (!canSubmit) { + return; + } + + setIsSubmitting(true); + void onSubmit(domain) + .then(() => domainField.setValue('')) + .finally(() => setIsSubmitting(false)); + }; + + return ( + + + ({ gap: t.space.$2 })} + > + + + + + ({ gap: t.space.$2 })} + > + + + + + + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx b/packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx index f1b02c4766b..bf0ca368f63 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsx @@ -17,30 +17,26 @@ vi.mock('../../elements/Wizard', () => ({ const createEnterpriseConnection = vi.fn(); +const VERIFIED_DOMAINS = [{ name: 'clerk.com' }, { name: 'example.com' }]; +const VERIFIED_DOMAIN_NAMES = VERIFIED_DOMAINS.map(domain => domain.name); + // Provider is sourced from the connection entity // (organizationEnterpriseConnection.provider) rather than a context-level // setProvider. The step uses goNext (not goToStep) after a successful create. const contextState = vi.hoisted(() => ({ provider: undefined as 'saml_okta' | 'saml_custom' | undefined, - primaryEmailAddress: { emailAddress: 'test@clerk.com' } as { emailAddress: string } | undefined, - isPrimaryEmailVerified: true, + organizationDomains: [{ name: 'clerk.com' }, { name: 'example.com' }] as Array<{ name: string }> | undefined, })); vi.mock('../../ConfigureSSOContext', () => ({ useConfigureSSO: () => ({ enterpriseConnection: undefined, - // The step's local `handleContinue` reads the reverification-wrapped create - // mutation off the bundled `mutations` object. - mutations: { + enterpriseConnectionMutations: { createConnection: createEnterpriseConnection, }, - primaryEmailAddress: contextState.primaryEmailAddress, - // Provider is sourced from the connection entity; the step no longer reads a - // context-level setProvider — verify-domain runs first, so the create is - // unconditional. + organizationDomains: contextState.organizationDomains, organizationEnterpriseConnection: { provider: contextState.provider, - isPrimaryEmailVerified: contextState.isPrimaryEmailVerified, }, }), })); @@ -61,8 +57,7 @@ const resetMocks = () => { createEnterpriseConnection.mockReset(); createEnterpriseConnection.mockResolvedValue(undefined); contextState.provider = undefined; - contextState.primaryEmailAddress = { emailAddress: 'test@clerk.com' }; - contextState.isPrimaryEmailVerified = true; + contextState.organizationDomains = [{ name: 'clerk.com' }, { name: 'example.com' }]; }; describe('SelectProviderStep', () => { @@ -166,7 +161,7 @@ describe('SelectProviderStep', () => { expect(goNext).toHaveBeenCalled(); }); - expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_okta', contextState.primaryEmailAddress); + expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_okta', VERIFIED_DOMAIN_NAMES); // The create then the goNext are the tail of the call order. expect(callOrder.slice(-2)).toEqual(['createEnterpriseConnection', 'goNext']); }); @@ -183,7 +178,7 @@ describe('SelectProviderStep', () => { expect(goNext).toHaveBeenCalled(); }); - expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_custom', contextState.primaryEmailAddress); + expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_custom', VERIFIED_DOMAIN_NAMES); }); it('does not advance when failing to create enterprise connection', async () => { @@ -201,7 +196,7 @@ describe('SelectProviderStep', () => { await userEvent.click(screen.getByRole('button', { name: /Continue/i })); await waitFor(() => { - expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_okta', contextState.primaryEmailAddress); + expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_okta', VERIFIED_DOMAIN_NAMES); }); expect(goNext).not.toHaveBeenCalled(); @@ -215,12 +210,8 @@ describe('SelectProviderStep', () => { expect(screen.getByRole('button', { name: /Previous/i })).toBeDisabled(); }); - it('always creates and jumps to configure (verify-domain ran first, so no branch back)', async () => { - // Under the new step order the user reaches select-provider only after - // verify-domain, so the create is unconditional even if the verified fact is - // somehow false — there is no longer a branch back to verify-domain. + it('forwards the verified organization domain names to createConnection', async () => { resetMocks(); - contextState.isPrimaryEmailVerified = false; const { wrapper } = await createFixtures(); const { userEvent } = renderStep(wrapper); @@ -232,6 +223,6 @@ describe('SelectProviderStep', () => { expect(goNext).toHaveBeenCalled(); }); - expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_okta', contextState.primaryEmailAddress); + expect(createEnterpriseConnection).toHaveBeenCalledWith('saml_okta', VERIFIED_DOMAIN_NAMES); }); }); diff --git a/packages/ui/src/components/ConfigureSSO/steps/__tests__/TestConfigurationStep.test.tsx b/packages/ui/src/components/ConfigureSSO/steps/__tests__/TestConfigurationStep.test.tsx index c95fab503f2..5c2d2510b44 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/__tests__/TestConfigurationStep.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/__tests__/TestConfigurationStep.test.tsx @@ -47,7 +47,7 @@ vi.mock('../../ConfigureSSOContext', () => ({ }, }, testRuns: testRunsSource, - mutations: { createTestRun }, + enterpriseConnectionMutations: { createTestRun }, }), })); diff --git a/packages/ui/src/components/ConfigureSSO/steps/index.ts b/packages/ui/src/components/ConfigureSSO/steps/index.ts index f505cad9979..163d59463ed 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/index.ts +++ b/packages/ui/src/components/ConfigureSSO/steps/index.ts @@ -2,4 +2,4 @@ export { ConfigureStep } from './ConfigureStep'; export { ConfirmationStep } from './ConfirmationStep'; export { SelectProviderStep } from './SelectProviderStep'; export { TestConfigurationStep } from './TestConfigurationStep'; -export { VerifyDomainStep } from './VerifyDomainStep'; +export { VerifyDomainsStep } from './VerifyDomainsStep'; diff --git a/packages/ui/src/components/OrganizationProfile/EnrollmentBadge.tsx b/packages/ui/src/components/OrganizationProfile/EnrollmentBadge.tsx index 0b71ba2f1e1..5266a922ece 100644 --- a/packages/ui/src/components/OrganizationProfile/EnrollmentBadge.tsx +++ b/packages/ui/src/components/OrganizationProfile/EnrollmentBadge.tsx @@ -7,6 +7,7 @@ const badgeLabelsMap: Record { diff --git a/packages/ui/src/elements/TagInput.tsx b/packages/ui/src/elements/TagInput.tsx index 17a02456e03..60bd0e9c842 100644 --- a/packages/ui/src/elements/TagInput.tsx +++ b/packages/ui/src/elements/TagInput.tsx @@ -180,7 +180,7 @@ export const TagInput = (props: TagInputProps) => { }; type TagPillProps = React.PropsWithChildren<{ onRemoveClick: React.MouseEventHandler }>; -const TagPill = (props: TagPillProps) => { +export const TagPill = (props: TagPillProps) => { const { onRemoveClick, children, ...rest } = props; return (