Files
secrets/src/config.rs
voson 31b0ea9bf1
Some checks failed
Secrets CLI - Build & Release / 版本 & Release (push) Successful in 2s
Secrets CLI - Build & Release / 质量检查 (fmt / clippy / test) (push) Successful in 1m42s
Secrets CLI - Build & Release / Build (x86_64-unknown-linux-musl) (push) Successful in 1m18s
Secrets CLI - Build & Release / 发布草稿 Release (push) Successful in 2s
Secrets CLI - Build & Release / Build (aarch64-apple-darwin) (push) Failing after 7m40s
Secrets CLI - Build & Release / Build (x86_64-pc-windows-msvc) (push) Has been cancelled
refactor: 代码审阅优化
P0:
- fix(config): config_dir 使用 home_dir 回退,避免 ~ 不展开
- fix(search): 模糊查询转义 LIKE 通配符 % 和 _

P1:
- chore(db): 连接池添加 acquire_timeout 10s
- refactor(update): 消除 meta_keys/secret_keys 重复计算

P2:
- refactor(config): 合并 ConfigAction 枚举
- chore(deps): 移除 clap/env、uuid/v4 无用 features
- perf(main): delete 命令跳过 master_key 加载
- i18n(config): 统一错误消息为英文
- perf(search): show_secrets=false 时不再解密获取 key_count
- feat(delete,update): 支持 -o json/json-compact 输出

P3:
- feat(search): --tag 支持多值交叉过滤

docs: 将 seed-data.sh 替换为 setup-gitea-actions.sh
Made-with: Cursor
2026-03-19 09:31:53 +08:00

74 lines
2.2 KiB
Rust

use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Config {
pub database_url: Option<String>,
}
pub fn config_dir() -> PathBuf {
dirs::config_dir()
.or_else(|| dirs::home_dir().map(|h| h.join(".config")))
.unwrap_or_else(|| PathBuf::from(".config"))
.join("secrets")
}
pub fn config_path() -> PathBuf {
config_dir().join("config.toml")
}
pub fn load_config() -> Result<Config> {
let path = config_path();
if !path.exists() {
return Ok(Config::default());
}
let content = fs::read_to_string(&path)
.with_context(|| format!("failed to read config file: {}", path.display()))?;
let config: Config = toml::from_str(&content)
.with_context(|| format!("failed to parse config file: {}", path.display()))?;
Ok(config)
}
pub fn save_config(config: &Config) -> Result<()> {
let dir = config_dir();
fs::create_dir_all(&dir)
.with_context(|| format!("failed to create config dir: {}", dir.display()))?;
let path = config_path();
let content = toml::to_string_pretty(config).context("failed to serialize config")?;
fs::write(&path, &content)
.with_context(|| format!("failed to write config file: {}", path.display()))?;
// Set file permissions to 0600 (owner read/write only)
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let perms = fs::Permissions::from_mode(0o600);
fs::set_permissions(&path, perms)
.with_context(|| format!("failed to set file permissions: {}", path.display()))?;
}
Ok(())
}
/// Resolve database URL by priority:
/// 1. --db-url CLI flag (if non-empty)
/// 2. database_url in ~/.config/secrets/config.toml
/// 3. Error with setup instructions
pub fn resolve_db_url(cli_db_url: &str) -> Result<String> {
if !cli_db_url.is_empty() {
return Ok(cli_db_url.to_string());
}
let config = load_config()?;
if let Some(url) = config.database_url
&& !url.is_empty()
{
return Ok(url);
}
anyhow::bail!("Database not configured. Run:\n\n secrets config set-db <DATABASE_URL>\n")
}