This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new fda911198 KNOX-3187 - Show pop-up window on Token 
Management/Generation pages when Knox token hash key is missing (#1082)
fda911198 is described below

commit fda91119814b84b1e8bfa7ac95755e25c0f7d85e
Author: Sandor Molnar <[email protected]>
AuthorDate: Tue Sep 9 15:42:42 2025 +0200

    KNOX-3187 - Show pop-up window on Token Management/Generation pages when 
Knox token hash key is missing (#1082)
---
 .../app/token-generation.component.ts              | 34 +++++++++++++++++-----
 .../app/token-generation.service.ts                | 21 ++++++++++++-
 .../app/token.management.component.html            |  8 ++---
 .../app/token.management.component.ts              | 33 +++++++++++++++++++--
 .../app/token.management.service.ts                | 20 +++++++++++++
 5 files changed, 101 insertions(+), 15 deletions(-)

diff --git 
a/knox-token-generation-ui/token-generation/app/token-generation.component.ts 
b/knox-token-generation-ui/token-generation/app/token-generation.component.ts
index e155fc931..4eb703089 100644
--- 
a/knox-token-generation-ui/token-generation/app/token-generation.component.ts
+++ 
b/knox-token-generation-ui/token-generation/app/token-generation.component.ts
@@ -68,6 +68,7 @@ export class TokenGenerationComponent implements OnInit {
   // Data coming from TokenStateService status request
   tssStatus: TssStatusData;
 
+
   constructor(private http: HttpClient, private tokenGenService: 
TokenGenService) {
     this.tssStatusMessageLevel = 'info';
     this.tssStatusMessage = '';
@@ -79,7 +80,14 @@ export class TokenGenerationComponent implements OnInit {
   }
 
   ngOnInit(): void {
-    this.setTokenStateServiceStatus();
+    this.tokenGenService.isTokenHashKeyPresent().then(
+        tokenHashKeyPresent => {
+          if (tokenHashKeyPresent) {
+            this.setTokenStateServiceStatus();
+          } else {
+            this.showMissingKnoxTokenHashKeyPopup();
+          }
+        });
   }
 
   generateToken() {
@@ -110,13 +118,13 @@ export class TokenGenerationComponent implements OnInit {
 
   setTokenStateServiceStatus() {
     this.tokenGenService.getTokenStateServiceStatus()
-    .then(tssStatus => {
-      this.tssStatus = tssStatus;
-      this.decideTssMessage();
-    })
-    .catch((errorMessage) => {
-      this.requestErrorMessage = errorMessage;
-    });
+        .then(tssStatus => {
+          this.tssStatus = tssStatus;
+          this.decideTssMessage();
+        })
+        .catch((errorMessage) => {
+          this.requestErrorMessage = errorMessage;
+        });
   }
 
   copyTextToClipboard(elementId) {
@@ -206,4 +214,14 @@ export class TokenGenerationComponent implements OnInit {
     this.tssStatusMessageLevel = level;
     this.tssStatusMessage = message;
   }
+
+  private showMissingKnoxTokenHashKeyPopup(): void {
+    const message = 'The required gateway-level alias, knox.token.hash.key, is 
missing.';
+    Swal.fire({
+      icon: 'warning',
+      title: 'Token Generation Disabled!',
+      text: message,
+      confirmButtonColor: '#7cd1f9'
+    });
+  }
 }
diff --git 
a/knox-token-generation-ui/token-generation/app/token-generation.service.ts 
b/knox-token-generation-ui/token-generation/app/token-generation.service.ts
index f315988f7..7122336e6 100644
--- a/knox-token-generation-ui/token-generation/app/token-generation.service.ts
+++ b/knox-token-generation-ui/token-generation/app/token-generation.service.ts
@@ -25,6 +25,7 @@ export class TokenGenService {
     readonly tokenURL: string;
     readonly tssStatusRequestURL: string;
     readonly sessionUrl: string;
+    readonly metadataInfoUrl: string;
 
     constructor(private http: HttpClient) {
         const knoxtokenURL = 'knoxtoken/api/v2/token';
@@ -37,6 +38,7 @@ export class TokenGenService {
         this.tokenURL = topologyContext + knoxtokenURL;
         this.tssStatusRequestURL = topologyContext + tssStatusURL;
         this.sessionUrl = topologyContext + 'session/api/v1/sessioninfo';
+        this.metadataInfoUrl = topologyContext + 'api/v1/metadata/info';
     }
 
     getTokenStateServiceStatus(): Promise<TssStatusData> {
@@ -73,6 +75,23 @@ export class TokenGenService {
         });
     }
 
+    isTokenHashKeyPresent(): Promise<boolean> {
+        let headers = new HttpHeaders();
+        headers = this.addHeaders(headers);
+        return this.http.get(this.metadataInfoUrl, { headers: headers})
+            .toPromise()
+            .then(response => {
+                return response['generalProxyInfo']?.['enableTokenManagement'] 
=== 'true';
+            })
+            .catch((err: HttpErrorResponse) => {
+                console.debug('TokenGenService --> isTokenHashKeyPresent() --> 
' + this.metadataInfoUrl + '\n  error: ' + err.message);
+                if (err.status === 401) {
+                    window.location.assign(document.location.pathname);
+                } else {
+                    return this.handleError(err);
+                }
+            });
+    }
     getSessionInformation(): Promise<SessionInformation> {
         let headers = new HttpHeaders();
         headers = this.addHeaders(headers);
@@ -80,7 +99,7 @@ export class TokenGenService {
             .toPromise()
             .then(response => response['sessioninfo'] as SessionInformation)
             .catch((err: HttpErrorResponse) => {
-                console.debug('TokenManagementService --> 
getSessionInformation() --> ' + this.sessionUrl + '\n  error: ' + err.message);
+                console.debug('TokenGenService --> getSessionInformation() --> 
' + this.sessionUrl + '\n  error: ' + err.message);
                 if (err.status === 401) {
                     window.location.assign(document.location.pathname);
                 } else {
diff --git 
a/knox-token-management-ui/token-management/app/token.management.component.html 
b/knox-token-management-ui/token-management/app/token.management.component.html
index be371c4e9..6260b964c 100644
--- 
a/knox-token-management-ui/token-management/app/token.management.component.html
+++ 
b/knox-token-management-ui/token-management/app/token.management.component.html
@@ -15,12 +15,12 @@
 <div>
 
     <div>
-        <button (click)="gotoTokenGenerationPage();">Generate New 
Token</button>
-        <button type="button" title="Refresh Knox Tokens" 
(click)="fetchKnoxTokens();">
+        <button (click)="gotoTokenGenerationPage();" 
[disabled]="!isTokenHashKeyPresent()">Generate New Token</button>
+        <button type="button" title="Refresh Knox Tokens" 
(click)="fetchKnoxTokens();" [disabled]="!isTokenHashKeyPresent()">
             <span class="glyphicon glyphicon-refresh"></span>
         </button>
         <span style="float: right;">
-            <mat-slide-toggle (change)="onChangeShowDisabledCookies($event)" 
[(ngModel)]="showDisabledKnoxSsoCookies">
+            <mat-slide-toggle (change)="onChangeShowDisabledCookies($event)" 
[(ngModel)]="showDisabledKnoxSsoCookies" [disabled]="!isTokenHashKeyPresent()">
               Show Disabled KnoxSSO Cookies
             </mat-slide-toggle>
         </span>
@@ -28,7 +28,7 @@
 
     <div *ngIf="userCanSeeAllTokens()">
         <span style="float: right;">
-            <mat-slide-toggle (change)="onChangeShowMyTokensOnly($event)" 
[(ngModel)]="showMyTokensOnly">
+            <mat-slide-toggle (change)="onChangeShowMyTokensOnly($event)" 
[(ngModel)]="showMyTokensOnly" [disabled]="!isTokenHashKeyPresent()">
               Show My Tokens Only
             </mat-slide-toggle>
         </span>
diff --git 
a/knox-token-management-ui/token-management/app/token.management.component.ts 
b/knox-token-management-ui/token-management/app/token.management.component.ts
index 903ecd5d0..74777b7a4 100644
--- 
a/knox-token-management-ui/token-management/app/token.management.component.ts
+++ 
b/knox-token-management-ui/token-management/app/token.management.component.ts
@@ -22,6 +22,7 @@ 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';
+import Swal from 'sweetalert2';
 
 @Component({
     selector: 'app-token-management',
@@ -39,6 +40,7 @@ export class TokenManagementComponent implements OnInit {
     userName: string;
     canSeeAllTokens: boolean;
     currentKnoxSsoCookieTokenId: string;
+    tokenHashKeyPresent: boolean;
     knoxTokens: MatTableDataSource<KnoxToken> = new MatTableDataSource();
     selection = new SelectionModel<KnoxToken>(true, []);
     allKnoxTokens: KnoxToken[];
@@ -103,6 +105,15 @@ export class TokenManagementComponent implements OnInit {
 
     ngOnInit(): void {
         console.debug('TokenManagementComponent --> ngOnInit()');
+        this.tokenManagementService.isTokenHashKeyPresent().then(
+            tokenHashKeyPresent => {
+                this.tokenHashKeyPresent = tokenHashKeyPresent;
+                if (!tokenHashKeyPresent) {
+                    this.showMissingKnoxTokenHashKeyPopup();
+                }
+            }
+        );
+
         this.tokenManagementService.getSessionInformation()
             .then(sessionInformation => {
               this.canSeeAllTokens = sessionInformation.canSeeAllTokens;
@@ -111,6 +122,10 @@ export class TokenManagementComponent implements OnInit {
             });
     }
 
+    isTokenHashKeyPresent(): boolean{
+        return this.tokenHashKeyPresent;
+    }
+
     setUserName(userName: string) {
         this.userName = userName;
         this.fetchKnoxTokens();
@@ -121,8 +136,12 @@ export class TokenManagementComponent implements OnInit {
     }
 
     fetchKnoxTokens(): void {
-        this.tokenManagementService.getKnoxTokens(this.userName, 
this.canSeeAllTokens)
-            .then(tokens => this.updateTokens(tokens));
+        if (this.tokenHashKeyPresent) {
+            this.tokenManagementService.getKnoxTokens(this.userName, 
this.canSeeAllTokens)
+                .then(tokens => this.updateTokens(tokens));
+        } else {
+            console.debug('knox.token.hash.key is missing, skipping Knox token 
fetch...');
+        }
     }
 
     private isMyToken(token: KnoxToken): boolean {
@@ -284,4 +303,14 @@ export class TokenManagementComponent implements OnInit {
         return this.isKnoxSsoCookie(token) && token.tokenId === 
this.currentKnoxSsoCookieTokenId;
     }
 
+    private showMissingKnoxTokenHashKeyPopup(): void {
+        const message = 'The required gateway-level alias, 
knox.token.hash.key, is missing.';
+        Swal.fire({
+            icon: 'warning',
+            title: 'Token Management Disabled!',
+            text: message,
+            confirmButtonColor: '#7cd1f9'
+        });
+    }
+
 }
diff --git 
a/knox-token-management-ui/token-management/app/token.management.service.ts 
b/knox-token-management-ui/token-management/app/token.management.service.ts
index f9a8f0d02..0cb52705a 100644
--- a/knox-token-management-ui/token-management/app/token.management.service.ts
+++ b/knox-token-management-ui/token-management/app/token.management.service.ts
@@ -38,6 +38,7 @@ export class TokenManagementService {
     revokeKnoxTokenUrl = this.apiUrl + 'revoke';
     revokeKnoxTokensBatchUrl = this.apiUrl + 'revokeTokens';
     getTssStatusUrl = this.apiUrl + 'getTssStatus';
+    metadataInfoUrl = this.topologyContext + 'api/v1/metadata/info';
 
     constructor(private http: HttpClient) {}
 
@@ -129,6 +130,25 @@ export class TokenManagementService {
             });
     }
 
+    isTokenHashKeyPresent(): Promise<boolean> {
+        let headers = new HttpHeaders();
+        headers = this.addJsonHeaders(headers);
+        return this.http.get(this.metadataInfoUrl, { headers: headers})
+            .toPromise()
+            .then(response => {
+                return response['generalProxyInfo']?.['enableTokenManagement'] 
=== 'true';
+            })
+            .catch((err: HttpErrorResponse) => {
+                console.debug('TokenManagementService --> 
isTokenHashKeyPresent() --> '
+                    + this.metadataInfoUrl + '\n  error: ' + err.message);
+                if (err.status === 401) {
+                    window.location.assign(document.location.pathname);
+                } else {
+                    return this.handleError(err);
+                }
+            });
+    }
+
     getSessionInformation(): Promise<SessionInformation> {
         let headers = new HttpHeaders();
         headers = this.addJsonHeaders(headers);

Reply via email to