mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-12 09:05:12 +00:00
feat: manage restrictions in console (#6965)
* 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 * feat: manage restrictions in console * check for duplicates * remove useless restriction checks * review * revert restriction renaming * manage languages * 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 * fix languages lists * simplify default language selection * translate * discard * lint * load languages for tests * load languages * lint * cleanup * lint * cleanup * get allowed only on admin * cleanup * reduce flakiness on very limited postgres * simplify langSvc * refactor according to suggestions in pr * lint * improve ux * update central allowed languages * set first allowed language as default * readd lost translations * disable sorting disallowed languages * fix permissions * lint * selectionchange for language in msg texts * initialize login texts * init message texts * lint * fix drag and drop list styles * start from 1 * cleanup * prettier * correct orgdefaultlabel * unsubscribe * lint * docs: describe language settings --------- Co-authored-by: peintnermax <[email protected]>
This commit is contained in:
co-authored by
peintnermax
parent
3842319d07
commit
d639c5200a
@@ -0,0 +1,116 @@
|
||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { UntypedFormBuilder } from '@angular/forms';
|
||||
import { LanguagesService } from '../../../services/languages.service';
|
||||
import { BehaviorSubject, concat, forkJoin, from, Observable, of, Subject, switchMap, take, takeUntil } from 'rxjs';
|
||||
import { GrpcAuthService } from '../../../services/grpc-auth.service';
|
||||
import { CdkDrag, CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
|
||||
interface State {
|
||||
allowed: string[];
|
||||
notAllowed: string[];
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-language-settings',
|
||||
templateUrl: './language-settings.component.html',
|
||||
styleUrls: ['./language-settings.component.scss'],
|
||||
})
|
||||
export class LanguageSettingsComponent {
|
||||
public canWriteRestrictions$: Observable<boolean> = this.authService.isAllowed(['iam.restrictions.write']);
|
||||
public canWriteDefaultLanguage$: Observable<boolean> = this.authService.isAllowed(['iam.write']);
|
||||
|
||||
public localState$ = new BehaviorSubject<State>({ allowed: [], notAllowed: [] });
|
||||
public remoteState$ = new BehaviorSubject<State>({ allowed: [], notAllowed: [] });
|
||||
public defaultLang$ = new BehaviorSubject<string>('');
|
||||
|
||||
public loading: boolean = false;
|
||||
constructor(
|
||||
private service: AdminService,
|
||||
private toast: ToastService,
|
||||
private langSvc: LanguagesService,
|
||||
private authService: GrpcAuthService,
|
||||
) {
|
||||
const sub = forkJoin([
|
||||
langSvc.allowed$.pipe(take(1)),
|
||||
langSvc.notAllowed$.pipe(take(1)),
|
||||
from(this.service.getDefaultLanguage()).pipe(take(1)),
|
||||
]).subscribe({
|
||||
next: ([allowed, notAllowed, { language: defaultLang }]) => {
|
||||
this.defaultLang$.next(defaultLang);
|
||||
this.remoteState$.next({ notAllowed: [...notAllowed], ...{ allowed: [...allowed] } });
|
||||
this.localState$.next({ notAllowed: [...notAllowed], ...{ allowed: [...allowed] } });
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
drop(event: CdkDragDrop<string[]>) {
|
||||
if (event.previousContainer === event.container) {
|
||||
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
|
||||
} else {
|
||||
transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public defaultLangPredicate = (lang: CdkDrag<string>) => {
|
||||
return !!lang?.data && lang.data !== this.defaultLang$.value;
|
||||
};
|
||||
|
||||
public isRemotelyAllowed$(lang: string): Observable<boolean> {
|
||||
return this.remoteState$.pipe(map(({ allowed }) => allowed.includes(lang)));
|
||||
}
|
||||
|
||||
public allowAll(): void {
|
||||
this.localState$.next({ allowed: [...this.allLocalLangs()], notAllowed: [] });
|
||||
}
|
||||
|
||||
public disallowAll(): void {
|
||||
const disallowed = this.allLocalLangs().filter((lang) => lang !== this.defaultLang$.value);
|
||||
this.localState$.next({ allowed: [this.defaultLang$.value], notAllowed: disallowed });
|
||||
}
|
||||
|
||||
public submit(): void {
|
||||
const { allowed, notAllowed } = this.localState$.value;
|
||||
const sub = from(this.service.setRestrictions(undefined, allowed)).subscribe({
|
||||
next: () => {
|
||||
this.remoteState$.next({
|
||||
allowed: [...allowed],
|
||||
notAllowed: [...notAllowed],
|
||||
});
|
||||
this.langSvc.newAllowed(allowed);
|
||||
this.toast.showInfo('SETTING.LANGUAGES.ALLOWED_SAVED', true);
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public discard(): void {
|
||||
this.localState$.next(this.remoteState$.value);
|
||||
}
|
||||
|
||||
public setDefaultLang(lang: string): void {
|
||||
const sub = from(this.service.setDefaultLanguage(lang)).subscribe({
|
||||
next: () => {
|
||||
this.defaultLang$.next(lang);
|
||||
this.toast.showInfo('SETTING.LANGUAGES.DEFAULT_SAVED', true);
|
||||
},
|
||||
error: this.toast.showError,
|
||||
complete: () => {
|
||||
sub.unsubscribe();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private allLocalLangs(): string[] {
|
||||
return [...this.localState$.value.allowed, ...this.localState$.value.notAllowed];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user