blob: 7d83409cea8aa44cf5063174d4aa397863a1641f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Component, OnInit, ViewChild} from '@angular/core';
import {TokenManagementService} from './token.management.service';
import {KnoxToken} from './knox.token';
import {MatTableDataSource} from '@angular/material/table';
import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import {MatSlideToggleChange} from '@angular/material/slide-toggle';
import {SelectionModel} from '@angular/cdk/collections';
@Component({
selector: 'app-token-management',
templateUrl: './token.management.component.html',
styleUrls: ['../assets/token-management-ui.css'],
providers: [TokenManagementService]
})
export class TokenManagementComponent implements OnInit {
pathParts = window.location.pathname.split('/');
topologyContext = '/' + this.pathParts[1] + '/' + this.pathParts[2] + '/';
tokenGenerationPageURL = this.topologyContext + 'token-generation/index.html';
userName: string;
canSeeAllTokens: boolean;
currentKnoxSsoCookieTokenId: string;
knoxTokens: MatTableDataSource<KnoxToken> = new MatTableDataSource();
selection = new SelectionModel<KnoxToken>(true, []);
allKnoxTokens: KnoxToken[];
displayedColumns = ['select', 'tokenId', 'issued', 'expires', 'userName', 'impersonated', 'knoxSso', 'comment', 'metadata', 'actions'];
@ViewChild('knoxTokensPaginator') paginator: MatPaginator;
@ViewChild('knoxTokensSort') sort: MatSort = new MatSort();
showDisabledKnoxSsoCookies: boolean;
showMyTokensOnly: boolean;
showDisableSelectedTokensButton: boolean;
showEnableSelectedTokensButton: boolean;
showRevokeSelectedTokensButton: boolean;
constructor(private tokenManagementService: TokenManagementService) {
this.showDisabledKnoxSsoCookies = true;
let isMatch: (record: KnoxToken, filter: String) => boolean = (record, filter) => {
let normalizedFilter = filter.trim().toLocaleLowerCase();
let matchesTokenId = record.tokenId.toLocaleLowerCase().includes(normalizedFilter);
let matchesComment = record.metadata.comment && record.metadata.comment.toLocaleLowerCase().includes(normalizedFilter);
let matchesUserName = record.metadata.userName.toLocaleLowerCase().includes(normalizedFilter);
let matchesCreatedBy = record.metadata.createdBy && record.metadata.createdBy.toLocaleLowerCase().includes(normalizedFilter);
let matchesCustomMetadata = false;
if (record.metadata.customMetadataMap) {
for (let entry of Array.from(Object.entries(record.metadata.customMetadataMap))) {
if (entry[0].toLocaleLowerCase().includes(normalizedFilter) || entry[1].toLocaleLowerCase().includes(normalizedFilter)) {
matchesCustomMetadata = true;
break;
}
}
} else {
matchesCustomMetadata = true; // nothing to match
}
return matchesTokenId || matchesComment || matchesCustomMetadata || matchesUserName || matchesCreatedBy;
};
this.knoxTokens.filterPredicate = function (record, filter) {
return isMatch(record, filter);
};
this.knoxTokens.sortingDataAccessor = (item, property) => {
switch(property) {
case 'metadata.comment': return item.metadata.comment;
case 'metadata.username': return item.metadata.userName;
case 'metadata.createdBy': return item.metadata.createdBy;
default: return item[property];
}
};
}
onChangeShowDisabledCookies(value: MatSlideToggleChange) {
this.showDisabledKnoxSsoCookies = value.checked;
this.actualizeTokensToDisplay();
}
onChangeShowMyTokensOnly(value: MatSlideToggleChange) {
this.showMyTokensOnly = value.checked;
this.actualizeTokensToDisplay();
}
ngOnInit(): void {
console.debug('TokenManagementComponent --> ngOnInit()');
this.tokenManagementService.getSessionInformation()
.then(sessionInformation => {
this.canSeeAllTokens = sessionInformation.canSeeAllTokens;
this.currentKnoxSsoCookieTokenId = sessionInformation.currentKnoxSsoCookieTokenId;
this.setUserName(sessionInformation.user);
});
}
setUserName(userName: string) {
this.userName = userName;
this.fetchKnoxTokens();
}
userCanSeeAllTokens(): boolean {
return this.canSeeAllTokens;
}
fetchKnoxTokens(): void {
this.tokenManagementService.getKnoxTokens(this.userName, this.canSeeAllTokens)
.then(tokens => this.updateTokens(tokens));
}
private isMyToken(token: KnoxToken): boolean {
return token.metadata.userName === this.userName || (token.metadata.createdBy && token.metadata.createdBy === this.userName);
}
private isDisabledKnoxSsoCookie(token: KnoxToken): boolean {
return token.metadata.knoxSsoCookie && !token.metadata.enabled;
}
private updateTokens(tokens: KnoxToken[]): void {
this.allKnoxTokens = tokens;
this.selection.clear();
this.showHideBatchOperations();
this.actualizeTokensToDisplay();
}
private actualizeTokensToDisplay(): void {
let tokensToDisplay = this.allKnoxTokens;
if (!this.showDisabledKnoxSsoCookies) {
tokensToDisplay = tokensToDisplay.filter(token => !this.isDisabledKnoxSsoCookie(token));
}
if (this.showMyTokensOnly) {
tokensToDisplay = tokensToDisplay.filter(token => this.isMyToken(token));
}
this.knoxTokens.data = tokensToDisplay;
setTimeout(() => {
this.knoxTokens.paginator = this.paginator;
this.knoxTokens.sort = this.sort;
});
}
disableToken(tokenId: string) {
this.tokenManagementService.setEnabledDisabledFlag(false, tokenId).then((response: string) => this.fetchKnoxTokens());
}
disableSelectedTokens(): void {
this.tokenManagementService.setEnabledDisabledFlagsInBatch(false, this.getSelectedTokenIds())
.then((response: string) => this.fetchKnoxTokens());
}
private getSelectedTokenIds(): string[] {
let selectedTokenIds = [] as string[];
this.selection.selected.forEach(token => selectedTokenIds.push(token.tokenId));
return selectedTokenIds;
}
enableToken(tokenId: string) {
this.tokenManagementService.setEnabledDisabledFlag(true, tokenId).then((response: string) => this.fetchKnoxTokens());
}
enableSelectedTokens(): void {
this.tokenManagementService.setEnabledDisabledFlagsInBatch(true, this.getSelectedTokenIds())
.then((response: string) => this.fetchKnoxTokens());
}
revokeToken(tokenId: string) {
this.tokenManagementService.revokeToken(tokenId).then((response: string) => this.fetchKnoxTokens());
}
revokeSelectedTokens() {
this.tokenManagementService.revokeTokensInBatch(this.getSelectedTokenIds()).then((response: string) => this.fetchKnoxTokens());
}
gotoTokenGenerationPage() {
window.open(this.tokenGenerationPageURL, '_blank');
}
formatDateTime(dateTime: number) {
return dateTime < 0 ? 'Never' : new Date(dateTime).toLocaleString();
}
isTokenExpired(expiration: number): boolean {
return expiration < 0 ? false : Date.now() > expiration;
}
getExpirationColor(expiration: number): string {
return this.isTokenExpired(expiration) ? 'red' : 'green';
}
getCustomMetadataArray(knoxToken: KnoxToken): [string, string][] {
let mdMap = new Map();
if (knoxToken.metadata.customMetadataMap) {
mdMap = new Map(Object.entries(knoxToken.metadata.customMetadataMap));
}
return Array.from(mdMap);
}
isKnoxSsoCookie(knoxToken: KnoxToken): boolean {
return knoxToken.metadata.knoxSsoCookie;
}
isDisabledKnoxSSoCookie(knoxToken: KnoxToken): boolean {
return this.isKnoxSsoCookie(knoxToken) && !knoxToken.metadata.enabled;
}
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
this.knoxTokens.filter = filterValue;
}
/** Whether the number of selected elements matches the total number of rows. */
isAllSelected(): boolean {
const numSelected = this.selection.selected.length;
const numRows = this.knoxTokens.filteredData.length;
return numSelected === numRows;
}
/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle(): void {
if (this.isAllSelected()) {
this.selection.clear();
} else {
this.knoxTokens.filteredData.forEach(row => {
if (!this.isDisabledKnoxSsoCookie(row)) {
this.selection.select(row);
}
});
}
this.showHideBatchOperations();
}
onRowSelectionChange(knoxToken: KnoxToken): void {
this.selection.toggle(knoxToken);
this.showHideBatchOperations();
}
showHideBatchOperations() {
if (this.selection.isEmpty()) {
this.showDisableSelectedTokensButton = false;
this.showEnableSelectedTokensButton = false;
this.showRevokeSelectedTokensButton = false;
} else {
this.showDisableSelectedTokensButton = this.selectionHasZeroExpiredToken(); // expired tokens must not be disabled
this.showEnableSelectedTokensButton = this.selectionHasZeroExpiredToken(); // expired tokens must not be enabled
this.showRevokeSelectedTokensButton = this.selectionHasZeroKnoxSsoCookie(); // KnoxSSO cookies must not be revoked
}
}
private selectionHasZeroKnoxSsoCookie(): boolean {
return this.selection.selected.every(token => !token.metadata.knoxSsoCookie);
}
private selectionHasZeroExpiredToken(): boolean {
return this.selection.selected.every(token => !this.isTokenExpired(token.expirationLong));
}
getFontWeight(token: KnoxToken): string {
return this.isCurrentKnoxSsoCookietoken(token) ? 'bold' : 'normal';
}
private isCurrentKnoxSsoCookietoken(token: KnoxToken): boolean {
return this.isKnoxSsoCookie(token) && token.tokenId === this.currentKnoxSsoCookieTokenId;
}
}