Add disconnect/uninstall for persistent sessions

- Server: Add DELETE /api/sessions/:id endpoint to disconnect agents
- Server: SessionManager.disconnect_session() sends Disconnect message
- Agent: Handle ADMIN_DISCONNECT to trigger uninstall
- Agent: Add startup::uninstall() to remove from startup and schedule exe deletion
- Dashboard: Add Disconnect button in Access tab machine details
- Dashboard: Add Chat button for persistent sessions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 16:53:29 -07:00
parent aa03a87c7c
commit 4b29dbe6c8
7 changed files with 131 additions and 2 deletions

View File

@@ -134,6 +134,49 @@ pub fn remove_from_startup() -> Result<()> {
Ok(())
}
/// Full uninstall: remove from startup and delete the executable
#[cfg(windows)]
pub fn uninstall() -> Result<()> {
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use windows::Win32::Storage::FileSystem::{MoveFileExW, MOVEFILE_DELAY_UNTIL_REBOOT};
info!("Uninstalling agent");
// First remove from startup
let _ = remove_from_startup();
// Get the path to the current executable
let exe_path = std::env::current_exe()?;
let exe_path_str = exe_path.to_string_lossy();
info!("Scheduling deletion of: {}", exe_path_str);
// Convert path to wide string
let exe_wide: Vec<u16> = OsStr::new(&*exe_path_str)
.encode_wide()
.chain(std::iter::once(0))
.collect();
// Schedule the file for deletion on next reboot
// This is necessary because the executable is currently running
unsafe {
let result = MoveFileExW(
PCWSTR(exe_wide.as_ptr()),
PCWSTR::null(),
MOVEFILE_DELAY_UNTIL_REBOOT,
);
if result.is_err() {
warn!("Failed to schedule file deletion: {:?}. File may need manual removal.", result);
} else {
info!("Executable scheduled for deletion on reboot");
}
}
Ok(())
}
#[cfg(not(windows))]
pub fn add_to_startup() -> Result<()> {
warn!("Startup persistence not implemented for this platform");
@@ -144,3 +187,9 @@ pub fn add_to_startup() -> Result<()> {
pub fn remove_from_startup() -> Result<()> {
Ok(())
}
#[cfg(not(windows))]
pub fn uninstall() -> Result<()> {
warn!("Uninstall not implemented for this platform");
Ok(())
}