diff --git a/apps/desktop/src-tauri/src/agent.rs b/apps/desktop/src-tauri/src/agent.rs index b221fb0..e54f567 100644 --- a/apps/desktop/src-tauri/src/agent.rs +++ b/apps/desktop/src-tauri/src/agent.rs @@ -1215,11 +1215,9 @@ async fn check_and_apply_usb_policy(base_url: &str, token: &str) { } }; - eprintln!("[agent] Aplicando politica USB: {}", policy_str); - #[cfg(target_os = "windows")] { - use crate::usb_control::{apply_usb_policy, UsbPolicy}; + use crate::usb_control::{apply_usb_policy, get_current_policy, UsbPolicy}; let policy = match UsbPolicy::from_str(&policy_str) { Some(p) => p, @@ -1230,6 +1228,26 @@ async fn check_and_apply_usb_policy(base_url: &str, token: &str) { } }; + // Verifica se a politica ja esta aplicada localmente + match get_current_policy() { + Ok(current) if current == policy => { + eprintln!("[agent] Politica USB ja esta aplicada localmente: {}", policy_str); + report_usb_policy_status(base_url, token, "APPLIED", None, Some(policy_str)).await; + return; + } + Ok(current) => { + eprintln!("[agent] Politica atual: {:?}, esperada: {:?}", current, policy); + } + Err(e) => { + eprintln!("[agent] Nao foi possivel ler politica atual: {e}"); + } + } + + eprintln!("[agent] Aplicando politica USB: {}", policy_str); + + // Reporta APPLYING para progress bar real no frontend + report_usb_policy_status(base_url, token, "APPLYING", None, None).await; + match apply_usb_policy(policy) { Ok(result) => { eprintln!("[agent] Politica USB aplicada com sucesso: {:?}", result); @@ -1265,8 +1283,38 @@ async fn report_usb_policy_status( current_policy, }; - if let Err(e) = HTTP_CLIENT.post(&url).json(&report).send().await { - eprintln!("[agent] Falha ao reportar status de politica USB: {e}"); + // Retry com backoff exponencial: 2s, 4s, 8s + let delays = [2, 4, 8]; + let mut last_error = None; + + for (attempt, delay_secs) in delays.iter().enumerate() { + match HTTP_CLIENT.post(&url).json(&report).send().await { + Ok(response) if response.status().is_success() => { + if attempt > 0 { + eprintln!("[agent] Report de politica USB enviado na tentativa {}", attempt + 1); + } + return; + } + Ok(response) => { + last_error = Some(format!("HTTP {}", response.status())); + } + Err(e) => { + last_error = Some(e.to_string()); + } + } + + if attempt < delays.len() - 1 { + eprintln!( + "[agent] Falha ao reportar politica USB (tentativa {}), retentando em {}s...", + attempt + 1, + delay_secs + ); + tokio::time::sleep(Duration::from_secs(*delay_secs)).await; + } + } + + if let Some(err) = last_error { + eprintln!("[agent] Falha ao reportar status de politica USB apos 3 tentativas: {err}"); } } @@ -1344,7 +1392,7 @@ impl AgentRuntime { let mut heartbeat_ticker = tokio::time::interval(Duration::from_secs(interval)); heartbeat_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); - let mut usb_ticker = tokio::time::interval(Duration::from_secs(60)); + let mut usb_ticker = tokio::time::interval(Duration::from_secs(15)); usb_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); loop { diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index ba131de..1b2eaad 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Raven", - "version": "0.1.6", + "version": "0.1.9", "identifier": "br.com.esdrasrenan.sistemadechamados", "build": { "beforeDevCommand": "bun run dev", diff --git a/convex/usbPolicy.ts b/convex/usbPolicy.ts index ae1dca8..8bfefb8 100644 --- a/convex/usbPolicy.ts +++ b/convex/usbPolicy.ts @@ -18,7 +18,7 @@ function hashToken(token: string) { export const USB_POLICY_VALUES = ["ALLOW", "BLOCK_ALL", "READONLY"] as const export type UsbPolicyValue = (typeof USB_POLICY_VALUES)[number] -export const USB_POLICY_STATUS = ["PENDING", "APPLIED", "FAILED"] as const +export const USB_POLICY_STATUS = ["PENDING", "APPLYING", "APPLIED", "FAILED"] as const export type UsbPolicyStatus = (typeof USB_POLICY_STATUS)[number] export const setUsbPolicy = mutation({ diff --git a/src/app/api/machines/usb-policy/route.ts b/src/app/api/machines/usb-policy/route.ts index ff453e6..814a257 100644 --- a/src/app/api/machines/usb-policy/route.ts +++ b/src/app/api/machines/usb-policy/route.ts @@ -10,7 +10,7 @@ const getPolicySchema = z.object({ const reportStatusSchema = z.object({ machineToken: z.string().min(1), - status: z.enum(["PENDING", "APPLIED", "FAILED"]), + status: z.enum(["PENDING", "APPLYING", "APPLIED", "FAILED"]), error: z.string().optional(), currentPolicy: z.string().optional(), }) diff --git a/src/components/admin/devices/admin-devices-overview.tsx b/src/components/admin/devices/admin-devices-overview.tsx index c3640ed..98b03ae 100644 --- a/src/components/admin/devices/admin-devices-overview.tsx +++ b/src/components/admin/devices/admin-devices-overview.tsx @@ -4622,7 +4622,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) { return (
  • {name ?? "Adaptador de vídeo"} - {memoryBytes ? VRAM {formatBytes(memoryBytes)} : null} + {memoryBytes ? {formatBytes(memoryBytes)} VRAM : null} {vendor ? · {vendor} : null} {driver ? · Driver {driver} : null}
  • diff --git a/src/components/admin/devices/usb-policy-control.tsx b/src/components/admin/devices/usb-policy-control.tsx index 6eec555..9ab30ac 100644 --- a/src/components/admin/devices/usb-policy-control.tsx +++ b/src/components/admin/devices/usb-policy-control.tsx @@ -73,6 +73,13 @@ function getStatusBadge(status: string | undefined | null) { Pendente ) + case "APPLYING": + return ( + + + Aplicando + + ) case "APPLIED": return ( @@ -92,6 +99,36 @@ function getStatusBadge(status: string | undefined | null) { } } +function getProgressValue(status: string | undefined | null): number { + switch (status) { + case "PENDING": + return 33 + case "APPLYING": + return 66 + case "APPLIED": + return 100 + case "FAILED": + return 100 + default: + return 0 + } +} + +function getProgressColor(status: string | undefined | null): string { + switch (status) { + case "PENDING": + return "bg-amber-500" + case "APPLYING": + return "bg-blue-500" + case "APPLIED": + return "bg-emerald-500" + case "FAILED": + return "bg-red-500" + default: + return "bg-neutral-300" + } +} + interface UsbPolicyControlProps { machineId: string machineName?: string @@ -168,11 +205,27 @@ export function UsbPolicyControl({ const content = (
    - {/* Status atual no topo */} + {/* Status atual com progress bar real */} {usbPolicy?.status && ( -
    - Status da política - {getStatusBadge(usbPolicy.status)} +
    +
    + Status da política + {getStatusBadge(usbPolicy.status)} +
    + {/* Progress bar real baseada no estado */} + {(usbPolicy.status === "PENDING" || usbPolicy.status === "APPLYING") && ( +
    +
    +
    +
    +

    + {usbPolicy.status === "PENDING" ? "Aguardando agente..." : "Agente aplicando política..."} +

    +
    + )}
    )}