diff --git a/console/src/app/modules/project-members/project-members-datasource.ts b/console/src/app/modules/project-members/project-members-datasource.ts index 4e025f1e8a..b1378c4f08 100644 --- a/console/src/app/modules/project-members/project-members-datasource.ts +++ b/console/src/app/modules/project-members/project-members-datasource.ts @@ -7,8 +7,8 @@ import { Member } from 'src/app/proto/generated/zitadel/member_pb'; import { ManagementService } from 'src/app/services/mgmt.service'; export enum ProjectType { - PROJECTTYPE_OWNED = 'OWNED', - PROJECTTYPE_GRANTED = 'GRANTED', + PROJECTTYPE_OWNED = 'OWNED', + PROJECTTYPE_GRANTED = 'GRANTED', } /** @@ -17,68 +17,70 @@ export enum ProjectType { * (including sorting, pagination, and filtering). */ export class ProjectMembersDataSource extends DataSource { - public totalResult: number = 0; - public viewTimestamp!: Timestamp.AsObject; + public totalResult: number = 0; + public viewTimestamp!: Timestamp.AsObject; - public membersSubject: BehaviorSubject = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); + public membersSubject: BehaviorSubject = new BehaviorSubject([]); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); - constructor(private mgmtService: ManagementService) { - super(); - } - - public loadMembers(projectId: string, - projectType: ProjectType, - pageIndex: number, pageSize: number, grantId?: string): void { - const offset = pageIndex * pageSize; - - this.loadingSubject.next(true); - - const promise: - Promise | - Promise - | undefined = - projectType === ProjectType.PROJECTTYPE_OWNED ? - this.mgmtService.listProjectMembers(projectId, pageSize, offset) : - projectType === ProjectType.PROJECTTYPE_GRANTED && grantId ? - this.mgmtService.listProjectGrantMembers(projectId, - grantId, pageSize, offset) : undefined; - if (promise) { - from(promise).pipe( - map(resp => { - if (resp.details?.totalResult) { - this.totalResult = resp.details?.totalResult; - } - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details.viewTimestamp; - } - return resp.resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(members => { - this.membersSubject.next(members); - }); - } + constructor(private mgmtService: ManagementService) { + super(); + } + + public loadMembers(projectId: string, + projectType: ProjectType, + pageIndex: number, pageSize: number, grantId?: string): void { + const offset = pageIndex * pageSize; + + this.loadingSubject.next(true); + + const promise: + Promise | + Promise + | undefined = + projectType === ProjectType.PROJECTTYPE_OWNED ? + this.mgmtService.listProjectMembers(projectId, pageSize, offset) : + projectType === ProjectType.PROJECTTYPE_GRANTED && grantId ? + this.mgmtService.listProjectGrantMembers(projectId, + grantId, pageSize, offset) : undefined; + if (promise) { + from(promise).pipe( + map(resp => { + if (resp.details?.totalResult) { + this.totalResult = resp.details?.totalResult; + } else { + this.totalResult = 0; + } + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details.viewTimestamp; + } + return resp.resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(members => { + this.membersSubject.next(members); + }); } + } - /** - * Connect this data source to the table. The table will only update when - * the returned stream emits new items. - * @returns A stream of the items to be rendered. - */ - public connect(): Observable { - return this.membersSubject.asObservable(); - } + /** + * Connect this data source to the table. The table will only update when + * the returned stream emits new items. + * @returns A stream of the items to be rendered. + */ + public connect(): Observable { + return this.membersSubject.asObservable(); + } - /** - * Called when the table is being destroyed. Use this function, to clean up - * any open connections or free any held resources that were set up during connect. - */ - public disconnect(): void { - this.membersSubject.complete(); - this.loadingSubject.complete(); - } + /** + * Called when the table is being destroyed. Use this function, to clean up + * any open connections or free any held resources that were set up during connect. + */ + public disconnect(): void { + this.membersSubject.complete(); + this.loadingSubject.complete(); + } } 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..29dd19703d 100644 --- a/console/src/app/modules/user-grants/user-grants-datasource.ts +++ b/console/src/app/modules/user-grants/user-grants-datasource.ts @@ -4,150 +4,152 @@ import { BehaviorSubject, from, Observable, of } from 'rxjs'; import { catchError, finalize, map } from 'rxjs/operators'; import { ListUserGrantResponse } from 'src/app/proto/generated/zitadel/management_pb'; import { - UserGrant, - UserGrantProjectGrantIDQuery, - UserGrantProjectIDQuery, - UserGrantQuery, - UserGrantUserIDQuery, + UserGrant, + UserGrantProjectGrantIDQuery, + UserGrantProjectIDQuery, + UserGrantQuery, + UserGrantUserIDQuery, } from 'src/app/proto/generated/zitadel/user_pb'; import { ManagementService } from 'src/app/services/mgmt.service'; export enum UserGrantContext { - NONE = 'none', - USER = 'user', - OWNED_PROJECT = 'owned', - GRANTED_PROJECT = 'granted', + NONE = 'none', + USER = 'user', + OWNED_PROJECT = 'owned', + GRANTED_PROJECT = 'granted', } export class UserGrantsDataSource extends DataSource { - public totalResult: number = 0; - public viewTimestamp!: Timestamp.AsObject; + public totalResult: number = 0; + public viewTimestamp!: Timestamp.AsObject; - public grantsSubject: BehaviorSubject = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); + public grantsSubject: BehaviorSubject = new BehaviorSubject([]); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); - constructor(private userService: ManagementService) { - super(); - } + constructor(private userService: ManagementService) { + super(); + } - public loadGrants( - context: UserGrantContext, - pageIndex: number, - pageSize: number, - data: { - projectId?: string; - grantId?: string; - userId?: string; - }, - queries?: UserGrantQuery[], - ): void { - switch (context) { - case UserGrantContext.USER: - if (data && data.userId) { - this.loadingSubject.next(true); + public loadGrants( + context: UserGrantContext, + pageIndex: number, + pageSize: number, + data: { + projectId?: string; + grantId?: string; + userId?: string; + }, + queries?: UserGrantQuery[], + ): void { + switch (context) { + case UserGrantContext.USER: + if (data && data.userId) { + this.loadingSubject.next(true); - const userfilter = new UserGrantQuery(); - const ugUiq = new UserGrantUserIDQuery(); - ugUiq.setUserId(data.userId); - userfilter.setUserIdQuery(ugUiq); + const userfilter = new UserGrantQuery(); + const ugUiq = new UserGrantUserIDQuery(); + ugUiq.setUserId(data.userId); + userfilter.setUserIdQuery(ugUiq); - if (queries) { - queries.push(userfilter); - } else { - queries = [userfilter]; - } + if (queries) { + queries.push(userfilter); + } else { + queries = [userfilter]; + } - const promise = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries); - this.loadResponse(promise); - } - break; - case UserGrantContext.OWNED_PROJECT: - if (data && data.projectId) { - this.loadingSubject.next(true); - - const projectfilter = new UserGrantQuery(); - const ugPfq = new UserGrantProjectIDQuery(); - ugPfq.setProjectId(data.projectId); - projectfilter.setProjectIdQuery(ugPfq); - - if (queries) { - queries.push(projectfilter); - } else { - queries = [projectfilter]; - } - - const promise1 = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries); - this.loadResponse(promise1); - } - break; - case UserGrantContext.GRANTED_PROJECT: - if (data && data.grantId && data.projectId) { - this.loadingSubject.next(true); - - const grantfilter = new UserGrantQuery(); - - const uggiq = new UserGrantProjectGrantIDQuery(); - uggiq.setProjectGrantId(data.grantId); - grantfilter.setProjectGrantIdQuery(uggiq); - - const projectfilter = new UserGrantQuery(); - const ugPfq = new UserGrantProjectIDQuery(); - ugPfq.setProjectId(data.projectId); - projectfilter.setProjectIdQuery(ugPfq); - - if (queries) { - queries.push(grantfilter); - } else { - queries = [grantfilter]; - } - - const promise2 = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries); - this.loadResponse(promise2); - } - break; - default: - this.loadingSubject.next(true); - const promise3 = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries ?? []); - this.loadResponse(promise3); - break; + const promise = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries); + this.loadResponse(promise); } - } + break; + case UserGrantContext.OWNED_PROJECT: + if (data && data.projectId) { + this.loadingSubject.next(true); - private loadResponse(promise: Promise): void { - from(promise).pipe( - map(resp => { - if (resp.details?.totalResult) { - this.totalResult = resp.details.totalResult; - } - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details.viewTimestamp; - } - return resp.resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(grants => { - this.grantsSubject.next(grants); - }); + const projectfilter = new UserGrantQuery(); + const ugPfq = new UserGrantProjectIDQuery(); + ugPfq.setProjectId(data.projectId); + projectfilter.setProjectIdQuery(ugPfq); + + if (queries) { + queries.push(projectfilter); + } else { + queries = [projectfilter]; + } + + const promise1 = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries); + this.loadResponse(promise1); + } + break; + case UserGrantContext.GRANTED_PROJECT: + if (data && data.grantId && data.projectId) { + this.loadingSubject.next(true); + + const grantfilter = new UserGrantQuery(); + + const uggiq = new UserGrantProjectGrantIDQuery(); + uggiq.setProjectGrantId(data.grantId); + grantfilter.setProjectGrantIdQuery(uggiq); + + const projectfilter = new UserGrantQuery(); + const ugPfq = new UserGrantProjectIDQuery(); + ugPfq.setProjectId(data.projectId); + projectfilter.setProjectIdQuery(ugPfq); + + if (queries) { + queries.push(grantfilter); + } else { + queries = [grantfilter]; + } + + const promise2 = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries); + this.loadResponse(promise2); + } + break; + default: + this.loadingSubject.next(true); + const promise3 = this.userService.listUserGrants(pageSize, pageSize * pageIndex, queries ?? []); + this.loadResponse(promise3); + break; } + } + + private loadResponse(promise: Promise): void { + from(promise).pipe( + map(resp => { + if (resp.details?.totalResult) { + this.totalResult = resp.details.totalResult; + } else { + this.totalResult = 0; + } + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details.viewTimestamp; + } + return resp.resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(grants => { + this.grantsSubject.next(grants); + }); + } - /** - * Connect this data source to the table. The table will only update when - * the returned stream emits new items. - * @returns A stream of the items to be rendered. - */ - public connect(): Observable { - return this.grantsSubject.asObservable(); - } + /** + * Connect this data source to the table. The table will only update when + * the returned stream emits new items. + * @returns A stream of the items to be rendered. + */ + public connect(): Observable { + return this.grantsSubject.asObservable(); + } - /** - * Called when the table is being destroyed. Use this function, to clean up - * any open connections or free any held resources that were set up during connect. - */ - public disconnect(): void { - this.grantsSubject.complete(); - this.loadingSubject.complete(); - } + /** + * Called when the table is being destroyed. Use this function, to clean up + * any open connections or free any held resources that were set up during connect. + */ + public disconnect(): void { + this.grantsSubject.complete(); + this.loadingSubject.complete(); + } } diff --git a/console/src/app/pages/iam/iam.component.ts b/console/src/app/pages/iam/iam.component.ts index 557cb560cb..852dcb033a 100644 --- a/console/src/app/pages/iam/iam.component.ts +++ b/console/src/app/pages/iam/iam.component.ts @@ -13,83 +13,85 @@ import { AdminService } from 'src/app/services/admin.service'; import { ToastService } from 'src/app/services/toast.service'; @Component({ - selector: 'app-iam', - templateUrl: './iam.component.html', - styleUrls: ['./iam.component.scss'], + selector: 'app-iam', + templateUrl: './iam.component.html', + styleUrls: ['./iam.component.scss'], }) export class IamComponent { - public PolicyComponentServiceType: any = PolicyComponentServiceType; - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); - public totalMemberResult: number = 0; - public membersSubject: BehaviorSubject - = new BehaviorSubject([]); + public PolicyComponentServiceType: any = PolicyComponentServiceType; + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); + public totalMemberResult: number = 0; + public membersSubject: BehaviorSubject + = new BehaviorSubject([]); - public PolicyGridType: any = PolicyGridType; - public features!: Features.AsObject; + public PolicyGridType: any = PolicyGridType; + public features!: Features.AsObject; - constructor(public adminService: AdminService, private dialog: MatDialog, private toast: ToastService, - private router: Router) { - this.loadMembers(); - this.loadFeatures(); - this.adminService.getDefaultFeatures(); - } + constructor(public adminService: AdminService, private dialog: MatDialog, private toast: ToastService, + private router: Router) { + this.loadMembers(); + this.loadFeatures(); + this.adminService.getDefaultFeatures(); + } - public loadMembers(): void { - this.loadingSubject.next(true); - from(this.adminService.listIAMMembers(100, 0)).pipe( - map(resp => { - if (resp.details?.totalResult) { - this.totalMemberResult = resp.details.totalResult; - } - return resp.resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(members => { - this.membersSubject.next(members); - }); - } + public loadMembers(): void { + this.loadingSubject.next(true); + from(this.adminService.listIAMMembers(100, 0)).pipe( + map(resp => { + if (resp.details?.totalResult) { + this.totalMemberResult = resp.details.totalResult; + } else { + this.totalMemberResult = 0; + } + return resp.resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(members => { + this.membersSubject.next(members); + }); + } - public openAddMember(): void { - const dialogRef = this.dialog.open(MemberCreateDialogComponent, { - data: { - creationType: CreationType.IAM, - }, - width: '400px', - }); + public openAddMember(): void { + const dialogRef = this.dialog.open(MemberCreateDialogComponent, { + data: { + creationType: CreationType.IAM, + }, + width: '400px', + }); - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - const users: User.AsObject[] = resp.users; - const roles: string[] = resp.roles; + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + const users: User.AsObject[] = resp.users; + const roles: string[] = resp.roles; - if (users && users.length && roles && roles.length) { - Promise.all(users.map(user => { - return this.adminService.addIAMMember(user.id, roles); - })).then(() => { - this.toast.showInfo('IAM.TOAST.MEMBERADDED'); - setTimeout(() => { - this.loadMembers(); - }, 1000); - }).catch(error => { - this.toast.showError(error); - }); - } - } - }); - } + if (users && users.length && roles && roles.length) { + Promise.all(users.map(user => { + return this.adminService.addIAMMember(user.id, roles); + })).then(() => { + this.toast.showInfo('IAM.TOAST.MEMBERADDED'); + setTimeout(() => { + this.loadMembers(); + }, 1000); + }).catch(error => { + this.toast.showError(error); + }); + } + } + }); + } - public showDetail(): void { - this.router.navigate(['iam/members']); - } + public showDetail(): void { + this.router.navigate(['iam/members']); + } - public loadFeatures(): void { - this.loadingSubject.next(true); - this.adminService.getDefaultFeatures().then(resp => { - if (resp.features) { - this.features = resp.features; - } - }); - } + public loadFeatures(): void { + this.loadingSubject.next(true); + this.adminService.getDefaultFeatures().then(resp => { + if (resp.features) { + this.features = resp.features; + } + }); + } } diff --git a/console/src/app/pages/orgs/org-detail/org-detail.component.ts b/console/src/app/pages/orgs/org-detail/org-detail.component.ts index 49cd7f6ec0..7c728f5705 100644 --- a/console/src/app/pages/orgs/org-detail/org-detail.component.ts +++ b/console/src/app/pages/orgs/org-detail/org-detail.component.ts @@ -204,7 +204,10 @@ export class OrgDetailComponent implements OnInit { map(resp => { if (resp.details?.totalResult) { this.totalMemberResult = resp.details?.totalResult; + } else { + this.totalMemberResult = 0; } + return resp.resultList; }), catchError(() => of([])), diff --git a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html index b041494e1a..18c1340ed4 100644 --- a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html +++ b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html @@ -3,16 +3,27 @@

{{'APP.OIDC.CLIENTSECRET_DESCRIPTION' | translate}}

-

ClientId: {{data.clientId}}

+
+ ClientId: {{data.clientId}} + +
-
+
+ ClientSecret: {{data.clientSecret}} - {{data.clientSecret}}
+ + + {{'APP.OIDC.CLIENTSECRET_NOSECRET' | translate}} +
diff --git a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.scss b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.scss index 87f3b764d0..f1f21edb58 100644 --- a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.scss +++ b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.scss @@ -23,11 +23,16 @@ .flex { display: flex; align-items: center; - padding: .5rem; border: 1px solid #ffffff20; border-radius: .5rem; + justify-content: space-between; - .secret { + .overflow-auto { overflow: auto; + + .desc { + font-size: 14px; + color: var(--grey); + } } } diff --git a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts index 0d4f876a57..57758307ec 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts +++ b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts @@ -15,127 +15,129 @@ import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; @Component({ - selector: 'app-granted-project-detail', - templateUrl: './granted-project-detail.component.html', - styleUrls: ['./granted-project-detail.component.scss'], + selector: 'app-granted-project-detail', + templateUrl: './granted-project-detail.component.html', + styleUrls: ['./granted-project-detail.component.scss'], }) export class GrantedProjectDetailComponent implements OnInit, OnDestroy { - public projectId: string = ''; - public grantId: string = ''; - public project!: GrantedProject.AsObject; + public projectId: string = ''; + public grantId: string = ''; + public project!: GrantedProject.AsObject; - public ProjectState: any = ProjectState; - public ChangeType: any = ChangeType; + public ProjectState: any = ProjectState; + public ChangeType: any = ChangeType; - private subscription?: Subscription; + private subscription?: Subscription; - public isZitadel: boolean = false; + public isZitadel: boolean = false; - UserGrantContext: any = UserGrantContext; + UserGrantContext: any = UserGrantContext; - // members - public totalMemberResult: number = 0; - public membersSubject: BehaviorSubject - = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(true); - public loading$: Observable = this.loadingSubject.asObservable(); + // members + public totalMemberResult: number = 0; + public membersSubject: BehaviorSubject + = new BehaviorSubject([]); + private loadingSubject: BehaviorSubject = new BehaviorSubject(true); + public loading$: Observable = this.loadingSubject.asObservable(); - constructor( - public translate: TranslateService, - private route: ActivatedRoute, - private toast: ToastService, - private mgmtService: ManagementService, - private _location: Location, - private router: Router, - private dialog: MatDialog, - ) { - } + constructor( + public translate: TranslateService, + private route: ActivatedRoute, + private toast: ToastService, + private mgmtService: ManagementService, + private _location: Location, + private router: Router, + private dialog: MatDialog, + ) { + } - public ngOnInit(): void { - this.subscription = this.route.params.subscribe(params => this.getData(params)); - } + public ngOnInit(): void { + this.subscription = this.route.params.subscribe(params => this.getData(params)); + } - public ngOnDestroy(): void { - this.subscription?.unsubscribe(); - } + public ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } - private async getData({ id, grantId }: Params): Promise { - this.projectId = id; - this.grantId = grantId; + private async getData({ id, grantId }: Params): Promise { + this.projectId = id; + this.grantId = grantId; - this.mgmtService.getIAM().then(iam => { - this.isZitadel = iam.iamProjectId === this.projectId; - }); + this.mgmtService.getIAM().then(iam => { + this.isZitadel = iam.iamProjectId === this.projectId; + }); - if (this.projectId && this.grantId) { - this.mgmtService.getGrantedProjectByID(this.projectId, this.grantId).then(proj => { - if (proj.grantedProject) { - this.project = proj.grantedProject; - } - }).catch(error => { - this.toast.showError(error); - }); - - this.loadMembers(); + if (this.projectId && this.grantId) { + this.mgmtService.getGrantedProjectByID(this.projectId, this.grantId).then(proj => { + if (proj.grantedProject) { + this.project = proj.grantedProject; } - } + }).catch(error => { + this.toast.showError(error); + }); - public loadMembers(): void { - this.loadingSubject.next(true); - from(this.mgmtService.listProjectGrantMembers(this.projectId, - this.grantId, 100, 0)).pipe( - map(resp => { - if (resp.details?.totalResult) { - this.totalMemberResult = resp.details.totalResult; - } - return resp.resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(members => { - this.membersSubject.next(members); + this.loadMembers(); + } + } + + public loadMembers(): void { + this.loadingSubject.next(true); + from(this.mgmtService.listProjectGrantMembers(this.projectId, + this.grantId, 100, 0)).pipe( + map(resp => { + if (resp.details?.totalResult) { + this.totalMemberResult = resp.details.totalResult; + } else { + this.totalMemberResult = 0; + } + return resp.resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(members => { + this.membersSubject.next(members); + }); + } + + public navigateBack(): void { + this._location.back(); + } + + public openAddMember(): void { + const dialogRef = this.dialog.open(MemberCreateDialogComponent, { + data: { + creationType: CreationType.PROJECT_GRANTED, + }, + width: '400px', + }); + + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + const users: User.AsObject[] = resp.users; + const roles: string[] = resp.roles; + + if (users && users.length && roles && roles.length) { + users.forEach(user => { + return this.mgmtService.addProjectGrantMember( + this.projectId, + this.grantId, + user.id, + roles, + ).then(() => { + this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true); + setTimeout(() => { + this.loadMembers(); + }, 1000); + }).catch(error => { + this.toast.showError(error); }); - } + }); + } + } + }); + } - public navigateBack(): void { - this._location.back(); - } - - public openAddMember(): void { - const dialogRef = this.dialog.open(MemberCreateDialogComponent, { - data: { - creationType: CreationType.PROJECT_GRANTED, - }, - width: '400px', - }); - - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - const users: User.AsObject[] = resp.users; - const roles: string[] = resp.roles; - - if (users && users.length && roles && roles.length) { - users.forEach(user => { - return this.mgmtService.addProjectGrantMember( - this.projectId, - this.grantId, - user.id, - roles, - ).then(() => { - this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true); - setTimeout(() => { - this.loadMembers(); - }, 1000); - }).catch(error => { - this.toast.showError(error); - }); - }); - } - } - }); - } - - public showDetail(): void { - this.router.navigate(['granted-projects', this.project.projectId, 'grant', this.grantId, 'members']); - } + public showDetail(): void { + this.router.navigate(['granted-projects', this.project.projectId, 'grant', this.grantId, 'members']); + } } diff --git a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.ts b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.ts index 63c6b680b8..7076417e10 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.ts +++ b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-list.component.ts @@ -12,107 +12,109 @@ import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; @Component({ - selector: 'app-granted-project-list', - templateUrl: './granted-project-list.component.html', - styleUrls: ['./granted-project-list.component.scss'], - animations: [ - trigger('list', [ - transition(':enter', [ - query('@animate', - stagger(80, animateChild()), - ), - ]), - ]), - trigger('animate', [ - transition(':enter', [ - style({ opacity: 0, transform: 'translateY(-100%)' }), - animate('100ms', style({ opacity: 1, transform: 'translateY(0)' })), - ]), - transition(':leave', [ - style({ opacity: 1, transform: 'translateY(0)' }), - animate('100ms', style({ opacity: 0, transform: 'translateY(100%)' })), - ]), - ]), - ], + selector: 'app-granted-project-list', + templateUrl: './granted-project-list.component.html', + styleUrls: ['./granted-project-list.component.scss'], + animations: [ + trigger('list', [ + transition(':enter', [ + query('@animate', + stagger(80, animateChild()), + ), + ]), + ]), + trigger('animate', [ + transition(':enter', [ + style({ opacity: 0, transform: 'translateY(-100%)' }), + animate('100ms', style({ opacity: 1, transform: 'translateY(0)' })), + ]), + transition(':leave', [ + style({ opacity: 1, transform: 'translateY(0)' }), + animate('100ms', style({ opacity: 0, transform: 'translateY(100%)' })), + ]), + ]), + ], }) export class GrantedProjectListComponent implements OnInit, OnDestroy { - public totalResult: number = 0; - public viewTimestamp!: Timestamp.AsObject; + public totalResult: number = 0; + public viewTimestamp!: Timestamp.AsObject; - public dataSource: MatTableDataSource = - new MatTableDataSource(); - @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; + public dataSource: MatTableDataSource = + new MatTableDataSource(); + @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; - public grantedProjectList: GrantedProject.AsObject[] = []; - public displayedColumns: string[] = ['select', 'name', 'resourceOwnerName', 'state', 'creationDate', 'changeDate']; - public selection: SelectionModel = new SelectionModel(true, []); + public grantedProjectList: GrantedProject.AsObject[] = []; + public displayedColumns: string[] = ['select', 'name', 'resourceOwnerName', 'state', 'creationDate', 'changeDate']; + public selection: SelectionModel = new SelectionModel(true, []); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); - public grid: boolean = true; - private subscription?: Subscription; + public grid: boolean = true; + private subscription?: Subscription; - constructor(private router: Router, - public translate: TranslateService, - private mgmtService: ManagementService, - private toast: ToastService, - ) { } + constructor(private router: Router, + public translate: TranslateService, + private mgmtService: ManagementService, + private toast: ToastService, + ) { } - public ngOnInit(): void { - this.getData(10, 0); - } + public ngOnInit(): void { + this.getData(10, 0); + } - public ngOnDestroy(): void { - this.subscription?.unsubscribe(); - } + public ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } - public isAllSelected(): boolean { - const numSelected = this.selection.selected.length; - const numRows = this.dataSource.data.length; - return numSelected === numRows; - } + public isAllSelected(): boolean { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected === numRows; + } - public masterToggle(): void { - this.isAllSelected() ? - this.selection.clear() : - this.dataSource.data.forEach(row => this.selection.select(row)); - } + public masterToggle(): void { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); + } - public changePage(event: PageEvent): void { - this.getData(event.pageSize, event.pageIndex); - } + public changePage(event: PageEvent): void { + this.getData(event.pageSize, event.pageIndex); + } - public addProject(): void { - this.router.navigate(['/projects', 'create']); - } + public addProject(): void { + this.router.navigate(['/projects', 'create']); + } - private async getData(limit: number, offset: number): Promise { - this.loadingSubject.next(true); - this.mgmtService.listGrantedProjects(limit, offset).then(resp => { - this.grantedProjectList = resp.resultList; - if (resp.details?.totalResult) { - this.totalResult = resp.details.totalResult; - } - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details?.viewTimestamp; - } - if (this.totalResult > 5) { - this.grid = false; - } - this.dataSource.data = this.grantedProjectList; - console.log(resp.resultList); + private async getData(limit: number, offset: number): Promise { + this.loadingSubject.next(true); + this.mgmtService.listGrantedProjects(limit, offset).then(resp => { + this.grantedProjectList = resp.resultList; + if (resp.details?.totalResult) { + this.totalResult = resp.details.totalResult; + } else { + this.totalResult = 0; + } + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details?.viewTimestamp; + } + if (this.totalResult > 5) { + this.grid = false; + } + this.dataSource.data = this.grantedProjectList; + console.log(resp.resultList); - this.loadingSubject.next(false); - }).catch(error => { - console.error(error); - this.toast.showError(error); - this.loadingSubject.next(false); - }); - } + this.loadingSubject.next(false); + }).catch(error => { + console.error(error); + this.toast.showError(error); + this.loadingSubject.next(false); + }); + } - public refreshPage(): void { - this.selection.clear(); - this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); - } + public refreshPage(): void { + this.selection.clear(); + this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); + } } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts index e6e705764b..e763beea8b 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts @@ -19,220 +19,222 @@ import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; @Component({ - selector: 'app-owned-project-detail', - templateUrl: './owned-project-detail.component.html', - styleUrls: ['./owned-project-detail.component.scss'], + selector: 'app-owned-project-detail', + templateUrl: './owned-project-detail.component.html', + styleUrls: ['./owned-project-detail.component.scss'], }) export class OwnedProjectDetailComponent implements OnInit, OnDestroy { - public projectId: string = ''; - public project!: Project.AsObject; + public projectId: string = ''; + public project!: Project.AsObject; - public pageSizeApps: number = 10; - public appsDataSource: MatTableDataSource = new MatTableDataSource(); - public appsResult!: ListAppsResponse.AsObject; - public appsColumns: string[] = ['name']; + public pageSizeApps: number = 10; + public appsDataSource: MatTableDataSource = new MatTableDataSource(); + public appsResult!: ListAppsResponse.AsObject; + public appsColumns: string[] = ['name']; - public ProjectState: any = ProjectState; - public ChangeType: any = ChangeType; + public ProjectState: any = ProjectState; + public ChangeType: any = ChangeType; - public grid: boolean = true; - private subscription?: Subscription; - public editstate: boolean = false; + public grid: boolean = true; + private subscription?: Subscription; + public editstate: boolean = false; - public isZitadel: boolean = false; + public isZitadel: boolean = false; - public UserGrantContext: any = UserGrantContext; + public UserGrantContext: any = UserGrantContext; - // members - public totalMemberResult: number = 0; - public membersSubject: BehaviorSubject - = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(true); - public loading$: Observable = this.loadingSubject.asObservable(); - public refreshChanges$: EventEmitter = new EventEmitter(); + // members + public totalMemberResult: number = 0; + public membersSubject: BehaviorSubject + = new BehaviorSubject([]); + private loadingSubject: BehaviorSubject = new BehaviorSubject(true); + public loading$: Observable = this.loadingSubject.asObservable(); + public refreshChanges$: EventEmitter = new EventEmitter(); - constructor( - public translate: TranslateService, - private route: ActivatedRoute, - private toast: ToastService, - private mgmtService: ManagementService, - private _location: Location, - private dialog: MatDialog, - private router: Router, - ) { } + constructor( + public translate: TranslateService, + private route: ActivatedRoute, + private toast: ToastService, + private mgmtService: ManagementService, + private _location: Location, + private dialog: MatDialog, + private router: Router, + ) { } - public ngOnInit(): void { - this.subscription = this.route.params.subscribe(params => this.getData(params)); - } + public ngOnInit(): void { + this.subscription = this.route.params.subscribe(params => this.getData(params)); + } - public ngOnDestroy(): void { - this.subscription?.unsubscribe(); - } + public ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } - private async getData({ id }: Params): Promise { - this.projectId = id; + private async getData({ id }: Params): Promise { + this.projectId = id; - this.mgmtService.getIAM().then(iam => { - this.isZitadel = iam.iamProjectId === this.projectId; - }); + this.mgmtService.getIAM().then(iam => { + this.isZitadel = iam.iamProjectId === this.projectId; + }); - this.mgmtService.getProjectByID(id).then(resp => { - if (resp.project) { - this.project = resp.project; - } - }).catch(error => { - console.error(error); - this.toast.showError(error); - }); + this.mgmtService.getProjectByID(id).then(resp => { + if (resp.project) { + this.project = resp.project; + } + }).catch(error => { + console.error(error); + this.toast.showError(error); + }); - this.loadMembers(); - } + this.loadMembers(); + } - public loadMembers(): void { - this.loadingSubject.next(true); - from(this.mgmtService.listProjectMembers(this.projectId, 100, 0)).pipe( - map(resp => { - if (resp.details?.totalResult) { - this.totalMemberResult = resp.details?.totalResult; - } - return resp.resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(members => { - this.membersSubject.next(members); - }); - } - - public changeState(newState: ProjectState): void { - if (newState === ProjectState.PROJECT_STATE_ACTIVE) { - const dialogRef = this.dialog.open(WarnDialogComponent, { - data: { - confirmKey: 'ACTIONS.REACTIVATE', - cancelKey: 'ACTIONS.CANCEL', - titleKey: 'PROJECT.PAGES.DIALOG.REACTIVATE.TITLE', - descriptionKey: 'PROJECT.PAGES.DIALOG.REACTIVATE.DESCRIPTION', - }, - width: '400px', - }); - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - this.mgmtService.reactivateProject(this.projectId).then(() => { - this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true); - this.project.state = ProjectState.PROJECT_STATE_ACTIVE; - this.refreshChanges$.emit(); - }).catch(error => { - this.toast.showError(error); - }); - } - }); - - } else if (newState === ProjectState.PROJECT_STATE_INACTIVE) { - const dialogRef = this.dialog.open(WarnDialogComponent, { - data: { - confirmKey: 'ACTIONS.DEACTIVATE', - cancelKey: 'ACTIONS.CANCEL', - titleKey: 'PROJECT.PAGES.DIALOG.DEACTIVATE.TITLE', - descriptionKey: 'PROJECT.PAGES.DIALOG.DEACTIVATE.DESCRIPTION', - }, - width: '400px', - }); - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - this.mgmtService.deactivateProject(this.projectId).then(() => { - this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true); - this.project.state = ProjectState.PROJECT_STATE_INACTIVE; - this.refreshChanges$.emit(); - }).catch(error => { - this.toast.showError(error); - }); - } - }); + public loadMembers(): void { + this.loadingSubject.next(true); + from(this.mgmtService.listProjectMembers(this.projectId, 100, 0)).pipe( + map(resp => { + if (resp.details?.totalResult) { + this.totalMemberResult = resp.details?.totalResult; + } else { + this.totalMemberResult = 0; } - } + return resp.resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(members => { + this.membersSubject.next(members); + }); + } - public deleteProject(): void { - const dialogRef = this.dialog.open(WarnDialogComponent, { - data: { - confirmKey: 'ACTIONS.DELETE', - cancelKey: 'ACTIONS.CANCEL', - titleKey: 'PROJECT.PAGES.DIALOG.DELETE.TITLE', - descriptionKey: 'PROJECT.PAGES.DIALOG.DELETE.DESCRIPTION', - }, - width: '400px', - }); - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - this.mgmtService.removeProject(this.projectId).then(() => { - this.toast.showInfo('PROJECT.TOAST.DELETED', true); - const params: Params = { - 'deferredReload': true, - }; - this.router.navigate(['/projects'], { queryParams: params }); - }).catch(error => { - this.toast.showError(error); - }); - } - }); - } - - public saveProject(): void { - const req = new UpdateProjectRequest(); - req.setId(this.project.id); - req.setName(this.project.name); - req.setProjectRoleAssertion(this.project.projectRoleAssertion); - req.setProjectRoleCheck(this.project.projectRoleCheck); - - this.mgmtService.updateProject(req).then(() => { - this.toast.showInfo('PROJECT.TOAST.UPDATED', true); + public changeState(newState: ProjectState): void { + if (newState === ProjectState.PROJECT_STATE_ACTIVE) { + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.REACTIVATE', + cancelKey: 'ACTIONS.CANCEL', + titleKey: 'PROJECT.PAGES.DIALOG.REACTIVATE.TITLE', + descriptionKey: 'PROJECT.PAGES.DIALOG.REACTIVATE.DESCRIPTION', + }, + width: '400px', + }); + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + this.mgmtService.reactivateProject(this.projectId).then(() => { + this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true); + this.project.state = ProjectState.PROJECT_STATE_ACTIVE; this.refreshChanges$.emit(); - }).catch(error => { + }).catch(error => { this.toast.showError(error); + }); + } + }); + + } else if (newState === ProjectState.PROJECT_STATE_INACTIVE) { + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.DEACTIVATE', + cancelKey: 'ACTIONS.CANCEL', + titleKey: 'PROJECT.PAGES.DIALOG.DEACTIVATE.TITLE', + descriptionKey: 'PROJECT.PAGES.DIALOG.DEACTIVATE.DESCRIPTION', + }, + width: '400px', + }); + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + this.mgmtService.deactivateProject(this.projectId).then(() => { + this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true); + this.project.state = ProjectState.PROJECT_STATE_INACTIVE; + this.refreshChanges$.emit(); + }).catch(error => { + this.toast.showError(error); + }); + } + }); + } + } + + public deleteProject(): void { + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.DELETE', + cancelKey: 'ACTIONS.CANCEL', + titleKey: 'PROJECT.PAGES.DIALOG.DELETE.TITLE', + descriptionKey: 'PROJECT.PAGES.DIALOG.DELETE.DESCRIPTION', + }, + width: '400px', + }); + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + this.mgmtService.removeProject(this.projectId).then(() => { + this.toast.showInfo('PROJECT.TOAST.DELETED', true); + const params: Params = { + 'deferredReload': true, + }; + this.router.navigate(['/projects'], { queryParams: params }); + }).catch(error => { + this.toast.showError(error); }); - } + } + }); + } - public navigateBack(): void { - this._location.back(); - } + public saveProject(): void { + const req = new UpdateProjectRequest(); + req.setId(this.project.id); + req.setName(this.project.name); + req.setProjectRoleAssertion(this.project.projectRoleAssertion); + req.setProjectRoleCheck(this.project.projectRoleCheck); - public updateName(): void { - this.saveProject(); - this.editstate = false; - } + this.mgmtService.updateProject(req).then(() => { + this.toast.showInfo('PROJECT.TOAST.UPDATED', true); + this.refreshChanges$.emit(); + }).catch(error => { + this.toast.showError(error); + }); + } - public openAddMember(): void { - const dialogRef = this.dialog.open(MemberCreateDialogComponent, { - data: { - creationType: CreationType.PROJECT_OWNED, - projectId: this.project.id, - }, - width: '400px', - }); + public navigateBack(): void { + this._location.back(); + } - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - const users: User.AsObject[] = resp.users; - const roles: string[] = resp.roles; + public updateName(): void { + this.saveProject(); + this.editstate = false; + } - if (users && users.length && roles && roles.length) { - users.forEach(user => { - return this.mgmtService.addProjectMember(this.projectId, user.id, roles) - .then(() => { - this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true); - setTimeout(() => { - this.loadMembers(); - }, 1000); - }).catch(error => { - this.toast.showError(error); - }); - }); - } - } - }); - } + public openAddMember(): void { + const dialogRef = this.dialog.open(MemberCreateDialogComponent, { + data: { + creationType: CreationType.PROJECT_OWNED, + projectId: this.project.id, + }, + width: '400px', + }); - public showDetail(): void { - this.router.navigate(['projects', this.project.id, 'members']); - } + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + const users: User.AsObject[] = resp.users; + const roles: string[] = resp.roles; + + if (users && users.length && roles && roles.length) { + users.forEach(user => { + return this.mgmtService.addProjectMember(this.projectId, user.id, roles) + .then(() => { + this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true); + setTimeout(() => { + this.loadMembers(); + }, 1000); + }).catch(error => { + this.toast.showError(error); + }); + }); + } + } + }); + } + + public showDetail(): void { + this.router.navigate(['projects', this.project.id, 'members']); + } } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/project-grants/project-grants-datasource.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/project-grants/project-grants-datasource.ts index bc1daa4391..c742925af4 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/project-grants/project-grants-datasource.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/project-grants/project-grants-datasource.ts @@ -11,53 +11,55 @@ import { ManagementService } from 'src/app/services/mgmt.service'; * (including sorting, pagination, and filtering). */ export class ProjectGrantsDataSource extends DataSource { - public totalResult: number = 0; - public viewTimestamp!: Timestamp.AsObject; - public grantsSubject: BehaviorSubject = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); + public totalResult: number = 0; + public viewTimestamp!: Timestamp.AsObject; + public grantsSubject: BehaviorSubject = new BehaviorSubject([]); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); - constructor(private mgmtService: ManagementService) { - super(); - } + constructor(private mgmtService: ManagementService) { + super(); + } - public loadGrants(projectId: string, pageIndex: number, pageSize: number, sortDirection?: string): void { - const offset = pageIndex * pageSize; + public loadGrants(projectId: string, pageIndex: number, pageSize: number, sortDirection?: string): void { + const offset = pageIndex * pageSize; - this.loadingSubject.next(true); - from(this.mgmtService.listProjectGrants(projectId, pageSize, offset)).pipe( - map(resp => { - if (resp.details?.totalResult) { - this.totalResult = resp.details.totalResult; - } - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details?.viewTimestamp; - } - return resp.resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(grants => { - this.grantsSubject.next(grants); - }); - } + this.loadingSubject.next(true); + from(this.mgmtService.listProjectGrants(projectId, pageSize, offset)).pipe( + map(resp => { + if (resp.details?.totalResult) { + this.totalResult = resp.details.totalResult; + } else { + this.totalResult = 0; + } + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details?.viewTimestamp; + } + return resp.resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(grants => { + this.grantsSubject.next(grants); + }); + } - /** - * Connect this data source to the table. The table will only update when - * the returned stream emits new items. - * @returns A stream of the items to be rendered. - */ - public connect(): Observable { - return this.grantsSubject.asObservable(); - } + /** + * Connect this data source to the table. The table will only update when + * the returned stream emits new items. + * @returns A stream of the items to be rendered. + */ + public connect(): Observable { + return this.grantsSubject.asObservable(); + } - /** - * Called when the table is being destroyed. Use this function, to clean up - * any open connections or free any held resources that were set up during connect. - */ - public disconnect(): void { - this.grantsSubject.complete(); - this.loadingSubject.complete(); - } + /** + * Called when the table is being destroyed. Use this function, to clean up + * any open connections or free any held resources that were set up during connect. + */ + public disconnect(): void { + this.grantsSubject.complete(); + this.loadingSubject.complete(); + } } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts index 9ae20b68be..e2a94ca539 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts @@ -15,173 +15,175 @@ import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; @Component({ - selector: 'app-owned-project-list', - templateUrl: './owned-project-list.component.html', - styleUrls: ['./owned-project-list.component.scss'], - animations: [ - trigger('list', [ - transition(':enter', [ - query('@animate', - stagger(80, animateChild()), - ), - ]), - ]), - trigger('animate', [ - transition(':enter', [ - style({ opacity: 0, transform: 'translateY(-100%)' }), - animate('100ms', style({ opacity: 1, transform: 'translateY(0)' })), - ]), - transition(':leave', [ - style({ opacity: 1, transform: 'translateY(0)' }), - animate('100ms', style({ opacity: 0, transform: 'translateY(100%)' })), - ]), - ]), - ], + selector: 'app-owned-project-list', + templateUrl: './owned-project-list.component.html', + styleUrls: ['./owned-project-list.component.scss'], + animations: [ + trigger('list', [ + transition(':enter', [ + query('@animate', + stagger(80, animateChild()), + ), + ]), + ]), + trigger('animate', [ + transition(':enter', [ + style({ opacity: 0, transform: 'translateY(-100%)' }), + animate('100ms', style({ opacity: 1, transform: 'translateY(0)' })), + ]), + transition(':leave', [ + style({ opacity: 1, transform: 'translateY(0)' }), + animate('100ms', style({ opacity: 0, transform: 'translateY(100%)' })), + ]), + ]), + ], }) export class OwnedProjectListComponent implements OnInit, OnDestroy { - public totalResult: number = 0; - public viewTimestamp!: Timestamp.AsObject; + public totalResult: number = 0; + public viewTimestamp!: Timestamp.AsObject; - public dataSource: MatTableDataSource = - new MatTableDataSource(); + public dataSource: MatTableDataSource = + new MatTableDataSource(); - @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; + @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; - public ownedProjectList: Project.AsObject[] = []; - public displayedColumns: string[] = ['select', 'name', 'state', 'creationDate', 'changeDate', 'actions']; - public selection: SelectionModel = new SelectionModel(true, []); + public ownedProjectList: Project.AsObject[] = []; + public displayedColumns: string[] = ['select', 'name', 'state', 'creationDate', 'changeDate', 'actions']; + public selection: SelectionModel = new SelectionModel(true, []); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); - public grid: boolean = true; - private subscription?: Subscription; + public grid: boolean = true; + private subscription?: Subscription; - public zitadelProjectId: string = ''; + public zitadelProjectId: string = ''; - constructor(private router: Router, - private route: ActivatedRoute, - public translate: TranslateService, - private mgmtService: ManagementService, - private toast: ToastService, - private dialog: MatDialog, - ) { - this.mgmtService.getIAM().then(iam => { - this.zitadelProjectId = iam.iamProjectId; - }); - } + constructor(private router: Router, + private route: ActivatedRoute, + public translate: TranslateService, + private mgmtService: ManagementService, + private toast: ToastService, + private dialog: MatDialog, + ) { + this.mgmtService.getIAM().then(iam => { + this.zitadelProjectId = iam.iamProjectId; + }); + } - public ngOnInit(): void { - this.route.queryParams.pipe(take(1)).subscribe(params => { - this.getData(); - if (params.deferredReload) { - setTimeout(() => { - this.getData(); - }, 2000); - } - }); - } + public ngOnInit(): void { + this.route.queryParams.pipe(take(1)).subscribe(params => { + this.getData(); + if (params.deferredReload) { + setTimeout(() => { + this.getData(); + }, 2000); + } + }); + } - public ngOnDestroy(): void { - this.subscription?.unsubscribe(); - } + public ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } - public isAllSelected(): boolean { - const numSelected = this.selection.selected.length; - const numRows = this.dataSource.data.length; - return numSelected === numRows; - } + public isAllSelected(): boolean { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected === numRows; + } - public masterToggle(): void { - this.isAllSelected() ? - this.selection.clear() : - this.dataSource.data.forEach(row => this.selection.select(row)); - } + public masterToggle(): void { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); + } - public changePage(event: PageEvent): void { - this.getData(event.pageSize, event.pageSize * event.pageIndex); - } + public changePage(event: PageEvent): void { + this.getData(event.pageSize, event.pageSize * event.pageIndex); + } - public addProject(): void { - this.router.navigate(['/projects', 'create']); - } + public addProject(): void { + this.router.navigate(['/projects', 'create']); + } - private async getData(limit?: number, offset?: number): Promise { - this.loadingSubject.next(true); - this.mgmtService.listProjects(limit, offset).then(resp => { - this.ownedProjectList = resp.resultList; - if (resp.details?.totalResult) { - this.totalResult = resp.details.totalResult; - } - if (this.totalResult > 10) { - this.grid = false; - } - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details?.viewTimestamp; - } - this.dataSource.data = this.ownedProjectList; - this.loadingSubject.next(false); + private async getData(limit?: number, offset?: number): Promise { + this.loadingSubject.next(true); + this.mgmtService.listProjects(limit, offset).then(resp => { + this.ownedProjectList = resp.resultList; + if (resp.details?.totalResult) { + this.totalResult = resp.details.totalResult; + } else { + this.totalResult = 0; + } + if (this.totalResult > 10) { + this.grid = false; + } + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details?.viewTimestamp; + } + this.dataSource.data = this.ownedProjectList; + this.loadingSubject.next(false); + }).catch(error => { + console.error(error); + this.toast.showError(error); + this.loadingSubject.next(false); + }); + + this.ownedProjectList = []; + } + + public reactivateSelectedProjects(): void { + const promises = this.selection.selected.map(project => { + this.mgmtService.reactivateProject(project.id); + }); + + Promise.all(promises).then(() => { + this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true); + }).catch(error => { + this.toast.showError(error); + }); + } + + + public deactivateSelectedProjects(): void { + const promises = this.selection.selected.map(project => { + this.mgmtService.deactivateProject(project.id); + }); + + Promise.all(promises).then(() => { + this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true); + }).catch(error => { + this.toast.showError(error); + }); + } + + public refreshPage(): void { + this.selection.clear(); + this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); + } + + public deleteProject(item: Project.AsObject): void { + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.DELETE', + cancelKey: 'ACTIONS.CANCEL', + titleKey: 'PROJECT.PAGES.DIALOG.DELETE.TITLE', + descriptionKey: 'PROJECT.PAGES.DIALOG.DELETE.DESCRIPTION', + }, + width: '400px', + }); + + dialogRef.afterClosed().subscribe(resp => { + if (this.zitadelProjectId && resp && item.id !== this.zitadelProjectId) { + this.mgmtService.removeProject(item.id).then(() => { + this.toast.showInfo('PROJECT.TOAST.DELETED', true); + setTimeout(() => { + this.refreshPage(); + }, 1000); }).catch(error => { - console.error(error); - this.toast.showError(error); - this.loadingSubject.next(false); + this.toast.showError(error); }); - - this.ownedProjectList = []; - } - - public reactivateSelectedProjects(): void { - const promises = this.selection.selected.map(project => { - this.mgmtService.reactivateProject(project.id); - }); - - Promise.all(promises).then(() => { - this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true); - }).catch(error => { - this.toast.showError(error); - }); - } - - - public deactivateSelectedProjects(): void { - const promises = this.selection.selected.map(project => { - this.mgmtService.deactivateProject(project.id); - }); - - Promise.all(promises).then(() => { - this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true); - }).catch(error => { - this.toast.showError(error); - }); - } - - public refreshPage(): void { - this.selection.clear(); - this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); - } - - public deleteProject(item: Project.AsObject): void { - const dialogRef = this.dialog.open(WarnDialogComponent, { - data: { - confirmKey: 'ACTIONS.DELETE', - cancelKey: 'ACTIONS.CANCEL', - titleKey: 'PROJECT.PAGES.DIALOG.DELETE.TITLE', - descriptionKey: 'PROJECT.PAGES.DIALOG.DELETE.DESCRIPTION', - }, - width: '400px', - }); - - dialogRef.afterClosed().subscribe(resp => { - if (this.zitadelProjectId && resp && item.id !== this.zitadelProjectId) { - this.mgmtService.removeProject(item.id).then(() => { - this.toast.showInfo('PROJECT.TOAST.DELETED', true); - setTimeout(() => { - this.refreshPage(); - }, 1000); - }).catch(error => { - this.toast.showError(error); - }); - } - }); - } + } + }); + } } 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 9e395451cf..478f529074 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 @@ -5,7 +5,7 @@
- {{ 'USER.MACHINE.USERNAME' | translate }} + {{ 'USER.MACHINE.USERNAME' | translate }}* {{ 'USER.VALIDATION.REQUIRED' | translate }} @@ -15,7 +15,7 @@ - {{ 'USER.MACHINE.NAME' | translate }} + {{ 'USER.MACHINE.NAME' | translate }}* {{ 'USER.VALIDATION.REQUIRED' | translate }} diff --git a/console/src/app/pages/users/user-create/user-create.component.html b/console/src/app/pages/users/user-create/user-create.component.html index 2995272735..bd5f622180 100644 --- a/console/src/app/pages/users/user-create/user-create.component.html +++ b/console/src/app/pages/users/user-create/user-create.component.html @@ -5,7 +5,7 @@

{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}

- + {{ 'USER.PROFILE.EMAIL' | translate }}* @@ -15,7 +15,7 @@ {{ 'USER.VALIDATION.REQUIRED' | translate }} - + {{ 'USER.PROFILE.USERNAME' | translate }}* @@ -30,21 +30,21 @@
- + {{ 'USER.PROFILE.FIRSTNAME' | translate }}* {{ 'USER.VALIDATION.REQUIRED' | translate }} - + {{ 'USER.PROFILE.LASTNAME' | translate }}* {{ 'USER.VALIDATION.REQUIRED' | translate }} - + {{ 'USER.PROFILE.NICKNAME' | translate }} @@ -54,7 +54,7 @@

{{ 'USER.CREATE.GENDERLANGSECTION' | translate }}

- + {{ 'USER.PROFILE.GENDER' | translate }} @@ -65,7 +65,7 @@ {{ 'USER.VALIDATION.REQUIRED' | translate }}
- + {{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }} @@ -79,7 +79,7 @@

{{ 'USER.CREATE.ADDRESSANDPHONESECTION' | translate }}

- + {{ 'USER.PROFILE.PHONE' | translate }} diff --git a/console/src/app/pages/users/user-detail/external-idps/external-idps.component.ts b/console/src/app/pages/users/user-detail/external-idps/external-idps.component.ts index 2168283717..00fd21ce43 100644 --- a/console/src/app/pages/users/user-detail/external-idps/external-idps.component.ts +++ b/console/src/app/pages/users/user-detail/external-idps/external-idps.component.ts @@ -13,109 +13,111 @@ import { ManagementService } from '../../../../services/mgmt.service'; import { ToastService } from '../../../../services/toast.service'; @Component({ - selector: 'app-external-idps', - templateUrl: './external-idps.component.html', - styleUrls: ['./external-idps.component.scss'], + selector: 'app-external-idps', + templateUrl: './external-idps.component.html', + styleUrls: ['./external-idps.component.scss'], }) export class ExternalIdpsComponent implements OnInit { - @Input() service!: GrpcAuthService | ManagementService; - @Input() userId!: string; - @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; - public totalResult: number = 0; - public viewTimestamp!: Timestamp.AsObject; - public dataSource: MatTableDataSource - = new MatTableDataSource(); - public selection: SelectionModel - = new SelectionModel(true, []); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); - @Input() public displayedColumns: string[] = ['idpConfigId', 'idpName', 'externalUserId', 'externalUserDisplayName', 'actions']; + @Input() service!: GrpcAuthService | ManagementService; + @Input() userId!: string; + @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; + public totalResult: number = 0; + public viewTimestamp!: Timestamp.AsObject; + public dataSource: MatTableDataSource + = new MatTableDataSource(); + public selection: SelectionModel + = new SelectionModel(true, []); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); + @Input() public displayedColumns: string[] = ['idpConfigId', 'idpName', 'externalUserId', 'externalUserDisplayName', 'actions']; - constructor(private toast: ToastService, private dialog: MatDialog) { } + constructor(private toast: ToastService, private dialog: MatDialog) { } - ngOnInit(): void { - this.getData(10, 0); + ngOnInit(): void { + this.getData(10, 0); + } + + public isAllSelected(): boolean { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected === numRows; + } + + public masterToggle(): void { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); + } + + public changePage(event: PageEvent): void { + this.getData(event.pageSize, event.pageIndex * event.pageSize); + } + + private async getData(limit: number, offset: number): Promise { + this.loadingSubject.next(true); + + let promise; + if (this.service instanceof ManagementService) { + promise = (this.service as ManagementService).listHumanLinkedIDPs(this.userId, limit, offset); + } else if (this.service instanceof GrpcAuthService) { + promise = (this.service as GrpcAuthService).listMyLinkedIDPs(limit, offset); } - public isAllSelected(): boolean { - const numSelected = this.selection.selected.length; - const numRows = this.dataSource.data.length; - return numSelected === numRows; + if (promise) { + promise.then(resp => { + this.dataSource.data = resp.resultList; + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details.viewTimestamp; + } + if (resp.details?.totalResult) { + this.totalResult = resp.details?.totalResult; + } else { + this.totalResult = 0; + } + this.loadingSubject.next(false); + }).catch((error: any) => { + this.toast.showError(error); + this.loadingSubject.next(false); + }); } + } - public masterToggle(): void { - this.isAllSelected() ? - this.selection.clear() : - this.dataSource.data.forEach(row => this.selection.select(row)); - } + public refreshPage(): void { + this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); + } - public changePage(event: PageEvent): void { - this.getData(event.pageSize, event.pageIndex * event.pageSize); - } - - private async getData(limit: number, offset: number): Promise { - this.loadingSubject.next(true); + public removeExternalIdp(idp: IDPUserLink.AsObject): void { + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.REMOVE', + cancelKey: 'ACTIONS.CANCEL', + titleKey: 'USER.EXTERNALIDP.DIALOG.DELETE_TITLE', + descriptionKey: 'USER.EXTERNALIDP.DIALOG.DELETE_DESCRIPTION', + }, + width: '400px', + }); + dialogRef.afterClosed().subscribe(resp => { + if (resp) { let promise; if (this.service instanceof ManagementService) { - promise = (this.service as ManagementService).listHumanLinkedIDPs(this.userId, limit, offset); + promise = (this.service as ManagementService) + .removeHumanLinkedIDP(idp.providedUserId, idp.idpId, idp.userId); } else if (this.service instanceof GrpcAuthService) { - promise = (this.service as GrpcAuthService).listMyLinkedIDPs(limit, offset); + promise = (this.service as GrpcAuthService) + .removeMyLinkedIDP(idp.providedUserId, idp.idpId); } if (promise) { - promise.then(resp => { - this.dataSource.data = resp.resultList; - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details.viewTimestamp; - } - if (resp.details?.totalResult) { - this.totalResult = resp.details?.totalResult; - } - this.loadingSubject.next(false); - }).catch((error: any) => { - this.toast.showError(error); - this.loadingSubject.next(false); - }); + promise.then(_ => { + setTimeout(() => { + this.refreshPage(); + }, 1000); + }).catch((error: any) => { + this.toast.showError(error); + }); } - } - - public refreshPage(): void { - this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); - } - - public removeExternalIdp(idp: IDPUserLink.AsObject): void { - const dialogRef = this.dialog.open(WarnDialogComponent, { - data: { - confirmKey: 'ACTIONS.REMOVE', - cancelKey: 'ACTIONS.CANCEL', - titleKey: 'USER.EXTERNALIDP.DIALOG.DELETE_TITLE', - descriptionKey: 'USER.EXTERNALIDP.DIALOG.DELETE_DESCRIPTION', - }, - width: '400px', - }); - - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - let promise; - if (this.service instanceof ManagementService) { - promise = (this.service as ManagementService) - .removeHumanLinkedIDP(idp.providedUserId, idp.idpId, idp.userId); - } else if (this.service instanceof GrpcAuthService) { - promise = (this.service as GrpcAuthService) - .removeMyLinkedIDP(idp.providedUserId, idp.idpId); - } - - if (promise) { - promise.then(_ => { - setTimeout(() => { - this.refreshPage(); - }, 1000); - }).catch((error: any) => { - this.toast.showError(error); - }); - } - } - }); - } + } + }); + } } diff --git a/console/src/app/pages/users/user-detail/memberships/memberships.component.ts b/console/src/app/pages/users/user-detail/memberships/memberships.component.ts index 38e0df3aa2..9fd0aac250 100644 --- a/console/src/app/pages/users/user-detail/memberships/memberships.component.ts +++ b/console/src/app/pages/users/user-detail/memberships/memberships.component.ts @@ -63,6 +63,7 @@ export class MembershipsComponent implements OnInit { } else { this.mgmtService.listUserMemberships(userId, 100, 0, []).then(resp => { this.memberships = resp.resultList; + this.totalResult = resp.details?.totalResult || 0; this.loading = false; }); } 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 f1f203ce8f..57ff95fab2 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 @@ -19,7 +19,7 @@ (click)="changeState(UserState.USER_STATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' | translate}}
diff --git a/console/src/app/pages/users/user-list/user-table/user-table.component.ts b/console/src/app/pages/users/user-list/user-table/user-table.component.ts index 4eb9050a26..6e3d9dd5e5 100644 --- a/console/src/app/pages/users/user-list/user-table/user-table.component.ts +++ b/console/src/app/pages/users/user-list/user-table/user-table.component.ts @@ -12,242 +12,244 @@ import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.com import { Timestamp } from 'src/app/proto/generated/google/protobuf/timestamp_pb'; import { TextQueryMethod } from 'src/app/proto/generated/zitadel/object_pb'; import { - DisplayNameQuery, - EmailQuery, - FirstNameQuery, - LastNameQuery, - SearchQuery, - Type, - TypeQuery, - User, - UserNameQuery, - UserState, + DisplayNameQuery, + EmailQuery, + FirstNameQuery, + LastNameQuery, + SearchQuery, + Type, + TypeQuery, + User, + UserNameQuery, + UserState, } from 'src/app/proto/generated/zitadel/user_pb'; import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; enum UserListSearchKey { - FIRST_NAME, - LAST_NAME, - DISPLAY_NAME, - USER_NAME, - EMAIL, + FIRST_NAME, + LAST_NAME, + DISPLAY_NAME, + USER_NAME, + EMAIL, } @Component({ - selector: 'app-user-table', - templateUrl: './user-table.component.html', - styleUrls: ['./user-table.component.scss'], - animations: [ - enterAnimations, - ], + selector: 'app-user-table', + templateUrl: './user-table.component.html', + styleUrls: ['./user-table.component.scss'], + animations: [ + enterAnimations, + ], }) export class UserTableComponent implements OnInit { - public userSearchKey: UserListSearchKey | undefined = undefined; - public Type: any = Type; - @Input() type: Type = Type.TYPE_HUMAN; - @Input() refreshOnPreviousRoutes: string[] = []; - @Input() disabled: boolean = false; - @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; - @ViewChild('input') public filter!: Input; + public userSearchKey: UserListSearchKey | undefined = undefined; + public Type: any = Type; + @Input() type: Type = Type.TYPE_HUMAN; + @Input() refreshOnPreviousRoutes: string[] = []; + @Input() disabled: boolean = false; + @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; + @ViewChild('input') public filter!: Input; - public viewTimestamp!: Timestamp.AsObject; - public totalResult: number = 0; - public dataSource: MatTableDataSource = new MatTableDataSource(); - public selection: SelectionModel = new SelectionModel(true, []); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); - public loading$: Observable = this.loadingSubject.asObservable(); - @Input() public displayedColumns: string[] = ['select', 'displayName', 'username', 'email', 'state', 'actions']; + public viewTimestamp!: Timestamp.AsObject; + public totalResult: number = 0; + public dataSource: MatTableDataSource = new MatTableDataSource(); + public selection: SelectionModel = new SelectionModel(true, []); + private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + public loading$: Observable = this.loadingSubject.asObservable(); + @Input() public displayedColumns: string[] = ['select', 'displayName', 'username', 'email', 'state', 'actions']; - @Output() public changedSelection: EventEmitter> = new EventEmitter(); + @Output() public changedSelection: EventEmitter> = new EventEmitter(); - public UserState: any = UserState; - public UserListSearchKey: any = UserListSearchKey; + public UserState: any = UserState; + public UserListSearchKey: any = UserListSearchKey; - constructor( - public translate: TranslateService, - private userService: ManagementService, - private toast: ToastService, - private dialog: MatDialog, - private route: ActivatedRoute, - ) { - this.selection.changed.subscribe(() => { - this.changedSelection.emit(this.selection.selected); - }); - } + constructor( + public translate: TranslateService, + private userService: ManagementService, + private toast: ToastService, + private dialog: MatDialog, + private route: ActivatedRoute, + ) { + this.selection.changed.subscribe(() => { + this.changedSelection.emit(this.selection.selected); + }); + } - ngOnInit(): void { - this.route.queryParams.pipe(take(1)).subscribe(params => { - this.getData(10, 0, this.type); - if (params.deferredReload) { - setTimeout(() => { - this.getData(10, 0, this.type); - }, 2000); - } - }); - } - - public isAllSelected(): boolean { - const numSelected = this.selection.selected.length; - const numRows = this.dataSource.data.length; - return numSelected === numRows; - } - - public masterToggle(): void { - this.isAllSelected() ? - this.selection.clear() : - this.dataSource.data.forEach(row => this.selection.select(row)); - } - - - public changePage(event: PageEvent): void { - this.selection.clear(); - this.getData(event.pageSize, event.pageIndex * event.pageSize, this.type); - } - - public deactivateSelectedUsers(): void { - Promise.all(this.selection.selected.map(value => { - return this.userService.deactivateUser(value.id); - })).then(() => { - this.toast.showInfo('USER.TOAST.SELECTEDDEACTIVATED', true); - this.selection.clear(); - setTimeout(() => { - this.refreshPage(); - }, 1000); - }).catch(error => { - this.toast.showError(error); - }); - } - - public reactivateSelectedUsers(): void { - Promise.all(this.selection.selected.map(value => { - return this.userService.reactivateUser(value.id); - })).then(() => { - this.toast.showInfo('USER.TOAST.SELECTEDREACTIVATED', true); - this.selection.clear(); - setTimeout(() => { - this.refreshPage(); - }, 1000); - }).catch(error => { - this.toast.showError(error); - }); - } - - private async getData(limit: number, offset: number, type: Type, searchValue?: string): Promise { - this.loadingSubject.next(true); - const query = new SearchQuery(); - const typeQuery = new TypeQuery(); - typeQuery.setType(type); - query.setTypeQuery(typeQuery); - - if (searchValue && this.userSearchKey !== undefined) { - switch (this.userSearchKey) { - case UserListSearchKey.DISPLAY_NAME: - const dNQuery = new DisplayNameQuery(); - dNQuery.setDisplayName(searchValue); - dNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); - - query.setDisplayNameQuery(dNQuery); - break; - case UserListSearchKey.USER_NAME: - const uNQuery = new UserNameQuery(); - uNQuery.setUserName(searchValue); - uNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); - - query.setUserNameQuery(uNQuery); - break; - case UserListSearchKey.FIRST_NAME: - const fNQuery = new FirstNameQuery(); - fNQuery.setFirstName(searchValue); - fNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); - - query.setFirstNameQuery(fNQuery); - break; - case UserListSearchKey.FIRST_NAME: - const lNQuery = new LastNameQuery(); - lNQuery.setLastName(searchValue); - lNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); - - query.setLastNameQuery(lNQuery); - break; - case UserListSearchKey.EMAIL: - const eQuery = new EmailQuery(); - eQuery.setEmailAddress(searchValue); - eQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); - - query.setEmailQuery(eQuery); - break; - } - } - - this.userService.listUsers(limit, offset, [query]).then(resp => { - if (resp.details?.totalResult) { - this.totalResult = resp.details?.totalResult; - } - if (resp.details?.viewTimestamp) { - this.viewTimestamp = resp.details?.viewTimestamp; - } - this.dataSource.data = resp.resultList; - this.loadingSubject.next(false); - }).catch(error => { - this.toast.showError(error); - this.loadingSubject.next(false); - }); - } - - public refreshPage(): void { - this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize, this.type); - } - - public applyFilter(event: Event): void { - this.selection.clear(); - const filterValue = (event.target as HTMLInputElement).value; - - this.getData( - this.paginator.pageSize, - this.paginator.pageIndex * this.paginator.pageSize, - this.type, - filterValue, - ); - } - - public setFilter(key: UserListSearchKey): void { + ngOnInit(): void { + this.route.queryParams.pipe(take(1)).subscribe(params => { + this.getData(10, 0, this.type); + if (params.deferredReload) { setTimeout(() => { - if (this.filter) { - (this.filter as any).nativeElement.focus(); - } - }, 100); + this.getData(10, 0, this.type); + }, 2000); + } + }); + } - if (this.userSearchKey !== key) { - this.userSearchKey = key; - } else { - this.userSearchKey = undefined; + public isAllSelected(): boolean { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected === numRows; + } + + public masterToggle(): void { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); + } + + + public changePage(event: PageEvent): void { + this.selection.clear(); + this.getData(event.pageSize, event.pageIndex * event.pageSize, this.type); + } + + public deactivateSelectedUsers(): void { + Promise.all(this.selection.selected.map(value => { + return this.userService.deactivateUser(value.id); + })).then(() => { + this.toast.showInfo('USER.TOAST.SELECTEDDEACTIVATED', true); + this.selection.clear(); + setTimeout(() => { + this.refreshPage(); + }, 1000); + }).catch(error => { + this.toast.showError(error); + }); + } + + public reactivateSelectedUsers(): void { + Promise.all(this.selection.selected.map(value => { + return this.userService.reactivateUser(value.id); + })).then(() => { + this.toast.showInfo('USER.TOAST.SELECTEDREACTIVATED', true); + this.selection.clear(); + setTimeout(() => { + this.refreshPage(); + }, 1000); + }).catch(error => { + this.toast.showError(error); + }); + } + + private async getData(limit: number, offset: number, type: Type, searchValue?: string): Promise { + this.loadingSubject.next(true); + const query = new SearchQuery(); + const typeQuery = new TypeQuery(); + typeQuery.setType(type); + query.setTypeQuery(typeQuery); + + if (searchValue && this.userSearchKey !== undefined) { + switch (this.userSearchKey) { + case UserListSearchKey.DISPLAY_NAME: + const dNQuery = new DisplayNameQuery(); + dNQuery.setDisplayName(searchValue); + dNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + + query.setDisplayNameQuery(dNQuery); + break; + case UserListSearchKey.USER_NAME: + const uNQuery = new UserNameQuery(); + uNQuery.setUserName(searchValue); + uNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + + query.setUserNameQuery(uNQuery); + break; + case UserListSearchKey.FIRST_NAME: + const fNQuery = new FirstNameQuery(); + fNQuery.setFirstName(searchValue); + fNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + + query.setFirstNameQuery(fNQuery); + break; + case UserListSearchKey.FIRST_NAME: + const lNQuery = new LastNameQuery(); + lNQuery.setLastName(searchValue); + lNQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + + query.setLastNameQuery(lNQuery); + break; + case UserListSearchKey.EMAIL: + const eQuery = new EmailQuery(); + eQuery.setEmailAddress(searchValue); + eQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + + query.setEmailQuery(eQuery); + break; + } + } + + this.userService.listUsers(limit, offset, [query]).then(resp => { + if (resp.details?.totalResult) { + this.totalResult = resp.details?.totalResult; + } else { + this.totalResult = 0; + } + if (resp.details?.viewTimestamp) { + this.viewTimestamp = resp.details?.viewTimestamp; + } + this.dataSource.data = resp.resultList; + this.loadingSubject.next(false); + }).catch(error => { + this.toast.showError(error); + this.loadingSubject.next(false); + }); + } + + public refreshPage(): void { + this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize, this.type); + } + + public applyFilter(event: Event): void { + this.selection.clear(); + const filterValue = (event.target as HTMLInputElement).value; + + this.getData( + this.paginator.pageSize, + this.paginator.pageIndex * this.paginator.pageSize, + this.type, + filterValue, + ); + } + + public setFilter(key: UserListSearchKey): void { + setTimeout(() => { + if (this.filter) { + (this.filter as any).nativeElement.focus(); + } + }, 100); + + if (this.userSearchKey !== key) { + this.userSearchKey = key; + } else { + this.userSearchKey = undefined; + this.refreshPage(); + } + } + + public deleteUser(user: User.AsObject): void { + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.DELETE', + cancelKey: 'ACTIONS.CANCEL', + titleKey: 'USER.DIALOG.DELETE_TITLE', + descriptionKey: 'USER.DIALOG.DELETE_DESCRIPTION', + }, + width: '400px', + }); + + dialogRef.afterClosed().subscribe(resp => { + if (resp) { + this.userService.removeUser(user.id).then(() => { + setTimeout(() => { this.refreshPage(); - } - } - - public deleteUser(user: User.AsObject): void { - const dialogRef = this.dialog.open(WarnDialogComponent, { - data: { - confirmKey: 'ACTIONS.DELETE', - cancelKey: 'ACTIONS.CANCEL', - titleKey: 'USER.DIALOG.DELETE_TITLE', - descriptionKey: 'USER.DIALOG.DELETE_DESCRIPTION', - }, - width: '400px', + }, 1000); + this.toast.showInfo('USER.TOAST.DELETED', true); + }).catch(error => { + this.toast.showError(error); }); - - dialogRef.afterClosed().subscribe(resp => { - if (resp) { - this.userService.removeUser(user.id).then(() => { - setTimeout(() => { - this.refreshPage(); - }, 1000); - this.toast.showInfo('USER.TOAST.DELETED', true); - }).catch(error => { - this.toast.showError(error); - }); - } - }); - } + } + }); + } } diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 12cae3027c..4eea6218e6 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -1078,6 +1078,7 @@ "TITLE": "OIDC-Konfiguration", "CLIENTID": "Client ID", "CLIENTSECRET": "Client Secret", + "CLIENTSECRET_NOSECRET":"Bei ihrem gewählten Authentication Flow wird kein Secret benötigt und steht daher nicht zur Verfügung.", "CLIENTSECRET_DESCRIPTION": "Verwahre das Client Secret an einem sicheren Ort, da es nicht mehr angezeigt werden kann, sobald der Dialog geschlossen wird.", "REGENERATESECRET": "Client Secret neu generieren", "DEVMODE": "Entwicklermodus", diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index f64d9b83cb..66ec885c6c 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -1079,6 +1079,7 @@ "TITLE": "OIDC Configuration", "CLIENTID": "Client ID", "CLIENTSECRET": "Client Secret", + "CLIENTSECRET_NOSECRET":"With your chosen authentication flow, no secret is required and is therefore not available.", "CLIENTSECRET_DESCRIPTION": "Keep your client secret at a safe place as it will disappear once the dialog is closed.", "REGENERATESECRET": "Regenerate Client Secret", "DEVMODE": "Development Mode",