fix: Implement Phase 2 major fixes

Database:
- Add missing indexes for api_key_hash, status, metrics queries
- New migration: 005_add_missing_indexes.sql

Server:
- Fix WebSocket Ping/Pong protocol (RFC 6455 compliance)
- Use separate channel for Pong responses

Agent:
- Replace format!() path construction with PathBuf::join()
- Replace todo!() macros with proper errors for macOS support

Dashboard:
- Fix duplicate filter values in Agents page (__unassigned__ sentinel)
- Add onError handlers to all mutations in Agents, Clients, Sites pages

All changes reviewed and approved.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 21:23:36 -07:00
parent 65086f4407
commit b298a8aa17
7 changed files with 127 additions and 26 deletions

View File

@@ -224,8 +224,11 @@ async fn install_service(
#[cfg(target_os = "macos")]
{
let _ = (server_url, api_key, skip_legacy_check); // Suppress unused warnings
info!("Installing GuruRMM Agent as launchd service...");
todo!("macOS launchd service installation not yet implemented");
return Err(anyhow::anyhow!(
"macOS launchd service installation is not yet implemented.\n\
For now, you can run the agent manually or create a launchd plist.\n\
See: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html"
));
}
}
@@ -504,7 +507,10 @@ async fn uninstall_service() -> Result<()> {
#[cfg(target_os = "macos")]
{
todo!("macOS service uninstallation not yet implemented");
return Err(anyhow::anyhow!(
"macOS launchd service uninstallation is not yet implemented.\n\
If you created a launchd plist manually, remove it from ~/Library/LaunchAgents/ or /Library/LaunchDaemons/"
));
}
}
@@ -593,7 +599,10 @@ async fn start_service() -> Result<()> {
#[cfg(target_os = "macos")]
{
todo!("macOS service start not yet implemented");
return Err(anyhow::anyhow!(
"macOS launchd service start is not yet implemented.\n\
If you created a launchd plist manually, use: launchctl load <plist-path>"
));
}
}
@@ -626,7 +635,10 @@ async fn stop_service() -> Result<()> {
#[cfg(target_os = "macos")]
{
todo!("macOS service stop not yet implemented");
return Err(anyhow::anyhow!(
"macOS launchd service stop is not yet implemented.\n\
If you created a launchd plist manually, use: launchctl unload <plist-path>"
));
}
}

View File

@@ -90,7 +90,7 @@ pub mod windows {
.context("Failed to set StartPending status")?;
// Determine config path
let config_path = PathBuf::from(format!(r"{}\\agent.toml", CONFIG_DIR));
let config_path = PathBuf::from(CONFIG_DIR).join("agent.toml");
// Create the tokio runtime for the agent
let runtime = tokio::runtime::Runtime::new().context("Failed to create tokio runtime")?;
@@ -331,8 +331,8 @@ pub mod windows {
let current_exe =
std::env::current_exe().context("Failed to get current executable path")?;
let binary_dest = PathBuf::from(format!(r"{}\\gururmm-agent.exe", INSTALL_DIR));
let config_dest = PathBuf::from(format!(r"{}\\agent.toml", CONFIG_DIR));
let binary_dest = PathBuf::from(INSTALL_DIR).join("gururmm-agent.exe");
let config_dest = PathBuf::from(CONFIG_DIR).join("agent.toml");
// Create directories
info!("Creating directories...");
@@ -490,7 +490,7 @@ pub mod windows {
pub fn uninstall() -> Result<()> {
info!("Uninstalling GuruRMM Agent...");
let binary_path = PathBuf::from(format!(r"{}\\gururmm-agent.exe", INSTALL_DIR));
let binary_path = PathBuf::from(INSTALL_DIR).join("gururmm-agent.exe");
// Open the service manager
let manager = ServiceManager::local_computer(
@@ -685,8 +685,8 @@ pub mod windows {
// Get the current executable path
let current_exe = std::env::current_exe()?;
let binary_dest = PathBuf::from(format!(r"{}\\gururmm-agent.exe", INSTALL_DIR));
let config_dest = PathBuf::from(format!(r"{}\\agent.toml", CONFIG_DIR));
let binary_dest = PathBuf::from(INSTALL_DIR).join("gururmm-agent.exe");
let config_dest = PathBuf::from(CONFIG_DIR).join("agent.toml");
// Create directories
std::fs::create_dir_all(INSTALL_DIR)?;
@@ -727,7 +727,7 @@ pub mod windows {
pub fn uninstall() -> Result<()> {
use std::path::PathBuf;
let binary_path = PathBuf::from(format!(r"{}\\gururmm-agent.exe", INSTALL_DIR));
let binary_path = PathBuf::from(INSTALL_DIR).join("gururmm-agent.exe");
println!("** To uninstall legacy service, use NSSM:");
println!(" nssm stop {}", SERVICE_NAME);