import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { toast } from "sonner"; import { Shield, Trash2, RefreshCw } from "lucide-react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; interface BanList { bannedIPs: string[]; bannedUserIds: string[]; bannedTokens: string[]; } export const BansManager = ({ session }: { session: any }) => { const [banList, setBanList] = useState({ bannedIPs: [], bannedUserIds: [], bannedTokens: [], }); const [loading, setLoading] = useState(false); const [unbanTarget, setUnbanTarget] = useState<{ type: 'ip' | 'user'; value: string } | null>(null); const fetchBanList = async () => { try { setLoading(true); const res = await fetch(`${import.meta.env.VITE_SERVER_IMAGE_API_URL}/api/admin/bans`, { headers: { 'Authorization': `Bearer ${session?.access_token || ''}` } }); if (!res.ok) { throw new Error('Failed to fetch ban list'); } const data = await res.json(); setBanList(data); } catch (err: any) { toast.error("Failed to fetch ban list", { description: err.message }); } finally { setLoading(false); } }; const handleUnban = async () => { if (!unbanTarget) return; try { const endpoint = unbanTarget.type === 'ip' ? '/api/admin/bans/unban-ip' : '/api/admin/bans/unban-user'; const body = unbanTarget.type === 'ip' ? { ip: unbanTarget.value } : { userId: unbanTarget.value }; const res = await fetch(`${import.meta.env.VITE_SERVER_IMAGE_API_URL}${endpoint}`, { method: 'POST', headers: { 'Authorization': `Bearer ${session?.access_token || ''}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); if (!res.ok) { throw new Error('Failed to unban'); } const data = await res.json(); if (data.success) { toast.success("Unbanned successfully", { description: data.message }); fetchBanList(); } else { toast.warning("Not found", { description: data.message }); } } catch (err: any) { toast.error("Failed to unban", { description: err.message }); } finally { setUnbanTarget(null); } }; useEffect(() => { fetchBanList(); }, []); const totalBans = banList.bannedIPs.length + banList.bannedUserIds.length + banList.bannedTokens.length; return (

Ban Management

Banned IPs
{banList.bannedIPs.length}
Banned Users
{banList.bannedUserIds.length}
Banned Tokens
{banList.bannedTokens.length}
{totalBans === 0 ? ( No active bans ) : (
{banList.bannedIPs.length > 0 && ( Banned IP Addresses IP addresses that have been auto-banned for excessive requests IP Address Actions {banList.bannedIPs.map((ip) => ( {ip} ))}
)} {banList.bannedUserIds.length > 0 && ( Banned Users User accounts that have been auto-banned for excessive requests User ID Actions {banList.bannedUserIds.map((userId) => ( {userId} ))}
)} {banList.bannedTokens.length > 0 && ( Banned Tokens Authentication tokens that have been auto-banned (cannot be unbanned via UI) Token (truncated) {banList.bannedTokens.map((token, idx) => ( {token.substring(0, 40)}... ))}
)}
)} !open && setUnbanTarget(null)}> Confirm Unban Are you sure you want to unban this {unbanTarget?.type}?
{unbanTarget?.value}
Cancel Unban
); };