mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-13 17:02:11 +00:00
fix(console): dependencies, list my memberships, passwordless texts, privatelabelling issues (#2142)
* fix: list my memberships in console * show manager context in detail page * console dependencies (#2161) * feat: User metadata (#2025) * feat: user meta data events * feat: user meta data set tests * feat: user meta data tests * feat: user meta data in protos * feat: user meta data command api * feat: user meta data query side * feat: proto correct order, fix handlers * feat: proto correct order * feat: fixes of pr comments * feat: fixes of pr comments * feat: value as byte array * feat: metadata feature * Update internal/auth/repository/eventsourcing/handler/meta_data.go Co-authored-by: Silvan <silvan.reusser@gmail.com> * Update internal/command/user_meta_data.go Co-authored-by: Silvan <silvan.reusser@gmail.com> * Update proto/zitadel/metadata.proto Co-authored-by: Silvan <silvan.reusser@gmail.com> * Update proto/zitadel/metadata.proto Co-authored-by: Silvan <silvan.reusser@gmail.com> * fix: rename metadata files and table * fix: rename meta data to metadat in protos * Update internal/domain/metadata.go Co-authored-by: Silvan <silvan.reusser@gmail.com> * fix: rename vars * fix: rebiuld docs * Update internal/iam/repository/view/metadata_view.go Co-authored-by: Silvan <silvan.reusser@gmail.com> Co-authored-by: Silvan <silvan.reusser@gmail.com> * fix(auth): read privacy policy from eventstore if not found (#2125) * fix(auth): read privacy policy from eventstore if not found * Update internal/auth/repository/eventsourcing/eventstore/auth_request.go Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * chore(deps-dev): bump @angular/cli from 12.1.1 to 12.2.0 in /console (#2149) Bumps [@angular/cli](https://github.com/angular/angular-cli) from 12.1.1 to 12.2.0. - [Release notes](https://github.com/angular/angular-cli/releases) - [Changelog](https://github.com/angular/angular-cli/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular-cli/compare/v12.1.1...12.2.0) --- updated-dependencies: - dependency-name: "@angular/cli" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @angular/material-moment-adapter in /console (#2147) Bumps [@angular/material-moment-adapter](https://github.com/angular/components) from 12.1.1 to 12.2.0. - [Release notes](https://github.com/angular/components/releases) - [Changelog](https://github.com/angular/components/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/components/compare/12.1.1...12.2.0) --- updated-dependencies: - dependency-name: "@angular/material-moment-adapter" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump ts-node from 9.1.1 to 10.2.0 in /console (#2145) Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 9.1.1 to 10.2.0. - [Release notes](https://github.com/TypeStrong/ts-node/releases) - [Commits](https://github.com/TypeStrong/ts-node/compare/v9.1.1...v10.2.0) --- updated-dependencies: - dependency-name: ts-node dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/jasmine from 3.7.7 to 3.8.2 in /console (#2115) Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.7.7 to 3.8.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine) --- updated-dependencies: - dependency-name: "@types/jasmine" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump libphonenumber-js from 1.9.19 to 1.9.23 in /console (#2114) Bumps [libphonenumber-js](https://gitlab.com/catamphetamine/libphonenumber-js) from 1.9.19 to 1.9.23. - [Release notes](https://gitlab.com/catamphetamine/libphonenumber-js/tags) - [Changelog](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/CHANGELOG.md) - [Commits](https://gitlab.com/catamphetamine/libphonenumber-js/compare/v1.9.19...v1.9.23) --- updated-dependencies: - dependency-name: libphonenumber-js dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @angular/core and @angular/animations in /console (#2072) Bumps [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) and [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations). These dependencies needed to be updated together. Updates `@angular/core` from 12.0.3 to 12.1.3 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/12.1.3/packages/core) Updates `@angular/animations` from 12.0.3 to 12.1.3 - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/12.1.3/packages/animations) --- updated-dependencies: - dependency-name: "@angular/core" dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: "@angular/animations" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump stylelint-config-standard in /console (#2065) Bumps [stylelint-config-standard](https://github.com/stylelint/stylelint-config-standard) from 20.0.0 to 22.0.0. - [Release notes](https://github.com/stylelint/stylelint-config-standard/releases) - [Changelog](https://github.com/stylelint/stylelint-config-standard/blob/master/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint-config-standard/compare/20.0.0...22.0.0) --- updated-dependencies: - dependency-name: stylelint-config-standard dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @types/google-protobuf in /console (#2000) Bumps [@types/google-protobuf](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/google-protobuf) from 3.15.2 to 3.15.3. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/google-protobuf) --- updated-dependencies: - dependency-name: "@types/google-protobuf" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * package * angular core * update angular core, cdk, allow commonjs deps Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> Co-authored-by: Silvan <silvan.reusser@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix labelpolicy max size, double trigger, labels * lint styles * disable rule, add passwordless message texts * lint exceeding linelimit * login texts * remove duplicate keyname * rm unused * fix: read lockout policy Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> Co-authored-by: Silvan <silvan.reusser@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -3,55 +3,75 @@ import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { catchError, finalize, map } from 'rxjs/operators';
|
||||
import { Membership } from 'src/app/proto/generated/zitadel/user_pb';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
|
||||
export class MembershipDetailDataSource extends DataSource<Membership.AsObject> {
|
||||
public totalResult: number = 0;
|
||||
public viewTimestamp!: Timestamp.AsObject;
|
||||
public membersSubject: BehaviorSubject<Membership.AsObject[]>
|
||||
= new BehaviorSubject<Membership.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public totalResult: number = 0;
|
||||
public viewTimestamp!: Timestamp.AsObject;
|
||||
public membersSubject: BehaviorSubject<Membership.AsObject[]>
|
||||
= new BehaviorSubject<Membership.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
|
||||
constructor(private mgmtUserService: ManagementService) {
|
||||
super();
|
||||
}
|
||||
constructor(private mgmtUserService: ManagementService, private authServce: GrpcAuthService) {
|
||||
super();
|
||||
}
|
||||
|
||||
public loadMemberships(userId: string, pageIndex: number, pageSize: number): void {
|
||||
const offset = pageIndex * pageSize;
|
||||
public loadMemberships(userId: string, pageIndex: number, pageSize: number): void {
|
||||
const offset = pageIndex * pageSize;
|
||||
|
||||
this.loadingSubject.next(true);
|
||||
from(this.mgmtUserService.listUserMemberships(userId, pageSize, offset)).pipe(
|
||||
map(resp => {
|
||||
this.totalResult = resp.details?.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);
|
||||
});
|
||||
}
|
||||
this.loadingSubject.next(true);
|
||||
from(this.mgmtUserService.listUserMemberships(userId, pageSize, offset)).pipe(
|
||||
map(resp => {
|
||||
this.totalResult = resp.details?.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);
|
||||
});
|
||||
}
|
||||
|
||||
public loadMyMemberships(pageIndex: number, pageSize: number): void {
|
||||
const offset = pageIndex * pageSize;
|
||||
|
||||
this.loadingSubject.next(true);
|
||||
from(this.authServce.listMyMemberships(pageSize, offset)).pipe(
|
||||
map(resp => {
|
||||
this.totalResult = resp.details?.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<Membership.AsObject[]> {
|
||||
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<Membership.AsObject[]> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<app-detail-layout [backRouterLink]="[ '/users', user?.id]"
|
||||
title="{{user?.human?.displayName}} {{ 'USER.MEMBERSHIPS.TITLE' | translate }}"
|
||||
description="{{ 'USER.MEMBERSHIPS.DESCRIPTION' | translate }}">
|
||||
<cnsl-info-section class="context-wrapper">
|
||||
<span *ngIf="isMe">{{'USER.MEMBERSHIPS.USERCONTEXT' | translate}}</span>
|
||||
<span *ngIf="!isMe">{{'USER.MEMBERSHIPS.ORGCONTEXT' | translate}}</span>
|
||||
</cnsl-info-section>
|
||||
|
||||
<app-refresh-table class="refresh-table" (refreshed)="refreshPage()" [dataSize]="dataSource?.totalResult"
|
||||
[timestamp]="dataSource?.viewTimestamp" [selection]="selection" [loading]="dataSource?.loading$ | async">
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
.context-wrapper {
|
||||
margin-bottom: 1rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.refresh-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -3,233 +3,257 @@ import { AfterViewInit, Component, ViewChild } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatTable } from '@angular/material/table';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { map, switchMap, tap } from 'rxjs/operators';
|
||||
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
|
||||
import { PaginatorComponent } from 'src/app/modules/paginator/paginator.component';
|
||||
import { Membership, User } from 'src/app/proto/generated/zitadel/user_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { MembershipDetailDataSource } from './membership-detail-datasource';
|
||||
|
||||
@Component({
|
||||
selector: 'app-membership-detail',
|
||||
templateUrl: './membership-detail.component.html',
|
||||
styleUrls: ['./membership-detail.component.scss'],
|
||||
selector: 'app-membership-detail',
|
||||
templateUrl: './membership-detail.component.html',
|
||||
styleUrls: ['./membership-detail.component.scss'],
|
||||
})
|
||||
export class MembershipDetailComponent implements AfterViewInit {
|
||||
public user!: User.AsObject;
|
||||
public user!: User.AsObject;
|
||||
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table!: MatTable<Membership.AsObject>;
|
||||
public dataSource!: MembershipDetailDataSource;
|
||||
public selection: SelectionModel<Membership.AsObject>
|
||||
= new SelectionModel<Membership.AsObject>(true, []);
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table!: MatTable<Membership.AsObject>;
|
||||
public dataSource!: MembershipDetailDataSource;
|
||||
public selection: SelectionModel<Membership.AsObject>
|
||||
= new SelectionModel<Membership.AsObject>(true, []);
|
||||
|
||||
public memberRoleOptions: string[] = [];
|
||||
public memberRoleOptions: string[] = [];
|
||||
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
public displayedColumns: string[] = ['select', 'memberType', 'displayName', 'creationDate', 'changeDate', 'roles', 'actions'];
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
public displayedColumns: string[] = ['select', 'memberType', 'displayName', 'creationDate', 'changeDate', 'roles', 'actions'];
|
||||
|
||||
public loading: boolean = false;
|
||||
public memberships!: Membership.AsObject[];
|
||||
public loading: boolean = false;
|
||||
public memberships!: Membership.AsObject[];
|
||||
|
||||
constructor(
|
||||
activatedRoute: ActivatedRoute,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
private mgmtService: ManagementService,
|
||||
private adminService: AdminService,
|
||||
) {
|
||||
activatedRoute.params.subscribe(data => {
|
||||
const { id } = data;
|
||||
if (id) {
|
||||
this.mgmtService.getUserByID(id).then(resp => {
|
||||
if (resp.user) {
|
||||
this.user = resp.user;
|
||||
this.dataSource = new MembershipDetailDataSource(this.mgmtService);
|
||||
this.dataSource.loadMemberships(
|
||||
this.user.id,
|
||||
0,
|
||||
50,
|
||||
);
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
public isMe: boolean = false;
|
||||
|
||||
public ngAfterViewInit(): void {
|
||||
this.paginator.page
|
||||
.pipe(
|
||||
tap(() => this.loadMembershipsPage()),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
constructor(
|
||||
authService: GrpcAuthService,
|
||||
activatedRoute: ActivatedRoute,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
private mgmtService: ManagementService,
|
||||
private adminService: AdminService,
|
||||
) {
|
||||
activatedRoute.params
|
||||
.pipe(switchMap(({ id }) => {
|
||||
return authService.user.pipe(
|
||||
map(user => user?.id === id),
|
||||
tap((isMe) => {
|
||||
this.isMe = isMe;
|
||||
|
||||
private loadMembershipsPage(): void {
|
||||
this.dataSource.loadMemberships(
|
||||
this.user.id,
|
||||
this.paginator.pageIndex,
|
||||
this.paginator.pageSize,
|
||||
);
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.membersSubject.value.length;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.membersSubject.value.forEach(row => this.selection.select(row));
|
||||
}
|
||||
|
||||
public addMember(): void {
|
||||
const dialogRef = this.dialog.open(MemberCreateDialogComponent, {
|
||||
width: '400px',
|
||||
data: {
|
||||
user: this.user,
|
||||
},
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp && resp.creationType !== undefined) {
|
||||
switch (resp.creationType) {
|
||||
case CreationType.IAM:
|
||||
this.createIamMember(resp);
|
||||
break;
|
||||
case CreationType.ORG:
|
||||
this.createOrgMember(resp);
|
||||
break;
|
||||
case CreationType.PROJECT_OWNED:
|
||||
this.createOwnedProjectMember(resp);
|
||||
break;
|
||||
case CreationType.PROJECT_GRANTED:
|
||||
this.createGrantedProjectMember(resp);
|
||||
break;
|
||||
if (isMe) {
|
||||
this.mgmtService.getUserByID(id).then(resp => {
|
||||
if (resp.user) {
|
||||
this.user = resp.user;
|
||||
this.dataSource = new MembershipDetailDataSource(this.mgmtService, authService);
|
||||
this.dataSource.loadMyMemberships(
|
||||
0,
|
||||
50,
|
||||
);
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
} else {
|
||||
this.mgmtService.getUserByID(id).then(resp => {
|
||||
if (resp.user) {
|
||||
this.user = resp.user;
|
||||
this.dataSource = new MembershipDetailDataSource(this.mgmtService, authService);
|
||||
this.dataSource.loadMemberships(
|
||||
this.user.id,
|
||||
0,
|
||||
50,
|
||||
);
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
})).subscribe();
|
||||
}
|
||||
|
||||
public ngAfterViewInit(): void {
|
||||
this.paginator.page
|
||||
.pipe(
|
||||
tap(() => this.loadMembershipsPage()),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private loadMembershipsPage(): void {
|
||||
this.dataSource.loadMemberships(
|
||||
this.user.id,
|
||||
this.paginator.pageIndex,
|
||||
this.paginator.pageSize,
|
||||
);
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.membersSubject.value.length;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.membersSubject.value.forEach(row => this.selection.select(row));
|
||||
}
|
||||
|
||||
public addMember(): void {
|
||||
const dialogRef = this.dialog.open(MemberCreateDialogComponent, {
|
||||
width: '400px',
|
||||
data: {
|
||||
user: this.user,
|
||||
},
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp && resp.creationType !== undefined) {
|
||||
switch (resp.creationType) {
|
||||
case CreationType.IAM:
|
||||
this.createIamMember(resp);
|
||||
break;
|
||||
case CreationType.ORG:
|
||||
this.createOrgMember(resp);
|
||||
break;
|
||||
case CreationType.PROJECT_OWNED:
|
||||
this.createOwnedProjectMember(resp);
|
||||
break;
|
||||
case CreationType.PROJECT_GRANTED:
|
||||
this.createGrantedProjectMember(resp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async loadManager(userId: string): Promise<void> {
|
||||
this.mgmtService.listUserMemberships(userId, 100, 0, []).then(response => {
|
||||
this.memberships = response.resultList;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
public createIamMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.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', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createOrgMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.roles;
|
||||
|
||||
if (users && users.length && roles && roles.length) {
|
||||
Promise.all(users.map(user => {
|
||||
return this.mgmtService.addOrgMember(user.id, roles);
|
||||
})).then(() => {
|
||||
this.toast.showInfo('ORG.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createGrantedProjectMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.roles;
|
||||
|
||||
if (users && users.length && roles && roles.length) {
|
||||
users.forEach(user => {
|
||||
return this.mgmtService.addProjectGrantMember(
|
||||
response.projectId,
|
||||
response.grantId,
|
||||
user.id,
|
||||
roles,
|
||||
).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createOwnedProjectMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.roles;
|
||||
|
||||
if (users && users.length && roles && roles.length) {
|
||||
users.forEach(user => {
|
||||
return this.mgmtService.addProjectMember(response.projectId, user.id, roles)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public removeMembership(membership: Membership.AsObject): void {
|
||||
let prom;
|
||||
|
||||
if (membership.projectId && membership.projectGrantId && membership.userId) {
|
||||
prom = this.mgmtService.removeProjectGrantMember(
|
||||
membership.projectId,
|
||||
membership.projectGrantId,
|
||||
membership.userId,
|
||||
);
|
||||
} else if (membership.projectId && membership.userId) {
|
||||
prom = this.mgmtService.removeProjectMember(membership.projectId, membership.userId);
|
||||
} else if (membership.orgId && membership.userId) {
|
||||
prom = this.mgmtService.removeOrgMember(membership.userId);
|
||||
} else if (membership.userId) {
|
||||
prom = this.adminService.removeIAMMember(membership.userId);
|
||||
}
|
||||
|
||||
public async loadManager(userId: string): Promise<void> {
|
||||
this.mgmtService.listUserMemberships(userId, 100, 0, []).then(response => {
|
||||
this.memberships = response.resultList;
|
||||
this.loading = false;
|
||||
});
|
||||
if (prom) {
|
||||
prom.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERREMOVED', true);
|
||||
this.refreshPage();
|
||||
}).catch(error => this.toast.showError(error));
|
||||
}
|
||||
}
|
||||
|
||||
public createIamMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.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', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createOrgMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.roles;
|
||||
|
||||
if (users && users.length && roles && roles.length) {
|
||||
Promise.all(users.map(user => {
|
||||
return this.mgmtService.addOrgMember(user.id, roles);
|
||||
})).then(() => {
|
||||
this.toast.showInfo('ORG.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createGrantedProjectMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.roles;
|
||||
|
||||
if (users && users.length && roles && roles.length) {
|
||||
users.forEach(user => {
|
||||
return this.mgmtService.addProjectGrantMember(
|
||||
response.projectId,
|
||||
response.grantId,
|
||||
user.id,
|
||||
roles,
|
||||
).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createOwnedProjectMember(response: any): void {
|
||||
const users: User.AsObject[] = response.users;
|
||||
const roles: string[] = response.roles;
|
||||
|
||||
if (users && users.length && roles && roles.length) {
|
||||
users.forEach(user => {
|
||||
return this.mgmtService.addProjectMember(response.projectId, user.id, roles)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public removeMembership(membership: Membership.AsObject): void {
|
||||
let prom;
|
||||
|
||||
if (membership.projectId && membership.projectGrantId && membership.userId) {
|
||||
prom = this.mgmtService.removeProjectGrantMember(
|
||||
membership.projectId,
|
||||
membership.projectGrantId,
|
||||
membership.userId,
|
||||
);
|
||||
} else if (membership.projectId && membership.userId) {
|
||||
prom = this.mgmtService.removeProjectMember(membership.projectId, membership.userId);
|
||||
} else if (membership.orgId && membership.userId) {
|
||||
prom = this.mgmtService.removeOrgMember(membership.userId);
|
||||
} else if (membership.userId) {
|
||||
prom = this.adminService.removeIAMMember(membership.userId);
|
||||
}
|
||||
|
||||
if (prom) {
|
||||
prom.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERREMOVED', true);
|
||||
this.refreshPage();
|
||||
}).catch(error => this.toast.showError(error));
|
||||
}
|
||||
}
|
||||
|
||||
public refreshPage(): void {
|
||||
this.selection.clear();
|
||||
this.dataSource.loadMemberships(this.user.id, this.paginator.pageIndex, this.paginator.pageSize);
|
||||
}
|
||||
public refreshPage(): void {
|
||||
this.selection.clear();
|
||||
this.dataSource.loadMemberships(this.user.id, this.paginator.pageIndex, this.paginator.pageSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { RouterModule, Routes } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InfoSectionModule } from 'src/app/modules/info-section/info-section.module';
|
||||
import { PaginatorModule } from 'src/app/modules/paginator/paginator.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
@@ -19,34 +20,35 @@ import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/
|
||||
import { MembershipDetailComponent } from './membership-detail.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: MembershipDetailComponent,
|
||||
canActivate: [],
|
||||
data: {
|
||||
roles: ['user.write'],
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: MembershipDetailComponent,
|
||||
canActivate: [],
|
||||
data: {
|
||||
roles: ['user.write'],
|
||||
},
|
||||
},
|
||||
];
|
||||
@NgModule({
|
||||
declarations: [MembershipDetailComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes),
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
MatCheckboxModule,
|
||||
MatTableModule,
|
||||
PaginatorModule,
|
||||
MatProgressSpinnerModule,
|
||||
LocalizedDatePipeModule,
|
||||
TimestampToDatePipeModule,
|
||||
HasRoleModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
HasRolePipeModule,
|
||||
RefreshTableModule,
|
||||
MatTooltipModule,
|
||||
],
|
||||
declarations: [MembershipDetailComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes),
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
MatCheckboxModule,
|
||||
MatTableModule,
|
||||
PaginatorModule,
|
||||
MatProgressSpinnerModule,
|
||||
LocalizedDatePipeModule,
|
||||
TimestampToDatePipeModule,
|
||||
HasRoleModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
HasRolePipeModule,
|
||||
RefreshTableModule,
|
||||
MatTooltipModule,
|
||||
InfoSectionModule,
|
||||
],
|
||||
})
|
||||
export class MembershipDetailModule { }
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
span {
|
||||
max-width: 30px;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 800;
|
||||
font-weight: 300;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -55,7 +55,7 @@ export class MembershipsComponent implements OnInit {
|
||||
|
||||
public async loadManager(userId: string): Promise<void> {
|
||||
if (this.auth) {
|
||||
this.authService.listMyUserGrants(100, 0, []).then(resp => {
|
||||
this.authService.listMyMemberships(100, 0, []).then(resp => {
|
||||
this.memberships = resp.resultList;
|
||||
this.totalResult = resp.details?.totalResult || 0;
|
||||
this.loading = false;
|
||||
|
||||
Reference in New Issue
Block a user