mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-29 10:32:15 +00:00
fix: restrict languages in console (#6964)
* feat: return 404 or 409 if org reg disallowed * fix: system limit permissions * feat: add iam limits api * feat: disallow public org registrations on default instance * add integration test * test: integration * fix test * docs: describe public org registrations * avoid updating docs deps * fix system limits integration test * silence integration tests * fix linting * ignore strange linter complaints * review * improve reset properties naming * redefine the api * use restrictions aggregate * test query * simplify and test projection * test commands * fix unit tests * move integration test * support restrictions on default instance * also test GetRestrictions * self review * lint * abstract away resource owner * fix tests * configure supported languages * fix allowed languages * fix tests * default lang must not be restricted * preferred language must be allowed * change preferred languages * check languages everywhere * lint * test command side * lint * add integration test * add integration test * restrict supported ui locales * lint * lint * cleanup * lint * allow undefined preferred language * fix integration tests * update main * fix env var * ignore linter * ignore linter * improve integration test config * reduce cognitive complexity * compile * fix(console): switch back to saved language * feat(API): get allowed languages * fix(console): only make allowed languages selectable * warn when editing not allowed languages * check for duplicates * remove useless restriction checks * review * revert restriction renaming * fix language restrictions * lint * generate * allow custom texts for supported langs for now * fix tests * cleanup * cleanup * cleanup * lint * unsupported preferred lang is allowed * fix integration test * allow unsupported preferred languages * lint * load languages for tests * cleanup * lint * cleanup * get allowed only on admin * cleanup * reduce flakiness on very limited postgres * simplify langSvc * refactor according to suggestions in pr * lint * set first allowed language as default * selectionchange for language in msg texts * initialize login texts * init message texts * lint --------- Co-authored-by: peintnermax <[email protected]>
This commit is contained in:
co-authored by
peintnermax
parent
f09fbf8709
commit
8c85318fbd
@@ -69,6 +69,7 @@ import { StatehandlerService, StatehandlerServiceImpl } from './services/stateha
|
||||
import { StorageService } from './services/storage.service';
|
||||
import { ThemeService } from './services/theme.service';
|
||||
import { ToastService } from './services/toast.service';
|
||||
import { LanguagesService } from './services/languages.service';
|
||||
|
||||
registerLocaleData(localeDe);
|
||||
i18nIsoCountries.registerLocale(require('i18n-iso-countries/langs/de.json'));
|
||||
@@ -228,6 +229,7 @@ const authConfig: AuthConfig = {
|
||||
AssetService,
|
||||
ToastService,
|
||||
NavigationService,
|
||||
LanguagesService,
|
||||
{ provide: 'windowObject', useValue: window },
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
|
||||
@@ -26,7 +26,7 @@ export class GeneralSettingsComponent implements OnInit {
|
||||
this.service.getDefaultLanguage().then((langResp) => {
|
||||
this.defaultLanguage = langResp.language;
|
||||
});
|
||||
this.service.getSupportedLanguages().then((supportedResp) => {
|
||||
this.service.getAllowedLanguages().then((supportedResp) => {
|
||||
this.defaultLanguageOptions = supportedResp.languagesList;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<h2>{{ 'POLICY.LOGIN_TEXTS.TITLE' | translate }}</h2>
|
||||
<p class="cnsl-secondary-text">{{ 'POLICY.LOGIN_TEXTS.DESCRIPTION' | translate }}</p>
|
||||
<cnsl-info-section class="locked" *ngIf="langSvc.isNotAllowed(language) | async" [type]="InfoSectionType.WARN">
|
||||
{{ 'POLICY.LOGIN_TEXTS.ACTIVE_LANGUAGE_NOT_ALLOWED' | translate }}</cnsl-info-section
|
||||
>
|
||||
|
||||
<div *ngIf="loading" class="spinner-wr">
|
||||
<mat-spinner diameter="30" color="primary"></mat-spinner>
|
||||
@@ -24,7 +27,7 @@
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<form *ngIf="form" class="top-actions" [formGroup]="form">
|
||||
<form *ngIf="allowed$ | async" class="top-actions" [formGroup]="form">
|
||||
<cnsl-form-field class="keys">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.KEYNAME' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="currentSubMap" name="currentSubMap">
|
||||
@@ -35,18 +38,30 @@
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="language">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LOCALE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="locale" name="locale">
|
||||
<mat-option *ngFor="let loc of LOCALES" [value]="loc">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="language" name="language">
|
||||
<mat-option *ngFor="let lang of allowed$ | async" [value]="lang">
|
||||
<div class="centerline">
|
||||
<span
|
||||
>{{ loc }}
|
||||
>{{ lang }}
|
||||
<span class="lighter cnsl-secondary-text"
|
||||
>| {{ 'POLICY.LOGIN_TEXTS.LOCALES.' + loc | translate }}</span
|
||||
>| {{ 'POLICY.LOGIN_TEXTS.LANGUAGES.' + lang | translate }}</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
</mat-option>
|
||||
<mat-optgroup [label]="'POLICY.LOGIN_TEXTS.LANGUAGES_NOT_ALLOWED' | translate" *ngIf="langSvc.restricted$ | async">
|
||||
<mat-option *ngFor="let lang of langSvc.notAllowed$ | async" [value]="lang">
|
||||
<div class="centerline">
|
||||
<span
|
||||
>{{ lang }}
|
||||
<span class="lighter cnsl-secondary-text"
|
||||
>| {{ 'POLICY.LOGIN_TEXTS.LANGUAGES.' + lang | translate }}</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-optgroup>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</form>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component, Injector, Input, OnDestroy, OnInit, Type } from '@angular/core';
|
||||
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { FormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, from, interval, Observable, of, Subject, Subscription } from 'rxjs';
|
||||
import { BehaviorSubject, from, interval, Observable, of, Subject, Subscription, switchMap, take, tap } from 'rxjs';
|
||||
import { map, pairwise, startWith, takeUntil } from 'rxjs/operators';
|
||||
import {
|
||||
GetCustomLoginTextsRequest as AdminGetCustomLoginTextsRequest,
|
||||
@@ -19,11 +19,11 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { supportedLanguages } from 'src/app/utils/language';
|
||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { mapRequestValues } from './helper';
|
||||
import { LanguagesService } from '../../../services/languages.service';
|
||||
|
||||
const MIN_INTERVAL_SECONDS = 10; // if the difference of a newer version to the current exceeds this time, a refresh button is shown.
|
||||
|
||||
@@ -110,7 +110,6 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
@Input() public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public KeyNamesArray: string[] = KeyNamesArray;
|
||||
public LOCALES: string[] = supportedLanguages;
|
||||
|
||||
private sub: Subscription = new Subscription();
|
||||
|
||||
@@ -119,9 +118,15 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
public destroy$: Subject<void> = new Subject();
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
public form: UntypedFormGroup = new UntypedFormGroup({
|
||||
currentSubMap: new UntypedFormControl('emailVerificationDoneText'),
|
||||
locale: new UntypedFormControl('en'),
|
||||
currentSubMap: new FormControl<string>('emailVerificationDoneText'),
|
||||
language: new FormControl<string>('en'),
|
||||
});
|
||||
public allowed$: Observable<string[]> = this.langSvc.allowed$.pipe(
|
||||
take(1),
|
||||
tap(([firstAllowed]) => {
|
||||
this.form.get('language')?.setValue(firstAllowed);
|
||||
}),
|
||||
);
|
||||
|
||||
public isDefault: boolean = false;
|
||||
|
||||
@@ -137,9 +142,10 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
private injector: Injector,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
public langSvc: LanguagesService,
|
||||
) {
|
||||
this.form.valueChanges
|
||||
.pipe(startWith({ currentSubMap: 'emailVerificationDoneText', locale: 'en' }), pairwise(), takeUntil(this.destroy$))
|
||||
.pipe(startWith({ currentSubMap: 'emailVerificationDoneText', language: 'en' }), pairwise(), takeUntil(this.destroy$))
|
||||
.subscribe((pair) => {
|
||||
this.checkForUnsaved(pair[0].currentSubMap).then((wantsToSave) => {
|
||||
if (wantsToSave) {
|
||||
@@ -162,21 +168,9 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
|
||||
this.service.getSupportedLanguages().then((lang) => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
|
||||
this.loadData();
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
|
||||
this.service.getSupportedLanguages().then((lang) => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
|
||||
this.loadData();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -215,10 +209,10 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
public async loadData(): Promise<any> {
|
||||
this.loading = true;
|
||||
const reqDefaultInit = REQUESTMAP[this.serviceType].getDefault;
|
||||
reqDefaultInit.setLanguage(this.locale);
|
||||
reqDefaultInit.setLanguage(this.language);
|
||||
this.getDefaultInitMessageTextMap$ = from(this.getDefaultValues(reqDefaultInit)).pipe(map((m) => m[this.currentSubMap]));
|
||||
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.locale);
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.language);
|
||||
return this.getCurrentValues(reqCustomInit)
|
||||
.then((policy) => {
|
||||
this.loading = false;
|
||||
@@ -236,14 +230,14 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private async patchSingleCurrentMap(): Promise<any> {
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.locale);
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.language);
|
||||
this.getCurrentValues(reqCustomInit).then((policy) => {
|
||||
this.getCustomInitMessageTextMap$.next(policy[this.currentSubMap]);
|
||||
});
|
||||
}
|
||||
|
||||
public checkForChanges(): void {
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.locale);
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.language);
|
||||
|
||||
(this.service as ManagementService).getCustomLoginTexts(reqCustomInit).then((policy) => {
|
||||
this.newerPolicyChangeDate = policy.customText?.details?.changeDate;
|
||||
@@ -282,7 +276,7 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
this.totalCustomPolicy[this.currentSubMap] = values;
|
||||
|
||||
this.updateRequest = setFcn(this.totalCustomPolicy);
|
||||
this.updateRequest.setLanguage(this.locale);
|
||||
this.updateRequest.setLanguage(this.language);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,7 +344,7 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
if (resp) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
(this.service as ManagementService)
|
||||
.resetCustomLoginTextToDefault(this.locale)
|
||||
.resetCustomLoginTextToDefault(this.language)
|
||||
.then(() => {
|
||||
this.updateCurrentPolicyDate();
|
||||
this.isDefault = true;
|
||||
@@ -363,7 +357,7 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
(this.service as AdminService)
|
||||
.resetCustomLoginTextToDefault(this.locale)
|
||||
.resetCustomLoginTextToDefault(this.language)
|
||||
.then(() => {
|
||||
this.updateCurrentPolicyDate();
|
||||
setTimeout(() => {
|
||||
@@ -397,8 +391,12 @@ export class LoginTextsComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
public get locale(): string {
|
||||
return this.form.get('locale')?.value;
|
||||
public get language(): string {
|
||||
return this.form.get('language')?.value;
|
||||
}
|
||||
|
||||
public set language(lang: string) {
|
||||
this.form.get('language')?.setValue(lang);
|
||||
}
|
||||
|
||||
public get currentSubMap(): string {
|
||||
|
||||
@@ -1,70 +1,86 @@
|
||||
<h2>{{ 'POLICY.MESSAGE_TEXTS.TITLE' | translate }}</h2>
|
||||
<p class="cnsl-secondary-text">{{ 'POLICY.MESSAGE_TEXTS.DESCRIPTION' | translate }}</p>
|
||||
<cnsl-info-section class="locked" *ngIf="langSvc.isNotAllowed(language) | async" [type]="InfoSectionType.WARN">
|
||||
{{ 'POLICY.LOGIN_TEXTS.ACTIVE_LANGUAGE_NOT_ALLOWED' | translate }}</cnsl-info-section
|
||||
>
|
||||
|
||||
<div *ngIf="loading" class="spinner-wr">
|
||||
<mat-spinner diameter="30" color="primary"></mat-spinner>
|
||||
</div>
|
||||
|
||||
<div class="message-texts-top-actions">
|
||||
<cnsl-form-field class="type">
|
||||
<cnsl-label>{{ 'POLICY.MESSAGE_TEXTS.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="currentType" name="currentSubMap" (selectionChange)="changedCurrentType()">
|
||||
<mat-option *ngFor="let type of MESSAGETYPES | keyvalue" [value]="type.value">
|
||||
{{ 'POLICY.MESSAGE_TEXTS.TYPES.' + type.value | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<div *ngIf="allowed$ | async">
|
||||
<div class="message-texts-top-actions">
|
||||
<cnsl-form-field class="type">
|
||||
<cnsl-label>{{ 'POLICY.MESSAGE_TEXTS.TYPE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="currentType" name="currentSubMap" (selectionChange)="changedCurrentType()">
|
||||
<mat-option *ngFor="let type of MESSAGETYPES | keyvalue" [value]="type.value">
|
||||
{{ 'POLICY.MESSAGE_TEXTS.TYPES.' + type.value | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="language">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="language" (selectionChange)="changeLocale($event)" name="language">
|
||||
<mat-option *ngFor="let lang of langSvc.allowed$ | async" [value]="lang">
|
||||
<div class="centerline">
|
||||
<span
|
||||
>{{ lang }}
|
||||
<span class="lighter cnsl-secondary-text"
|
||||
>| {{ 'POLICY.LOGIN_TEXTS.LANGUAGES.' + lang | translate }}</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
</mat-option>
|
||||
<mat-optgroup [label]="'POLICY.LOGIN_TEXTS.LANGUAGES_NOT_ALLOWED' | translate" *ngIf="langSvc.restricted$ | async">
|
||||
<mat-option *ngFor="let lang of langSvc.notAllowed$ | async" [value]="lang">
|
||||
<div class="centerline">
|
||||
<span
|
||||
>{{ lang }}
|
||||
<span class="lighter cnsl-secondary-text"
|
||||
>| {{ 'POLICY.LOGIN_TEXTS.LANGUAGES.' + lang | translate }}</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-optgroup>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="language">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LOCALE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="locale" name="locale" (selectionChange)="changeLocale($event)">
|
||||
<mat-option *ngFor="let loc of LOCALES" [value]="loc">
|
||||
<div class="centerline">
|
||||
<span
|
||||
>{{ loc }}
|
||||
<span class="lighter cnsl-secondary-text"
|
||||
>| {{ 'POLICY.LOGIN_TEXTS.LOCALES.' + loc | translate }}</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="message-text-content">
|
||||
<cnsl-edit-text
|
||||
[chips]="chips[currentType]"
|
||||
[disabled]="(canWrite$ | async) === false"
|
||||
label="one"
|
||||
[default$]="getDefaultMessageTextMap$"
|
||||
[current$]="getCustomMessageTextMap$"
|
||||
(changedValues)="updateCurrentValues($event)"
|
||||
></cnsl-edit-text>
|
||||
</div>
|
||||
|
||||
<div class="message-text-content">
|
||||
<cnsl-edit-text
|
||||
[chips]="chips[currentType]"
|
||||
[disabled]="(canWrite$ | async) === false"
|
||||
label="one"
|
||||
[default$]="getDefaultMessageTextMap$"
|
||||
[current$]="getCustomMessageTextMap$"
|
||||
(changedValues)="updateCurrentValues($event)"
|
||||
></cnsl-edit-text>
|
||||
</div>
|
||||
|
||||
<div class="message-text-actions">
|
||||
<button
|
||||
class="reset-button"
|
||||
*ngIf="(getCustomMessageTextMap$ | async) && (getCustomMessageTextMap$ | async)?.['isDefault'] === false"
|
||||
[disabled]="(canWrite$ | async) === false"
|
||||
(click)="resetDefault()"
|
||||
color="message-text-warn"
|
||||
type="submit"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-history"></i><span>{{ 'ACTIONS.RESETDEFAULT' | translate }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="save-button"
|
||||
[disabled]="!updateRequest || (canWrite$ | async) === false"
|
||||
(click)="saveCurrentMessage()"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
<div class="message-text-actions">
|
||||
<button
|
||||
class="reset-button"
|
||||
*ngIf="(getCustomMessageTextMap$ | async) && (getCustomMessageTextMap$ | async)?.['isDefault'] === false"
|
||||
[disabled]="(canWrite$ | async) === false"
|
||||
(click)="resetDefault()"
|
||||
color="message-text-warn"
|
||||
type="submit"
|
||||
mat-stroked-button
|
||||
>
|
||||
<div class="cnsl-action-button">
|
||||
<i class="las la-history"></i><span>{{ 'ACTIONS.RESETDEFAULT' | translate }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="save-button"
|
||||
[disabled]="!updateRequest || (canWrite$ | async) === false"
|
||||
(click)="saveCurrentMessage()"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.SAVE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, Injector, Input, OnDestroy, OnInit, Type } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs';
|
||||
import { BehaviorSubject, from, Observable, of, Subscription, switchMap, take, tap } from 'rxjs';
|
||||
import {
|
||||
GetDefaultDomainClaimedMessageTextRequest as AdminGetDefaultDomainClaimedMessageTextRequest,
|
||||
GetDefaultInitMessageTextRequest as AdminGetDefaultInitMessageTextRequest,
|
||||
@@ -57,10 +57,11 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { supportedLanguages } from 'src/app/utils/language';
|
||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { LanguagesService } from '../../../services/languages.service';
|
||||
|
||||
enum MESSAGETYPES {
|
||||
INIT = 'INIT',
|
||||
@@ -537,8 +538,15 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
],
|
||||
};
|
||||
|
||||
public locale: string = 'en';
|
||||
public LOCALES: string[] = supportedLanguages;
|
||||
public language: string = 'en';
|
||||
public allowed$: Observable<string[]> = this.langSvc.allowed$.pipe(
|
||||
take(1),
|
||||
tap(([firstAllowed]) => {
|
||||
this.language = firstAllowed;
|
||||
this.loadData(this.currentType);
|
||||
}),
|
||||
);
|
||||
|
||||
private sub: Subscription = new Subscription();
|
||||
public canWrite$: Observable<boolean> = this.authService.isAllowed([
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN
|
||||
@@ -553,23 +561,16 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
private toast: ToastService,
|
||||
private injector: Injector,
|
||||
private dialog: MatDialog,
|
||||
public langSvc: LanguagesService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
this.service.getSupportedLanguages().then((lang) => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
this.loadData(this.currentType);
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
this.service.getSupportedLanguages().then((lang) => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
this.loadData(this.currentType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -623,7 +624,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public changeLocale(selection: MatSelectChange): void {
|
||||
this.locale = selection.value;
|
||||
this.language = selection.value;
|
||||
this.loadData(this.currentType);
|
||||
}
|
||||
|
||||
@@ -631,11 +632,11 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
const reqDefaultInit = REQUESTMAP[this.serviceType][type].getDefault;
|
||||
|
||||
reqDefaultInit.setLanguage(this.locale);
|
||||
reqDefaultInit.setLanguage(this.language);
|
||||
this.getDefaultMessageTextMap$ = from(this.getDefaultValues(type, reqDefaultInit));
|
||||
}
|
||||
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType][type].get.setLanguage(this.locale);
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType][type].get.setLanguage(this.language);
|
||||
this.loading = true;
|
||||
return this.getCurrentValues(type, reqCustomInit)
|
||||
?.then((data) => {
|
||||
@@ -652,7 +653,7 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
const req = REQUESTMAP[this.serviceType][this.currentType].setFcn;
|
||||
const mappedValues = req(values);
|
||||
this.updateRequest = mappedValues;
|
||||
this.updateRequest.setLanguage(this.locale);
|
||||
this.updateRequest.setLanguage(this.language);
|
||||
}
|
||||
|
||||
public saveCurrentMessage(): any {
|
||||
@@ -741,23 +742,23 @@ export class MessageTextsComponent implements OnInit, OnDestroy {
|
||||
|
||||
switch (this.currentType) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return handler(this.service.resetCustomInitMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomInitMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return handler(this.service.resetCustomVerifyPhoneMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomVerifyPhoneMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.VERIFYSMSOTP:
|
||||
return handler(this.service.resetCustomVerifySMSOTPMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomVerifySMSOTPMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.VERIFYEMAILOTP:
|
||||
return handler(this.service.resetCustomVerifyEmailOTPMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomVerifyEmailOTPMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return handler(this.service.resetCustomVerifyEmailMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomVerifyEmailMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return handler(this.service.resetCustomPasswordResetMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomPasswordResetMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return handler(this.service.resetCustomDomainClaimedMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomDomainClaimedMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.PASSWORDLESS:
|
||||
return handler(this.service.resetCustomPasswordlessRegistrationMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomPasswordlessRegistrationMessageTextToDefault(this.language));
|
||||
case MESSAGETYPES.PASSWORDCHANGE:
|
||||
return handler(this.service.resetCustomPasswordChangeMessageTextToDefault(this.locale));
|
||||
return handler(this.service.resetCustomPasswordChangeMessageTextToDefault(this.language));
|
||||
default:
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="preferredLanguage">
|
||||
<mat-option *ngFor="let language of languages" [value]="language">
|
||||
<mat-option *ngFor="let language of langSvc.supported$ | async" [value]="language">
|
||||
{{ 'LANGUAGES.' + language | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
||||
@@ -20,7 +20,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { supportedLanguages } from 'src/app/utils/language';
|
||||
import { LanguagesService } from '../../services/languages.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-org-create',
|
||||
@@ -46,7 +46,6 @@ export class OrgCreateComponent {
|
||||
public pwdForm?: UntypedFormGroup;
|
||||
|
||||
public genders: Gender[] = [Gender.GENDER_FEMALE, Gender.GENDER_MALE, Gender.GENDER_UNSPECIFIED];
|
||||
public languages: string[] = supportedLanguages;
|
||||
|
||||
public policy?: PasswordComplexityPolicy.AsObject;
|
||||
public usePassword: boolean = false;
|
||||
@@ -60,6 +59,7 @@ export class OrgCreateComponent {
|
||||
private _location: Location,
|
||||
private fb: UntypedFormBuilder,
|
||||
private mgmtService: ManagementService,
|
||||
public langSvc: LanguagesService,
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
const instanceBread = new Breadcrumb({
|
||||
@@ -70,10 +70,6 @@ export class OrgCreateComponent {
|
||||
|
||||
breadcrumbService.setBreadcrumb([instanceBread]);
|
||||
this.initForm();
|
||||
|
||||
this.adminService.getSupportedLanguages().then((supportedResp) => {
|
||||
this.languages = supportedResp.languagesList;
|
||||
});
|
||||
}
|
||||
|
||||
public createSteps: number = 2;
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<cnsl-form-field>
|
||||
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="preferredLanguage">
|
||||
<mat-option *ngFor="let language of languages" [value]="language">
|
||||
<mat-option *ngFor="let language of langSvc.supported$ | async" [value]="language">
|
||||
{{ 'LANGUAGES.' + language | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Location } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Subject, debounceTime } from 'rxjs';
|
||||
import { Subject, debounceTime, Observable } from 'rxjs';
|
||||
import { AddHumanUserRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { Domain } from 'src/app/proto/generated/zitadel/org_pb';
|
||||
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
@@ -13,7 +13,6 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CountryCallingCodesService, CountryPhoneCode } from 'src/app/services/country-calling-codes.service';
|
||||
import { formatPhone } from 'src/app/utils/formatPhone';
|
||||
import { supportedLanguages } from 'src/app/utils/language';
|
||||
import {
|
||||
containsLowerCaseValidator,
|
||||
containsNumberValidator,
|
||||
@@ -25,6 +24,7 @@ import {
|
||||
phoneValidator,
|
||||
requiredValidator,
|
||||
} from '../../../modules/form-field/validators/validators';
|
||||
import { LanguagesService } from '../../../services/languages.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-user-create',
|
||||
@@ -34,7 +34,6 @@ import {
|
||||
export class UserCreateComponent implements OnInit, OnDestroy {
|
||||
public user: AddHumanUserRequest.AsObject = new AddHumanUserRequest().toObject();
|
||||
public genders: Gender[] = [Gender.GENDER_FEMALE, Gender.GENDER_MALE, Gender.GENDER_UNSPECIFIED];
|
||||
public languages: string[] = supportedLanguages;
|
||||
public selected: CountryPhoneCode | undefined = {
|
||||
countryCallingCode: '1',
|
||||
countryCode: 'US',
|
||||
@@ -61,6 +60,7 @@ export class UserCreateComponent implements OnInit, OnDestroy {
|
||||
private changeDetRef: ChangeDetectorRef,
|
||||
private _location: Location,
|
||||
private countryCallingCodesService: CountryCallingCodesService,
|
||||
public langSvc: LanguagesService,
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
breadcrumbService.setBreadcrumb([
|
||||
@@ -69,7 +69,6 @@ export class UserCreateComponent implements OnInit, OnDestroy {
|
||||
routerLink: ['/org'],
|
||||
}),
|
||||
]);
|
||||
|
||||
this.loading = true;
|
||||
this.loadOrg();
|
||||
this.mgmtService
|
||||
@@ -88,10 +87,6 @@ export class UserCreateComponent implements OnInit, OnDestroy {
|
||||
this.loading = false;
|
||||
this.changeDetRef.detectChanges();
|
||||
});
|
||||
|
||||
this.mgmtService.getSupportedLanguages().then((lang) => {
|
||||
this.languages = lang.languagesList;
|
||||
});
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
|
||||
+7
-2
@@ -19,7 +19,12 @@
|
||||
|
||||
<div class="max-width-container">
|
||||
<cnsl-meta-layout>
|
||||
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList" queryParam="id">
|
||||
<cnsl-sidenav
|
||||
[(ngModel)]="currentSetting"
|
||||
[settingsList]="settingsList"
|
||||
queryParam="id"
|
||||
(ngModelChange)="settingChanged()"
|
||||
>
|
||||
<ng-container *ngIf="currentSetting === 'general'">
|
||||
<cnsl-card
|
||||
*ngIf="user && user.human && user.human.profile"
|
||||
@@ -30,7 +35,7 @@
|
||||
[showEditImage]="true"
|
||||
[preferredLoginName]="user.preferredLoginName"
|
||||
[genders]="genders"
|
||||
[languages]="languages"
|
||||
[languages]="(langSvc.supported$ | async) || []"
|
||||
[username]="user.userName"
|
||||
[user]="user.human"
|
||||
[disabled]="false"
|
||||
|
||||
+21
-7
@@ -6,7 +6,7 @@ import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Buffer } from 'buffer';
|
||||
import { Subscription, take } from 'rxjs';
|
||||
import { from, Observable, Subscription, take } from 'rxjs';
|
||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||
import { phoneValidator, requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||
import { InfoDialogComponent } from 'src/app/modules/info-dialog/info-dialog.component';
|
||||
@@ -24,8 +24,8 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { formatPhone } from 'src/app/utils/formatPhone';
|
||||
import { supportedLanguages } from 'src/app/utils/language';
|
||||
import { EditDialogComponent, EditDialogType } from './edit-dialog/edit-dialog.component';
|
||||
import { LanguagesService } from '../../../../services/languages.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-auth-user-detail',
|
||||
@@ -35,7 +35,6 @@ import { EditDialogComponent, EditDialogType } from './edit-dialog/edit-dialog.c
|
||||
export class AuthUserDetailComponent implements OnDestroy {
|
||||
public user?: User.AsObject;
|
||||
public genders: Gender[] = [Gender.GENDER_MALE, Gender.GENDER_FEMALE, Gender.GENDER_DIVERSE];
|
||||
public languages: string[] = supportedLanguages;
|
||||
|
||||
private subscription: Subscription = new Subscription();
|
||||
|
||||
@@ -65,6 +64,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
];
|
||||
public currentSetting: string | undefined = this.settingsList[0].id;
|
||||
public loginPolicy?: LoginPolicy.AsObject;
|
||||
private savedLanguage?: string;
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
@@ -77,10 +77,12 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
private mediaMatcher: MediaMatcher,
|
||||
private _location: Location,
|
||||
activatedRoute: ActivatedRoute,
|
||||
public langSvc: LanguagesService,
|
||||
) {
|
||||
activatedRoute.queryParams.pipe(take(1)).subscribe((params: Params) => {
|
||||
const { id } = params;
|
||||
if (id) {
|
||||
this.cleanupTranslation();
|
||||
this.currentSetting = id;
|
||||
}
|
||||
});
|
||||
@@ -97,10 +99,6 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
this.loading = true;
|
||||
this.refreshUser();
|
||||
|
||||
this.userService.getSupportedLanguages().then((lang) => {
|
||||
this.languages = lang.languagesList;
|
||||
});
|
||||
|
||||
this.userService.getMyLoginPolicy().then((policy) => {
|
||||
if (policy.policy) {
|
||||
this.loginPolicy = policy.policy;
|
||||
@@ -109,6 +107,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
private changeSelection(small: boolean): void {
|
||||
this.cleanupTranslation();
|
||||
if (small) {
|
||||
this.currentSetting = undefined;
|
||||
} else {
|
||||
@@ -138,6 +137,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
}),
|
||||
]);
|
||||
}
|
||||
this.savedLanguage = resp.user?.human?.profile?.preferredLanguage;
|
||||
this.loading = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -147,9 +147,22 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
this.cleanupTranslation();
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
public settingChanged(): void {
|
||||
this.cleanupTranslation();
|
||||
}
|
||||
|
||||
private cleanupTranslation(): void {
|
||||
if (this?.savedLanguage) {
|
||||
this.translate.use(this?.savedLanguage);
|
||||
} else {
|
||||
this.translate.use(this.translate.defaultLang);
|
||||
}
|
||||
}
|
||||
|
||||
public changeUsername(): void {
|
||||
const dialogRef = this.dialog.open(EditDialogComponent, {
|
||||
data: {
|
||||
@@ -193,6 +206,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
)
|
||||
.then(() => {
|
||||
this.toast.showInfo('USER.TOAST.SAVED', true);
|
||||
this.savedLanguage = this.user?.human?.profile?.preferredLanguage;
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
[preferredLoginName]="user.preferredLoginName"
|
||||
[disabled]="(canWrite$ | async) === false"
|
||||
[genders]="genders"
|
||||
[languages]="languages"
|
||||
[languages]="(langSvc.supported$ | async) || []"
|
||||
[username]="user.userName"
|
||||
[user]="user.human"
|
||||
(submitData)="saveProfile($event)"
|
||||
|
||||
@@ -22,10 +22,11 @@ import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { formatPhone } from 'src/app/utils/formatPhone';
|
||||
import { supportedLanguages } from 'src/app/utils/language';
|
||||
import { EditDialogComponent, EditDialogType } from '../auth-user-detail/edit-dialog/edit-dialog.component';
|
||||
import { ResendEmailDialogComponent } from '../auth-user-detail/resend-email-dialog/resend-email-dialog.component';
|
||||
import { MachineSecretDialogComponent } from './machine-secret-dialog/machine-secret-dialog.component';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LanguagesService } from '../../../../services/languages.service';
|
||||
|
||||
const GENERAL: SidenavSetting = { id: 'general', i18nKey: 'USER.SETTINGS.GENERAL' };
|
||||
const GRANTS: SidenavSetting = { id: 'grants', i18nKey: 'USER.SETTINGS.USERGRANTS' };
|
||||
@@ -45,7 +46,6 @@ export class UserDetailComponent implements OnInit {
|
||||
public user!: User.AsObject;
|
||||
public metadata: Metadata.AsObject[] = [];
|
||||
public genders: Gender[] = [Gender.GENDER_MALE, Gender.GENDER_FEMALE, Gender.GENDER_DIVERSE];
|
||||
public languages: string[] = supportedLanguages;
|
||||
|
||||
public ChangeType: any = ChangeType;
|
||||
|
||||
@@ -76,6 +76,7 @@ export class UserDetailComponent implements OnInit {
|
||||
private router: Router,
|
||||
activatedRoute: ActivatedRoute,
|
||||
private mediaMatcher: MediaMatcher,
|
||||
public langSvc: LanguagesService,
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
activatedRoute.queryParams.pipe(take(1)).subscribe((params: Params) => {
|
||||
@@ -100,10 +101,6 @@ export class UserDetailComponent implements OnInit {
|
||||
this.mediaMatcher.matchMedia(mediaq).onchange = (small) => {
|
||||
this.changeSelection(small.matches);
|
||||
};
|
||||
|
||||
this.mgmtUserService.getSupportedLanguages().then((lang) => {
|
||||
this.languages = lang.languagesList;
|
||||
});
|
||||
}
|
||||
|
||||
private changeSelection(small: boolean): void {
|
||||
|
||||
@@ -54,6 +54,8 @@ import {
|
||||
DeactivateSMSProviderResponse,
|
||||
DeleteProviderRequest,
|
||||
DeleteProviderResponse,
|
||||
GetAllowedLanguagesRequest,
|
||||
GetAllowedLanguagesResponse,
|
||||
GetCustomDomainClaimedMessageTextRequest,
|
||||
GetCustomDomainClaimedMessageTextResponse,
|
||||
GetCustomDomainPolicyRequest,
|
||||
@@ -433,6 +435,11 @@ export class AdminService {
|
||||
return this.grpcService.admin.getSupportedLanguages(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public getAllowedLanguages(): Promise<GetAllowedLanguagesResponse.AsObject> {
|
||||
const req = new GetAllowedLanguagesRequest();
|
||||
return this.grpcService.admin.getAllowedLanguages(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public getDefaultLoginTexts(req: GetDefaultLoginTextsRequest): Promise<GetDefaultLoginTextsResponse.AsObject> {
|
||||
return this.grpcService.admin.getDefaultLoginTexts(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ import {
|
||||
GetMyProfileResponse,
|
||||
GetMyUserRequest,
|
||||
GetMyUserResponse,
|
||||
GetSupportedLanguagesRequest,
|
||||
GetSupportedLanguagesResponse,
|
||||
ListMyAuthFactorsRequest,
|
||||
ListMyAuthFactorsResponse,
|
||||
ListMyLinkedIDPsRequest,
|
||||
@@ -494,11 +492,6 @@ export class GrpcAuthService {
|
||||
return this.grpcService.auth.resendMyEmailVerification(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public getSupportedLanguages(): Promise<GetSupportedLanguagesResponse.AsObject> {
|
||||
const req = new GetSupportedLanguagesRequest();
|
||||
return this.grpcService.auth.getSupportedLanguages(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public getMyLoginPolicy(): Promise<GetMyLoginPolicyResponse.AsObject> {
|
||||
const req = new GetMyLoginPolicyRequest();
|
||||
return this.grpcService.auth.getMyLoginPolicy(req, null).then((resp) => resp.toObject());
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { forkJoin, Observable, ReplaySubject, Subscription } from 'rxjs';
|
||||
import { map, withLatestFrom } from 'rxjs/operators';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AdminService } from './admin.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LanguagesService {
|
||||
private supportedSubject$ = new ReplaySubject<string[]>(1);
|
||||
public supported$: Observable<string[]> = this.supportedSubject$.asObservable();
|
||||
private allowedSubject$ = new ReplaySubject<string[]>(1);
|
||||
public allowed$: Observable<string[]> = this.allowedSubject$.asObservable();
|
||||
public notAllowed$: Observable<string[]> = this.allowed$.pipe(
|
||||
withLatestFrom(this.supported$),
|
||||
map(([allowed, supported]) => {
|
||||
return supported.filter((s) => !allowed.includes(s));
|
||||
}),
|
||||
);
|
||||
public restricted$: Observable<boolean> = this.notAllowed$.pipe(
|
||||
map((notallowed) => {
|
||||
return notallowed.length > 0;
|
||||
}),
|
||||
);
|
||||
|
||||
constructor(private adminSvc: AdminService) {
|
||||
const sub: Subscription = forkJoin([
|
||||
this.adminSvc.getSupportedLanguages(),
|
||||
this.adminSvc.getAllowedLanguages(),
|
||||
]).subscribe({
|
||||
next: ([{ languagesList: supported }, { languagesList: allowed }]) => {
|
||||
this.supportedSubject$.next(supported);
|
||||
this.allowedSubject$.next(allowed);
|
||||
},
|
||||
complete: () => sub.unsubscribe(),
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: call this in https://github.com/zitadel/zitadel/pull/6965
|
||||
public newAllowed(languages: string[]) {
|
||||
this.allowedSubject$.next(languages);
|
||||
}
|
||||
|
||||
public isNotAllowed(language: string): Observable<boolean> {
|
||||
return this.notAllowed$.pipe(map((notAllowed) => notAllowed.includes(language)));
|
||||
}
|
||||
}
|
||||
@@ -551,11 +551,6 @@ export class ManagementService {
|
||||
|
||||
constructor(private readonly grpcService: GrpcService) {}
|
||||
|
||||
public getSupportedLanguages(): Promise<GetSupportedLanguagesResponse.AsObject> {
|
||||
const req = new GetSupportedLanguagesRequest();
|
||||
return this.grpcService.mgmt.getSupportedLanguages(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public getDefaultLoginTexts(req: GetDefaultLoginTextsRequest): Promise<GetDefaultLoginTextsResponse.AsObject> {
|
||||
return this.grpcService.mgmt.getDefaultLoginTexts(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user