mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-13 18:22:12 +00:00
fix: Merge master (#1373)
* feat(console): app infos, api apps, fix redirects on create, fix role update, redesign idps, policy, prettier history (#1310) * idp fixes * idp cleanup and rehaul, complexity policy preview * policy fixes, orthodox redirect * link component, add links to policies * redirect pipe, state labels * Cnsl map changes (#1315) * map changes to different format * fix changes layout, cursor * set asc values * fix user appearance in changes, index * changes * app create with api * api app create * auth method for api config * authmethods, app card for api, authmethod in dev create * move machine keys to own module * jwt method for oidc * fix app edit * save toast * fix changes, change det in app detail * regenerate secret * chore(deps-dev): bump @angular-devkit/build-angular in /console (#1324) Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1102.0 to 0.1102.1. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/commits) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix policy backlink Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit40a7e958d7) * fix: i18n refs, unnecessary logs (#1343) (cherry picked from commit2e04c977eb) * fix: tos link (#1345) (cherry picked from commit5333ef10c1) * fix: reactivate/deactivate idp, remove idp provider (#1348) * fix: reactivate/deactivate idp, remove idp provider * fix build * fix(console): add jwt to selection, idp deactivate reactivate (#1347) * fix: log error on idp change * add jwt to method selection Co-authored-by: Max Peintner <max@caos.ch> (cherry picked from commitc8b9888427) * fix: reactivate/deactivate idp (#1351) (cherry picked from commit54f395e2e0) Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
@@ -19,9 +19,10 @@
|
||||
<div class="left">
|
||||
<span class="label">{{ 'USER.EMAIL' | translate }}</span>
|
||||
<span class="name">{{human?.email}}</span>
|
||||
<span *ngIf="human?.isEmailVerified" class="state verified">{{'USER.EMAILVERIFIED' | translate}}</span>
|
||||
<span *ngIf="human?.isEmailVerified" class="contact-state verified">{{'USER.EMAILVERIFIED' |
|
||||
translate}}</span>
|
||||
<div *ngIf="!human?.isEmailVerified" class="block">
|
||||
<span class="state notverified">{{'USER.NOTVERIFIED' | translate}}</span>
|
||||
<span class="contact-state notverified">{{'USER.NOTVERIFIED' | translate}}</span>
|
||||
|
||||
<ng-container *ngIf="human?.email">
|
||||
<a *ngIf="canWrite && state != userStateEnum?.USERSTATE_INITIAL" class="verify"
|
||||
@@ -45,9 +46,10 @@
|
||||
<div class="left">
|
||||
<span class="label">{{ 'USER.PHONE' | translate }}</span>
|
||||
<span class="name">{{human?.phone ? human.phone : ('USER.PHONEEMPTY' | translate)}}</span>
|
||||
<span *ngIf="human?.isPhoneVerified" class="state verified">{{'USER.PHONEVERIFIED' | translate}}</span>
|
||||
<span *ngIf="human?.isPhoneVerified" class="contact-state verified">{{'USER.PHONEVERIFIED' |
|
||||
translate}}</span>
|
||||
<div *ngIf="!human?.isPhoneVerified" class="block">
|
||||
<span class="state notverified">{{'USER.NOTVERIFIED' | translate}}</span>
|
||||
<span class="contact-state notverified">{{'USER.NOTVERIFIED' | translate}}</span>
|
||||
|
||||
<ng-container *ngIf="human?.phone">
|
||||
<a *ngIf="!disablePhoneCode && canWrite" class="verify"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.state {
|
||||
.contact-state {
|
||||
font-size: 14px;
|
||||
margin-bottom: .5rem;
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<span class="title" mat-dialog-title>{{'USER.MACHINE.ADD.TITLE' | translate}}</span>
|
||||
<div mat-dialog-content>
|
||||
<p class="desc"> {{'USER.MACHINE.ADD.DESCRIPTION' | translate}}</p>
|
||||
|
||||
<cnsl-form-field class="form-field" appearance="outline">
|
||||
<cnsl-label>{{'USER.MACHINE.TYPE' | translate}}</cnsl-label>
|
||||
<mat-select [(ngModel)]="type">
|
||||
<mat-option *ngFor="let t of types" [value]="t">
|
||||
{{'USER.MACHINE.KEYTYPES.'+t | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="form-field" appearance="outline">
|
||||
<cnsl-label>{{'USER.MACHINE.CHOOSEEXPIRY' | translate}} (optional)</cnsl-label>
|
||||
<input cnslInput [matDatepicker]="picker" [min]="startDate" [formControl]="dateControl">
|
||||
<mat-datepicker-toggle style="top: 0;" cnslSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker>
|
||||
<span cnsl-error *ngIf="dateControl?.errors?.matDatepickerMin?.min">
|
||||
{{'USER.MACHINE.CHOOSEDATEAFTER' | translate}}:
|
||||
{{dateControl?.errors?.matDatepickerMin.min.toDate() | localizedDate: 'EEE dd. MMM'}}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class=" action">
|
||||
<button mat-button (click)="closeDialog()">
|
||||
{{'ACTIONS.CANCEL' | translate}}
|
||||
</button>
|
||||
|
||||
<button color="primary" mat-raised-button class="ok-button" [disabled]="type == undefined || dateControl.invalid"
|
||||
(click)="closeDialogWithSuccess()">
|
||||
{{'ACTIONS.ADD' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
@@ -1,22 +0,0 @@
|
||||
.title {
|
||||
font-size: 1.2rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: var(--grey);
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.ok-button {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { AddKeyDialogComponent } from './add-key-dialog.component';
|
||||
|
||||
describe('AddKeyDialogComponent', () => {
|
||||
let component: AddKeyDialogComponent;
|
||||
let fixture: ComponentFixture<AddKeyDialogComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AddKeyDialogComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AddKeyDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MachineKeyType } from 'src/app/proto/generated/management_pb';
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-key-dialog',
|
||||
templateUrl: './add-key-dialog.component.html',
|
||||
styleUrls: ['./add-key-dialog.component.scss'],
|
||||
})
|
||||
export class AddKeyDialogComponent {
|
||||
public startDate: Date = new Date();
|
||||
types: MachineKeyType[] = [
|
||||
MachineKeyType.MACHINEKEY_JSON,
|
||||
];
|
||||
public type: MachineKeyType = MachineKeyType.MACHINEKEY_JSON;
|
||||
public dateControl: FormControl = new FormControl('', []);
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AddKeyDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {
|
||||
const today = new Date();
|
||||
this.startDate.setDate(today.getDate() + 1);
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
public closeDialogWithSuccess(): void {
|
||||
this.dialogRef.close({ type: this.type, date: this.dateControl.value });
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
|
||||
import { AddKeyDialogComponent } from './add-key-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AddKeyDialogComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslateModule,
|
||||
MatButtonModule,
|
||||
InputModule,
|
||||
MatSelectModule,
|
||||
MatIconModule,
|
||||
FormsModule,
|
||||
MatDatepickerModule,
|
||||
MatMomentDateModule,
|
||||
ReactiveFormsModule,
|
||||
LocalizedDatePipeModule,
|
||||
],
|
||||
})
|
||||
export class AddKeyDialogModule { }
|
||||
@@ -1,65 +0,0 @@
|
||||
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
|
||||
[timestamp]="keyResult?.viewTimestamp" [selection]="selection">
|
||||
<ng-template appHasRole [appHasRole]="['user.write']" actions>
|
||||
<button color="warn" [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) == false"
|
||||
(click)="deleteSelectedKeys()" matTooltip="{{'ACTIONS.DELETE' | translate}}" class="icon-button"
|
||||
mat-icon-button *ngIf="selection.hasValue()">
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
<a [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) == false" color="primary"
|
||||
mat-raised-button (click)="openAddKey()">
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
</ng-template>
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="table" mat-table [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox color="primary" (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let key">
|
||||
<mat-checkbox color="primary" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(key) : null" [checked]="selection.isSelected(key)">
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="id">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.ID' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let key"> {{key?.id}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.TYPE' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let key"> {{'USER.MACHINE.KEYTYPES.'+key?.type | translate}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="creationDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.CREATIONDATE' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let key">
|
||||
{{key.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm'}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="expirationDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.EXPIRATIONDATE' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let key">
|
||||
{{key.expirationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm'}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||
[routerLink]="row.id ? ['/users', row.id ]: null">
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<mat-paginator #paginator class="paginator" [length]="keyResult?.totalResult || 0" [pageSize]="10"
|
||||
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></mat-paginator>
|
||||
</div>
|
||||
</app-refresh-table>
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
.table-wrapper {
|
||||
overflow: auto;
|
||||
|
||||
.table,
|
||||
.paginator {
|
||||
width: 100%;
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0 1rem;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
outline: none;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { MachineKeysComponent } from './machine-keys.component';
|
||||
|
||||
describe('MachineKeysComponent', () => {
|
||||
let component: MachineKeysComponent;
|
||||
let fixture: ComponentFixture<MachineKeysComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MachineKeysComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MachineKeysComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,137 +0,0 @@
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { Moment } from 'moment';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { MachineKeySearchResponse, MachineKeyType, MachineKeyView } from 'src/app/proto/generated/management_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { AddKeyDialogComponent } from './add-key-dialog/add-key-dialog.component';
|
||||
import { ShowKeyDialogComponent } from './show-key-dialog/show-key-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-machine-keys',
|
||||
templateUrl: './machine-keys.component.html',
|
||||
styleUrls: ['./machine-keys.component.scss'],
|
||||
})
|
||||
export class MachineKeysComponent implements OnInit {
|
||||
@Input() userId!: string;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
public dataSource: MatTableDataSource<MachineKeyView.AsObject> = new MatTableDataSource<MachineKeyView.AsObject>();
|
||||
public selection: SelectionModel<MachineKeyView.AsObject> = new SelectionModel<MachineKeyView.AsObject>(true, []);
|
||||
public keyResult!: MachineKeySearchResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
@Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate'];
|
||||
|
||||
@Output() public changedSelection: EventEmitter<Array<MachineKeyView.AsObject>> = new EventEmitter();
|
||||
|
||||
constructor(public translate: TranslateService, private userService: ManagementService, private dialog: MatDialog,
|
||||
private toast: ToastService) {
|
||||
this.selection.changed.subscribe(() => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.getData(10, 0);
|
||||
}
|
||||
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.data.length;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.data.forEach(row => this.selection.select(row));
|
||||
}
|
||||
|
||||
|
||||
public changePage(event: PageEvent): void {
|
||||
this.getData(event.pageSize, event.pageIndex * event.pageSize);
|
||||
}
|
||||
|
||||
public deleteSelectedKeys(): void {
|
||||
const mappedDeletions = this.selection.selected.map(value => {
|
||||
return this.userService.DeleteMachineKey(value.id, this.userId);
|
||||
});
|
||||
Promise.all(mappedDeletions).then(() => {
|
||||
this.selection.clear();
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
|
||||
this.getData(10, 0);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public openAddKey(): void {
|
||||
const dialogRef = this.dialog.open(AddKeyDialogComponent, {
|
||||
data: {},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
const type: MachineKeyType = resp.type;
|
||||
|
||||
let date: Timestamp | undefined;
|
||||
|
||||
if (resp.date as Moment) {
|
||||
const ts = new Timestamp();
|
||||
console.log(resp.date.toDate());
|
||||
const milliseconds = resp.date.toDate().getTime();
|
||||
const seconds = Math.abs(milliseconds / 1000);
|
||||
const nanos = (milliseconds - seconds * 1000) * 1000 * 1000;
|
||||
ts.setSeconds(seconds);
|
||||
ts.setNanos(nanos);
|
||||
date = ts;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
return this.userService.AddMachineKey(this.userId, type, date).then((response) => {
|
||||
if (response) {
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
|
||||
this.dialog.open(ShowKeyDialogComponent, {
|
||||
data: {
|
||||
key: response.toObject(),
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
}
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getData(limit: number, offset: number): Promise<void> {
|
||||
this.loadingSubject.next(true);
|
||||
|
||||
this.userService.SearchMachineKeys(this.userId, limit, offset).then(resp => {
|
||||
this.keyResult = resp.toObject();
|
||||
this.dataSource.data = this.keyResult.resultList;
|
||||
this.loadingSubject.next(false);
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
}
|
||||
|
||||
public refreshPage(): void {
|
||||
this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<span class="title" mat-dialog-title>{{'USER.MACHINE.ADDED.TITLE' | translate}}</span>
|
||||
<div mat-dialog-content>
|
||||
<p class="desc"> {{'USER.MACHINE.ADDED.DESCRIPTION' | translate}}</p>
|
||||
<ng-container *ngIf="addedKey">
|
||||
<div class="row">
|
||||
<p class="left">{{'USER.MACHINE.ID' | translate}}</p>
|
||||
<p class="right">{{addedKey?.id}}</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="left">{{'USER.MACHINE.TYPE' | translate}}</p>
|
||||
<p class="right">{{'USER.MACHINE.KEYTYPES.'+addedKey?.type | translate}}</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="left">{{'USER.MACHINE.CREATIONDATE' | translate}}</p>
|
||||
<p class="right">{{addedKey?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM YYYY, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="left">{{'USER.MACHINE.EXPIRATIONDATE' | translate}}</p>
|
||||
<p class="right">{{addedKey?.expirationDate | timestampToDate | localizedDate: 'EEE dd. MMM YYYY, HH:mm'}}
|
||||
</p>
|
||||
</div>
|
||||
<button class="download-button" mat-stroked-button color="primary" (click)="saveFile()">Download</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button color="primary" mat-raised-button class="ok-button" (click)="closeDialog()">
|
||||
{{'ACTIONS.CLOSE' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
@@ -1,51 +0,0 @@
|
||||
.title {
|
||||
font-size: 1.2rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: rgb(201, 51, 71);
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.ok-button {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
font-size: 14px;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.left {
|
||||
color: var(--grey);
|
||||
margin-right: 1rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.download-button {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ShowKeyDialogComponent } from './show-key-dialog.component';
|
||||
|
||||
describe('ShowKeyDialogComponent', () => {
|
||||
let component: ShowKeyDialogComponent;
|
||||
let fixture: ComponentFixture<ShowKeyDialogComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ShowKeyDialogComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ShowKeyDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { AddMachineKeyResponse } from 'src/app/proto/generated/management_pb';
|
||||
|
||||
@Component({
|
||||
selector: 'app-show-key-dialog',
|
||||
templateUrl: './show-key-dialog.component.html',
|
||||
styleUrls: ['./show-key-dialog.component.scss'],
|
||||
})
|
||||
export class ShowKeyDialogComponent {
|
||||
public addedKey!: AddMachineKeyResponse.AsObject;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<ShowKeyDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) {
|
||||
this.addedKey = data.key;
|
||||
}
|
||||
|
||||
public saveFile(): void {
|
||||
const json = atob(this.addedKey.keyDetails.toString());
|
||||
const blob = new Blob([json], { type: 'text/plain;charset=utf-8' });
|
||||
saveAs(blob, `${this.addedKey.id}.json`);
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { ShowKeyDialogComponent } from './show-key-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ShowKeyDialogComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslateModule,
|
||||
MatButtonModule,
|
||||
LocalizedDatePipeModule,
|
||||
TimestampToDatePipeModule,
|
||||
],
|
||||
})
|
||||
export class ShowKeyDialogModule { }
|
||||
@@ -42,15 +42,13 @@ import { ContactComponent } from './contact/contact.component';
|
||||
import { DetailFormMachineModule } from './detail-form-machine/detail-form-machine.module';
|
||||
import { DetailFormModule } from './detail-form/detail-form.module';
|
||||
import { ExternalIdpsComponent } from './external-idps/external-idps.component';
|
||||
import { AddKeyDialogModule } from './machine-keys/add-key-dialog/add-key-dialog.module';
|
||||
import { MachineKeysComponent } from './machine-keys/machine-keys.component';
|
||||
import { ShowKeyDialogModule } from './machine-keys/show-key-dialog/show-key-dialog.module';
|
||||
import { MembershipsComponent } from './memberships/memberships.component';
|
||||
import { PasswordComponent } from './password/password.component';
|
||||
import { UserDetailRoutingModule } from './user-detail-routing.module';
|
||||
import { PasswordlessComponent } from './user-detail/passwordless/passwordless.component';
|
||||
import { UserDetailComponent } from './user-detail/user-detail.component';
|
||||
import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
import { MachineKeysModule } from 'src/app/modules/machine-keys/machine-keys.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -66,7 +64,6 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
PasswordComponent,
|
||||
CodeDialogComponent,
|
||||
MembershipsComponent,
|
||||
MachineKeysComponent,
|
||||
ExternalIdpsComponent,
|
||||
ContactComponent,
|
||||
ResendEmailDialogComponent,
|
||||
@@ -84,8 +81,6 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
MatDialogModule,
|
||||
QRCodeModule,
|
||||
MetaLayoutModule,
|
||||
AddKeyDialogModule,
|
||||
ShowKeyDialogModule,
|
||||
MatCheckboxModule,
|
||||
HasRolePipeModule,
|
||||
UserGrantsModule,
|
||||
@@ -108,6 +103,7 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
TimestampToDatePipeModule,
|
||||
LocalizedDatePipeModule,
|
||||
InputModule,
|
||||
MachineKeysModule,
|
||||
],
|
||||
})
|
||||
export class UserDetailModule { }
|
||||
|
||||
@@ -51,7 +51,6 @@ export class PasswordlessComponent implements OnInit, OnDestroy {
|
||||
|
||||
public getPasswordless(): void {
|
||||
this.service.GetPasswordless(this.user.id).then(passwordless => {
|
||||
console.log(passwordless.toObject().tokensList);
|
||||
this.dataSource = new MatTableDataSource(passwordless.toObject().tokensList);
|
||||
this.dataSource.sort = this.sort;
|
||||
}).catch(error => {
|
||||
|
||||
@@ -47,7 +47,6 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
||||
|
||||
public getMFAs(): void {
|
||||
this.mgmtUserService.getUserMfas(this.user.id).then(mfas => {
|
||||
console.log(mfas.toObject().mfasList);
|
||||
this.dataSource = new MatTableDataSource(mfas.toObject().mfasList);
|
||||
this.dataSource.sort = this.sort;
|
||||
}).catch(error => {
|
||||
@@ -56,7 +55,6 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public deleteMFA(type: MfaType, id?: string): void {
|
||||
console.log(type, id);
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
@@ -82,7 +80,6 @@ export class UserMfaComponent implements OnInit, OnDestroy {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (type === MfaType.MFATYPE_U2F && id) {
|
||||
console.log(this.user.id, id);
|
||||
this.mgmtUserService.RemoveMfaU2F(this.user.id, id).then(() => {
|
||||
this.toast.showInfo('USER.TOAST.U2FREMOVED', true);
|
||||
|
||||
|
||||
@@ -69,21 +69,3 @@
|
||||
td {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.state {
|
||||
border-radius: 50vw;
|
||||
padding: 2px .5rem;
|
||||
letter-spacing: .05em;
|
||||
font-size: 11px;
|
||||
background-color: #8795a120;
|
||||
|
||||
&.active {
|
||||
background-color: #85d996;
|
||||
color: black;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
background-color: #ff8981;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user