import { useEffect, useState } from 'react' import { apiRequest, applyFirewallRules } from '../api/client' import { Plus, Trash2, Zap } from 'lucide-react' interface FirewallRule { id: number port: string protocol: string action: string ps: string } export function FirewallPage() { const [rules, setRules] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [showCreate, setShowCreate] = useState(false) const [creating, setCreating] = useState(false) const [creatingError, setCreatingError] = useState('') const [applying, setApplying] = useState(false) const loadRules = () => { setLoading(true) apiRequest('/firewall/list') .then(setRules) .catch((err) => setError(err.message)) .finally(() => setLoading(false)) } useEffect(() => { loadRules() }, []) const handleCreate = (e: React.FormEvent) => { e.preventDefault() const form = e.currentTarget const port = (form.elements.namedItem('port') as HTMLInputElement).value.trim() const protocol = (form.elements.namedItem('protocol') as HTMLSelectElement).value const action = (form.elements.namedItem('action') as HTMLSelectElement).value const ps = (form.elements.namedItem('ps') as HTMLInputElement).value.trim() if (!port) { setCreatingError('Port is required') return } setCreating(true) setCreatingError('') apiRequest<{ status: boolean; msg: string }>('/firewall/create', { method: 'POST', body: JSON.stringify({ port, protocol, action, ps }), }) .then(() => { setShowCreate(false) form.reset() loadRules() }) .catch((err) => setCreatingError(err.message)) .finally(() => setCreating(false)) } const handleDelete = (id: number, port: string) => { if (!confirm(`Delete rule for port ${port}?`)) return apiRequest<{ status: boolean }>(`/firewall/${id}`, { method: 'DELETE' }) .then(loadRules) .catch((err) => setError(err.message)) } const handleApply = () => { setApplying(true) applyFirewallRules() .then(() => loadRules()) .catch((err) => setError(err.message)) .finally(() => setApplying(false)) } if (loading) return
Loading...
if (error) return
{error}
return (

Security / Firewall

Rules are stored in the panel. Click "Apply to UFW" to run ufw allow/deny for each rule.
{showCreate && (

Add Firewall Rule

{creatingError && (
{creatingError}
)}
)}
{rules.length === 0 ? ( ) : ( rules.map((r) => ( )) )}
Port Protocol Action Note Actions
No rules. Click "Add Rule" to create one.
{r.port} {r.protocol} {r.action} {r.ps || '-'}
) }