diff --git a/console/src/app/modules/changes/changes.component.scss b/console/src/app/modules/changes/changes.component.scss index a1d41be22b..f796d46fdb 100644 --- a/console/src/app/modules/changes/changes.component.scss +++ b/console/src/app/modules/changes/changes.component.scss @@ -21,10 +21,13 @@ } @mixin changes-theme($theme) { + $is-dark-theme: map-get($theme, is-dark); + .scroll-container { max-height: 50vh; overflow-y: scroll; - border-bottom: 1px solid #ffffff20; + border-bottom: 1px solid if($is-dark-theme, #303131, #e3e8ee); + /* stylelint-enable */ margin-bottom: 0.5rem; .date { diff --git a/console/src/app/modules/client-keys/client-keys.component.html b/console/src/app/modules/client-keys/client-keys.component.html index 94e069899a..57c4b09ffc 100644 --- a/console/src/app/modules/client-keys/client-keys.component.html +++ b/console/src/app/modules/client-keys/client-keys.component.html @@ -1,12 +1,6 @@
- add{{ 'ACTIONS.NEW' | translate }} @@ -42,7 +36,7 @@ {{ 'USER.MACHINE.CREATIONDATE' | translate }} - {{key.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm'}} + {{key.details.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm'}} @@ -53,6 +47,17 @@ + + + + + + = new BehaviorSubject(false); public loading$: Observable = this.loadingSubject.asObservable(); - @Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate']; + @Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate', 'actions']; @Output() public changedSelection: EventEmitter> = new EventEmitter(); @@ -62,11 +62,8 @@ export class ClientKeysComponent implements OnInit { this.getData(event.pageSize, event.pageIndex * event.pageSize); } - public deleteSelectedKeys(): void { - const mappedDeletions = this.selection.selected.map(value => { - return this.mgmtService.removeAppKey(this.projectId, this.appId, value.id); - }); - Promise.all(mappedDeletions).then(() => { + public deleteKey(key: Key.AsObject): void { + this.mgmtService.removeAppKey(this.projectId, this.appId, key.id).then(() => { this.selection.clear(); this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true); this.getData(10, 0); diff --git a/console/src/app/modules/contributors/contributors.component.ts b/console/src/app/modules/contributors/contributors.component.ts index 49fe9e6af4..57ea2e74c5 100644 --- a/console/src/app/modules/contributors/contributors.component.ts +++ b/console/src/app/modules/contributors/contributors.component.ts @@ -1,6 +1,7 @@ import { animate, animateChild, keyframes, query, stagger, style, transition, trigger } from '@angular/animations'; import { Component, EventEmitter, Input, Output } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; +import { Member } from 'src/app/proto/generated/zitadel/member_pb'; @Component({ selector: 'app-contributors', @@ -29,7 +30,7 @@ export class ContributorsComponent { @Input() disabled: boolean = false; @Input() totalResult: number = 0; @Input() loading: boolean = false; - @Input() membersSubject!: BehaviorSubject; + @Input() membersSubject!: BehaviorSubject; @Output() addClicked: EventEmitter = new EventEmitter(); @Output() showDetailClicked: EventEmitter = new EventEmitter(); @Output() refreshClicked: EventEmitter = new EventEmitter(); diff --git a/console/src/app/modules/idp-table/idp-table.component.html b/console/src/app/modules/idp-table/idp-table.component.html index 04058b1e62..286650b43d 100644 --- a/console/src/app/modules/idp-table/idp-table.component.html +++ b/console/src/app/modules/idp-table/idp-table.component.html @@ -69,19 +69,19 @@
{{ 'IDP.CREATIONDATE' | translate }}: - {{idp.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} + {{idp.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
{{ 'IDP.CHANGEDATE' | translate }} - {{idp.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} + {{idp.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}
- + {{ 'IDP.TYPE' | translate }} - {{'IDP.TYPES.'+idp.providerType | translate }} + {{'IDP.OWNERTYPES.'+idp.owner | translate }} @@ -89,7 +89,7 @@ diff --git a/console/src/app/modules/idp-table/idp-table.component.ts b/console/src/app/modules/idp-table/idp-table.component.ts index 1e27357bba..3d3a8069ba 100644 --- a/console/src/app/modules/idp-table/idp-table.component.ts +++ b/console/src/app/modules/idp-table/idp-table.component.ts @@ -51,7 +51,7 @@ export class IdpTableComponent implements OnInit { ngOnInit(): void { this.getData(10, 0); if (this.serviceType === PolicyComponentServiceType.MGMT) { - this.displayedColumns = ['select', 'name', 'config', 'dates', 'state', 'type']; + this.displayedColumns = ['select', 'name', 'config', 'dates', 'state', 'owner']; } if (!this.disabled) { diff --git a/console/src/app/modules/machine-keys/machine-keys.component.html b/console/src/app/modules/machine-keys/machine-keys.component.html index da44d24d9b..6396bd4c50 100644 --- a/console/src/app/modules/machine-keys/machine-keys.component.html +++ b/console/src/app/modules/machine-keys/machine-keys.component.html @@ -1,11 +1,6 @@
- add{{ 'ACTIONS.NEW' | translate }} @@ -52,6 +47,17 @@ + + + + + + + diff --git a/console/src/app/modules/machine-keys/machine-keys.component.scss b/console/src/app/modules/machine-keys/machine-keys.component.scss index bade0aa759..818d7f1c87 100644 --- a/console/src/app/modules/machine-keys/machine-keys.component.scss +++ b/console/src/app/modules/machine-keys/machine-keys.component.scss @@ -24,4 +24,14 @@ tr { outline: none; + + button { + visibility: hidden; + } + + &:hover { + button { + visibility: visible; + } + } } diff --git a/console/src/app/modules/machine-keys/machine-keys.component.ts b/console/src/app/modules/machine-keys/machine-keys.component.ts index 0769aaf458..84f574a20c 100644 --- a/console/src/app/modules/machine-keys/machine-keys.component.ts +++ b/console/src/app/modules/machine-keys/machine-keys.component.ts @@ -28,7 +28,7 @@ export class MachineKeysComponent implements OnInit { public keyResult!: ListMachineKeysResponse.AsObject; private loadingSubject: BehaviorSubject = new BehaviorSubject(false); public loading$: Observable = this.loadingSubject.asObservable(); - @Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate']; + @Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate', 'actions']; @Output() public changedSelection: EventEmitter> = new EventEmitter(); @@ -61,11 +61,8 @@ export class MachineKeysComponent implements OnInit { this.getData(event.pageSize, event.pageIndex * event.pageSize); } - public deleteSelectedKeys(): void { - const mappedDeletions = this.selection.selected.map(value => { - return this.mgmtService.removeMachineKey(value.id, this.userId); - }); - Promise.all(mappedDeletions).then(() => { + public deleteKey(key: Key.AsObject): void { + this.mgmtService.removeMachineKey(key.id, this.userId).then(() => { this.selection.clear(); this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true); this.getData(10, 0); diff --git a/console/src/app/modules/members-table/members-table.component.html b/console/src/app/modules/members-table/members-table.component.html index ecd7ea9476..2aaa6efdeb 100644 --- a/console/src/app/modules/members-table/members-table.component.html +++ b/console/src/app/modules/members-table/members-table.component.html @@ -51,10 +51,10 @@ {{member.lastName}} - - {{ 'PROJECT.MEMBER.USERNAME' | translate }} + + {{ 'PROJECT.MEMBER.LOGINNAME' | translate }} - {{member.userName}} + {{member.preferredloginname}} diff --git a/console/src/app/modules/members-table/members-table.component.ts b/console/src/app/modules/members-table/members-table.component.ts index 7627538eaf..4aa8c5670b 100644 --- a/console/src/app/modules/members-table/members-table.component.ts +++ b/console/src/app/modules/members-table/members-table.component.ts @@ -23,20 +23,20 @@ export class MembersTableComponent implements OnInit, OnDestroy { @Input() public canDelete: boolean = false; @Input() public canWrite: boolean = false; @ViewChild(MatPaginator) public paginator!: MatPaginator; - @ViewChild(MatTable) public table!: MatTable; + @ViewChild(MatTable) public table!: MatTable; @Input() public dataSource!: MemberDatasource; public selection: SelectionModel = new SelectionModel(true, []); @Input() public memberRoleOptions: string[] = []; @Input() public factoryLoadFunc!: Function; @Input() public refreshTrigger!: Observable; - @Output() public updateRoles: EventEmitter<{ member: Member, change: MatSelectChange; }> = new EventEmitter(); + @Output() public updateRoles: EventEmitter<{ member: Member.AsObject, change: MatSelectChange; }> = new EventEmitter(); @Output() public changedSelection: EventEmitter = new EventEmitter(); - @Output() public deleteMember: EventEmitter = new EventEmitter(); + @Output() public deleteMember: EventEmitter = new EventEmitter(); private destroyed: Subject = new Subject(); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - public displayedColumns: string[] = ['select', 'userId', 'firstname', 'lastname', 'username', 'email', 'roles']; + public displayedColumns: string[] = ['select', 'userId', 'firstname', 'lastname', 'loginname', 'email', 'roles']; constructor() { this.selection.changed.pipe(takeUntil(this.destroyed)).subscribe(_ => { 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 2b877b5976..8e53c76efb 100644 --- a/console/src/app/modules/mfa-table/mfa-table.component.ts +++ b/console/src/app/modules/mfa-table/mfa-table.component.ts @@ -214,6 +214,8 @@ export class MfaTableComponent implements OnInit { }); } } + + console.log(this.mfas); } public refreshPageAfterTimout(to: number): void { diff --git a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts index 42080808fa..e8f889426e 100644 --- a/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts +++ b/console/src/app/modules/policies/login-policy/add-idp-dialog/add-idp-dialog.component.ts @@ -49,19 +49,24 @@ export class AddIdpDialogComponent { public loadIdps(): void { this.idp = undefined; - if (this.serviceType === PolicyComponentServiceType.MGMT) { - const query: IDPQuery = new IDPQuery(); - const idpOTQ: IDPOwnerTypeQuery = new IDPOwnerTypeQuery(); - idpOTQ.setOwnerType(this.idpType); - query.setOwnerTypeQuery(idpOTQ); + switch (this.idpType) { + case IDPOwnerType.IDP_OWNER_TYPE_ORG: + const query: IDPQuery = new IDPQuery(); + const idpOTQ: IDPOwnerTypeQuery = new IDPOwnerTypeQuery(); + idpOTQ.setOwnerType(this.idpType); + query.setOwnerTypeQuery(idpOTQ); + + this.mgmtService.listOrgIDPs(undefined, undefined, [query]).then(resp => { + this.availableIdps = resp.resultList; + }); + break; + case IDPOwnerType.IDP_OWNER_TYPE_SYSTEM: + this.adminService.listIDPs().then(resp => { + this.availableIdps = resp.resultList; + console.log(resp); + }); + break; - this.mgmtService.listOrgIDPs(undefined, undefined, [query]).then(resp => { - this.availableIdps = resp.resultList; - }); - } else if (this.serviceType === PolicyComponentServiceType.ADMIN) { - this.adminService.listIDPs().then(resp => { - this.availableIdps = resp.resultList; - }); } } diff --git a/console/src/app/pages/orgs/org-detail/org-detail.component.html b/console/src/app/pages/orgs/org-detail/org-detail.component.html index e9c138895a..481e5aca5b 100644 --- a/console/src/app/pages/orgs/org-detail/org-detail.component.html +++ b/console/src/app/pages/orgs/org-detail/org-detail.component.html @@ -46,7 +46,7 @@
{{'ORG.PAGES.STATE' | translate}} {{'ORG.STATE.'+org.state + [ngClass]="{'active': org.state === OrgState.ORG_STATE_ACTIVE, 'inactive': org.state === OrgState.ORG_STATE_INACTIVE}">{{'ORG.STATE.'+org.state | translate}}
diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html index 9563ccb746..41d823afbf 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html @@ -141,6 +141,13 @@ +
+ +
+
diff --git a/console/src/app/pages/users/user-create-machine/user-create-machine.component.html b/console/src/app/pages/users/user-create-machine/user-create-machine.component.html index e36daca69b..9e395451cf 100644 --- a/console/src/app/pages/users/user-create-machine/user-create-machine.component.html +++ b/console/src/app/pages/users/user-create-machine/user-create-machine.component.html @@ -27,8 +27,8 @@
- +
\ 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.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-factor-dialog/auth-factor-dialog.component.ts index 629173edba..77d2190e62 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 @@ -52,20 +52,22 @@ export class AuthFactorDialogComponent { }); } else if (type == AuthFactorType.U2F) { this.authService.addMyMultiFactorU2F().then((u2fresp) => { - const credOptions: CredentialCreationOptions = JSON.parse(atob(u2fresp.key?.publicKey as string)); + if (u2fresp.key) { + const credOptions: CredentialCreationOptions = JSON.parse(atob(u2fresp.key?.publicKey as string)); - if (credOptions.publicKey?.challenge) { - credOptions.publicKey.challenge = _base64ToArrayBuffer(credOptions.publicKey.challenge as any); - credOptions.publicKey.user.id = _base64ToArrayBuffer(credOptions.publicKey.user.id as any); - if (credOptions.publicKey.excludeCredentials) { - credOptions.publicKey.excludeCredentials.map(cred => { - cred.id = _base64ToArrayBuffer(cred.id as any); - return cred; - }); + if (credOptions.publicKey?.challenge) { + console.log(credOptions.publicKey); + credOptions.publicKey.challenge = _base64ToArrayBuffer(credOptions.publicKey.challenge as any); + credOptions.publicKey.user.id = _base64ToArrayBuffer(credOptions.publicKey.user.id as any); + if (credOptions.publicKey.excludeCredentials) { + credOptions.publicKey.excludeCredentials.map(cred => { + cred.id = _base64ToArrayBuffer(cred.id as any); + return cred; + }); + } + this.u2fCredentialOptions = credOptions; } - this.u2fCredentialOptions = credOptions; } - }, error => { this.toast.showError(error); }); 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 e7679526fe..6600345a54 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 @@ -74,11 +74,7 @@ export class AuthPasswordlessComponent implements OnInit, OnDestroy { }); dialogRef.afterClosed().subscribe(done => { - if (done) { - this.getPasswordless(); - } else { - this.getPasswordless(); - } + this.getPasswordless(); }); } } diff --git a/console/src/app/pages/users/user-detail/detail-form-machine/detail-form-machine.component.ts b/console/src/app/pages/users/user-detail/detail-form-machine/detail-form-machine.component.ts index 6cd53052ee..20d6996a3b 100644 --- a/console/src/app/pages/users/user-detail/detail-form-machine/detail-form-machine.component.ts +++ b/console/src/app/pages/users/user-detail/detail-form-machine/detail-form-machine.component.ts @@ -23,7 +23,7 @@ export class DetailFormMachineComponent implements OnInit, OnDestroy { userName: [{ value: '', disabled: true }, [ Validators.required, ]], - name: [{ value: '', disabled: true }, Validators.required], + name: [{ value: '', disabled: this.disabled }, Validators.required], description: [{ value: '', disabled: this.disabled }], }); } diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html index 7db32aea8a..a8711deacb 100644 --- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html +++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html @@ -15,11 +15,12 @@ + *ngIf="user?.state === UserState.USER_STATE_ACTIVE" + (click)="changeState(UserState.USER_STATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' | + translate}} + *ngIf="user?.state === UserState.USER_STATE_INACTIVE" + (click)="changeState(UserState.USER_STATE_ACTIVE)">{{'USER.PAGES.REACTIVATE' | translate}}
@@ -76,11 +77,11 @@ (resendEmailVerification)="resendEmailVerification()" (resendPhoneVerification)="resendPhoneVerification()"> - + mat-stroked-button color="primary" *ngIf="user.state === UserState.USER_STATE_INITIAL">{{ + 'USER.PASSWORD.RESENDNOTIFICATION' | translate }} + @@ -109,9 +110,10 @@ {{user.preferredLoginName}}
- {{'ORG.PAGES.STATE' | translate}} + {{'ORG.PAGES.STATE' | translate}} {{'USER.DATA.STATE'+user.state | translate}} + [ngClass]="{'active': user.state === UserState.USER_STATE_ACTIVE, 'inactive': user.state === UserState.USER_STATE_INACTIVE}">{{'USER.DATA.STATE'+user.state + | translate}}
diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts index 596de57508..7fbcb7a054 100644 --- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts +++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts @@ -111,6 +111,7 @@ export class UserDetailComponent implements OnInit { this.mgmtUserService .updateMachine( this.user.id, + this.user.machine.name, this.user.machine.description) .then(() => { this.toast.showInfo('USER.TOAST.SAVED', true); @@ -156,6 +157,14 @@ export class UserDetailComponent implements OnInit { if (this.user.id && email) { this.mgmtUserService.updateHumanEmail(this.user.id, email).then(() => { this.toast.showInfo('USER.TOAST.EMAILSAVED', true); + if (this.user.state == UserState.USER_STATE_INITIAL) { + this.mgmtUserService.resendHumanInitialization(this.user.id, email ?? '').then(() => { + this.toast.showInfo('USER.TOAST.INITEMAILSENT', true); + this.refreshChanges$.emit(); + }).catch(error => { + this.toast.showError(error); + }); + } if (this.user.human) { this.user.human.email = new Email().setEmail(email).toObject(); this.refreshUser(); diff --git a/console/src/app/pages/users/user-detail/user-detail/user-mfa/user-mfa.component.html b/console/src/app/pages/users/user-detail/user-detail/user-mfa/user-mfa.component.html index d14b4a22d6..262b2e8a06 100644 --- a/console/src/app/pages/users/user-detail/user-detail/user-mfa/user-mfa.component.html +++ b/console/src/app/pages/users/user-detail/user-detail/user-mfa/user-mfa.component.html @@ -3,7 +3,10 @@ - + diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index ca818d35af..c5fdf93c0d 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -724,6 +724,7 @@ "USERNAME": "Benutzername", "FIRSTNAME": "Vorname", "LASTNAME": "Nachname", + "LOGINNAME":"Loginname", "EMAIL": "E-Mail", "ROLES": "Rollen", "USERID": "Benutzer-ID" @@ -857,7 +858,7 @@ "DESCRIPTION":"Geben Sie die korrekte OIDC Konfiguration Ihres Identity Providers an!" } }, - "TYPES": { + "OWNERTYPES": { "0":"unknown", "1":"System", "2":"Organisation" diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index a35b7082e8..5f0c1ac981 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -722,6 +722,7 @@ "USERNAME": "User Name", "FIRSTNAME": "First Name", "LASTNAME": "Last Name", + "LOGINNAME":"Loginname", "EMAIL": "E-mail", "ROLES": "Roles", "USERID":"User ID" @@ -855,7 +856,7 @@ "DESCRIPTION":"Provide the correct OIDC Configuration for your identity Provider below!" } }, - "TYPES": { + "OWNERTYPES": { "0":"unknown", "1":"System", "2":"Organisation"
{{ 'USER.MFA.TABLETYPE' | translate }} {{'USER.MFA.TYPE.'+ mfa.type | translate}} + OTP (One-Time Password) + U2F (Universal 2nd Factor) +