mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 11:04:25 +00:00
Merge branch 'main' into new-push
This commit is contained in:
commit
ed04d09db9
@ -12,5 +12,8 @@ If you are using Zitadel, please consider adding yourself as a user with a quick
|
||||
| ----------------------- | -------------------------------------------------------------------- | ----------------------------------------------- |
|
||||
| Zitadel | [@fforootd](https://github.com/fforootd) (and many more) | Zitadel Cloud makes heavy use of of Zitadel ;-) |
|
||||
| Rawkode Academy | [@RawkodeAcademy](https://github.com/RawkodeAcademy) | Rawkode Academy Platform & Zulip use Zitadel for all user and M2M authentication |
|
||||
| devOS: Sanity Edition | [@devOS-Sanity-Edition](https://github.com/devOS-Sanity-Edition) | Uses SSO Auth for every piece of our internal and external infrastructure |
|
||||
| CNAP.tech | [@cnap-tech](https://github.com/cnap-tech) | Using Zitadel for authentication and authorization in cloud-native applications |
|
||||
| Minekube | [@minekube](https://github.com/minekube) | Leveraging Zitadel for secure user authentication in gaming infrastructure |
|
||||
| Organization Name | contact@example.com | Description of how they use Zitadel |
|
||||
| Individual Name | contact@example.com | Description of how they use Zitadel |
|
||||
|
@ -17,6 +17,7 @@ import localeRu from '@angular/common/locales/ru';
|
||||
import localeNl from '@angular/common/locales/nl';
|
||||
import localeSv from '@angular/common/locales/sv';
|
||||
import localeHu from '@angular/common/locales/hu';
|
||||
import localeKo from '@angular/common/locales/ko';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
@ -108,6 +109,8 @@ registerLocaleData(localeSv);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/sv.json'));
|
||||
registerLocaleData(localeHu);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/hu.json'));
|
||||
registerLocaleData(localeKo);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/ko.json'));
|
||||
|
||||
export class WebpackTranslateLoader implements TranslateLoader {
|
||||
getTranslation(lang: string): Observable<any> {
|
||||
|
@ -16,6 +16,7 @@ export const supportedLanguages = [
|
||||
'nl',
|
||||
'sv',
|
||||
'hu',
|
||||
'ko',
|
||||
];
|
||||
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|id|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv|hu/;
|
||||
export const supportedLanguagesRegexp: RegExp = /de|en|es|fr|id|it|ja|pl|zh|bg|pt|mk|cs|ru|nl|sv|hu|ko/;
|
||||
export const fallbackLanguage: string = 'en';
|
||||
|
@ -1383,7 +1383,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1620,7 +1621,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Проверката на имейл е извършена",
|
||||
@ -1720,8 +1722,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Разрешено е конвенционалното влизане с потребителско име и парола.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Входът е разрешен за основните доставчици на самоличност",
|
||||
"ALLOWREGISTER_DESC": "Ако опцията е избрана, в входа се появява допълнителна стъпка за регистрация на потребител.",
|
||||
"FORCEMFA": "Сила MFA",
|
||||
"FORCEMFALOCALONLY": "Принудително MFA за локални потребители",
|
||||
"FORCEMFA": "Наложи MFA за всички потребители",
|
||||
"FORCEMFALOCALONLY": "Наложи MFA само за локално автентифицирани потребители",
|
||||
"FORCEMFALOCALONLY_DESC": "Ако е избрана опцията, локалните удостоверени потребители трябва да конфигурират втори фактор за влизане.",
|
||||
"HIDEPASSWORDRESET_DESC": "Ако опцията е избрана, потребителят не може да нулира паролата си в процеса на влизане.",
|
||||
"HIDELOGINNAMESUFFIX": "Скриване на суфикса на името за влизане",
|
||||
@ -2559,7 +2561,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Добавяне на мениджър",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1621,7 +1622,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Ověření e-mailu dokončeno",
|
||||
@ -1722,8 +1724,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Je povoleno klasické přihlášení s uživatelským jménem a heslem.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Přihlášení je povoleno pro níže uvedené poskytovatele identity.",
|
||||
"ALLOWREGISTER_DESC": "Pokud je možnost vybrána, objeví se při přihlášení další krok pro registraci uživatele.",
|
||||
"FORCEMFA": "Vynutit MFA",
|
||||
"FORCEMFALOCALONLY": "Vynutit MFA pouze pro lokálně ověřené uživatele",
|
||||
"FORCEMFA": "Vynuti MFA pro všechny uživatele",
|
||||
"FORCEMFALOCALONLY": "Vynutit MFA pouze pro místně ověřené uživatele",
|
||||
"FORCEMFALOCALONLY_DESC": "Pokud je možnost vybrána, lokálně ověření uživatelé musí pro přihlášení nastavit druhý faktor.",
|
||||
"HIDEPASSWORDRESET_DESC": "Pokud je možnost vybrána, uživatel nemůže během přihlašovacího procesu resetovat své heslo.",
|
||||
"HIDELOGINNAMESUFFIX": "Skrýt příponu přihlašovacího jména",
|
||||
@ -2572,7 +2574,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Přidat manažera",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1621,7 +1622,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Email Verification erfolgreich",
|
||||
@ -1721,8 +1723,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Der konventionelle Login mit Benutzername und Passwort wird erlaubt.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Der Login wird für die darunter liegenden Identitätsanbieter erlaubt.",
|
||||
"ALLOWREGISTER_DESC": "Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers.",
|
||||
"FORCEMFA": "MFA erzwingen",
|
||||
"FORCEMFALOCALONLY": "MFA für lokale Benutzer erzwingen",
|
||||
"FORCEMFA": "MFA für alle Benutzer erzwingen",
|
||||
"FORCEMFALOCALONLY": "MFA nur für lokal authentifizierte Benutzer erzwingen",
|
||||
"FORCEMFALOCALONLY_DESC": "Ist die Option gewählt, müssen lokal authentifizierte Benutzer einen zweiten Faktor für den Login verwenden.",
|
||||
"HIDEPASSWORDRESET_DESC": "Ist die Option gewählt, ist es nicht möglich im Login das Passwort zurück zusetzen via Passwort vergessen Link.",
|
||||
"HIDELOGINNAMESUFFIX": "Loginname Suffix ausblenden",
|
||||
@ -2563,7 +2565,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Manager hinzufügen",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1621,7 +1622,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Email verification done",
|
||||
@ -1721,8 +1723,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "The conventional login with user name and password is allowed.",
|
||||
"ALLOWEXTERNALIDP_DESC": "The login is allowed for the underlying identity providers",
|
||||
"ALLOWREGISTER_DESC": "If the option is selected, an additional step for registering a user appears in the login.",
|
||||
"FORCEMFA": "Force MFA",
|
||||
"FORCEMFALOCALONLY": "Force MFA for local authenticated users",
|
||||
"FORCEMFA": "Force MFA for all users",
|
||||
"FORCEMFALOCALONLY": "Force MFA for local authenticated users only",
|
||||
"FORCEMFALOCALONLY_DESC": "If the option is selected, local authenticated users have to configure a second factor for login.",
|
||||
"HIDEPASSWORDRESET_DESC": "If the option is selected, the user can't reset his password in the login process.",
|
||||
"HIDELOGINNAMESUFFIX": "Hide Loginname suffix",
|
||||
@ -2588,7 +2590,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Add a Manager",
|
||||
|
@ -1385,7 +1385,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1622,7 +1623,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificación de email realizada",
|
||||
@ -1722,8 +1724,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "El inicio de sesión convencional con nombre de usuario y contraseña está permitido.",
|
||||
"ALLOWEXTERNALIDP_DESC": "El inicio de sesión está permitido para los proveedores de identidad subyacentes",
|
||||
"ALLOWREGISTER_DESC": "Si esta opción es seleccionada, aparece un paso adicional durante el inicio de sesión para registrar un usuario.",
|
||||
"FORCEMFA": "Forzar MFA",
|
||||
"FORCEMFALOCALONLY": "Forzar MFA para usuarios locales",
|
||||
"FORCEMFA": "Forzar MFA para todos los usuarios",
|
||||
"FORCEMFALOCALONLY": "Forzar MFA solo para usuarios autenticados localmente",
|
||||
"FORCEMFALOCALONLY_DESC": "Si esta opción es seleccionada, los usuarios autenticados localmente tendrán que configurar un doble factor para iniciar sesión",
|
||||
"HIDEPASSWORDRESET_DESC": "Si esta opción es seleccionada, el usuario no podrá restablecer su contraseña en el proceso de inicio de sesión.",
|
||||
"HIDELOGINNAMESUFFIX": "Ocultar sufijo del nombre de inicio de sesión",
|
||||
@ -2560,7 +2562,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Añadir un Mánager",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1621,7 +1622,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Vérification de l'e-mail effectuée",
|
||||
@ -1721,8 +1723,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "La connexion classique avec nom d'utilisateur et mot de passe est autorisée.",
|
||||
"ALLOWEXTERNALIDP_DESC": "La connexion est autorisée pour les fournisseurs d'identité sous-jacents",
|
||||
"ALLOWREGISTER_DESC": "Si l'option est sélectionnée, une étape supplémentaire pour l'enregistrement d'un utilisateur apparaît dans la connexion.",
|
||||
"FORCEMFA": "Forcer MFA",
|
||||
"FORCEMFALOCALONLY": "Forcer MFA pour les utilisateurs locaux",
|
||||
"FORCEMFA": "Forcer MFA pour tous les utilisateurs",
|
||||
"FORCEMFALOCALONLY": "Forcer MFA uniquement pour les utilisateurs authentifiés localement",
|
||||
"FORCEMFALOCALONLY_DESC": "Si l'option est sélectionnée, les utilisateurs locaux authentifiés doivent configurer un deuxième facteur pour la connexion.",
|
||||
"HIDEPASSWORDRESET_DESC": "Si l'option est sélectionnée, l'utilisateur ne peut pas réinitialiser son mot de passe lors du processus de connexion.",
|
||||
"HIDELOGINNAMESUFFIX": "Masquer le suffixe du nom de connexion",
|
||||
@ -2564,7 +2566,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Ajouter un responsable",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Holland",
|
||||
"sv": "Svéd",
|
||||
"id": "Indonéz",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1619,7 +1620,8 @@
|
||||
"ru": "Orosz",
|
||||
"nl": "Holland",
|
||||
"sv": "Svéd",
|
||||
"id": "Indonéz"
|
||||
"id": "Indonéz",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-mail ellenőrzés kész",
|
||||
@ -1719,8 +1721,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "A hagyományos bejelentkezés felhasználónévvel és jelszóval engedélyezett.",
|
||||
"ALLOWEXTERNALIDP_DESC": "A bejelentkezés engedélyezett az alapul szolgáló identitásszolgáltatóknál",
|
||||
"ALLOWREGISTER_DESC": "Ha ezt az opciót választod, egy további lépés jelenik meg a bejelentkezés során a felhasználói regisztrációhoz.",
|
||||
"FORCEMFA": "MFA kényszerítése",
|
||||
"FORCEMFALOCALONLY": "Kényszerítsd az MFA-t a helyileg hitelesített felhasználókra",
|
||||
"FORCEMFA": "MFA kikényszerítése minden felhasználó számára",
|
||||
"FORCEMFALOCALONLY": "MFA kikényszerítése csak helyi hitelesített felhasználók számára",
|
||||
"FORCEMFALOCALONLY_DESC": "Ha ezt az opciót választod, a helyileg hitelesített felhasználóknak be kell állítaniuk egy második faktor a bejelentkezéshez.",
|
||||
"HIDEPASSWORDRESET_DESC": "Ha ezt az opciót választod, a felhasználó nem tudja visszaállítani a jelszavát a bejelentkezési folyamat során.",
|
||||
"HIDELOGINNAMESUFFIX": "Bejelentkezési név utótag elrejtése",
|
||||
|
@ -1262,7 +1262,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1486,7 +1487,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verifikasi email selesai",
|
||||
@ -1585,8 +1587,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Login konvensional dengan nama pengguna dan kata sandi diperbolehkan.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Login diperbolehkan untuk penyedia identitas yang mendasarinya",
|
||||
"ALLOWREGISTER_DESC": "Jika opsi ini dipilih, langkah tambahan untuk mendaftarkan pengguna akan muncul di login.",
|
||||
"FORCEMFA": "Paksa MFA",
|
||||
"FORCEMFALOCALONLY": "Paksa MFA untuk pengguna lokal yang diautentikasi",
|
||||
"FORCEMFA": "Memaksa MFA untuk semua pengguna",
|
||||
"FORCEMFALOCALONLY": "Memaksa MFA hanya untuk pengguna yang diautentikasi lokal",
|
||||
"FORCEMFALOCALONLY_DESC": "Jika opsi ini dipilih, pengguna yang diautentikasi lokal harus mengonfigurasi faktor kedua untuk login.",
|
||||
"HIDEPASSWORDRESET_DESC": "Jika opsi ini dipilih, pengguna tidak dapat mengatur ulang kata sandinya dalam proses login.",
|
||||
"HIDELOGINNAMESUFFIX": "Sembunyikan akhiran Nama Login",
|
||||
@ -2272,7 +2274,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Tambahkan Manajer",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1621,7 +1622,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verifica dell'e-mail terminata con successo.",
|
||||
@ -1721,8 +1723,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Autenticazione classica con nome utente e password è permessa.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Il login è permesso per gli IDP sottostanti",
|
||||
"ALLOWREGISTER_DESC": "Se l'opzione è selezionata, nel login apparirà un passo aggiuntivo per la registrazione di un utente.",
|
||||
"FORCEMFA": "Forza MFA",
|
||||
"FORCEMFALOCALONLY": "Forza MFA per gli utenti locali",
|
||||
"FORCEMFA": "Forzare MFA per tutti gli utenti",
|
||||
"FORCEMFALOCALONLY": "Forzare MFA solo per gli utenti autenticati localmente",
|
||||
"FORCEMFALOCALONLY_DESC": "Se l'opzione è selezionata, gli utenti locali autenticati devono configurare un secondo fattore per l'accesso.",
|
||||
"HIDEPASSWORDRESET_DESC": "Se l'opzione è selezionata, l'utente non può resettare la sua password nel interfaccia login.",
|
||||
"HIDELOGINNAMESUFFIX": "Nascondi il suffisso del nome utente",
|
||||
@ -2564,7 +2566,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Aggiungi un manager",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1617,7 +1618,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "メール認証が完了しました",
|
||||
@ -1716,8 +1718,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "ユーザー名とパスワードを使用した従来のログインを許可します。",
|
||||
"ALLOWEXTERNALIDP_DESC": "基礎となるIDプロバイダーにログインを許可します。",
|
||||
"ALLOWREGISTER_DESC": "このオプションが選択されている場合、ユーザーを登録するための追加のステップがログインに表示されます。",
|
||||
"FORCEMFA": "MFAを強制する",
|
||||
"FORCEMFALOCALONLY": "ローカル ユーザーに MFA を強制する",
|
||||
"FORCEMFA": "すべてのユーザーに MFA を強制する",
|
||||
"FORCEMFALOCALONLY": "ローカル認証ユーザーのみに MFA を強制する",
|
||||
"FORCEMFALOCALONLY_DESC": "オプションが選択されている場合、ローカル認証されたユーザーはログインの 2 番目の要素を構成する必要があります。",
|
||||
"HIDEPASSWORDRESET_DESC": "このオプションが選択されている場合、ユーザーはログイン過程ででパスワードをリセットできません。",
|
||||
"HIDELOGINNAMESUFFIX": "ログイン名の接尾辞を非表示にする",
|
||||
@ -2554,7 +2556,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "マネージャーを追加する",
|
||||
|
2671
console/src/assets/i18n/ko.json
Normal file
2671
console/src/assets/i18n/ko.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1385,7 +1385,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1622,7 +1623,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Е-поштата е верифицирана",
|
||||
@ -1722,8 +1724,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Дозволена е конвенционална најава со корисничко име и лозинка.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Најавата е дозволена за поддржуваните IDPs",
|
||||
"ALLOWREGISTER_DESC": "Доколку е избрана опцијата, се прикажува дополнителен чекор за регистрирање на корисник во најавата.",
|
||||
"FORCEMFA": "Задолжителна MFA",
|
||||
"FORCEMFALOCALONLY": "Force MFA за локални корисници",
|
||||
"FORCEMFA": "Наметнете MFA за сите корисници",
|
||||
"FORCEMFALOCALONLY": "Наметнете MFA само за локално автентифицирани корисници",
|
||||
"FORCEMFALOCALONLY_DESC": "Ако е избрана опцијата, локалните автентицирани корисници треба да конфигурираат втор фактор за најавување.",
|
||||
"HIDEPASSWORDRESET_DESC": "Доколку е избрана опцијата, корисникот нема да може да ја ресетира својата лозинка во процесот на најава.",
|
||||
"HIDELOGINNAMESUFFIX": "Сокриј го суфиксот на корисничкото име",
|
||||
@ -2560,7 +2562,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Додај Менаџер",
|
||||
|
@ -1620,7 +1620,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-mail verificatie voltooid",
|
||||
@ -1720,8 +1721,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "De conventionele login met gebruikersnaam en wachtwoord is toegestaan.",
|
||||
"ALLOWEXTERNALIDP_DESC": "De login is toegestaan voor de onderliggende identiteitsproviders",
|
||||
"ALLOWREGISTER_DESC": "Als de optie is geselecteerd, verschijnt er een extra stap voor het registreren van een gebruiker in het login proces.",
|
||||
"FORCEMFA": "Forceer MFA",
|
||||
"FORCEMFALOCALONLY": "Forceer MFA voor lokaal geauthenticeerde gebruikers",
|
||||
"FORCEMFA": "MFA afdwingen voor alle gebruikers",
|
||||
"FORCEMFALOCALONLY": "MFA alleen afdwingen voor lokaal geverifieerde gebruikers",
|
||||
"FORCEMFALOCALONLY_DESC": "Als de optie is geselecteerd, moeten lokaal geauthenticeerde gebruikers een tweede factor configureren voor login.",
|
||||
"HIDEPASSWORDRESET_DESC": "Als de optie is geselecteerd, kan de gebruiker zijn wachtwoord niet resetten in het login proces.",
|
||||
"HIDELOGINNAMESUFFIX": "Verberg Inlognaam achtervoegsel",
|
||||
@ -2580,7 +2581,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Voeg een Manager toe",
|
||||
|
@ -1383,7 +1383,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1620,7 +1621,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Weryfikacja adresu e-mail zakończona",
|
||||
@ -1720,8 +1722,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Zwykłe logowanie za pomocą nazwy użytkownika i hasła jest dozwolone.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Logowanie jest dozwolone dla dostawców tożsamości podstawowych",
|
||||
"ALLOWREGISTER_DESC": "Jeśli ta opcja jest zaznaczona, pojawi się dodatkowy krok rejestracji użytkownika w procesie logowania.",
|
||||
"FORCEMFA": "Wymuś MFA",
|
||||
"FORCEMFALOCALONLY": "Wymuś MFA dla lokalnych użytkowników",
|
||||
"FORCEMFA": "Wymuś MFA dla wszystkich użytkowników",
|
||||
"FORCEMFALOCALONLY": "Wymuś MFA tylko dla lokalnie uwierzytelnionych użytkowników",
|
||||
"FORCEMFALOCALONLY_DESC": "Jeśli ta opcja jest zaznaczona, lokalni uwierzytelnieni użytkownicy muszą skonfigurować drugi czynnik logowania.",
|
||||
"HIDEPASSWORDRESET_DESC": "Jeśli ta opcja jest zaznaczona, użytkownik nie może zresetować swojego hasła w procesie logowania.",
|
||||
"HIDELOGINNAMESUFFIX": "Ukryj sufiks nazwy użytkownika",
|
||||
@ -2563,7 +2565,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Dodaj managera",
|
||||
|
@ -1385,7 +1385,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1622,7 +1623,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "Verificação de email concluída",
|
||||
@ -1722,7 +1724,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "O login convencional com nome de usuário e senha é permitido.",
|
||||
"ALLOWEXTERNALIDP_DESC": "O login é permitido para os provedores de identidade subjacentes",
|
||||
"ALLOWREGISTER_DESC": "Se a opção estiver selecionada, uma etapa adicional para registrar um usuário aparecerá no login.",
|
||||
"FORCEMFA": "Forçar MFA",
|
||||
"FORCEMFA": "Forçar MFA para todos os utilizadores",
|
||||
"FORCEMFALOCALONLY": "Forçar MFA apenas para utilizadores autenticados localmente",
|
||||
"HIDEPASSWORDRESET_DESC": "Se a opção estiver selecionada, o usuário não poderá redefinir sua senha no processo de login.",
|
||||
"HIDELOGINNAMESUFFIX": "Ocultar sufixo do nome de login",
|
||||
"HIDELOGINNAMESUFFIX_DESC": "Oculta o sufixo do nome de login na interface de login",
|
||||
@ -2558,7 +2561,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Adicionar um Gerente",
|
||||
|
@ -1428,7 +1428,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1677,7 +1678,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"LOCALE": "Код языка",
|
||||
"LOCALES": {
|
||||
@ -1792,7 +1794,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Допускается стандартный вход с именем пользователя и паролем.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Вход разрешён для основных поставщиков идентификационных данных.",
|
||||
"ALLOWREGISTER_DESC": "Если данный параметр выбран, при входе в систему появляется дополнительный шаг для регистрации пользователя.",
|
||||
"FORCEMFA": "Принудительная многофакторная аутентификация (MFA)",
|
||||
"FORCEMFA": "Принудительная многофакторная аутентификация для всех пользователей",
|
||||
"FORCEMFALOCALONLY": "Принудительная многофакторная аутентификация только для локально аутентифицированных пользователей",
|
||||
"FORCEMFA_DESC": "Если данный параметр выбран, пользователи должны настроить двухфакторную аутентификацию для входа в систему.",
|
||||
"HIDEPASSWORDRESET": "Скрыть сброс пароля",
|
||||
"HIDEPASSWORDRESET_DESC": "Если данный параметр выбран, пользователь не может сбросить свой пароль в процессе входа в систему.",
|
||||
@ -2670,7 +2673,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Добавить менеджера",
|
||||
|
@ -1388,7 +1388,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1625,7 +1626,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "E-postverifiering klar",
|
||||
@ -1725,8 +1727,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "Den konventionella inloggningen med användarnamn och lösenord är tillåten.",
|
||||
"ALLOWEXTERNALIDP_DESC": "Inloggning är tillåten för de underliggande identitetsleverantörerna",
|
||||
"ALLOWREGISTER_DESC": "Om alternativet är valt visas ett ytterligare steg för att registrera en användare i inloggningen.",
|
||||
"FORCEMFA": "Tvinga MFA",
|
||||
"FORCEMFALOCALONLY": "Tvinga MFA för lokalt autentiserade användare",
|
||||
"FORCEMFA": "Tvinga MFA för alla användare",
|
||||
"FORCEMFALOCALONLY": "Tvinga MFA endast för lokalt autentiserade användare",
|
||||
"FORCEMFALOCALONLY_DESC": "Om alternativet är valt måste lokalt autentiserade användare konfigurera en andra faktor för inloggning.",
|
||||
"HIDEPASSWORDRESET_DESC": "Om alternativet är valt kan användaren inte återställa sitt lösenord i inloggningsprocessen.",
|
||||
"HIDELOGINNAMESUFFIX": "Dölj inloggningsnamn suffix",
|
||||
@ -2592,7 +2594,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "Lägg till en administratör",
|
||||
|
@ -1384,7 +1384,8 @@
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia",
|
||||
"hu": "Magyar"
|
||||
"hu": "Magyar",
|
||||
"ko": "한국어"
|
||||
}
|
||||
},
|
||||
"SMTP": {
|
||||
@ -1620,7 +1621,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"KEYS": {
|
||||
"emailVerificationDoneText": "电子邮件验证完成",
|
||||
@ -1720,8 +1722,8 @@
|
||||
"ALLOWUSERNAMEPASSWORD_DESC": "允许使用用户名和密码进行登录。",
|
||||
"ALLOWEXTERNALIDP_DESC": "允许外部身份提供者进行登录",
|
||||
"ALLOWREGISTER_DESC": "如果选择了该选项,登录中会出现一个用于注册用户的附加步骤。",
|
||||
"FORCEMFA": "强制使用 MFA",
|
||||
"FORCEMFALOCALONLY": "对本地用户强制执行 MFA",
|
||||
"FORCEMFA": "强制所有用户使用 MFA",
|
||||
"FORCEMFALOCALONLY": "仅强制本地认证用户使用 MFA",
|
||||
"FORCEMFALOCALONLY_DESC": "如果选择该选项,本地经过身份验证的用户必须配置第二个登录因素。",
|
||||
"HIDEPASSWORDRESET_DESC": "如果选择该选项,则用户无法在登录过程中重置其密码。",
|
||||
"HIDELOGINNAMESUFFIX": "隐藏登录名后缀",
|
||||
@ -2563,7 +2565,8 @@
|
||||
"ru": "Русский",
|
||||
"nl": "Nederlands",
|
||||
"sv": "Svenska",
|
||||
"id": "Bahasa Indonesia"
|
||||
"id": "Bahasa Indonesia",
|
||||
"ko": "한국어"
|
||||
},
|
||||
"MEMBER": {
|
||||
"ADD": "添加管理者",
|
||||
|
@ -51,6 +51,7 @@ ZITADEL is available in the following languages
|
||||
- Dutch (nl)
|
||||
- Swedish (sv)
|
||||
- Hungarian (hu)
|
||||
- 한국어 (ko)
|
||||
|
||||
A language is displayed based on your agent's language header.
|
||||
If a users language header doesn't match any of the supported or [restricted](#restrict-languages) languages, the instances default language will be used.
|
||||
|
@ -469,12 +469,12 @@ func updateAppleProviderToCommand(req *admin_pb.UpdateAppleProviderRequest) comm
|
||||
}
|
||||
}
|
||||
|
||||
func addSAMLProviderToCommand(req *admin_pb.AddSAMLProviderRequest) command.SAMLProvider {
|
||||
func addSAMLProviderToCommand(req *admin_pb.AddSAMLProviderRequest) *command.SAMLProvider {
|
||||
var nameIDFormat *domain.SAMLNameIDFormat
|
||||
if req.NameIdFormat != nil {
|
||||
nameIDFormat = gu.Ptr(idp_grpc.SAMLNameIDFormatToDomain(req.GetNameIdFormat()))
|
||||
}
|
||||
return command.SAMLProvider{
|
||||
return &command.SAMLProvider{
|
||||
Name: req.Name,
|
||||
Metadata: req.GetMetadataXml(),
|
||||
MetadataURL: req.GetMetadataUrl(),
|
||||
@ -486,12 +486,12 @@ func addSAMLProviderToCommand(req *admin_pb.AddSAMLProviderRequest) command.SAML
|
||||
}
|
||||
}
|
||||
|
||||
func updateSAMLProviderToCommand(req *admin_pb.UpdateSAMLProviderRequest) command.SAMLProvider {
|
||||
func updateSAMLProviderToCommand(req *admin_pb.UpdateSAMLProviderRequest) *command.SAMLProvider {
|
||||
var nameIDFormat *domain.SAMLNameIDFormat
|
||||
if req.NameIdFormat != nil {
|
||||
nameIDFormat = gu.Ptr(idp_grpc.SAMLNameIDFormatToDomain(req.GetNameIdFormat()))
|
||||
}
|
||||
return command.SAMLProvider{
|
||||
return &command.SAMLProvider{
|
||||
Name: req.Name,
|
||||
Metadata: req.GetMetadataXml(),
|
||||
MetadataURL: req.GetMetadataUrl(),
|
||||
|
@ -462,12 +462,12 @@ func updateAppleProviderToCommand(req *mgmt_pb.UpdateAppleProviderRequest) comma
|
||||
}
|
||||
}
|
||||
|
||||
func addSAMLProviderToCommand(req *mgmt_pb.AddSAMLProviderRequest) command.SAMLProvider {
|
||||
func addSAMLProviderToCommand(req *mgmt_pb.AddSAMLProviderRequest) *command.SAMLProvider {
|
||||
var nameIDFormat *domain.SAMLNameIDFormat
|
||||
if req.NameIdFormat != nil {
|
||||
nameIDFormat = gu.Ptr(idp_grpc.SAMLNameIDFormatToDomain(req.GetNameIdFormat()))
|
||||
}
|
||||
return command.SAMLProvider{
|
||||
return &command.SAMLProvider{
|
||||
Name: req.Name,
|
||||
Metadata: req.GetMetadataXml(),
|
||||
MetadataURL: req.GetMetadataUrl(),
|
||||
@ -479,12 +479,12 @@ func addSAMLProviderToCommand(req *mgmt_pb.AddSAMLProviderRequest) command.SAMLP
|
||||
}
|
||||
}
|
||||
|
||||
func updateSAMLProviderToCommand(req *mgmt_pb.UpdateSAMLProviderRequest) command.SAMLProvider {
|
||||
func updateSAMLProviderToCommand(req *mgmt_pb.UpdateSAMLProviderRequest) *command.SAMLProvider {
|
||||
var nameIDFormat *domain.SAMLNameIDFormat
|
||||
if req.NameIdFormat != nil {
|
||||
nameIDFormat = gu.Ptr(idp_grpc.SAMLNameIDFormatToDomain(req.GetNameIdFormat()))
|
||||
}
|
||||
return command.SAMLProvider{
|
||||
return &command.SAMLProvider{
|
||||
Name: req.Name,
|
||||
Metadata: req.GetMetadataXml(),
|
||||
MetadataURL: req.GetMetadataUrl(),
|
||||
|
@ -58,7 +58,7 @@ func TestServer_AddOTPSMS(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user mismatch",
|
||||
name: "no permission",
|
||||
args: args{
|
||||
ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser),
|
||||
req: &user.AddOTPSMSRequest{
|
||||
@ -127,14 +127,24 @@ func TestServer_RemoveOTPSMS(t *testing.T) {
|
||||
|
||||
userVerified := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userVerified.GetUserId())
|
||||
_, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId())
|
||||
userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified)
|
||||
_, err := Instance.Client.UserV2.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{
|
||||
_, err := Instance.Client.UserV2.VerifyPhone(CTX, &user.VerifyPhoneRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
VerificationCode: userVerified.GetPhoneCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Instance.Client.UserV2.AddOTPSMS(userVerifiedCtx, &user.AddOTPSMSRequest{UserId: userVerified.GetUserId()})
|
||||
_, err = Instance.Client.UserV2.AddOTPSMS(CTX, &user.AddOTPSMSRequest{UserId: userVerified.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
userSelf := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userSelf.GetUserId())
|
||||
_, sessionTokenSelf, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userSelf.GetUserId())
|
||||
userSelfCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenSelf)
|
||||
_, err = Instance.Client.UserV2.VerifyPhone(CTX, &user.VerifyPhoneRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
VerificationCode: userSelf.GetPhoneCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Instance.Client.UserV2.AddOTPSMS(CTX, &user.AddOTPSMSRequest{UserId: userSelf.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
type args struct {
|
||||
@ -157,10 +167,24 @@ func TestServer_RemoveOTPSMS(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success, self",
|
||||
args: args{
|
||||
ctx: userSelfCtx,
|
||||
req: &user.RemoveOTPSMSRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
},
|
||||
},
|
||||
want: &user.RemoveOTPSMSResponse{
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success",
|
||||
args: args{
|
||||
ctx: userVerifiedCtx,
|
||||
ctx: CTX,
|
||||
req: &user.RemoveOTPSMSRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
},
|
||||
@ -230,7 +254,7 @@ func TestServer_AddOTPEmail(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user mismatch",
|
||||
name: "no permission",
|
||||
args: args{
|
||||
ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser),
|
||||
req: &user.AddOTPEmailRequest{
|
||||
@ -301,14 +325,24 @@ func TestServer_RemoveOTPEmail(t *testing.T) {
|
||||
|
||||
userVerified := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userVerified.GetUserId())
|
||||
_, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId())
|
||||
userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified)
|
||||
_, err := Instance.Client.UserV2.VerifyEmail(userVerifiedCtx, &user.VerifyEmailRequest{
|
||||
_, err := Instance.Client.UserV2.VerifyEmail(CTX, &user.VerifyEmailRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
VerificationCode: userVerified.GetEmailCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Instance.Client.UserV2.AddOTPEmail(userVerifiedCtx, &user.AddOTPEmailRequest{UserId: userVerified.GetUserId()})
|
||||
_, err = Instance.Client.UserV2.AddOTPEmail(CTX, &user.AddOTPEmailRequest{UserId: userVerified.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
userSelf := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userSelf.GetUserId())
|
||||
_, sessionTokenSelf, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userSelf.GetUserId())
|
||||
userSelfCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenSelf)
|
||||
_, err = Instance.Client.UserV2.VerifyEmail(CTX, &user.VerifyEmailRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
VerificationCode: userSelf.GetEmailCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Instance.Client.UserV2.AddOTPEmail(CTX, &user.AddOTPEmailRequest{UserId: userSelf.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
type args struct {
|
||||
@ -331,10 +365,25 @@ func TestServer_RemoveOTPEmail(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success, self",
|
||||
args: args{
|
||||
ctx: userSelfCtx,
|
||||
req: &user.RemoveOTPEmailRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
},
|
||||
},
|
||||
want: &user.RemoveOTPEmailResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success",
|
||||
args: args{
|
||||
ctx: userVerifiedCtx,
|
||||
ctx: CTX,
|
||||
req: &user.RemoveOTPEmailRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
},
|
||||
|
@ -93,15 +93,30 @@ func TestServer_RegisterPasskey(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user mismatch",
|
||||
name: "user no permission",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
ctx: UserCTX,
|
||||
req: &user.RegisterPasskeyRequest{
|
||||
UserId: userID,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user permission",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RegisterPasskeyRequest{
|
||||
UserId: userID,
|
||||
},
|
||||
},
|
||||
want: &user.RegisterPasskeyResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Instance.DefaultOrg.Id,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user setting its own passkey",
|
||||
args: args{
|
||||
|
@ -13,7 +13,6 @@ func (s *Server) AddOTPSMS(ctx context.Context, req *user.AddOTPSMSRequest) (*us
|
||||
return nil, err
|
||||
}
|
||||
return &user.AddOTPSMSResponse{Details: object.DomainToDetailsPb(details)}, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) RemoveOTPSMS(ctx context.Context, req *user.RemoveOTPSMSRequest) (*user.RemoveOTPSMSResponse, error) {
|
||||
|
@ -58,7 +58,7 @@ func TestServer_AddOTPSMS(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user mismatch",
|
||||
name: "no permission",
|
||||
args: args{
|
||||
ctx: integration.WithAuthorizationToken(context.Background(), sessionTokenOtherUser),
|
||||
req: &user.AddOTPSMSRequest{
|
||||
@ -127,14 +127,24 @@ func TestServer_RemoveOTPSMS(t *testing.T) {
|
||||
|
||||
userVerified := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userVerified.GetUserId())
|
||||
_, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId())
|
||||
userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified)
|
||||
_, err := Client.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{
|
||||
_, err := Instance.Client.UserV2beta.VerifyPhone(CTX, &user.VerifyPhoneRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
VerificationCode: userVerified.GetPhoneCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Client.AddOTPSMS(userVerifiedCtx, &user.AddOTPSMSRequest{UserId: userVerified.GetUserId()})
|
||||
_, err = Instance.Client.UserV2beta.AddOTPSMS(CTX, &user.AddOTPSMSRequest{UserId: userVerified.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
userSelf := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userSelf.GetUserId())
|
||||
_, sessionTokenSelf, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userSelf.GetUserId())
|
||||
userSelfCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenSelf)
|
||||
_, err = Instance.Client.UserV2beta.VerifyPhone(CTX, &user.VerifyPhoneRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
VerificationCode: userSelf.GetPhoneCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Instance.Client.UserV2beta.AddOTPSMS(CTX, &user.AddOTPSMSRequest{UserId: userSelf.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
type args struct {
|
||||
@ -157,10 +167,24 @@ func TestServer_RemoveOTPSMS(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success, self",
|
||||
args: args{
|
||||
ctx: userSelfCtx,
|
||||
req: &user.RemoveOTPSMSRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
},
|
||||
},
|
||||
want: &user.RemoveOTPSMSResponse{
|
||||
Details: &object.Details{
|
||||
ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success",
|
||||
args: args{
|
||||
ctx: userVerifiedCtx,
|
||||
ctx: CTX,
|
||||
req: &user.RemoveOTPSMSRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
},
|
||||
@ -301,14 +325,24 @@ func TestServer_RemoveOTPEmail(t *testing.T) {
|
||||
|
||||
userVerified := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userVerified.GetUserId())
|
||||
_, sessionTokenVerified, _, _ := Instance.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId())
|
||||
userVerifiedCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenVerified)
|
||||
_, err := Client.VerifyEmail(userVerifiedCtx, &user.VerifyEmailRequest{
|
||||
_, err := Client.VerifyEmail(CTX, &user.VerifyEmailRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
VerificationCode: userVerified.GetEmailCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Client.AddOTPEmail(userVerifiedCtx, &user.AddOTPEmailRequest{UserId: userVerified.GetUserId()})
|
||||
_, err = Client.AddOTPEmail(CTX, &user.AddOTPEmailRequest{UserId: userVerified.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
userSelf := Instance.CreateHumanUser(CTX)
|
||||
Instance.RegisterUserPasskey(CTX, userSelf.GetUserId())
|
||||
_, sessionTokenSelf, _, _ := Instance.CreateVerifiedWebAuthNSession(t, IamCTX, userSelf.GetUserId())
|
||||
userSelfCtx := integration.WithAuthorizationToken(context.Background(), sessionTokenSelf)
|
||||
_, err = Client.VerifyEmail(CTX, &user.VerifyEmailRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
VerificationCode: userSelf.GetEmailCode(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = Client.AddOTPEmail(CTX, &user.AddOTPEmailRequest{UserId: userSelf.GetUserId()})
|
||||
require.NoError(t, err)
|
||||
|
||||
type args struct {
|
||||
@ -331,10 +365,25 @@ func TestServer_RemoveOTPEmail(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success, self",
|
||||
args: args{
|
||||
ctx: userSelfCtx,
|
||||
req: &user.RemoveOTPEmailRequest{
|
||||
UserId: userSelf.GetUserId(),
|
||||
},
|
||||
},
|
||||
want: &user.RemoveOTPEmailResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Instance.DefaultOrg.Details.ResourceOwner,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success",
|
||||
args: args{
|
||||
ctx: userVerifiedCtx,
|
||||
ctx: CTX,
|
||||
req: &user.RemoveOTPEmailRequest{
|
||||
UserId: userVerified.GetUserId(),
|
||||
},
|
||||
|
@ -92,15 +92,30 @@ func TestServer_RegisterPasskey(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user mismatch",
|
||||
name: "user no permission",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
ctx: UserCTX,
|
||||
req: &user.RegisterPasskeyRequest{
|
||||
UserId: userID,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "user permission",
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &user.RegisterPasskeyRequest{
|
||||
UserId: userID,
|
||||
},
|
||||
},
|
||||
want: &user.RegisterPasskeyResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Instance.DefaultOrg.Id,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user setting its own passkey",
|
||||
args: args{
|
||||
|
@ -260,6 +260,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Пол
|
||||
Female: Женски пол
|
||||
Male: Мъжки
|
||||
@ -301,6 +302,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Правила и условия
|
||||
TosConfirm: Приемам
|
||||
TosLinkText: TOS
|
||||
@ -371,6 +373,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Упълномощаване на устройството
|
||||
UserCode:
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Pohlaví
|
||||
Female: Žena
|
||||
Male: Muž
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Obchodní podmínky
|
||||
TosConfirm: Souhlasím s
|
||||
TosLinkText: obchodními podmínkami
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Autorizace zařízení
|
||||
UserCode:
|
||||
|
@ -263,6 +263,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Geschlecht
|
||||
Female: weiblich
|
||||
Male: männlich
|
||||
@ -305,6 +306,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Allgemeine Geschäftsbedingungen und Datenschutz
|
||||
TosConfirm: Ich akzeptiere die
|
||||
TosLinkText: AGB
|
||||
@ -381,6 +383,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Gerät verbinden
|
||||
UserCode:
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Gender
|
||||
Female: Female
|
||||
Male: Male
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Terms and conditions
|
||||
TosConfirm: I accept the
|
||||
TosLinkText: TOS
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Device Authorization
|
||||
UserCode:
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Género
|
||||
Female: Mujer
|
||||
Male: Hombre
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Términos y condiciones
|
||||
TosConfirm: Acepto los
|
||||
TosLinkText: TDS
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
Footer:
|
||||
PoweredBy: Powered By
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Genre
|
||||
Female: Femme
|
||||
Male: Homme
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Termes et conditions
|
||||
TosConfirm: J'accepte les
|
||||
TosLinkText: TOS
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autorisation de l'appareil
|
||||
|
@ -234,6 +234,7 @@ RegistrationUser:
|
||||
Swedish: Svéd
|
||||
Indonesian: Indonéz
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Nem
|
||||
Female: Nő
|
||||
Male: Férfi
|
||||
@ -275,6 +276,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svéd
|
||||
Indonesian: Indonéz
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Felhasználási feltételek
|
||||
TosConfirm: Elfogadom a
|
||||
TosLinkText: TOS
|
||||
@ -345,6 +347,7 @@ ExternalNotFound:
|
||||
Swedish: Svéd
|
||||
Indonesian: Indonéz
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Eszköz engedélyezése
|
||||
UserCode:
|
||||
|
@ -234,6 +234,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Jenis kelamin
|
||||
Female: Perempuan
|
||||
Male: Pria
|
||||
@ -274,6 +275,7 @@ ExternalRegistrationUserOverview:
|
||||
Dutch: Nederlands
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Syarat dan Ketentuan
|
||||
TosConfirm: Saya menerima itu
|
||||
TosLinkText: KL
|
||||
@ -344,6 +346,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Otorisasi Perangkat
|
||||
UserCode:
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Genere
|
||||
Female: Femminile
|
||||
Male: Maschile
|
||||
@ -305,6 +306,7 @@ ExternalRegistrationUserOverview:
|
||||
Dutch: Nederlands
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Termini di servizio
|
||||
TosConfirm: Accetto i
|
||||
TosLinkText: Termini di servizio
|
||||
@ -381,6 +383,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autorizzazione del dispositivo
|
||||
|
@ -256,6 +256,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: 性別
|
||||
Female: 女性
|
||||
Male: 男性
|
||||
@ -298,6 +299,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: 利用規約
|
||||
TosConfirm: 私は利用規約を承諾します。
|
||||
TosLinkText: TOS
|
||||
@ -374,6 +376,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: デバイス認証
|
||||
|
521
internal/api/ui/login/static/i18n/ko.yaml
Normal file
521
internal/api/ui/login/static/i18n/ko.yaml
Normal file
@ -0,0 +1,521 @@
|
||||
Login:
|
||||
Title: 다시 오신 것을 환영합니다!
|
||||
Description: 로그인 정보를 입력하세요.
|
||||
TitleLinking: 사용자 연결을 위한 로그인
|
||||
DescriptionLinking: 외부 사용자를 연결하려면 로그인 정보를 입력하세요.
|
||||
LoginNameLabel: 로그인 이름
|
||||
UsernamePlaceHolder: 사용자 이름
|
||||
LoginnamePlaceHolder: username@domain
|
||||
ExternalUserDescription: 외부 사용자로 로그인하세요.
|
||||
MustBeMemberOfOrg: 사용자는 {{.OrgName}} 조직의 멤버여야 합니다.
|
||||
RegisterButtonText: 등록
|
||||
NextButtonText: 다음
|
||||
|
||||
LDAP:
|
||||
Title: 로그인
|
||||
Description: 로그인 정보를 입력하세요.
|
||||
LoginNameLabel: 로그인 이름
|
||||
PasswordLabel: 비밀번호
|
||||
NextButtonText: 다음
|
||||
|
||||
SelectAccount:
|
||||
Title: 계정 선택
|
||||
Description: 계정을 사용하세요
|
||||
TitleLinking: 사용자 연결을 위한 계정 선택
|
||||
DescriptionLinking: 외부 사용자와 연결할 계정을 선택하세요.
|
||||
OtherUser: 다른 사용자
|
||||
SessionState0: 활성
|
||||
SessionState1: 로그아웃됨
|
||||
MustBeMemberOfOrg: 사용자는 {{.OrgName}} 조직의 멤버여야 합니다.
|
||||
|
||||
Password:
|
||||
Title: 비밀번호
|
||||
Description: 로그인 정보를 입력하세요.
|
||||
PasswordLabel: 비밀번호
|
||||
MinLength: 최소 길이는
|
||||
MinLengthp2: 자 이상이어야 합니다.
|
||||
MaxLength: 70자 미만이어야 합니다.
|
||||
HasUppercase: 대문자가 포함되어야 합니다.
|
||||
HasLowercase: 소문자가 포함되어야 합니다.
|
||||
HasNumber: 숫자가 포함되어야 합니다.
|
||||
HasSymbol: 기호가 포함되어야 합니다.
|
||||
Confirmation: 비밀번호가 일치합니다.
|
||||
ResetLinkText: 비밀번호 재설정
|
||||
BackButtonText: 뒤로
|
||||
NextButtonText: 다음
|
||||
|
||||
UsernameChange:
|
||||
Title: 사용자 이름 변경
|
||||
Description: 새 사용자 이름을 설정하세요
|
||||
UsernameLabel: 사용자 이름
|
||||
CancelButtonText: 취소
|
||||
NextButtonText: 다음
|
||||
|
||||
UsernameChangeDone:
|
||||
Title: 사용자 이름 변경 완료
|
||||
Description: 사용자 이름이 성공적으로 변경되었습니다.
|
||||
NextButtonText: 다음
|
||||
|
||||
InitPassword:
|
||||
Title: 비밀번호 설정
|
||||
Description: 아래 양식에 새 비밀번호를 설정하기 위해 받은 코드를 입력하세요.
|
||||
CodeLabel: 코드
|
||||
NewPasswordLabel: 새 비밀번호
|
||||
NewPasswordConfirmLabel: 비밀번호 확인
|
||||
ResendButtonText: 코드 재전송
|
||||
NextButtonText: 다음
|
||||
|
||||
InitPasswordDone:
|
||||
Title: 비밀번호 설정 완료
|
||||
Description: 비밀번호가 성공적으로 설정되었습니다.
|
||||
NextButtonText: 다음
|
||||
CancelButtonText: 취소
|
||||
|
||||
InitUser:
|
||||
Title: 사용자 활성화
|
||||
Description: 아래 코드를 통해 이메일을 인증하고 비밀번호를 설정하세요.
|
||||
CodeLabel: 코드
|
||||
NewPasswordLabel: 새 비밀번호
|
||||
NewPasswordConfirm: 비밀번호 확인
|
||||
NextButtonText: 다음
|
||||
ResendButtonText: 코드 재전송
|
||||
|
||||
InitUserDone:
|
||||
Title: 사용자 활성화 완료
|
||||
Description: 이메일이 인증되었으며 비밀번호가 성공적으로 설정되었습니다.
|
||||
NextButtonText: 다음
|
||||
CancelButtonText: 취소
|
||||
|
||||
InviteUser:
|
||||
Title: 사용자 활성화
|
||||
Description: 아래 코드를 통해 이메일을 인증하고 비밀번호를 설정하세요.
|
||||
CodeLabel: 코드
|
||||
NewPasswordLabel: 새 비밀번호
|
||||
NewPasswordConfirm: 비밀번호 확인
|
||||
NextButtonText: 다음
|
||||
ResendButtonText: 코드 재전송
|
||||
|
||||
InitMFAPrompt:
|
||||
Title: 2단계 인증 설정
|
||||
Description: 2단계 인증은 사용자 계정에 추가 보안을 제공합니다. 이를 통해 계정 접근이 본인에게만 허용됩니다.
|
||||
Provider0: "인증 앱 (예: Google/Microsoft Authenticator, Authy)"
|
||||
Provider1: "장치 종속 (예: FaceID, Windows Hello, 지문)"
|
||||
Provider3: OTP SMS
|
||||
Provider4: OTP 이메일
|
||||
NextButtonText: 다음
|
||||
SkipButtonText: 건너뛰기
|
||||
|
||||
InitMFAOTP:
|
||||
Title: 2단계 인증
|
||||
Description: 2단계 인증을 설정하세요. 인증 앱이 없으면 다운로드하세요.
|
||||
OTPDescription: "인증 앱으로 코드를 스캔하거나 비밀을 복사하여 아래에 생성된 코드를 입력하세요 (예: Google/Microsoft Authenticator, Authy)."
|
||||
SecretLabel: 비밀
|
||||
CodeLabel: 코드
|
||||
NextButtonText: 다음
|
||||
CancelButtonText: 취소
|
||||
|
||||
InitMFAOTPSMS:
|
||||
Title: 2단계 인증
|
||||
DescriptionPhone: 2단계 인증을 설정하세요. 전화번호를 입력하여 인증하세요.
|
||||
DescriptionCode: 2단계 인증을 설정하세요. 받은 코드를 입력하여 전화번호를 인증하세요.
|
||||
PhoneLabel: 전화번호
|
||||
CodeLabel: 코드
|
||||
EditButtonText: 수정
|
||||
ResendButtonText: 코드 재전송
|
||||
NextButtonText: 다음
|
||||
|
||||
InitMFAU2F:
|
||||
Title: 보안 키 추가
|
||||
Description: 보안 키는 휴대폰에 내장되거나, 블루투스 또는 컴퓨터 USB 포트에 직접 연결할 수 있는 인증 방법입니다.
|
||||
TokenNameLabel: 보안 키/장치 이름
|
||||
NotSupported: "WebAuthN이 브라우저에서 지원되지 않습니다. 최신 상태인지 확인하거나 다른 브라우저를 사용하세요 (예: Chrome, Safari, Firefox)."
|
||||
RegisterTokenButtonText: 보안 키 추가
|
||||
ErrorRetry: 다시 시도, 새 챌린지 생성 또는 다른 방법 선택.
|
||||
|
||||
InitMFADone:
|
||||
Title: 2단계 인증 완료
|
||||
Description: 축하합니다! 2단계 인증을 성공적으로 설정하여 계정을 더욱 안전하게 보호했습니다. 로그인 시마다 이 인증이 필요합니다.
|
||||
NextButtonText: 다음
|
||||
CancelButtonText: 취소
|
||||
|
||||
MFAProvider:
|
||||
Provider0: "인증 앱 (예: Google/Microsoft Authenticator, Authy)"
|
||||
Provider1: "장치 종속 (예: FaceID, Windows Hello, 지문)"
|
||||
Provider3: OTP SMS
|
||||
Provider4: OTP 이메일
|
||||
ChooseOther: 다른 옵션 선택
|
||||
|
||||
VerifyMFAOTP:
|
||||
Title: 2단계 인증 확인
|
||||
Description: 2단계 인증을 확인하세요
|
||||
CodeLabel: 코드
|
||||
NextButtonText: 다음
|
||||
|
||||
VerifyOTP:
|
||||
Title: 2단계 인증 확인
|
||||
Description: 2단계 인증을 확인하세요
|
||||
CodeLabel: 코드
|
||||
ResendButtonText: 코드 재전송
|
||||
NextButtonText: 다음
|
||||
|
||||
VerifyMFAU2F:
|
||||
Title: 2단계 인증
|
||||
Description: "등록된 장치로 2단계 인증을 진행하세요 (예: FaceID, Windows Hello, 지문)"
|
||||
NotSupported: "WebAuthN이 브라우저에서 지원되지 않습니다. 최신 버전을 사용하거나 지원되는 다른 브라우저로 변경하세요 (예: Chrome, Safari, Firefox)."
|
||||
ErrorRetry: 다시 시도, 새 요청 생성 또는 다른 방법 선택.
|
||||
ValidateTokenButtonText: 2단계 인증
|
||||
|
||||
Passwordless:
|
||||
Title: 비밀번호 없이 로그인
|
||||
Description: "FaceID, Windows Hello, 지문과 같은 장치에서 제공하는 인증 방법으로 로그인하세요."
|
||||
NotSupported: "WebAuthN이 브라우저에서 지원되지 않습니다. 최신 상태인지 확인하거나 다른 브라우저를 사용하세요 (예: Chrome, Safari, Firefox)."
|
||||
ErrorRetry: 다시 시도, 새 챌린지 생성 또는 다른 방법 선택.
|
||||
LoginWithPwButtonText: 비밀번호로 로그인
|
||||
ValidateTokenButtonText: 비밀번호 없이 로그인
|
||||
|
||||
PasswordlessPrompt:
|
||||
Title: 비밀번호 없는 로그인 설정
|
||||
Description: "비밀번호 없는 로그인을 설정하시겠습니까? (FaceID, Windows Hello, 지문과 같은 장치 인증 방법)"
|
||||
DescriptionInit: 비밀번호 없는 로그인을 설정해야 합니다. 기기 등록을 위해 제공된 링크를 사용하세요.
|
||||
PasswordlessButtonText: 비밀번호 없이 사용
|
||||
NextButtonText: 다음
|
||||
SkipButtonText: 건너뛰기
|
||||
|
||||
PasswordlessRegistration:
|
||||
Title: 비밀번호 없는 로그인 설정
|
||||
Description: "장치 이름을 입력한 후 아래의 '비밀번호 없이 등록' 버튼을 클릭하여 인증을 추가하세요 (예: 내 휴대폰, MacBook 등)."
|
||||
TokenNameLabel: 장치 이름
|
||||
NotSupported: "WebAuthN이 브라우저에서 지원되지 않습니다. 최신 상태인지 확인하거나 다른 브라우저를 사용하세요 (예: Chrome, Safari, Firefox)."
|
||||
RegisterTokenButtonText: 비밀번호 없이 등록
|
||||
ErrorRetry: 다시 시도, 새 챌린지 생성 또는 다른 방법 선택.
|
||||
|
||||
PasswordlessRegistrationDone:
|
||||
Title: 비밀번호 없는 로그인 설정 완료
|
||||
Description: 비밀번호 없는 장치가 성공적으로 추가되었습니다.
|
||||
DescriptionClose: 이제 이 창을 닫을 수 있습니다.
|
||||
NextButtonText: 다음
|
||||
CancelButtonText: 취소
|
||||
|
||||
PasswordChange:
|
||||
Title: 비밀번호 변경
|
||||
Description: 비밀번호를 변경하세요. 기존 비밀번호와 새 비밀번호를 입력하세요.
|
||||
ExpiredDescription: 비밀번호가 만료되어 변경이 필요합니다. 기존 비밀번호와 새 비밀번호를 입력하세요.
|
||||
OldPasswordLabel: 기존 비밀번호
|
||||
NewPasswordLabel: 새 비밀번호
|
||||
NewPasswordConfirmLabel: 비밀번호 확인
|
||||
CancelButtonText: 취소
|
||||
NextButtonText: 다음
|
||||
Footer: 푸터
|
||||
|
||||
PasswordChangeDone:
|
||||
Title: 비밀번호 변경 완료
|
||||
Description: 비밀번호가 성공적으로 변경되었습니다.
|
||||
NextButtonText: 다음
|
||||
|
||||
PasswordResetDone:
|
||||
Title: 비밀번호 재설정 링크 발송됨
|
||||
Description: 비밀번호를 재설정하려면 이메일을 확인하세요.
|
||||
NextButtonText: 다음
|
||||
|
||||
EmailVerification:
|
||||
Title: 이메일 인증
|
||||
Description: 이메일 인증을 위해 전송된 코드를 아래 양식에 입력하세요.
|
||||
CodeLabel: 코드
|
||||
NextButtonText: 다음
|
||||
ResendButtonText: 코드 재전송
|
||||
|
||||
EmailVerificationDone:
|
||||
Title: 이메일 인증 완료
|
||||
Description: 이메일 주소가 성공적으로 인증되었습니다.
|
||||
NextButtonText: 다음
|
||||
CancelButtonText: 취소
|
||||
LoginButtonText: 로그인
|
||||
|
||||
RegisterOption:
|
||||
Title: 등록 옵션
|
||||
Description: 등록 방법을 선택하세요
|
||||
RegisterUsernamePasswordButtonText: 사용자 이름과 비밀번호로 등록
|
||||
ExternalLoginDescription: 또는 외부 사용자로 등록
|
||||
LoginButtonText: 로그인
|
||||
|
||||
RegistrationUser:
|
||||
Title: 등록
|
||||
Description: 사용자 정보를 입력하세요. 이메일 주소는 로그인 이름으로 사용됩니다.
|
||||
DescriptionOrgRegister: 사용자 정보를 입력하세요.
|
||||
EmailLabel: 이메일
|
||||
UsernameLabel: 사용자 이름
|
||||
FirstnameLabel: 이름
|
||||
LastnameLabel: 성
|
||||
LanguageLabel: 언어
|
||||
German: Deutsch
|
||||
English: English
|
||||
Italian: Italiano
|
||||
French: Français
|
||||
Chinese: 简体中文
|
||||
Polish: Polski
|
||||
Japanese: 日本語
|
||||
Spanish: Español
|
||||
Bulgarian: Български
|
||||
Portuguese: Português
|
||||
Macedonian: Македонски
|
||||
Czech: Čeština
|
||||
Russian: Русский
|
||||
Dutch: Nederlands
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: 성별
|
||||
Female: 여성
|
||||
Male: 남성
|
||||
Diverse: 기타 / X
|
||||
PasswordLabel: 비밀번호
|
||||
PasswordConfirmLabel: 비밀번호 확인
|
||||
TosAndPrivacyLabel: 동의사항
|
||||
TosConfirm: 이용 약관에 동의합니다.
|
||||
TosLinkText: 이용 약관
|
||||
PrivacyConfirm: 개인정보 수집 및 이용에 동의합니다.
|
||||
PrivacyLinkText: 개인정보처리방침
|
||||
ExternalLogin: 또는 외부 사용자로 등록
|
||||
BackButtonText: 로그인
|
||||
NextButtonText: 다음
|
||||
|
||||
ExternalRegistrationUserOverview:
|
||||
Title: 외부 사용자 등록
|
||||
Description: 선택한 제공자에서 사용자 정보를 가져왔습니다. 이제 정보를 수정하거나 완성할 수 있습니다.
|
||||
EmailLabel: 이메일
|
||||
UsernameLabel: 사용자 이름
|
||||
FirstnameLabel: 이름
|
||||
LastnameLabel: 성
|
||||
NicknameLabel: 닉네임
|
||||
PhoneLabel: 전화번호
|
||||
LanguageLabel: 언어
|
||||
German: Deutsch
|
||||
English: English
|
||||
Italian: Italiano
|
||||
French: Français
|
||||
Chinese: 简体中文
|
||||
Polish: Polski
|
||||
Japanese: 日本語
|
||||
Spanish: Español
|
||||
Bulgarian: Български
|
||||
Portuguese: Português
|
||||
Macedonian: Македонски
|
||||
Czech: Čeština
|
||||
Russian: Русский
|
||||
Dutch: Nederlands
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: 동의사항
|
||||
TosConfirm: 이용 약관에 동의합니다.
|
||||
TosLinkText: 이용 약관
|
||||
PrivacyConfirm: 개인정보 수집 및 이용에 동의합니다.
|
||||
PrivacyLinkText: 개인정보처리방침
|
||||
ExternalLogin: 또는 외부 사용자로 등록
|
||||
BackButtonText: 뒤로
|
||||
NextButtonText: 저장
|
||||
|
||||
RegistrationOrg:
|
||||
Title: 조직 등록
|
||||
Description: 조직 이름과 사용자 정보를 입력하세요.
|
||||
OrgNameLabel: 조직 이름
|
||||
EmailLabel: 이메일
|
||||
UsernameLabel: 사용자 이름
|
||||
FirstnameLabel: 이름
|
||||
LastnameLabel: 성
|
||||
PasswordLabel: 비밀번호
|
||||
PasswordConfirmLabel: 비밀번호 확인
|
||||
TosAndPrivacyLabel: 동의사항
|
||||
TosConfirm: 이용 약관에 동의합니다.
|
||||
TosLinkText: 이용 약관
|
||||
PrivacyConfirm: 개인정보 수집 및 이용에 동의합니다.
|
||||
PrivacyLinkText: 개인정보처리방침
|
||||
SaveButtonText: 조직 생성
|
||||
|
||||
LoginSuccess:
|
||||
Title: 로그인 성공
|
||||
AutoRedirectDescription: 자동으로 애플리케이션으로 리디렉션됩니다. 그렇지 않으면 아래 버튼을 클릭하세요. 이후 창을 닫아도 됩니다.
|
||||
RedirectedDescription: 이제 이 창을 닫을 수 있습니다.
|
||||
NextButtonText: 다음
|
||||
|
||||
LogoutDone:
|
||||
Title: 로그아웃 완료
|
||||
Description: 성공적으로 로그아웃되었습니다.
|
||||
LoginButtonText: 로그인
|
||||
|
||||
LinkingUserPrompt:
|
||||
Title: 기존 사용자 발견
|
||||
Description: "기존 계정을 연결하시겠습니까:"
|
||||
LinkButtonText: 연결
|
||||
OtherButtonText: 다른 옵션
|
||||
|
||||
LinkingUsersDone:
|
||||
Title: 사용자 연결
|
||||
Description: 사용자가 연결되었습니다.
|
||||
CancelButtonText: 취소
|
||||
NextButtonText: 다음
|
||||
|
||||
ExternalNotFound:
|
||||
Title: 외부 사용자 찾을 수 없음
|
||||
Description: 외부 사용자를 찾을 수 없습니다. 사용자 계정을 연결하거나 새 계정을 자동 등록하시겠습니까?
|
||||
LinkButtonText: 연결
|
||||
AutoRegisterButtonText: 등록
|
||||
TosAndPrivacyLabel: 동의사항
|
||||
TosConfirm: 이용 약관에 동의합니다.
|
||||
TosLinkText: 이용 약관
|
||||
PrivacyConfirm: 개인정보 수집 및 이용에 동의합니다.
|
||||
PrivacyLinkText: 개인정보처리방침
|
||||
German: Deutsch
|
||||
English: English
|
||||
Italian: Italiano
|
||||
French: Français
|
||||
Chinese: 简体中文
|
||||
Polish: Polski
|
||||
Japanese: 日本語
|
||||
Spanish: Español
|
||||
Bulgarian: Български
|
||||
Portuguese: Português
|
||||
Macedonian: Македонски
|
||||
Czech: Čeština
|
||||
Russian: Русский
|
||||
Dutch: Nederlands
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: 기기 인증
|
||||
UserCode:
|
||||
Label: 사용자 코드
|
||||
Description: 기기에서 표시된 사용자 코드를 입력하세요.
|
||||
ButtonNext: 다음
|
||||
Action:
|
||||
Description: 기기 접근 권한을 부여하세요.
|
||||
GrantDevice: 기기에게 권한을 부여하려고 합니다
|
||||
AccessToScopes: 다음 범위에 접근 권한이 있습니다
|
||||
Button:
|
||||
Allow: 허용
|
||||
Deny: 거부
|
||||
Done:
|
||||
Description: 완료.
|
||||
Approved: 기기 인증이 승인되었습니다. 이제 기기로 돌아가세요.
|
||||
Denied: 기기 인증이 거부되었습니다. 이제 기기로 돌아가세요.
|
||||
|
||||
Footer:
|
||||
PoweredBy: 제공자
|
||||
Tos: 이용 약관
|
||||
PrivacyPolicy: 개인정보처리방침
|
||||
Help: 도움말
|
||||
SupportEmail: 지원 이메일
|
||||
|
||||
SignIn: "{{.Provider}}로 로그인"
|
||||
|
||||
Errors:
|
||||
Internal: 내부 오류가 발생했습니다
|
||||
AuthRequest:
|
||||
NotFound: 인증 요청을 찾을 수 없습니다
|
||||
UserAgentNotCorresponding: 사용자 에이전트가 일치하지 않습니다
|
||||
UserAgentNotFound: 사용자 에이전트 ID를 찾을 수 없습니다
|
||||
TokenNotFound: 토큰을 찾을 수 없습니다
|
||||
RequestTypeNotSupported: 요청 유형이 지원되지 않습니다
|
||||
MissingParameters: 필수 매개변수가 없습니다
|
||||
User:
|
||||
NotFound: 사용자를 찾을 수 없습니다
|
||||
AlreadyExists: 사용자가 이미 존재합니다
|
||||
Inactive: 사용자가 비활성화되었습니다
|
||||
NotFoundOnOrg: 선택된 조직에서 사용자를 찾을 수 없습니다
|
||||
NotAllowedOrg: 사용자는 필수 조직의 멤버가 아닙니다
|
||||
NotMatchingUserID: 사용자와 인증 요청의 사용자가 일치하지 않습니다
|
||||
UserIDMissing: 사용자 ID가 비어 있습니다
|
||||
Invalid: 잘못된 사용자 데이터입니다
|
||||
DomainNotAllowedAsUsername: 도메인이 이미 예약되어 사용할 수 없습니다
|
||||
NotAllowedToLink: 외부 로그인 제공자와 연결할 수 없습니다
|
||||
Profile:
|
||||
NotFound: 프로필을 찾을 수 없습니다
|
||||
NotChanged: 프로필이 변경되지 않았습니다
|
||||
Empty: 프로필이 비어 있습니다
|
||||
FirstNameEmpty: 프로필에 이름이 비어 있습니다
|
||||
LastNameEmpty: 프로필에 성이 비어 있습니다
|
||||
IDMissing: 프로필 ID가 없습니다
|
||||
Email:
|
||||
NotFound: 이메일을 찾을 수 없습니다
|
||||
Invalid: 잘못된 이메일입니다
|
||||
AlreadyVerified: 이메일이 이미 인증되었습니다
|
||||
NotChanged: 이메일이 변경되지 않았습니다
|
||||
Empty: 이메일이 비어 있습니다
|
||||
IDMissing: 이메일 ID가 없습니다
|
||||
Phone:
|
||||
NotFound: 전화번호를 찾을 수 없습니다
|
||||
Invalid: 잘못된 전화번호입니다
|
||||
AlreadyVerified: 전화번호가 이미 인증되었습니다
|
||||
Empty: 전화번호가 비어 있습니다
|
||||
NotChanged: 전화번호가 변경되지 않았습니다
|
||||
Address:
|
||||
NotFound: 주소를 찾을 수 없습니다
|
||||
NotChanged: 주소가 변경되지 않았습니다
|
||||
Username:
|
||||
AlreadyExists: 사용자 이름이 이미 사용 중입니다
|
||||
Reserved: 사용자 이름이 이미 예약되었습니다
|
||||
Empty: 사용자 이름이 비어 있습니다
|
||||
Password:
|
||||
ConfirmationWrong: 비밀번호 확인이 일치하지 않습니다
|
||||
Empty: 비밀번호가 비어 있습니다
|
||||
Invalid: 잘못된 비밀번호입니다
|
||||
InvalidAndLocked: 비밀번호가 잘못되었고 사용자가 잠겼습니다. 관리자에게 문의하세요.
|
||||
NotChanged: 새 비밀번호는 현재 비밀번호와 다르게 설정해야 합니다
|
||||
UsernameOrPassword:
|
||||
Invalid: 사용자 이름 또는 비밀번호가 잘못되었습니다
|
||||
PasswordComplexityPolicy:
|
||||
NotFound: 비밀번호 정책을 찾을 수 없습니다
|
||||
MinLength: 비밀번호가 너무 짧습니다
|
||||
HasLower: 비밀번호에 소문자가 포함되어야 합니다
|
||||
HasUpper: 비밀번호에 대문자가 포함되어야 합니다
|
||||
HasNumber: 비밀번호에 숫자가 포함되어야 합니다
|
||||
HasSymbol: 비밀번호에 기호가 포함되어야 합니다
|
||||
Code:
|
||||
Expired: 코드가 만료되었습니다
|
||||
Invalid: 잘못된 코드입니다
|
||||
Empty: 코드가 비어 있습니다
|
||||
CryptoCodeNil: 암호화 코드가 없습니다
|
||||
NotFound: 코드를 찾을 수 없습니다
|
||||
GeneratorAlgNotSupported: 지원되지 않는 생성 알고리즘입니다
|
||||
EmailVerify:
|
||||
UserIDEmpty: 사용자 ID가 비어 있습니다
|
||||
ExternalData:
|
||||
CouldNotRead: 외부 데이터를 올바르게 읽을 수 없습니다
|
||||
MFA:
|
||||
NoProviders: 사용 가능한 다중 인증 제공자가 없습니다
|
||||
OTP:
|
||||
AlreadyReady: 다중 인증 OTP(일회용 비밀번호)가 이미 설정되었습니다
|
||||
NotExisting: 다중 인증 OTP(일회용 비밀번호)가 존재하지 않습니다
|
||||
InvalidCode: 잘못된 코드입니다
|
||||
NotReady: 다중 인증 OTP(일회용 비밀번호)가 준비되지 않았습니다
|
||||
Locked: 사용자가 잠겼습니다
|
||||
SomethingWentWrong: 문제가 발생했습니다
|
||||
NotActive: 사용자가 활성 상태가 아닙니다
|
||||
ExternalIDP:
|
||||
IDPTypeNotImplemented: IDP 유형이 구현되지 않았습니다
|
||||
NotAllowed: 외부 로그인 제공자가 허용되지 않습니다
|
||||
IDPConfigIDEmpty: ID 제공자 ID가 비어 있습니다
|
||||
ExternalUserIDEmpty: 외부 사용자 ID가 비어 있습니다
|
||||
UserDisplayNameEmpty: 사용자 표시 이름이 비어 있습니다
|
||||
NoExternalUserData: 외부 사용자 데이터를 받을 수 없습니다
|
||||
CreationNotAllowed: 이 제공자에서는 새 사용자 생성을 허용하지 않습니다
|
||||
LinkingNotAllowed: 이 제공자에서는 사용자를 연결할 수 없습니다
|
||||
NoOptionAllowed: 이 제공자에서는 생성과 연결이 모두 허용되지 않습니다. 관리자에게 문의하세요.
|
||||
GrantRequired: 로그인 불가. 사용자는 애플리케이션에서 최소한 하나의 권한이 필요합니다. 관리자에게 문의하세요.
|
||||
ProjectRequired: 로그인 불가. 사용자의 조직이 프로젝트에 허가되어야 합니다. 관리자에게 문의하세요.
|
||||
IdentityProvider:
|
||||
InvalidConfig: ID 제공자 설정이 잘못되었습니다
|
||||
IAM:
|
||||
LockoutPolicy:
|
||||
NotExisting: 잠금 정책이 존재하지 않습니다
|
||||
Org:
|
||||
LoginPolicy:
|
||||
RegistrationNotAllowed: 등록이 허용되지 않습니다
|
||||
DeviceAuth:
|
||||
NotExisting: 사용자 코드가 존재하지 않습니다
|
||||
|
||||
optional: (선택 사항)
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Пол
|
||||
Female: Женски
|
||||
Male: Машки
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Правила и услови
|
||||
TosConfirm: Се согласувам со
|
||||
TosLinkText: правилата за користење
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: Овластување преку уред
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Geslacht
|
||||
Female: Vrouw
|
||||
Male: Man
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Algemene voorwaarden
|
||||
TosConfirm: Ik accepteer de
|
||||
TosLinkText: AV
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Apparaat Autorisatie
|
||||
UserCode:
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Płeć
|
||||
Female: Kobieta
|
||||
Male: Mężczyzna
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Warunki i zasady
|
||||
TosConfirm: Akceptuję
|
||||
TosLinkText: Warunki korzystania
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autoryzacja urządzenia
|
||||
|
@ -260,6 +260,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Gênero
|
||||
Female: Feminino
|
||||
Male: Masculino
|
||||
@ -302,6 +303,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Termos e condições
|
||||
TosConfirm: Eu aceito os
|
||||
TosLinkText: termos de serviço
|
||||
@ -378,6 +380,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: Autorização de dispositivo
|
||||
|
@ -1,246 +1,247 @@
|
||||
Login:
|
||||
Title: Добро пожаловать!
|
||||
Description: Введите ваши данные.
|
||||
Description: Введите свои данные дял входа.
|
||||
TitleLinking: Вход для привязки пользователей
|
||||
DescriptionLinking: Введите данные для входа, чтобы привязать внешнего пользователя к пользователю ZITADEL.
|
||||
DescriptionLinking: Введите данные для входа, чтобы привязать внешнего пользователя к учётной записи ZITADEL.
|
||||
LoginNameLabel: Логин
|
||||
UsernamePlaceHolder: логин
|
||||
LoginnamePlaceHolder: username@domain
|
||||
ExternalUserDescription: Войти под внешним пользователем.
|
||||
MustBeMemberOfOrg: Пользователь должен быть участником организации {{.OrgName}}.
|
||||
RegisterButtonText: зарегистрироваться
|
||||
NextButtonText: далее
|
||||
ExternalUserDescription: Войти как внешний пользователь.
|
||||
MustBeMemberOfOrg: Пользователь должен быть членом организации {{.OrgName}}.
|
||||
RegisterButtonText: Зарегистрироваться
|
||||
NextButtonText: Продолжить
|
||||
|
||||
LDAP:
|
||||
Title: Войти
|
||||
Description: Введите ваши данные дял входа.
|
||||
LoginNameLabel: Имя пользователя
|
||||
Description: Введите свои данные для входа.
|
||||
LoginNameLabel: Логин
|
||||
PasswordLabel: Пароль
|
||||
NextButtonText: следующий
|
||||
NextButtonText: Продолжить
|
||||
|
||||
SelectAccount:
|
||||
Title: Выбор учётной записи
|
||||
Description: Выберите вашу учётную запись.
|
||||
Description: Выберите учётную запись.
|
||||
TitleLinking: Выберите учётную запись для привязки пользователя
|
||||
DescriptionLinking: Выберите свою учётную запись для связи с внешним пользователем.
|
||||
OtherUser: Другой пользователь
|
||||
OtherUser: Другая учётная запись
|
||||
SessionState0: активный
|
||||
SessionState1: неактивный
|
||||
MustBeMemberOfOrg: Пользователь должен быть участником организации {{.OrgName}}.
|
||||
MustBeMemberOfOrg: Пользователь должен быть членом организации {{.OrgName}}.
|
||||
|
||||
Password:
|
||||
Title: Пароль
|
||||
Description: Введите свои данные для входа.
|
||||
Description: Введите данные для входа.
|
||||
PasswordLabel: Пароль
|
||||
MinLength: Должно быть не менее
|
||||
MinLength: Минимум
|
||||
MinLengthp2: символов.
|
||||
MaxLength: Должно быть меньше 70 символов.
|
||||
HasUppercase: Должно содержать заглавную букву.
|
||||
HasLowercase: Должно содержать строчную букву.
|
||||
HasNumber: Должно содержать число.
|
||||
HasSymbol: Должно содержать символ.
|
||||
Confirmation: Подтверждение пароля совпадает.
|
||||
MaxLength: Не более 70 символов.
|
||||
HasUppercase: Должен содержать заглавную букву.
|
||||
HasLowercase: Должен содержать строчную букву.
|
||||
HasNumber: Должен содержать цифру.
|
||||
HasSymbol: Должен содержить специальный символ.
|
||||
Confirmation: Пароли должны совпадать.
|
||||
ResetLinkText: Сбросить пароль
|
||||
BackButtonText: Назад
|
||||
NextButtonText: Вперед
|
||||
NextButtonText: Продолжить
|
||||
|
||||
UsernameChange:
|
||||
Title: Изменение логина
|
||||
Description: Установите новый логин.
|
||||
UsernameLabel: Логин
|
||||
CancelButtonText: отмена
|
||||
NextButtonText: далее
|
||||
CancelButtonText: Отмена
|
||||
NextButtonText: Продолжить
|
||||
|
||||
UsernameChangeDone:
|
||||
Title: Логин изменён
|
||||
Description: Ваш логин был успешно изменён.
|
||||
NextButtonText: далее
|
||||
NextButtonText: Продолжить
|
||||
|
||||
InitPassword:
|
||||
Title: Установка пароля
|
||||
Description: Введите код из письма, отправленного на вашу электронную почту, чтобы установить пароль.
|
||||
CodeLabel: Код
|
||||
CodeLabel: Код из письма
|
||||
NewPasswordLabel: Новый пароль
|
||||
NewPasswordConfirmLabel: Подтверждение пароля
|
||||
ResendButtonText: повторно отправить код
|
||||
NextButtonText: далее
|
||||
NewPasswordConfirmLabel: Повторите пароль
|
||||
ResendButtonText: Отправить код ещё раз
|
||||
NextButtonText: Продолжить
|
||||
|
||||
InitPasswordDone:
|
||||
Title: Пароль установлен
|
||||
Description: Пароль успешно установлен.
|
||||
NextButtonText: далее
|
||||
CancelButtonText: отмена
|
||||
NextButtonText: Продолжить
|
||||
CancelButtonText: Отмена
|
||||
|
||||
InitUser:
|
||||
Title: Активация пользователя
|
||||
Description: Подтвердите вашу электронную почту кодом из письма и установите пароль.
|
||||
CodeLabel: Код
|
||||
Title: Активация учётной записи
|
||||
Description: Введите код из письма для подтверждения электронной почты и установите новый пароль.
|
||||
CodeLabel: Код из письма
|
||||
NewPasswordLabel: Новый пароль
|
||||
NewPasswordConfirm: Подтверждение пароля
|
||||
NextButtonText: далее
|
||||
ResendButtonText: повторно отправить код
|
||||
NewPasswordConfirm: Повторите пароль
|
||||
NextButtonText: Продолжить
|
||||
ResendButtonText: Отправить код ещё раз
|
||||
|
||||
InitUserDone:
|
||||
Title: Пользователь активирован
|
||||
Title: Учётная запись активирована
|
||||
Description: Электронная почта подтверждена и пароль успешно установлен.
|
||||
NextButtonText: далее
|
||||
CancelButtonText: отмена
|
||||
NextButtonText: Продолжить
|
||||
CancelButtonText: Отмена
|
||||
|
||||
InviteUser:
|
||||
Title: Активировать пользователя
|
||||
Description: Проверьте свой адрес электронной почты с помощью кода ниже и установите свой пароль.
|
||||
CodeLabel: Код
|
||||
Title: Активация учётной записи
|
||||
Description: Введите код из письма для подтверждения электронной почты и установите новый пароль.
|
||||
CodeLabel: Код из письма
|
||||
NewPasswordLabel: Новый пароль
|
||||
NewPasswordConfirm: Подтвердить пароль
|
||||
NextButtonText: Далее
|
||||
ResendButtonText: Отправить код повторно
|
||||
NewPasswordConfirm: Повторите пароль
|
||||
NextButtonText: Продолжить
|
||||
ResendButtonText: Отправить код ещё раз
|
||||
|
||||
InitMFAPrompt:
|
||||
Title: Установка двухфакторной аутентификации
|
||||
Description: Двухфакторная аутентификация обеспечивает дополнительную защиту вашей учётной записи.
|
||||
Provider0: Через приложение (например, Google/Microsoft Authenticator, Authy)
|
||||
Provider1: Через устройство (например, FaceID, Windows Hello, Fingerprint)
|
||||
Provider3: OTP SMS
|
||||
Provider4: Электронная почта OTP
|
||||
NextButtonText: следующий
|
||||
SkipButtonText: скип
|
||||
Description: Установите двухфакторную аутентификацию для дополнительной защиты вашей учётной записи.
|
||||
Provider0: Приложение для кодов (например, Google/Microsoft Authenticator или Authy)
|
||||
Provider1: С помощью устройства (Face ID, Windows Hello, отпечаток пальца)
|
||||
Provider3: Получать код по СМС
|
||||
Provider4: Получать код по электронной почте
|
||||
NextButtonText: Продолжить
|
||||
SkipButtonText: Пропустить
|
||||
|
||||
InitMFAOTP:
|
||||
Title: Подтверждение двухфакторной аутентификации
|
||||
Description: Создайте двухфакторную аутентификацию. Загрузите приложение для проверки подлинности, если у вас его ещё нет.
|
||||
OTPDescription: Отсканируйте код с помощью приложения для проверки подлинности (например, Google/Microsoft Authenticator, Authy) или сгенерируйте код указанного ключа и введите его в поле ниже.
|
||||
SecretLabel: Ключ
|
||||
CodeLabel: Код
|
||||
NextButtonText: далее
|
||||
CancelButtonText: отмена
|
||||
Title: Настройка двухфакторной аутентификации
|
||||
Description: Настройте двухфакторную аутентификацию. Загрузите приложение для генерации кодов, если оно у вас отсутствует.
|
||||
OTPDescription: Отсканируйте QR-код с помощью приложения (например, Google Authenticator, Microsoft Authenticator или Authy), либо скопируйте секретный ключ и введите код ниже.
|
||||
SecretLabel: Секретный ключ
|
||||
CodeLabel: Код подтверждения
|
||||
NextButtonText: Продолжить
|
||||
CancelButtonText: Отмена
|
||||
|
||||
InitMFAOTPSMS:
|
||||
Title: 2-факторная верификация
|
||||
DescriptionPhone: Создайте свой 2-фактор. Введите свой номер телефона, чтобы подтвердить его.
|
||||
DescriptionCode: Создайте свой 2-фактор. Введите полученный код, чтобы подтвердить свой номер телефона.
|
||||
PhoneLabel: Телефон
|
||||
CodeLabel: Код
|
||||
EditButtonText: редактировать
|
||||
ResendButtonText: Повторная отправка кода
|
||||
NextButtonText: следующий
|
||||
Title: Настройка двухфакторной аутентификации
|
||||
DescriptionPhone: Введите номер телефона для его подтверждения.
|
||||
DescriptionCode: Введите код из СМС для подтверждения номера телефона.
|
||||
PhoneLabel: Номер телефона
|
||||
CodeLabel: Код из СМС
|
||||
EditButtonText: Изменить
|
||||
ResendButtonText: Отправить код ещё раз
|
||||
NextButtonText: Продолжить
|
||||
|
||||
InitMFAU2F:
|
||||
Title: Добавление ключа безопасности
|
||||
Description: Ключ безопасности — это метод проверки, который можно встроить в телефон, используя Bluetooth, или подключить непосредственно к USB-порту компьютера.
|
||||
Description: Ключ безопасности — это метод проверки, который может быть встроен в телефон, использовать Bluetooth или подключаться напрямую к USB-порту вашего компьютера.
|
||||
TokenNameLabel: Название ключа безопасности / устройства
|
||||
NotSupported: WebAuthN не поддерживается вашим браузером. Пожалуйста, убедитесь, что он обновлён или используйте другой (например, Chrome, Safari, Firefox)
|
||||
NotSupported: Ваш браузер не поддерживает WebAuthN. Пожалуйста, обновите его или используйте другой (например, Chrome, Safari, Firefox).
|
||||
RegisterTokenButtonText: Добавить ключ безопасности
|
||||
ErrorRetry: Повторите попытку или выберите другой метод.
|
||||
ErrorRetry: Повторите попытку, создайте новый запрос или выберите другой метод.
|
||||
|
||||
InitMFADone:
|
||||
Title: Ключ безопасности подтверждён
|
||||
Description: Поздравляю! Вы только что успешно настроили двухфакторную аутентификацию и сделали свою учётную запись более безопасной. Фактор необходимо вводить при каждом входе в систему.
|
||||
NextButtonText: далее
|
||||
CancelButtonText: отмена
|
||||
Description: Отлично! Вы успешно настроили двухфакторную аутентификацию и сделали свою учётную запись более безопасной. Фактор необходимо вводить при каждом входе в систему.
|
||||
NextButtonText: Продолжить
|
||||
CancelButtonText: Отмена
|
||||
|
||||
MFAProvider:
|
||||
Provider0: Через приложение (например, Google/Microsoft Authenticator, Authy)
|
||||
Provider1: Через устройство (например, FaceID, Windows Hello, Fingerprint)
|
||||
Provider3: OTP SMS
|
||||
Provider4: Электронная почта OTP
|
||||
Provider0: Приложение для кодов (например, Google/Microsoft Authenticator или Authy)
|
||||
Provider1: С помощью устройства (Face ID, Windows Hello, отпечаток пальца)
|
||||
Provider3: Получать код по СМС
|
||||
Provider4: Получать код по электронной почте
|
||||
ChooseOther: или выберите другой вариант
|
||||
|
||||
VerifyMFAOTP:
|
||||
Title: Подтверждение двухфакторной аутентификации
|
||||
Description: Подтвердите двухфакторную аутентификацию.
|
||||
Description: Введите код для проверки второго фактора
|
||||
CodeLabel: Код
|
||||
NextButtonText: далее
|
||||
NextButtonText: Продолжить
|
||||
|
||||
VerifyOTP:
|
||||
Title: Проверка 2-фактора
|
||||
Description: Проверьте свой второй фактор
|
||||
Title: Подтверждение двухфакторной аутентификации
|
||||
Description: Введите код для проверки второго фактора
|
||||
CodeLabel: Код
|
||||
ResendButtonText: Повторная отправка кода
|
||||
NextButtonText: следующий
|
||||
ResendButtonText: Отправить код ещё раз
|
||||
NextButtonText: Продолжить
|
||||
|
||||
VerifyMFAU2F:
|
||||
Title: Подтверждение двухфакторной аутентификации
|
||||
Description: Подтвердите двухфакторную аутентификацию с помощью зарегистрированного устройства (например, FaceID, Windows Hello, Fingerprint).
|
||||
NotSupported: WebAuthN не поддерживается вашим браузером. Убедитесь, что вы используете самую новую версию, или измените браузер на поддерживаемый (Chrome, Safari, Firefox)
|
||||
Description: Подтвердите двухфакторную аутентификацию с помощью зарегистрированного устройства (например, FaceID, Windows Hello или отпечатка пальца).
|
||||
NotSupported: Ваш браузер не поддерживает WebAuthN. Пожалуйста, обновите его или используйте другой (например, Chrome, Safari, Firefox).
|
||||
ErrorRetry: Повторите попытку или выберите другой метод.
|
||||
ValidateTokenButtonText: Подтвердить двухфакторную аутентификацию
|
||||
ValidateTokenButtonText: Подтвердить
|
||||
|
||||
Passwordless:
|
||||
Title: Вход без пароля
|
||||
Description: Войдите в систему с помощью методов аутентификации, предоставляемых вашим устройством, таких как FaceID, Windows Hello или Fingerprint.
|
||||
NotSupported: WebAuthN не поддерживается вашим браузером. Пожалуйста, убедитесь, что он обновлён или используйте другой (например, Chrome, Safari, Firefox)
|
||||
Description: Войдите в систему с помощью методов аутентификации, доступных на вашем устройстве, таких как FaceID, Windows Hello или отпечаток пальца.
|
||||
NotSupported: Ваш браузер не поддерживает WebAuthN. Пожалуйста, обновите его или используйте другой (например, Chrome, Safari, Firefox).
|
||||
ErrorRetry: Повторите попытку или выберите другой метод.
|
||||
LoginWithPwButtonText: Войти по паролю
|
||||
LoginWithPwButtonText: Войти с паролем
|
||||
ValidateTokenButtonText: Войти без пароля
|
||||
|
||||
PasswordlessPrompt:
|
||||
Title: Установка входа без пароля
|
||||
Description: Хотите настроить вход без пароля? (Например, используя методы аутентификации вашего устройства, такие как FaceID, Windows Hello или Fingerprint).
|
||||
DescriptionInit: Вам необходимо настроить вход без пароля. Воспользуйтесь ссылкой, которую вы получили, чтобы зарегистрировать своё устройство.
|
||||
PasswordlessButtonText: Перейти к входу без пароля
|
||||
NextButtonText: далее
|
||||
SkipButtonText: пропустить
|
||||
Title: Настройка входа без пароля
|
||||
Description: Хотите настроить вход без пароля? Вы сможете использовать методы аутентификации вашего устройства, такие как FaceID, Windows Hello или отпечаток пальца.
|
||||
DescriptionInit: Для начала настройки входа без пароля перейдите по полученной ссылке и зарегистрируйте своё устройство.
|
||||
PasswordlessButtonText: Настроить вход без пароля
|
||||
NextButtonText: Продолжить
|
||||
SkipButtonText: Пропустить
|
||||
|
||||
PasswordlessRegistration:
|
||||
Title: Установка входа без пароля
|
||||
Description: Добавьте свою аутентификацию, указав имя (например, MyMobilePhone, MacBook и так далее), а затем нажмите кнопку «Зарегистрировать вход без пароля» ниже.
|
||||
TokenNameLabel: Название устройства
|
||||
NotSupported: WebAuthN не поддерживается вашим браузером. Пожалуйста, убедитесь, что он обновлён или используйте другой (например, Chrome, Safari, Firefox)
|
||||
Title: Настройка входа без пароля
|
||||
Description: Укажите имя устройства (например, MyMobilePhone, MacBook и так далее), а затем нажмите кнопку «Зарегистрировать вход без пароля» ниже.
|
||||
TokenNameLabel: Имя устройства
|
||||
NotSupported: Ваш браузер не поддерживает WebAuthN. Пожалуйста, обновите его или используйте другой (например, Chrome, Safari, Firefox).
|
||||
RegisterTokenButtonText: Зарегистрировать вход без пароля
|
||||
ErrorRetry: Повторите попытку или выберите другой метод.
|
||||
|
||||
PasswordlessRegistrationDone:
|
||||
Title: Установка входа без пароля
|
||||
Description: Устройство для входа без пароля успешно добавлено.
|
||||
DescriptionClose: Теперь вы можете закрыть данное окно.
|
||||
NextButtonText: далее
|
||||
CancelButtonText: отмена
|
||||
Title: Вход без пароля настроен
|
||||
Description: Устройство для входа без пароля успешно зарегистрировано.
|
||||
DescriptionClose: Теперь вы можете закрыть это окно.
|
||||
NextButtonText: Продолжить
|
||||
CancelButtonText: Отмена
|
||||
|
||||
PasswordChange:
|
||||
Title: Изменение пароля
|
||||
Description: Измените ваш пароль. Введите старый и новый пароли.
|
||||
ExpiredDescription: Срок действия вашего пароля истек, и его необходимо изменить. Введите старый и новый пароль.
|
||||
OldPasswordLabel: Старый пароль
|
||||
Description: Введите текущий пароль и задайте новый.
|
||||
ExpiredDescription: Срок действия вашего пароля истёк. Пожалуйста, введите текущий пароль и задайте новый.
|
||||
OldPasswordLabel: Текущий пароль
|
||||
NewPasswordLabel: Новый пароль
|
||||
NewPasswordConfirmLabel: Подтверждение пароля
|
||||
CancelButtonText: отмена
|
||||
NextButtonText: далее
|
||||
Footer: Нижний колонтитул
|
||||
NewPasswordConfirmLabel: Повторите новый пароль
|
||||
CancelButtonText: Отмена
|
||||
NextButtonText: Продолжить
|
||||
Footer: Примечание
|
||||
|
||||
PasswordChangeDone:
|
||||
Title: Изменение пароля
|
||||
Description: Ваш пароль был успешно изменён.
|
||||
NextButtonText: далее
|
||||
NextButtonText: Продолжить
|
||||
|
||||
PasswordResetDone:
|
||||
Title: Ссылка для сброса пароля отправлена
|
||||
Description: Проверьте вашу электронную почту, чтобы сбросить пароль.
|
||||
NextButtonText: далее
|
||||
NextButtonText: Продолжить
|
||||
|
||||
EmailVerification:
|
||||
Title: Подтверждение электронной почты
|
||||
Description: Мы отправили вам письмо для подтверждения вашей электронной почты. Пожалуйста, введите полученный код в поле ниже.
|
||||
Description: Мы отправили письмо с кодом для подтверждения вашей электронной почты. Введите код ниже.
|
||||
CodeLabel: Код
|
||||
NextButtonText: далее
|
||||
ResendButtonText: повторно отправить код
|
||||
NextButtonText: Продолжить
|
||||
ResendButtonText: Отправить код ещё раз
|
||||
|
||||
EmailVerificationDone:
|
||||
Title: Подтверждение электронной почты
|
||||
Description: Ваша электронная почта была успешно подтверждена.
|
||||
NextButtonText: далее
|
||||
CancelButtonText: отмена
|
||||
LoginButtonText: вход
|
||||
Description: Ваша электронная почта успешно подтверждена.
|
||||
NextButtonText: Продолжить
|
||||
CancelButtonText: Отмена
|
||||
LoginButtonText: Войти
|
||||
|
||||
RegisterOption:
|
||||
Title: Способы регистрации
|
||||
Description: Выберите способ регистрации.
|
||||
RegisterUsernamePasswordButtonText: С паролем логина
|
||||
ExternalLoginDescription: или зарегистрируйтесь внешним пользователем
|
||||
LoginButtonText: вход
|
||||
RegisterUsernamePasswordButtonText: С логином и паролем
|
||||
ExternalLoginDescription: или зарегистрируйтесь с помощью внешнего пользователя
|
||||
LoginButtonText: Войти
|
||||
|
||||
RegistrationUser:
|
||||
Title: Регистрация
|
||||
Description: Введите ваши данные. Электронная почта будет использоваться в качестве логина.
|
||||
DescriptionOrgRegister: Введите ваши данные.
|
||||
Description: Введите свои данные. Электронная почта будет использоваться как логин.
|
||||
DescriptionOrgRegister: Введите свои данные.
|
||||
EmailLabel: Электронная почта
|
||||
UsernameLabel: Логин
|
||||
FirstnameLabel: Имя
|
||||
@ -263,24 +264,25 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Пол
|
||||
Female: Женский
|
||||
Male: Мужской
|
||||
Diverse: Другой / X
|
||||
PasswordLabel: Пароль
|
||||
PasswordConfirmLabel: Подтверждение пароля
|
||||
PasswordConfirmLabel: Повторите пароль
|
||||
TosAndPrivacyLabel: Условия использования
|
||||
TosConfirm: Я согласен с
|
||||
TosLinkText: Пользовательским соглашением
|
||||
PrivacyConfirm: Я согласен с
|
||||
PrivacyLinkText: Политикой конфиденциальности
|
||||
ExternalLogin: или зарегистрируйтесь внешним пользователем
|
||||
BackButtonText: вход
|
||||
NextButtonText: далее
|
||||
ExternalLogin: или зарегистрируйтесь с помощью внешнего пользователя
|
||||
BackButtonText: Войти
|
||||
NextButtonText: Продолжить
|
||||
|
||||
ExternalRegistrationUserOverview:
|
||||
Title: Регистрация внешнего пользователя
|
||||
Description: Мы получили ваши данные пользователя у выбранного провайдера. Теперь вы можете изменить или дополнить их.
|
||||
Description: Мы получили ваши данные от провайдера. Вы можете изменить или дополнить их.
|
||||
EmailLabel: Электронная почта
|
||||
UsernameLabel: Логин
|
||||
FirstnameLabel: Имя
|
||||
@ -305,14 +307,15 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Условия использования
|
||||
TosConfirm: Я согласен с
|
||||
TosLinkText: Пользовательским соглашением
|
||||
PrivacyConfirm: Я согласен с
|
||||
PrivacyLinkText: Политикой конфиденциальности
|
||||
ExternalLogin: или зарегистрируйтесь внешним пользователем
|
||||
BackButtonText: назад
|
||||
NextButtonText: сохранить
|
||||
ExternalLogin: или зарегистрируйтесь с помощью внешнего пользователя
|
||||
BackButtonText: Назад
|
||||
NextButtonText: Сохранить
|
||||
|
||||
RegistrationOrg:
|
||||
Title: Регистрация организации
|
||||
@ -323,7 +326,7 @@ RegistrationOrg:
|
||||
FirstnameLabel: Имя
|
||||
LastnameLabel: Фамилия
|
||||
PasswordLabel: Пароль
|
||||
PasswordConfirmLabel: Подтверждение пароля
|
||||
PasswordConfirmLabel: Повторите пароль
|
||||
TosAndPrivacyLabel: Условия использования
|
||||
TosConfirm: Я согласен с
|
||||
TosLinkText: Пользовательским соглашением
|
||||
@ -333,32 +336,32 @@ RegistrationOrg:
|
||||
|
||||
LoginSuccess:
|
||||
Title: Успешный вход
|
||||
AutoRedirectDescription: Вы будете автоматически перенаправлены в своё приложение. Если этого не произошло, нажмите кнопку ниже. После этого вы можете закрыть окно.
|
||||
RedirectedDescription: Теперь вы можете закрыть данное окно.
|
||||
NextButtonText: далее
|
||||
AutoRedirectDescription: Вы будете автоматически перенаправлены в приложение. Если этого не произошло, нажмите кнопку ниже.
|
||||
RedirectedDescription: Вы можете закрыть это окно.
|
||||
NextButtonText: Продолжить
|
||||
|
||||
LogoutDone:
|
||||
Title: Выход из системы
|
||||
Description: Вы успешно вышли из системы.
|
||||
LoginButtonText: вход
|
||||
LoginButtonText: Войти
|
||||
|
||||
LinkingUserPrompt:
|
||||
Title: Существующий пользователь найден
|
||||
Description: "Хотите ли вы связать существующую учетную запись:"
|
||||
LinkButtonText: Связь
|
||||
Title: Найден существующий пользователь
|
||||
Description: "Хотите связать эту учётную запись с существующей?"
|
||||
LinkButtonText: Связать
|
||||
OtherButtonText: Другие варианты
|
||||
|
||||
LinkingUsersDone:
|
||||
Title: Привязка пользователя
|
||||
Description: Привязка пользователя выполнена.
|
||||
CancelButtonText: отмена
|
||||
NextButtonText: далее
|
||||
Description: Привязка учётной записи выполнена успешно.
|
||||
CancelButtonText: Отмена
|
||||
NextButtonText: Продолжить
|
||||
|
||||
ExternalNotFound:
|
||||
Title: Внешний пользователь не найден
|
||||
Description: Внешний пользователь не найден. Вы можете привязать своего пользователя или автоматически зарегистрировать нового.
|
||||
Description: Мы не смогли найти указанного внешнего пользователя. Вы можете привязать существующую учетную запись или зарегистрировать нового пользователя.
|
||||
LinkButtonText: Привязать
|
||||
AutoRegisterButtonText: зарегистрировать
|
||||
AutoRegisterButtonText: Зарегистрировать
|
||||
TosAndPrivacyLabel: Условия использования
|
||||
TosConfirm: Я согласен с
|
||||
TosLinkText: Пользовательским соглашением
|
||||
@ -381,137 +384,138 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
|
||||
DeviceAuth:
|
||||
Title: Авторизация устройства
|
||||
UserCode:
|
||||
Label: Код пользователя
|
||||
Description: Введите код пользователя, представленный на устройстве.
|
||||
ButtonNext: следующий
|
||||
Description: Введите код, отображаемый на вашем устройстве.
|
||||
ButtonNext: Продолжить
|
||||
Action:
|
||||
Description: Предоставьте доступ к устройству.
|
||||
GrantDevice: Вы собираетесь предоставить устройство
|
||||
AccessToScopes: Доступ к следующим областям
|
||||
Description: Предоставьте устройству доступ к системе.
|
||||
GrantDevice: вы собираетесь предоставить устройству
|
||||
AccessToScopes: доступ к следующим областям
|
||||
Button:
|
||||
Allow: разрешать
|
||||
Deny: отрицать
|
||||
Allow: Разрешать
|
||||
Deny: Отклонить
|
||||
Done:
|
||||
Description: Договорились.
|
||||
Approved: Авторизация устройства одобрена. Теперь вы можете вернуться к устройству.
|
||||
Denied: Отказано в авторизации устройства. Теперь вы можете вернуться к устройству.
|
||||
Description: Операция завершена.
|
||||
Approved: Устройство успешно авторизовано. Теперь вы можете вернуться к устройству.
|
||||
Denied: Авторизация устройства отклонена. Теперь вы можете вернуться к устройству.
|
||||
|
||||
Footer:
|
||||
PoweredBy: На базе
|
||||
PoweredBy: Работает на основе
|
||||
Tos: Пользовательское соглашение
|
||||
PrivacyPolicy: Политика конфиденциальности
|
||||
Help: Помощь
|
||||
SupportEmail: Электронная почта службы поддержки
|
||||
|
||||
SignIn: Вход с помощью {{.Provider}}
|
||||
SignIn: Войти с помощью {{.Provider}}
|
||||
|
||||
Errors:
|
||||
Internal: Произошла внутренняя ошибка
|
||||
AuthRequest:
|
||||
NotFound: Не удалось обнаружить запрос авторизации
|
||||
UserAgentNotCorresponding: User Agent не соответствует
|
||||
UserAgentNotFound: ID User Agent не найден
|
||||
NotFound: authrequest не найден
|
||||
UserAgentNotCorresponding: User Agent не совпадает
|
||||
UserAgentNotFound: User Agent ID не найден
|
||||
TokenNotFound: Токен не найден
|
||||
RequestTypeNotSupported: Тип запроса не поддерживается
|
||||
MissingParameters: Отсутствуют обязательные параметры
|
||||
User:
|
||||
NotFound: Пользователь не может быть найден
|
||||
NotFound: Пользователь не найден
|
||||
AlreadyExists: Пользователь уже существует
|
||||
Inactive: Пользователь неактивен
|
||||
NotFoundOnOrg: Не удалось найти пользователя в выбранной организации
|
||||
NotAllowedOrg: Пользователь не является участником требуемой организации
|
||||
NotMatchingUserID: Пользователь не совпадает с пользователем в запросе авторизации
|
||||
UserIDMissing: UserID пустой
|
||||
NotAllowedOrg: Пользователь не является членом требуемой организации
|
||||
NotMatchingUserID: Указанный пользователь не совпадает с пользователем в authrequest
|
||||
UserIDMissing: Не указан UserID
|
||||
Invalid: Неверные данные пользователя
|
||||
DomainNotAllowedAsUsername: Домен уже зарезервирован и не может быть использован
|
||||
NotAllowedToLink: Пользователя не разрешено привязывать к внешнему провайдеру входа
|
||||
DomainNotAllowedAsUsername: Домен уже зарезервирован и не может быть использован в качестве логина
|
||||
NotAllowedToLink: Привязка пользователя к внешнему провайдеру запрещена
|
||||
Profile:
|
||||
NotFound: Профиль не найден
|
||||
NotChanged: Профиль не изменен
|
||||
Empty: Профиль пуст
|
||||
FirstNameEmpty: Имя в профиле пусто
|
||||
LastNameEmpty: Фамилия в профиле пуста
|
||||
FirstNameEmpty: Поле имени пусто
|
||||
LastNameEmpty: Поле фамилии пусто
|
||||
IDMissing: Отсутствует идентификатор профиля
|
||||
Email:
|
||||
NotFound: Электронная почта не найдена
|
||||
Invalid: Адрес электронной почты недействителен
|
||||
Invalid: Некорректный адрес электронной почты
|
||||
AlreadyVerified: Электронная почта уже подтверждена
|
||||
NotChanged: Адрес электронной почты не изменился
|
||||
Empty: Электронная почта пуста
|
||||
Empty: Электронная почта не указана
|
||||
IDMissing: Отсутствует идентификатор электронной почты
|
||||
Phone:
|
||||
NotFound: Телефон не найден
|
||||
Invalid: Телефон недействителен
|
||||
AlreadyVerified: Телефон уже проверен
|
||||
Empty: Телефон пуст
|
||||
NotChanged: Телефон не менялся
|
||||
NotFound: Номер телефона не найден
|
||||
Invalid: Неверный номер телефона
|
||||
AlreadyVerified: Номер телефона уже подтвержден
|
||||
Empty: Номер телефона не указан
|
||||
NotChanged: Номер телефона не изменился
|
||||
Address:
|
||||
NotFound: Адрес не найден
|
||||
NotChanged: Адрес не изменился
|
||||
Username:
|
||||
AlreadyExists: Имя пользователя уже занято
|
||||
Reserved: Имя пользователя уже занято
|
||||
Empty: Имя пользователя пусто
|
||||
AlreadyExists: Логин уже занят
|
||||
Reserved: Логин уже занят
|
||||
Empty: Логин не указан
|
||||
Password:
|
||||
ConfirmationWrong: Неверное подтверждение пароля
|
||||
Empty: Пароль пустой
|
||||
ConfirmationWrong: Указанные пароли не совпадают
|
||||
Empty: Пароль не указан
|
||||
Invalid: Неверный пароль
|
||||
InvalidAndLocked: Неверный пароль, пользователь заблокирован. Обратитесь к администратору.
|
||||
NotChanged: Пароль не изменен
|
||||
NotChanged: Пароль не изменился
|
||||
UsernameOrPassword:
|
||||
Invalid: Логин или пароль недействительны
|
||||
Invalid: Неверный логин или пароль
|
||||
PasswordComplexityPolicy:
|
||||
NotFound: Политика паролей не найдена
|
||||
MinLength: Пароль слишком короткий
|
||||
HasLower: Пароль должен содержать строчную букву
|
||||
HasUpper: Пароль должен содержать заглавную букву
|
||||
HasNumber: Пароль должен содержать цифру
|
||||
HasSymbol: Пароль должен содержать символ
|
||||
HasLower: Пароль должен содержать хотя бы одну строчную букву
|
||||
HasUpper: Пароль должен содержать хотя бы одну заглавную букву
|
||||
HasNumber: Пароль должен содержать хотя бы одну цифру
|
||||
HasSymbol: Пароль должен содержать хотя бы один специальный символ
|
||||
Code:
|
||||
Expired: Код истёк
|
||||
Invalid: Неверный код
|
||||
Empty: Код пустой
|
||||
CryptoCodeNil: Криптокод равен нулю
|
||||
NotFound: Не удалось найти код
|
||||
GeneratorAlgNotSupported: Неподдерживаемый алгоритм генератора
|
||||
Empty: Код не указан
|
||||
CryptoCodeNil: Пустой криптокод
|
||||
NotFound: Код не найден
|
||||
GeneratorAlgNotSupported: Алгоритм генерации кода не поддерживается
|
||||
EmailVerify:
|
||||
UserIDEmpty: UserID пустой
|
||||
UserIDEmpty: UserID не указан
|
||||
ExternalData:
|
||||
CouldNotRead: Внешние данные не могут быть обработаны корректно
|
||||
CouldNotRead: Не удалось обработать внешние данные
|
||||
MFA:
|
||||
NoProviders: Нет доступных многофакторных поставщиков
|
||||
NoProviders: Нет доступных методов многофакторной аутентификации
|
||||
OTP:
|
||||
AlreadyReady: Мультифактор OTP (OneTimePassword) уже настроен
|
||||
NotExisting: Мультифактор OTP (OneTimePassword) не существует
|
||||
AlreadyReady: OTP (OneTimePassword) уже настроен
|
||||
NotExisting: OTP (OneTimePassword) не существует
|
||||
InvalidCode: Неверный код
|
||||
NotReady: Мультифактор OTP (OneTimePassword) не готов
|
||||
NotReady: OTP (OneTimePassword) не готов
|
||||
Locked: Пользователь заблокирован
|
||||
SomethingWentWrong: Что-то пошло не так
|
||||
NotActive: Пользователь неактивен
|
||||
ExternalIDP:
|
||||
IDPTypeNotImplemented: IDP тип не реализован
|
||||
NotAllowed: Внешний провайдер входа запрещён
|
||||
IDPConfigIDEmpty: IDP ID пустой
|
||||
ExternalUserIDEmpty: External User ID пустой
|
||||
UserDisplayNameEmpty: Отображаемое имя пользователя пустое
|
||||
NoExternalUserData: Данные внешнего пользователя не получены
|
||||
CreationNotAllowed: Создание нового пользователя для данного провайдера не разрешено
|
||||
LinkingNotAllowed: Привязка пользователя с данным провайдером запрещена
|
||||
NoOptionAllowed: Ни создание, ни связывание не разрешены для этого провайдера. Пожалуйста, обратитесь к администратору.
|
||||
GrantRequired: Вход невозможен. Пользователь должен иметь хотя бы один допуск в приложении. Пожалуйста, свяжитесь с вашим администратором.
|
||||
ProjectRequired: Вход невозможен. Организация пользователя должна иметь допуск к проекту. Пожалуйста, свяжитесь с вашим администратором.
|
||||
IDPTypeNotImplemented: Тип внешнего провайдера не поддерживается
|
||||
NotAllowed: Доступ к внешнему провайдеру запрещен
|
||||
IDPConfigIDEmpty: Не указан идентификатор конфигурации провайдера
|
||||
ExternalUserIDEmpty: Не указан внешний идентификатор пользователя
|
||||
UserDisplayNameEmpty: Отображаемое имя пользователя не указано
|
||||
NoExternalUserData: Внешние данные пользователя отсутствуют
|
||||
CreationNotAllowed: Создание нового пользователя для этого провайдера запрещено
|
||||
LinkingNotAllowed: Привязка к этому провайдеру запрещена
|
||||
NoOptionAllowed: Ни создание, ни привязка пользователя к этому провайдеру невозможны. Обратитесь к администратору.
|
||||
GrantRequired: Вход невозможен. Пользователь должен иметь хотя бы один допуск к приложению. Обратитесь к администратору.
|
||||
ProjectRequired: Вход невозможен. Организация пользователя должна иметь доступ к проекту. Обратитесь к администратору.
|
||||
IdentityProvider:
|
||||
InvalidConfig: Недопустимая конфигурация поставщика идентификационных данных
|
||||
InvalidConfig: Некорректная конфигурация провайдера идентификации
|
||||
IAM:
|
||||
LockoutPolicy:
|
||||
NotExisting: Политика блокировки не существует
|
||||
NotExisting: Политика блокировки не найдена
|
||||
Org:
|
||||
LoginPolicy:
|
||||
RegistrationNotAllowed: Регистрация не допускается
|
||||
RegistrationNotAllowed: Регистрация запрещена
|
||||
DeviceAuth:
|
||||
NotExisting: Код пользователя не существует
|
||||
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: Kön
|
||||
Female: Man
|
||||
Male: Kvinna
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: Användarvillkor
|
||||
TosConfirm: Jag accepterar
|
||||
TosLinkText: Användarvillkoren
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: Tillgång från hårdvaruenhet
|
||||
UserCode:
|
||||
|
@ -264,6 +264,7 @@ RegistrationUser:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
GenderLabel: 性别
|
||||
Female: 女性
|
||||
Male: 男性
|
||||
@ -306,6 +307,7 @@ ExternalRegistrationUserOverview:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
TosAndPrivacyLabel: 条款和条款
|
||||
TosConfirm: 我接受
|
||||
TosLinkText: 服务条款
|
||||
@ -382,6 +384,7 @@ ExternalNotFound:
|
||||
Swedish: Svenska
|
||||
Indonesian: Bahasa Indonesia
|
||||
Hungarian: Magyar
|
||||
Korean: 한국어
|
||||
DeviceAuth:
|
||||
Title: 设备授权
|
||||
UserCode:
|
||||
|
@ -98,6 +98,8 @@
|
||||
</option>
|
||||
<option value="hu" id="hu" {{if (selectedLanguage "hu")}} selected {{end}}>{{t "ExternalNotFound.Hungarian"}}
|
||||
</option>
|
||||
<option value="ko" id="ko" {{if (selectedLanguage "ko")}} selected {{end}}>{{t "ExternalNotFound.Korean"}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/saml"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@ -511,10 +512,10 @@ func (c *Commands) UpdateInstanceAppleProvider(ctx context.Context, id string, p
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) AddInstanceSAMLProvider(ctx context.Context, provider SAMLProvider) (string, *domain.ObjectDetails, error) {
|
||||
func (c *Commands) AddInstanceSAMLProvider(ctx context.Context, provider *SAMLProvider) (id string, details *domain.ObjectDetails, err error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
id, err := c.idGenerator.Next()
|
||||
id, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -530,7 +531,7 @@ func (c *Commands) AddInstanceSAMLProvider(ctx context.Context, provider SAMLPro
|
||||
return id, pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) UpdateInstanceSAMLProvider(ctx context.Context, id string, provider SAMLProvider) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) UpdateInstanceSAMLProvider(ctx context.Context, id string, provider *SAMLProvider) (details *domain.ObjectDetails, err error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
writeModel := NewSAMLInstanceIDPWriteModel(instanceID, id)
|
||||
@ -1719,7 +1720,7 @@ func (c *Commands) prepareUpdateInstanceAppleProvider(a *instance.Aggregate, wri
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider SAMLProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider *SAMLProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-o07zjotgnd", "Errors.Invalid.Argument")
|
||||
@ -1734,6 +1735,9 @@ func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeMo
|
||||
if len(provider.Metadata) == 0 {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-3bi3esi16t", "Errors.Invalid.Argument")
|
||||
}
|
||||
if _, err := saml.ParseMetadata(provider.Metadata); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "INST-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@ -1772,7 +1776,7 @@ func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeMo
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider SAMLProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider *SAMLProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-7o3rq1owpm", "Errors.Invalid.Argument")
|
||||
@ -1790,6 +1794,9 @@ func (c *Commands) prepareUpdateInstanceSAMLProvider(a *instance.Aggregate, writ
|
||||
}
|
||||
provider.Metadata = data
|
||||
}
|
||||
if _, err := saml.ParseMetadata(provider.Metadata); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "INST-dsfj3kl2", "Errors.Project.App.SAMLMetadataFormat")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
|
@ -22,6 +22,73 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
validSAMLMetadata = []byte(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8080/saml/v2/metadata" ID="_8b02ecf6-aea4-4eda-96c6-190551f05b07">
|
||||
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<CanonicalizationMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
|
||||
<SignatureMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
|
||||
<Reference xmlns="http://www.w3.org/2000/09/xmldsig#" URI="#_8b02ecf6-aea4-4eda-96c6-190551f05b07">
|
||||
<Transforms xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<Transform xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform>
|
||||
<Transform xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
|
||||
</Transforms>
|
||||
<DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
|
||||
<DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#">Tyw4csdpNNq0E7wi5FXWdVNkdPNg+cM6kK21VB2+iF0=</DigestValue>
|
||||
</Reference>
|
||||
</SignedInfo>
|
||||
<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">hWQSYmnBJENy/okk2qRDuHaZiyqpDsdV6BF9/T/LNjUh/8z4dV2NEZvkNhFEyQ+bqdj+NmRWvKqpg1dtgNJxQc32+IsLQvXNYyhMCtyG570/jaTOtm8daV4NKJyTV7SdwM6yfXgubz5YCRTyV13W2gBIFYppIRImIv5NDcjz+lEmWhnrkw8G2wRSFUY7VvkDn9rgsTzw/Pnsw6hlzpjGDYPMPx3ux3kjFVevdhFGNo+VC7t9ozruuGyH3yue9Re6FZoqa4oyWaPSOwei0ZH6UNqkX93Eo5Y49QKwaO8Rm+kWsOhdTqebVmCc+SpWbbrZbQj4nSLgWGlvCkZSivmH7ezr4Ol1ZkRetQ92UQ7xJS7E0y6uXAGvdgpDnyqHCOFfhTS6yqltHtc3m7JZex327xkv6e69uAEOSiv++sifVUIE0h/5u3hZLvwmTPrkoRVY4wgZ4ieb86QPvhw4UPeYapOhCBk5RfjoEFIeYwPUw5rtOlpTyeBJiKMpH1+mDAoa+8HQytZoMrnnY1s612vINtY7jU5igMwIk6MitQpRGibnBVBHRc2A6aE+XS333ganFK9hX6TzNkpHUb66NINDZ8Rgb1thn3MABArGlomtM5/enrAixWExZp70TSElor7SBdBW57H7OZCYUCobZuPRDLsCO6LLKeVrbdygWeRqr/o=</SignatureValue>
|
||||
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIFIjCCAwqgAwIBAgICA7YwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjc0NFoXDTI1MTEyNzE2Mjc0NFowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIG1ldGFkYXRhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApEpYT7EjbRBp0Hw7PGCiSgUoJtwd2nwZOhGy5WZVWvraAtHzW5ih2B6UwEShjwCmRJZeKYEN9JKJbpAy2EdL/l2rm/pArVNvSQu6sN4izz5p2rd9NfHAO3/EcvYdrelWLQj8WQx6LVM282Z4wbclp8Jz1y8Ow43352hGfFVc1x8gauoNl5MAy4kdbvs8UqihqcRmEyIOWl6UwTApb+XIRSRz0Yop99Fv9ALJwfUppsx+d4j9rlRDvrQJMJz7GC/19L9INTbY0HsVEiTltdAWHwREwrpwxNJQt42p3W/zpf1mjwXd3qNNDZAr1t2POPP4SXd598kabBZ3EMWGGxFw+NYYajyjG5EFOZw09FFJn2jIcovejvigfdqem5DGPECvHefqcqHkBPGukI3RaotXpAYyAGfnV7slVytSW484IX3KloAJLICbETbFGGsGQzIDw8rUqWyaOCOttw2fVNDyRFUMHrGe1PhJ9qA1If+KCWYD0iJqF03rIEhdrvNSdQNYkRa0DdtpacQLpzQtqsUioODqX0W3uzLceJEXLBbU0ZEk8mWZM/auwMo3ycPNXDVwrb6AkUKar+sqSumUuixw7da3KF1/mynh6M2Eo4NRB16oUiyN0EYrit/RRJjsTdH+71cj0V+8KqO88cBpmm+lO6x4RM5xpOf/EwwQHivxgRkCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQBz+7R99uX1Us9T4BB2RK3RD9K8Q5foNmxJ8GbxpOQFL8IG1DE3FqBssciJkOsKY+1+Y6eow2TgmD9MxfCY444C8k8YDDjxIcs+4dEaWMUxA6NoEy378ciy0U1E6rpYLxWYTxXmsELyODWwTrRNIiWfbBD2m0w9HYbK6QvX6IYQqYoTOJJ3WJKsMCeQ8XhQsJYNINZEq8RsERY/aikOlTWN7ax4Mkr3bfnz1euXGClExCOM6ej4m2I33i4nyYBvvRkRRZRQCfkAQ+5WFVZoVXrQHNe/Oifit7tfLaDuybcjgkzzY3o0YbczzbdV69fVoj53VpR3QQOB+PCF/VJPUMtUFPEC05yH76g24KVBiM/Ws8GaERW1AxgupHSmvTY3GSiwDXQ2NzgDxUHfRHo8rxenJdEcPlGM0DstbUONDSFGLwvGDiidUVtqj1UB4yGL26bgtmwf61G4qsTn9PJMWdRmCeeOf7fmloRxTA0EEey3bulBBHim466tWHUhgOP+g1X0iE7CnwL8aJ//CCiQOAv1O6x5RLyxrmVTehPLr1T8qvnBmxpmuYU0kfbYpO3tMVe7VLabBx0cYh7izClZKHhgEj1w4aE9tIk7nqVAwvVocT3io8RrcKixlnBrFd7RYIuF3+RsYC/kYEgnZYKAig5u2TySgGmJ7nIS24FYW68WDg==</X509Certificate>
|
||||
</X509Data>
|
||||
</KeyInfo>
|
||||
</Signature>
|
||||
<IDPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" WantAuthnRequestsSigned="1" ID="_fd70402c-8a31-4a9a-a4a7-da526524c609" validUntil="2024-12-02T16:54:55.656Z" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<SingleSignOnService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/saml/v2/SSO"></SingleSignOnService>
|
||||
<SingleSignOnService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/saml/v2/SSO"></SingleSignOnService>
|
||||
<AttributeProfile>urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic</AttributeProfile>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="Email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="SurName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FullName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<SingleLogoutService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/saml/v2/SLO"></SingleLogoutService>
|
||||
<SingleLogoutService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/saml/v2/SLO"></SingleLogoutService>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
|
||||
<KeyDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" use="signing">
|
||||
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<KeyName>http://localhost:8080/saml/v2/metadata IDP signing</KeyName>
|
||||
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIFIjCCAwqgAwIBAgICA7QwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjUwMloXDTI1MTEyNzE2MjUwMlowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIHJlc3BvbnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lUgaI6AS/9xvM9DNSWK6Ho64LpK8UIioM26QfvAfeQ/I2pgX6SwWxEbd7qv+PkJzaFTjrXSlwOmWsJYma+UsdyFClaGFRyCgY8SWxPceandC8a+hQIDS/irLd9XF33RWp0b/09HjQl+n0HZ4teUFDUd2U1mUf3XCpn0+Ho316bmi6xSW6zaMy5RsbUl01hgWj2fgapAsGAHSBphwCE3Dz/9I/UfHWQw1k2/UTgjc9uIujcza6WgOxfsKluXYIOxwNKTfmzzOJMUwXz6GRgB2jhQI29MuKOZOITA7pXq5kZKf0lSRU8zKFTMJaK4zAHQ6f877Drr8XdAHemuXGZ2JdH/Dbdwarzy3YBMCWsAYlpeEvaVAdiSpyR7fAZktNuHd39Zg00Vlj2wdc44Vk5yVssW7pv5qnVZ7JTrXX2uBYFecLAXmplQ2ph1VdSXZLEDGgjiNA2T/fBj7G4/VjsuCBZFm1I0KCJp3HWEJx5dwwhSVc5wOJEzl7fMuPYMKWH/RM6P/7LnO1ulpdmiKPa4gHzdg3hDZn42NKcVt3UYf0phtxpWMrZp/DUEeizhckrC4ed6cfGtS3CUtJEqoycrCROJ5Hy+ONHl5Aqxt+JoPU+t/XATuctfPxQVcDr0itHzo2cjh/AVTU+IC7C0oQHSS9CC8Fp58UqbtYwFtSAd7ecCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQAp+IGZScVIbRdCq5HPjlYBPOY7UbL8ZXnlMW/HLELV9GndnULuFhnuQTIdA5dquCsk8RI1fKsScEV1rqWvHZeSo5nVbvUaPJctoD/4GACqE6F8axs1AgSOvpJMyuycjSzSh6gDM1z37Fdqc/2IRqgi7SKdDsfJpi8XW8LtErpp4kyE1rEXopsXG2fe1UH25bZpXraUqYvp61rwVUCazAtV/U7ARG5AnT0mPqzUriIPrfL+v/+2ntV/BSc8/uCqYnHbwpIwjPURCaxo1Pmm6EEkm+V/Ss4ieNwwkD2bLLLST1LoVMim7Ebfy53PEKpsznKsGlVSu0YYKUsStWQVpwhKQw0bQLCJHdpvZtZSDgS9RbSMZz+aY/fpoNx6wDvmMgtdrb3pVXZ8vPKdq9YDrGfFqP60QdZ3CuSHXCM/zX4742GgImJ4KYAcTuF1+BkGf5JLAJOUZBkfCQ/kBT5wr8+EotLxASOC6717whLBYMEG6N8osEk+LDqoJRTLqkzirJsyOHWChKK47yGkdS3HBIZfo91QrJwKpfATYziBjEnqipkTu+6jFylBIkxKTPye4b3vgcodZP8LSNVXAsMGTPNPJxzPWQ37ba4zMnYZ5iUerlaox/SNsn68DT6RajIb1A1JDq+HNFc3hQP2bzk2y5pCax8zo5swjdklnm4clfB2Lw==</X509Certificate>
|
||||
</X509Data>
|
||||
</KeyInfo>
|
||||
</KeyDescriptor>
|
||||
</IDPSSODescriptor>
|
||||
<AttributeAuthorityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b3fed381-af56-4160-abf5-5ffd1e21cf61" validUntil="2024-12-02T16:54:55.656Z" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<AttributeService xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/saml/v2/attribute"></AttributeService>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
|
||||
<AttributeProfile>urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic</AttributeProfile>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="Email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="SurName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="FullName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<Attribute xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><AttributeValue></AttributeValue></Attribute>
|
||||
<KeyDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" use="signing">
|
||||
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<KeyName>http://localhost:8080/saml/v2/metadata IDP signing</KeyName>
|
||||
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIFIjCCAwqgAwIBAgICA7QwDQYJKoZIhvcNAQELBQAwLDEQMA4GA1UEChMHWklUQURFTDEYMBYGA1UEAxMPWklUQURFTCBTQU1MIENBMB4XDTI0MTEyNzEwMjUwMloXDTI1MTEyNzE2MjUwMlowMjEQMA4GA1UEChMHWklUQURFTDEeMBwGA1UEAxMVWklUQURFTCBTQU1MIHJlc3BvbnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lUgaI6AS/9xvM9DNSWK6Ho64LpK8UIioM26QfvAfeQ/I2pgX6SwWxEbd7qv+PkJzaFTjrXSlwOmWsJYma+UsdyFClaGFRyCgY8SWxPceandC8a+hQIDS/irLd9XF33RWp0b/09HjQl+n0HZ4teUFDUd2U1mUf3XCpn0+Ho316bmi6xSW6zaMy5RsbUl01hgWj2fgapAsGAHSBphwCE3Dz/9I/UfHWQw1k2/UTgjc9uIujcza6WgOxfsKluXYIOxwNKTfmzzOJMUwXz6GRgB2jhQI29MuKOZOITA7pXq5kZKf0lSRU8zKFTMJaK4zAHQ6f877Drr8XdAHemuXGZ2JdH/Dbdwarzy3YBMCWsAYlpeEvaVAdiSpyR7fAZktNuHd39Zg00Vlj2wdc44Vk5yVssW7pv5qnVZ7JTrXX2uBYFecLAXmplQ2ph1VdSXZLEDGgjiNA2T/fBj7G4/VjsuCBZFm1I0KCJp3HWEJx5dwwhSVc5wOJEzl7fMuPYMKWH/RM6P/7LnO1ulpdmiKPa4gHzdg3hDZn42NKcVt3UYf0phtxpWMrZp/DUEeizhckrC4ed6cfGtS3CUtJEqoycrCROJ5Hy+ONHl5Aqxt+JoPU+t/XATuctfPxQVcDr0itHzo2cjh/AVTU+IC7C0oQHSS9CC8Fp58UqbtYwFtSAd7ecCAwEAAaNIMEYwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFIzl7uckcPWldirXeOFL3rH6K8FLMA0GCSqGSIb3DQEBCwUAA4ICAQAp+IGZScVIbRdCq5HPjlYBPOY7UbL8ZXnlMW/HLELV9GndnULuFhnuQTIdA5dquCsk8RI1fKsScEV1rqWvHZeSo5nVbvUaPJctoD/4GACqE6F8axs1AgSOvpJMyuycjSzSh6gDM1z37Fdqc/2IRqgi7SKdDsfJpi8XW8LtErpp4kyE1rEXopsXG2fe1UH25bZpXraUqYvp61rwVUCazAtV/U7ARG5AnT0mPqzUriIPrfL+v/+2ntV/BSc8/uCqYnHbwpIwjPURCaxo1Pmm6EEkm+V/Ss4ieNwwkD2bLLLST1LoVMim7Ebfy53PEKpsznKsGlVSu0YYKUsStWQVpwhKQw0bQLCJHdpvZtZSDgS9RbSMZz+aY/fpoNx6wDvmMgtdrb3pVXZ8vPKdq9YDrGfFqP60QdZ3CuSHXCM/zX4742GgImJ4KYAcTuF1+BkGf5JLAJOUZBkfCQ/kBT5wr8+EotLxASOC6717whLBYMEG6N8osEk+LDqoJRTLqkzirJsyOHWChKK47yGkdS3HBIZfo91QrJwKpfATYziBjEnqipkTu+6jFylBIkxKTPye4b3vgcodZP8LSNVXAsMGTPNPJxzPWQ37ba4zMnYZ5iUerlaox/SNsn68DT6RajIb1A1JDq+HNFc3hQP2bzk2y5pCax8zo5swjdklnm4clfB2Lw==</X509Certificate>
|
||||
</X509Data>
|
||||
</KeyInfo>
|
||||
</KeyDescriptor>
|
||||
</AttributeAuthorityDescriptor>
|
||||
</EntityDescriptor>`)
|
||||
)
|
||||
|
||||
func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
@ -5180,7 +5247,7 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
provider SAMLProvider
|
||||
provider *SAMLProvider
|
||||
}
|
||||
type res struct {
|
||||
id string
|
||||
@ -5201,7 +5268,7 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -5210,14 +5277,14 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata",
|
||||
"no metadata",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
@ -5227,6 +5294,25 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata, error",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
@ -5236,7 +5322,7 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -5258,9 +5344,9 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -5277,7 +5363,7 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -5304,9 +5390,9 @@ func TestCommandSide_AddInstanceSAMLIDP(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
Binding: "binding",
|
||||
WithSignedRequest: true,
|
||||
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
||||
@ -5356,7 +5442,7 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
id string
|
||||
provider SAMLProvider
|
||||
provider *SAMLProvider
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -5375,7 +5461,7 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -5391,7 +5477,7 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -5400,14 +5486,14 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata",
|
||||
"no metadata",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
@ -5417,6 +5503,25 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata, error",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "INST-dsfj3kl2", "Errors.Project.App.SAMLMetadataFormat"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
@ -5427,9 +5532,9 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -5445,7 +5550,7 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
instance.NewSAMLIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -5465,9 +5570,9 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -5505,7 +5610,7 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
"id1",
|
||||
[]idp.SAMLIDPChanges{
|
||||
idp.ChangeSAMLName("new name"),
|
||||
idp.ChangeSAMLMetadata([]byte("new metadata")),
|
||||
idp.ChangeSAMLMetadata(validSAMLMetadata),
|
||||
idp.ChangeSAMLBinding("new binding"),
|
||||
idp.ChangeSAMLWithSignedRequest(true),
|
||||
idp.ChangeSAMLNameIDFormat(gu.Ptr(domain.SAMLNameIDFormatTransient)),
|
||||
@ -5527,9 +5632,9 @@ func TestCommandSide_UpdateInstanceGenericSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "new name",
|
||||
Metadata: []byte("new metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
Binding: "new binding",
|
||||
WithSignedRequest: true,
|
||||
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/saml"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@ -446,9 +447,9 @@ func (c *Commands) UpdateOrgLDAPProvider(ctx context.Context, resourceOwner, id
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) AddOrgSAMLProvider(ctx context.Context, resourceOwner string, provider SAMLProvider) (string, *domain.ObjectDetails, error) {
|
||||
func (c *Commands) AddOrgSAMLProvider(ctx context.Context, resourceOwner string, provider *SAMLProvider) (id string, details *domain.ObjectDetails, err error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
id, err := c.idGenerator.Next()
|
||||
id, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -464,7 +465,7 @@ func (c *Commands) AddOrgSAMLProvider(ctx context.Context, resourceOwner string,
|
||||
return id, pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) UpdateOrgSAMLProvider(ctx context.Context, resourceOwner, id string, provider SAMLProvider) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) UpdateOrgSAMLProvider(ctx context.Context, resourceOwner, id string, provider *SAMLProvider) (details *domain.ObjectDetails, err error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
writeModel := NewSAMLOrgIDPWriteModel(resourceOwner, id)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgSAMLProvider(orgAgg, writeModel, provider))
|
||||
@ -1703,7 +1704,7 @@ func (c *Commands) prepareUpdateOrgAppleProvider(a *org.Aggregate, writeModel *O
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddOrgSAMLProvider(a *org.Aggregate, writeModel *OrgSAMLIDPWriteModel, provider SAMLProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddOrgSAMLProvider(a *org.Aggregate, writeModel *OrgSAMLIDPWriteModel, provider *SAMLProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "ORG-957lr0f8u3", "Errors.Invalid.Argument")
|
||||
@ -1718,6 +1719,9 @@ func (c *Commands) prepareAddOrgSAMLProvider(a *org.Aggregate, writeModel *OrgSA
|
||||
}
|
||||
provider.Metadata = data
|
||||
}
|
||||
if _, err := saml.ParseMetadata(provider.Metadata); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "ORG-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@ -1755,7 +1759,7 @@ func (c *Commands) prepareAddOrgSAMLProvider(a *org.Aggregate, writeModel *OrgSA
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateOrgSAMLProvider(a *org.Aggregate, writeModel *OrgSAMLIDPWriteModel, provider SAMLProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateOrgSAMLProvider(a *org.Aggregate, writeModel *OrgSAMLIDPWriteModel, provider *SAMLProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "ORG-wwdwdlaya0", "Errors.Invalid.Argument")
|
||||
@ -1773,6 +1777,9 @@ func (c *Commands) prepareUpdateOrgSAMLProvider(a *org.Aggregate, writeModel *Or
|
||||
if provider.Metadata == nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "ORG-j6spncd74m", "Errors.Invalid.Argument")
|
||||
}
|
||||
if _, err := saml.ParseMetadata(provider.Metadata); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "ORG-SFqqh42", "Errors.Project.App.SAMLMetadataFormat")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
|
@ -5348,7 +5348,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
provider SAMLProvider
|
||||
provider *SAMLProvider
|
||||
}
|
||||
type res struct {
|
||||
id string
|
||||
@ -5370,7 +5370,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -5379,7 +5379,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata",
|
||||
"no metadata",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
@ -5387,7 +5387,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
@ -5397,6 +5397,26 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata, fail on error",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
@ -5406,7 +5426,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -5428,9 +5448,9 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -5447,7 +5467,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -5475,9 +5495,9 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
Binding: "binding",
|
||||
WithSignedRequest: true,
|
||||
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
||||
@ -5528,7 +5548,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
id string
|
||||
provider SAMLProvider
|
||||
provider *SAMLProvider
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -5548,7 +5568,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -5565,7 +5585,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -5574,7 +5594,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata",
|
||||
"no metadata",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
@ -5582,7 +5602,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
@ -5592,6 +5612,26 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata, error",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SFqqh42", "Errors.Project.App.SAMLMetadataFormat"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
@ -5603,9 +5643,9 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -5623,7 +5663,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@ -5644,9 +5684,9 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -5684,7 +5724,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
"id1",
|
||||
[]idp.SAMLIDPChanges{
|
||||
idp.ChangeSAMLName("new name"),
|
||||
idp.ChangeSAMLMetadata([]byte("new metadata")),
|
||||
idp.ChangeSAMLMetadata(validSAMLMetadata),
|
||||
idp.ChangeSAMLBinding("new binding"),
|
||||
idp.ChangeSAMLWithSignedRequest(true),
|
||||
idp.ChangeSAMLNameIDFormat(gu.Ptr(domain.SAMLNameIDFormatTransient)),
|
||||
@ -5707,9 +5747,9 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "new name",
|
||||
Metadata: []byte("new metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
Binding: "new binding",
|
||||
WithSignedRequest: true,
|
||||
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
@ -79,10 +78,8 @@ func (c *Commands) createHumanTOTP(ctx context.Context, userID, resourceOwner st
|
||||
logging.WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("unable to get human for loginname")
|
||||
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-SqyJz", "Errors.User.NotFound")
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserCredentialWrite, human.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUserCredentials(ctx, human.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
org, err := c.getOrg(ctx, human.ResourceOwner)
|
||||
if err != nil {
|
||||
@ -139,10 +136,8 @@ func (c *Commands) HumanCheckMFATOTPSetup(ctx context.Context, userID, code, use
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserCredentialWrite, existingOTP.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUserCredentials(ctx, existingOTP.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingOTP.State == domain.MFAStateUnspecified || existingOTP.State == domain.MFAStateRemoved {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-3Mif9s", "Errors.User.MFA.OTP.NotExisting")
|
||||
@ -242,10 +237,8 @@ func (c *Commands) HumanRemoveTOTP(ctx context.Context, userID, resourceOwner st
|
||||
if existingOTP.State == domain.MFAStateUnspecified || existingOTP.State == domain.MFAStateRemoved {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-Hd9sd", "Errors.User.MFA.OTP.NotExisting")
|
||||
}
|
||||
if userID != authz.GetCtxData(ctx).UserID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserWrite, existingOTP.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUser(ctx, existingOTP.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userAgg := UserAggregateFromWriteModel(&existingOTP.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, user.NewHumanOTPRemovedEvent(ctx, userAgg))
|
||||
@ -286,10 +279,8 @@ func (c *Commands) addHumanOTPSMS(ctx context.Context, userID, resourceOwner str
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserCredentialWrite, otpWriteModel.ResourceOwner(), userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUserCredentials(ctx, otpWriteModel.ResourceOwner(), userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if otpWriteModel.otpAdded {
|
||||
return nil, zerrors.ThrowAlreadyExists(nil, "COMMAND-Ad3g2", "Errors.User.MFA.OTP.AlreadyReady")
|
||||
@ -318,10 +309,8 @@ func (c *Commands) RemoveHumanOTPSMS(ctx context.Context, userID, resourceOwner
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userID != authz.GetCtxData(ctx).UserID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserWrite, existingOTP.WriteModel.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUser(ctx, existingOTP.WriteModel.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingOTP.otpAdded {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-Sr3h3", "Errors.User.MFA.OTP.NotExisting")
|
||||
@ -420,10 +409,8 @@ func (c *Commands) addHumanOTPEmail(ctx context.Context, userID, resourceOwner s
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserCredentialWrite, otpWriteModel.ResourceOwner(), userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUserCredentials(ctx, otpWriteModel.ResourceOwner(), userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if otpWriteModel.otpAdded {
|
||||
return nil, zerrors.ThrowAlreadyExists(nil, "COMMAND-MKL2s", "Errors.User.MFA.OTP.AlreadyReady")
|
||||
@ -452,10 +439,8 @@ func (c *Commands) RemoveHumanOTPEmail(ctx context.Context, userID, resourceOwne
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userID != authz.GetCtxData(ctx).UserID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserWrite, existingOTP.WriteModel.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUser(ctx, existingOTP.WriteModel.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingOTP.otpAdded {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-b312D", "Errors.User.MFA.OTP.NotExisting")
|
||||
|
@ -110,7 +110,7 @@ type setPasswordVerification func(ctx context.Context) (newEncodedPassword strin
|
||||
// setPasswordWithPermission returns a permission check as [setPasswordVerification] implementation
|
||||
func (c *Commands) setPasswordWithPermission(userID, orgID string) setPasswordVerification {
|
||||
return func(ctx context.Context) (_ string, err error) {
|
||||
return "", c.checkPermission(ctx, domain.PermissionUserWrite, orgID, userID)
|
||||
return "", c.checkPermissionUpdateUser(ctx, orgID, userID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
@ -146,10 +145,8 @@ func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner,
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err = c.checkPermission(ctx, domain.PermissionUserCredentialWrite, user.ResourceOwner, userID); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUserCredentials(ctx, user.ResourceOwner, userID); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
org, err := c.getOrg(ctx, user.ResourceOwner)
|
||||
if err != nil {
|
||||
@ -603,10 +600,9 @@ func (c *Commands) removeHumanWebAuthN(ctx context.Context, userID, webAuthNID,
|
||||
if existingWebAuthN.State == domain.MFAStateUnspecified || existingWebAuthN.State == domain.MFAStateRemoved {
|
||||
return nil, zerrors.ThrowNotFound(nil, "COMMAND-DAfb2", "Errors.User.WebAuthN.NotFound")
|
||||
}
|
||||
if userID != authz.GetCtxData(ctx).UserID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserWrite, existingWebAuthN.ResourceOwner, existingWebAuthN.AggregateID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.checkPermissionUpdateUser(ctx, existingWebAuthN.ResourceOwner, existingWebAuthN.AggregateID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userAgg := UserAggregateFromWriteModel(&existingWebAuthN.WriteModel)
|
||||
|
@ -127,6 +127,16 @@ func (c *Commands) checkPermissionUpdateUser(ctx context.Context, resourceOwner,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkPermissionUpdateUserCredentials(ctx context.Context, resourceOwner, userID string) error {
|
||||
if userID != "" && userID == authz.GetCtxData(ctx).UserID {
|
||||
return nil
|
||||
}
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserCredentialWrite, resourceOwner, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) checkPermissionDeleteUser(ctx context.Context, resourceOwner, userID string) error {
|
||||
if userID != "" && userID == authz.GetCtxData(ctx).UserID {
|
||||
return nil
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
@ -118,10 +117,8 @@ func (c *Commands) changeUserEmailWithGeneratorEvents(ctx context.Context, userI
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err = c.checkPermission(ctx, domain.PermissionUserWrite, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = cmd.Change(ctx, domain.EmailAddress(email)); err != nil {
|
||||
return nil, err
|
||||
@ -137,10 +134,8 @@ func (c *Commands) resendUserEmailCodeWithGeneratorEvents(ctx context.Context, u
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err = c.checkPermission(ctx, domain.PermissionUserWrite, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cmd.model.Code == nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(err, "EMAIL-5w5ilin4yt", "Errors.User.Code.Empty")
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
@ -74,10 +73,8 @@ func (c *Commands) ResendInviteCode(ctx context.Context, userID, resourceOwner,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err := c.checkPermission(ctx, domain.PermissionUserWrite, existingCode.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkPermissionUpdateUser(ctx, existingCode.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existingCode.UserState.Exists() {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-H3b2a", "Errors.User.NotFound")
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
@ -18,7 +17,7 @@ import (
|
||||
// RegisterUserPasskey creates a passkey registration for the current authenticated user.
|
||||
// UserID, usually taken from the request is compared against the user ID in the context.
|
||||
func (c *Commands) RegisterUserPasskey(ctx context.Context, userID, resourceOwner, rpID string, authenticator domain.AuthenticatorAttachment) (*domain.WebAuthNRegistrationDetails, error) {
|
||||
if err := authz.UserIDInCTX(ctx, userID); err != nil {
|
||||
if err := c.checkPermissionUpdateUserCredentials(ctx, resourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.registerUserPasskey(ctx, userID, resourceOwner, rpID, authenticator)
|
||||
|
@ -34,8 +34,9 @@ func TestCommands_RegisterUserPasskey(t *testing.T) {
|
||||
}
|
||||
userAgg := &user.NewAggregate("user1", "org1").Aggregate
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
checkPermission domain.PermissionCheck
|
||||
}
|
||||
type args struct {
|
||||
userID string
|
||||
@ -51,18 +52,22 @@ func TestCommands_RegisterUserPasskey(t *testing.T) {
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "wrong user",
|
||||
name: "no permission",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(),
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
},
|
||||
args: args{
|
||||
userID: "foo",
|
||||
resourceOwner: "org1",
|
||||
authenticator: domain.AuthenticatorAttachmentCrossPlattform,
|
||||
},
|
||||
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTH-Bohd2", "Errors.User.UserIDWrong"),
|
||||
wantErr: zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
||||
},
|
||||
{
|
||||
name: "get human passwordless error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilterError(io.ErrClosedPipe),
|
||||
),
|
||||
},
|
||||
@ -76,7 +81,7 @@ func TestCommands_RegisterUserPasskey(t *testing.T) {
|
||||
{
|
||||
name: "id generator error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(), // getHumanPasswordlessTokens
|
||||
expectFilter(eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(ctx,
|
||||
@ -118,9 +123,10 @@ func TestCommands_RegisterUserPasskey(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
webauthnConfig: webauthnConfig,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
webauthnConfig: webauthnConfig,
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
}
|
||||
_, err := c.RegisterUserPasskey(ctx, tt.args.userID, tt.args.resourceOwner, tt.args.rpID, tt.args.authenticator)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
@ -50,10 +49,8 @@ func (c *Commands) requestPasswordReset(ctx context.Context, userID string, retu
|
||||
if model.UserState == domain.UserStateInitial {
|
||||
return nil, nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfe4g", "Errors.User.NotInitialised")
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err = c.checkPermission(ctx, domain.PermissionUserWrite, model.ResourceOwner, userID); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err = c.checkPermissionUpdateUser(ctx, model.ResourceOwner, userID); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var passwordCode *EncryptedCode
|
||||
var generatorID string
|
||||
|
@ -82,10 +82,8 @@ func (c *Commands) changeUserPhoneWithGenerator(ctx context.Context, userID, pho
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err = c.checkPermission(ctx, domain.PermissionUserWrite, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = cmd.Change(ctx, domain.PhoneNumber(phone)); err != nil {
|
||||
return nil, err
|
||||
@ -104,10 +102,8 @@ func (c *Commands) resendUserPhoneCodeWithGenerator(ctx context.Context, userID
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != userID {
|
||||
if err = c.checkPermission(ctx, domain.PermissionUserWrite, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = c.checkPermissionUpdateUser(ctx, cmd.aggregate.ResourceOwner, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cmd.model.Code == nil && cmd.model.GeneratorID == "" {
|
||||
return nil, zerrors.ThrowPreconditionFailed(err, "PHONE-5xrra88eq8", "Errors.User.Code.Empty")
|
||||
|
@ -1,15 +1,19 @@
|
||||
package saml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/crewjam/saml"
|
||||
"github.com/crewjam/saml/samlsp"
|
||||
"golang.org/x/text/encoding/ianaindex"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/idp"
|
||||
@ -104,6 +108,41 @@ func WithEntityID(entityID string) ProviderOpts {
|
||||
}
|
||||
}
|
||||
|
||||
// ParseMetadata parses the metadata with the provided XML encoding and returns the EntityDescriptor
|
||||
func ParseMetadata(metadata []byte) (*saml.EntityDescriptor, error) {
|
||||
entityDescriptor := new(saml.EntityDescriptor)
|
||||
reader := bytes.NewReader(metadata)
|
||||
decoder := xml.NewDecoder(reader)
|
||||
decoder.CharsetReader = func(charset string, reader io.Reader) (io.Reader, error) {
|
||||
enc, err := ianaindex.IANA.Encoding(charset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return enc.NewDecoder().Reader(reader), nil
|
||||
}
|
||||
if err := decoder.Decode(entityDescriptor); err != nil {
|
||||
if err.Error() == "expected element type <EntityDescriptor> but have <EntitiesDescriptor>" {
|
||||
// reset reader to start of metadata so we can try to parse it as an EntitiesDescriptor
|
||||
if _, err := reader.Seek(0, io.SeekStart); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entities := &saml.EntitiesDescriptor{}
|
||||
if err := decoder.Decode(entities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, e := range entities.EntityDescriptors {
|
||||
if len(e.IDPSSODescriptors) > 0 {
|
||||
return &entities.EntityDescriptors[i], nil
|
||||
}
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(nil, "SAML-Ejoi3r2", "no entity found with IDPSSODescriptor")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return entityDescriptor, nil
|
||||
}
|
||||
|
||||
func New(
|
||||
name string,
|
||||
rootURLStr string,
|
||||
@ -112,8 +151,8 @@ func New(
|
||||
key []byte,
|
||||
options ...ProviderOpts,
|
||||
) (*Provider, error) {
|
||||
entityDescriptor := new(saml.EntityDescriptor)
|
||||
if err := xml.Unmarshal(metadata, entityDescriptor); err != nil {
|
||||
entityDescriptor, err := ParseMetadata(metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyPair, err := tls.X509KeyPair(certificate, key)
|
||||
@ -180,6 +219,7 @@ func (p *Provider) GetSP() (*samlsp.Middleware, error) {
|
||||
if p.binding != "" {
|
||||
sp.Binding = p.binding
|
||||
}
|
||||
sp.ServiceProvider.MetadataValidDuration = time.Until(sp.ServiceProvider.Certificate.NotAfter)
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package saml
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
|
||||
"github.com/crewjam/saml"
|
||||
@ -10,6 +11,7 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/saml/requesttracker"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestProvider_Options(t *testing.T) {
|
||||
@ -170,3 +172,111 @@ func TestProvider_Options(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
type args struct {
|
||||
metadata []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *saml.EntityDescriptor
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
"invalid",
|
||||
args{
|
||||
metadata: []byte(`<Test></Test>`),
|
||||
},
|
||||
nil,
|
||||
xml.UnmarshalError("expected element type <EntityDescriptor> but have <Test>"),
|
||||
},
|
||||
{
|
||||
"valid entity descriptor",
|
||||
args{
|
||||
metadata: []byte(`<?xml version="1.0" encoding="UTF-8"?><EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8000/metadata"><IDPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"><SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8000/sso"></SingleSignOnService></IDPSSODescriptor></EntityDescriptor>`),
|
||||
},
|
||||
&saml.EntityDescriptor{
|
||||
EntityID: "http://localhost:8000/metadata",
|
||||
IDPSSODescriptors: []saml.IDPSSODescriptor{
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "IDPSSODescriptor",
|
||||
},
|
||||
SingleSignOnServices: []saml.Endpoint{
|
||||
{
|
||||
Binding: saml.HTTPRedirectBinding,
|
||||
Location: "http://localhost:8000/sso",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid entity descriptor, non utf-8",
|
||||
args{
|
||||
metadata: []byte(`<?xml version="1.0" encoding="windows-1252"?><EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8000/metadata"><IDPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"><SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8000/sso"></SingleSignOnService></IDPSSODescriptor></EntityDescriptor>`),
|
||||
},
|
||||
&saml.EntityDescriptor{
|
||||
EntityID: "http://localhost:8000/metadata",
|
||||
IDPSSODescriptors: []saml.IDPSSODescriptor{
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "IDPSSODescriptor",
|
||||
},
|
||||
SingleSignOnServices: []saml.Endpoint{
|
||||
{
|
||||
Binding: saml.HTTPRedirectBinding,
|
||||
Location: "http://localhost:8000/sso",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"entities descriptor without IDPSSODescriptor",
|
||||
args{
|
||||
metadata: []byte(`<?xml version="1.0" encoding="UTF-8"?><EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"><EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8000/metadata"></EntityDescriptor></EntitiesDescriptor>`),
|
||||
},
|
||||
nil,
|
||||
zerrors.ThrowInternal(nil, "SAML-Ejoi3r2", "no entity found with IDPSSODescriptor"),
|
||||
},
|
||||
{
|
||||
"valid entities descriptor",
|
||||
args{
|
||||
metadata: []byte(`<?xml version="1.0" encoding="UTF-8"?><EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"><EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8000/metadata"><IDPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"><SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8000/sso"></SingleSignOnService></IDPSSODescriptor></EntityDescriptor></EntitiesDescriptor>`),
|
||||
},
|
||||
&saml.EntityDescriptor{
|
||||
EntityID: "http://localhost:8000/metadata",
|
||||
IDPSSODescriptors: []saml.IDPSSODescriptor{
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "IDPSSODescriptor",
|
||||
},
|
||||
SingleSignOnServices: []saml.Endpoint{
|
||||
{
|
||||
Binding: saml.HTTPRedirectBinding,
|
||||
Location: "http://localhost:8000/sso",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ParseMetadata(tt.args.metadata)
|
||||
assert.ErrorIs(t, err, tt.wantErr)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/crewjam/saml"
|
||||
"github.com/crewjam/saml/samlsp"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/idp"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
@ -71,7 +70,7 @@ func (s *Session) FetchUser(ctx context.Context) (user idp.User, err error) {
|
||||
if err != nil {
|
||||
invalidRespErr := new(saml.InvalidResponseError)
|
||||
if errors.As(err, &invalidRespErr) {
|
||||
logging.WithError(invalidRespErr.PrivateErr).Info("invalid SAML response details")
|
||||
return nil, zerrors.ThrowInvalidArgument(invalidRespErr.PrivateErr, "SAML-ajl3irfs", "Errors.Intent.ResponseInvalid")
|
||||
}
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "SAML-nuo0vphhh9", "Errors.Intent.ResponseInvalid")
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ func TestSession_FetchUser(t *testing.T) {
|
||||
requestID: "id-b22c90db88bf01d82ffb0a7b6fe25ac9fcb2c679",
|
||||
},
|
||||
want: want{
|
||||
err: zerrors.ThrowInvalidArgument(nil, "SAML-nuo0vphhh9", "Errors.Intent.ResponseInvalid"),
|
||||
err: zerrors.ThrowInvalidArgument(nil, "SAML-ajl3irfs", "Errors.Intent.ResponseInvalid"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
68
internal/notification/static/i18n/ko.yaml
Normal file
68
internal/notification/static/i18n/ko.yaml
Normal file
@ -0,0 +1,68 @@
|
||||
InitCode:
|
||||
Title: 사용자 초기화
|
||||
PreHeader: 사용자 초기화
|
||||
Subject: 사용자 초기화
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 사용자가 생성되었습니다. 로그인하려면 사용자 이름 {{.PreferredLoginName}}을 사용하세요. 초기화 프로세스를 완료하려면 아래 버튼을 클릭하세요. (코드 {{.Code}}) 이 메일을 요청하지 않으셨다면 무시하셔도 됩니다.
|
||||
ButtonText: 초기화 완료
|
||||
PasswordReset:
|
||||
Title: 비밀번호 재설정
|
||||
PreHeader: 비밀번호 재설정
|
||||
Subject: 비밀번호 재설정
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 비밀번호 재설정 요청을 받았습니다. 비밀번호를 재설정하려면 아래 버튼을 사용하세요. (코드 {{.Code}}) 이 메일을 요청하지 않으셨다면 무시하셔도 됩니다.
|
||||
ButtonText: 비밀번호 재설정
|
||||
VerifyEmail:
|
||||
Title: 이메일 인증
|
||||
PreHeader: 이메일 인증
|
||||
Subject: 이메일 인증
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 새 이메일이 추가되었습니다. 이메일을 인증하려면 아래 버튼을 사용하세요. (코드 {{.Code}}) 새로운 이메일을 추가하지 않으셨다면 이 메일을 무시하세요.
|
||||
ButtonText: 이메일 인증
|
||||
VerifyPhone:
|
||||
Title: 전화번호 인증
|
||||
PreHeader: 전화번호 인증
|
||||
Subject: 전화번호 인증
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 새 전화번호가 추가되었습니다. 다음 코드를 사용하여 인증하세요 {{.Code}}
|
||||
ButtonText: 전화번호 인증
|
||||
VerifyEmailOTP:
|
||||
Title: 일회용 비밀번호 인증
|
||||
PreHeader: 일회용 비밀번호 인증
|
||||
Subject: 일회용 비밀번호 인증
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 인증하려면 다음 일회용 비밀번호 {{.OTP}}를 5분 이내에 사용하거나 "인증" 버튼을 클릭하세요.
|
||||
ButtonText: 인증
|
||||
VerifySMSOTP:
|
||||
Text: >-
|
||||
{{.OTP}}는 {{ .Domain }}의 일회용 비밀번호입니다. 다음 {{.Expiry}} 이내에 사용하세요.
|
||||
|
||||
@{{.Domain}} #{{.OTP}}
|
||||
DomainClaimed:
|
||||
Title: 조직에서 도메인을 소유하게 되었습니다
|
||||
PreHeader: 이메일 / 사용자 이름 변경
|
||||
Subject: 조직에서 도메인을 소유하게 되었습니다
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 도메인 {{.Domain}} 은(는) 조직에서 소유하게 되었습니다. 현재 사용자인 {{.Username}}은 이 조직의 구성원이 아닙니다. 따라서 로그인할 때 이메일을 변경해야 합니다. 이 로그인용으로 임시 사용자 이름 ({{.TempUsername}})을 생성했습니다.
|
||||
ButtonText: 로그인
|
||||
PasswordlessRegistration:
|
||||
Title: 비밀번호 없는 로그인 추가
|
||||
PreHeader: 비밀번호 없는 로그인 추가
|
||||
Subject: 비밀번호 없는 로그인 추가
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 비밀번호 없는 로그인을 위한 토큰 추가 요청을 받았습니다. 비밀번호 없는 로그인을 위해 토큰 또는 장치를 추가하려면 아래 버튼을 클릭하세요.
|
||||
ButtonText: 비밀번호 없는 로그인 추가
|
||||
PasswordChange:
|
||||
Title: 사용자 비밀번호 변경됨
|
||||
PreHeader: 비밀번호 변경
|
||||
Subject: 사용자 비밀번호 변경됨
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: 사용자의 비밀번호가 변경되었습니다. 본인이 직접 변경하지 않으셨다면 즉시 비밀번호를 재설정하시기 바랍니다.
|
||||
ButtonText: 로그인
|
||||
InviteUser:
|
||||
Title: "{{.ApplicationName}} 초대"
|
||||
PreHeader: "{{.ApplicationName}} 초대"
|
||||
Subject: "{{.ApplicationName}} 초대"
|
||||
Greeting: 안녕하세요, {{.DisplayName}}님,
|
||||
Text: "{{.ApplicationName}}에 초대되었습니다. 초대 프로세스를 완료하려면 아래 버튼을 클릭하세요. 이 메일을 요청하지 않으셨다면 무시하셔도 됩니다."
|
||||
ButtonText: 초대 수락
|
1406
internal/static/i18n/ko.yaml
Normal file
1406
internal/static/i18n/ko.yaml
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user