mirror of
https://github.com/zitadel/zitadel.git
synced 2025-06-12 06:48:43 +00:00
fix(console): password validation hints, mfa, i18n (#265)
* proto gen * fix: remove type from project lists (#256) * fix: remove type from project lists * Update user-detail.component.ts * fix: remove add project Co-authored-by: Livio Amstutz <livio.a@gmail.com> * fix project view model * regen mgmt proto * rm orgid from route, switch to project view * chore(deps-dev): bump @types/jasmine from 3.5.10 to 3.5.11 in /console (#252) Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.5.10 to 3.5.11. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @angular-devkit/build-angular in /console (#251) Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.901.7 to 0.901.9. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/commits) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump moment from 2.26.0 to 2.27.0 in /console (#250) Bumps [moment](https://github.com/moment/moment) from 2.26.0 to 2.27.0. - [Release notes](https://github.com/moment/moment/releases) - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.26.0...2.27.0) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump karma from 5.0.9 to 5.1.0 in /console (#218) Bumps [karma](https://github.com/karma-runner/karma) from 5.0.9 to 5.1.0. - [Release notes](https://github.com/karma-runner/karma/releases) - [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md) - [Commits](https://github.com/karma-runner/karma/compare/v5.0.9...v5.1.0) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump ngx-moment from 3.5.0 to 4.0.1 in /console (#219) Bumps [ngx-moment](https://github.com/urish/ngx-moment) from 3.5.0 to 4.0.1. - [Release notes](https://github.com/urish/ngx-moment/releases) - [Changelog](https://github.com/urish/ngx-moment/blob/master/CHANGELOG.md) - [Commits](https://github.com/urish/ngx-moment/compare/3.5.0...4.0.1) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <max@caos.ch> * chore(deps-dev): bump @angular/language-service in /console (#217) Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 9.1.10 to 9.1.11. - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/9.1.11/packages/language-service) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <max@caos.ch> * chore(deps-dev): bump @angular/cli from 9.1.7 to 9.1.9 in /console (#249) Bumps [@angular/cli](https://github.com/angular/angular-cli) from 9.1.7 to 9.1.9. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/compare/v9.1.7...v9.1.9) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <max@caos.ch> * set partial user profile * fix org routing * auth user loginnames, i18n * fix clipboard, secret regeneration * project role required field * show change editor * show granted project grid, remove add button * hide meta overflow * username validation * common pwd validators * fix org create pwd validation * show 2fa error * i18n Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> Co-authored-by: Livio Amstutz <livio.a@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
f7aed1c864
commit
aa0510aa3d
@ -47,11 +47,11 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
|
||||||
<input matInput formControlName="userName" required />
|
<input matInput formControlName="userName" required />
|
||||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PROFILE.EMAIL' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PROFILE.EMAIL' | translate }}</mat-label>
|
||||||
@ -113,25 +113,52 @@
|
|||||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||||
<input autocomplete="off" name="firstpassword" matInput formControlName="password"
|
<input autocomplete="off" name="firstpassword" matInput formControlName="password"
|
||||||
type="password" />
|
type="password" />
|
||||||
<mat-error *ngIf="password?.errors?.required">{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
|
<mat-error *ngIf="password?.errors?.required">
|
||||||
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="password?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
<mat-error *ngIf="password?.errors?.symbolValidator">
|
||||||
|
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.numberValidator">
|
||||||
|
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.upperCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.lowerCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="password?.errors?.minlength">
|
<mat-error *ngIf="password?.errors?.minlength">
|
||||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
{{ 'USER.VALIDATION.MINLENGTH' | translate:password?.errors?.minlength }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||||
<input autocomplete="off" name="firstpasswordRepeat" matInput formControlName="confirmPassword"
|
<input autocomplete="off" name="confirmPassword" matInput formControlName="confirmPassword"
|
||||||
type="password" />
|
type="password" />
|
||||||
|
|
||||||
|
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.required">
|
<mat-error *ngIf="confirmPassword?.errors?.required">
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="password?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
<mat-error *ngIf="confirmPassword?.errors?.symbolValidator">
|
||||||
|
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="password?.errors?.minlength">
|
<mat-error *ngIf="confirmPassword?.errors?.numberValidator">
|
||||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.notequal">
|
||||||
|
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.upperCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.lowerCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.minlength">
|
||||||
|
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@ -150,4 +177,4 @@
|
|||||||
{{'CONTINUE' | translate}}
|
{{'CONTINUE' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
@ -9,6 +9,8 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { OrgService } from 'src/app/services/org.service';
|
import { OrgService } from 'src/app/services/org.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
|
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../../user-detail/validators';
|
||||||
|
|
||||||
function passwordConfirmValidator(c: AbstractControl): any {
|
function passwordConfirmValidator(c: AbstractControl): any {
|
||||||
if (!c.parent || !c) {
|
if (!c.parent || !c) {
|
||||||
return;
|
return;
|
||||||
@ -20,7 +22,12 @@ function passwordConfirmValidator(c: AbstractControl): any {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pwd.value !== cpwd.value) {
|
if (pwd.value !== cpwd.value) {
|
||||||
return { invalid: true };
|
return {
|
||||||
|
invalid: true,
|
||||||
|
notequal: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,16 +76,16 @@ export class OrgCreateComponent {
|
|||||||
validators.push(Validators.minLength(this.policy.minLength));
|
validators.push(Validators.minLength(this.policy.minLength));
|
||||||
}
|
}
|
||||||
if (this.policy.hasLowercase) {
|
if (this.policy.hasLowercase) {
|
||||||
validators.push(Validators.pattern(/[a-z]/g));
|
validators.push(lowerCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasUppercase) {
|
if (this.policy.hasUppercase) {
|
||||||
validators.push(Validators.pattern(/[A-Z]/g));
|
validators.push(upperCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasNumber) {
|
if (this.policy.hasNumber) {
|
||||||
validators.push(Validators.pattern(/[0-9]/g));
|
validators.push(numberValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasSymbol) {
|
if (this.policy.hasSymbol) {
|
||||||
validators.push(Validators.pattern(/[^a-z0-9]/gi));
|
validators.push(symbolValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.userForm = this.fb.group({
|
this.userForm = this.fb.group({
|
||||||
@ -154,7 +161,7 @@ export class OrgCreateComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get userName(): AbstractControl | null {
|
public get userName(): AbstractControl | null {
|
||||||
return this.userForm.get('userName');
|
return this.userForm.get('userName');
|
||||||
}
|
}
|
||||||
|
|
||||||
public get firstName(): AbstractControl | null {
|
public get firstName(): AbstractControl | null {
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<p class="desc">{{ 'USER.CREATE.DESCRIPTION' | translate }}</p>
|
<p class="desc">{{ 'USER.CREATE.DESCRIPTION' | translate }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
||||||
<!-- <h2>{{ 'USER.PAGES.CREATE' | translate}}</h2> -->
|
<!-- <h2>{{ 'USER.PAGES.CREATE' | translate}}</h2> -->
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
||||||
@ -30,6 +30,9 @@
|
|||||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
<mat-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||||
|
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
||||||
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
|
||||||
|
@ -4,8 +4,27 @@ import { Router } from '@angular/router';
|
|||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { CreateUserRequest, Gender, User } from 'src/app/proto/generated/management_pb';
|
import { CreateUserRequest, Gender, User } from 'src/app/proto/generated/management_pb';
|
||||||
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
|
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
|
||||||
|
import { OrgService } from 'src/app/services/org.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
|
function noEmailValidator(c: AbstractControl): any {
|
||||||
|
const EMAIL_REGEXP: RegExp = /^((?!@).)*$/gm;
|
||||||
|
if (!c.parent || !c) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const username = c.parent.get('userName');
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EMAIL_REGEXP.test(username.value) ? null : {
|
||||||
|
noEmailValidator: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-create',
|
selector: 'app-user-create',
|
||||||
templateUrl: './user-create.component.html',
|
templateUrl: './user-create.component.html',
|
||||||
@ -19,12 +38,35 @@ export class UserCreateComponent implements OnDestroy {
|
|||||||
|
|
||||||
private sub: Subscription = new Subscription();
|
private sub: Subscription = new Subscription();
|
||||||
|
|
||||||
constructor(private router: Router, private toast: ToastService, public userService: MgmtUserService,
|
public userLoginMustBeDomain: boolean = false;
|
||||||
private fb: FormBuilder) {
|
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
private toast: ToastService,
|
||||||
|
public userService: MgmtUserService,
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private orgService: OrgService,
|
||||||
|
) {
|
||||||
|
this.orgService.GetMyOrgIamPolicy().then((iampolicy) => {
|
||||||
|
this.userLoginMustBeDomain = iampolicy.toObject().userLoginMustBeDomain;
|
||||||
|
console.log(this.userLoginMustBeDomain);
|
||||||
|
this.initForm();
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
this.initForm();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private initForm(): void {
|
||||||
this.userForm = this.fb.group({
|
this.userForm = this.fb.group({
|
||||||
email: ['', [Validators.required, Validators.email]],
|
email: ['', [Validators.required, Validators.email]],
|
||||||
userName: ['', [Validators.required, Validators.minLength(2)]],
|
userName: ['',
|
||||||
|
[
|
||||||
|
Validators.required,
|
||||||
|
Validators.minLength(2),
|
||||||
|
this.userLoginMustBeDomain ? noEmailValidator : Validators.email,
|
||||||
|
],
|
||||||
|
],
|
||||||
firstName: ['', Validators.required],
|
firstName: ['', Validators.required],
|
||||||
lastName: ['', Validators.required],
|
lastName: ['', Validators.required],
|
||||||
nickName: [''],
|
nickName: [''],
|
||||||
|
@ -6,6 +6,20 @@
|
|||||||
|
|
||||||
<span *ngIf="!loading && !user">{{ 'USER.PAGES.NOUSER' | translate }}</span>
|
<span *ngIf="!loading && !user">{{ 'USER.PAGES.NOUSER' | translate }}</span>
|
||||||
|
|
||||||
|
<div class="col" *ngIf="user">
|
||||||
|
<app-card title="{{ 'USER.PROFILE.TITLE' | translate }}"
|
||||||
|
description="{{'USER.PROFILE.DESCRIPTION' | translate}}">
|
||||||
|
<app-detail-form [genders]="genders" [languages]="languages" [profile]="user"
|
||||||
|
(changedLanguage)="changedLanguage($event)" (submitData)="saveProfile($event)">
|
||||||
|
</app-detail-form>
|
||||||
|
</app-card>
|
||||||
|
|
||||||
|
<app-card title="Theme" class="theme-card">
|
||||||
|
<app-theme-setting></app-theme-setting>
|
||||||
|
</app-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<app-card title="{{ 'USER.PAGES.LOGINNAMES' | translate }}"
|
<app-card title="{{ 'USER.PAGES.LOGINNAMES' | translate }}"
|
||||||
description="{{ 'USER.PAGES.LOGINNAMESDESC' | translate }}" *ngIf="user">
|
description="{{ 'USER.PAGES.LOGINNAMESDESC' | translate }}" *ngIf="user">
|
||||||
<div class="login-name-row" *ngFor="let login of user?.loginNamesList">
|
<div class="login-name-row" *ngFor="let login of user?.loginNamesList">
|
||||||
@ -19,18 +33,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</app-card>
|
</app-card>
|
||||||
|
|
||||||
<div class="col" *ngIf="user">
|
|
||||||
<app-card title="{{ 'USER.PROFILE.TITLE' | translate }}"
|
|
||||||
description="{{'USER.PROFILE.DESCRIPTION' | translate}}">
|
|
||||||
<app-detail-form [genders]="genders" [languages]="languages" [profile]="user"
|
|
||||||
(changedLanguage)="changedLanguage($event)" (submitData)="saveProfile($event)">
|
|
||||||
</app-detail-form>
|
|
||||||
</app-card>
|
|
||||||
|
|
||||||
<app-card title="Theme" class="theme-card">
|
|
||||||
<app-theme-setting></app-theme-setting>
|
|
||||||
</app-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<app-card *ngIf="user" title="{{'USER.PASSWORD.TITLE' | translate}}"
|
<app-card *ngIf="user" title="{{'USER.PASSWORD.TITLE' | translate}}"
|
||||||
description="{{'USER.PASSWORD.DESCRIPTION' | translate}}">
|
description="{{'USER.PASSWORD.DESCRIPTION' | translate}}">
|
||||||
@ -47,27 +49,52 @@
|
|||||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||||
<input autocomplete="off" name="new password" type="password" matInput
|
<input autocomplete="off" name="new password" type="password" matInput
|
||||||
formControlName="newPassword" />
|
formControlName="newPassword" />
|
||||||
<mat-error *ngIf="newPassword?.errors?.required">{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
|
<mat-error *ngIf="newPassword?.errors?.required">
|
||||||
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="newPassword?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
<mat-error *ngIf="newPassword?.errors?.symbolValidator">
|
||||||
|
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="newPassword?.errors?.numberValidator">
|
||||||
|
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="newPassword?.errors?.upperCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="newPassword?.errors?.lowerCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="newPassword?.errors?.minlength">
|
<mat-error *ngIf="newPassword?.errors?.minlength">
|
||||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
{{ 'USER.VALIDATION.MINLENGTH' | translate:newPassword?.errors?.minlength }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||||
<input autocomplete="off" name="password repeating" type="password" matInput
|
<input autocomplete="off" name="password repeating" type="password" matInput
|
||||||
formControlName="confirmPassword" />
|
formControlName="confirmPassword" />
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.required">{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.required">
|
||||||
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.pattern">
|
<mat-error *ngIf="confirmPassword?.errors?.symbolValidator">
|
||||||
{{ policy | passwordPattern | translate }}
|
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.numberValidator">
|
||||||
|
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.notequal">
|
||||||
|
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.upperCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.lowerCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.minlength">
|
<mat-error *ngIf="confirmPassword?.errors?.minlength">
|
||||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.notequal">{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,6 +143,7 @@ h1 {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
margin: -.5rem;
|
margin: -.5rem;
|
||||||
|
|
||||||
app-card {
|
app-card {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: .5rem
|
margin: .5rem
|
||||||
|
@ -10,6 +10,7 @@ import { OrgService } from 'src/app/services/org.service';
|
|||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
|
import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
|
||||||
|
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
|
||||||
|
|
||||||
function passwordConfirmValidator(c: AbstractControl): any {
|
function passwordConfirmValidator(c: AbstractControl): any {
|
||||||
if (!c.parent || !c) {
|
if (!c.parent || !c) {
|
||||||
@ -22,7 +23,12 @@ function passwordConfirmValidator(c: AbstractControl): any {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pwd.value !== cpwd.value) {
|
if (pwd.value !== cpwd.value) {
|
||||||
return { invalid: true, notequal: 'Password is not equal' };
|
return {
|
||||||
|
invalid: true,
|
||||||
|
notequal: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +57,8 @@ export class AuthUserDetailComponent implements OnDestroy {
|
|||||||
public policy!: PasswordComplexityPolicy.AsObject;
|
public policy!: PasswordComplexityPolicy.AsObject;
|
||||||
public copied: string = '';
|
public copied: string = '';
|
||||||
|
|
||||||
|
public userLoginMustBeDomain: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public translate: TranslateService,
|
public translate: TranslateService,
|
||||||
private toast: ToastService,
|
private toast: ToastService,
|
||||||
@ -67,16 +75,16 @@ export class AuthUserDetailComponent implements OnDestroy {
|
|||||||
validators.push(Validators.minLength(this.policy.minLength));
|
validators.push(Validators.minLength(this.policy.minLength));
|
||||||
}
|
}
|
||||||
if (this.policy.hasLowercase) {
|
if (this.policy.hasLowercase) {
|
||||||
validators.push(Validators.pattern(/[a-z]/g));
|
validators.push(lowerCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasUppercase) {
|
if (this.policy.hasUppercase) {
|
||||||
validators.push(Validators.pattern(/[A-Z]/g));
|
validators.push(upperCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasNumber) {
|
if (this.policy.hasNumber) {
|
||||||
validators.push(Validators.pattern(/[0-9]/g));
|
validators.push(numberValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasSymbol) {
|
if (this.policy.hasSymbol) {
|
||||||
validators.push(Validators.pattern(/[^a-z0-9]/gi));
|
validators.push(symbolValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.passwordForm = this.fb.group({
|
this.passwordForm = this.fb.group({
|
||||||
@ -84,6 +92,11 @@ export class AuthUserDetailComponent implements OnDestroy {
|
|||||||
newPassword: ['', validators],
|
newPassword: ['', validators],
|
||||||
confirmPassword: ['', [...validators, passwordConfirmValidator]],
|
confirmPassword: ['', [...validators, passwordConfirmValidator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.passwordForm.controls['newPassword'].valueChanges.subscribe(() => {
|
||||||
|
console.log(this.passwordForm.controls['newPassword'].errors);
|
||||||
|
});
|
||||||
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.toast.showError(error.message);
|
this.toast.showError(error.message);
|
||||||
console.error(error.message);
|
console.error(error.message);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<mat-icon>delete_outline</mat-icon>
|
<mat-icon>delete_outline</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="row" *ngIf="error">{{error}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="add-row">
|
<div class="add-row">
|
||||||
<button (click)="addOTP()" mat-stroked-button color="primary" matTooltip="{{'ACTIONS.NEW' | translate}}">
|
<button (click)="addOTP()" mat-stroked-button color="primary" matTooltip="{{'ACTIONS.NEW' | translate}}">
|
||||||
|
@ -19,6 +19,8 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public MfaType: any = MfaType;
|
public MfaType: any = MfaType;
|
||||||
public MFAState: any = MFAState;
|
public MFAState: any = MFAState;
|
||||||
|
|
||||||
|
public error: string = '';
|
||||||
constructor(private userService: AuthUserService, private toast: ToastService, private dialog: MatDialog) { }
|
constructor(private userService: AuthUserService, private toast: ToastService, private dialog: MatDialog) { }
|
||||||
|
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
@ -55,10 +57,9 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
|
|||||||
public getOTP(): void {
|
public getOTP(): void {
|
||||||
this.userService.GetMyMfas().then(mfas => {
|
this.userService.GetMyMfas().then(mfas => {
|
||||||
this.mfaSubject.next(mfas.toObject().mfasList);
|
this.mfaSubject.next(mfas.toObject().mfasList);
|
||||||
console.log(mfas.toObject());
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
this.toast.showError(error.message);
|
this.error = error.message;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { Subscription } from 'rxjs';
|
|||||||
import { Gender as authGender, UserProfile as authUP } from 'src/app/proto/generated/auth_pb';
|
import { Gender as authGender, UserProfile as authUP } from 'src/app/proto/generated/auth_pb';
|
||||||
import { Gender as mgmtGender, UserProfile as mgmtUP } from 'src/app/proto/generated/management_pb';
|
import { Gender as mgmtGender, UserProfile as mgmtUP } from 'src/app/proto/generated/management_pb';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-detail-form',
|
selector: 'app-detail-form',
|
||||||
templateUrl: './detail-form.component.html',
|
templateUrl: './detail-form.component.html',
|
||||||
@ -23,7 +24,9 @@ export class DetailFormComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(private fb: FormBuilder) {
|
constructor(private fb: FormBuilder) {
|
||||||
this.profileForm = this.fb.group({
|
this.profileForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [Validators.required]],
|
userName: [{ value: '', disabled: true }, [
|
||||||
|
Validators.required,
|
||||||
|
]],
|
||||||
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||||
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||||
nickName: [{ value: '', disabled: this.disabled }],
|
nickName: [{ value: '', disabled: this.disabled }],
|
||||||
|
@ -33,32 +33,55 @@
|
|||||||
</card-actions>
|
</card-actions>
|
||||||
<form *ngIf="passwordForm" autocomplete="new-password" [formGroup]="passwordForm"
|
<form *ngIf="passwordForm" autocomplete="new-password" [formGroup]="passwordForm"
|
||||||
(ngSubmit)="setInitialPassword()">
|
(ngSubmit)="setInitialPassword()">
|
||||||
<!-- {{USERSTATE_INITIAL}} -->
|
|
||||||
<div class="content center">
|
<div class="content center">
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||||
<input autocomplete="off" name="password" matInput formControlName="password" type="password" />
|
<input autocomplete="off" name="password" matInput formControlName="password" type="password" />
|
||||||
<mat-error *ngIf="password?.errors?.required">{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
|
<mat-error *ngIf="password?.errors?.required">
|
||||||
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.symbolValidator">
|
||||||
|
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.numberValidator">
|
||||||
|
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.upperCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="password?.errors?.lowerCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="password?.errors?.minlength">
|
<mat-error *ngIf="password?.errors?.minlength">
|
||||||
{{ 'USER.VALIDATION.MINLENGTH' | translate: policy }}
|
{{ 'USER.VALIDATION.MINLENGTH' | translate:password?.errors?.minlength }}
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="password?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="formfield">
|
<mat-form-field class="formfield">
|
||||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||||
<input autocomplete="off" name="passwordRepeat" matInput formControlName="confirmPassword"
|
<input autocomplete="off" name="passwordRepeat" matInput formControlName="confirmPassword"
|
||||||
type="password" />
|
type="password" />
|
||||||
|
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.required">
|
<mat-error *ngIf="confirmPassword?.errors?.required">
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.symbolValidator">
|
||||||
|
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.numberValidator">
|
||||||
|
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.notequal">
|
||||||
|
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.upperCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="confirmPassword?.errors?.lowerCaseValidator">
|
||||||
|
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
|
||||||
|
</mat-error>
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.minlength">
|
<mat-error *ngIf="confirmPassword?.errors?.minlength">
|
||||||
{{ 'USER.VALIDATION.MINLENGTH' | translate: policy }}
|
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
|
||||||
</mat-error>
|
|
||||||
<mat-error *ngIf="confirmPassword?.errors?.notequal">{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@ -151,7 +174,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</app-card>
|
</app-card>
|
||||||
|
|
||||||
<app-auth-user-mfa *ngIf="user" [user]="user"></app-auth-user-mfa>
|
<app-user-mfa *ngIf="user" [user]="user"></app-user-mfa>
|
||||||
|
|
||||||
<app-card title="{{ 'USER.ADDRESS.TITLE' | translate }}">
|
<app-card title="{{ 'USER.ADDRESS.TITLE' | translate }}">
|
||||||
<form [formGroup]="addressForm" (ngSubmit)="saveAddress()">
|
<form [formGroup]="addressForm" (ngSubmit)="saveAddress()">
|
||||||
|
@ -23,6 +23,7 @@ import { OrgService } from 'src/app/services/org.service';
|
|||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
|
import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
|
||||||
|
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
|
||||||
|
|
||||||
function passwordConfirmValidator(c: AbstractControl): any {
|
function passwordConfirmValidator(c: AbstractControl): any {
|
||||||
if (!c.parent || !c) {
|
if (!c.parent || !c) {
|
||||||
@ -84,16 +85,16 @@ export class UserDetailComponent implements OnInit, OnDestroy {
|
|||||||
validators.push(Validators.minLength(this.policy.minLength));
|
validators.push(Validators.minLength(this.policy.minLength));
|
||||||
}
|
}
|
||||||
if (this.policy.hasLowercase) {
|
if (this.policy.hasLowercase) {
|
||||||
validators.push(Validators.pattern(/[a-z]/g));
|
validators.push(lowerCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasUppercase) {
|
if (this.policy.hasUppercase) {
|
||||||
validators.push(Validators.pattern(/[A-Z]/g));
|
validators.push(upperCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasNumber) {
|
if (this.policy.hasNumber) {
|
||||||
validators.push(Validators.pattern(/[0-9]/g));
|
validators.push(numberValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasSymbol) {
|
if (this.policy.hasSymbol) {
|
||||||
validators.push(Validators.pattern(/[^a-z0-9]/gi));
|
validators.push(symbolValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.passwordForm = this.fb.group({
|
this.passwordForm = this.fb.group({
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<span>{{'USER.MFA.TYPE.'+ mfa.type | translate}}</span>
|
<span>{{'USER.MFA.TYPE.'+ mfa.type | translate}}</span>
|
||||||
<span>{{'USER.MFA.STATE.'+ mfa.state | translate}}</span>
|
<span>{{'USER.MFA.STATE.'+ mfa.state | translate}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="row" *ngIf="error">{{error}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<div class="spinner-container" *ngIf="loading$ | async">
|
<div class="spinner-container" *ngIf="loading$ | async">
|
||||||
|
@ -2,7 +2,6 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
|||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { MFAState, MfaType, MultiFactor, UserView } from 'src/app/proto/generated/management_pb';
|
import { MFAState, MfaType, MultiFactor, UserView } from 'src/app/proto/generated/management_pb';
|
||||||
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
|
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
|
||||||
|
|
||||||
|
|
||||||
export interface MFAItem {
|
export interface MFAItem {
|
||||||
@ -23,11 +22,11 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public MfaType: any = MfaType;
|
public MfaType: any = MfaType;
|
||||||
public MFAState: any = MFAState;
|
public MFAState: any = MFAState;
|
||||||
constructor(private mgmtUserService: MgmtUserService,
|
|
||||||
private toast: ToastService) { }
|
public error: string = '';
|
||||||
|
constructor(private mgmtUserService: MgmtUserService) { }
|
||||||
|
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
console.log(this.user);
|
|
||||||
this.getOTP();
|
this.getOTP();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,31 +36,12 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getOTP(): void {
|
public getOTP(): void {
|
||||||
console.log('otp', this.user);
|
|
||||||
this.mgmtUserService.getUserMfas(this.user.id).then(mfas => {
|
this.mgmtUserService.getUserMfas(this.user.id).then(mfas => {
|
||||||
this.mfaSubject.next(mfas.toObject().mfasList);
|
this.mfaSubject.next(mfas.toObject().mfasList);
|
||||||
console.log(mfas.toObject());
|
this.error = '';
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
this.toast.showError(error.message);
|
this.error = error.message;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// public deleteMFA(type: MfaType): void {
|
|
||||||
// if (type === MfaType.MFATYPE_OTP) {
|
|
||||||
// this.userService.RemoveMfaOTP().then(() => {
|
|
||||||
// this.toast.showInfo('OTP Deleted');
|
|
||||||
|
|
||||||
// const index = this.mfaSubject.value.findIndex(mfa => mfa.type === type);
|
|
||||||
// if (index > -1) {
|
|
||||||
// const newValues = this.mfaSubject.value;
|
|
||||||
// newValues.splice(index, 1);
|
|
||||||
// this.mfaSubject.next(newValues);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }).catch(error => {
|
|
||||||
// this.toast.showError(error.message);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
45
console/src/app/pages/user-detail/validators.ts
Normal file
45
console/src/app/pages/user-detail/validators.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
|
export function symbolValidator(c: FormControl): any {
|
||||||
|
const REGEXP = /[^a-z0-9]/gi;
|
||||||
|
|
||||||
|
return REGEXP.test(c.value) ? null : {
|
||||||
|
invalid: true,
|
||||||
|
symbolValidator: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function numberValidator(c: FormControl): any {
|
||||||
|
const REGEXP = /[0-9]/g;
|
||||||
|
|
||||||
|
return REGEXP.test(c.value) ? null : {
|
||||||
|
invalid: true,
|
||||||
|
numberValidator: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function upperCaseValidator(c: FormControl): any {
|
||||||
|
const REGEXP = /[A-Z]/g;
|
||||||
|
|
||||||
|
return REGEXP.test(c.value) ? null : {
|
||||||
|
invalid: true,
|
||||||
|
upperCaseValidator: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lowerCaseValidator(c: FormControl): any {
|
||||||
|
const REGEXP = /[a-z]/g;
|
||||||
|
|
||||||
|
return REGEXP.test(c.value) ? null : {
|
||||||
|
invalid: true,
|
||||||
|
lowerCaseValidator: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
import { PasswordPatternPipe } from './password-pattern.pipe';
|
|
||||||
|
|
||||||
describe('PasswordPatternPipe', () => {
|
|
||||||
it('create an instance', () => {
|
|
||||||
const pipe = new PasswordPatternPipe();
|
|
||||||
expect(pipe).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,17 +0,0 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
|
|
||||||
import { PasswordComplexityPolicy } from '../proto/generated/management_pb';
|
|
||||||
import { OrgService } from '../services/org.service';
|
|
||||||
|
|
||||||
@Pipe({
|
|
||||||
name: 'passwordPattern',
|
|
||||||
})
|
|
||||||
export class PasswordPatternPipe implements PipeTransform {
|
|
||||||
|
|
||||||
constructor(private orgService: OrgService) { }
|
|
||||||
|
|
||||||
transform(policy: PasswordComplexityPolicy.AsObject, ...args: unknown[]): string {
|
|
||||||
return this.orgService.getLocalizedComplexityPolicyPatternErrorString(policy);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -3,13 +3,11 @@ import { NgModule } from '@angular/core';
|
|||||||
import { MomentModule } from 'ngx-moment';
|
import { MomentModule } from 'ngx-moment';
|
||||||
|
|
||||||
import { LocalizedDatePipe } from './localized-date.pipe';
|
import { LocalizedDatePipe } from './localized-date.pipe';
|
||||||
import { PasswordPatternPipe } from './password-pattern.pipe';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
LocalizedDatePipe,
|
LocalizedDatePipe,
|
||||||
PasswordPatternPipe,
|
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -17,7 +15,6 @@ import { PasswordPatternPipe } from './password-pattern.pipe';
|
|||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
LocalizedDatePipe,
|
LocalizedDatePipe,
|
||||||
PasswordPatternPipe,
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PipesModule { }
|
export class PipesModule { }
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
OrgDomainSearchQuery,
|
OrgDomainSearchQuery,
|
||||||
OrgDomainSearchRequest,
|
OrgDomainSearchRequest,
|
||||||
OrgDomainSearchResponse,
|
OrgDomainSearchResponse,
|
||||||
|
OrgIamPolicy,
|
||||||
OrgID,
|
OrgID,
|
||||||
OrgMemberRoles,
|
OrgMemberRoles,
|
||||||
OrgMemberSearchRequest,
|
OrgMemberSearchRequest,
|
||||||
@ -198,6 +199,14 @@ export class OrgService {
|
|||||||
|
|
||||||
// Policy
|
// Policy
|
||||||
|
|
||||||
|
public async GetMyOrgIamPolicy(): Promise<OrgIamPolicy> {
|
||||||
|
return await this.request(
|
||||||
|
c => c.getMyOrgIamPolicy,
|
||||||
|
new Empty(),
|
||||||
|
f => f,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public async GetPasswordAgePolicy(): Promise<PasswordAgePolicy> {
|
public async GetPasswordAgePolicy(): Promise<PasswordAgePolicy> {
|
||||||
const req = new Empty();
|
const req = new Empty();
|
||||||
|
|
||||||
|
@ -164,7 +164,12 @@
|
|||||||
"VALIDATION": {
|
"VALIDATION": {
|
||||||
"INVALIDPATTERN": "Das Password muss aus mindestens 8 Zeichen bestehen und einen Grossbuchstaben, ein Sonderzeichen und eine Zahl enthalten. Die maximale Anzahl an Zeichen ist 72!",
|
"INVALIDPATTERN": "Das Password muss aus mindestens 8 Zeichen bestehen und einen Grossbuchstaben, ein Sonderzeichen und eine Zahl enthalten. Die maximale Anzahl an Zeichen ist 72!",
|
||||||
"REQUIRED": "Das Feld ist leer",
|
"REQUIRED": "Das Feld ist leer",
|
||||||
"MINLENGTH":"Das Password muss mindestens {{minLength}} Zeichen lang sein!"
|
"MINLENGTH":"Das Password muss mindestens {{requiredLength}} Zeichen lang sein!",
|
||||||
|
"NOEMAIL":"Username darf keine email sein!",
|
||||||
|
"UPPERCASEMISSING":"Password muss einen Großbuchstaben beinhalten",
|
||||||
|
"LOWERCASEMISSING":"Password muss einen Kleinbuchstaben beinhalten",
|
||||||
|
"SYMBOLERROR":"Das Password muss ein Symbol beinhalten!",
|
||||||
|
"NUMBERERROR":"Das Password muss eine Nummer beinhalten!"
|
||||||
},
|
},
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0":"unbekannt",
|
"0":"unbekannt",
|
||||||
@ -287,9 +292,9 @@
|
|||||||
"PROJECT": {
|
"PROJECT": {
|
||||||
"PAGES": {
|
"PAGES": {
|
||||||
"TITLE": "Projekt",
|
"TITLE": "Projekt",
|
||||||
"DESCRIPTION": "Hier können Sie wichtige Einstellungen prüfen und die Daten einsehen, mit denen das der Dienst konfiguriert worden ist",
|
"DESCRIPTION": "Hier können Sie wichtige Einstellungen prüfen und die Daten einsehen, mit denen der Dienst konfiguriert worden ist",
|
||||||
"LIST": "Projekte",
|
"LIST": "Projekte",
|
||||||
"LISTDESCRIPTION":"Hier finden Sie alle Projekte, für die Sie Aktionen anzeigen oder ausführen dürfen. Wenn Sie kein Projekt finden können, wenden Sie sich an einen Projektbesitzer oder an jemanden mit den entsprechenden Rechten, um Projektzugriff zu erhalten.",
|
"LISTDESCRIPTION":"Hier finden Sie alle Projekte, für die Sie Aktionen anzeigen oder ausführen dürfen. Wenn Sie Ihr Projekt nicht finden können, wenden Sie sich an einen Projektbesitzer oder an jemanden mit den entsprechenden Rechten, um Projektzugriff zu erhalten.",
|
||||||
"DETAIL": "Detail",
|
"DETAIL": "Detail",
|
||||||
"CREATE": "Projekt erstellen",
|
"CREATE": "Projekt erstellen",
|
||||||
"CREATE_DESC": "Geben Sie den Namen ein",
|
"CREATE_DESC": "Geben Sie den Namen ein",
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
"DETAIL": "Detail",
|
"DETAIL": "Detail",
|
||||||
"CREATE": "Create",
|
"CREATE": "Create",
|
||||||
"MY": "My Informations",
|
"MY": "My Informations",
|
||||||
"LOGINNAMES":"Login names",
|
"LOGINNAMES":"Loginnames",
|
||||||
"LOGINNAMESDESC":"You can log into zitadel with these names",
|
"LOGINNAMESDESC":"You can log into zitadel with these names",
|
||||||
"COPY":"Copy to clipboard",
|
"COPY":"Copy to clipboard",
|
||||||
"COPIED":"Copied to clipboard!",
|
"COPIED":"Copied to clipboard!",
|
||||||
@ -164,7 +164,12 @@
|
|||||||
"VALIDATION": {
|
"VALIDATION": {
|
||||||
"INVALIDPATTERN": "The password must consist of at least 8 characters and contain a capital letter, a special character and a number. The maximum length is 72.",
|
"INVALIDPATTERN": "The password must consist of at least 8 characters and contain a capital letter, a special character and a number. The maximum length is 72.",
|
||||||
"REQUIRED": "The input field is empty",
|
"REQUIRED": "The input field is empty",
|
||||||
"MINLENGTH":"The password has to be at least {{minLength}} characters long!"
|
"MINLENGTH":"The password has to be at least {{requiredLength}} characters long!",
|
||||||
|
"NOEMAIL":"Username can not be an email",
|
||||||
|
"UPPERCASEMISSING":"An uppercase character is needed!",
|
||||||
|
"LOWERCASEMISSING":"A lowercase character is needed!",
|
||||||
|
"SYMBOLERROR":"The password must include a symbol!",
|
||||||
|
"NUMBERERROR":"The password must include a number!"
|
||||||
},
|
},
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0":"unbekannt",
|
"0":"unbekannt",
|
||||||
@ -223,7 +228,6 @@
|
|||||||
"SYMBOLERROR":"The password must include a symbol!",
|
"SYMBOLERROR":"The password must include a symbol!",
|
||||||
"NUMBERERROR":"The password must include a number!",
|
"NUMBERERROR":"The password must include a number!",
|
||||||
"PATTERNERROR":"The required pattern is not fulfilled!"
|
"PATTERNERROR":"The required pattern is not fulfilled!"
|
||||||
|
|
||||||
},
|
},
|
||||||
"PWD_AGE": {
|
"PWD_AGE": {
|
||||||
"TITLE":"Password Age",
|
"TITLE":"Password Age",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user