mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-12 00:55:12 +00:00
fix(console): better error messages (#5409)
* fix(console): better error messages * fix: fix i18n error labels * rollout cnsl-i18n-errors * move errors to form-field * fix: form control errors * rollout validators * translate * replace variables * lint * self review * fix confirm validation * use help observable * fix validation errors * cleanup * custom validator for idp templates * lint * validate on blur * remove element --------- Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
co-authored by
Max Peintner
parent
e00cc187fa
commit
93e1fe0056
@@ -0,0 +1,20 @@
|
||||
<div class="cnsl-form-field-wrapper" (click)="_control.onContainerClick && _control.onContainerClick($event)">
|
||||
<ng-content select="cnsl-label"></ng-content>
|
||||
<div class="cnsl-rel" #inputContainer>
|
||||
<ng-content></ng-content>
|
||||
<ng-content select="cnslSuffix"></ng-content>
|
||||
</div>
|
||||
<ng-container *ngIf="help$ && help$ | async as help">
|
||||
<div [ngSwitch]="help.type" class="cnsl-form-field-subscript-wrapper">
|
||||
<div *ngSwitchCase="'hints'" class="cnsl-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<ng-content select="cnsl-hint"></ng-content>
|
||||
</div>
|
||||
<div *ngSwitchCase="'errors'" class="cnsl-form-field-error-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<span cnslError *ngFor="let err of help.validationErrors">
|
||||
{{ err.i18nKey | translate : err.params }}
|
||||
</span>
|
||||
<ng-content select="cnsl-error"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
+79
-17
@@ -10,6 +10,7 @@ import {
|
||||
HostListener,
|
||||
Inject,
|
||||
InjectionToken,
|
||||
Input,
|
||||
OnDestroy,
|
||||
QueryList,
|
||||
ViewChild,
|
||||
@@ -17,11 +18,10 @@ import {
|
||||
} from '@angular/core';
|
||||
import { NgControl } from '@angular/forms';
|
||||
import { MatLegacyFormFieldControl as MatFormFieldControl } from '@angular/material/legacy-form-field';
|
||||
import { Subject } from 'rxjs';
|
||||
import { startWith, takeUntil } from 'rxjs/operators';
|
||||
import { combineLatest, map, Observable, of, startWith, Subject, takeUntil } from 'rxjs';
|
||||
|
||||
import { CnslErrorDirective, CNSL_ERROR } from '../error/error.directive';
|
||||
import { cnslFormFieldAnimations } from './animations';
|
||||
import { CnslErrorDirective, CNSL_ERROR } from './error.directive';
|
||||
|
||||
export const CNSL_FORM_FIELD = new InjectionToken<CnslFormFieldComponent>('CnslFormFieldComponent');
|
||||
|
||||
@@ -29,6 +29,15 @@ class CnslFormFieldBase {
|
||||
constructor(public _elementRef: ElementRef) {}
|
||||
}
|
||||
|
||||
interface Help {
|
||||
type: 'hints' | 'errors';
|
||||
validationErrors?: Array<ValidationError>;
|
||||
}
|
||||
interface ValidationError {
|
||||
i18nKey: string;
|
||||
params: any;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-form-field',
|
||||
templateUrl: './form-field.component.html',
|
||||
@@ -59,19 +68,24 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
||||
@ViewChild('inputContainer') _inputContainerRef!: ElementRef;
|
||||
@ContentChild(MatFormFieldControl) _controlNonStatic!: MatFormFieldControl<any>;
|
||||
@ContentChild(MatFormFieldControl, { static: true }) _controlStatic!: MatFormFieldControl<any>;
|
||||
@Input() public disableValidationErrors = false;
|
||||
|
||||
get _control(): MatFormFieldControl<any> {
|
||||
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
||||
}
|
||||
set _control(value: MatFormFieldControl<any>) {
|
||||
this._explicitFormFieldControl = value;
|
||||
}
|
||||
|
||||
private _explicitFormFieldControl!: MatFormFieldControl<any>;
|
||||
readonly stateChanges: Subject<void> = new Subject<void>();
|
||||
public help$?: Observable<Help>;
|
||||
|
||||
_subscriptAnimationState: string = '';
|
||||
|
||||
@ContentChildren(CNSL_ERROR as any, { descendants: true }) _errorChildren!: QueryList<CnslErrorDirective>;
|
||||
|
||||
// TODO: Remove?
|
||||
@HostListener('blur', ['false'])
|
||||
_focusChanged(isFocused: boolean): void {
|
||||
if (isFocused !== this.focused && !isFocused) {
|
||||
@@ -91,8 +105,6 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
||||
}
|
||||
|
||||
public ngAfterViewInit(): void {
|
||||
// Avoid animations on load.
|
||||
this._subscriptAnimationState = 'enter';
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
@@ -103,25 +115,21 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
||||
|
||||
public ngAfterContentInit(): void {
|
||||
this._validateControlChild();
|
||||
this.mapHelp();
|
||||
|
||||
const control = this._control;
|
||||
control.stateChanges.pipe(startWith(null)).subscribe(() => {
|
||||
control.stateChanges.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
|
||||
this._syncDescribedByIds();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
|
||||
// Run change detection if the value changes.
|
||||
// TODO: Is that not redundant (see immediately above)?
|
||||
if (control.ngControl && control.ngControl.valueChanges) {
|
||||
control.ngControl.valueChanges
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(() => this._changeDetectorRef.markForCheck());
|
||||
}
|
||||
|
||||
// Update the aria-described by when the number of errors changes.
|
||||
this._errorChildren.changes.pipe(startWith(null)).subscribe(() => {
|
||||
this._syncDescribedByIds();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/** Throws an error if the form field's control is missing. */
|
||||
@@ -147,14 +155,68 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
||||
}
|
||||
}
|
||||
|
||||
private mapHelp(): void {
|
||||
const validationErrors$: Observable<Array<ValidationError>> = this.disableValidationErrors
|
||||
? of([])
|
||||
: this._control.stateChanges?.pipe(
|
||||
map(() => this.currentValidationErrors()),
|
||||
startWith([]),
|
||||
) || of([]);
|
||||
|
||||
const childrenErrors$: Observable<boolean> = this._errorChildren.changes.pipe(
|
||||
map(() => {
|
||||
return this._errorChildren.length > 0;
|
||||
}),
|
||||
startWith(false),
|
||||
);
|
||||
|
||||
this.help$ = combineLatest([validationErrors$, childrenErrors$]).pipe(
|
||||
map((combined) => {
|
||||
return combined[0].length >= 1
|
||||
? <Help>{
|
||||
type: 'errors',
|
||||
validationErrors: combined[0],
|
||||
}
|
||||
: combined[1]
|
||||
? <Help>{
|
||||
type: 'errors',
|
||||
}
|
||||
: <Help>{
|
||||
type: 'hints',
|
||||
validationErrors: undefined,
|
||||
};
|
||||
}),
|
||||
);
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
private currentValidationErrors(): Array<ValidationError> {
|
||||
return (
|
||||
Object.entries(this._control.ngControl?.control?.errors || [])
|
||||
?.filter(this.filterErrorsProperties)
|
||||
.map(this.mapToValidationError)
|
||||
.filter(this.distinctFilter) || []
|
||||
);
|
||||
}
|
||||
|
||||
private filterErrorsProperties(kv: [string, any]): boolean {
|
||||
return typeof kv[1] == 'object' && (kv[1] as { valid: boolean }).valid === false;
|
||||
}
|
||||
|
||||
private mapToValidationError(kv: [string, any]): ValidationError {
|
||||
return {
|
||||
i18nKey: 'ERRORS.INVALID_FORMAT',
|
||||
...(kv[1] as ValidationError | any),
|
||||
};
|
||||
}
|
||||
|
||||
private distinctFilter(_: ValidationError, index: number, arr: Array<ValidationError>): boolean {
|
||||
return arr.findIndex((item) => item.i18nKey) === index;
|
||||
}
|
||||
|
||||
/** Determines whether a class from the NgControl should be forwarded to the host element. */
|
||||
_shouldForward(prop: keyof NgControl): boolean {
|
||||
const ngControl: any = this._control ? this._control.ngControl : null;
|
||||
return ngControl && ngControl[prop];
|
||||
}
|
||||
|
||||
/** Determines whether to display hints or errors. */
|
||||
_getDisplayedMessages(): 'error' | 'hint' {
|
||||
return this._errorChildren && this._errorChildren.length > 0 ? 'error' : 'hint';
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<div class="cnsl-form-field-wrapper" (click)="_control.onContainerClick && _control.onContainerClick($event)">
|
||||
<ng-content select="cnsl-label"></ng-content>
|
||||
<div class="cnsl-rel" #inputContainer>
|
||||
<ng-content></ng-content>
|
||||
<ng-content select="cnslSuffix"></ng-content>
|
||||
</div>
|
||||
<div class="cnsl-form-field-subscript-wrapper" [ngSwitch]="_getDisplayedMessages()">
|
||||
<div *ngSwitchCase="'error'" class="cnsl-form-field-error-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<ng-content select="cnsl-error"></ng-content>
|
||||
</div>
|
||||
<div *ngSwitchCase="'hint'" class="cnsl-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||
<ng-content select="cnsl-hint"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,15 +1,16 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LabelModule } from 'src/app/modules/label/label.module';
|
||||
|
||||
import { LabelComponent } from '../label/label.component';
|
||||
import { CnslErrorDirective } from './error.directive';
|
||||
import { CnslFormFieldComponent } from './form-field.component';
|
||||
import { CnslErrorDirective } from './error/error.directive';
|
||||
import { CnslFormFieldComponent } from './field/form-field.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [CnslFormFieldComponent, CnslErrorDirective],
|
||||
imports: [CommonModule, MatRippleModule, LabelModule],
|
||||
imports: [CommonModule, MatRippleModule, LabelModule, TranslateModule],
|
||||
exports: [CnslFormFieldComponent, LabelComponent, CnslErrorDirective],
|
||||
})
|
||||
export class FormFieldModule {}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
||||
|
||||
export function containsSymbolValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return regexpValidator(c, /[^a-z0-9]/gi, 'ERRORS.SYMBOLERROR');
|
||||
}
|
||||
|
||||
export function containsNumberValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return regexpValidator(c, /[0-9]/g, 'ERRORS.NUMBERERROR');
|
||||
}
|
||||
|
||||
export function containsUpperCaseValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return regexpValidator(c, /[A-Z]/g, 'ERRORS.UPPERCASEMISSING');
|
||||
}
|
||||
|
||||
export function containsLowerCaseValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return regexpValidator(c, /[a-z]/g, 'ERRORS.LOWERCASEMISSING');
|
||||
}
|
||||
|
||||
export function phoneValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return regexpValidator(c, /^($|(\+|00)[0-9 ]+$)/, 'ERRORS.PHONE');
|
||||
}
|
||||
|
||||
export function requiredValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return i18nErr(Validators.required(c), 'ERRORS.REQUIRED');
|
||||
}
|
||||
|
||||
export function emailValidator(c: AbstractControl): ValidationErrors | null {
|
||||
return i18nErr(Validators.email(c), 'ERRORS.NOTANEMAIL');
|
||||
}
|
||||
|
||||
export function minLengthValidator(minLength: number): ValidatorFn {
|
||||
return (c: AbstractControl): ValidationErrors | null => {
|
||||
return i18nErr(Validators.minLength(minLength)(c), 'ERRORS.MINLENGTH', { requiredLength: minLength });
|
||||
};
|
||||
}
|
||||
|
||||
export function passwordConfirmValidator(passwordControlName: string = 'password') {
|
||||
return (c: AbstractControl): ValidationErrors | null => {
|
||||
if (!c.parent || !c) {
|
||||
return null;
|
||||
}
|
||||
const pwd = c.parent.get(passwordControlName);
|
||||
const cpwd = c;
|
||||
|
||||
if (!pwd || !cpwd) {
|
||||
return null;
|
||||
}
|
||||
if (pwd.value !== cpwd.value) {
|
||||
return i18nErr(undefined, 'ERRORS.PWNOTEQUAL');
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
function regexpValidator(c: AbstractControl, regexp: RegExp, i18nKey: string): ValidationErrors | null {
|
||||
return !c.value || regexp.test(c.value) ? null : i18nErr({ invalid: true }, i18nKey, { regexp: regexp });
|
||||
}
|
||||
|
||||
function i18nErr(err: ValidationErrors | null | undefined, i18nKey: string, params?: any): ValidationErrors | null {
|
||||
if (err === null) {
|
||||
return null;
|
||||
} else {
|
||||
return {
|
||||
...err,
|
||||
invalid: true,
|
||||
[i18nKey.toLowerCase().replaceAll('.', '')]: {
|
||||
valid: false,
|
||||
i18nKey: i18nKey,
|
||||
params: params,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
-12
@@ -28,23 +28,23 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="val" *ngIf="this.policy.hasSymbol">
|
||||
<i *ngIf="password?.errors?.symbolValidator" class="las la-times red"></i>
|
||||
<i *ngIf="!password?.errors?.symbolValidator" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text"> {{ 'USER.VALIDATION.SYMBOLERROR' | translate }}</span>
|
||||
<i *ngIf="password?.pristine || password?.errors?.errorssymbolerror" class="las la-times red"></i>
|
||||
<i *ngIf="password?.dirty && !password?.errors?.errorssymbolerror" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text"> {{ 'ERRORS.SYMBOLERROR' | translate }}</span>
|
||||
</div>
|
||||
<div class="val" *ngIf="this.policy.hasNumber">
|
||||
<i *ngIf="password?.errors?.numberValidator" class="las la-times red"></i>
|
||||
<i *ngIf="!password?.errors?.numberValidator" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text"> {{ 'USER.VALIDATION.NUMBERERROR' | translate }}</span>
|
||||
<i *ngIf="password?.pristine || password?.errors?.errorsnumbererror" class="las la-times red"></i>
|
||||
<i *ngIf="password?.dirty && !password?.errors?.errorsnumbererror" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text"> {{ 'ERRORS.NUMBERERROR' | translate }}</span>
|
||||
</div>
|
||||
<div class="val" *ngIf="this.policy.hasUppercase">
|
||||
<i *ngIf="password?.errors?.upperCaseValidator" class="las la-times red"></i>
|
||||
<i *ngIf="!password?.errors?.upperCaseValidator" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text"> {{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}</span>
|
||||
<i *ngIf="password?.pristine || password?.errors?.errorsuppercasemissing" class="las la-times red"></i>
|
||||
<i *ngIf="password?.dirty && !password?.errors?.errorsuppercasemissing" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text"> {{ 'ERRORS.UPPERCASEMISSING' | translate }}</span>
|
||||
</div>
|
||||
<div class="val" *ngIf="this.policy.hasLowercase">
|
||||
<i *ngIf="password?.errors?.lowerCaseValidator" class="las la-times red"></i>
|
||||
<i *ngIf="!password?.errors?.lowerCaseValidator" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text">{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}</span>
|
||||
<i *ngIf="password?.pristine || password?.errors?.errorslowercasemissing" class="las la-times red"></i>
|
||||
<i *ngIf="password?.dirty && !password?.errors?.errorslowercasemissing" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text">{{ 'ERRORS.LOWERCASEMISSING' | translate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { take } from 'rxjs';
|
||||
@@ -18,6 +18,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
||||
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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
@@ -45,11 +46,11 @@ export class LoginPolicyComponent implements OnInit {
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
public PasswordlessType: any = PasswordlessType;
|
||||
public lifetimeForm: UntypedFormGroup = this.fb.group({
|
||||
passwordCheckLifetime: [{ disabled: true }, [Validators.required]],
|
||||
externalLoginCheckLifetime: [{ disabled: true }, [Validators.required]],
|
||||
mfaInitSkipLifetime: [{ disabled: true }, [Validators.required]],
|
||||
secondFactorCheckLifetime: [{ disabled: true }, [Validators.required]],
|
||||
multiFactorCheckLifetime: [{ disabled: true }, [Validators.required]],
|
||||
passwordCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
externalLoginCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
mfaInitSkipLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
secondFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
multiFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
});
|
||||
constructor(
|
||||
private toast: ToastService,
|
||||
|
||||
+5
-4
@@ -1,10 +1,11 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import {
|
||||
MatLegacyDialog as MatDialog,
|
||||
MatLegacyDialogRef as MatDialogRef,
|
||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||
} from '@angular/material/legacy-dialog';
|
||||
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||
import {
|
||||
AddSMSProviderTwilioRequest,
|
||||
UpdateSMSProviderTwilioRequest,
|
||||
@@ -44,15 +45,15 @@ export class DialogAddSMSProviderComponent {
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {
|
||||
this.twilioForm = this.fb.group({
|
||||
sid: ['', [Validators.required]],
|
||||
senderNumber: ['', [Validators.required]],
|
||||
sid: ['', [requiredValidator]],
|
||||
senderNumber: ['', [requiredValidator]],
|
||||
});
|
||||
|
||||
this.smsProviders = data.smsProviders;
|
||||
if (!!this.twilio) {
|
||||
this.twilioForm.patchValue(this.twilio);
|
||||
} else {
|
||||
this.twilioForm.addControl('token', new FormControl('', Validators.required));
|
||||
this.twilioForm.addControl('token', new FormControl('', requiredValidator));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -1,5 +1,5 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||
import { take } from 'rxjs';
|
||||
import {
|
||||
@@ -15,6 +15,7 @@ import { DebugNotificationProvider, SMSProvider, SMSProviderConfigState } from '
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
@@ -55,11 +56,11 @@ export class NotificationSettingsComponent implements OnInit {
|
||||
private authService: GrpcAuthService,
|
||||
) {
|
||||
this.form = this.fb.group({
|
||||
senderAddress: [{ disabled: true, value: '' }, [Validators.required]],
|
||||
senderName: [{ disabled: true, value: '' }, [Validators.required]],
|
||||
tls: [{ disabled: true, value: true }, [Validators.required]],
|
||||
hostAndPort: [{ disabled: true, value: '' }, [Validators.required]],
|
||||
user: [{ disabled: true, value: '' }, [Validators.required]],
|
||||
senderAddress: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
senderName: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
tls: [{ disabled: true, value: true }, [requiredValidator]],
|
||||
hostAndPort: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
user: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { take } from 'rxjs';
|
||||
import {
|
||||
@@ -12,6 +12,7 @@ import { OIDCSettings } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-oidc-configuration',
|
||||
@@ -31,10 +32,10 @@ export class OIDCConfigurationComponent implements OnInit {
|
||||
private authService: GrpcAuthService,
|
||||
) {
|
||||
this.form = this.fb.group({
|
||||
accessTokenLifetime: [{ disabled: true }, [Validators.required]],
|
||||
idTokenLifetime: [{ disabled: true }, [Validators.required]],
|
||||
refreshTokenExpiration: [{ disabled: true }, [Validators.required]],
|
||||
refreshTokenIdleExpiration: [{ disabled: true }, [Validators.required]],
|
||||
accessTokenLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
idTokenLifetime: [{ disabled: true }, [requiredValidator]],
|
||||
refreshTokenExpiration: [{ disabled: true }, [requiredValidator]],
|
||||
refreshTokenIdleExpiration: [{ disabled: true }, [requiredValidator]],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+9
-8
@@ -1,10 +1,11 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import {
|
||||
MatLegacyDialogRef as MatDialogRef,
|
||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||
} from '@angular/material/legacy-dialog';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||
import { UpdateSecretGeneratorRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { SecretGeneratorType } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||
|
||||
@@ -33,13 +34,13 @@ export class DialogAddSecretGeneratorComponent {
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {
|
||||
this.specsForm = this.fb.group({
|
||||
generatorType: [SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET, [Validators.required]],
|
||||
expiry: [1, [Validators.required]],
|
||||
includeDigits: [true, [Validators.required]],
|
||||
includeLowerLetters: [true, [Validators.required]],
|
||||
includeSymbols: [true, [Validators.required]],
|
||||
includeUpperLetters: [true, [Validators.required]],
|
||||
length: [6, [Validators.required]],
|
||||
generatorType: [SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET, [requiredValidator]],
|
||||
expiry: [1, [requiredValidator]],
|
||||
includeDigits: [true, [requiredValidator]],
|
||||
includeLowerLetters: [true, [requiredValidator]],
|
||||
includeSymbols: [true, [requiredValidator]],
|
||||
includeUpperLetters: [true, [requiredValidator]],
|
||||
length: [6, [requiredValidator]],
|
||||
});
|
||||
|
||||
this.generatorType?.setValue(data.type);
|
||||
|
||||
+3
-2
@@ -1,11 +1,12 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import {
|
||||
MatLegacyDialogRef as MatDialogRef,
|
||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||
} from '@angular/material/legacy-dialog';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { requiredValidator } from '../form-field/validators/validators';
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-project-role-detail-dialog',
|
||||
@@ -24,7 +25,7 @@ export class ProjectRoleDetailDialogComponent {
|
||||
) {
|
||||
this.projectId = data.projectId;
|
||||
this.formGroup = new UntypedFormGroup({
|
||||
key: new UntypedFormControl({ value: '', disabled: true }, [Validators.required]),
|
||||
key: new UntypedFormControl({ value: '', disabled: true }, [requiredValidator]),
|
||||
displayName: new UntypedFormControl(''),
|
||||
group: new UntypedFormControl(''),
|
||||
});
|
||||
|
||||
+8
-7
@@ -1,7 +1,7 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
@@ -20,6 +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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@@ -51,12 +52,12 @@ export class ProviderGithubESComponent {
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
this.form = new UntypedFormGroup({
|
||||
name: new UntypedFormControl('', [Validators.required]),
|
||||
clientId: new UntypedFormControl('', [Validators.required]),
|
||||
clientSecret: new UntypedFormControl('', [Validators.required]),
|
||||
authorizationEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
tokenEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
userEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
name: new UntypedFormControl('', [requiredValidator]),
|
||||
clientId: new UntypedFormControl('', [requiredValidator]),
|
||||
clientSecret: new UntypedFormControl('', [requiredValidator]),
|
||||
authorizationEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
tokenEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
userEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
@@ -20,6 +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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@@ -53,8 +54,8 @@ export class ProviderGithubComponent {
|
||||
) {
|
||||
this.form = new FormGroup({
|
||||
name: new FormControl('', []),
|
||||
clientId: new FormControl('', [Validators.required]),
|
||||
clientSecret: new FormControl('', [Validators.required]),
|
||||
clientId: new FormControl('', [requiredValidator]),
|
||||
clientSecret: new FormControl('', [requiredValidator]),
|
||||
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
@@ -20,6 +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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@@ -53,8 +54,8 @@ export class ProviderGoogleComponent {
|
||||
) {
|
||||
this.form = new FormGroup({
|
||||
name: new FormControl('', []),
|
||||
clientId: new FormControl('', [Validators.required]),
|
||||
clientSecret: new FormControl('', [Validators.required]),
|
||||
clientId: new FormControl('', [requiredValidator]),
|
||||
clientSecret: new FormControl('', [requiredValidator]),
|
||||
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { take } from 'rxjs/operators';
|
||||
import {
|
||||
@@ -19,6 +19,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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@@ -82,11 +83,11 @@ export class ProviderJWTComponent {
|
||||
});
|
||||
|
||||
this.form = new UntypedFormGroup({
|
||||
name: new UntypedFormControl('', [Validators.required]),
|
||||
headerName: new UntypedFormControl('', [Validators.required]),
|
||||
issuer: new UntypedFormControl('', [Validators.required]),
|
||||
jwtEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
keysEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
name: new UntypedFormControl('', [requiredValidator]),
|
||||
headerName: new UntypedFormControl('', [requiredValidator]),
|
||||
issuer: new UntypedFormControl('', [requiredValidator]),
|
||||
jwtEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
keysEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
@@ -20,6 +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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@@ -52,13 +53,13 @@ export class ProviderOAuthComponent {
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
this.form = new UntypedFormGroup({
|
||||
name: new UntypedFormControl('', [Validators.required]),
|
||||
clientId: new UntypedFormControl('', [Validators.required]),
|
||||
clientSecret: new UntypedFormControl('', [Validators.required]),
|
||||
authorizationEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
tokenEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
userEndpoint: new UntypedFormControl('', [Validators.required]),
|
||||
idAttribute: new UntypedFormControl('', [Validators.required]),
|
||||
name: new UntypedFormControl('', [requiredValidator]),
|
||||
clientId: new UntypedFormControl('', [requiredValidator]),
|
||||
clientSecret: new UntypedFormControl('', [requiredValidator]),
|
||||
authorizationEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
tokenEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
userEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||
idAttribute: new UntypedFormControl('', [requiredValidator]),
|
||||
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, Injector, Type } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
@@ -20,6 +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 { requiredValidator } from '../../form-field/validators/validators';
|
||||
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@@ -51,10 +52,10 @@ export class ProviderOIDCComponent {
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
this.oidcFormGroup = new UntypedFormGroup({
|
||||
name: new UntypedFormControl('', [Validators.required]),
|
||||
clientId: new UntypedFormControl('', [Validators.required]),
|
||||
clientSecret: new UntypedFormControl('', [Validators.required]),
|
||||
issuer: new UntypedFormControl('', [Validators.required]),
|
||||
name: new UntypedFormControl('', [requiredValidator]),
|
||||
clientId: new UntypedFormControl('', [requiredValidator]),
|
||||
clientSecret: new UntypedFormControl('', [requiredValidator]),
|
||||
issuer: new UntypedFormControl('', [requiredValidator]),
|
||||
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user