Merge pull request 'feat(rebrand): rename binary to trcaa and auto-generate DB key' (#18) from feat/rebrand-binary-trcaa into master
Reviewed-on: #18
This commit is contained in:
commit
a40bc2304f
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tftsr"
|
name = "trcaa"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,34 @@
|
|||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
fn get_db_key() -> anyhow::Result<String> {
|
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<String> {
|
||||||
if let Ok(key) = std::env::var("TFTSR_DB_KEY") {
|
if let Ok(key) = std::env::var("TFTSR_DB_KEY") {
|
||||||
if !key.trim().is_empty() {
|
if !key.trim().is_empty() {
|
||||||
return Ok(key);
|
return Ok(key);
|
||||||
@ -12,9 +39,22 @@ fn get_db_key() -> anyhow::Result<String> {
|
|||||||
return Ok("dev-key-change-in-prod".to_string());
|
return Ok("dev-key-change-in-prod".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(anyhow::anyhow!(
|
// Release: load or auto-generate a per-installation key stored in the
|
||||||
"TFTSR_DB_KEY must be set in release builds"
|
// 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<Connection> {
|
pub fn open_encrypted_db(path: &Path, key: &str) -> anyhow::Result<Connection> {
|
||||||
@ -45,8 +85,7 @@ pub fn init_db(data_dir: &Path) -> anyhow::Result<Connection> {
|
|||||||
std::fs::create_dir_all(data_dir)?;
|
std::fs::create_dir_all(data_dir)?;
|
||||||
let db_path = data_dir.join("tftsr.db");
|
let db_path = data_dir.join("tftsr.db");
|
||||||
|
|
||||||
// In dev/test mode use unencrypted DB; in production use encryption
|
let key = get_db_key(data_dir)?;
|
||||||
let key = get_db_key()?;
|
|
||||||
|
|
||||||
let conn = if cfg!(debug_assertions) {
|
let conn = if cfg!(debug_assertions) {
|
||||||
open_dev_db(&db_path)?
|
open_dev_db(&db_path)?
|
||||||
@ -62,18 +101,26 @@ pub fn init_db(data_dir: &Path) -> anyhow::Result<Connection> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn test_get_db_key_uses_env_var_when_present() {
|
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");
|
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");
|
assert_eq!(key, "test-db-key");
|
||||||
std::env::remove_var("TFTSR_DB_KEY");
|
std::env::remove_var("TFTSR_DB_KEY");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_db_key_debug_fallback_for_empty_env() {
|
fn test_get_db_key_debug_fallback_for_empty_env() {
|
||||||
|
let dir = temp_dir("empty-env");
|
||||||
std::env::set_var("TFTSR_DB_KEY", " ");
|
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");
|
assert_eq!(key, "dev-key-change-in-prod");
|
||||||
std::env::remove_var("TFTSR_DB_KEY");
|
std::env::remove_var("TFTSR_DB_KEY");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -124,13 +124,13 @@ fn dirs_data_dir() -> std::path::PathBuf {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
if let Ok(xdg) = std::env::var("XDG_DATA_HOME") {
|
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") {
|
if let Ok(home) = std::env::var("HOME") {
|
||||||
return std::path::PathBuf::from(home)
|
return std::path::PathBuf::from(home)
|
||||||
.join(".local")
|
.join(".local")
|
||||||
.join("share")
|
.join("share")
|
||||||
.join("tftsr");
|
.join("trcaa");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,17 +140,17 @@ fn dirs_data_dir() -> std::path::PathBuf {
|
|||||||
return std::path::PathBuf::from(home)
|
return std::path::PathBuf::from(home)
|
||||||
.join("Library")
|
.join("Library")
|
||||||
.join("Application Support")
|
.join("Application Support")
|
||||||
.join("tftsr");
|
.join("trcaa");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
if let Ok(appdata) = std::env::var("APPDATA") {
|
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
|
// Fallback
|
||||||
std::path::PathBuf::from("./tftsr-data")
|
std::path::PathBuf::from("./trcaa-data")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"productName": "Troubleshooting and RCA Assistant",
|
"productName": "Troubleshooting and RCA Assistant",
|
||||||
"version": "0.2.10",
|
"version": "0.2.10",
|
||||||
"identifier": "com.tftsr.devops",
|
"identifier": "com.trcaa.app",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../dist",
|
"frontendDist": "../dist",
|
||||||
"devUrl": "http://localhost:1420",
|
"devUrl": "http://localhost:1420",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user