diff --git a/public/admin/dashboard.html b/public/admin/dashboard.html index f8d4256..9fdd6af 100644 --- a/public/admin/dashboard.html +++ b/public/admin/dashboard.html @@ -452,6 +452,35 @@

Quick Actions

})(); }); + // Validate token and initialize dashboard + async function validateAndInit() { + const token = localStorage.getItem('spiralsafe_admin_token') || + sessionStorage.getItem('spiralsafe_admin_token'); + + try { + const response = await fetch(`${API_BASE}/admin/auth/me`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Accept': 'application/json' + } + }); + + if (!response.ok) { + // Invalid or expired token, clear it and redirect to login + logout(); + return; + } + + // Token is valid - initialize charts and load metrics + initCharts(); + loadMetrics(); + } catch (error) { + // On network or other errors, clear token and redirect to login + logout(); + } + } + // Logout function function logout() { localStorage.removeItem('spiralsafe_admin_token'); diff --git a/public/admin/login.html b/public/admin/login.html index da0c994..3812fa7 100644 --- a/public/admin/login.html +++ b/public/admin/login.html @@ -308,6 +308,9 @@

🔐 ATOM-AUTH: Conversational Cohe if (response.ok && data.token) { // Store token + // SECURITY NOTE: Storing tokens in localStorage/sessionStorage exposes them to XSS attacks. + // For production deployments, consider using httpOnly cookies set by the backend + // or implementing additional security measures (strict CSP, token rotation, etc.) if (remember) { localStorage.setItem('spiralsafe_admin_token', data.token); } else { diff --git a/public/api/index.html b/public/api/index.html index 182efa4..e9425e0 100644 --- a/public/api/index.html +++ b/public/api/index.html @@ -605,10 +605,24 @@

RapiDoc

responseEl.classList.remove('hidden'); codeEl.textContent = 'Loading...'; - const response = await fetch(`${API_BASE}/api/health`); - const data = await response.json(); + // Demo mode: simulated response for interactive preview + // For production API calls, include X-API-Key header in your request + const simulatedResponse = { + status: "healthy", + timestamp: new Date().toISOString(), + version: "1.0.0", + services: { + database: "operational", + cache: "operational", + queue: "operational" + }, + _note: "Interactive demo - use curl or your preferred HTTP client with a valid X-API-Key header for actual results" + }; - codeEl.textContent = JSON.stringify(data, null, 2); + // Simulate network delay + await new Promise(resolve => setTimeout(resolve, 500)); + + codeEl.textContent = JSON.stringify(simulatedResponse, null, 2); hljs.highlightElement(codeEl); } catch (error) { codeEl.textContent = JSON.stringify({ error: error.message }, null, 2);