diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4cec5be1..43526339 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "tftsr" +name = "trcaa" version = "0.1.0" edition = "2021" diff --git a/src-tauri/src/db/connection.rs b/src-tauri/src/db/connection.rs index 417b29b3..3b1a8052 100644 --- a/src-tauri/src/db/connection.rs +++ b/src-tauri/src/db/connection.rs @@ -1,7 +1,34 @@ use rusqlite::Connection; use std::path::Path; -fn get_db_key() -> anyhow::Result { +fn generate_key() -> String { + use rand::RngCore; + let mut bytes = [0u8; 32]; + rand::rngs::OsRng.fill_bytes(&mut bytes); + hex::encode(bytes) +} + +#[cfg(unix)] +fn write_key_file(path: &Path, key: &str) -> anyhow::Result<()> { + use std::io::Write; + use std::os::unix::fs::OpenOptionsExt; + let mut f = std::fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .mode(0o600) + .open(path)?; + f.write_all(key.as_bytes())?; + Ok(()) +} + +#[cfg(not(unix))] +fn write_key_file(path: &Path, key: &str) -> anyhow::Result<()> { + std::fs::write(path, key)?; + Ok(()) +} + +fn get_db_key(data_dir: &Path) -> anyhow::Result { if let Ok(key) = std::env::var("TFTSR_DB_KEY") { if !key.trim().is_empty() { return Ok(key); @@ -12,9 +39,22 @@ fn get_db_key() -> anyhow::Result { return Ok("dev-key-change-in-prod".to_string()); } - Err(anyhow::anyhow!( - "TFTSR_DB_KEY must be set in release builds" - )) + // Release: load or auto-generate a per-installation key stored in the + // app data directory. This lets the app work out of the box without + // requiring users to set an environment variable. + let key_path = data_dir.join(".dbkey"); + if key_path.exists() { + let key = std::fs::read_to_string(&key_path)?; + let key = key.trim().to_string(); + if !key.is_empty() { + return Ok(key); + } + } + + let key = generate_key(); + std::fs::create_dir_all(data_dir)?; + write_key_file(&key_path, &key)?; + Ok(key) } pub fn open_encrypted_db(path: &Path, key: &str) -> anyhow::Result { @@ -45,8 +85,7 @@ pub fn init_db(data_dir: &Path) -> anyhow::Result { std::fs::create_dir_all(data_dir)?; let db_path = data_dir.join("tftsr.db"); - // In dev/test mode use unencrypted DB; in production use encryption - let key = get_db_key()?; + let key = get_db_key(data_dir)?; let conn = if cfg!(debug_assertions) { open_dev_db(&db_path)? @@ -62,18 +101,26 @@ pub fn init_db(data_dir: &Path) -> anyhow::Result { mod tests { use super::*; + fn temp_dir(name: &str) -> std::path::PathBuf { + let dir = std::env::temp_dir().join(format!("tftsr-test-{}", name)); + std::fs::create_dir_all(&dir).unwrap(); + dir + } + #[test] fn test_get_db_key_uses_env_var_when_present() { + let dir = temp_dir("env-var"); std::env::set_var("TFTSR_DB_KEY", "test-db-key"); - let key = get_db_key().unwrap(); + let key = get_db_key(&dir).unwrap(); assert_eq!(key, "test-db-key"); std::env::remove_var("TFTSR_DB_KEY"); } #[test] fn test_get_db_key_debug_fallback_for_empty_env() { + let dir = temp_dir("empty-env"); std::env::set_var("TFTSR_DB_KEY", " "); - let key = get_db_key().unwrap(); + let key = get_db_key(&dir).unwrap(); assert_eq!(key, "dev-key-change-in-prod"); std::env::remove_var("TFTSR_DB_KEY"); } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index b204f074..6b147e2a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -124,13 +124,13 @@ fn dirs_data_dir() -> std::path::PathBuf { #[cfg(target_os = "linux")] { if let Ok(xdg) = std::env::var("XDG_DATA_HOME") { - return std::path::PathBuf::from(xdg).join("tftsr"); + return std::path::PathBuf::from(xdg).join("trcaa"); } if let Ok(home) = std::env::var("HOME") { return std::path::PathBuf::from(home) .join(".local") .join("share") - .join("tftsr"); + .join("trcaa"); } } @@ -140,17 +140,17 @@ fn dirs_data_dir() -> std::path::PathBuf { return std::path::PathBuf::from(home) .join("Library") .join("Application Support") - .join("tftsr"); + .join("trcaa"); } } #[cfg(target_os = "windows")] { if let Ok(appdata) = std::env::var("APPDATA") { - return std::path::PathBuf::from(appdata).join("tftsr"); + return std::path::PathBuf::from(appdata).join("trcaa"); } } // Fallback - std::path::PathBuf::from("./tftsr-data") + std::path::PathBuf::from("./trcaa-data") } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5b7449b1..d38ffc27 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "productName": "Troubleshooting and RCA Assistant", "version": "0.2.10", - "identifier": "com.tftsr.devops", + "identifier": "com.trcaa.app", "build": { "frontendDist": "../dist", "devUrl": "http://localhost:1420",