mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-15 19:33:44 +00:00
feat(console): authorizations from user context, add grants to auth user view, fix app saving (#895)
* user grant on project * grant in auth user, enable creation, fix inv regex * use autocomplete solutions, section for usre ctx * user grant create for user context * fix edit from table * fix create context * fix authorization to write * grant overview component * fix user grants without context * lint * turn table highlighting off, rm logs * fix app name saving * fix table refresh for project grants * translate toast * i18n * lint * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <florian@caos.ch> Co-authored-by: Florian Forster <florian@caos.ch>
This commit is contained in:
17
console/src/app/pages/grants/grants-routing.module.ts
Normal file
17
console/src/app/pages/grants/grants-routing.module.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { GrantsComponent } from './grants.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GrantsComponent,
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class GrantsRoutingModule { }
|
||||
9
console/src/app/pages/grants/grants.component.html
Normal file
9
console/src/app/pages/grants/grants.component.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<div class="max-width-container">
|
||||
<h2>{{ 'GRANTS.TITLE' | translate }}</h2>
|
||||
<p class="desc">{{'GRANTS.DESC' | translate }}</p>
|
||||
<app-user-grants
|
||||
[displayedColumns]="['select', 'user', 'org', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
</div>
|
||||
4
console/src/app/pages/grants/grants.component.scss
Normal file
4
console/src/app/pages/grants/grants.component.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
.desc {
|
||||
color: var(--grey);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
25
console/src/app/pages/grants/grants.component.spec.ts
Normal file
25
console/src/app/pages/grants/grants.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GrantsComponent } from './grants.component';
|
||||
|
||||
describe('GrantsComponent', () => {
|
||||
let component: GrantsComponent;
|
||||
let fixture: ComponentFixture<GrantsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [GrantsComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GrantsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
8
console/src/app/pages/grants/grants.component.ts
Normal file
8
console/src/app/pages/grants/grants.component.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-grants',
|
||||
templateUrl: './grants.component.html',
|
||||
styleUrls: ['./grants.component.scss'],
|
||||
})
|
||||
export class GrantsComponent { }
|
||||
24
console/src/app/pages/grants/grants.module.ts
Normal file
24
console/src/app/pages/grants/grants.module.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { GrantsRoutingModule } from './grants-routing.module';
|
||||
import { GrantsComponent } from './grants.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
GrantsComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
GrantsRoutingModule,
|
||||
UserGrantsModule,
|
||||
TranslateModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
],
|
||||
})
|
||||
export class GrantsModule { }
|
||||
@@ -12,7 +12,7 @@
|
||||
<span *ngIf="errorMessage" class="err-container">{{errorMessage}}</span>
|
||||
|
||||
<app-card title="{{ 'APP.PAGES.DETAIL.TITLE' | translate }}" *ngIf="app">
|
||||
<form [formGroup]="appNameForm" (ngSubmit)="saveOIDCApp()">
|
||||
<form [formGroup]="appNameForm" (ngSubmit)="saveApp()">
|
||||
<div class="content">
|
||||
<mat-button-toggle-group formControlName="state" class="toggle" (change)="changeState($event)">
|
||||
<mat-button-toggle [value]="AppState.APPSTATE_INACTIVE"
|
||||
|
||||
@@ -216,6 +216,22 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
public saveApp(): void {
|
||||
if (this.appNameForm.valid) {
|
||||
this.app.name = this.name?.value;
|
||||
|
||||
this.mgmtService
|
||||
.UpdateApplication(this.projectId, this.app.id, this.name?.value)
|
||||
.then(() => {
|
||||
this.toast.showInfo('APP.TOAST.OIDCUPDATED', true);
|
||||
})
|
||||
.catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public saveOIDCApp(): void {
|
||||
if (this.appNameForm.valid) {
|
||||
this.app.name = this.name?.value;
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
<app-user-grants *ngIf="projectId && grantId" [context]="UserGrantContext.GRANTED_PROJECT"
|
||||
[projectId]="projectId" [grantId]="grantId"
|
||||
[displayedColumns]="['select','user', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
|
||||
[allowWrite]="['user.grant.write$','user.grant.write:'+grantId] | hasRole | async"
|
||||
[allowDelete]="['user.grant.delete$','user.grant.delete:'+grantId] | hasRole | async"
|
||||
refreshOnPreviousRoute="/grant-create/project/{{projectId}}/grant/{{grantId}}">
|
||||
[disableWrite]="(['user.grant.write$','user.grant.write:'+grantId] | hasRole | async) == false"
|
||||
[disableDelete]="(['user.grant.delete$','user.grant.delete:'+grantId] | hasRole | async) == false"
|
||||
refreshOnPreviousRoutes="['/grant-create/project/{{projectId}}/grant/{{grantId}}']">
|
||||
</app-user-grants>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
@@ -68,7 +68,8 @@
|
||||
[appHasRole]="['project.grant.read:' + project.projectId, 'project.grant.read']">
|
||||
<app-card title="{{ 'PROJECT.GRANT.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.GRANT.DESCRIPTION' | translate }}">
|
||||
<app-project-grants refreshOnPreviousRoute="/projects/{{projectId}}/grants/create"
|
||||
<app-project-grants
|
||||
[refreshOnPreviousRoutes]="['/projects/'+projectId+'/grants/create','/projects/'+projectId+'/roles/create']"
|
||||
[disabled]="((['project.grant.write$', 'project.grant.write:'+ project.projectId]| hasRole | async))== false"
|
||||
[projectId]="projectId">
|
||||
</app-project-grants>
|
||||
@@ -97,9 +98,9 @@
|
||||
<app-card *ngIf="project?.projectId" title="{{ 'GRANTS.PROJECT.TITLE' | translate }}"
|
||||
description="{{'GRANTS.PROJECT.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [context]="UserGrantContext.OWNED_PROJECT" [projectId]="projectId"
|
||||
refreshOnPreviousRoute="/grant-create/project/{{projectId}}"
|
||||
[allowWrite]="(['user.grant.write$', 'user.grant.write:'+projectId] | hasRole) | async"
|
||||
[allowDelete]="(['user.grant.delete$','user.grant.delete:'+projectId] | hasRole) | async">
|
||||
[refreshOnPreviousRoutes]="['/grant-create/project/'+projectId]"
|
||||
[disableWrite]="((['user.grant.write$', 'user.grant.write:'+projectId] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$','user.grant.delete:'+projectId] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<app-refresh-table [loading]="dataSource?.loading$ | async" *ngIf="projectId" (refreshed)="loadGrantsPage()"
|
||||
[dataSize]="dataSource.totalResult" [selection]="selection" [timestamp]="dataSource?.viewTimestamp"
|
||||
[emitRefreshOnPreviousRoute]="refreshOnPreviousRoute">
|
||||
[emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes" (refreshed)="getRoleOptions(projectId)">
|
||||
<ng-template appHasRole [appHasRole]="['project.grant.member.delete:'+projectId, 'project.grant.member.delete']"
|
||||
actions>
|
||||
<button (click)="deleteSelectedGrants()" [disabled]="disabled" mat-icon-button *ngIf="selection.hasValue()"
|
||||
|
||||
@@ -24,7 +24,7 @@ import { ProjectGrantsDataSource } from './project-grants-datasource';
|
||||
],
|
||||
})
|
||||
export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
@Input() refreshOnPreviousRoute: string = '';
|
||||
@Input() refreshOnPreviousRoutes: string[] = [];
|
||||
@Input() public projectId: string = '';
|
||||
@Input() public disabled: boolean = false;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
@@ -50,7 +50,6 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
tap(() => this.loadGrantsPage()),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
}
|
||||
|
||||
public loadGrantsPage(pageIndex?: number, pageSize?: number): void {
|
||||
|
||||
@@ -16,33 +16,36 @@
|
||||
{{'PROJECT.GRANT.CREATE.ORG_DESCRIPTION_DESC' | translate}}
|
||||
</p>
|
||||
|
||||
<ng-container *ngIf="context && context == UserGrantContext.USER">
|
||||
<ng-container>
|
||||
<h1>{{'PROJECT.GRANT.CREATE.SEL_USER' | translate}}</h1>
|
||||
|
||||
<app-search-user-autocomplete class="block" singleOutput="true" [users]="user ? [user] : []"
|
||||
(selectionChanged)="selectUser($event)"
|
||||
[target]="context === UserGrantContext.USER ? UserTarget.EXTERNAL : UserTarget.SELF">
|
||||
</app-search-user-autocomplete>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="context && (context == UserGrantContext.USER || context == UserGrantContext.NONE)">
|
||||
<h1>{{'PROJECT.GRANT.CREATE.SEL_PROJECT' | translate}}</h1>
|
||||
|
||||
<app-search-project-autocomplete class="block" singleOutput="true"
|
||||
(selectionChanged)="selectProject($event)">
|
||||
</app-search-project-autocomplete>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="context && (context == UserGrantContext.GRANTED_PROJECT || context == UserGrantContext.OWNED_PROJECT)">
|
||||
<h1>{{'PROJECT.GRANT.CREATE.SEL_USER' | translate}}</h1>
|
||||
|
||||
<app-search-user-autocomplete class="block" singleOutput="true" (selectionChanged)="selectUser($event)">
|
||||
</app-search-user-autocomplete>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentCreateStep === STEPS">
|
||||
<h1>{{'PROJECT.GRANT.CREATE.SEL_ROLES' | translate}}</h1>
|
||||
<ng-container *ngIf="context === UserGrantContext.OWNED_PROJECT && projectId">
|
||||
<ng-container
|
||||
*ngIf="(projectId && (context === UserGrantContext.OWNED_PROJECT || ((context === UserGrantContext.USER || context === UserGrantContext.NONE) && $any(project)?.id == undefined)))">
|
||||
<app-card>
|
||||
<app-project-roles (changedSelection)="selectRoles($event)" [projectId]="projectId">
|
||||
</app-project-roles>
|
||||
</app-card>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="context === UserGrantContext.GRANTED_PROJECT && grantRolesKeyList">
|
||||
<ng-container
|
||||
*ngIf="(context === UserGrantContext.GRANTED_PROJECT || ((context === UserGrantContext.USER || context === UserGrantContext.NONE) && $any(project)?.id)) && grantRolesKeyList">
|
||||
<mat-form-field class="form-field" appearance="outline">
|
||||
<mat-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</mat-label>
|
||||
<mat-select multiple (selectionChange)="rolesList = $event.value">
|
||||
@@ -56,9 +59,8 @@
|
||||
|
||||
<div class="btn-container">
|
||||
<ng-container *ngIf="currentCreateStep === 1">
|
||||
<button
|
||||
[disabled]="!org || ((context == UserGrantContext.GRANTED_PROJECT || context == UserGrantContext.OWNED_PROJECT) && !projectId) || (context == UserGrantContext.USER && !userId)"
|
||||
(click)="next()" color="primary" mat-raised-button class="big-button" cdkFocusInitial>
|
||||
<button [disabled]="!org || !projectId || !userId" (click)="next()" color="primary" mat-raised-button
|
||||
class="big-button" cdkFocusInitial>
|
||||
{{ 'ACTIONS.CONTINUE' | translate }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
@@ -64,3 +64,13 @@
|
||||
padding: .5rem 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sa-icon {
|
||||
display: block;
|
||||
width: 32px;
|
||||
margin: 0 .5rem;
|
||||
|
||||
i {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Location } from '@angular/common';
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { UserTarget } from 'src/app/modules/search-user-autocomplete/search-user-autocomplete.component';
|
||||
import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
|
||||
import { Org } from 'src/app/proto/generated/auth_pb';
|
||||
import { ProjectGrantView, ProjectRole, ProjectView, UserGrant, UserView } from 'src/app/proto/generated/management_pb';
|
||||
@@ -19,7 +20,10 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
|
||||
public org!: Org.AsObject;
|
||||
public userId: string = '';
|
||||
|
||||
public projectId: string = '';
|
||||
public project!: ProjectGrantView.AsObject | ProjectView.AsObject;
|
||||
|
||||
public grantId: string = '';
|
||||
public rolesList: string[] = [];
|
||||
|
||||
@@ -33,6 +37,12 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
public UserGrantContext: any = UserGrantContext;
|
||||
|
||||
public grantRolesKeyList: string[] = [];
|
||||
|
||||
public user!: UserView.AsObject;
|
||||
public UserTarget: any = UserTarget;
|
||||
|
||||
public ProjectGrantView: any = ProjectGrantView;
|
||||
public ProjectView: any = ProjectView;
|
||||
constructor(
|
||||
private userService: ManagementService,
|
||||
private toast: ToastService,
|
||||
@@ -42,8 +52,8 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
private mgmtService: ManagementService,
|
||||
) {
|
||||
this.subscription = this.route.params.subscribe((params: Params) => {
|
||||
const { context, projectid, grantid, userid } = params;
|
||||
this.context = context;
|
||||
const { projectid, grantid, userid } = params;
|
||||
this.context = UserGrantContext.NONE;
|
||||
|
||||
this.projectId = projectid;
|
||||
this.grantId = grantid;
|
||||
@@ -58,6 +68,14 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.userId) {
|
||||
this.context = UserGrantContext.USER;
|
||||
this.mgmtService.GetUserByID(this.userId).then(resp => {
|
||||
this.user = resp.toObject();
|
||||
console.log(this.user);
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -97,12 +115,52 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
break;
|
||||
case UserGrantContext.USER:
|
||||
let grantId;
|
||||
|
||||
if ((this.project as ProjectGrantView.AsObject)?.id) {
|
||||
grantId = (this.project as ProjectGrantView.AsObject).id;
|
||||
}
|
||||
|
||||
this.userService.CreateUserGrant(
|
||||
this.userId,
|
||||
this.rolesList,
|
||||
this.project.projectId,
|
||||
grantId,
|
||||
).then((data: UserGrant) => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTUSERGRANTADDED', true);
|
||||
this.close();
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
break;
|
||||
case UserGrantContext.NONE:
|
||||
let tempGrantId;
|
||||
|
||||
if ((this.project as ProjectGrantView.AsObject)?.id) {
|
||||
tempGrantId = (this.project as ProjectGrantView.AsObject).id;
|
||||
}
|
||||
|
||||
this.userService.CreateUserGrant(
|
||||
this.userId,
|
||||
this.rolesList,
|
||||
this.project.projectId,
|
||||
tempGrantId,
|
||||
).then((data: UserGrant) => {
|
||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTUSERGRANTADDED', true);
|
||||
this.close();
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public selectProject(project: ProjectView.AsObject | ProjectGrantView.AsObject | any): void {
|
||||
this.project = project;
|
||||
this.projectId = project.projectId;
|
||||
this.grantRolesKeyList = project.roleKeysList ?? [];
|
||||
}
|
||||
|
||||
public selectUser(user: UserView.AsObject): void {
|
||||
|
||||
@@ -47,6 +47,15 @@
|
||||
</app-card>
|
||||
|
||||
<app-auth-user-mfa *ngIf="user" #mfaComponent></app-auth-user-mfa>
|
||||
|
||||
<app-card *ngIf="user?.id" title="{{ 'GRANTS.USER.TITLE' | translate }}"
|
||||
description="{{'GRANTS.USER.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [userId]="user.id" [context]="USERGRANTCONTEXT"
|
||||
[displayedColumns]="['select', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
</app-card>
|
||||
</div>
|
||||
|
||||
<div *ngIf="user" class="side" metainfo>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component, OnDestroy } from '@angular/core';
|
||||
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 { Gender, UserAddress, UserEmail, UserPhone, UserProfile, UserView } from 'src/app/proto/generated/auth_pb';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
@@ -26,6 +27,8 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
public ChangeType: any = ChangeType;
|
||||
public userLoginMustBeDomain: boolean = false;
|
||||
|
||||
public USERGRANTCONTEXT: UserGrantContext = UserGrantContext.USER;
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
private toast: ToastService,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<span class="label">{{ 'USER.PROFILE.PASSWORD' | translate }}</span>
|
||||
|
||||
<span>*********</span>
|
||||
<div>
|
||||
<div class="overflow">
|
||||
<ng-content select="[phoneAction]"></ng-content>
|
||||
<a [disabled]="!canWrite" [routerLink]="['password']" mat-icon-button>
|
||||
<mat-icon class="icon">chevron_right</mat-icon>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
.label {
|
||||
font-size: .9rem;
|
||||
min-width: 100px;
|
||||
max-width: 100px;
|
||||
color: var(--grey);
|
||||
}
|
||||
|
||||
@@ -45,3 +45,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overflow {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@@ -83,10 +83,10 @@
|
||||
|
||||
<app-card *ngIf="user?.id" title="{{ 'GRANTS.USER.TITLE' | translate }}"
|
||||
description="{{'GRANTS.USER.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [userId]="user.id"
|
||||
[allowWrite]="['user.grant.write$'+ 'user.grant.write:'+user?.id] | hasRole | async"
|
||||
<app-user-grants [userId]="user.id" [context]="USERGRANTCONTEXT"
|
||||
[displayedColumns]="['select', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
|
||||
[allowDelete]="['user.grant.delete$', 'user.grant.delete'+ user?.id] | hasRole | async">
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
</app-card>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ActivatedRoute } 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 { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import {
|
||||
Gender,
|
||||
@@ -37,6 +38,7 @@ export class UserDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
public UserState: any = UserState;
|
||||
public copied: string = '';
|
||||
public USERGRANTCONTEXT: UserGrantContext = UserGrantContext.USER;
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
|
||||
[timestamp]="userResult?.viewTimestamp" [selection]="selection"
|
||||
[emitRefreshOnPreviousRoute]="refreshOnPreviousRoute">
|
||||
[emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes">
|
||||
<mat-form-field @appearfade *ngIf="userSearchKey != undefined" actions class="filtername">
|
||||
<mat-label>{{'USER.PAGES.FILTER' | translate}}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)"
|
||||
|
||||
@@ -27,7 +27,7 @@ export class UserTableComponent implements OnInit {
|
||||
public userSearchKey: UserSearchKey | undefined = undefined;
|
||||
public UserType: any = UserType;
|
||||
@Input() userType: UserType = UserType.HUMAN;
|
||||
@Input() refreshOnPreviousRoute: string = '';
|
||||
@Input() refreshOnPreviousRoutes: string[] = [];
|
||||
@Input() disabled: boolean = false;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
@ViewChild('input') public filter!: MatInput;
|
||||
|
||||
Reference in New Issue
Block a user