From 776875990613e97b561b69bd196ae11d7db58d15 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 23 Mar 2021 09:50:58 +0100 Subject: [PATCH] fix: console v2 (#1454) * some issues * passwordless, mfa * mfa, project fixes, login policy * user table, auth service, interceptor --- .../member-create-dialog.component.ts | 9 +- .../dialog-add-type.component.html | 9 +- .../dialog-add-type.component.ts | 8 +- .../modules/mfa-table/mfa-table.component.ts | 105 +++++++++--------- .../search-user-autocomplete.component.html | 2 +- .../search-user-autocomplete.component.ts | 1 + .../user-grants/user-grants-datasource.ts | 1 + .../user-grants/user-grants.component.html | 16 +-- .../user-grants/user-grants.component.ts | 2 + .../orgs/org-create/org-create.component.ts | 5 +- .../orgs/org-detail/org-detail.component.ts | 1 + .../apps/app-detail/app-detail.component.html | 2 +- .../granted-project-grid.component.html | 29 ++--- .../granted-project-grid.component.scss | 4 +- .../granted-project-list.component.ts | 2 + .../owned-project-grid.component.html | 8 +- .../owned-project-grid.component.scss | 6 +- .../owned-projects-routing.module.ts | 2 +- .../auth-factor-dialog.component.html | 43 ++++--- .../auth-factor-dialog.component.scss | 31 +++++- .../auth-factor-dialog.component.ts | 3 + .../auth-passwordless.component.html | 4 +- .../auth-passwordless.component.scss | 3 + .../auth-passwordless.component.ts | 1 + .../auth-user-detail.component.html | 7 +- .../auth-user-detail.component.ts | 4 + .../auth-user-mfa.component.html | 9 +- .../auth-user-mfa.component.scss | 1 + .../auth-user-mfa/auth-user-mfa.component.ts | 5 +- .../edit-dialog/edit-dialog.component.html | 11 +- .../edit-dialog/edit-dialog.component.ts | 41 ++++--- .../detail-form/detail-form.component.html | 8 +- .../detail-form/detail-form.component.ts | 5 + .../user-table/user-table.component.html | 2 +- .../app/services/authentication.service.ts | 6 +- console/src/app/services/grpc-auth.service.ts | 4 + .../services/interceptors/auth.interceptor.ts | 2 +- console/src/assets/environment.json | 2 +- console/src/assets/i18n/de.json | 9 +- console/src/assets/i18n/en.json | 5 +- 40 files changed, 261 insertions(+), 157 deletions(-) diff --git a/console/src/app/modules/add-member-dialog/member-create-dialog.component.ts b/console/src/app/modules/add-member-dialog/member-create-dialog.component.ts index a3b6deecda..df508d9578 100644 --- a/console/src/app/modules/add-member-dialog/member-create-dialog.component.ts +++ b/console/src/app/modules/add-member-dialog/member-create-dialog.component.ts @@ -97,9 +97,12 @@ export class MemberCreateDialogComponent { } public selectProject(project: Project.AsObject | GrantedProject.AsObject | any): void { - this.projectId = project.projectId; - if (project.id) { - this.grantId = project.id; + if (project.projectId && project.grantId) { + this.projectId = project.projectId; + this.grantId = project.grantId; + } + else if (project.id) { + this.projectId = project.id; } } diff --git a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.html b/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.html index 485c9e1987..4c85ae34b3 100644 --- a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.html +++ b/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.html @@ -2,14 +2,15 @@

{{data.desc | translate}}

- +
diff --git a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.ts b/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.ts index 3044bae64f..847f203f74 100644 --- a/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.ts +++ b/console/src/app/modules/mfa-table/dialog-add-type/dialog-add-type.component.ts @@ -1,5 +1,6 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MultiFactorType, SecondFactorType } from 'src/app/proto/generated/zitadel/policy_pb'; enum LoginMethodComponentType { MultiFactor = 1, @@ -13,10 +14,11 @@ enum LoginMethodComponentType { }) export class DialogAddTypeComponent { public LoginMethodComponentType: any = LoginMethodComponentType; - // public availableMfaTypes: Array = []; + public availableMfaTypes: Array = []; + public newMfaType!: MultiFactorType | SecondFactorType; constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any) { - // this.availableMfaTypes = data.types; + this.availableMfaTypes = data.types; } public closeDialog(): void { @@ -24,6 +26,6 @@ export class DialogAddTypeComponent { } public closeDialogWithCode(): void { - // this.dialogRef.close(this.newMfaType); + this.dialogRef.close(this.newMfaType); } } diff --git a/console/src/app/modules/mfa-table/mfa-table.component.ts b/console/src/app/modules/mfa-table/mfa-table.component.ts index 842ce97eed..2b877b5976 100644 --- a/console/src/app/modules/mfa-table/mfa-table.component.ts +++ b/console/src/app/modules/mfa-table/mfa-table.component.ts @@ -4,10 +4,14 @@ import { MatPaginator } from '@angular/material/paginator'; import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { + AddMultiFactorToLoginPolicyRequest as AdminAddMultiFactorToLoginPolicyRequest, + AddSecondFactorToLoginPolicyRequest as AdminAddSecondFactorToLoginPolicyRequest, RemoveMultiFactorFromLoginPolicyRequest as AdminRemoveMultiFactorFromLoginPolicyRequest, RemoveSecondFactorFromLoginPolicyRequest as AdminRemoveSecondFactorFromLoginPolicyRequest, } from 'src/app/proto/generated/zitadel/admin_pb'; import { + AddMultiFactorToLoginPolicyRequest as MgmtAddMultiFactorToLoginPolicyRequest, + AddSecondFactorToLoginPolicyRequest as MgmtAddSecondFactorToLoginPolicyRequest, RemoveMultiFactorFromLoginPolicyRequest as MgmtRemoveMultiFactorFromLoginPolicyRequest, RemoveSecondFactorFromLoginPolicyRequest as MgmtRemoveSecondFactorFromLoginPolicyRequest, } from 'src/app/proto/generated/zitadel/management_pb'; @@ -18,6 +22,7 @@ import { ToastService } from 'src/app/services/toast.service'; import { PolicyComponentServiceType } from '../policies/policy-component-types.enum'; import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component'; +import { DialogAddTypeComponent } from './dialog-add-type/dialog-add-type.component'; export enum LoginMethodComponentType { MultiFactor = 1, @@ -116,57 +121,57 @@ export class MfaTableComponent implements OnInit { } }); - // const dialogRef = this.dialog.open(DialogAddTypeComponent, { - // data: { - // title: 'MFA.CREATE.TITLE', - // desc: 'MFA.CREATE.DESCRIPTION', - // componentType: this.componentType, - // types: selection, - // }, - // width: '400px', - // }); + const dialogRef = this.dialog.open(DialogAddTypeComponent, { + data: { + title: 'MFA.CREATE.TITLE', + desc: 'MFA.CREATE.DESCRIPTION', + componentType: this.componentType, + types: selection, + }, + width: '400px', + }); - // dialogRef.afterClosed().subscribe((mfaType: ) => { - // if (mfaType) { - // if (this.serviceType === PolicyComponentServiceType.MGMT) { - // if (this.componentType === LoginMethodComponentType.MultiFactor) { - // const req = new MgmtAddMultiFactorToLoginPolicyRequest(); - // req.setType(mfaType as MultiFactorType); - // (this.service as ManagementService).addMultiFactorToLoginPolicy(req).then(() => { - // this.refreshPageAfterTimout(2000); - // }).catch(error => { - // this.toast.showError(error); - // }); - // } else if (this.componentType === LoginMethodComponentType.SecondFactor) { - // const req = new MgmtAddSecondFactorToLoginPolicyRequest(); - // req.setType(mfaType as SecondFactorType); - // (this.service as ManagementService).addSecondFactorToLoginPolicy(req).then(() => { - // this.refreshPageAfterTimout(2000); - // }).catch(error => { - // this.toast.showError(error); - // }); - // } - // } else if (this.serviceType === PolicyComponentServiceType.ADMIN) { - // if (this.componentType === LoginMethodComponentType.MultiFactor) { - // const req = new AdminAddMultiFactorToLoginPolicyRequest(); - // req.setType(mfaType as MultiFactorType); - // (this.service as AdminService).addMultiFactorToLoginPolicy(req).then(() => { - // this.refreshPageAfterTimout(2000); - // }).catch(error => { - // this.toast.showError(error); - // }); - // } else if (this.componentType === LoginMethodComponentType.SecondFactor) { - // const req = new AdminAddSecondFactorToLoginPolicyRequest(); - // req.setType(mfaType as SecondFactorType); - // (this.service as AdminService).addSecondFactorToLoginPolicy(req).then(() => { - // this.refreshPageAfterTimout(2000); - // }).catch(error => { - // this.toast.showError(error); - // }); - // } - // } - // } - // }); + dialogRef.afterClosed().subscribe((mfaType: MultiFactorType | SecondFactorType) => { + if (mfaType) { + if (this.serviceType === PolicyComponentServiceType.MGMT) { + if (this.componentType === LoginMethodComponentType.MultiFactor) { + const req = new MgmtAddMultiFactorToLoginPolicyRequest(); + req.setType(mfaType as MultiFactorType); + (this.service as ManagementService).addMultiFactorToLoginPolicy(req).then(() => { + this.refreshPageAfterTimout(2000); + }).catch(error => { + this.toast.showError(error); + }); + } else if (this.componentType === LoginMethodComponentType.SecondFactor) { + const req = new MgmtAddSecondFactorToLoginPolicyRequest(); + req.setType(mfaType as SecondFactorType); + (this.service as ManagementService).addSecondFactorToLoginPolicy(req).then(() => { + this.refreshPageAfterTimout(2000); + }).catch(error => { + this.toast.showError(error); + }); + } + } else if (this.serviceType === PolicyComponentServiceType.ADMIN) { + if (this.componentType === LoginMethodComponentType.MultiFactor) { + const req = new AdminAddMultiFactorToLoginPolicyRequest(); + req.setType(mfaType as MultiFactorType); + (this.service as AdminService).addMultiFactorToLoginPolicy(req).then(() => { + this.refreshPageAfterTimout(2000); + }).catch(error => { + this.toast.showError(error); + }); + } else if (this.componentType === LoginMethodComponentType.SecondFactor) { + const req = new AdminAddSecondFactorToLoginPolicyRequest(); + req.setType(mfaType as SecondFactorType); + (this.service as AdminService).addSecondFactorToLoginPolicy(req).then(() => { + this.refreshPageAfterTimout(2000); + }).catch(error => { + this.toast.showError(error); + }); + } + } + } + }); } private async getData(): Promise { diff --git a/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html b/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html index 09eee942d5..377287ea81 100644 --- a/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html +++ b/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.html @@ -8,7 +8,7 @@ - {{ selecteduser?.human ? (selecteduser.human.firstName + ' ' + selecteduser.human.lastName) : + {{ selecteduser?.human?.profile ? (selecteduser.human.profile.displayName) : selecteduser?.machine?.name}} | {{selecteduser.preferredLoginName}} diff --git a/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.ts b/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.ts index a6b16db5e4..8a04ccae19 100644 --- a/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.ts +++ b/console/src/app/modules/search-user-autocomplete/search-user-autocomplete.component.ts @@ -62,6 +62,7 @@ export class SearchUserAutocompleteComponent implements OnInit, AfterContentChec } else if (this.target === UserTarget.SELF) { this.getFilteredResults(); // new subscription } + console.log(this.users); } public ngAfterContentChecked(): void { diff --git a/console/src/app/modules/user-grants/user-grants-datasource.ts b/console/src/app/modules/user-grants/user-grants-datasource.ts index ddb4a3ad6c..61b1f63d52 100644 --- a/console/src/app/modules/user-grants/user-grants-datasource.ts +++ b/console/src/app/modules/user-grants/user-grants-datasource.ts @@ -128,6 +128,7 @@ export class UserGrantsDataSource extends DataSource { catchError(() => of([])), finalize(() => this.loadingSubject.next(false)), ).subscribe(grants => { + console.log(grants); this.grantsSubject.next(grants); }); } diff --git a/console/src/app/modules/user-grants/user-grants.component.html b/console/src/app/modules/user-grants/user-grants.component.html index 5fe6e401e1..e79b3ded3b 100644 --- a/console/src/app/modules/user-grants/user-grants.component.html +++ b/console/src/app/modules/user-grants/user-grants.component.html @@ -67,13 +67,13 @@ DATES -
+
{{ 'PROJECT.GRANT.CREATIONDATE' | translate }}: - {{grant.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} + {{grant.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
-
+
{{ 'PROJECT.GRANT.CHANGEDATE' | translate }} - {{grant.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} + {{grant.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
@@ -86,14 +86,14 @@ + *ngIf="(context === UserGrantContext.USER || context === UserGrantContext.NONE) && (grant.grantId && grantToEdit !== grant.grantId) || (grantToEdit !== grant.grantId)">
{{ role }}
- +
\ No newline at end of file diff --git a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html index 5a7ab7bd20..55bce1d571 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html +++ b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html @@ -9,17 +9,18 @@

{{'PROJECT.PAGES.PINNED' | translate}}

+ [ngClass]="{ inactive: item.state !== ProjectState.PROJECT_STATE_ACTIVE}" + (click)="navigateToProject(item.projectId,item.grantId, $event)">
- {{'PROJECT.PAGES.LASTMODIFIED' | translate}} + {{'PROJECT.PAGES.LASTMODIFIED' | translate}} {{ - item.changeDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' - }} + item.details.changeDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' + }} {{ item.projectName }} {{item.resourceOwnerName}} - {{'PROJECT.PAGES.CREATEDON' | translate}} - {{ item.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + {{'PROJECT.PAGES.CREATEDON' | translate}} + {{ item.details.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' + }}
@@ -33,17 +34,17 @@

{{'PROJECT.PAGES.ALL' | translate}}

+ (click)="navigateToProject(item.projectId,item.grantId, $event)" + [ngClass]="{ inactive: item.state !== ProjectState.PROJECT_STATE_ACTIVE}">
- {{'PROJECT.PAGES.LASTMODIFIED' | translate}} + {{'PROJECT.PAGES.LASTMODIFIED' | translate}} {{ - item.changeDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' - }} + item.details.changeDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' + }} {{ item.projectName }} {{item.resourceOwnerName}} - {{'PROJECT.PAGES.CREATEDON' | translate}} - {{ item.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} + {{'PROJECT.PAGES.CREATEDON' | translate}} + {{ item.details.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}
- -
+ +

{{'USER.MFA.DIALOG.ADD_MFA_DESCRIPTION' | translate}}

+ +
+ + +
+
-

{{'USER.MFA.OTP_DIALOG_DESCRIPTION' | translate}}

+

{{'USER.MFA.OTP_DIALOG_DESCRIPTION' | translate}}

+
- + Code @@ -44,7 +56,8 @@ {{'ACTIONS.CLOSE' | translate}} -
\ No newline at end of file diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.scss b/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.scss index bb7bcbff0e..9ec72b44af 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.scss +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.scss @@ -2,21 +2,44 @@ display: flex; margin: 0 -0.5rem; - .otp, - .u2f { + .otp-btn, + .u2f-btn { flex: 1; min-height: 100px; border-radius: .5rem; - border: 1px solid var(--grey); display: flex; flex-direction: column; justify-content: center; align-items: center; - padding: 1rem; + margin: 1rem; + box-sizing: border-box; + + .icon-row { + display: flex; + } + } + + button { margin: .5rem; } } +.desc { + font-size: 14px; + color: var(--grey); +} + +.otp { + max-width: 400px; + display: flex; + flex-direction: column; + align-items: center; +} + +.u2f { + max-width: 400px; +} + .formfield { width: 100%; } diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.ts index fcaf0cbebe..629173edba 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.ts +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.ts @@ -42,6 +42,8 @@ export class AuthFactorDialogComponent { } public selectType(type: AuthFactorType): void { + this.selectedType = type; + if (type == AuthFactorType.OTP) { this.authService.addMyMultiFactorOTP().then((otpresp) => { this.otpurl = otpresp.url; @@ -95,6 +97,7 @@ export class AuthFactorDialogComponent { (resp as any).response.clientDataJSON && (resp as any).rawId) { + console.log(resp); const attestationObject = (resp as any).response.attestationObject; const clientDataJSON = (resp as any).response.clientDataJSON; const rawId = (resp as any).rawId; diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.html b/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.html index bd67de17df..cf7a5aa652 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.html +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.html @@ -36,9 +36,9 @@
-
diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.scss b/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.scss index 3f9facae7c..d91523b033 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.scss +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.scss @@ -3,10 +3,13 @@ display: flex; margin: -.5rem; flex-wrap: wrap; + justify-content: flex-end; .button { margin: .5rem; margin-top: 1rem; + display: flex; + align-items: center; .icon { margin-right: .5rem; diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.ts index ff0a442c54..e7679526fe 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.ts +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-passwordless/auth-passwordless.component.ts @@ -53,6 +53,7 @@ export class AuthPasswordlessComponent implements OnInit, OnDestroy { public addPasswordless(): void { this.service.addMyPasswordless().then((resp) => { if (resp.key) { + console.log(resp.key); const credOptions: CredentialCreationOptions = JSON.parse(atob(resp.key.publicKey as string)); if (credOptions.publicKey?.challenge) { diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html index 436b13788a..611f688bcc 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html @@ -27,10 +27,9 @@
- - + + 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 6b196bbf5b..2d7cf3827d 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 @@ -69,6 +69,7 @@ export class AuthUserDetailComponent implements OnDestroy { this.user.human.profile?.firstName, this.user.human.profile?.lastName, this.user.human.profile?.nickName, + this.user.human.profile?.displayName, this.user.human.profile?.preferredLanguage, this.user.human.profile?.gender, ) @@ -169,6 +170,7 @@ export class AuthUserDetailComponent implements OnDestroy { titleKey: 'USER.LOGINMETHODS.PHONE.EDITTITLE', descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC', value: this.user.human?.phone?.phone, + type: type, }, width: '400px', }); @@ -180,6 +182,7 @@ export class AuthUserDetailComponent implements OnDestroy { }); break; case EditDialogType.EMAIL: + console.log('email'); const dialogRefEmail = this.dialog.open(EditDialogComponent, { data: { confirmKey: 'ACTIONS.SAVE', @@ -188,6 +191,7 @@ export class AuthUserDetailComponent implements OnDestroy { titleKey: 'USER.LOGINMETHODS.EMAIL.EDITTITLE', descriptionKey: 'USER.LOGINMETHODS.EMAIL.EDITDESC', value: this.user.human?.email?.email, + type: type }, width: '400px', }); diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.html b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.html index 3bdc171f65..a294163af7 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.html +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.html @@ -3,7 +3,10 @@ - + @@ -39,10 +42,10 @@
{{ 'USER.MFA.TABLETYPE' | translate }} {{'USER.MFA.TYPE.'+ mfa.type | translate}} + OTP (One-Time Password) + U2F (Universal 2nd Factor) +
-
diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss index 3f9facae7c..edb29e5fe5 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss @@ -3,6 +3,7 @@ display: flex; margin: -.5rem; flex-wrap: wrap; + justify-content: flex-end; .button { margin: .5rem; diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts index b40a413ca5..ae64f58c22 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts @@ -55,7 +55,9 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy { public addAuthFactor(): void { const dialogRef = this.dialog.open(AuthFactorDialogComponent, { - width: '400px', + data: { + otpDisabled: !this.otpAvailable + } }); dialogRef.afterClosed().subscribe((code) => { @@ -70,6 +72,7 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy { public getMFAs(): void { this.service.listMyMultiFactors().then(mfas => { const list = mfas.resultList; + console.log(list); this.dataSource = new MatTableDataSource(list); this.dataSource.sort = this.sort; 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 81628ab3e0..288500dffd 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 @@ -4,9 +4,10 @@

{{data.descriptionKey | translate}}

- {{data.labelKey | translate }} ({{ phoneCountry }}) - + {{data.labelKey | translate }} ({{ phoneCountry }}) + +
@@ -14,8 +15,8 @@ {{data.cancelKey | translate}} -
\ No newline at end of file diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.ts index 4044918319..75f298f917 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.ts +++ b/console/src/app/pages/users/user-detail/auth-user-detail/edit-dialog/edit-dialog.component.ts @@ -1,4 +1,5 @@ import { Component, Inject } from '@angular/core'; +import { FormControl, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { parsePhoneNumber } from 'libphonenumber-js'; @@ -13,34 +14,46 @@ export enum EditDialogType { styleUrls: ['./edit-dialog.component.scss'], }) export class EditDialogComponent { - public value: string = ''; public isPhone: boolean = false; public phoneCountry: string = 'CH'; + public valueControl: FormControl = new FormControl(['', [Validators.required]]); constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any) { - this.value = data.value; + this.valueControl.setValue(data.value); if (data.type == EditDialogType.PHONE) { this.isPhone = true; } + + this.valueControl.valueChanges.subscribe(value => { + console.log(value); + if (value && value.length > 1) { + this.changeValue(value); + } + }); } - changeValue(change: any) { - const value = change.target.value; - if (this.isPhone && value) { - const phoneNumber = parsePhoneNumber(value ?? '', 'CH'); - if (phoneNumber) { - const formmatted = phoneNumber.formatInternational(); - this.phoneCountry = phoneNumber.country || ''; - this.value = formmatted; + changeValue(changedValue: string) { + if (this.isPhone && changedValue) { + try { + const phoneNumber = parsePhoneNumber(changedValue ?? '', 'CH'); + if (phoneNumber) { + const formmatted = phoneNumber.formatInternational(); + this.phoneCountry = phoneNumber.country || ''; + if (formmatted !== this.valueControl.value) { + this.valueControl.setValue(formmatted); + } + } + } catch (error) { + console.error(error); } } } - closeDialog(email: string = ''): void { - this.dialogRef.close(email); + closeDialog(): void { + this.dialogRef.close(); } - closeDialogWithValue(value: string = ''): void { - this.dialogRef.close(value); + closeDialogWithValue(): void { + this.dialogRef.close(this.valueControl.value); } } diff --git a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html index b6d8149213..855e67f230 100644 --- a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html +++ b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.html @@ -16,6 +16,10 @@ {{ 'USER.PROFILE.NICKNAME' | translate }} + + {{ 'USER.PROFILE.DISPLAYNAME' | translate }} + + {{ 'USER.PROFILE.GENDER' | translate }} @@ -34,7 +38,7 @@
- +
\ No newline at end of file diff --git a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts index 0251833bf8..6dc977b710 100644 --- a/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts +++ b/console/src/app/pages/users/user-detail/detail-form/detail-form.component.ts @@ -30,6 +30,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges { firstName: [{ value: '', disabled: this.disabled }, Validators.required], lastName: [{ value: '', disabled: this.disabled }, Validators.required], nickName: [{ value: '', disabled: this.disabled }], + displayName: [{ value: '', disabled: this.disabled }, Validators.required], gender: [{ value: 0, disabled: this.disabled }], preferredLanguage: [{ value: '', disabled: this.disabled }], }); @@ -43,6 +44,7 @@ export class DetailFormComponent implements OnDestroy, OnChanges { firstName: [{ value: '', disabled: this.disabled }, Validators.required], lastName: [{ value: '', disabled: this.disabled }, Validators.required], nickName: [{ value: '', disabled: this.disabled }], + displayName: [{ value: '', disabled: this.disabled }, Validators.required], gender: [{ value: 0, disabled: this.disabled }], preferredLanguage: [{ value: '', disabled: this.disabled }], }); @@ -77,6 +79,9 @@ export class DetailFormComponent implements OnDestroy, OnChanges { public get nickName(): AbstractControl | null { return this.profileForm.get('nickName'); } + public get displayName(): AbstractControl | null { + return this.profileForm.get('displayName'); + } public get gender(): AbstractControl | null { return this.profileForm.get('gender'); } diff --git a/console/src/app/pages/users/user-list/user-table/user-table.component.html b/console/src/app/pages/users/user-list/user-table/user-table.component.html index 49faf322c6..9af760c8e5 100644 --- a/console/src/app/pages/users/user-list/user-table/user-table.component.html +++ b/console/src/app/pages/users/user-list/user-table/user-table.component.html @@ -38,7 +38,7 @@ class="avatar" [name]="user.human.profile.displayName" [size]="32"> -
+
diff --git a/console/src/app/services/authentication.service.ts b/console/src/app/services/authentication.service.ts index a760a32bc8..2ca3187424 100644 --- a/console/src/app/services/authentication.service.ts +++ b/console/src/app/services/authentication.service.ts @@ -37,8 +37,6 @@ export class AuthenticationService { public async authenticate( partialConfig?: Partial, - setState: boolean = true, - force: boolean = false, ): Promise { if (partialConfig) { Object.assign(this.authConfig, partialConfig); @@ -50,8 +48,8 @@ export class AuthenticationService { this._authenticated = this.oauthService.hasValidAccessToken(); - if (!this.oauthService.hasValidIdToken() || !this.authenticated || partialConfig || force) { - const newState = setState ? await this.statehandler.createState().toPromise() : undefined; + if (!this.oauthService.hasValidIdToken() || !this.authenticated || partialConfig) { + const newState = await this.statehandler.createState().toPromise(); this.oauthService.initCodeFlow(newState); } this._authenticationChanged.next(this.authenticated); diff --git a/console/src/app/services/grpc-auth.service.ts b/console/src/app/services/grpc-auth.service.ts index 0799fe7e26..acb183f1af 100644 --- a/console/src/app/services/grpc-auth.service.ts +++ b/console/src/app/services/grpc-auth.service.ts @@ -253,6 +253,7 @@ export class GrpcAuthService { firstName?: string, lastName?: string, nickName?: string, + displayName?: string, preferredLanguage?: string, gender?: Gender, ): Promise { @@ -266,6 +267,9 @@ export class GrpcAuthService { if (nickName) { req.setNickName(nickName); } + if (displayName) { + req.setDisplayName(displayName); + } if (gender) { req.setGender(gender); } diff --git a/console/src/app/services/interceptors/auth.interceptor.ts b/console/src/app/services/interceptors/auth.interceptor.ts index 08e13e0ab0..27646c9e22 100644 --- a/console/src/app/services/interceptors/auth.interceptor.ts +++ b/console/src/app/services/interceptors/auth.interceptor.ts @@ -61,7 +61,7 @@ export class AuthInterceptor implements UnaryIn dialogRef.afterClosed().pipe(take(1)).subscribe(resp => { if (resp) { - this.authenticationService.authenticate(undefined, true, true); + this.authenticationService.authenticate(undefined); } }); } diff --git a/console/src/assets/environment.json b/console/src/assets/environment.json index 115ba9f155..000ad04f1a 100644 --- a/console/src/assets/environment.json +++ b/console/src/assets/environment.json @@ -3,5 +3,5 @@ "mgmtServiceUrl": "https://api.zitadel.io", "adminServiceUrl":"https://api.zitadel.io", "issuer": "https://issuer.zitadel.io", - "clientid": "98804911164221523@zitadel" + "clientid": "100129365194565743@zitadel" } diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 23bea4425d..ca818d35af 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -222,10 +222,11 @@ "TITLE": "Multifaktor-Authentisierung", "DESCRIPTION": "Füge einen zusätzlichen Faktor hinzu, um Dein Konto optimal zu schützen.", "MANAGE_DESCRIPTION": "Verwalte die Multifaktor-Merkmale Deiner Benutzer.", - "OTP": "OTP konfigurieren", + "ADD":"Faktor hinzufügen", + "OTP": "OTP (One-Time Password)", "OTP_DIALOG_TITLE": "OTP hinzufügen", "OTP_DIALOG_DESCRIPTION": "Scanne den QR-Code mit einer Authenticator App und verifiziere den erhaltenen Code, um OTP zu aktivieren.", - "U2F":"U2F hinzufügen", + "U2F":"U2F (Universal 2nd Factor)", "U2F_DIALOG_TITLE": "U2F hinzufügen", "U2F_DIALOG_DESCRIPTION": "Gib einen Namen für den von dir verwendeten Universellen Multifaktor an.", "U2F_SUCCESS":"U2F erfolgreich erstellt!", @@ -244,7 +245,9 @@ }, "DIALOG": { "MFA_DELETE_TITLE":"Zweiten Faktor entfernen", - "MFA_DELETE_DESCRIPTION":"Sie sind im Begriff eine Zweitfaktormethode zu entfernen. Sind sie sicher?" + "MFA_DELETE_DESCRIPTION":"Sie sind im Begriff eine Zweitfaktormethode zu entfernen. Sind sie sicher?", + "ADD_MFA_TITLE":"Zweiten Faktor hinzufügen", + "ADD_MFA_DESCRIPTION":"Wählen Sie einen der verfügbaren Optionen." } }, "EXTERNALIDP": { diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index e0d8ed0753..a35b7082e8 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -222,10 +222,11 @@ "TITLE": "Multifactor Authentication", "DESCRIPTION": "Add a second factor to ensure optimal security for your account.", "MANAGE_DESCRIPTION": "Manage the second factor methods of your users.", - "OTP": "Configure OTP", + "ADD":"Add AuthFactor", + "OTP": "OTP (One-Time Password)", "OTP_DIALOG_TITLE": "Add OTP", "OTP_DIALOG_DESCRIPTION": "Scan the QR code with an authenticator app and enter the code below to verify and activate the OTP method.", - "U2F":"Add U2F", + "U2F":"U2F (Universal 2nd Factor)", "U2F_DIALOG_TITLE": "Verify U2F", "U2F_DIALOG_DESCRIPTION": "Enter a name for your used universal Multifactor.", "U2F_SUCCESS":"U2F created successfully!",