From 343a6f5facb6c85dc81f38a7d2709c95c12d66bc Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Fri, 15 Dec 2023 21:15:22 +0800 Subject: [PATCH] feat: v1.5.2, fix edit file issue, add prefixes --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 3 +++ src/cmd_decrypt.rs | 12 +++++++++--- src/cmd_encrypt.rs | 3 ++- src/cmd_execenv.rs | 3 ++- src/cmd_info.rs | 5 +++-- src/config.rs | 38 ++++++++++++++++++++++++++++++++++++-- 8 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca22c7c..3ffc994 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1700,7 +1700,7 @@ dependencies = [ [[package]] name = "tiny-encrypt" -version = "1.5.1" +version = "1.5.2" dependencies = [ "aes-gcm-stream", "base64", diff --git a/Cargo.toml b/Cargo.toml index d8db155..217d1a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tiny-encrypt" -version = "1.5.1" +version = "1.5.2" edition = "2021" license = "MIT" description = "A simple and tiny file encrypt tool" diff --git a/README.md b/README.md index 819653a..0cb0885 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,9 @@ Encrypt config `~/.tinyencrypt/config-rs.json`: "environment": { "TINY_ENCRYPT_DEFAULT_ALGORITHM": "AES or CHACHA20" }, + "namespaces": { + "name": "/Users/example/.name" + }, "envelops": [ { "type": "pgp-rsa", diff --git a/src/cmd_decrypt.rs b/src/cmd_decrypt.rs index 0ddde34..4b63555 100644 --- a/src/cmd_decrypt.rs +++ b/src/cmd_decrypt.rs @@ -20,7 +20,7 @@ use yubikey::piv::{AlgorithmId, decrypt_data}; use yubikey::YubiKey; use zeroize::Zeroize; -use crate::{cmd_encrypt, consts, crypto_simple, util, util_enc_file, util_env, util_envelop, util_file, util_pgp, util_piv}; +use crate::{cmd_encrypt, config, consts, crypto_simple, util, util_enc_file, util_env, util_envelop, util_file, util_pgp, util_piv}; use crate::compress::GzStreamDecoder; use crate::config::TinyEncryptConfig; use crate::consts::{ @@ -102,8 +102,9 @@ pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> { let key_id = cmd_decrypt.key_id.clone().or_else(util_env::get_key_id); for path in &cmd_decrypt.paths { + let path = config::resolve_path_namespace(&config, path, true); let start_decrypt_single = Instant::now(); - match decrypt_single(&config, path, &pin, &key_id, &cmd_decrypt.slot, &cmd_decrypt) { + match decrypt_single(&config, &path, &pin, &key_id, &cmd_decrypt.slot, &cmd_decrypt) { Ok(len) => { succeed_count += 1; if len > 0 { @@ -328,7 +329,12 @@ fn get_file_editor() -> (bool, String) { fn create_edit_temp_file(file_content: &[u8], path_out: &str) -> XResult { let temp_dir = temp_dir(); let current_millis = util_time::get_current_millis(); - let temp_file = temp_dir.join(format!("tmp_file_{}_{}", current_millis, path_out)); + let file_name = if path_out.contains('/') { + path_out.split('/').last().unwrap().to_string() + } else { + path_out.to_string() + }; + let temp_file = temp_dir.join(format!("tmp_file_{}_{}", current_millis, file_name)); information!("Temp file: {}", temp_file.display()); opt_result!(fs::write(&temp_file, file_content), "Write temp file failed: {}"); Ok(temp_file) diff --git a/src/cmd_encrypt.rs b/src/cmd_encrypt.rs index c019274..c9de05b 100644 --- a/src/cmd_encrypt.rs +++ b/src/cmd_encrypt.rs @@ -82,8 +82,9 @@ pub fn encrypt(cmd_encrypt: CmdEncrypt) -> XResult<()> { let mut failed_count = 0; let mut total_len = 0_u64; for path in &cmd_encrypt.paths { + let path = config.resolve_path_namespace(path, false); let start_encrypt_single = Instant::now(); - match encrypt_single(path, &envelops, &cmd_encrypt) { + match encrypt_single(&path, &envelops, &cmd_encrypt) { Ok(len) => { total_len += len; if len > 0 { succeed_count += 1; } else { skipped_count += 1; } diff --git a/src/cmd_execenv.rs b/src/cmd_execenv.rs index 247b4cd..7a7aec9 100644 --- a/src/cmd_execenv.rs +++ b/src/cmd_execenv.rs @@ -8,7 +8,7 @@ use rust_util::{debugging, iff, information, opt_result, simple_error, util_cmd, use serde_json::Value; use zeroize::Zeroize; -use crate::{consts, util, util_env}; +use crate::{config, consts, util, util_env}; use crate::cmd_decrypt::{decrypt_limited_content_to_vec, select_envelop, try_decrypt_key}; use crate::config::TinyEncryptConfig; use crate::consts::TINY_ENC_CONFIG_FILE; @@ -52,6 +52,7 @@ pub fn exec_env(cmd_exec_env: CmdExecEnv) -> XResult<()> { let key_id = cmd_exec_env.key_id.clone().or_else(util_env::get_key_id); let path = PathBuf::from(&cmd_exec_env.file_name); + let path = config::resolve_path_namespace(&config, &path, true); let path_display = format!("{}", &path.display()); util::require_tiny_enc_file_and_exists(&path)?; diff --git a/src/cmd_info.rs b/src/cmd_info.rs index f477065..1f2ae62 100644 --- a/src/cmd_info.rs +++ b/src/cmd_info.rs @@ -11,7 +11,7 @@ use rust_util::{ use rust_util::util_time::UnixEpochTime; use simpledateformat::format_human2; -use crate::{util, util_enc_file, util_envelop}; +use crate::{config, util, util_enc_file, util_envelop}; use crate::config::TinyEncryptConfig; use crate::consts::{DATE_TIME_FORMAT, TINY_ENC_AES_GCM, TINY_ENC_CONFIG_FILE, TINY_ENC_FILE_EXT}; use crate::wrap_key::WrapKey; @@ -28,8 +28,9 @@ pub struct CmdInfo { pub fn info(cmd_info: CmdInfo) -> XResult<()> { let config = TinyEncryptConfig::load(TINY_ENC_CONFIG_FILE).ok(); for (i, path) in cmd_info.paths.iter().enumerate() { + let path = config::resolve_path_namespace(&config, path, true); if i > 0 { println!("{}", "-".repeat(88)); } - if let Err(e) = info_single(path, &cmd_info, &config) { + if let Err(e) = info_single(&path, &cmd_info, &config) { failure!("Parse Tiny Encrypt file info failed: {}", e); } } diff --git a/src/config.rs b/src/config.rs index 27e4547..a4e559d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,11 +1,13 @@ +use std::{env, fs}; use std::cmp::Ordering; use std::collections::HashMap; -use std::{env, fs}; +use std::path::PathBuf; -use rust_util::{debugging, opt_result, simple_error, XResult}; +use rust_util::{debugging, opt_result, simple_error, warning, XResult}; use rust_util::util_file::resolve_file_path; use serde::{Deserialize, Serialize}; +use crate::consts::TINY_ENC_FILE_EXT; use crate::spec::TinyEncryptEnvelopType; /// Config file sample: @@ -35,6 +37,7 @@ use crate::spec::TinyEncryptEnvelopType; #[serde(rename_all = "camelCase")] pub struct TinyEncryptConfig { pub environment: Option>, + pub namespaces: Option>, pub envelops: Vec, pub profiles: HashMap>, } @@ -86,6 +89,30 @@ impl TinyEncryptConfig { Ok(config) } + pub fn resolve_path_namespace(&self, path: &PathBuf, append_te: bool) -> PathBuf { + if let Some(path_str) = path.to_str() { + if path_str.starts_with(':') { + let namespace = path_str.chars().skip(1) + .take_while(|c| *c != ':').collect::(); + let mut filename = path_str.chars().skip(1) + .skip_while(|c| *c != ':').skip(1).collect::(); + if append_te && !filename.ends_with(TINY_ENC_FILE_EXT) { + filename.push_str(TINY_ENC_FILE_EXT); + } + + match self.find_namespace(&namespace) { + None => warning!("Namespace: {} not found", &namespace), + Some(dir) => return PathBuf::from(dir).join(&filename), + } + } + } + path.clone() + } + + pub fn find_namespace(&self, prefix: &str) -> Option<&String> { + self.namespaces.as_ref().and_then(|m| m.get(prefix)) + } + pub fn find_first_arg_by_kid(&self, kid: &str) -> Option<&String> { self.find_args_by_kid(kid).and_then(|a| a.iter().next()) } @@ -169,3 +196,10 @@ impl TinyEncryptConfig { Ok(envelops) } } + +pub fn resolve_path_namespace(config: &Option, path: &PathBuf, append_te: bool) -> PathBuf { + match config { + None => path.clone(), + Some(config) => config.resolve_path_namespace(path, append_te), + } +}