From 71765c215225dbf82c8b2b4ac588e9cf5f709bab Mon Sep 17 00:00:00 2001 From: Ramon Date: Wed, 2 Apr 2025 06:36:44 +0200 Subject: [PATCH] fix(console): add loginV2 feature flag (#9682) # Which Problems Are Solved While there was already an option to enable the new login UI for a specific application, there was no possibility to do so for the whole instance yet. This prevents an easy switch to the new hosted UI or when running a self hosted login UI. # How the Problems Are Solved Added the LoginV2 settings to the feature toggle screen. # Additional Changes Simplified the feature flags code a bit and made typings more robust. # Additional Context Part of https://github.com/zitadel/zitadel/issues/9481 --- .../feature-toggle.component.html | 18 +- .../feature-toggle.component.ts | 58 +++--- .../login-v2-feature-toggle.component.html | 27 +++ .../login-v2-feature-toggle.component.ts | 47 +++++ .../features/features.component.html | 18 +- .../components/features/features.component.ts | 173 +++++++++--------- console/src/assets/i18n/bg.json | 5 +- console/src/assets/i18n/cs.json | 5 +- console/src/assets/i18n/de.json | 5 +- console/src/assets/i18n/en.json | 5 +- console/src/assets/i18n/es.json | 5 +- console/src/assets/i18n/fr.json | 5 +- console/src/assets/i18n/hu.json | 5 +- console/src/assets/i18n/id.json | 5 +- console/src/assets/i18n/it.json | 5 +- console/src/assets/i18n/ja.json | 5 +- console/src/assets/i18n/ko.json | 5 +- console/src/assets/i18n/mk.json | 5 +- console/src/assets/i18n/nl.json | 5 +- console/src/assets/i18n/pl.json | 5 +- console/src/assets/i18n/pt.json | 5 +- console/src/assets/i18n/ro.json | 5 +- console/src/assets/i18n/ru.json | 5 +- console/src/assets/i18n/sv.json | 5 +- console/src/assets/i18n/zh.json | 5 +- 25 files changed, 280 insertions(+), 156 deletions(-) create mode 100644 console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.html create mode 100644 console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.ts diff --git a/console/src/app/components/feature-toggle/feature-toggle.component.html b/console/src/app/components/feature-toggle/feature-toggle.component.html index eb09552445..cb97f1b746 100644 --- a/console/src/app/components/feature-toggle/feature-toggle.component.html +++ b/console/src/app/components/feature-toggle/feature-toggle.component.html @@ -1,29 +1,29 @@ -
- {{ 'SETTING.FEATURES.' + toggleStateKey.toUpperCase() | translate }} +
+ {{ 'SETTING.FEATURES.' + (toggleStateKey | uppercase) | translate }}
- +
{{ 'SETTING.FEATURES.STATES.DISABLED' | translate }}
- +
{{ 'SETTING.FEATURES.STATES.ENABLED' | translate }}
@@ -34,7 +34,7 @@ {{ i18nDescription }}
diff --git a/console/src/app/components/feature-toggle/feature-toggle.component.ts b/console/src/app/components/feature-toggle/feature-toggle.component.ts index 5c09489619..fab0b31d48 100644 --- a/console/src/app/components/feature-toggle/feature-toggle.component.ts +++ b/console/src/app/components/feature-toggle/feature-toggle.component.ts @@ -1,16 +1,14 @@ -import { CommonModule } from '@angular/common'; +import { AsyncPipe, NgIf, UpperCasePipe } from '@angular/common'; import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; -import { MatButtonModule } from '@angular/material/button'; import { MatTooltipModule } from '@angular/material/tooltip'; -import { CopyToClipboardModule } from '../../directives/copy-to-clipboard/copy-to-clipboard.module'; -import { CopyRowComponent } from '../copy-row/copy-row.component'; import { InfoSectionModule } from 'src/app/modules/info-section/info-section.module'; -import { ToggleState, ToggleStateKeys, ToggleStates } from '../features/features.component'; +import { ToggleStateKeys, ToggleStates } from '../features/features.component'; import { MatButtonToggleModule } from '@angular/material/button-toggle'; import { FormsModule } from '@angular/forms'; -import { GetInstanceFeaturesResponse } from '@zitadel/proto/zitadel/feature/v2/instance_pb'; -import { FeatureFlag, Source } from '@zitadel/proto/zitadel/feature/v2/feature_pb'; +import { Source } from '@zitadel/proto/zitadel/feature/v2/feature_pb'; +import { ReplaySubject } from 'rxjs'; +import { map } from 'rxjs/operators'; @Component({ standalone: true, @@ -19,37 +17,29 @@ import { FeatureFlag, Source } from '@zitadel/proto/zitadel/feature/v2/feature_p styleUrls: ['./feature-toggle.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, imports: [ - CommonModule, - FormsModule, - TranslateModule, - MatButtonModule, - InfoSectionModule, - MatTooltipModule, - CopyToClipboardModule, - CopyRowComponent, MatButtonToggleModule, + UpperCasePipe, + TranslateModule, + FormsModule, + MatTooltipModule, + InfoSectionModule, + AsyncPipe, + NgIf, ], }) -export class FeatureToggleComponent { - @Input() featureData: Partial = {}; - @Input() toggleStates: Partial = {}; - @Input() toggleStateKey: string = ''; - @Output() toggleChange = new EventEmitter(); - - protected ToggleState = ToggleState; - protected Source = Source; - - get isInherited(): boolean { - const source = this.featureData[this.toggleStateKey as ToggleStateKeys]?.source; - return source == Source.SYSTEM || source == Source.UNSPECIFIED; +export class FeatureToggleComponent { + @Input({ required: true }) toggleStateKey!: TKey; + @Input({ required: true }) + set toggleState(toggleState: TValue) { + // we copy the toggleState so we can mutate it + this.toggleState$.next(structuredClone(toggleState)); } - get enabled() { - // TODO: remove casting as not all features are a FeatureFlag - return (this.featureData[this.toggleStateKey as ToggleStateKeys] as FeatureFlag)?.enabled; - } + @Output() readonly toggleChange = new EventEmitter(); - onToggleChange() { - this.toggleChange.emit(); - } + protected readonly Source = Source; + protected readonly toggleState$ = new ReplaySubject(1); + protected readonly isInherited$ = this.toggleState$.pipe( + map(({ source }) => source == Source.SYSTEM || source == Source.UNSPECIFIED), + ); } diff --git a/console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.html b/console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.html new file mode 100644 index 0000000000..c1feeb894c --- /dev/null +++ b/console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.html @@ -0,0 +1,27 @@ + + + {{ 'SETTING.FEATURES.LOGINV2_BASEURI' | translate }} + + + + diff --git a/console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.ts b/console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.ts new file mode 100644 index 0000000000..01648d22ad --- /dev/null +++ b/console/src/app/components/feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component.ts @@ -0,0 +1,47 @@ +import { ChangeDetectionStrategy, Component, DestroyRef, EventEmitter, Input, Output } from '@angular/core'; +import { FeatureToggleComponent } from '../feature-toggle.component'; +import { ToggleStates } from 'src/app/components/features/features.component'; +import { distinctUntilKeyChanged, ReplaySubject } from 'rxjs'; +import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; +import { AsyncPipe, NgIf } from '@angular/common'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { InputModule } from 'src/app/modules/input/input.module'; +import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module'; +import { MatButtonModule } from '@angular/material/button'; +import { TranslateModule } from '@ngx-translate/core'; +import { MatTooltipModule } from '@angular/material/tooltip'; + +@Component({ + standalone: true, + selector: 'cnsl-login-v2-feature-toggle', + templateUrl: './login-v2-feature-toggle.component.html', + imports: [ + FeatureToggleComponent, + AsyncPipe, + NgIf, + ReactiveFormsModule, + InputModule, + HasRolePipeModule, + MatButtonModule, + TranslateModule, + MatTooltipModule, + ], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class LoginV2FeatureToggleComponent { + @Input({ required: true }) + set toggleState(toggleState: ToggleStates['loginV2']) { + this.toggleState$.next(toggleState); + } + @Output() + public toggleChanged = new EventEmitter(); + + protected readonly toggleState$ = new ReplaySubject(1); + protected readonly baseUri = new FormControl('', { nonNullable: true, validators: [Validators.required] }); + + constructor(destroyRef: DestroyRef) { + this.toggleState$.pipe(distinctUntilKeyChanged('baseUri'), takeUntilDestroyed(destroyRef)).subscribe(({ baseUri }) => { + this.baseUri.setValue(baseUri); + }); + } +} diff --git a/console/src/app/components/features/features.component.html b/console/src/app/components/features/features.component.html index 95cc889f77..30d8f629af 100644 --- a/console/src/app/components/features/features.component.html +++ b/console/src/app/components/features/features.component.html @@ -13,26 +13,20 @@

{{ 'DESCRIPTIONS.SETTINGS.FEATURES.DESCRIPTION' | translate }}

- - +
+
- - - - {{ 'SETTING.FEATURES.SOURCE.' + source | translate }} - - diff --git a/console/src/app/components/features/features.component.ts b/console/src/app/components/features/features.component.ts index e253bdf023..4a3fb0f88c 100644 --- a/console/src/app/components/features/features.component.ts +++ b/console/src/app/components/features/features.component.ts @@ -19,16 +19,14 @@ import { GetInstanceFeaturesResponse, SetInstanceFeaturesRequestSchema, } from '@zitadel/proto/zitadel/feature/v2/instance_pb'; -import { FeatureFlag, Source } from '@zitadel/proto/zitadel/feature/v2/feature_pb'; +import { Source } from '@zitadel/proto/zitadel/feature/v2/feature_pb'; import { MessageInitShape } from '@bufbuild/protobuf'; +import { firstValueFrom, Observable, ReplaySubject, shareReplay, switchMap } from 'rxjs'; +import { filter, map, startWith } from 'rxjs/operators'; +import { LoginV2FeatureToggleComponent } from '../feature-toggle/login-v2-feature-toggle/login-v2-feature-toggle.component'; -export enum ToggleState { - ENABLED = 'ENABLED', - DISABLED = 'DISABLED', -} - -// TODO: to add a new feature, add the key here and in the FEATURE_KEYS array -const FEATURE_KEYS: ToggleStateKeys[] = [ +// to add a new feature, add the key here and in the FEATURE_KEYS array +const FEATURE_KEYS = [ 'actions', 'consoleUseV2UserApi', 'debugOidcParentError', @@ -36,7 +34,6 @@ const FEATURE_KEYS: ToggleStateKeys[] = [ 'enableBackChannelLogout', // 'improvedPerformance', 'loginDefaultOrg', - // 'loginV2', 'oidcLegacyIntrospection', 'oidcSingleV1SessionTermination', 'oidcTokenExchange', @@ -44,15 +41,17 @@ const FEATURE_KEYS: ToggleStateKeys[] = [ 'permissionCheckV2', 'userSchema', // 'webKey', -]; - -type FeatureState = { source: Source; state: ToggleState }; -export type ToggleStateKeys = Exclude; +] as const; +export type ToggleState = { source: Source; enabled: boolean }; export type ToggleStates = { - [key in ToggleStateKeys]: FeatureState; + [key in (typeof FEATURE_KEYS)[number]]: ToggleState; +} & { + loginV2: ToggleState & { baseUri: string }; }; +export type ToggleStateKeys = keyof ToggleStates; + @Component({ imports: [ CommonModule, @@ -68,6 +67,7 @@ export type ToggleStates = { MatTooltipModule, HasRoleModule, FeatureToggleComponent, + LoginV2FeatureToggleComponent, ], standalone: true, selector: 'cnsl-features', @@ -75,16 +75,15 @@ export type ToggleStates = { styleUrls: ['./features.component.scss'], }) export class FeaturesComponent { - protected featureData: GetInstanceFeaturesResponse | undefined; - - protected toggleStates: ToggleStates | undefined; - protected Source: any = Source; - protected ToggleState: any = ToggleState; + private readonly refresh$ = new ReplaySubject(1); + protected readonly toggleStates$: Observable; + protected readonly Source = Source; + protected readonly FEATURE_KEYS = FEATURE_KEYS; constructor( - private featureService: NewFeatureService, - private breadcrumbService: BreadcrumbService, - private toast: ToastService, + private readonly featureService: NewFeatureService, + private readonly breadcrumbService: BreadcrumbService, + private readonly toast: ToastService, ) { const breadcrumbs = [ new Breadcrumb({ @@ -95,74 +94,84 @@ export class FeaturesComponent { ]; this.breadcrumbService.setBreadcrumb(breadcrumbs); - this.getFeatures(); + this.toggleStates$ = this.getToggleStates().pipe(shareReplay({ refCount: true, bufferSize: 1 })); } - public validateAndSave() { - const req: MessageInitShape = { - actions: this.toggleStates?.actions?.state === ToggleState.ENABLED, - consoleUseV2UserApi: this.toggleStates?.consoleUseV2UserApi?.state === ToggleState.ENABLED, - debugOidcParentError: this.toggleStates?.debugOidcParentError?.state === ToggleState.ENABLED, - disableUserTokenEvent: this.toggleStates?.disableUserTokenEvent?.state === ToggleState.ENABLED, - enableBackChannelLogout: this.toggleStates?.enableBackChannelLogout?.state === ToggleState.ENABLED, - loginDefaultOrg: this.toggleStates?.loginDefaultOrg?.state === ToggleState.ENABLED, - oidcLegacyIntrospection: this.toggleStates?.oidcLegacyIntrospection?.state === ToggleState.ENABLED, - oidcSingleV1SessionTermination: this.toggleStates?.oidcSingleV1SessionTermination?.state === ToggleState.ENABLED, - oidcTokenExchange: this.toggleStates?.oidcTokenExchange?.state === ToggleState.ENABLED, - oidcTriggerIntrospectionProjections: - this.toggleStates?.oidcTriggerIntrospectionProjections?.state === ToggleState.ENABLED, - permissionCheckV2: this.toggleStates?.permissionCheckV2?.state === ToggleState.ENABLED, - userSchema: this.toggleStates?.userSchema?.state === ToggleState.ENABLED, - // webKey: this.toggleStates?.webKey?.state === ToggleState.ENABLED, - }; - - this.featureService - .setInstanceFeatures(req) - .then(() => { - this.toast.showInfo('POLICY.TOAST.SET', true); - }) - .catch((error) => { - this.toast.showError(error); - }); - } - - private getFeatures() { - this.featureService.getInstanceFeatures().then((instanceFeaturesResponse) => { - this.featureData = instanceFeaturesResponse; - this.toggleStates = this.createToggleStates(this.featureData); - }); + private getToggleStates() { + return this.refresh$.pipe( + startWith(true), + switchMap(async () => { + try { + return await this.featureService.getInstanceFeatures(); + } catch (error) { + this.toast.showError(error); + return undefined; + } + }), + filter(Boolean), + map((res) => this.createToggleStates(res)), + ); } private createToggleStates(featureData: GetInstanceFeaturesResponse): ToggleStates { - const toggleStates: Partial = {}; - - FEATURE_KEYS.forEach((key) => { - // TODO: Fix this type cast as not all keys are present as FeatureFlag - const feature = featureData[key] as unknown as FeatureFlag; - toggleStates[key] = { - source: feature?.source || Source.SYSTEM, - state: !!feature?.enabled ? ToggleState.ENABLED : ToggleState.DISABLED, - }; - }); - - return toggleStates as ToggleStates; + return FEATURE_KEYS.reduce( + (acc, key) => { + const feature = featureData[key]; + acc[key] = { + source: feature?.source ?? Source.SYSTEM, + enabled: !!feature?.enabled, + }; + return acc; + }, + { + // to add special feature flags they have to be mapped here + loginV2: { + source: featureData.loginV2?.source ?? Source.SYSTEM, + enabled: !!featureData.loginV2?.required, + baseUri: featureData.loginV2?.baseUri ?? '', + }, + } as ToggleStates, + ); } - public resetSettings(): void { - this.featureService - .resetInstanceFeatures() - .then(() => { - this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true); - setTimeout(() => { - this.getFeatures(); - }, 1000); - }) - .catch((error) => { - this.toast.showError(error); - }); + public async saveFeatures(key: TKey, value: TValue) { + const toggleStates = { ...(await firstValueFrom(this.toggleStates$)), [key]: value }; + + const req = FEATURE_KEYS.reduce>((acc, key) => { + acc[key] = toggleStates[key].enabled; + return acc; + }, {}); + + // to save special flags they have to be handled here + req.loginV2 = { + required: toggleStates.loginV2.enabled, + baseUri: toggleStates.loginV2.baseUri, + }; + + try { + await this.featureService.setInstanceFeatures(req); + + // needed because of eventual consistency + await new Promise((res) => setTimeout(res, 1000)); + this.refresh$.next(true); + + this.toast.showInfo('POLICY.TOAST.SET', true); + } catch (error) { + this.toast.showError(error); + } } - public get toggleStateKeys() { - return Object.keys(this.toggleStates ?? {}); + public async resetFeatures() { + try { + await this.featureService.resetInstanceFeatures(); + + // needed because of eventual consistency + await new Promise((res) => setTimeout(res, 1000)); + this.refresh$.next(true); + + this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true); + } catch (error) { + this.toast.showError(error); + } } } diff --git a/console/src/assets/i18n/bg.json b/console/src/assets/i18n/bg.json index aa95e40fc6..9982a88e82 100644 --- a/console/src/assets/i18n/bg.json +++ b/console/src/assets/i18n/bg.json @@ -1541,7 +1541,10 @@ }, "RESET": "Задай всички на наследено", "CONSOLEUSEV2USERAPI": "Използвайте V2 API в конзолата за създаване на потребител", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Когато този флаг е активиран, конзолата използва V2 User API за създаване на нови потребители. С V2 API новосъздадените потребители започват без начален статус." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Когато този флаг е активиран, конзолата използва V2 User API за създаване на нови потребители. С V2 API новосъздадените потребители започват без начален статус.", + "LOGINV2": "Вход V2", + "LOGINV2_DESCRIPTION": "Активирането на това включва новия потребителски интерфейс за вход, базиран на TypeScript, с подобрена сигурност, производителност и възможности за персонализиране.", + "LOGINV2_BASEURI": "Базов URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/cs.json b/console/src/assets/i18n/cs.json index 32c7a6d9f1..d106b61ac1 100644 --- a/console/src/assets/i18n/cs.json +++ b/console/src/assets/i18n/cs.json @@ -1542,7 +1542,10 @@ }, "RESET": "Nastavit vše na děděné", "CONSOLEUSEV2USERAPI": "Použijte V2 API v konzoli pro vytvoření uživatele", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Když je tato příznak povolen, konzole používá V2 User API k vytvoření nových uživatelů. S V2 API nově vytvoření uživatelé začínají bez počátečního stavu." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Když je tato příznak povolen, konzole používá V2 User API k vytvoření nových uživatelů. S V2 API nově vytvoření uživatelé začínají bez počátečního stavu.", + "LOGINV2": "Přihlášení V2", + "LOGINV2_DESCRIPTION": "Povolením této možnosti se aktivuje nové přihlašovací rozhraní založené na TypeScriptu s vylepšeným zabezpečením, výkonem a přizpůsobitelností.", + "LOGINV2_BASEURI": "Základní URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 90b2cd5ae4..4eea5975d9 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -1542,7 +1542,10 @@ }, "RESET": "Alle auf Erben setzen", "CONSOLEUSEV2USERAPI": "Verwende die V2-API in der Konsole zur Erstellung von Benutzern", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Wenn diese Option aktiviert ist, verwendet die Konsole die V2 User API, um neue Benutzer zu erstellen. Mit der V2 API starten neu erstellte Benutzer nicht im Initial Zustand." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Wenn diese Option aktiviert ist, verwendet die Konsole die V2 User API, um neue Benutzer zu erstellen. Mit der V2 API starten neu erstellte Benutzer nicht im Initial Zustand.", + "LOGINV2": "Login V2", + "LOGINV2_DESCRIPTION": "Durch das Aktivieren wird das neue TypeScript-basierte Login-UI mit verbesserter Sicherheit, Leistung und Anpassbarkeit aktiviert.", + "LOGINV2_BASEURI": "Basis-URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index 48ec0efd12..729df6c4fa 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -1542,7 +1542,10 @@ }, "RESET": "Set all to inherit", "CONSOLEUSEV2USERAPI": "Use V2 Api in Console for User creation", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "When this flag is enabled, the console uses the V2 User API to create new users. With the V2 API, newly created users start without an initial state." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "When this flag is enabled, the console uses the V2 User API to create new users. With the V2 API, newly created users start without an initial state.", + "LOGINV2": "Login V2", + "LOGINV2_DESCRIPTION": "Enabling this activates the new TypeScript-based login UI with improved security, performance, and customization.", + "LOGINV2_BASEURI": "Base URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/es.json b/console/src/assets/i18n/es.json index 64c196b02c..3bcde9334b 100644 --- a/console/src/assets/i18n/es.json +++ b/console/src/assets/i18n/es.json @@ -1543,7 +1543,10 @@ }, "RESET": "Establecer todo a heredado", "CONSOLEUSEV2USERAPI": "Utilice la API V2 en la consola para la creación de usuarios", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Cuando esta opción está habilitada, la consola utiliza la API V2 de usuario para crear nuevos usuarios. Con la API V2, los usuarios recién creados comienzan sin un estado inicial." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Cuando esta opción está habilitada, la consola utiliza la API V2 de usuario para crear nuevos usuarios. Con la API V2, los usuarios recién creados comienzan sin un estado inicial.", + "LOGINV2": "Inicio de sesión V2", + "LOGINV2_DESCRIPTION": "Al habilitar esto, se activa la nueva interfaz de inicio de sesión basada en TypeScript con mejoras en seguridad, rendimiento y personalización.", + "LOGINV2_BASEURI": "URI base" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json index 71e47af1b1..73eb1a886f 100644 --- a/console/src/assets/i18n/fr.json +++ b/console/src/assets/i18n/fr.json @@ -1542,7 +1542,10 @@ }, "RESET": "Réinitialiser tout sur hérité", "CONSOLEUSEV2USERAPI": "Utilisez l'API V2 dans la console pour la création d'utilisateurs", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Lorsque ce drapeau est activé, la console utilise l'API V2 User pour créer de nouveaux utilisateurs. Avec l'API V2, les nouveaux utilisateurs commencent sans état initial." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Lorsque ce drapeau est activé, la console utilise l'API V2 User pour créer de nouveaux utilisateurs. Avec l'API V2, les nouveaux utilisateurs commencent sans état initial.", + "LOGINV2": "Connexion V2", + "LOGINV2_DESCRIPTION": "L’activation de cette option lance la nouvelle interface de connexion basée sur TypeScript, avec une sécurité, des performances et une personnalisation améliorées.", + "LOGINV2_BASEURI": "URI de base" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/hu.json b/console/src/assets/i18n/hu.json index 7833a519e0..78301312ee 100644 --- a/console/src/assets/i18n/hu.json +++ b/console/src/assets/i18n/hu.json @@ -1540,7 +1540,10 @@ }, "RESET": "Mindent állíts öröklésre", "CONSOLEUSEV2USERAPI": "Használja a V2 API-t a konzolban felhasználók létrehozásához", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Ha ez a jelző engedélyezve van, a konzol a V2 User API-t használja új felhasználók létrehozásához. A V2 API-val az újonnan létrehozott felhasználók kezdeti állapot nélkül indulnak." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Ha ez a jelző engedélyezve van, a konzol a V2 User API-t használja új felhasználók létrehozásához. A V2 API-val az újonnan létrehozott felhasználók kezdeti állapot nélkül indulnak.", + "LOGINV2": "Bejelentkezés V2", + "LOGINV2_DESCRIPTION": "Ennek engedélyezésével aktiválódik az új, TypeScript-alapú bejelentkezési felület, amely jobb biztonságot, teljesítményt és testreszabhatóságot nyújt.", + "LOGINV2_BASEURI": "Alap URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/id.json b/console/src/assets/i18n/id.json index 738834893c..f6a88af133 100644 --- a/console/src/assets/i18n/id.json +++ b/console/src/assets/i18n/id.json @@ -1409,7 +1409,10 @@ }, "RESET": "Tetapkan semua untuk diwarisi", "CONSOLEUSEV2USERAPI": "Gunakan API V2 di konsol untuk pembuatan pengguna", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Ketika flag ini diaktifkan, konsol menggunakan API Pengguna V2 untuk membuat pengguna baru. Dengan API V2, pengguna yang baru dibuat dimulai tanpa keadaan awal." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Ketika flag ini diaktifkan, konsol menggunakan API Pengguna V2 untuk membuat pengguna baru. Dengan API V2, pengguna yang baru dibuat dimulai tanpa keadaan awal.", + "LOGINV2": "Login V2", + "LOGINV2_DESCRIPTION": "Mengaktifkan ini akan mengaktifkan antarmuka login baru berbasis TypeScript dengan keamanan, performa, dan kustomisasi yang lebih baik.", + "LOGINV2_BASEURI": "URI dasar" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json index 5acb508d71..95eaa5da86 100644 --- a/console/src/assets/i18n/it.json +++ b/console/src/assets/i18n/it.json @@ -1542,7 +1542,10 @@ }, "RESET": "Imposta tutto su predefinito", "CONSOLEUSEV2USERAPI": "Utilizza l'API V2 nella console per la creazione degli utenti", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Quando questa opzione è abilitata, la console utilizza l'API V2 User per creare nuovi utenti. Con l'API V2, i nuovi utenti creati iniziano senza uno stato iniziale." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Quando questa opzione è abilitata, la console utilizza l'API V2 User per creare nuovi utenti. Con l'API V2, i nuovi utenti creati iniziano senza uno stato iniziale.", + "LOGINV2": "Accesso V2", + "LOGINV2_DESCRIPTION": "Abilitando questa opzione si attiva la nuova interfaccia di login basata su TypeScript con sicurezza, prestazioni e personalizzazione migliorate.", + "LOGINV2_BASEURI": "URI di base" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/ja.json b/console/src/assets/i18n/ja.json index f5aef6b416..d43c6c254b 100644 --- a/console/src/assets/i18n/ja.json +++ b/console/src/assets/i18n/ja.json @@ -1542,7 +1542,10 @@ }, "RESET": "すべて継承に設定", "CONSOLEUSEV2USERAPI": "コンソールでユーザー作成のためにV2 APIを使用してください。", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "このフラグが有効化されると、コンソールはV2ユーザーAPIを使用して新しいユーザーを作成します。V2 APIでは、新しく作成されたユーザーは初期状態なしで開始します。" + "CONSOLEUSEV2USERAPI_DESCRIPTION": "このフラグが有効化されると、コンソールはV2ユーザーAPIを使用して新しいユーザーを作成します。V2 APIでは、新しく作成されたユーザーは初期状態なしで開始します。", + "LOGINV2": "ログイン V2", + "LOGINV2_DESCRIPTION": "これを有効にすると、セキュリティ、パフォーマンス、およびカスタマイズ性が向上した、TypeScript ベースの新しいログイン UI が有効になります。", + "LOGINV2_BASEURI": "ベースURI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/ko.json b/console/src/assets/i18n/ko.json index 2da487c491..85960be34c 100644 --- a/console/src/assets/i18n/ko.json +++ b/console/src/assets/i18n/ko.json @@ -1542,7 +1542,10 @@ }, "RESET": "모두 상속으로 설정", "CONSOLEUSEV2USERAPI": "콘솔에서 사용자 생성을 위해 V2 API를 사용하세요", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "이 플래그가 활성화되면 콘솔은 V2 사용자 API를 사용하여 새 사용자를 생성합니다. V2 API를 사용하면 새로 생성된 사용자는 초기 상태 없이 시작합니다." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "이 플래그가 활성화되면 콘솔은 V2 사용자 API를 사용하여 새 사용자를 생성합니다. V2 API를 사용하면 새로 생성된 사용자는 초기 상태 없이 시작합니다.", + "LOGINV2": "로그인 V2", + "LOGINV2_DESCRIPTION": "이 옵션을 활성화하면 보안, 성능 및 사용자 정의 기능이 향상된 새로운 TypeScript 기반 로그인 UI가 활성화됩니다.", + "LOGINV2_BASEURI": "기본 URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/mk.json b/console/src/assets/i18n/mk.json index 82fc5b07f9..be315d1283 100644 --- a/console/src/assets/i18n/mk.json +++ b/console/src/assets/i18n/mk.json @@ -1543,7 +1543,10 @@ }, "RESET": "Поставете ги сите да наследат", "CONSOLEUSEV2USERAPI": "Користете V2 API во конзолата за креирање на корисници", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Кога ова знаме е овозможено, конзолата го користи V2 User API за креирање на нови корисници. Со V2 API, новосоздадените корисници започнуваат без почетна состојба." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Кога ова знаме е овозможено, конзолата го користи V2 User API за креирање на нови корисници. Со V2 API, новосоздадените корисници започнуваат без почетна состојба.", + "LOGINV2": "Најава V2", + "LOGINV2_DESCRIPTION": "Овозможувањето на ова ја активира новата TypeScript-базирана најава со подобрена безбедност, перформанси и прилагодливост.", + "LOGINV2_BASEURI": "Основен URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/nl.json b/console/src/assets/i18n/nl.json index 9fc7cf808f..1d564370c4 100644 --- a/console/src/assets/i18n/nl.json +++ b/console/src/assets/i18n/nl.json @@ -1542,7 +1542,10 @@ }, "RESET": "Alles instellen op overgenomen", "CONSOLEUSEV2USERAPI": "Gebruik de V2 API in de console voor het aanmaken van gebruikers", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Wanneer deze vlag is ingeschakeld, gebruikt de console de V2 User API om nieuwe gebruikers aan te maken. Met de V2 API beginnen nieuw aangemaakte gebruikers zonder een initiële status." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Wanneer deze vlag is ingeschakeld, gebruikt de console de V2 User API om nieuwe gebruikers aan te maken. Met de V2 API beginnen nieuw aangemaakte gebruikers zonder een initiële status.", + "LOGINV2": "Inloggen V2", + "LOGINV2_DESCRIPTION": "Door dit in te schakelen wordt de nieuwe TypeScript-gebaseerde login-UI geactiveerd met verbeterde beveiliging, prestaties en aanpasbaarheid.", + "LOGINV2_BASEURI": "Basis-URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json index 6a8aba22b7..1372b1a67d 100644 --- a/console/src/assets/i18n/pl.json +++ b/console/src/assets/i18n/pl.json @@ -1541,7 +1541,10 @@ }, "RESET": "Ustaw wszystko na dziedziczone", "CONSOLEUSEV2USERAPI": "Użyj API V2 w konsoli do tworzenia użytkowników", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Gdy ta flaga jest włączona, konsola używa API V2 User do tworzenia nowych użytkowników. W przypadku API V2 nowo utworzeni użytkownicy rozpoczynają bez stanu początkowego." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Gdy ta flaga jest włączona, konsola używa API V2 User do tworzenia nowych użytkowników. W przypadku API V2 nowo utworzeni użytkownicy rozpoczynają bez stanu początkowego.", + "LOGINV2": "Logowanie V2", + "LOGINV2_DESCRIPTION": "Włączenie tej opcji aktywuje nowy interfejs logowania oparty na TypeScript z ulepszonym bezpieczeństwem, wydajnością i możliwością dostosowania.", + "LOGINV2_BASEURI": "Podstawowy URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/pt.json b/console/src/assets/i18n/pt.json index 55a09b1642..b175b37632 100644 --- a/console/src/assets/i18n/pt.json +++ b/console/src/assets/i18n/pt.json @@ -1543,7 +1543,10 @@ }, "RESET": "Definir tudo para herdar", "CONSOLEUSEV2USERAPI": "Use a API V2 no console para criação de usuários", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Quando esta opção está ativada, o console utiliza a API V2 de Usuários para criar novos usuários. Com a API V2, os novos usuários criados começam sem um estado inicial." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Quando esta opção está ativada, o console utiliza a API V2 de Usuários para criar novos usuários. Com a API V2, os novos usuários criados começam sem um estado inicial.", + "LOGINV2": "Login V2", + "LOGINV2_DESCRIPTION": "Ativar esta opção ativa a nova interface de login baseada em TypeScript, com melhorias na segurança, desempenho e personalização.", + "LOGINV2_BASEURI": "URI base" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/ro.json b/console/src/assets/i18n/ro.json index fddcead454..bc98522a41 100644 --- a/console/src/assets/i18n/ro.json +++ b/console/src/assets/i18n/ro.json @@ -1540,7 +1540,10 @@ }, "RESET": "Setați totul pentru a moșteni", "CONSOLEUSEV2USERAPI": "Utilizați API-ul V2 în Consola pentru crearea utilizatorului", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Când acest indicator este activat, consola utilizează API-ul de utilizator V2 pentru a crea utilizatori noi. Cu API-ul V2, utilizatorii nou creați încep fără o stare inițială." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Când acest indicator este activat, consola utilizează API-ul de utilizator V2 pentru a crea utilizatori noi. Cu API-ul V2, utilizatorii nou creați încep fără o stare inițială.", + "LOGINV2": "Autentificare V2", + "LOGINV2_DESCRIPTION": "Activarea acestei opțiuni pornește noua interfață de autentificare bazată pe TypeScript, cu securitate, performanță și personalizare îmbunătățite.", + "LOGINV2_BASEURI": "URI de bază" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/ru.json b/console/src/assets/i18n/ru.json index 39f47e0cbd..389db2abc2 100644 --- a/console/src/assets/i18n/ru.json +++ b/console/src/assets/i18n/ru.json @@ -1595,7 +1595,10 @@ }, "RESET": "Установить все по умолчанию", "CONSOLEUSEV2USERAPI": "Используйте V2 API в консоли для создания пользователей", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "Когда этот флаг включен, консоль использует V2 User API для создания новых пользователей. С API V2 новые пользователи создаются без начального состояния." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "Когда этот флаг включен, консоль использует V2 User API для создания новых пользователей. С API V2 новые пользователи создаются без начального состояния.", + "LOGINV2": "Вход V2", + "LOGINV2_DESCRIPTION": "Включение этой опции активирует новый интерфейс входа на основе TypeScript с улучшенной безопасностью, производительностью и возможностью настройки.", + "LOGINV2_BASEURI": "Базовый URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/sv.json b/console/src/assets/i18n/sv.json index cf7c70800a..f0d119f07c 100644 --- a/console/src/assets/i18n/sv.json +++ b/console/src/assets/i18n/sv.json @@ -1546,7 +1546,10 @@ }, "RESET": "Återställ allt till arv", "CONSOLEUSEV2USERAPI": "Använd V2 API i konsolen för att skapa användare", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "När denna flagga är aktiverad använder konsolen V2 User API för att skapa nya användare. Med V2 API startar nyligen skapade användare utan ett initialt tillstånd." + "CONSOLEUSEV2USERAPI_DESCRIPTION": "När denna flagga är aktiverad använder konsolen V2 User API för att skapa nya användare. Med V2 API startar nyligen skapade användare utan ett initialt tillstånd.", + "LOGINV2": "Inloggning V2", + "LOGINV2_DESCRIPTION": "Att aktivera detta startar det nya inloggningsgränssnittet baserat på TypeScript med förbättrad säkerhet, prestanda och anpassning.", + "LOGINV2_BASEURI": "Bas-URI" }, "DIALOG": { "RESET": { diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json index bd079f7841..49edb39f18 100644 --- a/console/src/assets/i18n/zh.json +++ b/console/src/assets/i18n/zh.json @@ -1542,7 +1542,10 @@ }, "RESET": "全部设置为继承", "CONSOLEUSEV2USERAPI": "在控制台中使用V2 API创建用户。", - "CONSOLEUSEV2USERAPI_DESCRIPTION": "启用此标志时,控制台使用V2用户API创建新用户。使用V2 API,新创建的用户将以无初始状态开始。" + "CONSOLEUSEV2USERAPI_DESCRIPTION": "启用此标志时,控制台使用V2用户API创建新用户。使用V2 API,新创建的用户将以无初始状态开始。", + "LOGINV2": "登录 V2", + "LOGINV2_DESCRIPTION": "启用此选项将激活基于 TypeScript 的新登录界面,具有更高的安全性、性能和可定制性。", + "LOGINV2_BASEURI": "基础 URI" }, "DIALOG": { "RESET": {