"use client" import { useState, useEffect } from "react" import { useMutation, useQuery } from "convex/react" import { api } from "@/convex/_generated/api" import type { Id } from "@/convex/_generated/dataModel" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { Usb, Shield, ShieldOff, ShieldAlert, Clock, CheckCircle2, XCircle, Loader2, History } from "lucide-react" import { toast } from "sonner" import { formatDistanceToNow } from "date-fns" import { ptBR } from "date-fns/locale" type UsbPolicyValue = "ALLOW" | "BLOCK_ALL" | "READONLY" interface UsbPolicyEvent { id: string oldPolicy?: string newPolicy: string status: string error?: string actorEmail?: string actorName?: string createdAt: number appliedAt?: number } const POLICY_OPTIONS: Array<{ value: UsbPolicyValue; label: string; description: string; icon: typeof Shield }> = [ { value: "ALLOW", label: "Permitido", description: "Acesso total a dispositivos USB de armazenamento", icon: Shield, }, { value: "BLOCK_ALL", label: "Bloqueado", description: "Nenhum acesso a dispositivos USB de armazenamento", icon: ShieldOff, }, { value: "READONLY", label: "Somente leitura", description: "Permite leitura, bloqueia escrita em dispositivos USB", icon: ShieldAlert, }, ] function getPolicyConfig(policy: string | undefined | null) { return POLICY_OPTIONS.find((opt) => opt.value === policy) ?? POLICY_OPTIONS[0] } function getStatusBadge(status: string | undefined | null) { switch (status) { case "PENDING": return ( Pendente ) case "APPLIED": return ( Aplicado ) case "FAILED": return ( Falhou ) default: return null } } interface UsbPolicyControlProps { machineId: string machineName?: string actorEmail?: string actorName?: string actorId?: string disabled?: boolean variant?: "card" | "inline" } export function UsbPolicyControl({ machineId, machineName, actorEmail, actorName, actorId, disabled = false, variant = "card", }: UsbPolicyControlProps) { const [selectedPolicy, setSelectedPolicy] = useState("ALLOW") const [isApplying, setIsApplying] = useState(false) const [showHistory, setShowHistory] = useState(false) const usbPolicy = useQuery(api.usbPolicy.getUsbPolicy, { machineId: machineId as Id<"machines">, }) const policyEvents = useQuery( api.usbPolicy.listUsbPolicyEvents, showHistory ? { machineId: machineId as Id<"machines">, limit: 10 } : "skip" ) const setUsbPolicyMutation = useMutation(api.usbPolicy.setUsbPolicy) useEffect(() => { if (usbPolicy?.policy) { setSelectedPolicy(usbPolicy.policy as UsbPolicyValue) } }, [usbPolicy?.policy]) const currentConfig = getPolicyConfig(usbPolicy?.policy) const CurrentIcon = currentConfig.icon const handleApplyPolicy = async () => { if (selectedPolicy === usbPolicy?.policy) { toast.info("A política selecionada já está aplicada.") return } setIsApplying(true) try { await setUsbPolicyMutation({ machineId: machineId as Id<"machines">, policy: selectedPolicy, actorId: actorId ? (actorId as Id<"users">) : undefined, actorEmail, actorName, }) toast.success("Política USB enviada para aplicação.") } catch (error) { console.error("[usb-policy] Falha ao aplicar política", error) toast.error("Falha ao aplicar política USB. Tente novamente.") } finally { setIsApplying(false) } } const formatEventDate = (timestamp: number) => { return formatDistanceToNow(new Date(timestamp), { addSuffix: true, locale: ptBR, }) } const content = (
{/* Status atual no topo */} {usbPolicy?.status && (
Status da política {getStatusBadge(usbPolicy.status)}
)} {usbPolicy?.error && (

Erro na aplicação

{usbPolicy.error}

)} {/* Política atual */}

{currentConfig.label}

{currentConfig.description}

{selectedPolicy === usbPolicy?.policy ? "A política já está aplicada" : `Aplicar política "${getPolicyConfig(selectedPolicy).label}"`}
{showHistory && policyEvents && (
{policyEvents.length === 0 ? (

Nenhuma alteração registrada

) : ( policyEvents.map((event: UsbPolicyEvent) => (
{getPolicyConfig(event.oldPolicy).label} {getPolicyConfig(event.newPolicy).label} {getStatusBadge(event.status)}

{event.actorName ?? event.actorEmail ?? "Sistema"} · {formatEventDate(event.createdAt)}

{event.error && (

{event.error}

)}
)) )}
)}
{usbPolicy?.reportedAt && (

Último relato do agente: {formatEventDate(usbPolicy.reportedAt)}

)}
) if (variant === "inline") { return content } return (
Controle USB
Gerencie o acesso a dispositivos de armazenamento USB neste dispositivo.
{content}
) }