mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-31 11:32:15 +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 <[email protected]> * 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] <[email protected]> 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] <[email protected]> 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] <[email protected]> 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] <[email protected]> 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] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <[email protected]> * 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] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <[email protected]> * 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] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <[email protected]> * 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 <[email protected]> Co-authored-by: Livio Amstutz <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Fabi
Livio Amstutz
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
parent
f7aed1c864
commit
aa0510aa3d
@@ -47,11 +47,11 @@
|
||||
<div class="content">
|
||||
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="userName" required />
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="userName" required />
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.PROFILE.EMAIL' | translate }}</mat-label>
|
||||
@@ -113,25 +113,52 @@
|
||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="firstpassword" 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?.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 *ngIf="password?.errors?.minlength">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:password?.errors?.minlength }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<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" />
|
||||
|
||||
|
||||
<mat-error *ngIf="confirmPassword?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</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 *ngIf="password?.errors?.minlength">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
||||
<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">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
@@ -150,4 +177,4 @@
|
||||
{{'CONTINUE' | translate}}
|
||||
</button>
|
||||
</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 { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../../user-detail/validators';
|
||||
|
||||
function passwordConfirmValidator(c: AbstractControl): any {
|
||||
if (!c.parent || !c) {
|
||||
return;
|
||||
@@ -20,7 +22,12 @@ function passwordConfirmValidator(c: AbstractControl): any {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
}
|
||||
if (this.policy.hasLowercase) {
|
||||
validators.push(Validators.pattern(/[a-z]/g));
|
||||
validators.push(lowerCaseValidator);
|
||||
}
|
||||
if (this.policy.hasUppercase) {
|
||||
validators.push(Validators.pattern(/[A-Z]/g));
|
||||
validators.push(upperCaseValidator);
|
||||
}
|
||||
if (this.policy.hasNumber) {
|
||||
validators.push(Validators.pattern(/[0-9]/g));
|
||||
validators.push(numberValidator);
|
||||
}
|
||||
if (this.policy.hasSymbol) {
|
||||
validators.push(Validators.pattern(/[^a-z0-9]/gi));
|
||||
validators.push(symbolValidator);
|
||||
}
|
||||
|
||||
this.userForm = this.fb.group({
|
||||
@@ -154,7 +161,7 @@ export class OrgCreateComponent {
|
||||
}
|
||||
|
||||
public get userName(): AbstractControl | null {
|
||||
return this.userForm.get('userName');
|
||||
return this.userForm.get('userName');
|
||||
}
|
||||
|
||||
public get firstName(): AbstractControl | null {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<p class="desc">{{ 'USER.CREATE.DESCRIPTION' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
||||
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
||||
<!-- <h2>{{ 'USER.PAGES.CREATE' | translate}}</h2> -->
|
||||
<div class="content">
|
||||
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
||||
@@ -30,6 +30,9 @@
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
|
||||
|
||||
@@ -4,8 +4,27 @@ import { Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CreateUserRequest, Gender, User } from 'src/app/proto/generated/management_pb';
|
||||
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';
|
||||
|
||||
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({
|
||||
selector: 'app-user-create',
|
||||
templateUrl: './user-create.component.html',
|
||||
@@ -19,12 +38,35 @@ export class UserCreateComponent implements OnDestroy {
|
||||
|
||||
private sub: Subscription = new Subscription();
|
||||
|
||||
constructor(private router: Router, private toast: ToastService, public userService: MgmtUserService,
|
||||
private fb: FormBuilder) {
|
||||
public userLoginMustBeDomain: boolean = false;
|
||||
|
||||
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({
|
||||
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],
|
||||
lastName: ['', Validators.required],
|
||||
nickName: [''],
|
||||
|
||||
+48
-21
@@ -6,6 +6,20 @@
|
||||
|
||||
<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 }}"
|
||||
description="{{ 'USER.PAGES.LOGINNAMESDESC' | translate }}" *ngIf="user">
|
||||
<div class="login-name-row" *ngFor="let login of user?.loginNamesList">
|
||||
@@ -19,18 +33,6 @@
|
||||
</div>
|
||||
</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}}"
|
||||
description="{{'USER.PASSWORD.DESCRIPTION' | translate}}">
|
||||
@@ -47,27 +49,52 @@
|
||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="new password" type="password" matInput
|
||||
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 *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 *ngIf="newPassword?.errors?.minlength">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:newPassword?.errors?.minlength }}
|
||||
</mat-error>
|
||||
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="password repeating" type="password" matInput
|
||||
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 *ngIf="confirmPassword?.errors?.pattern">
|
||||
{{ policy | passwordPattern | translate }}
|
||||
<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">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:policy }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="confirmPassword?.errors?.notequal">{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@@ -143,6 +143,7 @@ h1 {
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
margin: -.5rem;
|
||||
|
||||
app-card {
|
||||
flex: 1;
|
||||
margin: .5rem
|
||||
|
||||
@@ -10,6 +10,7 @@ import { OrgService } from 'src/app/services/org.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
|
||||
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
|
||||
|
||||
function passwordConfirmValidator(c: AbstractControl): any {
|
||||
if (!c.parent || !c) {
|
||||
@@ -22,7 +23,12 @@ function passwordConfirmValidator(c: AbstractControl): any {
|
||||
return;
|
||||
}
|
||||
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 copied: string = '';
|
||||
|
||||
public userLoginMustBeDomain: boolean = false;
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
private toast: ToastService,
|
||||
@@ -67,16 +75,16 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
validators.push(Validators.minLength(this.policy.minLength));
|
||||
}
|
||||
if (this.policy.hasLowercase) {
|
||||
validators.push(Validators.pattern(/[a-z]/g));
|
||||
validators.push(lowerCaseValidator);
|
||||
}
|
||||
if (this.policy.hasUppercase) {
|
||||
validators.push(Validators.pattern(/[A-Z]/g));
|
||||
validators.push(upperCaseValidator);
|
||||
}
|
||||
if (this.policy.hasNumber) {
|
||||
validators.push(Validators.pattern(/[0-9]/g));
|
||||
validators.push(numberValidator);
|
||||
}
|
||||
if (this.policy.hasSymbol) {
|
||||
validators.push(Validators.pattern(/[^a-z0-9]/gi));
|
||||
validators.push(symbolValidator);
|
||||
}
|
||||
|
||||
this.passwordForm = this.fb.group({
|
||||
@@ -84,6 +92,11 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
newPassword: ['', validators],
|
||||
confirmPassword: ['', [...validators, passwordConfirmValidator]],
|
||||
});
|
||||
|
||||
this.passwordForm.controls['newPassword'].valueChanges.subscribe(() => {
|
||||
console.log(this.passwordForm.controls['newPassword'].errors);
|
||||
});
|
||||
|
||||
}).catch(error => {
|
||||
this.toast.showError(error.message);
|
||||
console.error(error.message);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<mat-icon>delete_outline</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<p class="row" *ngIf="error">{{error}}</p>
|
||||
</div>
|
||||
<div class="add-row">
|
||||
<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 MFAState: any = MFAState;
|
||||
|
||||
public error: string = '';
|
||||
constructor(private userService: AuthUserService, private toast: ToastService, private dialog: MatDialog) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
@@ -55,10 +57,9 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
|
||||
public getOTP(): void {
|
||||
this.userService.GetMyMfas().then(mfas => {
|
||||
this.mfaSubject.next(mfas.toObject().mfasList);
|
||||
console.log(mfas.toObject());
|
||||
}).catch(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 mgmtGender, UserProfile as mgmtUP } from 'src/app/proto/generated/management_pb';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-detail-form',
|
||||
templateUrl: './detail-form.component.html',
|
||||
@@ -23,7 +24,9 @@ export class DetailFormComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.profileForm = this.fb.group({
|
||||
userName: [{ value: '', disabled: true }, [Validators.required]],
|
||||
userName: [{ value: '', disabled: true }, [
|
||||
Validators.required,
|
||||
]],
|
||||
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
||||
nickName: [{ value: '', disabled: this.disabled }],
|
||||
|
||||
@@ -33,32 +33,55 @@
|
||||
</card-actions>
|
||||
<form *ngIf="passwordForm" autocomplete="new-password" [formGroup]="passwordForm"
|
||||
(ngSubmit)="setInitialPassword()">
|
||||
<!-- {{USERSTATE_INITIAL}} -->
|
||||
<div class="content center">
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||
<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 *ngIf="password?.errors?.minlength">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate: policy }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="password?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:password?.errors?.minlength }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="passwordRepeat" matInput formControlName="confirmPassword"
|
||||
type="password" />
|
||||
|
||||
<mat-error *ngIf="confirmPassword?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</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">
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate: policy }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="confirmPassword?.errors?.pattern">{{ policy | passwordPattern | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="confirmPassword?.errors?.notequal">{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@@ -151,7 +174,7 @@
|
||||
</div>
|
||||
</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 }}">
|
||||
<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 { CodeDialogComponent } from '../code-dialog/code-dialog.component';
|
||||
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
|
||||
|
||||
function passwordConfirmValidator(c: AbstractControl): any {
|
||||
if (!c.parent || !c) {
|
||||
@@ -84,16 +85,16 @@ export class UserDetailComponent implements OnInit, OnDestroy {
|
||||
validators.push(Validators.minLength(this.policy.minLength));
|
||||
}
|
||||
if (this.policy.hasLowercase) {
|
||||
validators.push(Validators.pattern(/[a-z]/g));
|
||||
validators.push(lowerCaseValidator);
|
||||
}
|
||||
if (this.policy.hasUppercase) {
|
||||
validators.push(Validators.pattern(/[A-Z]/g));
|
||||
validators.push(upperCaseValidator);
|
||||
}
|
||||
if (this.policy.hasNumber) {
|
||||
validators.push(Validators.pattern(/[0-9]/g));
|
||||
validators.push(numberValidator);
|
||||
}
|
||||
if (this.policy.hasSymbol) {
|
||||
validators.push(Validators.pattern(/[^a-z0-9]/gi));
|
||||
validators.push(symbolValidator);
|
||||
}
|
||||
|
||||
this.passwordForm = this.fb.group({
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<span>{{'USER.MFA.TYPE.'+ mfa.type | translate}}</span>
|
||||
<span>{{'USER.MFA.STATE.'+ mfa.state | translate}}</span>
|
||||
</div>
|
||||
<p class="row" *ngIf="error">{{error}}</p>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<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 { MFAState, MfaType, MultiFactor, UserView } from 'src/app/proto/generated/management_pb';
|
||||
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
|
||||
export interface MFAItem {
|
||||
@@ -23,11 +22,11 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
||||
|
||||
public MfaType: any = MfaType;
|
||||
public MFAState: any = MFAState;
|
||||
constructor(private mgmtUserService: MgmtUserService,
|
||||
private toast: ToastService) { }
|
||||
|
||||
public error: string = '';
|
||||
constructor(private mgmtUserService: MgmtUserService) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
console.log(this.user);
|
||||
this.getOTP();
|
||||
}
|
||||
|
||||
@@ -37,31 +36,12 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public getOTP(): void {
|
||||
console.log('otp', this.user);
|
||||
this.mgmtUserService.getUserMfas(this.user.id).then(mfas => {
|
||||
this.mfaSubject.next(mfas.toObject().mfasList);
|
||||
console.log(mfas.toObject());
|
||||
this.error = '';
|
||||
}).catch(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);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -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 { LocalizedDatePipe } from './localized-date.pipe';
|
||||
import { PasswordPatternPipe } from './password-pattern.pipe';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LocalizedDatePipe,
|
||||
PasswordPatternPipe,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@@ -17,7 +15,6 @@ import { PasswordPatternPipe } from './password-pattern.pipe';
|
||||
],
|
||||
exports: [
|
||||
LocalizedDatePipe,
|
||||
PasswordPatternPipe,
|
||||
],
|
||||
})
|
||||
export class PipesModule { }
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
OrgDomainSearchQuery,
|
||||
OrgDomainSearchRequest,
|
||||
OrgDomainSearchResponse,
|
||||
OrgIamPolicy,
|
||||
OrgID,
|
||||
OrgMemberRoles,
|
||||
OrgMemberSearchRequest,
|
||||
@@ -198,6 +199,14 @@ export class OrgService {
|
||||
|
||||
// Policy
|
||||
|
||||
public async GetMyOrgIamPolicy(): Promise<OrgIamPolicy> {
|
||||
return await this.request(
|
||||
c => c.getMyOrgIamPolicy,
|
||||
new Empty(),
|
||||
f => f,
|
||||
);
|
||||
}
|
||||
|
||||
public async GetPasswordAgePolicy(): Promise<PasswordAgePolicy> {
|
||||
const req = new Empty();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user