client mode added

This commit is contained in:
Ember
2026-02-14 12:55:48 -08:00
parent a7d38730f5
commit d9e269a825
15 changed files with 573 additions and 18 deletions
+19 -3
View File
@@ -7,6 +7,8 @@ use rayhunter::analysis::analyzer::AnalyzerConfig;
use crate::error::RayhunterError;
use crate::notifications::NotificationType;
pub const WIFI_CREDS_PATH: &str = "/data/rayhunter/wifi-creds.conf";
/// The structure of a valid rayhunter configuration
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(default)]
@@ -34,6 +36,8 @@ pub struct Config {
pub analyzers: AnalyzerConfig,
pub min_space_to_start_recording_mb: u64,
pub min_space_to_continue_recording_mb: u64,
pub wifi_ssid: Option<String>,
pub wifi_password: Option<String>,
}
impl Default for Config {
@@ -51,6 +55,8 @@ impl Default for Config {
enabled_notifications: vec![NotificationType::Warning, NotificationType::LowBattery],
min_space_to_start_recording_mb: 1,
min_space_to_continue_recording_mb: 1,
wifi_ssid: None,
wifi_password: None,
}
}
}
@@ -59,12 +65,22 @@ pub async fn parse_config<P>(path: P) -> Result<Config, RayhunterError>
where
P: AsRef<std::path::Path>,
{
if let Ok(config_file) = tokio::fs::read_to_string(&path).await {
Ok(toml::from_str(&config_file).map_err(RayhunterError::ConfigFileParsingError)?)
let mut config = if let Ok(config_file) = tokio::fs::read_to_string(&path).await {
toml::from_str(&config_file).map_err(RayhunterError::ConfigFileParsingError)?
} else {
warn!("unable to read config file, using default config");
Ok(Config::default())
Config::default()
};
if let Ok(creds) = tokio::fs::read_to_string(WIFI_CREDS_PATH).await {
config.wifi_ssid = creds
.lines()
.find_map(|line| line.strip_prefix("ssid="))
.map(|s| s.to_string());
}
config.wifi_password = None;
Ok(config)
}
pub struct Args {
+54 -2
View File
@@ -134,7 +134,9 @@ pub async fn serve_static(
pub async fn get_config(
State(state): State<Arc<ServerState>>,
) -> Result<Json<Config>, (StatusCode, String)> {
Ok(Json(state.config.clone()))
let mut config = state.config.clone();
config.wifi_password = None;
Ok(Json(config))
}
#[cfg_attr(feature = "apidocs", utoipa::path(
@@ -157,7 +159,11 @@ pub async fn set_config(
State(state): State<Arc<ServerState>>,
Json(config): Json<Config>,
) -> Result<(StatusCode, String), (StatusCode, String)> {
let config_str = toml::to_string_pretty(&config).map_err(|err| {
let mut config_to_write = config.clone();
config_to_write.wifi_ssid = None;
config_to_write.wifi_password = None;
let config_str = toml::to_string_pretty(&config_to_write).map_err(|err| {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("failed to serialize config as TOML: {err}"),
@@ -171,6 +177,8 @@ pub async fn set_config(
)
})?;
update_wifi_creds(&config).await;
// Trigger daemon restart after writing config
state.daemon_restart_token.cancel();
Ok((
@@ -179,6 +187,50 @@ pub async fn set_config(
))
}
async fn update_wifi_creds(config: &Config) {
let has_ssid = config
.wifi_ssid
.as_ref()
.is_some_and(|s| !s.trim().is_empty());
let has_password = config
.wifi_password
.as_ref()
.is_some_and(|s| !s.trim().is_empty());
let creds_path = crate::config::WIFI_CREDS_PATH;
if !has_ssid {
if tokio::fs::metadata(creds_path).await.is_ok()
&& let Err(e) = tokio::fs::remove_file(creds_path).await
{
warn!("failed to remove wifi credentials: {e}");
}
} else if has_password {
let contents = format!(
"ssid={}\npassword={}\n",
config.wifi_ssid.as_ref().unwrap(),
config.wifi_password.as_ref().unwrap()
);
if let Err(e) = write(creds_path, contents).await {
warn!("failed to write wifi credentials: {e}");
}
} else if let Ok(existing) = tokio::fs::read_to_string(creds_path).await {
let existing_password = existing
.lines()
.find_map(|line| line.strip_prefix("password="));
if let Some(password) = existing_password {
let contents = format!(
"ssid={}\npassword={}\n",
config.wifi_ssid.as_ref().unwrap(),
password
);
if let Err(e) = write(creds_path, contents).await {
warn!("failed to write wifi credentials: {e}");
}
}
}
}
#[cfg_attr(feature = "apidocs", utoipa::path(
post,
path = "/api/test-notification",