feat(config): persist database URL to ~/.config/secrets/config.toml

- Add 'secrets config set-db/show/path' subcommands
- Remove dotenvy and DATABASE_URL env var support
- Config file created with 0600 permission
- Bump version to 0.3.0

Made-with: Cursor
This commit is contained in:
voson
2026-03-18 16:19:11 +08:00
parent e6db23bd6d
commit 9620ff1923
6 changed files with 202 additions and 16 deletions

54
src/commands/config.rs Normal file
View File

@@ -0,0 +1,54 @@
use crate::config::{self, Config, config_path};
use anyhow::Result;
pub enum ConfigAction {
SetDb { url: String },
Show,
Path,
}
pub async fn run(action: ConfigAction) -> Result<()> {
match action {
ConfigAction::SetDb { url } => {
let cfg = Config {
database_url: Some(url.clone()),
};
config::save_config(&cfg)?;
println!("✓ 数据库连接串已保存到: {}", config_path().display());
println!(" {}", mask_password(&url));
}
ConfigAction::Show => {
let cfg = config::load_config()?;
match cfg.database_url {
Some(url) => {
println!("database_url = {}", mask_password(&url));
println!("配置文件: {}", config_path().display());
}
None => {
println!("未配置数据库连接串。");
println!("请运行secrets config set-db <DATABASE_URL>");
}
}
}
ConfigAction::Path => {
println!("{}", config_path().display());
}
}
Ok(())
}
/// 将 postgres://user:password@host/db 中的密码替换为 ***
fn mask_password(url: &str) -> String {
if let Some(at_pos) = url.rfind('@')
&& let Some(scheme_end) = url.find("://")
{
let prefix = &url[..scheme_end + 3];
let credentials = &url[scheme_end + 3..at_pos];
let rest = &url[at_pos..];
if let Some(colon_pos) = credentials.find(':') {
let user = &credentials[..colon_pos];
return format!("{}{}:***{}", prefix, user, rest);
}
}
url.to_string()
}