feat(add,update): key:=json typed values, nested path for meta/secrets, bump 0.7.4
Some checks failed
Secrets CLI - Build & Release / 质量检查 (fmt / clippy / test) (push) Successful in 1m53s
Secrets CLI - Build & Release / Build (x86_64-unknown-linux-musl) (push) Successful in 1m3s
Secrets CLI - Build & Release / 版本 & Release (push) Successful in 3s
Secrets CLI - Build & Release / Build (macOS aarch64 + x86_64) (push) Successful in 49s
Secrets CLI - Build & Release / 发布草稿 Release (push) Has been cancelled
Secrets CLI - Build & Release / Build (x86_64-pc-windows-msvc) (push) Has been cancelled

Made-with: Cursor
This commit is contained in:
voson
2026-03-19 14:27:04 +08:00
parent 5a5867adc1
commit efa76cae55
7 changed files with 386 additions and 72 deletions

View File

@@ -3,7 +3,9 @@ use serde_json::{Map, Value, json};
use sqlx::{FromRow, PgPool};
use uuid::Uuid;
use super::add::parse_kv;
use super::add::{
collect_field_paths, collect_key_paths, insert_path, parse_key_path, parse_kv, remove_path,
};
use crate::crypto;
use crate::db;
use crate::output::OutputMode;
@@ -89,11 +91,12 @@ pub async fn run(pool: &PgPool, args: UpdateArgs<'_>, master_key: &[u8; 32]) ->
_ => Map::new(),
};
for entry in args.meta_entries {
let (key, value) = parse_kv(entry)?;
meta_map.insert(key, value);
let (path, value) = parse_kv(entry)?;
insert_path(&mut meta_map, &path, value)?;
}
for key in args.remove_meta {
meta_map.remove(key);
let path = parse_key_path(key)?;
remove_path(&mut meta_map, &path)?;
}
let metadata = Value::Object(meta_map);
@@ -108,11 +111,12 @@ pub async fn run(pool: &PgPool, args: UpdateArgs<'_>, master_key: &[u8; 32]) ->
_ => Map::new(),
};
for entry in args.secret_entries {
let (key, value) = parse_kv(entry)?;
enc_map.insert(key, value);
let (path, value) = parse_kv(entry)?;
insert_path(&mut enc_map, &path, value)?;
}
for key in args.remove_secrets {
enc_map.remove(key);
let path = parse_key_path(key)?;
remove_path(&mut enc_map, &path)?;
}
let secret_json = Value::Object(enc_map);
let encrypted_bytes = crypto::encrypt_json(master_key, &secret_json)?;
@@ -148,16 +152,10 @@ pub async fn run(pool: &PgPool, args: UpdateArgs<'_>, master_key: &[u8; 32]) ->
);
}
let meta_keys: Vec<&str> = args
.meta_entries
.iter()
.filter_map(|s| s.split_once(['=', ':']).map(|(k, _)| k))
.collect();
let secret_keys: Vec<&str> = args
.secret_entries
.iter()
.filter_map(|s| s.split_once(['=', ':']).map(|(k, _)| k))
.collect();
let meta_keys = collect_key_paths(args.meta_entries)?;
let remove_meta_keys = collect_field_paths(args.remove_meta)?;
let secret_keys = collect_key_paths(args.secret_entries)?;
let remove_secret_keys = collect_field_paths(args.remove_secrets)?;
crate::audit::log_tx(
&mut tx,
@@ -169,9 +167,9 @@ pub async fn run(pool: &PgPool, args: UpdateArgs<'_>, master_key: &[u8; 32]) ->
"add_tags": args.add_tags,
"remove_tags": args.remove_tags,
"meta_keys": meta_keys,
"remove_meta": args.remove_meta,
"remove_meta": remove_meta_keys,
"secret_keys": secret_keys,
"remove_secrets": args.remove_secrets,
"remove_secrets": remove_secret_keys,
}),
)
.await;
@@ -186,9 +184,9 @@ pub async fn run(pool: &PgPool, args: UpdateArgs<'_>, master_key: &[u8; 32]) ->
"add_tags": args.add_tags,
"remove_tags": args.remove_tags,
"meta_keys": meta_keys,
"remove_meta": args.remove_meta,
"remove_meta": remove_meta_keys,
"secret_keys": secret_keys,
"remove_secrets": args.remove_secrets,
"remove_secrets": remove_secret_keys,
});
match args.output {
@@ -210,13 +208,13 @@ pub async fn run(pool: &PgPool, args: UpdateArgs<'_>, master_key: &[u8; 32]) ->
println!(" +metadata: {}", meta_keys.join(", "));
}
if !args.remove_meta.is_empty() {
println!(" -metadata: {}", args.remove_meta.join(", "));
println!(" -metadata: {}", remove_meta_keys.join(", "));
}
if !args.secret_entries.is_empty() {
println!(" +secrets: {}", secret_keys.join(", "));
}
if !args.remove_secrets.is_empty() {
println!(" -secrets: {}", args.remove_secrets.join(", "));
println!(" -secrets: {}", remove_secret_keys.join(", "));
}
}
}