mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-14 01:45:12 +00:00
feat: protos refactoring
* start with user * user first try done in all services * user, org, idp for discussion * remove unused stuff * bla * dockerbuild * rename search, get multiple to list... * add annotation * update proto dependencies * update proto dependencies * change proto imports * replace all old imports * fix go out * remove unused lines * correct protoc flags * grpc and openapi flags * go out source path relative * -p * remove dead code * sourcepath relative * ls * is onenapi the problem? * hobla * authoption output * wrong field name * gopf * correct option, add correct flags * small improvments * SIMPLYFY * relative path * gopf bin ich en tubel * correct path * default policies in admin * grpc generation in one file * remove non ascii * metadata on manipulations * correct auth_option import * fixes * larry * idp provider to idp * fix generate * admin and auth nearly done * admin and auth nearly done * gen * healthz * imports * deleted too much imports * fix org * add import * imports * import * naming * auth_opt * gopf * management * imports * _TYPE_UNSPECIFIED * improts * auth opts * management policies * imports * passwordlessType to MFAType * auth_opt * add user grant calls * add missing messages * result * fix option * improvements * ids * fix http * imports * fixes * fields * body * add fields * remove wrong member query * fix request response * fixes * add copy files * variable versions * generate all files * improvements * add dependencies * factors * user session * oidc information, iam * remove unused file * changes * enums * dockerfile * fix build * remove unused folder * update readme for build * move old server impl * add event type to change * some changes * start admin * remove wrong field * admin only list calls missing * fix proto numbers * surprisingly it compiles * service ts changes * admin mgmt * mgmt * auth manipulation and gets done, lists missing * validations and some field changes * validations * enum validations * remove todo * move proto files to proto/zitadel * change proto path in dockerfile * it compiles! * add validate import * remove duplicate import * fix protos * fix import * tests * cleanup * remove unimplemented methods * iam member multiple queries * all auth and admin calls * add initial password on crate human * message names * management user server * machine done * fix: todos (#1346) * fix: pub sub in new eventstore * fix: todos * fix: todos * fix: todos * fix: todos * fix: todos * fix tests * fix: search method domain * admin service, user import type typescript * admin changes * admin changes * fix: search method domain * more user grpc and begin org, fix configs * fix: return object details * org grpc * remove creation date add details * app * fix: return object details * fix: return object details * mgmt service, project members * app * fix: convert policies * project, members, granted projects, searches * fix: convert usergrants * fix: convert usergrants * auth user detail, user detail, mfa, second factor, auth * fix: convert usergrants * mfa, memberships, password, owned proj detail * fix: convert usergrants * project grant * missing details * changes, userview * idp table, keys * org list and user table filter * unify rest paths (#1381) * unify rest paths * post for all searches, mfa to multi_factor, secondfactor to second_factor * remove v1 * fix tests * rename api client key to app key * machine keys, age policy * user list, machine keys, changes * fix: org states * add default flag to policy * second factor to type * idp id * app type * unify ListQuery, ListDetails, ObjectDetails field names * user grants, apps, memberships * fix type params * metadata to detail, linke idps * api create, membership, app detail, create * idp, app, policy * queries, multi -> auth factors and missing fields * update converters * provider to user, remove old mgmt refs * temp remove authfactor dialog, build finish Co-authored-by: Max Peintner <[email protected]> Co-authored-by: Fabi <[email protected]> Co-authored-by: Livio Amstutz <[email protected]> Co-authored-by: Fabiennne <[email protected]>
This commit is contained in:
co-authored by
Max Peintner
Fabi
Livio Amstutz
Fabiennne
parent
9f417f3957
commit
dabd5920dc
+7
-6
@@ -1,8 +1,9 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { catchError, finalize, map } from 'rxjs/operators';
|
||||
import { Application, OIDCApplicationType, OIDCResponseType } from 'src/app/proto/generated/management_pb';
|
||||
import { App, OIDCAppType } from 'src/app/proto/generated/zitadel/app_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
|
||||
import { NATIVE_TYPE, USER_AGENT_TYPE, WEB_TYPE } from '../../../apps/authtypes';
|
||||
|
||||
@Component({
|
||||
@@ -14,10 +15,10 @@ export class ApplicationGridComponent implements OnInit {
|
||||
@Input() public projectId: string = '';
|
||||
@Input() public disabled: boolean = false;
|
||||
@Output() public changeView: EventEmitter<void> = new EventEmitter();
|
||||
public appsSubject: BehaviorSubject<Application.AsObject[]> = new BehaviorSubject<Application.AsObject[]>([]);
|
||||
public appsSubject: BehaviorSubject<App.AsObject[]> = new BehaviorSubject<App.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public OIDCApplicationType: any = OIDCApplicationType;
|
||||
public OIDCApplicationType: any = OIDCAppType;
|
||||
|
||||
public NATIVE_TYPE: any = NATIVE_TYPE;
|
||||
public WEB_TYPE: any = WEB_TYPE;
|
||||
@@ -30,14 +31,14 @@ export class ApplicationGridComponent implements OnInit {
|
||||
}
|
||||
|
||||
public loadApps(): void {
|
||||
from(this.mgmtService.SearchApplications(this.projectId, 100, 0)).pipe(
|
||||
from(this.mgmtService.listApps(this.projectId, 100, 0)).pipe(
|
||||
map(resp => {
|
||||
return resp.toObject().resultList;
|
||||
return resp.resultList;
|
||||
}),
|
||||
catchError(() => of([])),
|
||||
finalize(() => this.loadingSubject.next(false)),
|
||||
).subscribe((apps) => {
|
||||
this.appsSubject.next(apps as Application.AsObject[]);
|
||||
this.appsSubject.next(apps as App.AsObject[]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+11
-9
@@ -2,7 +2,7 @@ import { DataSource } from '@angular/cdk/collections';
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { catchError, finalize, map } from 'rxjs/operators';
|
||||
import { Application } from 'src/app/proto/generated/management_pb';
|
||||
import { App } from 'src/app/proto/generated/zitadel/app_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
|
||||
/**
|
||||
@@ -10,11 +10,11 @@ import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
* encapsulate all logic for fetching and manipulating the displayed data
|
||||
* (including sorting, pagination, and filtering).
|
||||
*/
|
||||
export class ProjectApplicationsDataSource extends DataSource<Application.AsObject> {
|
||||
export class ProjectApplicationsDataSource extends DataSource<App.AsObject> {
|
||||
public totalResult: number = 0;
|
||||
public viewTimestamp!: Timestamp.AsObject;
|
||||
|
||||
public appsSubject: BehaviorSubject<Application.AsObject[]> = new BehaviorSubject<Application.AsObject[]>([]);
|
||||
public appsSubject: BehaviorSubject<App.AsObject[]> = new BehaviorSubject<App.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
|
||||
@@ -26,12 +26,14 @@ export class ProjectApplicationsDataSource extends DataSource<Application.AsObje
|
||||
const offset = pageIndex * pageSize;
|
||||
|
||||
this.loadingSubject.next(true);
|
||||
from(this.mgmtService.SearchApplications(projectId, pageSize, offset)).pipe(
|
||||
from(this.mgmtService.listApps(projectId, pageSize, offset)).pipe(
|
||||
map(resp => {
|
||||
const response = resp.toObject();
|
||||
this.totalResult = response.totalResult;
|
||||
if (response.viewTimestamp) {
|
||||
this.viewTimestamp = response.viewTimestamp;
|
||||
const response = resp;
|
||||
if (response.details?.totalResult) {
|
||||
this.totalResult = response.details.totalResult;
|
||||
}
|
||||
if (response.details?.viewTimestamp) {
|
||||
this.viewTimestamp = response.details.viewTimestamp;
|
||||
}
|
||||
return response.resultList;
|
||||
}),
|
||||
@@ -48,7 +50,7 @@ export class ProjectApplicationsDataSource extends DataSource<Application.AsObje
|
||||
* the returned stream emits new items.
|
||||
* @returns A stream of the items to be rendered.
|
||||
*/
|
||||
public connect(): Observable<Application.AsObject[]> {
|
||||
public connect(): Observable<App.AsObject[]> {
|
||||
return this.appsSubject.asObservable();
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -5,9 +5,8 @@ import { MatSort } from '@angular/material/sort';
|
||||
import { MatTable } from '@angular/material/table';
|
||||
import { merge, of } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { Application } from 'src/app/proto/generated/management_pb';
|
||||
import { App } from 'src/app/proto/generated/zitadel/app_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { ProjectApplicationsDataSource } from './applications-datasource';
|
||||
|
||||
@@ -22,13 +21,13 @@ export class ApplicationsComponent implements AfterViewInit, OnInit {
|
||||
@Input() public disabled: boolean = false;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) public sort!: MatSort;
|
||||
@ViewChild(MatTable) public table!: MatTable<Application.AsObject>;
|
||||
@ViewChild(MatTable) public table!: MatTable<App.AsObject>;
|
||||
public dataSource!: ProjectApplicationsDataSource;
|
||||
public selection: SelectionModel<Application.AsObject> = new SelectionModel<Application.AsObject>(true, []);
|
||||
public selection: SelectionModel<App.AsObject> = new SelectionModel<App.AsObject>(true, []);
|
||||
|
||||
public displayedColumns: string[] = ['select', 'name', 'type'];
|
||||
|
||||
constructor(private mgmtService: ManagementService, private toast: ToastService) { }
|
||||
constructor(private mgmtService: ManagementService) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.dataSource = new ProjectApplicationsDataSource(this.mgmtService);
|
||||
@@ -60,7 +59,7 @@ export class ApplicationsComponent implements AfterViewInit, OnInit {
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.appsSubject.value.forEach((row: Application.AsObject) => this.selection.select(row));
|
||||
this.dataSource.appsSubject.value.forEach((row: App.AsObject) => this.selection.select(row));
|
||||
}
|
||||
|
||||
public refreshPage(): void {
|
||||
|
||||
+11
-11
@@ -1,6 +1,6 @@
|
||||
<app-meta-layout>
|
||||
<div class="max-width-container">
|
||||
<div class="head" *ngIf="project?.projectId">
|
||||
<div class="head" *ngIf="project?.id">
|
||||
<a [routerLink]="[ '/projects' ]" mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
@@ -22,12 +22,12 @@
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<button mat-stroked-button color="warn"
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.projectId]| hasRole | async) == false"
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.id]| hasRole | async) == false"
|
||||
*ngIf="project?.state === ProjectState.PROJECTSTATE_ACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECTSTATE_INACTIVE)">{{'PROJECT.TABLE.DEACTIVATE' |
|
||||
translate}}</button>
|
||||
<button mat-stroked-button color="warn"
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.projectId]| hasRole | async) == false"
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.id]| hasRole | async) == false"
|
||||
*ngIf="project?.state === ProjectState.PROJECTSTATE_INACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECTSTATE_ACTIVE)">{{'PROJECT.TABLE.ACTIVATE' |
|
||||
translate}}</button>
|
||||
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="project">
|
||||
<ng-template appHasRole [appHasRole]="['project.app.read:' + project.projectId, 'project.app.read']">
|
||||
<ng-template appHasRole [appHasRole]="['project.app.read:' + project.id, 'project.app.read']">
|
||||
<app-application-grid *ngIf="grid" [disabled]="isZitadel" (changeView)="grid = false"
|
||||
[projectId]="projectId"></app-application-grid>
|
||||
<app-card *ngIf="!grid" title="{{ 'PROJECT.APP.TITLE' | translate }}">
|
||||
@@ -68,18 +68,18 @@
|
||||
|
||||
<ng-container *ngIf="isZitadel == false">
|
||||
<ng-template appHasRole
|
||||
[appHasRole]="['project.grant.read:' + project.projectId, 'project.grant.read']">
|
||||
[appHasRole]="['project.grant.read:' + project.id, 'project.grant.read']">
|
||||
<app-card title="{{ 'PROJECT.GRANT.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.GRANT.DESCRIPTION' | translate }}">
|
||||
<app-project-grants
|
||||
[refreshOnPreviousRoutes]="['/projects/'+projectId+'/grants/create','/projects/'+projectId+'/roles/create']"
|
||||
[disabled]="((['project.grant.write$', 'project.grant.write:'+ project.projectId]| hasRole | async))== false"
|
||||
[disabled]="((['project.grant.write$', 'project.grant.write:'+ project.id]| hasRole | async))== false"
|
||||
[projectId]="projectId">
|
||||
</app-project-grants>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.projectId, 'project.role.read']">
|
||||
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.id, 'project.role.read']">
|
||||
<app-card id="roles" title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
|
||||
<p>{{'PROJECT.ROLE.OPTIONS' | translate}}</p>
|
||||
@@ -92,14 +92,14 @@
|
||||
<p class="desc">{{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}</p>
|
||||
<div class="divider"></div>
|
||||
<app-project-roles
|
||||
[disabled]="(['project.role.write$', 'project.role.write:'+ project.projectId]| hasRole | async) == false"
|
||||
[disabled]="(['project.role.write$', 'project.role.write:'+ project.id]| hasRole | async) == false"
|
||||
[actionsVisible]="true" [projectId]="projectId">
|
||||
</app-project-roles>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.grant.read']">
|
||||
<app-card *ngIf="project?.projectId" title="{{ 'GRANTS.PROJECT.TITLE' | translate }}"
|
||||
<app-card *ngIf="project?.id" title="{{ 'GRANTS.PROJECT.TITLE' | translate }}"
|
||||
description="{{'GRANTS.PROJECT.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [context]="UserGrantContext.OWNED_PROJECT" [projectId]="projectId"
|
||||
[refreshOnPreviousRoutes]="['/grant-create/project/'+projectId]"
|
||||
@@ -131,11 +131,11 @@
|
||||
[membersSubject]="membersSubject" title="{{ 'PROJECT.MEMBER.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.MEMBER.TITLEDESC' | translate }}" (addClicked)="openAddMember()"
|
||||
(showDetailClicked)="showDetail()" (refreshClicked)="loadMembers()"
|
||||
[disabled]="(['project.member.write$', 'project.member.write:'+ project.projectId]| hasRole | async) == false">
|
||||
[disabled]="(['project.member.write$', 'project.member.write:'+ project.id]| hasRole | async) == false">
|
||||
</app-contributors>
|
||||
</mat-tab>
|
||||
<mat-tab label="{{ 'CHANGES.PROJECT.TITLE' | translate }}" class="meta-flex-col">
|
||||
<app-changes *ngIf="project" [changeType]="ChangeType.PROJECT" [id]="project.projectId"></app-changes>
|
||||
<app-changes *ngIf="project" [changeType]="ChangeType.PROJECT" [id]="project.id"></app-changes>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
+40
-51
@@ -1,4 +1,3 @@
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
@@ -9,22 +8,14 @@ import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs';
|
||||
import { catchError, finalize, map } from 'rxjs/operators';
|
||||
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
|
||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||
import { ProjectType } from 'src/app/modules/project-members/project-members.component';
|
||||
import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import {
|
||||
Application,
|
||||
ApplicationSearchResponse,
|
||||
ProjectMember,
|
||||
ProjectMemberSearchResponse,
|
||||
ProjectMemberView,
|
||||
ProjectRole,
|
||||
ProjectRoleSearchResponse,
|
||||
ProjectState,
|
||||
ProjectType,
|
||||
ProjectView,
|
||||
UserGrantSearchKey,
|
||||
UserView,
|
||||
} from 'src/app/proto/generated/management_pb';
|
||||
import { App } from 'src/app/proto/generated/zitadel/app_pb';
|
||||
import { ListAppsResponse, UpdateProjectRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
|
||||
import { Project, ProjectState } from 'src/app/proto/generated/zitadel/project_pb';
|
||||
import { User } from 'src/app/proto/generated/zitadel/user_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@@ -36,22 +27,11 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
})
|
||||
export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
public projectId: string = '';
|
||||
public project!: ProjectView.AsObject;
|
||||
|
||||
public pageSizeRoles: number = 10;
|
||||
public roleDataSource: MatTableDataSource<ProjectRole.AsObject> = new MatTableDataSource<ProjectRole.AsObject>();
|
||||
public roleResult!: ProjectRoleSearchResponse.AsObject;
|
||||
public roleColumns: string[] = ['name', 'displayname', 'group', 'actions'];
|
||||
|
||||
public pageSizeMembers: number = 10;
|
||||
public projectDataSource: MatTableDataSource<ProjectMember.AsObject> = new MatTableDataSource<ProjectMember.AsObject>();
|
||||
public memberResult!: ProjectMemberSearchResponse.AsObject;
|
||||
public memberColumns: string[] = ['firstname', 'lastname', 'username', 'email', 'roles'];
|
||||
public selection: SelectionModel<ProjectMember.AsObject> = new SelectionModel<ProjectMember.AsObject>(true, []);
|
||||
public project!: Project.AsObject;
|
||||
|
||||
public pageSizeApps: number = 10;
|
||||
public appsDataSource: MatTableDataSource<Application.AsObject> = new MatTableDataSource<Application.AsObject>();
|
||||
public appsResult!: ApplicationSearchResponse.AsObject;
|
||||
public appsDataSource: MatTableDataSource<App.AsObject> = new MatTableDataSource<App.AsObject>();
|
||||
public appsResult!: ListAppsResponse.AsObject;
|
||||
public appsColumns: string[] = ['name'];
|
||||
|
||||
public ProjectState: any = ProjectState;
|
||||
@@ -64,13 +44,12 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
public isZitadel: boolean = false;
|
||||
|
||||
public userGrantSearchKey: UserGrantSearchKey = UserGrantSearchKey.USERGRANTSEARCHKEY_PROJECT_ID;
|
||||
public UserGrantContext: any = UserGrantContext;
|
||||
|
||||
// members
|
||||
public totalMemberResult: number = 0;
|
||||
public membersSubject: BehaviorSubject<ProjectMemberView.AsObject[]>
|
||||
= new BehaviorSubject<ProjectMemberView.AsObject[]>([]);
|
||||
public membersSubject: BehaviorSubject<Member.AsObject[]>
|
||||
= new BehaviorSubject<Member.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public refreshChanges$: EventEmitter<void> = new EventEmitter();
|
||||
@@ -96,12 +75,14 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
private async getData({ id }: Params): Promise<void> {
|
||||
this.projectId = id;
|
||||
|
||||
this.mgmtService.GetIam().then(iam => {
|
||||
this.isZitadel = iam.toObject().iamProjectId === this.projectId;
|
||||
this.mgmtService.getIAM().then(iam => {
|
||||
this.isZitadel = iam.iamProjectId === this.projectId;
|
||||
});
|
||||
|
||||
this.mgmtService.GetProjectById(id).then(proj => {
|
||||
this.project = proj.toObject();
|
||||
this.mgmtService.getProjectByID(id).then(resp => {
|
||||
if (resp.project) {
|
||||
this.project = resp.project;
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
this.toast.showError(error);
|
||||
@@ -112,10 +93,12 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
public loadMembers(): void {
|
||||
this.loadingSubject.next(true);
|
||||
from(this.mgmtService.SearchProjectMembers(this.projectId, 100, 0)).pipe(
|
||||
from(this.mgmtService.listProjectMembers(this.projectId, 100, 0)).pipe(
|
||||
map(resp => {
|
||||
this.totalMemberResult = resp.toObject().totalResult;
|
||||
return resp.toObject().resultList;
|
||||
if (resp.details?.totalResult) {
|
||||
this.totalMemberResult = resp.details?.totalResult;
|
||||
}
|
||||
return resp.resultList;
|
||||
}),
|
||||
catchError(() => of([])),
|
||||
finalize(() => this.loadingSubject.next(false)),
|
||||
@@ -125,7 +108,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public changeState(newState: ProjectState): void {
|
||||
if (newState === ProjectState.PROJECTSTATE_ACTIVE) {
|
||||
if (newState === ProjectState.PROJECT_STATE_ACTIVE) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.REACTIVATE',
|
||||
@@ -137,9 +120,9 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
this.mgmtService.ReactivateProject(this.projectId).then(() => {
|
||||
this.mgmtService.reactivateProject(this.projectId).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true);
|
||||
this.project.state = ProjectState.PROJECTSTATE_ACTIVE;
|
||||
this.project.state = ProjectState.PROJECT_STATE_ACTIVE;
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -147,7 +130,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
});
|
||||
|
||||
} else if (newState === ProjectState.PROJECTSTATE_INACTIVE) {
|
||||
} else if (newState === ProjectState.PROJECT_STATE_INACTIVE) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DEACTIVATE',
|
||||
@@ -159,9 +142,9 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
this.mgmtService.DeactivateProject(this.projectId).then(() => {
|
||||
this.mgmtService.deactivateProject(this.projectId).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true);
|
||||
this.project.state = ProjectState.PROJECTSTATE_INACTIVE;
|
||||
this.project.state = ProjectState.PROJECT_STATE_INACTIVE;
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -183,7 +166,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
this.mgmtService.RemoveProject(this.projectId).then(() => {
|
||||
this.mgmtService.removeProject(this.projectId).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DELETED', true);
|
||||
const params: Params = {
|
||||
'deferredReload': true,
|
||||
@@ -197,7 +180,13 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public saveProject(): void {
|
||||
this.mgmtService.UpdateProject(this.project.projectId, this.project).then(() => {
|
||||
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);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
@@ -218,19 +207,19 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
const dialogRef = this.dialog.open(MemberCreateDialogComponent, {
|
||||
data: {
|
||||
creationType: CreationType.PROJECT_OWNED,
|
||||
projectId: this.project.projectId,
|
||||
projectId: this.project.id,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
const users: UserView.AsObject[] = resp.users;
|
||||
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)
|
||||
return this.mgmtService.addProjectMember(this.projectId, user.id, roles)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.MEMBERADDED', true);
|
||||
setTimeout(() => {
|
||||
@@ -246,6 +235,6 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public showDetail(): void {
|
||||
this.router.navigate(['projects', this.project.projectId, 'members']);
|
||||
this.router.navigate(['projects', this.project.id, 'members']);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-10
@@ -2,7 +2,7 @@ import { DataSource } from '@angular/cdk/collections';
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { catchError, finalize, map } from 'rxjs/operators';
|
||||
import { ProjectGrant } from 'src/app/proto/generated/management_pb';
|
||||
import { GrantedProject } from 'src/app/proto/generated/zitadel/project_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
|
||||
/**
|
||||
@@ -10,10 +10,10 @@ import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
* encapsulate all logic for fetching and manipulating the displayed data
|
||||
* (including sorting, pagination, and filtering).
|
||||
*/
|
||||
export class ProjectGrantsDataSource extends DataSource<ProjectGrant.AsObject> {
|
||||
export class ProjectGrantsDataSource extends DataSource<GrantedProject.AsObject> {
|
||||
public totalResult: number = 0;
|
||||
public viewTimestamp!: Timestamp.AsObject;
|
||||
public grantsSubject: BehaviorSubject<ProjectGrant.AsObject[]> = new BehaviorSubject<ProjectGrant.AsObject[]>([]);
|
||||
public grantsSubject: BehaviorSubject<GrantedProject.AsObject[]> = new BehaviorSubject<GrantedProject.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
|
||||
@@ -25,14 +25,15 @@ export class ProjectGrantsDataSource extends DataSource<ProjectGrant.AsObject> {
|
||||
const offset = pageIndex * pageSize;
|
||||
|
||||
this.loadingSubject.next(true);
|
||||
from(this.mgmtService.SearchProjectGrants(projectId, pageSize, offset)).pipe(
|
||||
from(this.mgmtService.listProjectGrants(projectId, pageSize, offset)).pipe(
|
||||
map(resp => {
|
||||
const response = resp.toObject();
|
||||
this.totalResult = response.totalResult;
|
||||
if (response.viewTimestamp) {
|
||||
this.viewTimestamp = response.viewTimestamp;
|
||||
if (resp.details?.totalResult) {
|
||||
this.totalResult = resp.details.totalResult;
|
||||
}
|
||||
return response.resultList;
|
||||
if (resp.details?.viewTimestamp) {
|
||||
this.viewTimestamp = resp.details?.viewTimestamp;
|
||||
}
|
||||
return resp.resultList;
|
||||
}),
|
||||
catchError(() => of([])),
|
||||
finalize(() => this.loadingSubject.next(false)),
|
||||
@@ -47,7 +48,7 @@ export class ProjectGrantsDataSource extends DataSource<ProjectGrant.AsObject> {
|
||||
* the returned stream emits new items.
|
||||
* @returns A stream of the items to be rendered.
|
||||
*/
|
||||
public connect(): Observable<ProjectGrant.AsObject[]> {
|
||||
public connect(): Observable<GrantedProject.AsObject[]> {
|
||||
return this.grantsSubject.asObservable();
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -5,7 +5,7 @@ import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { MatTable } from '@angular/material/table';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { ProjectGrant, ProjectRoleView } from 'src/app/proto/generated/management_pb';
|
||||
import { GrantedProject, Role } from 'src/app/proto/generated/zitadel/project_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@@ -28,10 +28,10 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
@Input() public projectId: string = '';
|
||||
@Input() public disabled: boolean = false;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
@ViewChild(MatTable) public table!: MatTable<ProjectGrant.AsObject>;
|
||||
@ViewChild(MatTable) public table!: MatTable<GrantedProject.AsObject>;
|
||||
public dataSource!: ProjectGrantsDataSource;
|
||||
public selection: SelectionModel<ProjectGrant.AsObject> = new SelectionModel<ProjectGrant.AsObject>(true, []);
|
||||
public memberRoleOptions: ProjectRoleView.AsObject[] = [];
|
||||
public selection: SelectionModel<GrantedProject.AsObject> = new SelectionModel<GrantedProject.AsObject>(true, []);
|
||||
public memberRoleOptions: Role.AsObject[] = [];
|
||||
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
public displayedColumns: string[] = ['select', 'grantedOrgName', 'dates'];
|
||||
@@ -73,14 +73,14 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
public getRoleOptions(projectId: string): void {
|
||||
this.mgmtService.SearchProjectRoles(projectId, 100, 0).then(resp => {
|
||||
this.memberRoleOptions = resp.toObject().resultList;
|
||||
this.mgmtService.listProjectRoles(projectId, 100, 0).then(resp => {
|
||||
this.memberRoleOptions = resp.resultList;
|
||||
});
|
||||
}
|
||||
|
||||
updateRoles(grant: ProjectGrant.AsObject, selectionChange: MatSelectChange): void {
|
||||
this.mgmtService.UpdateProjectGrant(grant.id, grant.projectId, selectionChange.value)
|
||||
.then((newgrant: ProjectGrant) => {
|
||||
updateRoles(grant: GrantedProject.AsObject, selectionChange: MatSelectChange): void {
|
||||
this.mgmtService.updateProjectGrant(grant.grantId, grant.projectId, selectionChange.value)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTCHANGED', true);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -89,14 +89,14 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
|
||||
deleteSelectedGrants(): void {
|
||||
const promises = this.selection.selected.map(grant => {
|
||||
return this.mgmtService.RemoveProjectGrant(grant.id, grant.projectId);
|
||||
return this.mgmtService.removeProjectGrant(grant.grantId, grant.projectId);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
this.toast.showInfo('GRANTS.TOAST.BULKREMOVED', true);
|
||||
const data = this.dataSource.grantsSubject.getValue();
|
||||
this.selection.selected.forEach((item) => {
|
||||
const index = data.findIndex(i => i.id === item.id);
|
||||
const index = data.findIndex(i => i.grantId === item.grantId);
|
||||
if (index > -1) {
|
||||
data.splice(index, 1);
|
||||
this.dataSource.grantsSubject.next(data);
|
||||
|
||||
+20
-19
@@ -3,9 +3,10 @@ import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Router } from '@angular/router';
|
||||
import { ProjectType } from 'src/app/modules/project-members/project-members.component';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import { Org } from 'src/app/proto/generated/auth_pb';
|
||||
import { ProjectState, ProjectType, ProjectView } from 'src/app/proto/generated/management_pb';
|
||||
import { Org } from 'src/app/proto/generated/zitadel/org_pb';
|
||||
import { Project, ProjectState } from 'src/app/proto/generated/zitadel/project_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { StorageKey, StorageService } from 'src/app/services/storage.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
@@ -39,14 +40,14 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
],
|
||||
})
|
||||
export class OwnedProjectGridComponent implements OnChanges {
|
||||
@Input() items: Array<ProjectView.AsObject> = [];
|
||||
public notPinned: Array<ProjectView.AsObject> = [];
|
||||
@Input() items: Array<Project.AsObject> = [];
|
||||
public notPinned: Array<Project.AsObject> = [];
|
||||
|
||||
@Output() newClicked: EventEmitter<boolean> = new EventEmitter();
|
||||
@Output() changedView: EventEmitter<boolean> = new EventEmitter();
|
||||
@Input() loading: boolean = false;
|
||||
|
||||
public selection: SelectionModel<ProjectView.AsObject> = new SelectionModel<ProjectView.AsObject>(true, []);
|
||||
public selection: SelectionModel<Project.AsObject> = new SelectionModel<Project.AsObject>(true, []);
|
||||
|
||||
public showNewProject: boolean = false;
|
||||
public ProjectState: any = ProjectState;
|
||||
@@ -61,10 +62,10 @@ export class OwnedProjectGridComponent implements OnChanges {
|
||||
) {
|
||||
this.selection.changed.subscribe(selection => {
|
||||
this.setPrefixedItem('pinned-projects', JSON.stringify(
|
||||
this.selection.selected.map(item => item.projectId),
|
||||
this.selection.selected.map(item => item.id),
|
||||
)).then(() => {
|
||||
selection.added.forEach(item => {
|
||||
const index = this.notPinned.findIndex(i => i.projectId === item.projectId);
|
||||
const index = this.notPinned.findIndex(i => i.id === item.id);
|
||||
this.notPinned.splice(index, 1);
|
||||
});
|
||||
this.notPinned.push(...selection.removed);
|
||||
@@ -72,11 +73,11 @@ export class OwnedProjectGridComponent implements OnChanges {
|
||||
});
|
||||
}
|
||||
|
||||
public selectItem(item: ProjectView.AsObject, event?: any): void {
|
||||
public selectItem(item: Project.AsObject, event?: any): void {
|
||||
if (event && !event.target.classList.contains('mat-icon')) {
|
||||
this.router.navigate(['/projects', item.projectId]);
|
||||
this.router.navigate(['/projects', item.id]);
|
||||
} else if (!event) {
|
||||
this.router.navigate(['/projects', item.projectId]);
|
||||
this.router.navigate(['/projects', item.id]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,8 +96,8 @@ export class OwnedProjectGridComponent implements OnChanges {
|
||||
this.getPrefixedItem('pinned-projects').then(storageEntry => {
|
||||
if (storageEntry) {
|
||||
const array: string[] = JSON.parse(storageEntry);
|
||||
const toSelect: ProjectView.AsObject[] = this.items.filter((item, index) => {
|
||||
if (array.includes(item.projectId)) {
|
||||
const toSelect: Project.AsObject[] = this.items.filter((item, index) => {
|
||||
if (array.includes(item.id)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -125,12 +126,12 @@ export class OwnedProjectGridComponent implements OnChanges {
|
||||
this.changedView.emit(true);
|
||||
}
|
||||
|
||||
public toggle(item: ProjectView.AsObject, event: any): void {
|
||||
public toggle(item: Project.AsObject, event: any): void {
|
||||
event.stopPropagation();
|
||||
this.selection.toggle(item);
|
||||
}
|
||||
|
||||
public deleteProject(event: any, item: ProjectView.AsObject): void {
|
||||
public deleteProject(event: any, item: Project.AsObject): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
@@ -143,20 +144,20 @@ export class OwnedProjectGridComponent implements OnChanges {
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp && item.projectId !== this.zitadelProjectId) {
|
||||
this.mgmtService.RemoveProject(item.projectId).then(() => {
|
||||
if (resp && item.id !== this.zitadelProjectId) {
|
||||
this.mgmtService.removeProject(item.id).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DELETED', true);
|
||||
const index = this.items.findIndex(iter => iter.projectId === item.projectId);
|
||||
const index = this.items.findIndex(iter => iter.id === item.id);
|
||||
if (index > -1) {
|
||||
this.items.splice(index, 1);
|
||||
}
|
||||
|
||||
const indexSelection = this.selection.selected.findIndex(iter => iter.projectId === item.projectId);
|
||||
const indexSelection = this.selection.selected.findIndex(iter => iter.id === item.id);
|
||||
if (indexSelection > -1) {
|
||||
this.selection.selected.splice(indexSelection, 1);
|
||||
}
|
||||
|
||||
const indexPinned = this.notPinned.findIndex(iter => iter.projectId === item.projectId);
|
||||
const indexPinned = this.notPinned.findIndex(iter => iter.id === item.id);
|
||||
if (indexPinned > -1) {
|
||||
this.notPinned.splice(indexPinned, 1);
|
||||
}
|
||||
|
||||
+19
-18
@@ -10,7 +10,7 @@ import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import { ProjectView } from 'src/app/proto/generated/management_pb';
|
||||
import { Project } from 'src/app/proto/generated/zitadel/project_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@@ -42,14 +42,14 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
public totalResult: number = 0;
|
||||
public viewTimestamp!: Timestamp.AsObject;
|
||||
|
||||
public dataSource: MatTableDataSource<ProjectView.AsObject> =
|
||||
new MatTableDataSource<ProjectView.AsObject>();
|
||||
public dataSource: MatTableDataSource<Project.AsObject> =
|
||||
new MatTableDataSource<Project.AsObject>();
|
||||
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
|
||||
public ownedProjectList: ProjectView.AsObject[] = [];
|
||||
public ownedProjectList: Project.AsObject[] = [];
|
||||
public displayedColumns: string[] = ['select', 'name', 'state', 'creationDate', 'changeDate', 'actions'];
|
||||
public selection: SelectionModel<ProjectView.AsObject> = new SelectionModel<ProjectView.AsObject>(true, []);
|
||||
public selection: SelectionModel<Project.AsObject> = new SelectionModel<Project.AsObject>(true, []);
|
||||
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
@@ -66,8 +66,8 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
private toast: ToastService,
|
||||
private dialog: MatDialog,
|
||||
) {
|
||||
this.mgmtService.GetIam().then(iam => {
|
||||
this.zitadelProjectId = iam.toObject().iamProjectId;
|
||||
this.mgmtService.getIAM().then(iam => {
|
||||
this.zitadelProjectId = iam.iamProjectId;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,15 +108,16 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
|
||||
private async getData(limit?: number, offset?: number): Promise<void> {
|
||||
this.loadingSubject.next(true);
|
||||
this.mgmtService.SearchProjects(limit, offset).then(res => {
|
||||
const response = res.toObject();
|
||||
this.ownedProjectList = response.resultList;
|
||||
this.totalResult = response.totalResult;
|
||||
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 (response.viewTimestamp) {
|
||||
this.viewTimestamp = response.viewTimestamp;
|
||||
if (resp.details?.viewTimestamp) {
|
||||
this.viewTimestamp = resp.details?.viewTimestamp;
|
||||
}
|
||||
this.dataSource.data = this.ownedProjectList;
|
||||
this.loadingSubject.next(false);
|
||||
@@ -131,7 +132,7 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
|
||||
public reactivateSelectedProjects(): void {
|
||||
const promises = this.selection.selected.map(project => {
|
||||
this.mgmtService.ReactivateProject(project.projectId);
|
||||
this.mgmtService.reactivateProject(project.id);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
@@ -144,7 +145,7 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
|
||||
public deactivateSelectedProjects(): void {
|
||||
const promises = this.selection.selected.map(project => {
|
||||
this.mgmtService.DeactivateProject(project.projectId);
|
||||
this.mgmtService.deactivateProject(project.id);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
@@ -159,7 +160,7 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
|
||||
}
|
||||
|
||||
public deleteProject(item: ProjectView.AsObject): void {
|
||||
public deleteProject(item: Project.AsObject): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
@@ -171,8 +172,8 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (this.zitadelProjectId && resp && item.projectId !== this.zitadelProjectId) {
|
||||
this.mgmtService.RemoveProject(item.projectId).then(() => {
|
||||
if (this.zitadelProjectId && resp && item.id !== this.zitadelProjectId) {
|
||||
this.mgmtService.removeProject(item.id).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DELETED', true);
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { RoleGuard } from 'src/app/guards/role.guard';
|
||||
import { ProjectType } from 'src/app/proto/generated/management_pb';
|
||||
import { ProjectType } from 'src/app/modules/project-members/project-members.component';
|
||||
|
||||
import { OwnedProjectsComponent } from './owned-projects.component';
|
||||
|
||||
|
||||
+6
-6
@@ -10,7 +10,7 @@
|
||||
<div class="row">
|
||||
<span class="first">{{'PROJECT.GRANT.DETAIL.RESOURCEOWNER' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{grant?.resourceOwnerName}}</span>
|
||||
<span>{{grant?.details?.resourceOwner}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="formfield" appearance="outline" *ngIf="grant && grant.roleKeysList">
|
||||
<cnsl-form-field class="formfield" appearance="outline" *ngIf="grant && grant.grantedRoleKeysList">
|
||||
<cnsl-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="grant.roleKeysList" multiple (selectionChange)="updateRoles($event)">
|
||||
<mat-select [(ngModel)]="grant.grantedRoleKeysList" multiple (selectionChange)="updateRoles($event)">
|
||||
<mat-option *ngFor="let role of projectRoleOptions" [value]="role.key">
|
||||
{{role.key}}
|
||||
</mat-option>
|
||||
@@ -39,17 +39,17 @@
|
||||
<h1 class="h1">{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}</h1>
|
||||
<p class="desc">{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}</p>
|
||||
|
||||
<app-members-table *ngIf="grant" style="width: 100%;" [dataSource]="dataSource" [canWrite]="['project.grant.member.write','project.grant.member.write:' + grant.id] | hasRole | async"
|
||||
<app-members-table *ngIf="grant" style="width: 100%;" [dataSource]="dataSource" [canWrite]="['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async"
|
||||
[memberRoleOptions]="memberRoleOptions" (updateRoles)="updateMemberRoles($event.member, $event.change)"
|
||||
[factoryLoadFunc]="changePageFactory" (changedSelection)="selection = $event" [refreshTrigger]="changePage">
|
||||
<button selectactions (click)="removeProjectMemberSelection()"
|
||||
[disabled]="(['project.grant.member.delete','project.grant.member.delete:' + grant.id] | hasRole | async) == false"
|
||||
[disabled]="(['project.grant.member.delete','project.grant.member.delete:' + grant.grantId] | hasRole | async) == false"
|
||||
matTooltip="{{'ORG_DETAIL.TABLE.DELETE' | translate}}" class="del-button" color="warn" mat-raised-button>
|
||||
<i class="las la-trash"></i>
|
||||
{{'ACTIONS.SELECTIONDELETE' | translate}}
|
||||
</button>
|
||||
<a writeactions color="primary"
|
||||
[disabled]="(['project.grant.member.write','project.grant.member.write:' + grant.id] | hasRole | async) == false"
|
||||
[disabled]="(['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async) == false"
|
||||
(click)="openAddMember()" color="primary" mat-raised-button>
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
|
||||
+28
-32
@@ -3,15 +3,9 @@ import { MatDialog } from '@angular/material/dialog';
|
||||
import { PageEvent } from '@angular/material/paginator';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import {
|
||||
ProjectGrant,
|
||||
ProjectGrantMember,
|
||||
ProjectGrantMemberView,
|
||||
ProjectGrantState,
|
||||
ProjectGrantView,
|
||||
ProjectRoleView,
|
||||
ProjectType,
|
||||
} from 'src/app/proto/generated/management_pb';
|
||||
import { ProjectType } from 'src/app/modules/project-members/project-members.component';
|
||||
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
|
||||
import { GrantedProject, ProjectGrantState, Role } from 'src/app/proto/generated/zitadel/project_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@@ -29,7 +23,7 @@ import { ProjectGrantMembersDataSource } from './project-grant-members-datasourc
|
||||
export class ProjectGrantDetailComponent {
|
||||
public INITIALPAGESIZE: number = 25;
|
||||
|
||||
public grant!: ProjectGrantView.AsObject;
|
||||
public grant!: GrantedProject.AsObject;
|
||||
public projectid: string = '';
|
||||
public grantid: string = '';
|
||||
|
||||
@@ -39,12 +33,12 @@ export class ProjectGrantDetailComponent {
|
||||
public isZitadel: boolean = false;
|
||||
ProjectGrantState: any = ProjectGrantState;
|
||||
|
||||
public projectRoleOptions: ProjectRoleView.AsObject[] = [];
|
||||
public projectRoleOptions: Role.AsObject[] = [];
|
||||
public memberRoleOptions: Array<string> = [];
|
||||
|
||||
public changePageFactory!: Function;
|
||||
public changePage: EventEmitter<void> = new EventEmitter();
|
||||
public selection: Array<ProjectGrantMemberView.AsObject> = [];
|
||||
public selection: Array<Member.AsObject> = [];
|
||||
public dataSource!: ProjectGrantMembersDataSource;
|
||||
constructor(
|
||||
private mgmtService: ManagementService,
|
||||
@@ -71,22 +65,24 @@ export class ProjectGrantDetailComponent {
|
||||
);
|
||||
};
|
||||
|
||||
this.mgmtService.ProjectGrantByID(this.grantid, this.projectid).then((grant) => {
|
||||
this.grant = grant.toObject();
|
||||
this.mgmtService.getProjectGrantByID(this.grantid, this.projectid).then((resp) => {
|
||||
if (resp.projectGrant) {
|
||||
this.grant = resp.projectGrant;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public changeState(newState: ProjectGrantState): void {
|
||||
if (newState === ProjectGrantState.PROJECTGRANTSTATE_ACTIVE) {
|
||||
this.mgmtService.ReactivateProjectGrant(this.grantid, this.projectid).then(() => {
|
||||
if (newState === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE) {
|
||||
this.mgmtService.reactivateProjectGrant(this.grantid, this.projectid).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true);
|
||||
this.grant.state = newState;
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (newState === ProjectGrantState.PROJECTGRANTSTATE_INACTIVE) {
|
||||
this.mgmtService.DeactivateProjectGrant(this.grantid, this.projectid).then(() => {
|
||||
} else if (newState === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE) {
|
||||
this.mgmtService.deactivateProjectGrant(this.grantid, this.projectid).then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true);
|
||||
this.grant.state = newState;
|
||||
}).catch(error => {
|
||||
@@ -96,22 +92,22 @@ export class ProjectGrantDetailComponent {
|
||||
}
|
||||
|
||||
public getRoleOptions(projectId: string): void {
|
||||
this.mgmtService.SearchProjectRoles(projectId, 100, 0).then(resp => {
|
||||
this.projectRoleOptions = resp.toObject().resultList;
|
||||
this.mgmtService.listProjectRoles(projectId, 100, 0).then(resp => {
|
||||
this.projectRoleOptions = resp.resultList;
|
||||
});
|
||||
}
|
||||
|
||||
public getMemberRoleOptions(): void {
|
||||
this.mgmtService.GetProjectGrantMemberRoles().then(resp => {
|
||||
this.memberRoleOptions = resp.toObject().rolesList;
|
||||
this.mgmtService.listProjectGrantMemberRoles().then(resp => {
|
||||
this.memberRoleOptions = resp.resultList;
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
updateRoles(selectionChange: MatSelectChange): void {
|
||||
this.mgmtService.UpdateProjectGrant(this.grant.id, this.grant.projectId, selectionChange.value)
|
||||
.then((newgrant: ProjectGrant) => {
|
||||
this.mgmtService.updateProjectGrant(this.grant.grantId, this.grant.projectId, selectionChange.value)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.GRANTUPDATED');
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -120,7 +116,7 @@ export class ProjectGrantDetailComponent {
|
||||
|
||||
public removeProjectMemberSelection(): void {
|
||||
Promise.all(this.selection.map(member => {
|
||||
return this.mgmtService.RemoveProjectGrantMember(this.grant.projectId, this.grant.id, member.userId).then(() => {
|
||||
return this.mgmtService.removeProjectGrantMember(this.grant.projectId, this.grant.grantId, member.userId).then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERREMOVED', true);
|
||||
setTimeout(() => {
|
||||
this.changePage.emit();
|
||||
@@ -132,11 +128,11 @@ export class ProjectGrantDetailComponent {
|
||||
}
|
||||
|
||||
public async openAddMember(): Promise<any> {
|
||||
const keysList = (await this.mgmtService.GetProjectGrantMemberRoles()).toObject();
|
||||
const keysList = (await this.mgmtService.listProjectGrantMemberRoles());
|
||||
|
||||
const dialogRef = this.dialog.open(ProjectGrantMembersCreateDialogComponent, {
|
||||
data: {
|
||||
roleKeysList: keysList.rolesList,
|
||||
roleKeysList: keysList.resultList,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
@@ -144,9 +140,9 @@ export class ProjectGrantDetailComponent {
|
||||
dialogRef.afterClosed().subscribe((dataToAdd: ProjectGrantMembersCreateDialogExportType) => {
|
||||
if (dataToAdd) {
|
||||
Promise.all(dataToAdd.userIds.map((userid: string) => {
|
||||
return this.mgmtService.AddProjectGrantMember(
|
||||
return this.mgmtService.addProjectGrantMember(
|
||||
this.grant.projectId,
|
||||
this.grant.id,
|
||||
this.grant.grantId,
|
||||
userid,
|
||||
dataToAdd.rolesKeyList,
|
||||
);
|
||||
@@ -162,9 +158,9 @@ export class ProjectGrantDetailComponent {
|
||||
});
|
||||
}
|
||||
|
||||
updateMemberRoles(member: ProjectGrantMember.AsObject, selectionChange: MatSelectChange): void {
|
||||
this.mgmtService.ChangeProjectGrantMember(this.grant.projectId, this.grant.id, member.userId, selectionChange.value)
|
||||
.then((_: ProjectGrantMember) => {
|
||||
updateMemberRoles(member: Member.AsObject, selectionChange: MatSelectChange): void {
|
||||
this.mgmtService.updateProjectGrantMember(this.grant.projectId, this.grant.grantId, member.userId, selectionChange.value)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERCHANGED', true);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UserView } from 'src/app/proto/generated/management_pb';
|
||||
import { User } from 'src/app/proto/generated/zitadel/user_pb';
|
||||
|
||||
export interface ProjectGrantMembersCreateDialogExportType {
|
||||
userIds: string[];
|
||||
@@ -22,7 +22,7 @@ export class ProjectGrantMembersCreateDialogComponent {
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) { }
|
||||
|
||||
public selectUsers(users: UserView.AsObject[]): void {
|
||||
public selectUsers(users: User.AsObject[]): void {
|
||||
this.userIds = users.map(user => user.id);
|
||||
}
|
||||
|
||||
|
||||
+9
-10
@@ -2,7 +2,7 @@ import { DataSource } from '@angular/cdk/collections';
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { catchError, finalize, map } from 'rxjs/operators';
|
||||
import { ProjectMember } from 'src/app/proto/generated/management_pb';
|
||||
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
|
||||
/**
|
||||
@@ -10,11 +10,11 @@ import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
* encapsulate all logic for fetching and manipulating the displayed data
|
||||
* (including sorting, pagination, and filtering).
|
||||
*/
|
||||
export class ProjectGrantMembersDataSource extends DataSource<ProjectMember.AsObject> {
|
||||
export class ProjectGrantMembersDataSource extends DataSource<Member.AsObject> {
|
||||
public totalResult: number = 0;
|
||||
public viewTimestamp!: Timestamp.AsObject;
|
||||
|
||||
public membersSubject: BehaviorSubject<ProjectMember.AsObject[]> = new BehaviorSubject<ProjectMember.AsObject[]>([]);
|
||||
public membersSubject: BehaviorSubject<Member.AsObject[]> = new BehaviorSubject<Member.AsObject[]>([]);
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
|
||||
@@ -28,15 +28,14 @@ export class ProjectGrantMembersDataSource extends DataSource<ProjectMember.AsOb
|
||||
|
||||
this.loadingSubject.next(true);
|
||||
|
||||
from(this.mgmtService.SearchProjectGrantMembers(projectId,
|
||||
from(this.mgmtService.listProjectGrantMembers(projectId,
|
||||
grantId, pageSize, offset)).pipe(
|
||||
map(resp => {
|
||||
const response = resp.toObject();
|
||||
this.totalResult = response.totalResult;
|
||||
if (response.viewTimestamp) {
|
||||
this.viewTimestamp = response.viewTimestamp;
|
||||
this.totalResult = resp.details?.totalResult || 0;
|
||||
if (resp.details?.viewTimestamp) {
|
||||
this.viewTimestamp = resp.details?.viewTimestamp;
|
||||
}
|
||||
return response.resultList;
|
||||
return resp.resultList;
|
||||
}),
|
||||
catchError(() => of([])),
|
||||
finalize(() => this.loadingSubject.next(false)),
|
||||
@@ -51,7 +50,7 @@ export class ProjectGrantMembersDataSource extends DataSource<ProjectMember.AsOb
|
||||
* the returned stream emits new items.
|
||||
* @returns A stream of the items to be rendered.
|
||||
*/
|
||||
public connect(): Observable<ProjectMember.AsObject[]> {
|
||||
public connect(): Observable<Member.AsObject[]> {
|
||||
return this.membersSubject.asObservable();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user