): 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';
- }
}
diff --git a/console/src/app/modules/form-field/form-field.component.html b/console/src/app/modules/form-field/form-field.component.html
deleted file mode 100644
index 5de3d9e64..000000000
--- a/console/src/app/modules/form-field/form-field.component.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
diff --git a/console/src/app/modules/form-field/form-field.module.ts b/console/src/app/modules/form-field/form-field.module.ts
index e085fc35d..48d2fb7af 100644
--- a/console/src/app/modules/form-field/form-field.module.ts
+++ b/console/src/app/modules/form-field/form-field.module.ts
@@ -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 {}
diff --git a/console/src/app/modules/form-field/validators/validators.ts b/console/src/app/modules/form-field/validators/validators.ts
new file mode 100644
index 000000000..9c89699f4
--- /dev/null
+++ b/console/src/app/modules/form-field/validators/validators.ts
@@ -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,
+ },
+ };
+ }
+}
diff --git a/console/src/app/modules/password-complexity-view/password-complexity-view.component.html b/console/src/app/modules/password-complexity-view/password-complexity-view.component.html
index fff5887ec..73edd8cf0 100644
--- a/console/src/app/modules/password-complexity-view/password-complexity-view.component.html
+++ b/console/src/app/modules/password-complexity-view/password-complexity-view.component.html
@@ -28,23 +28,23 @@
-
-
- {{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
+
+
+ {{ 'ERRORS.SYMBOLERROR' | translate }}
-
-
- {{ 'USER.VALIDATION.NUMBERERROR' | translate }}
+
+
+ {{ 'ERRORS.NUMBERERROR' | translate }}
-
-
- {{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
+
+
+ {{ 'ERRORS.UPPERCASEMISSING' | translate }}
-
-
- {{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
+
+
+ {{ 'ERRORS.LOWERCASEMISSING' | translate }}
diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.ts b/console/src/app/modules/policies/login-policy/login-policy.component.ts
index 866df410f..b05ad5905 100644
--- a/console/src/app/modules/policies/login-policy/login-policy.component.ts
+++ b/console/src/app/modules/policies/login-policy/login-policy.component.ts
@@ -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,
diff --git a/console/src/app/modules/policies/notification-settings/dialog-add-sms-provider/dialog-add-sms-provider.component.ts b/console/src/app/modules/policies/notification-settings/dialog-add-sms-provider/dialog-add-sms-provider.component.ts
index 75c22add5..18ed54e5e 100644
--- a/console/src/app/modules/policies/notification-settings/dialog-add-sms-provider/dialog-add-sms-provider.component.ts
+++ b/console/src/app/modules/policies/notification-settings/dialog-add-sms-provider/dialog-add-sms-provider.component.ts
@@ -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));
}
}
diff --git a/console/src/app/modules/policies/notification-settings/notification-settings.component.ts b/console/src/app/modules/policies/notification-settings/notification-settings.component.ts
index 2cf94dbec..59fde5858 100644
--- a/console/src/app/modules/policies/notification-settings/notification-settings.component.ts
+++ b/console/src/app/modules/policies/notification-settings/notification-settings.component.ts
@@ -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]],
});
}
diff --git a/console/src/app/modules/policies/oidc-configuration/oidc-configuration.component.ts b/console/src/app/modules/policies/oidc-configuration/oidc-configuration.component.ts
index 974133bb6..abf5bc94e 100644
--- a/console/src/app/modules/policies/oidc-configuration/oidc-configuration.component.ts
+++ b/console/src/app/modules/policies/oidc-configuration/oidc-configuration.component.ts
@@ -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]],
});
}
diff --git a/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts
index 06dcd5a42..c8d888f91 100644
--- a/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts
+++ b/console/src/app/modules/policies/secret-generator/dialog-add-secret-generator/dialog-add-secret-generator.component.ts
@@ -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);
diff --git a/console/src/app/modules/project-role-detail-dialog/project-role-detail-dialog.component.ts b/console/src/app/modules/project-role-detail-dialog/project-role-detail-dialog.component.ts
index 55845500e..c30099fc5 100644
--- a/console/src/app/modules/project-role-detail-dialog/project-role-detail-dialog.component.ts
+++ b/console/src/app/modules/project-role-detail-dialog/project-role-detail-dialog.component.ts
@@ -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(''),
});
diff --git a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts
index 740b4b99e..e57a80be4 100644
--- a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts
+++ b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.ts
@@ -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'], []),
});
diff --git a/console/src/app/modules/providers/provider-github/provider-github.component.ts b/console/src/app/modules/providers/provider-github/provider-github.component.ts
index fa2742941..511b47657 100644
--- a/console/src/app/modules/providers/provider-github/provider-github.component.ts
+++ b/console/src/app/modules/providers/provider-github/provider-github.component.ts
@@ -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'], []),
});
diff --git a/console/src/app/modules/providers/provider-google/provider-google.component.ts b/console/src/app/modules/providers/provider-google/provider-google.component.ts
index 5866ab77d..221c621b3 100644
--- a/console/src/app/modules/providers/provider-google/provider-google.component.ts
+++ b/console/src/app/modules/providers/provider-google/provider-google.component.ts
@@ -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'], []),
});
diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts
index a6c1d7556..29ea834c0 100644
--- a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts
+++ b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.ts
@@ -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]),
});
}
diff --git a/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts b/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts
index a1958e1d6..d4331be27 100644
--- a/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts
+++ b/console/src/app/modules/providers/provider-oauth/provider-oauth.component.ts
@@ -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'], []),
});
diff --git a/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts b/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts
index 39e8d28e9..7c4a3ff99 100644
--- a/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts
+++ b/console/src/app/modules/providers/provider-oidc/provider-oidc.component.ts
@@ -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'], []),
});
diff --git a/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.ts b/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.ts
index 9f34b02fd..49f4a98d1 100644
--- a/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.ts
+++ b/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.ts
@@ -1,9 +1,10 @@
import { Component, Inject } from '@angular/core';
-import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
+import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import {
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 { Action, FlowType, TriggerType } from 'src/app/proto/generated/zitadel/action_pb';
import { SetTriggerActionsRequest } from 'src/app/proto/generated/zitadel/management_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
@@ -34,8 +35,8 @@ export class AddFlowDialogComponent {
}
this.form = this.fb.group({
- triggerType: [data.triggerType ? data.triggerType : '', [Validators.required]],
- actionIdsList: [data.actions ? (data.actions as Action.AsObject[]).map((a) => a.id) : [], [Validators.required]],
+ triggerType: [data.triggerType ? data.triggerType : '', [requiredValidator]],
+ actionIdsList: [data.actions ? (data.actions as Action.AsObject[]).map((a) => a.id) : [], [requiredValidator]],
});
this.getActionIds();
diff --git a/console/src/app/pages/org-create/org-create.component.html b/console/src/app/pages/org-create/org-create.component.html
index c51220946..5dafb0142 100644
--- a/console/src/app/pages/org-create/org-create.component.html
+++ b/console/src/app/pages/org-create/org-create.component.html
@@ -57,37 +57,22 @@
{{ 'USER.PROFILE.USERNAME' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.EMAIL' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.FIRSTNAME' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.LASTNAME' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.NICKNAME' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.CREATE.GENDERLANGSECTION' | translate }}
@@ -99,9 +84,6 @@
{{ 'GENDERS.' + gender | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}
@@ -109,9 +91,6 @@
{{ 'LANGUAGES.' + language | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
@@ -148,10 +127,6 @@
{{ 'USER.PASSWORD.NEW' | translate }}
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PASSWORD.CONFIRM' | translate }}
@@ -162,13 +137,6 @@
formControlName="confirmPassword"
type="password"
/>
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
-
- {{ 'USER.PASSWORD.NOTEQUAL' | translate }}
-
diff --git a/console/src/app/pages/org-create/org-create.component.ts b/console/src/app/pages/org-create/org-create.component.ts
index 3f7ebeb6e..ce97569fa 100644
--- a/console/src/app/pages/org-create/org-create.component.ts
+++ b/console/src/app/pages/org-create/org-create.component.ts
@@ -4,7 +4,15 @@ import { Component } from '@angular/core';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms';
import { MatLegacySlideToggleChange as MatSlideToggleChange } from '@angular/material/legacy-slide-toggle';
import { Router } from '@angular/router';
-import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from 'src/app/pages/validators';
+import {
+ containsLowerCaseValidator,
+ containsNumberValidator,
+ containsSymbolValidator,
+ containsUpperCaseValidator,
+ minLengthValidator,
+ passwordConfirmValidator,
+ requiredValidator,
+} from 'src/app/modules/form-field/validators/validators';
import { SetUpOrgRequest } from 'src/app/proto/generated/zitadel/admin_pb';
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
import { Gender } from 'src/app/proto/generated/zitadel/user_pb';
@@ -13,26 +21,6 @@ import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
-function passwordConfirmValidator(c: AbstractControl): any {
- if (!c.parent || !c) {
- return;
- }
- const pwd = c.parent.get('password');
- const cpwd = c.parent.get('confirmPassword');
-
- if (!pwd || !cpwd) {
- return;
- }
- if (pwd.value !== cpwd.value) {
- return {
- invalid: true,
- notequal: {
- valid: false,
- },
- };
- }
-}
-
@Component({
selector: 'cnsl-org-create',
templateUrl: './org-create.component.html',
@@ -49,7 +37,7 @@ function passwordConfirmValidator(c: AbstractControl): any {
})
export class OrgCreateComponent {
public orgForm: UntypedFormGroup = this.fb.group({
- name: ['', [Validators.required]],
+ name: ['', [requiredValidator]],
domain: [''],
});
@@ -133,10 +121,10 @@ export class OrgCreateComponent {
private initForm(): void {
this.userForm = this.fb.group({
- userName: ['', [Validators.required]],
- firstName: ['', [Validators.required]],
- lastName: ['', [Validators.required]],
- email: ['', [Validators.required]],
+ userName: ['', [requiredValidator]],
+ firstName: ['', [requiredValidator]],
+ lastName: ['', [requiredValidator]],
+ email: ['', [requiredValidator]],
isVerified: [false, []],
gender: [''],
nickName: [''],
@@ -145,7 +133,7 @@ export class OrgCreateComponent {
}
public initPwdValidators(): void {
- const validators: Validators[] = [Validators.required];
+ const validators: Validators[] = [requiredValidator];
if (this.usePassword) {
this.mgmtService.getDefaultPasswordComplexityPolicy().then((data) => {
@@ -153,23 +141,23 @@ export class OrgCreateComponent {
this.policy = data.policy;
if (this.policy.minLength) {
- validators.push(Validators.minLength(this.policy.minLength));
+ validators.push(minLengthValidator(this.policy.minLength));
}
if (this.policy.hasLowercase) {
- validators.push(lowerCaseValidator);
+ validators.push(containsLowerCaseValidator);
}
if (this.policy.hasUppercase) {
- validators.push(upperCaseValidator);
+ validators.push(containsUpperCaseValidator);
}
if (this.policy.hasNumber) {
- validators.push(numberValidator);
+ validators.push(containsNumberValidator);
}
if (this.policy.hasSymbol) {
- validators.push(symbolValidator);
+ validators.push(containsSymbolValidator);
}
const pwdValidators = [...validators] as ValidatorFn[];
- const confirmPwdValidators = [...validators, passwordConfirmValidator] as ValidatorFn[];
+ const confirmPwdValidators = [requiredValidator, passwordConfirmValidator()] as ValidatorFn[];
this.pwdForm = this.fb.group({
password: ['', pwdValidators],
confirmPassword: ['', confirmPwdValidators],
@@ -189,13 +177,13 @@ export class OrgCreateComponent {
this.createSteps = 1;
this.orgForm = this.fb.group({
- name: ['', [Validators.required]],
+ name: ['', [requiredValidator]],
});
} else {
this.createSteps = 2;
this.orgForm = this.fb.group({
- name: ['', [Validators.required]],
+ name: ['', [requiredValidator]],
domain: [''],
});
}
diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.html b/console/src/app/pages/projects/apps/app-create/app-create.component.html
index 6a8091cc7..a31a937dd 100644
--- a/console/src/app/pages/projects/apps/app-create/app-create.component.html
+++ b/console/src/app/pages/projects/apps/app-create/app-create.component.html
@@ -37,7 +37,6 @@
{{ 'APP.NAME' | translate }}
- {{ 'PROJECT.APP.NAMEREQUIRED' | translate }}
{{ 'APP.TYPETITLE' | translate }}
diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.ts b/console/src/app/pages/projects/apps/app-create/app-create.component.ts
index 41adaf793..9baf56949 100644
--- a/console/src/app/pages/projects/apps/app-create/app-create.component.ts
+++ b/console/src/app/pages/projects/apps/app-create/app-create.component.ts
@@ -2,13 +2,14 @@ import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { StepperSelectionEvent } from '@angular/cdk/stepper';
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
-import { AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
+import { AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Buffer } from 'buffer';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
+import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
import {
APIAuthMethodType,
OIDCAppType,
@@ -127,8 +128,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
private breadcrumbService: BreadcrumbService,
) {
this.form = this.fb.group({
- name: ['', [Validators.required]],
- appType: ['', [Validators.required]],
+ name: ['', [requiredValidator]],
+ appType: ['', [requiredValidator]],
// apptype OIDC
responseTypesList: ['', []],
grantTypesList: ['', []],
@@ -140,8 +141,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
this.initForm();
this.firstFormGroup = this.fb.group({
- name: ['', [Validators.required]],
- appType: [WEB_TYPE, [Validators.required]],
+ name: ['', [requiredValidator]],
+ appType: [WEB_TYPE, [requiredValidator]],
});
this.samlConfigForm = this.fb.group({
@@ -192,7 +193,7 @@ export class AppCreateComponent implements OnInit, OnDestroy {
});
this.secondFormGroup = this.fb.group({
- authMethod: [this.authMethods[0].key, [Validators.required]],
+ authMethod: [this.authMethods[0].key, [requiredValidator]],
});
this.secondFormGroup.valueChanges.subscribe((form) => {
@@ -276,8 +277,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
public setDevFormValidators(): void {
if (this.isDevOIDC) {
- const grantTypesControl = new UntypedFormControl('', [Validators.required]);
- const responseTypesControl = new UntypedFormControl('', [Validators.required]);
+ const grantTypesControl = new UntypedFormControl('', [requiredValidator]);
+ const responseTypesControl = new UntypedFormControl('', [requiredValidator]);
this.form.addControl('grantTypesList', grantTypesControl);
this.form.addControl('responseTypesList', responseTypesControl);
diff --git a/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.ts b/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.ts
index cc7ed140c..374902a43 100644
--- a/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.ts
+++ b/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.ts
@@ -1,9 +1,10 @@
import { animate, animateChild, query, stagger, style, transition, trigger } from '@angular/animations';
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
-import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
+import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Subscription } from 'rxjs';
+import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
import { BulkAddProjectRolesRequest } from 'src/app/proto/generated/zitadel/management_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
@@ -32,7 +33,7 @@ export class ProjectRoleCreateComponent implements OnInit, OnDestroy {
public formArray!: UntypedFormArray;
public formGroup: UntypedFormGroup = this.fb.group({
- key: new UntypedFormControl('', [Validators.required]),
+ key: new UntypedFormControl('', [requiredValidator]),
displayName: new UntypedFormControl(''),
group: new UntypedFormControl(''),
});
@@ -50,7 +51,7 @@ export class ProjectRoleCreateComponent implements OnInit, OnDestroy {
public addEntry(): void {
const newGroup = this.fb.group({
- key: new UntypedFormControl('', [Validators.required]),
+ key: new UntypedFormControl('', [requiredValidator]),
displayName: new UntypedFormControl(''),
group: new UntypedFormControl(''),
});
diff --git a/console/src/app/pages/users/user-create-machine/user-create-machine.component.html b/console/src/app/pages/users/user-create-machine/user-create-machine.component.html
index d9e10c369..9685f9066 100644
--- a/console/src/app/pages/users/user-create-machine/user-create-machine.component.html
+++ b/console/src/app/pages/users/user-create-machine/user-create-machine.component.html
@@ -12,19 +12,10 @@
{{ 'USER.MACHINE.USERNAME' | translate }}*
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
-
- {{ 'USER.VALIDATION.NOEMAIL' | translate }}
-
{{ 'USER.MACHINE.NAME' | translate }}*
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.MACHINE.DESCRIPTION' | translate }}
diff --git a/console/src/app/pages/users/user-create-machine/user-create-machine.component.ts b/console/src/app/pages/users/user-create-machine/user-create-machine.component.ts
index 3b8bcccf6..a402a7f1d 100644
--- a/console/src/app/pages/users/user-create-machine/user-create-machine.component.ts
+++ b/console/src/app/pages/users/user-create-machine/user-create-machine.component.ts
@@ -1,8 +1,9 @@
import { Location } from '@angular/common';
import { Component, OnDestroy } from '@angular/core';
-import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
+import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
+import { minLengthValidator, requiredValidator } from 'src/app/modules/form-field/validators/validators';
import { AddMachineUserRequest } from 'src/app/proto/generated/zitadel/management_pb';
import { AccessTokenType } from 'src/app/proto/generated/zitadel/user_pb';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
@@ -45,8 +46,8 @@ export class UserCreateMachineComponent implements OnDestroy {
private initForm(): void {
this.userForm = this.fb.group({
- userName: ['', [Validators.required, Validators.minLength(2)]],
- name: ['', [Validators.required]],
+ userName: ['', [requiredValidator, minLengthValidator(2)]],
+ name: ['', [requiredValidator]],
description: ['', []],
accessTokenType: [AccessTokenType.ACCESS_TOKEN_TYPE_BEARER, []],
});
diff --git a/console/src/app/pages/users/user-create/user-create.component.html b/console/src/app/pages/users/user-create/user-create.component.html
index 4705f2c68..acd3a8e10 100644
--- a/console/src/app/pages/users/user-create/user-create.component.html
+++ b/console/src/app/pages/users/user-create/user-create.component.html
@@ -15,12 +15,6 @@
{{ 'USER.PROFILE.EMAIL' | translate }}*
-
- {{ 'USER.VALIDATION.NOTANEMAIL' | translate }}
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.USERNAME' | translate }}*
@@ -31,35 +25,19 @@
[ngStyle]="{ 'padding-right': suffixPadding ? suffixPadding : '10px' }"
/>
{{ envSuffix }}
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
-
- {{ 'USER.VALIDATION.NOEMAIL' | translate }}
-
{{ 'USER.PROFILE.FIRSTNAME' | translate }}*
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.LASTNAME' | translate }}*
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.NICKNAME' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
@@ -84,10 +62,6 @@
{{ 'USER.PASSWORD.NEWINITIAL' | translate }}
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PASSWORD.CONFIRMINITIAL' | translate }}
@@ -98,13 +72,6 @@
formControlName="confirmPassword"
type="password"
/>
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
-
- {{ 'USER.PASSWORD.NOTEQUAL' | translate }}
-
@@ -120,9 +87,6 @@
{{ 'GENDERS.' + gender | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}
@@ -130,9 +94,6 @@
{{ 'LANGUAGES.' + language | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
@@ -154,9 +115,6 @@
{{ 'USER.PROFILE.PHONE' | translate }}
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
diff --git a/console/src/app/pages/users/user-create/user-create.component.ts b/console/src/app/pages/users/user-create/user-create.component.ts
index 811e57c17..c7e9976e5 100644
--- a/console/src/app/pages/users/user-create/user-create.component.ts
+++ b/console/src/app/pages/users/user-create/user-create.component.ts
@@ -13,27 +13,17 @@ 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 { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../../validators';
-
-function passwordConfirmValidator(c: AbstractControl): any {
- if (!c.parent || !c) {
- return;
- }
- const pwd = c.parent.get('password');
- const cpwd = c.parent.get('confirmPassword');
-
- if (!pwd || !cpwd) {
- return;
- }
- if (pwd.value !== cpwd.value) {
- return {
- invalid: true,
- notequal: {
- valid: false,
- },
- };
- }
-}
+import {
+ containsLowerCaseValidator,
+ containsNumberValidator,
+ containsSymbolValidator,
+ containsUpperCaseValidator,
+ emailValidator,
+ minLengthValidator,
+ passwordConfirmValidator,
+ phoneValidator,
+ requiredValidator,
+} from '../../../modules/form-field/validators/validators';
@Component({
selector: 'cnsl-user-create',
@@ -113,40 +103,40 @@ export class UserCreateComponent implements OnInit, OnDestroy {
private initForm(): void {
this.userForm = this.fb.group({
- email: ['', [Validators.required, Validators.email]],
- userName: ['', [Validators.required, Validators.minLength(2)]],
- firstName: ['', Validators.required],
- lastName: ['', Validators.required],
+ email: ['', [requiredValidator, emailValidator]],
+ userName: ['', [requiredValidator, minLengthValidator(2)]],
+ firstName: ['', requiredValidator],
+ lastName: ['', requiredValidator],
nickName: [''],
gender: [],
preferredLanguage: [''],
- phone: [''],
+ phone: ['', phoneValidator],
isVerified: [false, []],
});
- const validators: Validators[] = [Validators.required];
+ const validators: Validators[] = [requiredValidator];
this.mgmtService.getPasswordComplexityPolicy().then((data) => {
if (data.policy) {
this.policy = data.policy;
if (this.policy.minLength) {
- validators.push(Validators.minLength(this.policy.minLength));
+ validators.push(minLengthValidator(this.policy.minLength));
}
if (this.policy.hasLowercase) {
- validators.push(lowerCaseValidator);
+ validators.push(containsLowerCaseValidator);
}
if (this.policy.hasUppercase) {
- validators.push(upperCaseValidator);
+ validators.push(containsUpperCaseValidator);
}
if (this.policy.hasNumber) {
- validators.push(numberValidator);
+ validators.push(containsNumberValidator);
}
if (this.policy.hasSymbol) {
- validators.push(symbolValidator);
+ validators.push(containsSymbolValidator);
}
const pwdValidators = [...validators] as ValidatorFn[];
- const confirmPwdValidators = [...validators, passwordConfirmValidator] as ValidatorFn[];
+ const confirmPwdValidators = [requiredValidator, passwordConfirmValidator()] as ValidatorFn[];
this.pwdForm = this.fb.group({
password: ['', pwdValidators],
@@ -203,14 +193,13 @@ export class UserCreateComponent implements OnInit, OnDestroy {
public setCountryCallingCode(): void {
let value = (this.phone?.value as string) || '';
- this.phone?.setValue('+' + this.selected?.countryCallingCode + ' ' + value.replace(/\+[0-9]*\s/, ''));
+ this.countryPhoneCodes.forEach((code) => (value = value.replace(`+${code.countryCallingCode}`, '')));
+ value = value.trim();
+ this.phone?.setValue('+' + this.selected?.countryCallingCode + ' ' + value);
}
ngOnInit(): void {
- // Set default selected country for phone numbers
- const defaultCountryCallingCode = 'CH';
this.countryPhoneCodes = this.countryCallingCodesService.getCountryCallingCodes();
- this.selected = this.countryPhoneCodes.find((code) => code.countryCode === defaultCountryCallingCode);
}
ngOnDestroy(): void {
diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts
index 7eb7446cd..af50666e2 100644
--- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts
+++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts
@@ -1,12 +1,14 @@
import { MediaMatcher } from '@angular/cdk/layout';
import { Location } from '@angular/common';
import { Component, EventEmitter, OnDestroy } from '@angular/core';
+import { Validators } from '@angular/forms';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { ActivatedRoute, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Buffer } from 'buffer';
import { 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 { MetadataDialogComponent } from 'src/app/modules/metadata/metadata-dialog/metadata-dialog.component';
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
@@ -304,6 +306,7 @@ export class AuthUserDetailComponent implements OnDestroy {
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
value: this.user?.human?.phone?.phone,
type: type,
+ validator: Validators.compose([phoneValidator, requiredValidator]),
},
width: '400px',
});
diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.html b/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.html
index 5b4b21f14..2aa944959 100644
--- a/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.html
+++ b/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.html
@@ -3,40 +3,39 @@
{{ data.descriptionKey | translate }}
-
-
- {{ 'USER.PROFILE.COUNTRY' | translate }}
-
-
-
-
- {{ country.countryName }}
- +{{ country.countryCallingCode }}
-
-
-
-
- {{ data.labelKey | translate }}
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
-
-
+
@@ -58,9 +51,6 @@
{{ 'USER.PASSWORD.OLD' | translate }}
-
- {{ 'USER.PASSWORD.REQUIRED' | translate }}
-
@@ -71,10 +61,6 @@
{{ 'USER.PASSWORD.NEW' | translate }}
-
-
- {{ 'USER.VALIDATION.REQUIRED' | translate }}
-
{{ 'USER.PASSWORD.CONFIRM' | translate }}
@@ -85,9 +71,6 @@
type="password"
formControlName="confirmPassword"
/>
-
- {{ 'USER.PASSWORD.NOTEQUAL' | translate }}
-
diff --git a/console/src/app/pages/users/user-detail/password/password.component.ts b/console/src/app/pages/users/user-detail/password/password.component.ts
index ef32a1478..904981047 100644
--- a/console/src/app/pages/users/user-detail/password/password.component.ts
+++ b/console/src/app/pages/users/user-detail/password/password.component.ts
@@ -2,28 +2,21 @@ import { Component, OnDestroy } from '@angular/core';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Subject, Subscription, take, takeUntil } from 'rxjs';
-import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from 'src/app/pages/validators';
+import {
+ containsLowerCaseValidator,
+ containsNumberValidator,
+ containsSymbolValidator,
+ containsUpperCaseValidator,
+ minLengthValidator,
+ passwordConfirmValidator,
+ requiredValidator,
+} from 'src/app/modules/form-field/validators/validators';
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.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';
-function passwordConfirmValidator(c: AbstractControl): any {
- if (!c.parent || !c) {
- return;
- }
- const pwd = c.parent.get('password');
- const cpwd = c.parent.get('confirmPassword');
-
- if (!pwd || !cpwd) {
- return;
- }
- if (pwd.value !== cpwd.value) {
- return { invalid: true, notequal: 'Password is not equal' };
- }
-}
-
@Component({
selector: 'cnsl-password',
templateUrl: './password.component.html',
@@ -76,7 +69,7 @@ export class PasswordComponent implements OnDestroy {
});
}
- const validators: Validators[] = [Validators.required];
+ const validators: Validators[] = [requiredValidator];
this.authService
.getMyPasswordComplexityPolicy()
.then((resp) => {
@@ -84,19 +77,19 @@ export class PasswordComponent implements OnDestroy {
this.policy = resp.policy;
}
if (this.policy.minLength) {
- validators.push(Validators.minLength(this.policy.minLength));
+ validators.push(minLengthValidator(this.policy.minLength));
}
if (this.policy.hasLowercase) {
- validators.push(lowerCaseValidator);
+ validators.push(containsLowerCaseValidator);
}
if (this.policy.hasUppercase) {
- validators.push(upperCaseValidator);
+ validators.push(containsUpperCaseValidator);
}
if (this.policy.hasNumber) {
- validators.push(numberValidator);
+ validators.push(containsNumberValidator);
}
if (this.policy.hasSymbol) {
- validators.push(symbolValidator);
+ validators.push(containsSymbolValidator);
}
this.setupForm(validators);
@@ -117,13 +110,13 @@ export class PasswordComponent implements OnDestroy {
if (this.userId) {
this.passwordForm = this.fb.group({
password: ['', validators],
- confirmPassword: ['', [...validators, passwordConfirmValidator]],
+ confirmPassword: ['', [requiredValidator, passwordConfirmValidator()]],
});
} else {
this.passwordForm = this.fb.group({
- currentPassword: ['', Validators.required],
+ currentPassword: ['', requiredValidator],
newPassword: ['', validators],
- confirmPassword: ['', [...validators, passwordConfirmValidator]],
+ confirmPassword: ['', [requiredValidator, passwordConfirmValidator()]],
});
}
}
diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts
index a5788dde2..5ce365ae5 100644
--- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts
+++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts
@@ -1,12 +1,14 @@
import { MediaMatcher } from '@angular/cdk/layout';
import { Location } from '@angular/common';
import { Component, EventEmitter, OnInit } from '@angular/core';
+import { Validators } from '@angular/forms';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Buffer } from 'buffer';
import { take } from 'rxjs/operators';
import { ChangeType } from 'src/app/modules/changes/changes.component';
+import { phoneValidator, requiredValidator } from 'src/app/modules/form-field/validators/validators';
import { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
import { MetadataDialogComponent } from 'src/app/modules/metadata/metadata-dialog/metadata-dialog.component';
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
@@ -461,6 +463,7 @@ export class UserDetailComponent implements OnInit {
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
value: this.user.human?.phone?.phone,
type: EditDialogType.PHONE,
+ validator: Validators.compose([phoneValidator, requiredValidator]),
},
width: '400px',
});
diff --git a/console/src/app/pages/validators.ts b/console/src/app/pages/validators.ts
deleted file mode 100644
index 13236d232..000000000
--- a/console/src/app/pages/validators.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { UntypedFormControl } from '@angular/forms';
-
-export function symbolValidator(c: UntypedFormControl): any {
- const REGEXP: RegExp = /[^a-z0-9]/gi;
-
- return REGEXP.test(c.value)
- ? null
- : {
- invalid: true,
- symbolValidator: {
- valid: false,
- },
- };
-}
-
-export function numberValidator(c: UntypedFormControl): any {
- const REGEXP = /[0-9]/g;
-
- return REGEXP.test(c.value)
- ? null
- : {
- invalid: true,
- numberValidator: {
- valid: false,
- },
- };
-}
-
-export function upperCaseValidator(c: UntypedFormControl): any {
- const REGEXP = /[A-Z]/g;
-
- return REGEXP.test(c.value)
- ? null
- : {
- invalid: true,
- upperCaseValidator: {
- valid: false,
- },
- };
-}
-
-export function lowerCaseValidator(c: UntypedFormControl): any {
- const REGEXP = /[a-z]/g;
-
- return REGEXP.test(c.value)
- ? null
- : {
- invalid: true,
- lowerCaseValidator: {
- valid: false,
- },
- };
-}
diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
index b0b9fd725..085af409a 100644
--- a/console/src/assets/i18n/de.json
+++ b/console/src/assets/i18n/de.json
@@ -239,11 +239,20 @@
"NOROWS": "Keine Daten"
},
"ERRORS": {
- "REQUIRED": "Bitte fülle alle benötigten Felder aus.",
+ "REQUIRED": "Bitte fülle dieses Feld aus.",
"TOKENINVALID": {
"TITLE": "Du bist abgemeldet",
"DESCRIPTION": "Klicke auf \"Einloggen\", um Dich erneut anzumelden."
- }
+ },
+ "INVALID_FORMAT": "Das Format is ungültig.",
+ "NOTANEMAIL": "Der eingegebene Wert ist keine E-Mail Adresse.",
+ "MINLENGTH": "Muss mindestens {{requiredLength}} Zeichen lang sein.",
+ "UPPERCASEMISSING": "Muss einen Grossbuchstaben beinhalten.",
+ "LOWERCASEMISSING": "Muss einen Kleinbuchstaben beinhalten.",
+ "SYMBOLERROR": "Muss ein Symbol/Satzzeichen beinhalten.",
+ "NUMBERERROR": "Muss eine Ziffer beinhalten.",
+ "PWNOTEQUAL": "Die Passwörter stimmen nicht überein.",
+ "PHONE": "Die Telefonnummer muss mit 00 oder + starten."
},
"USER": {
"SETTINGS": {
@@ -524,8 +533,7 @@
"SET": "Passwort neu setzen",
"RESENDNOTIFICATION": "Email zum Zurücksetzen senden",
"REQUIRED": "Bitte prüfe, dass alle notwendigen Felder ausgefüllt sind.",
- "MINLENGTHERROR": "Muss mindestens {{value}} Zeichen lang sein.",
- "NOTEQUAL": "Die Passwörter stimmen nicht überein."
+ "MINLENGTHERROR": "Muss mindestens {{value}} Zeichen lang sein."
},
"ID": "ID",
"EMAIL": "E-Mail",
@@ -579,17 +587,6 @@
"3": "Nach Rolle filtern"
}
},
- "VALIDATION": {
- "INVALIDPATTERN": "Das Passwort erfüllt nicht die vorgegebenen Regeln.",
- "NOTANEMAIL": "Der eingegebene Wert ist keine E-Mail Adresse.",
- "REQUIRED": "Das Eingabefeld ist leer.",
- "MINLENGTH": "Das Passwort muss mindestens {{requiredLength}} Zeichen lang sein.",
- "NOEMAIL": "Benutzername darf keine E-Mail-Adresse sein.",
- "UPPERCASEMISSING": "Muss einen Grossbuchstaben beinhalten.",
- "LOWERCASEMISSING": "Muss einen Kleinbuchstaben beinhalten.",
- "SYMBOLERROR": "Muss ein Symbol/Satzzeichen beinhalten.",
- "NUMBERERROR": "Muss eine Ziffer beinhalten."
- },
"STATE": {
"0": "Unbekannt",
"1": "Aktiv",
diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json
index a30577cb1..76bafca94 100644
--- a/console/src/assets/i18n/en.json
+++ b/console/src/assets/i18n/en.json
@@ -240,11 +240,20 @@
"NOROWS": "No data"
},
"ERRORS": {
- "REQUIRED": "Some required fields are missing.",
+ "REQUIRED": "Please fill in this field.",
"TOKENINVALID": {
"TITLE": "Your authorization token has expired.",
"DESCRIPTION": "Click the button below to log in again."
- }
+ },
+ "INVALID_FORMAT": "The formatting is invalid.",
+ "NOTANEMAIL": "The given value is not an e-mail address.",
+ "MINLENGTH": "Must be at least {{requiredLength}} characters long.",
+ "UPPERCASEMISSING": "Must include an uppercase character.",
+ "LOWERCASEMISSING": "Must include a lowercase character.",
+ "SYMBOLERROR": "Must include a symbol or punctuation mark.",
+ "NUMBERERROR": "Must include a digit.",
+ "PWNOTEQUAL": "The passwords provided do not match.",
+ "PHONE": "The phone number must start with 00 or +."
},
"USER": {
"SETTINGS": {
@@ -525,8 +534,7 @@
"SET": "Set New Password",
"RESENDNOTIFICATION": "Send Password Reset Link",
"REQUIRED": "Some required fields are missing.",
- "MINLENGTHERROR": "Has to be at least {{value}} characters long.",
- "NOTEQUAL": "The passwords provided do not match."
+ "MINLENGTHERROR": "Has to be at least {{value}} characters long."
},
"ID": "ID",
"EMAIL": "E-mail",
@@ -580,17 +588,6 @@
"3": "filter for rolename"
}
},
- "VALIDATION": {
- "INVALIDPATTERN": "The password does not fulfil the defined rules.",
- "NOTANEMAIL": "The given value is not an e-mail address",
- "REQUIRED": "The input field is empty.",
- "MINLENGTH": "The password has to be at least {{requiredLength}} characters long.",
- "NOEMAIL": "The user name cannot be an e-mail address.",
- "UPPERCASEMISSING": "Must include an uppercase character.",
- "LOWERCASEMISSING": "Must include a lowercase character.",
- "SYMBOLERROR": "Must include a symbol or punctuation mark.",
- "NUMBERERROR": "Must include a digit."
- },
"STATE": {
"0": "Unknown",
"1": "Active",
diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json
index 1be1c6b7a..aafc1f7b7 100644
--- a/console/src/assets/i18n/fr.json
+++ b/console/src/assets/i18n/fr.json
@@ -239,11 +239,20 @@
"NOROWS": "Pas de données"
},
"ERRORS": {
- "REQUIRED": "Certains champs obligatoires sont manquants.",
+ "REQUIRED": "Remplis ce champ s'il te plaît.",
"TOKENINVALID": {
"TITLE": "Votre jeton d'autorisation a expiré.",
"DESCRIPTION": "Cliquez sur le bouton ci-dessous pour vous reconnecter."
- }
+ },
+ "INVALID_FORMAT": "Le format n'est pas valide",
+ "NOTANEMAIL": "La valeur donnée n'est pas une adresse e-mail",
+ "MINLENGTH": "Doit comporter au moins {{length}} caractères.",
+ "UPPERCASEMISSING": "Doit inclure un caractère majuscule.",
+ "LOWERCASEMISSING": "Doit inclure un caractère minuscule.",
+ "SYMBOLERROR": "Doit inclure un symbole ou un signe de ponctuation.",
+ "NUMBERERROR": "Doit inclure un chiffre.",
+ "PWNOTEQUAL": "Les mots de passe fournis ne correspondent pas.",
+ "PHONE": "Le numéro de téléphone doit commencer par 00 ou +."
},
"USER": {
"SETTINGS": {
@@ -524,8 +533,7 @@
"SET": "Définir un nouveau mot de passe",
"RESENDNOTIFICATION": "Envoyer le lien de réinitialisation du mot de passe",
"REQUIRED": "Certains champs obligatoires sont manquants.",
- "MINLENGTHERROR": "Doit comporter au moins {{value}} caractères.",
- "NOTEQUAL": "Les mots de passe fournis ne correspondent pas."
+ "MINLENGTHERROR": "Doit comporter au moins {{value}} caractères."
},
"ID": "ID",
"EMAIL": "E-mail",
@@ -579,17 +587,6 @@
"3": "filtre pour nom de rôle"
}
},
- "VALIDATION": {
- "INVALIDPATTERN": "Le mot de passe ne répond pas aux règles définies.",
- "NOTANEMAIL": "La valeur donnée n'est pas une adresse e-mail",
- "REQUIRED": "Le champ de saisie est vide.",
- "MINLENGTH": "Le mot de passe doit comporter au moins{{length}} caractères.",
- "NOEMAIL": "Le nom d'utilisateur ne peut pas être une adresse électronique.",
- "UPPERCASEMISSING": "Doit inclure un caractère majuscule.",
- "LOWERCASEMISSING": "Doit inclure un caractère minuscule.",
- "SYMBOLERROR": "Doit inclure un symbole ou un signe de ponctuation.",
- "NUMBERERROR": "Doit inclure un chiffre."
- },
"STATE": {
"0": "Inconnu",
"1": "Actif",
diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json
index 0ab2621b5..7651422d2 100644
--- a/console/src/assets/i18n/it.json
+++ b/console/src/assets/i18n/it.json
@@ -239,11 +239,20 @@
"NOROWS": "Nessun dato"
},
"ERRORS": {
- "REQUIRED": "Mancano alcuni campi obbligatori.",
+ "REQUIRED": "Compilare questo campo.",
"TOKENINVALID": {
"TITLE": "Il tuo Access Token \u00e8 scaduto.",
"DESCRIPTION": "Clicca il pulsante per richiedere una nuova sessione."
- }
+ },
+ "INVALID_FORMAT": "Il formato non è valido.",
+ "NOTANEMAIL": "Il valore dato non \u00e8 un indirizzo e-mail.",
+ "MINLENGTH": "Deve essere lunga almeno {{requiredLength}} caratteri.",
+ "UPPERCASEMISSING": "Deve includere un carattere maiuscolo.",
+ "LOWERCASEMISSING": "Deve includere un carattere minuscolo.",
+ "SYMBOLERROR": "Deve includere un simbolo o un segno di punteggiatura.",
+ "NUMBERERROR": "Deve includere una cifra.",
+ "PWNOTEQUAL": "Le password fornite non corrispondono.",
+ "PHONE": "Il numero di telefono deve iniziare con 00 o +."
},
"USER": {
"SETTINGS": {
@@ -524,8 +533,7 @@
"SET": "Imposta nuova password",
"RESENDNOTIFICATION": "Invia email per la reimpostazione",
"REQUIRED": "Mancano alcuni campi obbligatori.",
- "MINLENGTHERROR": "Deve essere lunga almeno {{valore}} caratteri.",
- "NOTEQUAL": "Le password fornite non corrispondono."
+ "MINLENGTHERROR": "Deve essere lunga almeno {{valore}} caratteri."
},
"ID": "ID",
"EMAIL": "E-mail",
@@ -579,17 +587,6 @@
"3": "filtro per rolename"
}
},
- "VALIDATION": {
- "INVALIDPATTERN": "La password non soddisfa le regole definite.",
- "NOTANEMAIL": "Il valore dato non \u00e8 un indirizzo e-mail",
- "REQUIRED": "Il campo di input \u00e8 vuoto.",
- "MINLENGTH": "Deve essere lunga almeno {{requiredLength}} caratteri.",
- "NOEMAIL": "Il nome utente non pu\u00f2 essere un indirizzo e-mail.",
- "UPPERCASEMISSING": "Deve includere un carattere maiuscolo.",
- "LOWERCASEMISSING": "Deve includere un carattere minuscolo.",
- "SYMBOLERROR": "Deve includere un simbolo o un segno di punteggiatura.",
- "NUMBERERROR": "Deve includere una cifra."
- },
"STATE": {
"0": "Sconosciuto",
"1": "Attivo",
diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json
index dca5fefd4..527179beb 100644
--- a/console/src/assets/i18n/pl.json
+++ b/console/src/assets/i18n/pl.json
@@ -239,11 +239,20 @@
"NOROWS": "Brak danych"
},
"ERRORS": {
- "REQUIRED": "Brakuje niektórych wymaganych pól.",
+ "REQUIRED": "Proszę wypełnić to pole.",
"TOKENINVALID": {
"TITLE": "Twój token autoryzacji wygasł.",
"DESCRIPTION": "Kliknij przycisk poniżej, aby ponownie się zalogować."
- }
+ },
+ "INVALID_FORMAT": "Format jest nieprawidłowy.",
+ "NOTANEMAIL": "Podana wartość nie jest adresem e-mail.",
+ "MINLENGTH": "Musi mieć co najmniej {{requiredLength}} znaków.",
+ "UPPERCASEMISSING": "Musi zawierać wielką literę.",
+ "LOWERCASEMISSING": "Musi zawierać małą literę.",
+ "SYMBOLERROR": "Musi zawierać symbol lub znak interpunkcyjny.",
+ "NUMBERERROR": "Musi zawierać cyfrę.",
+ "PWNOTEQUAL": "Podane hasła nie są identyczne.",
+ "PHONE": "Numer telefonu musi zaczynać się od 00 lub +."
},
"USER": {
"SETTINGS": {
@@ -524,8 +533,7 @@
"SET": "Ustaw nowe hasło",
"RESENDNOTIFICATION": "Wyślij link resetowania hasła",
"REQUIRED": "Brakuje niektórych wymaganych pól.",
- "MINLENGTHERROR": "Musi mieć co najmniej {{value}} znaków.",
- "NOTEQUAL": "Podane hasła nie są identyczne."
+ "MINLENGTHERROR": "Musi mieć co najmniej {{value}} znaków."
},
"ID": "ID",
"EMAIL": "E-mail",
@@ -579,17 +587,6 @@
"3": "filtruj po roli"
}
},
- "VALIDATION": {
- "INVALIDPATTERN": "Hasło nie spełnia określonych reguł.",
- "NOTANEMAIL": "Podana wartość nie jest adresem e-mail",
- "REQUIRED": "Pole jest puste.",
- "MINLENGTH": "Hasło musi mieć co najmniej {{requiredLength}} znaków.",
- "NOEMAIL": "Nazwa użytkownika nie może być adresem e-mail.",
- "UPPERCASEMISSING": "Musi zawierać wielką literę.",
- "LOWERCASEMISSING": "Musi zawierać małą literę.",
- "SYMBOLERROR": "Musi zawierać symbol lub znak interpunkcyjny.",
- "NUMBERERROR": "Musi zawierać cyfrę."
- },
"STATE": {
"0": "Nieznany",
"1": "Aktywny",
diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json
index 05e484cf8..2ee33ed92 100644
--- a/console/src/assets/i18n/zh.json
+++ b/console/src/assets/i18n/zh.json
@@ -239,11 +239,20 @@
"NOROWS": "没有数据"
},
"ERRORS": {
- "REQUIRED": "缺少一些必填字段。",
+ "REQUIRED": "请填写此栏",
"TOKENINVALID": {
"TITLE": "您的授权令牌已过期。",
"DESCRIPTION": "点击下方按钮再次登录。"
- }
+ },
+ "INVALID_FORMAT": "格式是无效的。",
+ "NOTANEMAIL": "给定的值不是合法电子邮件地址。",
+ "MINLENGTH": "长度必须至少是{{requiredLength}}字符。",
+ "UPPERCASEMISSING": "密码必须包含大写字符。",
+ "LOWERCASEMISSING": "密码必须包含小写字符。",
+ "SYMBOLERROR": "密码必须包含符号或标点符号。",
+ "NUMBERERROR": "密码必须包含数字。",
+ "PWNOTEQUAL": "提供的密码不匹配。",
+ "PHONE": "电话号码必须以00或+开头。"
},
"USER": {
"SETTINGS": {
@@ -524,8 +533,7 @@
"SET": "设置新密码",
"RESENDNOTIFICATION": "发送重置密码链接",
"REQUIRED": "缺少必填字段。",
- "MINLENGTHERROR": "密码长度必须至少为 {{value}} 个字符。",
- "NOTEQUAL": "提供的密码不匹配。"
+ "MINLENGTHERROR": "密码长度必须至少为 {{value}} 个字符。"
},
"ID": "ID",
"EMAIL": "电子邮件",
@@ -579,17 +587,6 @@
"3": "过滤角色名称"
}
},
- "VALIDATION": {
- "INVALIDPATTERN": "密码不符合定义的规则。",
- "NOTANEMAIL": "给定的值不是合法电子邮件地址",
- "REQUIRED": "输入字段为空。",
- "MINLENGTH": "密码长度必须至少为 {{requiredLength}} 个字符。",
- "NOEMAIL": "用户名不能是电子邮件地址。",
- "UPPERCASEMISSING": "密码必须包含大写字符。",
- "LOWERCASEMISSING": "密码必须包含小写字符。",
- "SYMBOLERROR": "密码必须包含符号或标点符号。",
- "NUMBERERROR": "密码必须包含数字。"
- },
"STATE": {
"0": "未知",
"1": "启用",
diff --git a/console/src/component-themes.scss b/console/src/component-themes.scss
index c278dca29..e3f67772c 100644
--- a/console/src/component-themes.scss
+++ b/console/src/component-themes.scss
@@ -41,7 +41,7 @@
@import './styles/color.scss';
@import 'src/app/pages/instance/instance.component.scss';
@import 'src/app/modules/refresh-table/refresh-table.component.scss';
-@import 'src/app/modules/form-field/form-field.component.scss';
+@import 'src/app/modules/form-field/field/form-field.component.scss';
@import 'src/app/modules/label/label.component.scss';
@import 'src/app/modules/meta-layout/meta.scss';
@import 'src/app/pages/projects/owned-projects/project-grant-detail/project-grant-illustration/project-grant-illustration.component';