import { SelectionModel } from '@angular/cdk/collections'; import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; 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 { AddKeyDialogComponent, AddKeyDialogType } from 'src/app/modules/add-key-dialog/add-key-dialog.component'; import { ShowKeyDialogComponent } from 'src/app/modules/show-key-dialog/show-key-dialog.component'; import { Key, KeyType } from 'src/app/proto/generated/zitadel/auth_n_key_pb'; import { ListMachineKeysResponse } from 'src/app/proto/generated/zitadel/management_pb'; import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; import { PaginatorComponent } from '../paginator/paginator.component'; import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component'; @Component({ selector: 'cnsl-machine-keys', templateUrl: './machine-keys.component.html', styleUrls: ['./machine-keys.component.scss'], }) export class MachineKeysComponent implements OnInit { @Input() userId?: string; @ViewChild(PaginatorComponent) public paginator!: PaginatorComponent; public dataSource: MatTableDataSource = new MatTableDataSource(); public selection: SelectionModel = new SelectionModel(true, []); public keyResult?: ListMachineKeysResponse.AsObject; private loadingSubject: BehaviorSubject = new BehaviorSubject(false); public loading$: Observable = this.loadingSubject.asObservable(); @Input() public displayedColumns: string[] = ['id', 'type', 'creationDate', 'expirationDate', 'actions']; @Output() public changedSelection: EventEmitter> = new EventEmitter(); constructor( public translate: TranslateService, private mgmtService: 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(): void { this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize); } public deleteKey(key: Key.AsObject): void { if (this.userId) { const dialogRef = this.dialog.open(WarnDialogComponent, { data: { confirmKey: 'ACTIONS.DELETE', cancelKey: 'ACTIONS.CANCEL', titleKey: 'USER.MACHINE.DIALOG.DELETE_KEY.TITLE', descriptionKey: 'USER.MACHINE.DIALOG.DELETE_KEY.DESCRIPTION', }, width: '400px', }); dialogRef.afterClosed().subscribe((resp) => { if (resp && this.userId) { this.mgmtService .removeMachineKey(key.id, this.userId) .then(() => { this.selection.clear(); this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true); this.changePage(); }) .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: KeyType = resp.type; let date: Timestamp | undefined; if (resp.date as Moment) { const ts = new Timestamp(); 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 && this.userId) { this.mgmtService .addMachineKey(this.userId, type, date) .then((response) => { if (response) { setTimeout(() => { this.refreshPage(); }, 1000); this.dialog.open(ShowKeyDialogComponent, { data: { key: response, type: AddKeyDialogType.MACHINE, }, width: '400px', }); } }) .catch((error: any) => { this.toast.showError(error); }); } } }); } private async getData(limit: number, offset: number): Promise { this.loadingSubject.next(true); if (this.userId) { this.mgmtService .listMachineKeys(this.userId, limit, offset) .then((resp) => { this.keyResult = resp; if (resp.resultList) { this.dataSource.data = resp.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); } }