"use client" import { useEffect, useState } from "react" import { useRouter } from "next/navigation" type AdminLog = { id: string timestamp: string event_type: string action: string status_code: number severity: string method: string ip: string path: string user_agent?: string metadata?: Record request_body?: unknown response_body?: unknown usage?: Record query?: Record duration_ms?: number origin?: string } const API_BASE = "http://127.0.0.1:5000" export default function AdminLogsPage() { const router = useRouter() const [ready, setReady] = useState(false) const [loading, setLoading] = useState(false) const [exporting, setExporting] = useState(false) const [message, setMessage] = useState("") const [logs, setLogs] = useState([]) const [selectedLog, setSelectedLog] = useState(null) const safeJson = (value: unknown) => { if (value === null || value === undefined || value === "") return "No data" if (typeof value === "string") { try { return JSON.stringify(JSON.parse(value), null, 2) } catch { return value } } try { return JSON.stringify(value, null, 2) } catch { return String(value) } } const copyText = async (value: string) => { try { await navigator.clipboard.writeText(value) setMessage("Copied to clipboard") } catch { setMessage("Copy failed") } } const selectedRequestData = selectedLog ? selectedLog.request_body ?? (selectedLog.metadata && (selectedLog.metadata as any).request_body) ?? (selectedLog.metadata && (selectedLog.metadata as any).request_details) ?? selectedLog.query ?? null : null const selectedResponseData = selectedLog ? selectedLog.response_body ?? (selectedLog.metadata && (selectedLog.metadata as any).response_body) ?? (selectedLog.metadata && (selectedLog.metadata as any).response_details) ?? null : null const selectedUsageData = selectedLog ? selectedLog.usage ?? (selectedLog.metadata && (selectedLog.metadata as any).usage) ?? { duration_ms: selectedLog.duration_ms ?? 0, note: "Usage metrics not captured for this log entry", } : null const [filters, setFilters] = useState({ event_type: "", severity: "", status_code: "", search: "", }) const [pagination, setPagination] = useState({ page: 1, limit: 50, total: 0, pages: 1 }) const getToken = () => localStorage.getItem("admin_token") const headers = () => { const token = getToken() return token ? { "Content-Type": "application/json", Authorization: `Bearer ${token}` } : { "Content-Type": "application/json" } } const ensureAuth = async () => { const token = getToken() if (!token) { router.push("/admin/login") return false } const resp = await fetch(`${API_BASE}/api/admin/test`, { headers: headers() }) if (!resp.ok) { localStorage.removeItem("admin_token") router.push("/admin/login") return false } return true } const fetchLogs = async (page = 1, nextFilters = filters) => { setLoading(true) setMessage("") const params = new URLSearchParams() params.set("page", String(page)) params.set("limit", String(pagination.limit)) if (nextFilters.event_type) params.set("event_type", nextFilters.event_type) if (nextFilters.severity) params.set("severity", nextFilters.severity) if (nextFilters.status_code) params.set("status_code", nextFilters.status_code) if (nextFilters.search) params.set("search", nextFilters.search) try { const resp = await fetch(`${API_BASE}/api/admin/logs?${params.toString()}`, { headers: headers() }) if (resp.ok) { const data = await resp.json() setLogs(Array.isArray(data.logs) ? data.logs : []) if (data.pagination) { setPagination(data.pagination) } } else { setLogs([]) } } catch { setLogs([]) } finally { setLoading(false) } } const triggerDownload = (content: string, filename: string, mimeType: string) => { const blob = new Blob([content], { type: mimeType }) const url = URL.createObjectURL(blob) const anchor = document.createElement("a") anchor.href = url anchor.download = filename document.body.appendChild(anchor) anchor.click() anchor.remove() URL.revokeObjectURL(url) } const exportLogs = async (format: "json" | "csv") => { setExporting(true) setMessage("") const params = new URLSearchParams() params.set("type", "logs") params.set("format", format) params.set("limit", "5000") if (filters.event_type) params.set("event_type", filters.event_type) if (filters.severity) params.set("severity", filters.severity) if (filters.status_code) params.set("status_code", filters.status_code) if (filters.search) params.set("search", filters.search) try { const resp = await fetch(`${API_BASE}/api/admin/reports/export?${params.toString()}`, { headers: headers() }) const data = await resp.json().catch(() => ({})) if (!resp.ok) { setMessage(String(data.error || "Failed to export logs.")) return } const stamp = new Date().toISOString().replace(/[.:]/g, "-") if (format === "json") { triggerDownload(JSON.stringify(data, null, 2), `admin-logs-${stamp}.json`, "application/json") } else { triggerDownload(String(data.content || ""), `admin-logs-${stamp}.csv`, "text/csv") } setMessage(`Logs exported as ${format.toUpperCase()}.`) } catch { setMessage("Network error while exporting logs.") } finally { setExporting(false) } } useEffect(() => { const init = async () => { const ok = await ensureAuth() if (!ok) return setReady(true) await fetchLogs(1) } init() }, []) if (!ready) { return (

Loading logs...

) } return (

Security and Activity Logs

Filter authentication, access-control, suspicious payload, and admin activity events.

{message ?

{message}

: null}
setFilters({ ...filters, search: e.target.value })} className="md:col-span-2 rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-800" /> setFilters({ ...filters, status_code: e.target.value })} className="rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-800" />
{loading ? ( ) : logs.length === 0 ? ( ) : ( logs.map((log) => ( setSelectedLog(log)} className="cursor-pointer hover:bg-blue-50 dark:hover:bg-gray-800/60" title="Click to view request and response details" > )) )}
Time Event Action Status IP Path
Loading logs...
No logs found for selected filters.
{new Date(log.timestamp).toLocaleString()} {log.event_type} {log.action} = 400 ? "bg-red-100 text-red-700" : "bg-green-100 text-green-700"}`}> {log.status_code} {log.ip} {log.path}
Page {pagination.page} of {pagination.pages} • Total {pagination.total}
{selectedLog ? (

Log Request and Response Details

Event

{selectedLog.event_type}

Action

{selectedLog.action}

Path

{selectedLog.path}

Method and Status

{selectedLog.method} {selectedLog.status_code}

Duration

{selectedLog.duration_ms ?? (selectedLog.metadata && (selectedLog.metadata as any).duration_ms) ?? 0} ms

Client

{selectedLog.ip}

{selectedLog.user_agent || "Unknown user agent"}

Request Body

{safeJson(selectedRequestData)}
                

Response Body

{safeJson(selectedResponseData)}
                

Usage Monitoring

{safeJson(selectedUsageData)}
                

Full Metadata

{safeJson(selectedLog.metadata ?? {})}
                
) : null}
) }