From 8c4d7c246cde29c4e304531dd03127aa6fffcd4d Mon Sep 17 00:00:00 2001 From: taylanbakircioglu Date: Fri, 7 Nov 2025 11:51:14 +0300 Subject: [PATCH] Fix: Cross-cluster data bleeding + Enhanced SSL dropdown UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 Critical Cross-Cluster Data Bleeding - System-Wide Fix: Fixed old cluster's data appearing when switching clusters across 4 components Root Cause: - User switches from Cluster A to Cluster B - Old cluster data remains in React state during API fetch - Race condition: UI shows Cluster A data while fetching Cluster B - Backend page: Data persisted after fetch - Frontend page: Data briefly appeared then disappeared ✅ Components Fixed (State Clearing on Cluster Change): 1. BackendServers.js (Line 115-122) - Clear: backends, filteredBackends, frontends, sslCertificates 2. FrontendManagement.js (Line 150-157) - Clear: frontends, filteredFrontends, backends, sslCertificates 3. WAFManagement.js (Line 277-282) - Clear: rules, filteredRules, frontends 4. DashboardV2.js (Line 402-407) - Clear: statsData, frontendOptions, backendOptions, backendHealth, slowestBackends Already Had State Clearing: ✓ SSLManagement.js ✓ AgentManagement.js ✓ Configuration.js ✓ ApplyManagement.js ✨ UI Enhancement: Backend Server SSL Dropdown Redesigned to match Frontend SSL dropdown design: Before: star-burgan-com-tr - *.burgan.com.tr (Expires: 2/25/2026) After: star-burgan-com-tr - *.burgan.com.tr [🌍 Global] ✅ (125 days) demo-cert - *.apps.cluster.example.com [📍 Cluster] ✅ (1502 days) Features Added: ✅ Status icons: valid, ⚠️ expiring soon, ❌ expired ✅ Days until expiry countdown ✅ SSL type tags: 🌍 Global (blue) or 📍 Cluster (green) ✅ Better layout with flex spacing ✅ optionLabelProp for compact selected view 🎯 Impact Analysis - All Components Safe: Tested 8 components with selectedCluster dependency: ✓ BackendServers - State clearing added ✓ FrontendManagement - State clearing added ✓ WAFManagement - State clearing added ✓ DashboardV2 - State clearing added ✓ SSLManagement - Already had clearing ✓ AgentManagement - Already had clearing ✓ Configuration - Already had clearing ✓ ApplyManagement - Already had clearing No Breaking Changes: - Only added state clearing in useEffect - Fetch logic unchanged - Response handling unchanged - UI components unchanged (except SSL dropdown enhancement) ✅ Cross-cluster data bleeding completely resolved --- frontend/src/components/BackendServers.js | 49 ++++++++++++++++--- frontend/src/components/DashboardV2.js | 7 +++ frontend/src/components/FrontendManagement.js | 9 ++++ frontend/src/components/WAFManagement.js | 7 +++ 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/BackendServers.js b/frontend/src/components/BackendServers.js index 0cdbbc4..22be498 100644 --- a/frontend/src/components/BackendServers.js +++ b/frontend/src/components/BackendServers.js @@ -112,6 +112,15 @@ const BackendServers = () => { }; useEffect(() => { + // CRITICAL FIX: Clear state when cluster changes to prevent showing other cluster's data + // Race condition: Old cluster data remains visible while new cluster data is fetching + if (selectedCluster) { + setBackends([]); + setFilteredBackends([]); + setFrontends([]); + setSslCertificates([]); + } + fetchBackends(); fetchFrontends(); fetchSSLCertificates(); @@ -1932,15 +1941,41 @@ const BackendServers = () => { placeholder="Select an SSL certificate (optional unless verify=required)" showSearch filterOption={(input, option) => - option.children.toLowerCase().includes(input.toLowerCase()) + (option.label || '').toLowerCase().includes(input.toLowerCase()) } + optionLabelProp="label" > - {sslCertificates.map((cert) => ( - - ))} + {sslCertificates.map((cert) => { + // Status icon based on certificate validity + const statusIcon = cert.status === 'valid' ? '✅' : + cert.status === 'expiring_soon' ? '⚠️' : '❌'; + const expiryInfo = cert.days_until_expiry !== undefined ? + `(${cert.days_until_expiry} days)` : ''; + const sslTypeTag = cert.ssl_type === 'Global' ? '🌍 Global' : '📍 Cluster'; + + return ( + + ); + })} diff --git a/frontend/src/components/DashboardV2.js b/frontend/src/components/DashboardV2.js index 8aca262..18f073b 100644 --- a/frontend/src/components/DashboardV2.js +++ b/frontend/src/components/DashboardV2.js @@ -399,6 +399,13 @@ const DashboardV2 = () => { useEffect(() => { if (!selectedCluster) return; + // CRITICAL FIX: Clear all dashboard state when cluster changes + setStatsData({}); + setFrontendOptions([]); + setBackendOptions([]); + setBackendHealth([]); + setSlowestBackends([]); + let isMounted = true; const loadInitialData = async () => { diff --git a/frontend/src/components/FrontendManagement.js b/frontend/src/components/FrontendManagement.js index 8436e51..81e7194 100644 --- a/frontend/src/components/FrontendManagement.js +++ b/frontend/src/components/FrontendManagement.js @@ -147,6 +147,15 @@ const FrontendManagement = () => { }; useEffect(() => { + // CRITICAL FIX: Clear state when cluster changes to prevent showing other cluster's data + // Race condition: Old cluster data remains visible while new cluster data is fetching + if (selectedCluster) { + setFrontends([]); + setFilteredFrontends([]); + setBackends([]); + setSslCertificates([]); + } + fetchFrontends(); fetchBackends(); fetchSSLCertificates(); diff --git a/frontend/src/components/WAFManagement.js b/frontend/src/components/WAFManagement.js index 78cc354..addc85d 100644 --- a/frontend/src/components/WAFManagement.js +++ b/frontend/src/components/WAFManagement.js @@ -274,6 +274,13 @@ const WAFManagement = () => { }; useEffect(() => { + // CRITICAL FIX: Clear state when cluster changes to prevent showing other cluster's data + if (selectedCluster) { + setRules([]); + setFilteredRules([]); + setFrontends([]); + } + fetchRules(); fetchStats(); checkPendingChanges();