diff --git a/Cargo.toml b/Cargo.toml index 52411e10e..2196c5bbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -140,6 +140,7 @@ diffs = "0.5.1" libc = "0.2.172" zstd-sys = "2.0.15+zstd.1.5.7" quickcheck = "1.0.3" +directories = "6.0.0" [profile.release] debug = true diff --git a/common/Cargo.toml b/common/Cargo.toml index 1a887ca6f..8d4939835 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -24,3 +24,4 @@ serde_json = { workspace = true } regex = { workspace = true } sea-orm = { workspace = true, features = ["macros"] } utoipa = { workspace = true } +directories = { workspace = true } diff --git a/common/src/config.rs b/common/src/config.rs index 109d4c3e1..b79f66943 100644 --- a/common/src/config.rs +++ b/common/src/config.rs @@ -11,6 +11,68 @@ use std::rc::Rc; use crate::utils; +/// Retrieves the base directory path for Mega +/// +/// The directory is determined in the following priority order: +/// 1. Uses the `MEGA_BASE_DIR` environment variable if set +/// 2. Falls back to system default paths when environment variable is not set: +/// - On Linux: `~/.local/share/mega` +/// - On Windows: `C:\Users\{UserName}\AppData\Local\mega` +/// - On macOS: `~/Library/Application Support/mega` +/// +/// # Returns +/// A PathBuf containing the base directory path +/// +/// # Panics +/// Will panic if both conditions occur: +/// - Environment variable is not set +/// - System base directories cannot be determined +/// +pub fn mega_base() -> PathBuf { + // Get the base directory from the environment variable or use the default + let base_dir = std::env::var("MEGA_BASE_DIR").unwrap_or_else(|_| { + let base_dirs = directories::BaseDirs::new().unwrap(); + base_dirs + .data_local_dir() + .join("mega") + .to_str() + .unwrap() + .to_string() + }); + PathBuf::from(base_dir) +} + +/// Retrieves the cache directory path for Mega +/// +/// The directory is determined in the following priority order: +/// 1. Uses the `MEGA_CACHE_DIR` environment variable if set +/// 2. Falls back to system default paths when environment variable is not set: +/// - On Linux: `~/.cache/mega` +/// - On Windows: `C:\Users\{username}\AppData\Local\Cache\mega` +/// - On macOS: `~/Library/Caches/mega` +/// +/// # Returns +/// A PathBuf containing the cache directory path +/// +/// # Panics +/// Will panic if both conditions occur: +/// - Environment variable is not set +/// - System cache directories cannot be determined +/// +pub fn mega_cache() -> PathBuf { + // Get the cache directory from the environment variable or use the default + let cache_dir = std::env::var("MEGA_CACHE_DIR").unwrap_or_else(|_| { + let base_dirs = directories::BaseDirs::new().unwrap(); + base_dirs + .cache_dir() + .join("mega") + .to_str() + .unwrap() + .to_string() + }); + PathBuf::from(cache_dir) +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Config { pub base_dir: PathBuf, @@ -89,9 +151,7 @@ impl Config { impl Default for Config { fn default() -> Self { - let base_dir = PathBuf::from( - std::env::var("MEGA_BASE_DIR").unwrap_or_else(|_| "/tmp/.mega".to_string()), - ); + let base_dir = mega_base(); std::fs::create_dir_all(&base_dir).unwrap(); let bin_name = utils::get_current_bin_name(); @@ -104,7 +164,7 @@ impl Default for Config { .lines() .map(|line| { if line.starts_with("base_dir ") { - format!("base_dir = \"{}\"", base_dir.to_str().unwrap()) + format!("base_dir = {:?}", base_dir) } else { line.to_string() } @@ -209,7 +269,7 @@ pub struct LogConfig { impl Default for LogConfig { fn default() -> Self { Self { - log_path: PathBuf::from("/tmp/.mega/logs"), + log_path: mega_cache().join("logs"), level: String::from("info"), print_std: true, } @@ -230,7 +290,7 @@ impl Default for DbConfig { fn default() -> Self { Self { db_type: String::from("sqlite"), - db_path: PathBuf::from("/tmp/.mega/mega.db"), + db_path: mega_base().join("mega.db"), db_url: String::from("postgres://mega:mega@localhost:5432/mega"), max_connection: 32, min_connection: 16, @@ -296,7 +356,7 @@ impl Default for PackConfig { Self { pack_decode_mem_size: "4G".to_string(), pack_decode_disk_size: "20%".to_string(), - pack_decode_cache_path: PathBuf::from("/tmp/.mega/cache"), + pack_decode_cache_path: mega_cache().join("pack_decode_cache"), clean_cache_after_decode: true, channel_message_size: 1_000_000, } @@ -446,7 +506,7 @@ pub struct LFSLocalConfig { impl Default for LFSLocalConfig { fn default() -> Self { Self { - lfs_file_path: PathBuf::from("/tmp/.mega/lfs"), + lfs_file_path: mega_base().join("lfs"), enable_split: true, split_size: "20M".to_string(), } @@ -483,6 +543,33 @@ pub struct OauthConfig { #[cfg(test)] mod test { + use super::*; + use std::path::Path; + + fn check_file_permission(path: &Path) { + let metadata = std::fs::metadata(path).expect("Failed to read metadata"); + assert!( + !metadata.permissions().readonly(), + "File should not be read-only" + ); + } + + #[test] + fn test_mega_base() { + let base_dir = mega_base(); + std::fs::create_dir_all(&base_dir).expect("Failed to create base directory"); + assert!(base_dir.exists(), "Mega base directory should exist"); + check_file_permission(&base_dir); + } + + #[test] + fn test_mega_cache() { + let cache_dir = mega_cache(); + std::fs::create_dir_all(&cache_dir).expect("Failed to create cache directory"); + assert!(cache_dir.exists(), "Mega cache directory should exist"); + check_file_permission(&cache_dir); + } + #[test] fn test_get_size_from_str() { use crate::config::PackConfig; diff --git a/vault/Cargo.toml b/vault/Cargo.toml index 9a474348d..784f48ac7 100644 --- a/vault/Cargo.toml +++ b/vault/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +common = { workspace = true} rusty_vault = { workspace = true } serde_json = { workspace = true } go-defer = { workspace = true } diff --git a/vault/src/pgp.rs b/vault/src/pgp.rs index 926262986..f9db57bd8 100644 --- a/vault/src/pgp.rs +++ b/vault/src/pgp.rs @@ -4,10 +4,10 @@ /// using asynchronous operations. use smallvec::smallvec; -use pgp::{SecretKeyParams, SecretKeyParamsBuilder, SubkeyParamsBuilder}; -use pgp::types::SecretKeyTrait; pub use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey}; +use pgp::types::SecretKeyTrait; pub use pgp::KeyType; +use pgp::{SecretKeyParams, SecretKeyParamsBuilder, SubkeyParamsBuilder}; use crate::vault::{delete_secret, read_secret, write_secret}; diff --git a/vault/src/vault.rs b/vault/src/vault.rs index 4f1d4693c..35dc4c237 100644 --- a/vault/src/vault.rs +++ b/vault/src/vault.rs @@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use std::collections::HashMap; use std::fs; -use std::path::PathBuf; use std::sync::{Arc, RwLock}; #[derive(Serialize, Deserialize, Debug)] @@ -31,7 +30,7 @@ lazy_static! { /// Initialize the vault core, used in `lazy_static!` fn init() -> CoreInfo { const CORE_KEY_FILE: &str = "core_key.json"; // where the core key is stored, like `root_token` - let dir = PathBuf::from("/tmp/rusty_vault_pki_module"); // RustyVault files TODO configurable + let dir = common::config::mega_base().join("vault"); let core_key_path = dir.join(CORE_KEY_FILE); // let dir = env::temp_dir().join("rusty_vault_pki_module"); // TODO: 改成数据库?