mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-13 18:22:12 +00:00
feat(console): JWT IDP, cleanup login policy, update deps (#2438)
* idp cleanup * lint * jwtidp service, create, detail, assets * idp detail, info row * detail actions * delete idp, fix state change * lint * cli core * cdk material * chore(deps-dev): bump karma-jasmine-html-reporter in /console (#2446) Bumps [karma-jasmine-html-reporter](https://github.com/dfederm/karma-jasmine-html-reporter) from 1.6.0 to 1.7.0. - [Release notes](https://github.com/dfederm/karma-jasmine-html-reporter/releases) - [Commits](https://github.com/dfederm/karma-jasmine-html-reporter/compare/v1.6.0...v1.7.0) --- updated-dependencies: - dependency-name: karma-jasmine-html-reporter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * update deps * lock * disable actions, user grant link to user, add granted org desc * lint Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -82,7 +82,7 @@ export class GrantedProjectGridComponent implements OnChanges {
|
||||
|
||||
private async getPrefixedItem(key: string): Promise<string | null> {
|
||||
const org = this.storage.getItem<Org.AsObject>(StorageKey.organization, StorageLocation.session) as Org.AsObject;
|
||||
return localStorage.getItem(`${org.id}:${key}`);
|
||||
return localStorage.getItem(`${org?.id}:${key}`);
|
||||
}
|
||||
|
||||
private async setPrefixedItem(key: string, value: any): Promise<void> {
|
||||
|
||||
@@ -1,148 +1,153 @@
|
||||
<app-meta-layout>
|
||||
<div class="max-width-container">
|
||||
<div class="head" *ngIf="project?.id">
|
||||
<a [routerLink]="[ '/projects' ]" mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
<h1>{{ 'PROJECT.PAGES.TITLE' | translate }} {{project?.name}}</h1>
|
||||
<div class="max-width-container">
|
||||
<div class="head" *ngIf="project?.id">
|
||||
<a [routerLink]="[ '/projects' ]" mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
<h1>{{ 'PROJECT.PAGES.TITLE' | translate }} {{project?.name}}</h1>
|
||||
|
||||
<span class="fill-space"></span>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.write:'+projectId, 'project.write']">
|
||||
<button class="actions-trigger" mat-raised-button color="primary" [matMenuTriggerFor]="actions">
|
||||
<span>{{'ACTIONS.ACTIONS' | translate}}</span>
|
||||
<mat-icon class="icon">keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
<mat-menu #actions="matMenu" xPosition="before">
|
||||
<button mat-menu-item (click)="openNameDialog()"
|
||||
aria-label="Edit project name" *ngIf="isZitadel === false">
|
||||
{{'ACTIONS.RENAME' | translate}}
|
||||
</button>
|
||||
<ng-template appHasRole [appHasRole]="['project.write:'+projectId, 'project.write']">
|
||||
<button class="actions-trigger" mat-raised-button color="primary" [matMenuTriggerFor]="actions">
|
||||
<span>{{'ACTIONS.ACTIONS' | translate}}</span>
|
||||
<mat-icon class="icon">keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
<mat-menu #actions="matMenu" xPosition="before">
|
||||
<button mat-menu-item (click)="openNameDialog()" aria-label="Edit project name" *ngIf="isZitadel === false">
|
||||
{{'ACTIONS.RENAME' | translate}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.id]| hasRole | async) == false"
|
||||
*ngIf="project?.state === ProjectState.PROJECT_STATE_ACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECT_STATE_INACTIVE)">
|
||||
{{'PROJECT.TABLE.DEACTIVATE' | translate}}
|
||||
</button>
|
||||
<button mat-menu-item
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.id]| hasRole | async) == false"
|
||||
*ngIf="project?.state === ProjectState.PROJECT_STATE_ACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECT_STATE_INACTIVE)">
|
||||
{{'PROJECT.TABLE.DEACTIVATE' | translate}}
|
||||
</button>
|
||||
|
||||
<button mat-menu-item
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.id]| hasRole | async) == false"
|
||||
*ngIf="project?.state === ProjectState.PROJECT_STATE_INACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECT_STATE_ACTIVE)">
|
||||
{{'PROJECT.TABLE.ACTIVATE' | translate}}
|
||||
</button>
|
||||
<button mat-menu-item
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:'+ project.id]| hasRole | async) == false"
|
||||
*ngIf="project?.state === ProjectState.PROJECT_STATE_INACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECT_STATE_ACTIVE)">
|
||||
{{'PROJECT.TABLE.ACTIVATE' | translate}}
|
||||
</button>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.delete$', 'project.delete:'+projectId]">
|
||||
<button mat-menu-item matTooltip="{{'ACTIONS.DELETE' | translate}}"
|
||||
(click)="deleteProject()" aria-label="Edit project name" *ngIf="isZitadel === false">
|
||||
<span [style.color]="'var(--warn)'">{{'PROJECT.PAGES.DELETE' | translate}}</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
</ng-template>
|
||||
<ng-template appHasRole [appHasRole]="['project.delete$', 'project.delete:'+projectId]">
|
||||
<button mat-menu-item matTooltip="{{'ACTIONS.DELETE' | translate}}" (click)="deleteProject()"
|
||||
aria-label="Edit project name" *ngIf="isZitadel === false">
|
||||
<span [style.color]="'var(--warn)'">{{'PROJECT.PAGES.DELETE' | translate}}</span>
|
||||
</button>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
</ng-template>
|
||||
|
||||
<div class="full-width">
|
||||
<p class="desc">{{ 'PROJECT.PAGES.DESCRIPTION' | translate }}</p>
|
||||
<p *ngIf="isZitadel" class="zitadel-warning">{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="project">
|
||||
<div class="privatelabel-info">
|
||||
<h2 class="setting-title">{{'PROJECT.PAGES.PRIVATELABEL.TITLE' | translate}}</h2>
|
||||
<p class="setting-desc">
|
||||
<span>{{'PROJECT.PAGES.PRIVATELABEL.'+project.privateLabelingSetting+'.TITLE' | translate}}</span>
|
||||
<button (click)="openPrivateLabelingDialog()" mat-icon-button><i class="las la-edit"></i></button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.app.read:' + project.id, 'project.app.read']">
|
||||
<app-application-grid *ngIf="grid" [disabled]="isZitadel" (changeView)="grid = false"
|
||||
[projectId]="projectId"></app-application-grid>
|
||||
<app-card *ngIf="!grid" title="{{ 'PROJECT.APP.TITLE' | translate }}">
|
||||
<div class="card-actions" card-actions>
|
||||
<button mat-icon-button (click)="grid = true">
|
||||
<i matTooltip="show grid view" class="las la-th-large"></i>
|
||||
</button>
|
||||
</div>
|
||||
<app-applications [disabled]="isZitadel" [projectId]="projectId"></app-applications>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-container *ngIf="isZitadel == false">
|
||||
<ng-template appHasRole [appHasRole]="['project.grant.read:' + project.id, 'project.grant.read']">
|
||||
<app-card title="{{ 'PROJECT.GRANT.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.GRANT.DESCRIPTION' | translate }}">
|
||||
<app-project-grants
|
||||
[refreshOnPreviousRoutes]="['/projects/'+projectId+'/grants/create','/projects/'+projectId+'/roles/create']"
|
||||
[disabled]="((['project.grant.write$', 'project.grant.write:'+ project.id]| hasRole | async))== false"
|
||||
[projectId]="projectId">
|
||||
</app-project-grants>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.id, 'project.role.read']">
|
||||
<app-card id="roles" title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
|
||||
<p>{{'PROJECT.ROLE.OPTIONS' | translate}}</p>
|
||||
<mat-checkbox [(ngModel)]="project.projectRoleAssertion" (change)="saveProject()"
|
||||
color="primary">
|
||||
{{'PROJECT.ROLE.ASSERTION' | translate}}</mat-checkbox>
|
||||
<p class="desc">{{'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate}}</p>
|
||||
<mat-checkbox [(ngModel)]="project.projectRoleCheck" (change)="saveProject()" color="primary">
|
||||
{{'PROJECT.ROLE.CHECK' | translate}}</mat-checkbox>
|
||||
<p class="desc">{{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}</p>
|
||||
<mat-checkbox [(ngModel)]="project.hasProjectCheck" (change)="saveProject()" color="primary">
|
||||
{{'PROJECT.HAS_PROJECT' | translate}}</mat-checkbox>
|
||||
<p class="desc">{{'PROJECT.HAS_PROJECT_DESCRIPTION' | translate}}</p>
|
||||
<div class="divider"></div>
|
||||
<app-project-roles
|
||||
[disabled]="(['project.role.write$', 'project.role.write:'+ project.id]| hasRole | async) == false"
|
||||
[actionsVisible]="true" [projectId]="projectId">
|
||||
</app-project-roles>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.grant.read']">
|
||||
<app-card *ngIf="project?.id" title="{{ 'GRANTS.PROJECT.TITLE' | translate }}"
|
||||
description="{{'GRANTS.PROJECT.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [context]="UserGrantContext.OWNED_PROJECT" [projectId]="projectId"
|
||||
[refreshOnPreviousRoutes]="['/grant-create/project/'+projectId]"
|
||||
[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>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<div class="full-width">
|
||||
<p class="desc">{{ 'PROJECT.PAGES.DESCRIPTION' | translate }}</p>
|
||||
<p *ngIf="isZitadel" class="zitadel-warning">{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="side" metainfo>
|
||||
<div class="meta-details">
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'RESOURCEID' | translate}}:</span>
|
||||
<span *ngIf="projectId" class="second">{{ projectId }}</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
|
||||
<span *ngIf="project && project.state !== undefined" class="state"
|
||||
[ngClass]="{'active': project.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': project.state === ProjectState.PROJECT_STATE_INACTIVE}">{{'PROJECT.STATE.'+project.state
|
||||
| translate}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-tab-group mat-stretch-tabs class="tab-group" disablePagination="true">
|
||||
<mat-tab label="Details">
|
||||
<app-contributors *ngIf="project" [loading]="loading$ | async" [totalResult]="totalMemberResult"
|
||||
[membersSubject]="membersSubject" title="{{ 'PROJECT.MEMBER.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.MEMBER.TITLEDESC' | translate }}" (addClicked)="openAddMember()"
|
||||
(showDetailClicked)="showDetail()" (refreshClicked)="loadMembers()"
|
||||
[disabled]="(['project.member.write$', 'project.member.write:'+ project.id]| hasRole | async) == false">
|
||||
</app-contributors>
|
||||
</mat-tab>
|
||||
<mat-tab label="{{ 'CHANGES.PROJECT.TITLE' | translate }}" class="meta-flex-col">
|
||||
<app-changes *ngIf="project" [changeType]="ChangeType.PROJECT" [id]="project.id"></app-changes>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
<ng-container *ngIf="project">
|
||||
<div class="privatelabel-info">
|
||||
<h2 class="setting-title">{{'PROJECT.PAGES.PRIVATELABEL.TITLE' | translate}}</h2>
|
||||
<p class="setting-desc">
|
||||
<span>{{'PROJECT.PAGES.PRIVATELABEL.'+project.privateLabelingSetting+'.TITLE' | translate}}</span>
|
||||
<button [disabled]="((['project.write$', 'project.write:'+ project.id]| hasRole | async))== false"
|
||||
(click)="openPrivateLabelingDialog()" mat-icon-button><i class="las la-edit"></i></button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.app.read:' + project.id, 'project.app.read']">
|
||||
<app-application-grid *ngIf="grid" [disabled]="isZitadel" (changeView)="grid = false" [projectId]="projectId">
|
||||
</app-application-grid>
|
||||
<app-card *ngIf="!grid" title="{{ 'PROJECT.APP.TITLE' | translate }}">
|
||||
<div class="card-actions" card-actions>
|
||||
<button mat-icon-button (click)="grid = true">
|
||||
<i matTooltip="show grid view" class="las la-th-large"></i>
|
||||
</button>
|
||||
</div>
|
||||
<app-applications [disabled]="isZitadel" [projectId]="projectId"></app-applications>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-container *ngIf="isZitadel == false">
|
||||
<ng-template appHasRole [appHasRole]="['project.grant.read:' + project.id, 'project.grant.read']">
|
||||
<app-card title="{{ 'PROJECT.GRANT.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.GRANT.DESCRIPTION' | translate }}">
|
||||
<app-project-grants
|
||||
[refreshOnPreviousRoutes]="['/projects/'+projectId+'/grants/create','/projects/'+projectId+'/roles/create']"
|
||||
[disabled]="((['project.grant.write$', 'project.grant.write:'+ project.id]| hasRole | async))== false"
|
||||
[projectId]="projectId">
|
||||
</app-project-grants>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['project.role.read:' + project.id, 'project.role.read']">
|
||||
<app-card id="roles" title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
|
||||
<p>{{'PROJECT.ROLE.OPTIONS' | translate}}</p>
|
||||
<mat-checkbox [(ngModel)]="project.projectRoleAssertion"
|
||||
[disabled]="((['project.write$', 'project.write:'+ project.id]| hasRole | async))== false"
|
||||
(change)="saveProject()" color="primary">
|
||||
{{'PROJECT.ROLE.ASSERTION' | translate}}</mat-checkbox>
|
||||
<p class="desc">{{'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate}}</p>
|
||||
<mat-checkbox [(ngModel)]="project.projectRoleCheck"
|
||||
[disabled]="((['project.write$', 'project.write:'+ project.id]| hasRole | async))== false"
|
||||
(change)="saveProject()" color="primary">
|
||||
{{'PROJECT.ROLE.CHECK' | translate}}</mat-checkbox>
|
||||
<p class="desc">{{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}</p>
|
||||
<mat-checkbox [(ngModel)]="project.hasProjectCheck"
|
||||
[disabled]="((['project.write$', 'project.write:'+ project.id]| hasRole | async))== false"
|
||||
(change)="saveProject()" color="primary">
|
||||
{{'PROJECT.HAS_PROJECT' | translate}}</mat-checkbox>
|
||||
<p class="desc">{{'PROJECT.HAS_PROJECT_DESCRIPTION' | translate}}</p>
|
||||
<div class="divider"></div>
|
||||
<app-project-roles
|
||||
[disabled]="(['project.role.write$', 'project.role.write:'+ project.id]| hasRole | async) == false"
|
||||
[actionsVisible]="true" [projectId]="projectId">
|
||||
</app-project-roles>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.grant.read']">
|
||||
<app-card *ngIf="project?.id" title="{{ 'GRANTS.PROJECT.TITLE' | translate }}"
|
||||
description="{{'GRANTS.PROJECT.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [context]="UserGrantContext.OWNED_PROJECT" [projectId]="projectId"
|
||||
[refreshOnPreviousRoutes]="['/grant-create/project/'+projectId]"
|
||||
[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>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="side" metainfo>
|
||||
<div class="meta-details">
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'RESOURCEID' | translate}}:</span>
|
||||
<span *ngIf="projectId" class="second">{{ projectId }}</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
|
||||
<span *ngIf="project && project.state !== undefined" class="state"
|
||||
[ngClass]="{'active': project.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': project.state === ProjectState.PROJECT_STATE_INACTIVE}">{{'PROJECT.STATE.'+project.state
|
||||
| translate}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</app-meta-layout>
|
||||
|
||||
<mat-tab-group mat-stretch-tabs class="tab-group" disablePagination="true">
|
||||
<mat-tab label="Details">
|
||||
<app-contributors *ngIf="project" [loading]="loading$ | async" [totalResult]="totalMemberResult"
|
||||
[membersSubject]="membersSubject" title="{{ 'PROJECT.MEMBER.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.MEMBER.TITLEDESC' | translate }}" (addClicked)="openAddMember()"
|
||||
(showDetailClicked)="showDetail()" (refreshClicked)="loadMembers()"
|
||||
[disabled]="(['project.member.write$', 'project.member.write:'+ project.id]| hasRole | async) == false">
|
||||
</app-contributors>
|
||||
</mat-tab>
|
||||
<mat-tab label="{{ 'CHANGES.PROJECT.TITLE' | translate }}" class="meta-flex-col">
|
||||
<app-changes *ngIf="project" [changeType]="ChangeType.PROJECT" [id]="project.id"></app-changes>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</app-meta-layout>
|
||||
@@ -106,7 +106,7 @@ export class OwnedProjectGridComponent implements OnChanges {
|
||||
|
||||
private async getPrefixedItem(key: string): Promise<string | null> {
|
||||
const org = this.storage.getItem<Org.AsObject>(StorageKey.organization, StorageLocation.session) as Org.AsObject;
|
||||
return localStorage.getItem(`${org.id}:${key}`);
|
||||
return localStorage.getItem(`${org?.id}:${key}`);
|
||||
}
|
||||
|
||||
private async setPrefixedItem(key: string, value: any): Promise<void> {
|
||||
|
||||
@@ -1,57 +1,64 @@
|
||||
<app-detail-layout [backRouterLink]="[ '/projects', projectid]" title="{{ 'PROJECT.GRANT.DETAIL.TITLE' | translate }}"
|
||||
description="{{ 'PROJECT.GRANT.DETAIL.DESC' | translate }}">
|
||||
<div class="master-row">
|
||||
<div class="left-col">
|
||||
<div class="row">
|
||||
<span class="first">{{'PROJECT.GRANT.DETAIL.PROJECTNAME' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{grant?.projectName}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="first">{{'PROJECT.GRANT.DETAIL.RESOURCEOWNER' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{grant?.details?.resourceOwner}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
description="{{ 'PROJECT.GRANT.DETAIL.DESC' | translate }}">
|
||||
<div class="master-row">
|
||||
<div class="left-col">
|
||||
<div class="row">
|
||||
<span class="first">{{'PROJECT.GRANT.DETAIL.PROJECTNAME' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<div>
|
||||
<button mat-stroked-button color="warn" *ngIf="grant?.state === ProjectGrantState.PROJECTGRANTSTATE_ACTIVE"
|
||||
(click)="changeState(ProjectGrantState.PROJECTGRANTSTATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' | translate}}</button>
|
||||
<button mat-stroked-button color="warn"
|
||||
*ngIf="grant?.state === ProjectGrantState.PROJECTGRANTSTATE_INACTIVE"
|
||||
(click)="changeState(ProjectGrantState.PROJECTGRANTSTATE_ACTIVE)">{{'USER.PAGES.REACTIVATE' | translate}}</button>
|
||||
</div>
|
||||
<span>{{grant?.projectName}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="first">{{'PROJECT.GRANT.DETAIL.RESOURCEOWNER' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{grant?.projectOwnerName}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="first">{{'PROJECT.GRANT.DETAIL.GRANTEDORG' | translate}}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span>{{grant?.grantedOrgName}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="formfield" appearance="outline" *ngIf="grant && grant.grantedRoleKeysList">
|
||||
<cnsl-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="grant.grantedRoleKeysList" multiple (selectionChange)="updateRoles($event)">
|
||||
<mat-option *ngFor="let role of projectRoleOptions" [value]="role.key">
|
||||
{{role.key}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div>
|
||||
<button mat-stroked-button color="warn" *ngIf="grant?.state === ProjectGrantState.PROJECTGRANTSTATE_ACTIVE"
|
||||
(click)="changeState(ProjectGrantState.PROJECTGRANTSTATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' |
|
||||
translate}}</button>
|
||||
<button mat-stroked-button color="warn" *ngIf="grant?.state === ProjectGrantState.PROJECTGRANTSTATE_INACTIVE"
|
||||
(click)="changeState(ProjectGrantState.PROJECTGRANTSTATE_ACTIVE)">{{'USER.PAGES.REACTIVATE' |
|
||||
translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="h1">{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}</h1>
|
||||
<p class="desc">{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}</p>
|
||||
<cnsl-form-field class="formfield" appearance="outline" *ngIf="grant && grant.grantedRoleKeysList">
|
||||
<cnsl-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="grant.grantedRoleKeysList" multiple (selectionChange)="updateRoles($event)">
|
||||
<mat-option *ngFor="let role of projectRoleOptions" [value]="role.key">
|
||||
{{role.key}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<app-members-table *ngIf="grant" style="width: 100%;" [dataSource]="dataSource" [canWrite]="['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async"
|
||||
[memberRoleOptions]="memberRoleOptions" (updateRoles)="updateMemberRoles($event.member, $event.change)"
|
||||
[factoryLoadFunc]="changePageFactory" (changedSelection)="selection = $event" [refreshTrigger]="changePage">
|
||||
<button selectactions (click)="removeProjectMemberSelection()"
|
||||
[disabled]="(['project.grant.member.delete','project.grant.member.delete:' + grant.grantId] | hasRole | async) == false"
|
||||
matTooltip="{{'ORG_DETAIL.TABLE.DELETE' | translate}}" class="del-button" color="warn" mat-raised-button>
|
||||
<i class="las la-trash"></i>
|
||||
{{'ACTIONS.SELECTIONDELETE' | translate}}
|
||||
</button>
|
||||
<a writeactions color="primary"
|
||||
[disabled]="(['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async) == false"
|
||||
(click)="openAddMember()" color="primary" mat-raised-button>
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
</app-members-table>
|
||||
<div class="divider"></div>
|
||||
|
||||
<h1 class="h1">{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}</h1>
|
||||
<p class="desc">{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}</p>
|
||||
|
||||
<app-members-table *ngIf="grant" style="width: 100%;" [dataSource]="dataSource"
|
||||
[canWrite]="['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async"
|
||||
[memberRoleOptions]="memberRoleOptions" (updateRoles)="updateMemberRoles($event.member, $event.change)"
|
||||
[factoryLoadFunc]="changePageFactory" (changedSelection)="selection = $event" [refreshTrigger]="changePage">
|
||||
<button selectactions (click)="removeProjectMemberSelection()"
|
||||
[disabled]="(['project.grant.member.delete','project.grant.member.delete:' + grant.grantId] | hasRole | async) == false"
|
||||
matTooltip="{{'ORG_DETAIL.TABLE.DELETE' | translate}}" class="del-button" color="warn" mat-raised-button>
|
||||
<i class="las la-trash"></i>
|
||||
{{'ACTIONS.SELECTIONDELETE' | translate}}
|
||||
</button>
|
||||
<a writeactions color="primary"
|
||||
[disabled]="(['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async) == false"
|
||||
(click)="openAddMember()" color="primary" mat-raised-button>
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
</app-members-table>
|
||||
</app-detail-layout>
|
||||
@@ -1,135 +1,136 @@
|
||||
<div class="max-width-container" *ngIf="error">{{error}}</div>
|
||||
|
||||
<app-meta-layout *ngIf="user && (['user.write$','user.write:' + user.id] | hasRole) as canWrite$">
|
||||
<div class="max-width-container">
|
||||
<div class="head">
|
||||
<a (click)="navigateBack()" mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
<div class="head-row">
|
||||
<h1>{{user.human ? user.human?.profile?.displayName : user.machine?.name}}</h1>
|
||||
<p *ngIf="user?.preferredLoginName">{{user?.preferredLoginName}}</p>
|
||||
</div>
|
||||
|
||||
<span class="fill-space"></span>
|
||||
<ng-template appHasRole [appHasRole]="['user.write$', 'user.write:'+user?.id]">
|
||||
<button class="actions-trigger" mat-raised-button color="primary" [matMenuTriggerFor]="actions">
|
||||
<span>{{'ACTIONS.ACTIONS' | translate}}</span>
|
||||
<mat-icon class="icon">keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
<mat-menu #actions="matMenu" xPosition="before">
|
||||
<button mat-menu-item color="warn"
|
||||
*ngIf="user?.state === UserState.USER_STATE_LOCKED"
|
||||
(click)="unlockUser()">{{'USER.PAGES.UNLOCK' |
|
||||
translate}}</button>
|
||||
<button mat-menu-item
|
||||
*ngIf="user?.state !== UserState.USER_STATE_INACTIVE"
|
||||
(click)="changeState(UserState.USER_STATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' |
|
||||
translate}}</button>
|
||||
<button mat-menu-item
|
||||
*ngIf="user?.state == UserState.USER_STATE_INACTIVE"
|
||||
(click)="changeState(UserState.USER_STATE_ACTIVE)">{{'USER.PAGES.REACTIVATE' | translate}}</button>
|
||||
<ng-template appHasRole [appHasRole]="['user.delete$', 'user.delete:'+user?.id]">
|
||||
<button mat-menu-item matTooltip="{{'USER.PAGES.DELETE' | translate}}"
|
||||
(click)="deleteUser()"><span [style.color]="'var(--warn)'">{{'USER.PAGES.DELETE' | translate}}</span></button>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
|
||||
|
||||
<cnsl-info-section class="locked" *ngIf="user?.state === UserState.USER_STATE_LOCKED" type="WARN">{{'USER.PAGES.LOCKEDDESCRIPTION' | translate}}</cnsl-info-section>
|
||||
<span *ngIf="!loading && !user">{{ 'USER.PAGES.NOUSER' | translate }}</span>
|
||||
|
||||
<cnsl-info-row *ngIf="user" [user]="user"></cnsl-info-row>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.read$', 'user.read:'+user?.id]">
|
||||
<app-card *ngIf="user.human" title="{{ 'USER.PROFILE.TITLE' | translate }}">
|
||||
<app-detail-form [preferredLoginName]="user.preferredLoginName" [disabled]="(canWrite$ | async) == false" [genders]="genders" [languages]="languages"
|
||||
[username]="user.userName" [user]="user.human" (submitData)="saveProfile($event)">
|
||||
</app-detail-form>
|
||||
</app-card>
|
||||
|
||||
<app-card *ngIf="user.human" title="{{ 'USER.LOGINMETHODS.TITLE' | translate }}"
|
||||
description="{{ 'USER.LOGINMETHODS.DESCRIPTION' | translate }}">
|
||||
<button card-actions class="icon-button" mat-icon-button (click)="refreshUser()" matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
||||
<mat-icon class="icon">refresh</mat-icon>
|
||||
</button>
|
||||
<app-contact disablePhoneCode="true"
|
||||
[canWrite]="(['user.write:' + user?.id, 'user.write$'] | hasRole | async)" *ngIf="user?.human"
|
||||
[human]="user.human" (editType)="openEditDialog($event)" (deletedPhone)="deletePhone()"
|
||||
(resendEmailVerification)="resendEmailVerification()"
|
||||
(resendPhoneVerification)="resendPhoneVerification()">
|
||||
<button pwdAction [disabled]="(canWrite$ | async) == false" (click)="sendSetPasswordNotification()"
|
||||
mat-stroked-button color="primary" *ngIf="user.state === UserState.USER_STATE_INITIAL">{{
|
||||
'USER.PASSWORD.RESENDNOTIFICATION' | translate }}</button>
|
||||
<button emailAction class="resendemail" *ngIf="user.state == UserState.USER_STATE_INITIAL"
|
||||
mat-stroked-button color="primary" (click)="resendInitEmail()">{{'USER.RESENDINITIALEMAIL' |
|
||||
translate}}</button>
|
||||
</app-contact>
|
||||
</app-card>
|
||||
|
||||
<app-external-idps *ngIf="user && user.human && user.id" [userId]="user.id" [service]="mgmtUserService"></app-external-idps>
|
||||
|
||||
<app-card *ngIf="user.machine" title="{{ 'USER.MACHINE.TITLE' | translate }}">
|
||||
<app-detail-form-machine [disabled]="(canWrite$ | async) == false" [username]="user.userName"
|
||||
[user]="user.machine" (submitData)="saveMachine($event)">
|
||||
</app-detail-form-machine>
|
||||
</app-card>
|
||||
|
||||
<app-card *ngIf="user.machine && user.id" title="{{ 'USER.MACHINE.KEYSTITLE' | translate }}"
|
||||
description="{{ 'USER.MACHINE.KEYSDESC' | translate }}">
|
||||
<app-machine-keys [userId]="user.id"></app-machine-keys>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<app-passwordless *ngIf="user && user.human" [user]="user"></app-passwordless>
|
||||
|
||||
<app-user-mfa *ngIf="user && user.human" [user]="user"></app-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', 'dates', 'roleNamesList']"
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
</app-card>
|
||||
|
||||
<ng-template appHasFeature [appHasFeature]="['metadata.user']">
|
||||
<cnsl-metadata *ngIf="user" [userId]="user.id"></cnsl-metadata>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div *ngIf="user" class="side" metainfo>
|
||||
<div class="meta-details">
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'RESOURCEID' | translate}}:</span>
|
||||
<span *ngIf="user?.id" class="second">{{ user.id }}</span>
|
||||
</div>
|
||||
<div class="meta-row" *ngIf="user?.preferredLoginName">
|
||||
<span class="first">{{'USER.PREFERRED_LOGINNAME' | translate}}</span>
|
||||
<span class="second"><span style="display: block;">{{user.preferredLoginName}}</span></span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'USER.PAGES.STATE' | translate}}</span>
|
||||
<span *ngIf="user && user.state !== undefined" class="state"
|
||||
[ngClass]="{'active': user.state === UserState.USER_STATE_ACTIVE, 'inactive': user.state === UserState.USER_STATE_INACTIVE}">{{'USER.DATA.STATE'+user.state
|
||||
| translate}}</span>
|
||||
</div>
|
||||
<div class="max-width-container">
|
||||
<div class="head">
|
||||
<a (click)="navigateBack()" mat-icon-button>
|
||||
<mat-icon class="icon">arrow_back</mat-icon>
|
||||
</a>
|
||||
<div class="head-row">
|
||||
<h1>{{user.human ? user.human?.profile?.displayName : user.machine?.name}}</h1>
|
||||
<p *ngIf="user?.preferredLoginName">{{user?.preferredLoginName}}</p>
|
||||
</div>
|
||||
|
||||
<mat-tab-group mat-stretch-tabs class="tab-group" disablePagination="true">
|
||||
<mat-tab label="Details">
|
||||
<div class="side-padding">
|
||||
<ng-template appHasRole [appHasRole]="['user.membership.read']">
|
||||
<app-memberships [user]="user" [disabled]="(canWrite$ | async) == false"></app-memberships>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="{{ 'CHANGES.PROJECT.TITLE' | translate }}" class="meta-flex-col">
|
||||
<app-changes class="changes" [refresh]="refreshChanges$" [changeType]="ChangeType.USER" [id]="user.id">
|
||||
</app-changes>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
<span class="fill-space"></span>
|
||||
<ng-template appHasRole [appHasRole]="['user.write$', 'user.write:'+user?.id]">
|
||||
<button class="actions-trigger" mat-raised-button color="primary" [matMenuTriggerFor]="actions">
|
||||
<span>{{'ACTIONS.ACTIONS' | translate}}</span>
|
||||
<mat-icon class="icon">keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
<mat-menu #actions="matMenu" xPosition="before">
|
||||
<button mat-menu-item color="warn" *ngIf="user?.state === UserState.USER_STATE_LOCKED"
|
||||
(click)="unlockUser()">{{'USER.PAGES.UNLOCK' |
|
||||
translate}}</button>
|
||||
<button mat-menu-item *ngIf="user?.state !== UserState.USER_STATE_INACTIVE"
|
||||
(click)="changeState(UserState.USER_STATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' |
|
||||
translate}}</button>
|
||||
<button mat-menu-item *ngIf="user?.state == UserState.USER_STATE_INACTIVE"
|
||||
(click)="changeState(UserState.USER_STATE_ACTIVE)">{{'USER.PAGES.REACTIVATE' | translate}}</button>
|
||||
<ng-template appHasRole [appHasRole]="['user.delete$', 'user.delete:'+user?.id]">
|
||||
<button mat-menu-item matTooltip="{{'USER.PAGES.DELETE' | translate}}" (click)="deleteUser()"><span
|
||||
[style.color]="'var(--warn)'">{{'USER.PAGES.DELETE' | translate}}</span></button>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<mat-progress-bar *ngIf="loading" color="primary" mode="indeterminate"></mat-progress-bar>
|
||||
|
||||
<cnsl-info-section class="locked" *ngIf="user?.state === UserState.USER_STATE_LOCKED" type="WARN">
|
||||
{{'USER.PAGES.LOCKEDDESCRIPTION' | translate}}</cnsl-info-section>
|
||||
<span *ngIf="!loading && !user">{{ 'USER.PAGES.NOUSER' | translate }}</span>
|
||||
|
||||
<cnsl-info-row *ngIf="user" [user]="user"></cnsl-info-row>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.read$', 'user.read:'+user?.id]">
|
||||
<app-card *ngIf="user.human" title="{{ 'USER.PROFILE.TITLE' | translate }}">
|
||||
<app-detail-form [preferredLoginName]="user.preferredLoginName" [disabled]="(canWrite$ | async) == false"
|
||||
[genders]="genders" [languages]="languages" [username]="user.userName" [user]="user.human"
|
||||
(submitData)="saveProfile($event)">
|
||||
</app-detail-form>
|
||||
</app-card>
|
||||
|
||||
<app-card *ngIf="user.human" title="{{ 'USER.LOGINMETHODS.TITLE' | translate }}"
|
||||
description="{{ 'USER.LOGINMETHODS.DESCRIPTION' | translate }}">
|
||||
<button card-actions class="icon-button" mat-icon-button (click)="refreshUser()"
|
||||
matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
||||
<mat-icon class="icon">refresh</mat-icon>
|
||||
</button>
|
||||
<app-contact disablePhoneCode="true" [canWrite]="(['user.write:' + user?.id, 'user.write$'] | hasRole | async)"
|
||||
*ngIf="user?.human" [human]="user.human" (editType)="openEditDialog($event)" (deletedPhone)="deletePhone()"
|
||||
(resendEmailVerification)="resendEmailVerification()" (resendPhoneVerification)="resendPhoneVerification()">
|
||||
<button pwdAction [disabled]="(canWrite$ | async) == false" (click)="sendSetPasswordNotification()"
|
||||
mat-stroked-button color="primary" *ngIf="user.state === UserState.USER_STATE_INITIAL">{{
|
||||
'USER.PASSWORD.RESENDNOTIFICATION' | translate }}</button>
|
||||
<button emailAction class="resendemail" *ngIf="user.state == UserState.USER_STATE_INITIAL" mat-stroked-button
|
||||
color="primary" (click)="resendInitEmail()">{{'USER.RESENDINITIALEMAIL' |
|
||||
translate}}</button>
|
||||
</app-contact>
|
||||
</app-card>
|
||||
|
||||
<app-external-idps *ngIf="user && user.human && user.id" [userId]="user.id" [service]="mgmtUserService">
|
||||
</app-external-idps>
|
||||
|
||||
<app-card *ngIf="user.machine" title="{{ 'USER.MACHINE.TITLE' | translate }}">
|
||||
<app-detail-form-machine [disabled]="(canWrite$ | async) == false" [username]="user.userName"
|
||||
[user]="user.machine" (submitData)="saveMachine($event)">
|
||||
</app-detail-form-machine>
|
||||
</app-card>
|
||||
|
||||
<app-card *ngIf="user.machine && user.id" title="{{ 'USER.MACHINE.KEYSTITLE' | translate }}"
|
||||
description="{{ 'USER.MACHINE.KEYSDESC' | translate }}">
|
||||
<app-machine-keys [userId]="user.id"></app-machine-keys>
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<app-passwordless *ngIf="user && user.human" [user]="user"></app-passwordless>
|
||||
|
||||
<app-user-mfa *ngIf="user && user.human" [user]="user"></app-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', 'dates', 'roleNamesList']"
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
</app-card>
|
||||
|
||||
<ng-template appHasFeature [appHasFeature]="['metadata.user']">
|
||||
<cnsl-metadata *ngIf="user" [userId]="user.id"></cnsl-metadata>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div *ngIf="user" class="side" metainfo>
|
||||
<div class="meta-details">
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'RESOURCEID' | translate}}:</span>
|
||||
<span *ngIf="user?.id" class="second">{{ user.id }}</span>
|
||||
</div>
|
||||
<div class="meta-row" *ngIf="user?.preferredLoginName">
|
||||
<span class="first">{{'USER.PREFERRED_LOGINNAME' | translate}}</span>
|
||||
<span class="second"><span style="display: block;">{{user.preferredLoginName}}</span></span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="first">{{'USER.PAGES.STATE' | translate}}</span>
|
||||
<span *ngIf="user && user.state !== undefined" class="state"
|
||||
[ngClass]="{'active': user.state === UserState.USER_STATE_ACTIVE, 'inactive': user.state === UserState.USER_STATE_INACTIVE}">{{'USER.DATA.STATE'+user.state
|
||||
| translate}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-tab-group mat-stretch-tabs class="tab-group" disablePagination="true">
|
||||
<mat-tab label="Details">
|
||||
<div class="side-padding">
|
||||
<ng-template appHasRole [appHasRole]="['user.membership.read']">
|
||||
<app-memberships [user]="user" [disabled]="(canWrite$ | async) == false"></app-memberships>
|
||||
</ng-template>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="{{ 'CHANGES.PROJECT.TITLE' | translate }}" class="meta-flex-col">
|
||||
<app-changes class="changes" [refresh]="refreshChanges$" [changeType]="ChangeType.USER" [id]="user.id">
|
||||
</app-changes>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</app-meta-layout>
|
||||
@@ -37,6 +37,8 @@ export class UserDetailComponent implements OnInit {
|
||||
public EditDialogType: any = EditDialogType;
|
||||
public refreshChanges$: EventEmitter<void> = new EventEmitter();
|
||||
|
||||
public error: string = '';
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
private route: ActivatedRoute,
|
||||
@@ -56,7 +58,8 @@ export class UserDetailComponent implements OnInit {
|
||||
this.user = resp.user;
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this.error = err.message ?? '';
|
||||
this.toast.showError(err);
|
||||
});
|
||||
|
||||
this.mgmtUserService.listUserMetadata(id, 0, 100, []).then(resp => {
|
||||
|
||||
Reference in New Issue
Block a user