diff --git a/console/src/app/app-routing.module.ts b/console/src/app/app-routing.module.ts
index 77b867b51b..a7ec050286 100644
--- a/console/src/app/app-routing.module.ts
+++ b/console/src/app/app-routing.module.ts
@@ -55,11 +55,28 @@ const routes: Routes = [
roles: ['org.read'],
},
},
+
+ {
+ path: 'grant-create/project/:projectid/grant/:grantid',
+ loadChildren: () => import('src/app/pages/user-grant-create/user-grant-create.module')
+ .then(m => m.UserGrantCreateModule),
+ },
+ {
+ path: 'grant-create/project/:projectid',
+ loadChildren: () => import('src/app/pages/user-grant-create/user-grant-create.module')
+ .then(m => m.UserGrantCreateModule),
+ },
+ {
+ path: 'grant-create/user/:userid',
+ loadChildren: () => import('src/app/pages/user-grant-create/user-grant-create.module')
+ .then(m => m.UserGrantCreateModule),
+ },
{
path: 'grant-create',
loadChildren: () => import('src/app/pages/user-grant-create/user-grant-create.module')
.then(m => m.UserGrantCreateModule),
},
+
{
path: 'signedout',
loadChildren: () => import('./pages/signedout/signedout.module').then(m => m.SignedoutModule),
diff --git a/console/src/app/app.module.ts b/console/src/app/app.module.ts
index 1d49a5a55d..c27d11e188 100644
--- a/console/src/app/app.module.ts
+++ b/console/src/app/app.module.ts
@@ -103,7 +103,7 @@ export let authConfig = {
MatMenuModule,
MatSnackBarModule,
AvatarModule,
- ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
+ ServiceWorkerModule.register('ngsw-config.json', { enabled: environment.production }),
],
providers: [
ThemeService,
diff --git a/console/src/app/modules/accounts-card/accounts-card.component.html b/console/src/app/modules/accounts-card/accounts-card.component.html
index 6d8b93598e..8ec771c0dd 100644
--- a/console/src/app/modules/accounts-card/accounts-card.component.html
+++ b/console/src/app/modules/accounts-card/accounts-card.component.html
@@ -11,8 +11,8 @@
-
+
diff --git a/console/src/app/modules/accounts-card/accounts-card.component.ts b/console/src/app/modules/accounts-card/accounts-card.component.ts
index d7860efce9..b8a15ea6c5 100644
--- a/console/src/app/modules/accounts-card/accounts-card.component.ts
+++ b/console/src/app/modules/accounts-card/accounts-card.component.ts
@@ -17,10 +17,7 @@ export class AccountsCardComponent implements OnInit {
@Output() public close: EventEmitter
= new EventEmitter();
public users: UserSessionView.AsObject[] = [];
public loadingUsers: boolean = false;
- constructor(public authService: AuthService, private router: Router, private userService: AuthUserService) { }
-
- public ngOnInit(): void {
- this.loadingUsers = true;
+ constructor(public authService: AuthService, private router: Router, private userService: AuthUserService) {
this.userService.getMyUserSessions().then(sessions => {
this.users = sessions.toObject().userSessionsList;
@@ -33,6 +30,10 @@ export class AccountsCardComponent implements OnInit {
});
}
+ public ngOnInit(): void {
+ this.loadingUsers = true;
+ }
+
public editUserProfile(): void {
this.router.navigate(['user/me']);
this.close.emit();
diff --git a/console/src/app/modules/changes/changes.component.ts b/console/src/app/modules/changes/changes.component.ts
index 55d503df4c..406dbc69e4 100644
--- a/console/src/app/modules/changes/changes.component.ts
+++ b/console/src/app/modules/changes/changes.component.ts
@@ -23,12 +23,10 @@ export class ChangesComponent implements OnInit {
@Input() public sortDirectionAsc: boolean = true;
public bottom: boolean = false;
- // Source data
private _done: BehaviorSubject = new BehaviorSubject(false);
private _loading: BehaviorSubject = new BehaviorSubject(false);
private _data: BehaviorSubject = new BehaviorSubject([]);
- // Observable data
loading: Observable = this._loading.asObservable();
public data!: Observable;
public changes!: Changes.AsObject;
diff --git a/console/src/app/modules/meta-layout/meta-layout.component.ts b/console/src/app/modules/meta-layout/meta-layout.component.ts
index f6a6bf710f..f96b778b75 100644
--- a/console/src/app/modules/meta-layout/meta-layout.component.ts
+++ b/console/src/app/modules/meta-layout/meta-layout.component.ts
@@ -19,6 +19,4 @@ export class MetaLayoutComponent {
.pipe(map(result => {
return result.matches;
}));
-
-
}
diff --git a/console/src/app/modules/project-contributors/project-contributors.component.html b/console/src/app/modules/project-contributors/project-contributors.component.html
index a33ea92402..e4934c6d4d 100644
--- a/console/src/app/modules/project-contributors/project-contributors.component.html
+++ b/console/src/app/modules/project-contributors/project-contributors.component.html
@@ -7,10 +7,8 @@
-
diff --git a/console/src/app/modules/project-contributors/project-contributors.component.scss b/console/src/app/modules/project-contributors/project-contributors.component.scss
index 79b450fb88..75a5859de1 100644
--- a/console/src/app/modules/project-contributors/project-contributors.component.scss
+++ b/console/src/app/modules/project-contributors/project-contributors.component.scss
@@ -30,11 +30,16 @@
align-items: center;
.avatar-circle {
- float: left;
- margin: 0 8px 0 -15px;
- height: 32px;
- width: 32px;
- border-radius: 50%;
+ float: left;
+ margin: 0 8px 0 -15px;
+ height: 32px;
+ width: 32px;
+ border-radius: 50%;
+ &:not(:first-child) {
+ -webkit-box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ -moz-box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ }
}
.add-img {
diff --git a/console/src/app/modules/project-members/project-members.component.ts b/console/src/app/modules/project-members/project-members.component.ts
index 55cb6a9d26..efc10295de 100644
--- a/console/src/app/modules/project-members/project-members.component.ts
+++ b/console/src/app/modules/project-members/project-members.component.ts
@@ -38,7 +38,6 @@ export class ProjectMembersComponent implements AfterViewInit {
private route: ActivatedRoute) {
this.route.data.pipe(take(1)).subscribe(data => {
this.projectType = data.type;
- console.log(data);
this.getRoleOptions();
@@ -156,6 +155,5 @@ export class ProjectMembersComponent implements AfterViewInit {
}).catch(error => {
this.toast.showError(error.message);
});
-
}
}
diff --git a/console/src/app/modules/project-roles/project-roles.module.ts b/console/src/app/modules/project-roles/project-roles.module.ts
index 36914707ec..b1de8f3416 100644
--- a/console/src/app/modules/project-roles/project-roles.module.ts
+++ b/console/src/app/modules/project-roles/project-roles.module.ts
@@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
+import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
@@ -28,6 +29,7 @@ import { ProjectRolesComponent } from './project-roles.component';
HasRoleModule,
MatTableModule,
MatPaginatorModule,
+ MatDialogModule,
MatFormFieldModule,
FormsModule,
ReactiveFormsModule,
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 3cea1f8e73..9a88fe96a1 100644
--- a/console/src/app/modules/user-grants/user-grants-datasource.ts
+++ b/console/src/app/modules/user-grants/user-grants-datasource.ts
@@ -1,9 +1,21 @@
import { DataSource } from '@angular/cdk/collections';
import { BehaviorSubject, from, Observable, of } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';
-import { UserGrant, UserGrantSearchKey, UserGrantSearchQuery } from 'src/app/proto/generated/management_pb';
+import {
+ UserGrant,
+ UserGrantSearchKey,
+ UserGrantSearchQuery,
+ UserGrantSearchResponse,
+} from 'src/app/proto/generated/management_pb';
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
+export enum UserGrantContext {
+ // AUTHUSER = 'authuser',
+ USER = 'user',
+ OWNED_PROJECT = 'owned',
+ GRANTED_PROJECT = 'granted',
+}
+
export class UserGrantsDataSource extends DataSource {
public totalResult: number = 0;
public grantsSubject: BehaviorSubject = new BehaviorSubject([]);
@@ -14,17 +26,54 @@ export class UserGrantsDataSource extends DataSource {
super();
}
- public loadGrants(filter: UserGrantSearchKey, userId: string, pageIndex: number, pageSize: number): void {
+ public loadGrants(
+ context: UserGrantContext,
+ pageIndex: number,
+ pageSize: number,
+ data: {
+ projectId?: string;
+ grantId?: string;
+ userId?: string;
+ },
+ queries?: UserGrantSearchQuery[],
+ ): void {
const offset = pageIndex * pageSize;
this.loadingSubject.next(true);
- const query = new UserGrantSearchQuery();
- query.setKey(filter);
- query.setValue(userId);
+ switch (context) {
+ case UserGrantContext.USER:
+ if (data && data.userId) {
+ const userfilter = new UserGrantSearchQuery();
+ userfilter.setKey(UserGrantSearchKey.USERGRANTSEARCHKEY_USER_ID);
+ userfilter.setValue(data.userId);
+ if (queries) {
+ queries.push(userfilter);
+ } else {
+ queries = [userfilter];
+ }
- const queries: UserGrantSearchQuery[] = [query];
- from(this.userService.SearchUserGrants(10, 0, queries)).pipe(
+ const promise = this.userService.SearchUserGrants(10, 0, queries);
+ this.loadResponse(promise);
+ }
+ break;
+ case UserGrantContext.OWNED_PROJECT:
+ if (data && data.projectId) {
+ const promise1 = this.userService.SearchProjectUserGrants(data.projectId, 10, 0, queries);
+ this.loadResponse(promise1);
+ }
+ break;
+ case UserGrantContext.GRANTED_PROJECT:
+ if (data && data.grantId) {
+ const promise2 = this.userService.SearchProjectGrantUserGrants(data.grantId, 10, 0, queries);
+ this.loadResponse(promise2);
+ }
+ break;
+ }
+ }
+
+ private loadResponse(promise: Promise): void {
+ from(promise).pipe(
map(resp => {
this.totalResult = resp.toObject().totalResult;
console.log(resp.toObject().resultList);
diff --git a/console/src/app/modules/user-grants/user-grants.component.html b/console/src/app/modules/user-grants/user-grants.component.html
index 6aefd7006c..f3aa5212f0 100644
--- a/console/src/app/modules/user-grants/user-grants.component.html
+++ b/console/src/app/modules/user-grants/user-grants.component.html
@@ -11,11 +11,11 @@
+ mat-raised-button [routerLink]="routerLink">
add{{ 'GRANTS.ADD_BTN' | translate }}
@@ -86,7 +86,7 @@
-
+
{{ 'PROJECT.GRANT.TITLE' | translate }}
diff --git a/console/src/app/modules/user-grants/user-grants.component.ts b/console/src/app/modules/user-grants/user-grants.component.ts
index 02b933a308..a46a202478 100644
--- a/console/src/app/modules/user-grants/user-grants.component.ts
+++ b/console/src/app/modules/user-grants/user-grants.component.ts
@@ -4,12 +4,12 @@ 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, UserGrant, UserGrantSearchKey } from 'src/app/proto/generated/management_pb';
+import { ProjectGrant, ProjectRoleView, UserGrant } from 'src/app/proto/generated/management_pb';
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
import { ProjectService } from 'src/app/services/project.service';
import { ToastService } from 'src/app/services/toast.service';
-import { UserGrantsDataSource } from './user-grants-datasource';
+import { UserGrantContext, UserGrantsDataSource } from './user-grants-datasource';
@Component({
selector: 'app-user-grants',
@@ -17,8 +17,9 @@ import { UserGrantsDataSource } from './user-grants-datasource';
styleUrls: ['./user-grants.component.scss'],
})
export class UserGrantsComponent implements OnInit, AfterViewInit {
- @Input() filterValue: string = '';
- @Input() filter: UserGrantSearchKey = UserGrantSearchKey.USERGRANTSEARCHKEY_USER_ID;
+ // @Input() filterValue: string = '';
+ // @Input() filter: UserGrantSearchKey = UserGrantSearchKey.USERGRANTSEARCHKEY_USER_ID;
+ @Input() context: UserGrantContext = UserGrantContext.USER;
public grants: UserGrant.AsObject[] = [];
public dataSource!: UserGrantsDataSource;
@@ -29,7 +30,12 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
@Input() allowCreate: boolean = false;
@Input() allowDelete: boolean = false;
+ @Input() userId: string = '';
+ @Input() projectId: string = '';
+ @Input() grantId: string = '';
+
public roleOptions: ProjectRoleView.AsObject[] = [];
+ public routerLink: any = [''];
constructor(
private userService: MgmtUserService,
@@ -44,11 +50,35 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
public ngOnInit(): void {
this.dataSource = new UserGrantsDataSource(this.userService);
- this.dataSource.loadGrants(this.filter, this.filterValue, 0, 25);
+ const data = {
+ projectId: this.projectId,
+ grantId: this.grantId,
+ userId: this.userId,
+ };
+ console.log(this.context);
- if (this.filter === UserGrantSearchKey.USERGRANTSEARCHKEY_PROJECT_ID) {
- this.getRoleOptions(this.filterValue);
+ switch (this.context) {
+ case UserGrantContext.OWNED_PROJECT:
+ if (this.projectId) {
+ this.getRoleOptions(this.projectId);
+ this.routerLink = ['/grant-create', 'project', this.projectId];
+ }
+ break;
+ case UserGrantContext.GRANTED_PROJECT:
+ if (data && data.grantId) {
+ this.routerLink = ['/grant-create', 'project', this.projectId, 'grant', this.grantId];
+ }
+ break;
+ case UserGrantContext.USER:
+ if (this.userId) {
+ this.routerLink = ['/grant-create', 'user', this.userId];
+ }
+ break;
+ default:
+ this.routerLink = ['/grant-create'];
}
+ console.log(data);
+ this.dataSource.loadGrants(this.context, 0, 25, data);
}
public ngAfterViewInit(): void {
@@ -61,10 +91,13 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
private loadGrantsPage(): void {
this.dataSource.loadGrants(
- this.filter,
- this.filterValue,
+ this.context,
this.paginator.pageIndex,
this.paginator.pageSize,
+ {
+ projectId: this.projectId,
+ grantId: this.grantId,
+ },
);
}
@@ -81,7 +114,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
}
public loadRoleOptions(projectId: string): void {
- if (this.filter === UserGrantSearchKey.USERGRANTSEARCHKEY_USER_ID) {
+ if (this.context === UserGrantContext.USER) {
this.getRoleOptions(projectId);
}
}
@@ -103,4 +136,13 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
this.toast.showError(error.message);
});
}
+
+ deleteGrantSelection(): void {
+ this.userService.BulkRemoveUserGrant(this.selection.selected.map(grant => grant.id)).then(() => {
+ this.toast.showInfo('Grants deleted');
+ this.loadGrantsPage();
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ }
}
diff --git a/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.html b/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.html
index d3b415705c..ff813d2b05 100644
--- a/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.html
+++ b/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.html
@@ -15,7 +15,7 @@
-
diff --git a/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.ts b/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.ts
index 64135bff17..ab19803a3c 100644
--- a/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.ts
+++ b/console/src/app/pages/granted-projects/granted-project-detail/granted-project-detail.component.ts
@@ -6,6 +6,7 @@ import { ActivatedRoute, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { ChangeType } from 'src/app/modules/changes/changes.component';
+import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
import {
Application,
ApplicationSearchResponse,
@@ -58,6 +59,7 @@ export class GrantedProjectDetailComponent implements OnInit, OnDestroy {
public isZitadel: boolean = false;
+ public userGrantContext: UserGrantContext = UserGrantContext.GRANTED_PROJECT;
public userGrantSearchKey: UserGrantSearchKey = UserGrantSearchKey.USERGRANTSEARCHKEY_PROJECT_ID;
constructor(
diff --git a/console/src/app/pages/granted-projects/granted-projects.module.ts b/console/src/app/pages/granted-projects/granted-projects.module.ts
index 89feee4bc5..1d1b62285a 100644
--- a/console/src/app/pages/granted-projects/granted-projects.module.ts
+++ b/console/src/app/pages/granted-projects/granted-projects.module.ts
@@ -3,10 +3,7 @@ import { HttpClient } from '@angular/common/http';
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
-import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCheckboxModule } from '@angular/material/checkbox';
-import { MatChipsModule } from '@angular/material/chips';
-import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
@@ -29,10 +26,7 @@ import { ChangesModule } from '../../modules/changes/changes.module';
import { MetaLayoutModule } from '../../modules/meta-layout/meta-layout.module';
import { ProjectContributorsModule } from '../../modules/project-contributors/project-contributors.module';
import { ProjectRolesModule } from '../../modules/project-roles/project-roles.module';
-import { SearchUserAutocompleteModule } from '../../modules/search-user-autocomplete/search-user-autocomplete.module';
import { PipesModule } from '../../pipes/pipes.module';
-import { OrgContributorsModule } from '../orgs/org-contributors/org-contributors.module';
-import { UserListModule } from '../user-list/user-list.module';
import { GrantedProjectDetailComponent } from './granted-project-detail/granted-project-detail.component';
import { GrantedProjectGridComponent } from './granted-project-grid/granted-project-grid.component';
import { GrantedProjectListComponent } from './granted-project-list/granted-project-list.component';
@@ -57,29 +51,23 @@ import { GrantedProjectsComponent } from './granted-projects.component';
HasRoleModule,
MatTableModule,
MatPaginatorModule,
+ MatMenuModule,
MatFormFieldModule,
MatInputModule,
ChangesModule,
- UserListModule,
- MatMenuModule,
- MatChipsModule,
MatIconModule,
MatSelectModule,
MatButtonModule,
MatProgressSpinnerModule,
MetaLayoutModule,
MatProgressBarModule,
- MatDialogModule,
- MatButtonToggleModule,
MatTabsModule,
ProjectRolesModule,
- SearchUserAutocompleteModule,
MatCheckboxModule,
CardModule,
MatTooltipModule,
MatSortModule,
PipesModule,
- OrgContributorsModule,
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
diff --git a/console/src/app/pages/iam/iam-contributors/iam-contributors.component.scss b/console/src/app/pages/iam/iam-contributors/iam-contributors.component.scss
index 1d9b82ea22..b9ecafc16d 100644
--- a/console/src/app/pages/iam/iam-contributors/iam-contributors.component.scss
+++ b/console/src/app/pages/iam/iam-contributors/iam-contributors.component.scss
@@ -30,11 +30,16 @@
align-items: center;
.avatar-img, .avatar-circle {
- float: left;
- margin: 0 8px 0 -15px;
- height: 32px;
- width: 32px;
- border-radius: 50%;
+ float: left;
+ margin: 0 8px 0 -15px;
+ height: 32px;
+ width: 32px;
+ border-radius: 50%;
+ &:not(:first-child) {
+ -webkit-box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ -moz-box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ }
}
.add-img {
diff --git a/console/src/app/pages/iam/iam-views/iam-views.component.ts b/console/src/app/pages/iam/iam-views/iam-views.component.ts
index 1455838ffd..c2de7220f8 100644
--- a/console/src/app/pages/iam/iam-views/iam-views.component.ts
+++ b/console/src/app/pages/iam/iam-views/iam-views.component.ts
@@ -39,6 +39,7 @@ export class IamViewsComponent {
).subscribe(views => {
this.dataSource = new MatTableDataSource(views);
this.dataSource.paginator = this.paginator;
+ this.dataSource.sort = this.sort;
});
}
diff --git a/console/src/app/pages/iam/iam.component.html b/console/src/app/pages/iam/iam.component.html
index 43a267cd66..b8e7ccd6e5 100644
--- a/console/src/app/pages/iam/iam.component.html
+++ b/console/src/app/pages/iam/iam.component.html
@@ -9,17 +9,7 @@
-
-
-
-
\ No newline at end of file
diff --git a/console/src/app/pages/iam/iam.component.ts b/console/src/app/pages/iam/iam.component.ts
index 89c311c823..3e5d5a7a37 100644
--- a/console/src/app/pages/iam/iam.component.ts
+++ b/console/src/app/pages/iam/iam.component.ts
@@ -1,17 +1,9 @@
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
@Component({
selector: 'app-iam',
templateUrl: './iam.component.html',
styleUrls: ['./iam.component.scss'],
})
-export class IamComponent implements OnInit {
-
- constructor() {
-
- }
-
- ngOnInit(): void {
- }
-
+export class IamComponent {
}
diff --git a/console/src/app/pages/orgs/org-contributors/org-contributors.component.scss b/console/src/app/pages/orgs/org-contributors/org-contributors.component.scss
index 1d9b82ea22..2b3edbf6ad 100644
--- a/console/src/app/pages/orgs/org-contributors/org-contributors.component.scss
+++ b/console/src/app/pages/orgs/org-contributors/org-contributors.component.scss
@@ -35,6 +35,11 @@
height: 32px;
width: 32px;
border-radius: 50%;
+ &:not(:first-child) {
+ -webkit-box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ -moz-box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ box-shadow: -9px 0px 20px -6px rgba(0,0,0,0.75);
+ }
}
.add-img {
diff --git a/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.html b/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.html
index ed4cfab060..e8b257015b 100644
--- a/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.html
+++ b/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.html
@@ -78,7 +78,7 @@
-
diff --git a/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.ts b/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.ts
index 6cc617aedf..2a73e9a77d 100644
--- a/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.ts
+++ b/console/src/app/pages/owned-projects/owned-project-detail/owned-project-detail.component.ts
@@ -6,6 +6,7 @@ import { ActivatedRoute, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { ChangeType } from 'src/app/modules/changes/changes.component';
+import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
import {
Application,
ApplicationSearchResponse,
@@ -59,6 +60,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
public isZitadel: boolean = false;
public userGrantSearchKey: UserGrantSearchKey = UserGrantSearchKey.USERGRANTSEARCHKEY_PROJECT_ID;
+ public userGrantContext: UserGrantContext = UserGrantContext.OWNED_PROJECT;
constructor(
public translate: TranslateService,
diff --git a/console/src/app/pages/owned-projects/owned-projects.component.spec.ts b/console/src/app/pages/owned-projects/owned-projects.component.spec.ts
index a33e1cc85a..6b6dfb2dca 100644
--- a/console/src/app/pages/owned-projects/owned-projects.component.spec.ts
+++ b/console/src/app/pages/owned-projects/owned-projects.component.spec.ts
@@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { ProjectsComponent } from './projects.component';
+import { OwnedProjectsComponent } from './owned-projects.component';
-describe('ProjectsComponent', () => {
- let component: ProjectsComponent;
- let fixture: ComponentFixture;
+describe('OwnedProjectComponent', () => {
+ let component: OwnedProjectsComponent;
+ let fixture: ComponentFixture;
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ProjectsComponent],
+ declarations: [OwnedProjectsComponent],
})
.compileComponents();
}));
beforeEach(() => {
- fixture = TestBed.createComponent(ProjectsComponent);
+ fixture = TestBed.createComponent(OwnedProjectsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/console/src/app/pages/owned-projects/owned-projects.module.ts b/console/src/app/pages/owned-projects/owned-projects.module.ts
index c658f1b141..1e7d69a1e6 100644
--- a/console/src/app/pages/owned-projects/owned-projects.module.ts
+++ b/console/src/app/pages/owned-projects/owned-projects.module.ts
@@ -3,10 +3,8 @@ import { HttpClient } from '@angular/common/http';
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
-import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
-import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
@@ -14,14 +12,13 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatSelectModule } from '@angular/material/select';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { AvatarModule } from 'src/app/modules/avatar/avatar.module';
-import { ProjectGrantMembersModule } from 'src/app/modules/project-grant-members/project-grant-members.module';
+import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.module';
import { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
import { HttpLoaderFactory } from '../../app.module';
@@ -30,10 +27,7 @@ import { CardModule } from '../../modules/card/card.module';
import { ChangesModule } from '../../modules/changes/changes.module';
import { MetaLayoutModule } from '../../modules/meta-layout/meta-layout.module';
import { ProjectContributorsModule } from '../../modules/project-contributors/project-contributors.module';
-import { ProjectRolesModule } from '../../modules/project-roles/project-roles.module';
-import { SearchUserAutocompleteModule } from '../../modules/search-user-autocomplete/search-user-autocomplete.module';
import { PipesModule } from '../../pipes/pipes.module';
-import { OrgContributorsModule } from '../orgs/org-contributors/org-contributors.module';
import { UserListModule } from '../user-list/user-list.module';
import { OwnedProjectDetailComponent } from './owned-project-detail/owned-project-detail.component';
import { OwnedProjectGridComponent } from './owned-project-grid/owned-project-grid.component';
@@ -59,7 +53,6 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen
OwnedProjectsRoutingModule,
UserGrantsModule,
ProjectContributorsModule,
- ProjectGrantMembersModule,
FormsModule,
TranslateModule,
AvatarModule,
@@ -74,22 +67,17 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen
MatMenuModule,
MatChipsModule,
MatIconModule,
- MatSelectModule,
MatButtonModule,
MatProgressSpinnerModule,
MetaLayoutModule,
MatProgressBarModule,
- MatDialogModule,
- MatButtonToggleModule,
- MatTabsModule,
ProjectRolesModule,
- SearchUserAutocompleteModule,
+ MatTabsModule,
MatCheckboxModule,
CardModule,
MatTooltipModule,
MatSortModule,
PipesModule,
- OrgContributorsModule,
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
diff --git a/console/src/app/pages/owned-projects/project-grant-detail/project-grant-detail.module.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-detail.module.ts
index ac10171f11..ea075c7b35 100644
--- a/console/src/app/pages/owned-projects/project-grant-detail/project-grant-detail.module.ts
+++ b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-detail.module.ts
@@ -13,10 +13,10 @@ import { MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
-import { ProjectGrantMembersModule } from 'src/app/modules/project-grant-members/project-grant-members.module';
import { ProjectGrantDetailRoutingModule } from './project-grant-detail-routing.module';
import { ProjectGrantDetailComponent } from './project-grant-detail.component';
+import { ProjectGrantMembersModule } from './project-grant-members/project-grant-members.module';
@NgModule({
diff --git a/console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.html b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.html
similarity index 100%
rename from console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.html
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.html
diff --git a/console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.scss b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.scss
similarity index 100%
rename from console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.scss
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.scss
diff --git a/console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.spec.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.spec.ts
similarity index 100%
rename from console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.spec.ts
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.spec.ts
diff --git a/console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.ts
similarity index 100%
rename from console/src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.ts
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component.ts
diff --git a/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.module.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.module.ts
new file mode 100644
index 0000000000..c39fcbb047
--- /dev/null
+++ b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.module.ts
@@ -0,0 +1,30 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSelectModule } from '@angular/material/select';
+import { TranslateModule } from '@ngx-translate/core';
+import { SearchUserAutocompleteModule } from 'src/app/modules/search-user-autocomplete/search-user-autocomplete.module';
+
+import { ProjectGrantMembersCreateDialogComponent } from './project-grant-members-create-dialog.component';
+
+@NgModule({
+ declarations: [ProjectGrantMembersCreateDialogComponent],
+ imports: [
+ CommonModule,
+ FormsModule,
+ MatDialogModule,
+ MatButtonModule,
+ TranslateModule,
+ MatSelectModule,
+ MatFormFieldModule,
+ SearchUserAutocompleteModule,
+ ],
+ entryComponents: [
+ ProjectGrantMembersCreateDialogComponent,
+ ],
+})
+export class ProjectGrantMembersCreateDialogModule { }
+
diff --git a/console/src/app/modules/project-grant-members/project-grant-members-datasource.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-datasource.ts
similarity index 94%
rename from console/src/app/modules/project-grant-members/project-grant-members-datasource.ts
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-datasource.ts
index 926826b9d7..6c8228f14f 100644
--- a/console/src/app/modules/project-grant-members/project-grant-members-datasource.ts
+++ b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members-datasource.ts
@@ -19,8 +19,8 @@ export class ProjectGrantMembersDataSource extends DataSource
{{ 'PROJECT.MEMBER.ROLES' | translate }} |
-
-
- {{ 'ROLES.'+role | translate }}
- |
-
-
-
- |
-
-
-
-
-
-
+ |
+
+ {{ 'PROJECT.GRANT.TITLE' | translate }}
+
+
+ {{ 'ROLES.'+role | translate }}
+
+
+
|
diff --git a/console/src/app/modules/project-grant-members/project-grant-members.component.scss b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.scss
similarity index 100%
rename from console/src/app/modules/project-grant-members/project-grant-members.component.scss
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.scss
diff --git a/console/src/app/modules/project-grant-members/project-grant-members.component.spec.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.spec.ts
similarity index 100%
rename from console/src/app/modules/project-grant-members/project-grant-members.component.spec.ts
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.spec.ts
diff --git a/console/src/app/modules/project-grant-members/project-grant-members.component.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.ts
similarity index 75%
rename from console/src/app/modules/project-grant-members/project-grant-members.component.ts
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.ts
index 9b30e170e7..f91cb961c3 100644
--- a/console/src/app/modules/project-grant-members/project-grant-members.component.ts
+++ b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.component.ts
@@ -2,6 +2,7 @@ import { SelectionModel } from '@angular/cdk/collections';
import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
+import { MatSelectChange } from '@angular/material/select';
import { MatTable } from '@angular/material/table';
import { tap } from 'rxjs/operators';
import { ProjectMember, ProjectType } from 'src/app/proto/generated/management_pb';
@@ -35,17 +36,19 @@ export class ProjectGrantMembersComponent implements AfterViewInit, OnInit {
public displayedColumns: string[] = ['select', 'firstname', 'lastname', 'username', 'email', 'roles'];
public ProjectType: any = ProjectType;
+ public memberRoleOptions: string[] = [];
constructor(
private projectService: ProjectService,
private dialog: MatDialog,
private toast: ToastService,
- ) { }
+ ) {
+ this.dataSource = new ProjectGrantMembersDataSource(this.projectService);
+ this.getRoleOptions();
+ }
public ngOnInit(): void {
- this.dataSource = new ProjectGrantMembersDataSource(this.projectService);
- console.log(this.projectId);
- this.dataSource.loadMembers(this.projectId, this.grantId, 0, 25, 'asc');
+ this.dataSource.loadGrantMembers(this.projectId, this.grantId, 0, 25);
}
public ngAfterViewInit(): void {
@@ -56,14 +59,32 @@ export class ProjectGrantMembersComponent implements AfterViewInit, OnInit {
.subscribe();
}
+ public getRoleOptions(): void {
+ if (this.type === ProjectType.PROJECTTYPE_GRANTED) {
+ this.projectService.GetProjectGrantMemberRoles().then(resp => {
+ this.memberRoleOptions = resp.toObject().rolesList;
+ console.log(this.memberRoleOptions);
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ } else if (this.type === ProjectType.PROJECTTYPE_OWNED) {
+ this.projectService.GetProjectMemberRoles().then(resp => {
+ this.memberRoleOptions = resp.toObject().rolesList;
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ }
+ }
+
private loadMembersPage(): void {
- this.dataSource.loadMembers(
+ this.dataSource.loadGrantMembers(
this.projectId,
this.grantId,
this.paginator.pageIndex,
this.paginator.pageSize,
);
}
+
public removeProjectMemberSelection(): void {
Promise.all(this.selection.selected.map(member => {
return this.projectService.RemoveProjectGrantMember(this.projectId, this.grantId, member.userId).then(() => {
@@ -124,4 +145,15 @@ export class ProjectGrantMembersComponent implements AfterViewInit, OnInit {
}
});
}
+
+ updateRoles(member: ProjectMember.AsObject, selectionChange: MatSelectChange): void {
+ console.log(this.projectId, this.grantId, member.userId, selectionChange.value);
+ this.projectService.ChangeProjectGrantMember(this.projectId, this.grantId, member.userId, selectionChange.value)
+ .then((newmember: ProjectMember) => {
+ console.log(newmember.toObject());
+ this.toast.showInfo('Member updated!');
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ }
}
diff --git a/console/src/app/modules/project-grant-members/project-grant-members.module.ts b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.module.ts
similarity index 77%
rename from console/src/app/modules/project-grant-members/project-grant-members.module.ts
rename to console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.module.ts
index 6d1675d823..d8c3eff0e4 100644
--- a/console/src/app/modules/project-grant-members/project-grant-members.module.ts
+++ b/console/src/app/pages/owned-projects/project-grant-detail/project-grant-members/project-grant-members.module.ts
@@ -1,15 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
-import { MatChipsModule } from '@angular/material/chips';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
-import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
@@ -19,22 +16,19 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
+import { SearchUserAutocompleteModule } from 'src/app/modules/search-user-autocomplete/search-user-autocomplete.module';
-import { SearchUserAutocompleteModule } from '../search-user-autocomplete/search-user-autocomplete.module';
import {
- ProjectGrantMembersCreateDialogComponent,
-} from './project-grant-members-create-dialog/project-grant-members-create-dialog.component';
+ ProjectGrantMembersCreateDialogModule,
+} from './project-grant-members-create-dialog/project-grant-members-create-dialog.module';
import { ProjectGrantMembersComponent } from './project-grant-members.component';
@NgModule({
- declarations: [ProjectGrantMembersComponent, ProjectGrantMembersCreateDialogComponent],
+ declarations: [ProjectGrantMembersComponent],
imports: [
CommonModule,
- MatAutocompleteModule,
HasRoleModule,
RouterModule,
- MatChipsModule,
- MatMenuModule,
MatButtonModule,
MatCheckboxModule,
MatIconModule,
@@ -43,6 +37,7 @@ import { ProjectGrantMembersComponent } from './project-grant-members.component'
MatSelectModule,
MatTableModule,
SearchUserAutocompleteModule,
+ ProjectGrantMembersCreateDialogModule,
MatPaginatorModule,
MatSortModule,
MatTooltipModule,
diff --git a/console/src/app/pages/owned-projects/project-grants/project-grants.component.ts b/console/src/app/pages/owned-projects/project-grants/project-grants.component.ts
index 4211413a9a..abd7436514 100644
--- a/console/src/app/pages/owned-projects/project-grants/project-grants.component.ts
+++ b/console/src/app/pages/owned-projects/project-grants/project-grants.component.ts
@@ -5,10 +5,6 @@ import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatTable } from '@angular/material/table';
import { tap } from 'rxjs/operators';
-import {
- ProjectGrantMembersCreateDialogComponent,
- ProjectGrantMembersCreateDialogExportType,
-} from 'src/app/modules/project-grant-members/project-grant-members-create-dialog/project-grant-members-create-dialog.component';
import { ProjectGrant, ProjectMemberView } from 'src/app/proto/generated/management_pb';
import { ProjectService } from 'src/app/services/project.service';
import { ToastService } from 'src/app/services/toast.service';
@@ -75,35 +71,4 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
this.selection.clear() :
this.dataSource.grantsSubject.value.forEach(row => this.selection.select(row));
}
-
- public async addProjectGrantMember(grant: ProjectGrant.AsObject): Promise {
- const keysList = (await this.projectService.GetProjectGrantMemberRoles()).toObject();
- console.log(keysList);
-
- const dialogRef = this.dialog.open(ProjectGrantMembersCreateDialogComponent, {
- data: {
- roleKeysList: keysList.rolesList,
- },
- width: '400px',
- });
-
- dialogRef.afterClosed().subscribe((dataToAdd: ProjectGrantMembersCreateDialogExportType) => {
- console.log(dataToAdd);
- if (dataToAdd) {
- dataToAdd.userIds.forEach((userid: string) => {
- this.projectService.AddProjectGrantMember(
- this.projectId,
- grant.id,
- userid,
- dataToAdd.rolesKeyList,
- ).then(() => {
- this.toast.showInfo('Project Grant Member successfully added!');
- }).catch(error => {
- this.toast.showError(error.message);
- });
- });
-
- }
- });
- }
}
diff --git a/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.html b/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.html
index 1da19c8920..e2fd6e596a 100644
--- a/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.html
+++ b/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.html
@@ -33,80 +33,20 @@
-
-
-
-
+
+
{{ 'USER.PROFILE.PASSWORD' | translate }}
+
+
*********
+
+
+
{{ 'USER.EMAIL' | translate }}
@@ -166,9 +106,6 @@
-
@@ -188,36 +125,6 @@
-
-
diff --git a/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.scss b/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.scss
index cda88ccdac..4464061363 100644
--- a/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.scss
+++ b/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.scss
@@ -94,7 +94,7 @@ h1 {
flex-wrap: wrap;
.label, .name {
- margin-right: 1rem;
+ margin-right: 1rem;
}
.actions {
@@ -107,7 +107,7 @@ h1 {
.label {
flex: 1;
font-size: .9rem;
- color: #818a8a;
+ color: #8795a1;
}
mat-icon {
@@ -150,6 +150,20 @@ h1 {
.theme-card {
max-width: 300px;
}
+
+ .pwd-row {
+ display: flex;
+ align-items: center;
+
+ span {
+ flex: 1;
+ }
+
+ .title {
+ color: #8795a1;
+ font-size: 0.9rem;
+ }
+ }
}
.side {
diff --git a/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.ts b/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.ts
index 5e8c1a691b..418b68ee26 100644
--- a/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.ts
+++ b/console/src/app/pages/user-detail/auth-user-detail/auth-user-detail.component.ts
@@ -1,17 +1,15 @@
import { Component, OnDestroy } from '@angular/core';
-import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { AbstractControl, FormBuilder } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { ChangeType } from 'src/app/modules/changes/changes.component';
import { Gender, UserAddress, UserEmail, UserPhone, UserProfile, UserView } from 'src/app/proto/generated/auth_pb';
-import { PasswordComplexityPolicy } from 'src/app/proto/generated/management_pb';
import { AuthUserService } from 'src/app/services/auth-user.service';
import { OrgService } from 'src/app/services/org.service';
import { ToastService } from 'src/app/services/toast.service';
import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
-import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
function passwordConfirmValidator(c: AbstractControl): any {
if (!c.parent || !c) {
@@ -44,7 +42,6 @@ export class AuthUserDetailComponent implements OnDestroy {
public genders: Gender[] = [Gender.GENDER_MALE, Gender.GENDER_FEMALE, Gender.GENDER_DIVERSE];
public languages: string[] = ['de', 'en'];
- public passwordForm!: FormGroup;
private subscription: Subscription = new Subscription();
public emailEditState: boolean = false;
@@ -52,7 +49,6 @@ export class AuthUserDetailComponent implements OnDestroy {
public loading: boolean = false;
- public policy!: PasswordComplexityPolicy.AsObject;
public copied: string = '';
public ChangeType: any = ChangeType;
@@ -66,40 +62,6 @@ export class AuthUserDetailComponent implements OnDestroy {
private dialog: MatDialog,
private orgService: OrgService,
) {
- const validators: Validators[] = [Validators.required];
- this.orgService.GetPasswordComplexityPolicy().then(data => {
- this.policy = data.toObject();
- if (this.policy.minLength) {
- validators.push(Validators.minLength(this.policy.minLength));
- }
- if (this.policy.hasLowercase) {
- validators.push(lowerCaseValidator);
- }
- if (this.policy.hasUppercase) {
- validators.push(upperCaseValidator);
- }
- if (this.policy.hasNumber) {
- validators.push(numberValidator);
- }
- if (this.policy.hasSymbol) {
- validators.push(symbolValidator);
- }
-
- this.passwordForm = this.fb.group({
- currentPassword: ['', []],
- newPassword: ['', validators],
- confirmPassword: ['', [...validators, passwordConfirmValidator]],
- });
- }).catch(error => {
- this.toast.showError(error.message);
- console.error(error.message);
- this.passwordForm = this.fb.group({
- currentPassword: ['', []],
- newPassword: ['', validators],
- confirmPassword: ['', [...validators, passwordConfirmValidator]],
- });
- });
-
this.loading = true;
this.getData().then(() => {
this.loading = false;
@@ -136,19 +98,6 @@ export class AuthUserDetailComponent implements OnDestroy {
});
}
- public setPassword(): void {
- if (this.passwordForm.valid && this.currentPassword &&
- this.currentPassword.value &&
- this.newPassword && this.newPassword.value && this.newPassword.valid) {
- this.userService
- .ChangeMyPassword(this.currentPassword.value, this.newPassword.value).then((data: any) => {
- this.toast.showInfo('Password Set');
- }).catch(data => {
- this.toast.showError(data.message);
- });
- }
- }
-
public saveEmail(): void {
this.emailEditState = false;
@@ -163,11 +112,6 @@ export class AuthUserDetailComponent implements OnDestroy {
});
}
- public deletePhone(): void {
- this.user.phone = '';
- this.savePhone();
- }
-
public enterCode(): void {
const dialogRef = this.dialog.open(CodeDialogComponent, {
data: {
@@ -220,16 +164,6 @@ export class AuthUserDetailComponent implements OnDestroy {
});
}
- public get currentPassword(): AbstractControl | null {
- return this.passwordForm.get('currentPassword');
- }
- public get newPassword(): AbstractControl | null {
- return this.passwordForm.get('newPassword');
- }
- public get confirmPassword(): AbstractControl | null {
- return this.passwordForm.get('confirmPassword');
- }
-
private async getData(): Promise {
this.userService.GetMyUser().then(user => {
this.user = user.toObject();
diff --git a/console/src/app/pages/user-detail/password/password.component.html b/console/src/app/pages/user-detail/password/password.component.html
new file mode 100644
index 0000000000..625212b6ff
--- /dev/null
+++ b/console/src/app/pages/user-detail/password/password.component.html
@@ -0,0 +1,151 @@
+
+
+
+
+
+
{{ 'USER.PASSWORD.TITLE' | translate }}
+
{{ 'USER.PASSWORD.DESCRIPTION' | translate }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/console/src/app/pages/user-detail/password/password.component.scss b/console/src/app/pages/user-detail/password/password.component.scss
new file mode 100644
index 0000000000..b81fae7b54
--- /dev/null
+++ b/console/src/app/pages/user-detail/password/password.component.scss
@@ -0,0 +1,66 @@
+.container {
+ display: flex;
+ padding-bottom: 3rem;
+
+ .left {
+ width: 100px;
+ display: flex;
+ padding: 1rem;
+ justify-content: center;
+
+ a {
+ margin-top: .2rem;
+ }
+ }
+
+ .right {
+ flex: 1;
+ padding-top: 1rem;
+
+ .head {
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid #ffffff20;
+ margin-bottom: 2rem;
+ flex-wrap: wrap;
+
+ a {
+ display: block;
+ }
+
+ h1 {
+ font-size: 2rem;
+ margin-top: 0.2rem;
+ }
+
+ .desc {
+ width: 100%;
+ display: block;
+ font-size: .9rem;
+ color: #8795a1;
+ }
+ }
+ }
+}
+
+.content {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ margin: 0 -.5rem;
+
+ mat-form-field {
+ margin: 0 .5rem;
+ }
+
+ &.center {
+ align-items: center;
+ }
+}
+
+.submit-button {
+ margin-top: 100px;
+ display: block;
+ padding: 0.5rem 4rem;
+ border-radius: 0.5rem;
+}
\ No newline at end of file
diff --git a/console/src/app/pages/user-detail/password/password.component.spec.ts b/console/src/app/pages/user-detail/password/password.component.spec.ts
new file mode 100644
index 0000000000..7f3799a94b
--- /dev/null
+++ b/console/src/app/pages/user-detail/password/password.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PasswordComponent } from './password.component';
+
+describe('PasswordComponent', () => {
+ let component: PasswordComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [PasswordComponent],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PasswordComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/console/src/app/pages/user-detail/password/password.component.ts b/console/src/app/pages/user-detail/password/password.component.ts
new file mode 100644
index 0000000000..3beb6ab247
--- /dev/null
+++ b/console/src/app/pages/user-detail/password/password.component.ts
@@ -0,0 +1,137 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import { PasswordComplexityPolicy } from 'src/app/proto/generated/management_pb';
+import { AuthUserService } from 'src/app/services/auth-user.service';
+import { MgmtUserService } from 'src/app/services/mgmt-user.service';
+import { OrgService } from 'src/app/services/org.service';
+import { ToastService } from 'src/app/services/toast.service';
+
+import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
+
+function passwordConfirmValidator(c: AbstractControl): any {
+ if (!c.parent || !c) {
+ return;
+ }
+ const pwd = c.parent.get('password');
+ const cpwd = c.parent.get('confirmPassword');
+
+ if (!pwd || !cpwd) {
+ return;
+ }
+ if (pwd.value !== cpwd.value) {
+ return { invalid: true, notequal: 'Password is not equal' };
+ }
+}
+
+@Component({
+ selector: 'app-password',
+ templateUrl: './password.component.html',
+ styleUrls: ['./password.component.scss'],
+})
+export class PasswordComponent implements OnInit {
+ userId: string = '';
+
+ public policy!: PasswordComplexityPolicy.AsObject;
+ public passwordForm!: FormGroup;
+
+ constructor(
+ private orgService: OrgService,
+ activatedRoute: ActivatedRoute,
+ private fb: FormBuilder,
+ private userService: AuthUserService,
+ private mgmtUserService: MgmtUserService,
+ private toast: ToastService,
+ ) {
+
+ activatedRoute.params.subscribe(data => {
+ const { id } = data;
+ if (id) {
+ this.userId = id;
+ }
+
+ const validators: Validators[] = [Validators.required];
+ this.orgService.GetPasswordComplexityPolicy().then(complexity => {
+ this.policy = complexity.toObject();
+ if (this.policy.minLength) {
+ validators.push(Validators.minLength(this.policy.minLength));
+ }
+ if (this.policy.hasLowercase) {
+ validators.push(lowerCaseValidator);
+ }
+ if (this.policy.hasUppercase) {
+ validators.push(upperCaseValidator);
+ }
+ if (this.policy.hasNumber) {
+ validators.push(numberValidator);
+ }
+ if (this.policy.hasSymbol) {
+ validators.push(symbolValidator);
+ }
+
+ this.setupForm(validators);
+ }).catch(error => {
+ this.setupForm(validators);
+ });
+ });
+ }
+
+ ngOnInit(): void {
+ }
+
+ setupForm(validators: Validators[]): void {
+ if (this.userId) {
+ this.passwordForm = this.fb.group({
+ password: ['', validators],
+ confirmPassword: ['', [...validators, passwordConfirmValidator]],
+ });
+ } else {
+ this.passwordForm = this.fb.group({
+ currentPassword: ['', validators],
+ newPassword: ['', validators],
+ confirmPassword: ['', [...validators, passwordConfirmValidator]],
+ });
+ }
+ }
+
+ public setInitialPassword(userId: string): void {
+ if (this.passwordForm.valid && this.password && this.password.value) {
+ this.mgmtUserService.SetInitialPassword(userId, this.password.value).then((data: any) => {
+ this.toast.showInfo('Set initial Password');
+ window.history.back();
+ }).catch(data => {
+ this.toast.showError(data.message);
+ });
+ }
+ }
+
+ public setPassword(): void {
+ if (this.passwordForm.valid && this.currentPassword &&
+ this.currentPassword.value &&
+ this.newPassword && this.newPassword.value && this.newPassword.valid) {
+ this.userService
+ .ChangeMyPassword(this.currentPassword.value, this.newPassword.value).then((data: any) => {
+ this.toast.showInfo('Password Set');
+ window.history.back();
+ }).catch(data => {
+ this.toast.showError(data.message);
+ });
+ }
+ }
+
+ public get password(): AbstractControl | null {
+ return this.passwordForm.get('password');
+ }
+
+ public get newPassword(): AbstractControl | null {
+ return this.passwordForm.get('newPassword');
+ }
+
+ public get currentPassword(): AbstractControl | null {
+ return this.passwordForm.get('newPassword');
+ }
+
+ public get confirmPassword(): AbstractControl | null {
+ return this.passwordForm.get('confirmPassword');
+ }
+}
diff --git a/console/src/app/pages/user-detail/user-detail-routing.module.ts b/console/src/app/pages/user-detail/user-detail-routing.module.ts
index 2b5fe61abd..d74d40c6c9 100644
--- a/console/src/app/pages/user-detail/user-detail-routing.module.ts
+++ b/console/src/app/pages/user-detail/user-detail-routing.module.ts
@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
import { RoleGuard } from 'src/app/guards/role.guard';
import { AuthUserDetailComponent } from './auth-user-detail/auth-user-detail.component';
+import { PasswordComponent } from './password/password.component';
import { UserDetailComponent } from './user-detail/user-detail.component';
const routes: Routes = [
@@ -10,6 +11,10 @@ const routes: Routes = [
path: 'me',
component: AuthUserDetailComponent,
},
+ {
+ path: 'me/password',
+ component: PasswordComponent,
+ },
{
path: ':id',
component: UserDetailComponent,
@@ -18,6 +23,14 @@ const routes: Routes = [
roles: ['user.read'],
},
},
+ {
+ path: ':id/password',
+ component: PasswordComponent,
+ canActivate: [RoleGuard],
+ data: {
+ roles: ['user.write'],
+ },
+ },
];
@NgModule({
diff --git a/console/src/app/pages/user-detail/user-detail.module.ts b/console/src/app/pages/user-detail/user-detail.module.ts
index 272757bf9b..d356cb4899 100644
--- a/console/src/app/pages/user-detail/user-detail.module.ts
+++ b/console/src/app/pages/user-detail/user-detail.module.ts
@@ -28,6 +28,7 @@ import { ThemeSettingComponent } from './theme-setting/theme-setting.component';
import { UserDetailRoutingModule } from './user-detail-routing.module';
import { UserDetailComponent } from './user-detail/user-detail.component';
import { UserMfaComponent } from './user-mfa/user-mfa.component';
+import { PasswordComponent } from './password/password.component';
@NgModule({
declarations: [
@@ -37,6 +38,7 @@ import { UserMfaComponent } from './user-mfa/user-mfa.component';
AuthUserMfaComponent,
UserMfaComponent,
ThemeSettingComponent,
+ PasswordComponent,
],
imports: [
UserDetailRoutingModule,
diff --git a/console/src/app/pages/user-detail/user-detail/user-detail.component.html b/console/src/app/pages/user-detail/user-detail/user-detail.component.html
index 73881402cf..eef0fccae1 100644
--- a/console/src/app/pages/user-detail/user-detail/user-detail.component.html
+++ b/console/src/app/pages/user-detail/user-detail/user-detail.component.html
@@ -24,76 +24,22 @@
-
-
-
-
-
-
-
+
+
{{ 'USER.PROFILE.PASSWORD' | translate }}
+
+
*********
+
+
@@ -177,7 +119,7 @@
-
diff --git a/console/src/app/pages/user-detail/user-detail/user-detail.component.scss b/console/src/app/pages/user-detail/user-detail/user-detail.component.scss
index e8d8069058..647662d210 100644
--- a/console/src/app/pages/user-detail/user-detail/user-detail.component.scss
+++ b/console/src/app/pages/user-detail/user-detail/user-detail.component.scss
@@ -9,7 +9,7 @@
}
h1 {
- font-size: 1.2rem;
+ font-size: 2rem;
margin: 0 1rem;
margin-left: 2rem;
font-weight: normal;
@@ -82,6 +82,10 @@
display: flex;
justify-content: flex-end;
align-items: center;
+
+ .notify-change-pwd {
+ border-radius: .5rem;
+ }
}
.label {
diff --git a/console/src/app/pages/user-detail/user-detail/user-detail.component.ts b/console/src/app/pages/user-detail/user-detail/user-detail.component.ts
index 71fe7bca38..7440b9f41c 100644
--- a/console/src/app/pages/user-detail/user-detail/user-detail.component.ts
+++ b/console/src/app/pages/user-detail/user-detail/user-detail.component.ts
@@ -1,7 +1,5 @@
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
-import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
-import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
@@ -9,7 +7,6 @@ import { ChangeType } from 'src/app/modules/changes/changes.component';
import {
Gender,
NotificationType,
- PasswordComplexityPolicy,
UserEmail,
UserPhone,
UserProfile,
@@ -18,27 +15,8 @@ import {
} from 'src/app/proto/generated/management_pb';
import { AuthUserService } from 'src/app/services/auth-user.service';
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
-import { OrgService } from 'src/app/services/org.service';
import { ToastService } from 'src/app/services/toast.service';
-import { CodeDialogComponent } from '../code-dialog/code-dialog.component';
-import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../validators';
-
-function passwordConfirmValidator(c: AbstractControl): any {
- if (!c.parent || !c) {
- return;
- }
- const pwd = c.parent.get('password');
- const cpwd = c.parent.get('confirmPassword');
-
- if (!pwd || !cpwd) {
- return;
- }
- if (pwd.value !== cpwd.value) {
- return { invalid: true, notequal: 'Password is not equal' };
- }
-}
-
@Component({
selector: 'app-user-detail',
templateUrl: './user-detail.component.html',
@@ -46,13 +24,9 @@ function passwordConfirmValidator(c: AbstractControl): any {
})
export class UserDetailComponent implements OnInit, OnDestroy {
public user!: UserView.AsObject;
- // public address: UserAddress.AsObject = { id: '' } as any;
public genders: Gender[] = [Gender.GENDER_MALE, Gender.GENDER_FEMALE, Gender.GENDER_DIVERSE];
public languages: string[] = ['de', 'en'];
- public passwordForm!: FormGroup;
- // public addressForm!: FormGroup;
-
public isMgmt: boolean = false;
private subscription: Subscription = new Subscription();
public emailEditState: boolean = false;
@@ -62,49 +36,14 @@ export class UserDetailComponent implements OnInit, OnDestroy {
public loading: boolean = false;
public UserState: any = UserState;
- public policy!: PasswordComplexityPolicy.AsObject;
constructor(
public translate: TranslateService,
private route: ActivatedRoute,
private toast: ToastService,
private mgmtUserService: MgmtUserService,
- private fb: FormBuilder,
private _location: Location,
- private dialog: MatDialog,
- private orgService: OrgService,
public authUserService: AuthUserService,
- ) {
- const validators: Validators[] = [Validators.required];
-
- this.orgService.GetPasswordComplexityPolicy().then(data => {
- this.policy = data.toObject();
- if (this.policy.minLength) {
- validators.push(Validators.minLength(this.policy.minLength));
- }
- if (this.policy.hasLowercase) {
- validators.push(lowerCaseValidator);
- }
- if (this.policy.hasUppercase) {
- validators.push(upperCaseValidator);
- }
- if (this.policy.hasNumber) {
- validators.push(numberValidator);
- }
- if (this.policy.hasSymbol) {
- validators.push(symbolValidator);
- }
-
- this.passwordForm = this.fb.group({
- password: ['', validators],
- confirmPassword: ['', [...validators, passwordConfirmValidator]],
- });
- }).catch(error => {
- this.passwordForm = this.fb.group({
- password: ['', []],
- confirmPassword: ['', [passwordConfirmValidator]],
- });
- });
- }
+ ) { }
public ngOnInit(): void {
this.subscription = this.route.params.subscribe(params => {
@@ -121,25 +60,6 @@ export class UserDetailComponent implements OnInit, OnDestroy {
this.subscription.unsubscribe();
}
- public deletePhone(): void {
- this.user.phone = '';
- this.savePhone();
- }
-
- public enterCode(): void {
- const dialogRef = this.dialog.open(CodeDialogComponent, {
- data: {
- number: this.user.phone,
- },
- });
-
- dialogRef.afterClosed().subscribe(code => {
- if (code) {
- this.toast.showInfo('TODO: implement service');
- }
- });
- }
-
public saveProfile(profileData: UserProfile.AsObject): void {
this.user.firstName = profileData.firstName;
this.user.lastName = profileData.lastName;
@@ -180,27 +100,6 @@ export class UserDetailComponent implements OnInit, OnDestroy {
});
}
- public setInitialPassword(): void {
- if (this.passwordForm.valid && this.password && this.password.value) {
- this.mgmtUserService.SetInitialPassword(this.user.id, this.password.value).then((data: any) => {
- this.toast.showInfo('Set initial Password');
- this.user.email = data.toObject();
- }).catch(data => {
- this.toast.showError(data.message);
- });
- }
- }
-
- public sendSetPasswordNotification(): void {
- this.mgmtUserService.SendSetPasswordNotification(this.user.id, NotificationType.NOTIFICATIONTYPE_EMAIL)
- .then((data: any) => {
- this.toast.showInfo('Set initial Password');
- this.user.email = data.toObject();
- }).catch(data => {
- this.toast.showError(data.message);
- });
- }
-
public saveEmail(): void {
this.emailEditState = false;
this.mgmtUserService
@@ -227,13 +126,6 @@ export class UserDetailComponent implements OnInit, OnDestroy {
this._location.back();
}
- public get password(): AbstractControl | null {
- return this.passwordForm.get('password');
- }
- public get confirmPassword(): AbstractControl | null {
- return this.passwordForm.get('confirmPassword');
- }
-
private async getData({ id }: Params): Promise {
this.isMgmt = true;
this.mgmtUserService.GetUserByID(id).then(user => {
@@ -242,4 +134,13 @@ export class UserDetailComponent implements OnInit, OnDestroy {
console.error(err);
});
}
+
+ public sendSetPasswordNotification(): void {
+ this.mgmtUserService.SendSetPasswordNotification(this.user.id, NotificationType.NOTIFICATIONTYPE_EMAIL)
+ .then(() => {
+ this.toast.showInfo('Set initial Password');
+ }).catch(data => {
+ this.toast.showError(data.message);
+ });
+ }
}
diff --git a/console/src/app/pages/user-grant-create/user-grant-create.component.html b/console/src/app/pages/user-grant-create/user-grant-create.component.html
index 4be2af7fef..52d05fbdc0 100644
--- a/console/src/app/pages/user-grant-create/user-grant-create.component.html
+++ b/console/src/app/pages/user-grant-create/user-grant-create.component.html
@@ -16,7 +16,7 @@
{{'PROJECT.GRANT.CREATE.ORG_DESCRIPTION_DESC' | translate}}
-
+
{{'PROJECT.GRANT.CREATE.SEL_PROJECT' | translate}}
-
+
{{'PROJECT.GRANT.CREATE.SEL_USER' | translate}}
@@ -43,7 +44,7 @@
diff --git a/console/src/app/pages/user-grant-create/user-grant-create.component.ts b/console/src/app/pages/user-grant-create/user-grant-create.component.ts
index f2626bcac0..1d05024f43 100644
--- a/console/src/app/pages/user-grant-create/user-grant-create.component.ts
+++ b/console/src/app/pages/user-grant-create/user-grant-create.component.ts
@@ -2,15 +2,9 @@ import { Location } from '@angular/common';
import { Component, OnDestroy } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Subscription } from 'rxjs';
+import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
import { Org } from 'src/app/proto/generated/auth_pb';
-import {
- ProjectGrantView,
- ProjectRole,
- ProjectView,
- User,
- UserGrant,
- UserGrantSearchKey,
-} from 'src/app/proto/generated/management_pb';
+import { ProjectGrantView, ProjectRole, ProjectView, User, UserGrant } from 'src/app/proto/generated/management_pb';
import { AuthService } from 'src/app/services/auth.service';
import { MgmtUserService } from 'src/app/services/mgmt-user.service';
import { ToastService } from 'src/app/services/toast.service';
@@ -21,6 +15,8 @@ import { ToastService } from 'src/app/services/toast.service';
styleUrls: ['./user-grant-create.component.scss'],
})
export class UserGrantCreateComponent implements OnDestroy {
+ public context!: UserGrantContext;
+
public org!: Org.AsObject;
public userId: string = '';
public projectId: string = '';
@@ -30,12 +26,11 @@ export class UserGrantCreateComponent implements OnDestroy {
public STEPS: number = 2; // project, roles
public currentCreateStep: number = 1;
- public filter!: UserGrantSearchKey;
public filterValue: string = '';
private subscription: Subscription = new Subscription();
- public UserGrantSearchKey: any = UserGrantSearchKey;
+ public UserGrantContext: any = UserGrantContext;
constructor(
private authService: AuthService,
private userService: MgmtUserService,
@@ -45,18 +40,20 @@ export class UserGrantCreateComponent implements OnDestroy {
) {
this.subscription = this.route.params.subscribe((params: Params) => {
console.log(params);
- const { filter, filterValue } = params;
- this.filter = filter;
- switch (filter) {
- case (`${UserGrantSearchKey.USERGRANTSEARCHKEY_PROJECT_ID}`):
- this.projectId = filterValue;
- break;
- case (`${UserGrantSearchKey.USERGRANTSEARCHKEY_USER_ID}`):
- this.userId = filterValue;
- break;
- }
+ const { context, projectid, grantid, userid } = params;
+ this.context = context;
- console.log(this.projectId, this.userId);
+ this.projectId = projectid;
+ this.grantId = grantid;
+ this.userId = userid;
+
+ if (this.userId) {
+ this.context = UserGrantContext.USER;
+ } else if (this.projectId && !this.grantId) {
+ this.context = UserGrantContext.OWNED_PROJECT;
+ } else if (this.projectId && this.grantId) {
+ this.context = UserGrantContext.GRANTED_PROJECT;
+ }
});
this.authService.GetActiveOrg().then(org => {
@@ -69,15 +66,48 @@ export class UserGrantCreateComponent implements OnDestroy {
}
public addGrant(): void {
- this.userService.CreateUserGrant(
- this.projectId,
- this.userId,
- this.rolesList,
- ).then((data: UserGrant) => {
- this.close();
- }).catch(error => {
- this.toast.showError(error.message);
- });
+ switch (this.context) {
+ case UserGrantContext.USER:
+ this.userService.CreateUserGrant(
+ this.projectId,
+ this.userId,
+ this.rolesList,
+ ).then((data: UserGrant) => {
+ this.toast.showInfo('User Grant added');
+ this.close();
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ break;
+ case UserGrantContext.OWNED_PROJECT:
+ this.userService.CreateProjectUserGrant(
+ this.projectId,
+ this.userId,
+ this.rolesList,
+ ).then((data: UserGrant) => {
+ this.toast.showInfo('Project User Grant added');
+ this.close();
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ break;
+ case UserGrantContext.GRANTED_PROJECT:
+ this.userService.CreateProjectGrantUserGrant(
+ this.org.id,
+ this.projectId,
+ this.grantId,
+ this.userId,
+ this.rolesList,
+ ).then((data: UserGrant) => {
+ this.toast.showInfo('Project Grant User Grant added');
+ this.close();
+ }).catch(error => {
+ this.toast.showError(error.message);
+ });
+ break;
+
+ }
+
}
public selectProject(project: ProjectView.AsObject | ProjectGrantView.AsObject | any): void {
diff --git a/console/src/app/services/mgmt-user.service.ts b/console/src/app/services/mgmt-user.service.ts
index c9d48b2a17..fc121d6c77 100644
--- a/console/src/app/services/mgmt-user.service.ts
+++ b/console/src/app/services/mgmt-user.service.ts
@@ -15,10 +15,12 @@ import {
ProjectGrantMemberSearchQuery,
ProjectGrantMemberSearchRequest,
ProjectGrantMemberSearchResponse,
+ ProjectGrantUserGrantCreate,
ProjectGrantUserGrantID,
ProjectGrantUserGrantSearchRequest,
ProjectGrantUserGrantUpdate,
ProjectRoleAdd,
+ ProjectUserGrantSearchRequest,
SetPasswordNotificationRequest,
UpdateUserAddressRequest,
UpdateUserEmailRequest,
@@ -30,6 +32,7 @@ import {
UserGrant,
UserGrantCreate,
UserGrantID,
+ UserGrantRemoveBulk,
UserGrantSearchQuery,
UserGrantSearchRequest,
UserGrantSearchResponse,
@@ -221,6 +224,44 @@ export class MgmtUserService {
);
}
+ public async CreateProjectUserGrant(
+ projectId: string,
+ userId: string,
+ roleNamesList: string[],
+ ): Promise {
+ const req = new UserGrantCreate();
+ req.setProjectId(projectId);
+ req.setUserId(userId);
+ req.setRoleKeysList(roleNamesList);
+
+ return await this.request(
+ c => c.createProjectUserGrant,
+ req,
+ f => f,
+ );
+ }
+
+ public async CreateProjectGrantUserGrant(
+ orgId: string,
+ projectId: string,
+ grantId: string,
+ userId: string,
+ roleNamesList: string[],
+ ): Promise {
+ const req = new ProjectGrantUserGrantCreate();
+ req.setOrgId(orgId);
+ req.setProjectId(projectId);
+ req.setProjectGrantId(grantId);
+ req.setUserId(userId);
+ req.setRoleKeysList(roleNamesList);
+
+ return await this.request(
+ c => c.createProjectGrantUserGrant,
+ req,
+ f => f,
+ );
+ }
+
public async ReactivateUser(id: string): Promise {
const req = new UserID();
req.setId(id);
@@ -355,6 +396,8 @@ export class MgmtUserService {
);
}
+ // USER GRANTS
+
public async SearchUserGrants(
limit: number,
offset: number,
@@ -373,13 +416,34 @@ export class MgmtUserService {
);
}
+ public async SearchProjectUserGrants(
+ projectId: string,
+ limit: number,
+ offset: number,
+ queryList?: UserGrantSearchQuery[],
+ ): Promise {
+ const req = new ProjectUserGrantSearchRequest();
+ req.setProjectId(projectId);
+ req.setLimit(limit);
+ req.setOffset(offset);
+ if (queryList) {
+ req.setQueriesList(queryList);
+ }
+ return await this.request(
+ c => c.searchProjectUserGrants,
+ req,
+ f => f,
+ );
+ }
- public async searchProjectGrantUserGrants(
+ public async SearchProjectGrantUserGrants(
+ projectGrantId: string,
limit: number,
offset: number,
queryList?: UserGrantSearchQuery[],
): Promise {
const req = new ProjectGrantUserGrantSearchRequest();
+ req.setProjectGrantId(projectGrantId);
req.setLimit(limit);
req.setOffset(offset);
if (queryList) {
@@ -460,6 +524,36 @@ export class MgmtUserService {
);
}
+ public async RemoveUserGrant(
+ id: string,
+ userId: string,
+ ): Promise {
+ const req = new UserGrantID();
+ req.setId(id);
+ req.setUserId(userId);
+
+ return await this.request(
+ c => c.removeUserGrant,
+ req,
+ f => f,
+ );
+ }
+
+ public async BulkRemoveUserGrant(
+ idsList: string[],
+ ): Promise {
+ const req = new UserGrantRemoveBulk();
+ req.setIdsList(idsList);
+
+ return await this.request(
+ c => c.bulkRemoveUserGrant,
+ req,
+ f => f,
+ );
+ }
+
+ //
+
public async ApplicationChanges(id: string, limit: number, offset: number): Promise {
const req = new ChangeRequest();
req.setId(id);
diff --git a/console/src/app/services/project.service.ts b/console/src/app/services/project.service.ts
index ec14ae56be..a5998341e4 100644
--- a/console/src/app/services/project.service.ts
+++ b/console/src/app/services/project.service.ts
@@ -19,7 +19,9 @@ import {
ProjectGrant,
ProjectGrantCreate,
ProjectGrantID,
+ ProjectGrantMember,
ProjectGrantMemberAdd,
+ ProjectGrantMemberChange,
ProjectGrantMemberRemove,
ProjectGrantMemberRoles,
ProjectGrantMemberSearchQuery,
@@ -246,6 +248,24 @@ export class ProjectService {
);
}
+ public async ChangeProjectGrantMember(
+ projectId: string,
+ grantId: string,
+ userId: string,
+ rolesList: string[],
+ ): Promise {
+ const req = new ProjectGrantMemberChange();
+ req.setProjectId(projectId);
+ req.setGrantId(grantId);
+ req.setUserId(userId);
+ req.setRolesList(rolesList);
+ return await this.request(
+ c => c.changeProjectGrantMember,
+ req,
+ f => f,
+ );
+ }
+
public async SearchProjectGrantMembers(
projectId: string,
grantId: string,
diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json
index ed9bdf0c7e..ce74e738e9 100644
--- a/console/src/assets/i18n/de.json
+++ b/console/src/assets/i18n/de.json
@@ -3,7 +3,7 @@
"HOME": {
"TITLE": "zitadel",
"SECURITYANDPRIVACY": "Datenschutz und Personalisierung",
- "SECURITYANDPRIVACY_DESC": "Sie können die Daten in Ihrem Caos-Konto sehen und auswählen, welche Aktivitäten gespeichert werden, um Caos für sich zu personalisieren",
+ "SECURITYANDPRIVACY_DESC": "Sie können die Daten in Ihrem Zitadel Konto sehen und auswählen, welche Aktivitäten gespeichert werden, um Zitadel für sich zu personalisieren",
"SECURITYANDPRIVACY_BUTTON": "Daten verwalten und personalisieren",
"PROTECTION": "Organisationsrichtlinien",
"PROTECTION_DESC": "Verwalten Sie Ihre Organisationsrichtlinien. Entdecken Sie einige vorgefertigte Lösungen, die Ihnen Zeit sparen und Sicherheit gewährleisten.",
@@ -52,7 +52,7 @@
},
"USER": {
"TITLE": "Persönliche Informationen",
- "DESCRIPTION": "Hier können Sie Ihre Daten sowie die Datenschutz- und Sicherheitseinstellungen verwalten, um Caos optimal an Ihre Bedürfnisse anzupassen",
+ "DESCRIPTION": "Hier können Sie Ihre Daten sowie die Datenschutz- und Sicherheitseinstellungen verwalten, um Zitadel optimal an Ihre Bedürfnisse anzupassen",
"PAGES": {
"LIST": "Benutzer",
"TITLE": "Benutzer",
@@ -112,18 +112,19 @@
"TITLE": "Profil",
"EMAIL": "Email",
"PHONE": "Phonenumber",
- "DESCRIPTION": "Hier können Sie Ihre Daten sowie die Datenschutz- und Sicherheitseinstellungen verwalten, um Caos optimal an Ihre Bedürfnisse anzupassen",
+ "DESCRIPTION": "Hier können Sie Ihre Daten sowie die Datenschutz- und Sicherheitseinstellungen verwalten, um Zitadel optimal an Ihre Bedürfnisse anzupassen",
"USERNAME": "Benutzername",
"FIRSTNAME": "Vorname",
"LASTNAME": "Nachname",
"NICKNAME": "Spitzname",
"DISPLAYNAME": "Anzeigename",
"PREFERRED_LANGUAGE": "Sprache",
- "GENDER": "Geschlecht"
+ "GENDER": "Geschlecht",
+ "PASSWORD":"Passwort"
},
"PASSWORD": {
"TITLE": "Passwort",
- "DESCRIPTION": "Das Password muss aus mindestens 8 Zeichen bestehen und einen Grossbuchstaben, ein Sonderzeichen und eine Zahl enthalten. Die maximale Anzahl an Zeichen ist 72!",
+ "DESCRIPTION": "Beachten Sie, dass das Password der von Ihrer Organisation definierten Richtlinie entsprechen muss.",
"OLD": "Aktuelles Passwort",
"NEW": "Neues Passwort",
"CONFIRM": "Neues Passwort Wiederholung",
diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json
index e6e63bada6..196fa4bcf6 100644
--- a/console/src/assets/i18n/en.json
+++ b/console/src/assets/i18n/en.json
@@ -3,7 +3,7 @@
"HOME": {
"TITLE": "zitadel",
"SECURITYANDPRIVACY": "Data protection and personalization",
- "SECURITYANDPRIVACY_DESC": "You can view the data in your Caos account and choose which activities are saved in order to personalize Caos for you",
+ "SECURITYANDPRIVACY_DESC": "You can view the data in your Zitadel account and choose which activities are saved in order to personalize Zitadel for you",
"SECURITYANDPRIVACY_BUTTON": "Personalize data",
"PROTECTION": "Organizational Policies",
"PROTECTION_DESC": "Manage your organizational guidelines. Explore some pre-packaged solutions that save you time and ensure security.",
@@ -112,18 +112,19 @@
"TITLE": "Profile",
"EMAIL": "Email",
"PHONE": "Phonenumber",
- "DESCRIPTION": "Here you can manage your data as well as data protection and security settings in order to optimally adapt Caos to your needs",
+ "DESCRIPTION": "Here you can manage your data as well as data protection and security settings in order to optimally adapt Zitadel to your needs",
"USERNAME": "Username",
"FIRSTNAME": "Firstname",
"LASTNAME": "Lastname",
"NICKNAME": "Nickname",
"DISPLAYNAME": "Displayname",
"PREFERRED_LANGUAGE": "Language",
- "GENDER": "Gender"
+ "GENDER": "Gender",
+ "PASSWORD":"Password"
},
"PASSWORD": {
"TITLE": "Password",
- "DESCRIPTION": "The password must consist of at least 8 characters and contain a capital letter, a special character and a number. The maximum length is 72.",
+ "DESCRIPTION": "Note that the possword must correspond to the policy your organization has set.",
"OLD": "Current Password",
"NEW": "New Password",
"CONFIRM": "Password Confirmation",
@@ -137,7 +138,7 @@
"EMAIL": "Email",
"PHONE": "Phonenumber",
"LOGINMETHODS": {
- "TITLE": "Methods to check your identity",
+ "TITLE": "Methods to access your identity",
"DESCRIPTION": "This allows us to confirm your identity when you register or to contact you if suspicious activity is detected in your account",
"EMAIL": {
"TITLE": "Email",