From 9e5faaa015b2f62c63f11b59787de48601a817f0 Mon Sep 17 00:00:00 2001 From: muji Date: Wed, 20 Jul 2022 13:35:52 +0800 Subject: [PATCH] Add updated date/time to secret meta data. (#76) Closes #20. --- workspace/client/src/shell/mod.rs | 5 ++++- workspace/client/src/shell/print.rs | 5 +++-- workspace/core/src/error.rs | 4 ++++ workspace/core/src/secret.rs | 20 ++++++++++++++++++-- workspace/core/src/timestamp.rs | 14 ++++++++++++-- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/workspace/client/src/shell/mod.rs b/workspace/client/src/shell/mod.rs index fa277caa46..958093317a 100644 --- a/workspace/client/src/shell/mod.rs +++ b/workspace/client/src/shell/mod.rs @@ -689,7 +689,7 @@ fn exec_program( drop(reader); - let (uuid, secret_meta, secret_data) = + let (uuid, mut secret_meta, secret_data) = result.ok_or(Error::SecretNotAvailable(secret.clone()))?; let result = @@ -717,6 +717,8 @@ fn exec_program( let summary = keeper.summary().clone(); + secret_meta.touch(); + let event = keeper .update(&uuid, secret_meta, edited_secret)? .ok_or(Error::SecretNotAvailable(secret))?; @@ -792,6 +794,7 @@ fn exec_program( let mut secret_meta = keeper.decrypt_meta(&meta_aead)?; secret_meta.set_label(label); + secret_meta.touch(); let meta_aead = keeper.encrypt_meta(&secret_meta)?; let (commit, _) = Vault::commit_hash(&meta_aead, &secret_aead)?; diff --git a/workspace/client/src/shell/print.rs b/workspace/client/src/shell/print.rs index e72fb97413..10aa2f5ba3 100644 --- a/workspace/client/src/shell/print.rs +++ b/workspace/client/src/shell/print.rs @@ -23,11 +23,12 @@ pub(super) fn secret( secret_data: &Secret, ) -> Result<()> { let heading = - format!("[{}] {}", secret_meta.short_name(), secret_meta.label()); + format!("[{}] {}", secret_meta.short_name(), secret_meta.last_updated().to_date_time()?); let banner = Banner::new() .padding(Padding::one()) - .text(Cow::Owned(heading)); + .text(Cow::Owned(heading)) + .text(Cow::Borrowed(secret_meta.label())); let banner = match secret_data { Secret::Note(text) => { diff --git a/workspace/core/src/error.rs b/workspace/core/src/error.rs index ca58979f5d..3892442b4a 100644 --- a/workspace/core/src/error.rs +++ b/workspace/core/src/error.rs @@ -192,6 +192,10 @@ pub enum Error { #[error(transparent)] TimeFormat(#[from] time::error::Format), + /// Error generated creating format descriptions for date formatting. + #[error(transparent)] + InvalidFormat(#[from] time::error::InvalidFormatDescription), + /// Error generated parsing PEM files. #[error(transparent)] Pem(#[from] pem::PemError), diff --git a/workspace/core/src/secret.rs b/workspace/core/src/secret.rs index f7c5a904f9..5196b9c36c 100644 --- a/workspace/core/src/secret.rs +++ b/workspace/core/src/secret.rs @@ -13,7 +13,7 @@ use std::{collections::HashMap, fmt, str::FromStr}; use url::Url; use uuid::Uuid; -use crate::Error; +use crate::{Error, Timestamp}; fn serialize_secret_string( secret: &SecretString, @@ -135,12 +135,14 @@ pub struct SecretMeta { label: String, /// Kind of the secret. kind: u8, + /// Last updated timestamp. + last_updated: Timestamp, } impl SecretMeta { /// Create new meta data for a secret. pub fn new(label: String, kind: u8) -> Self { - Self { label, kind } + Self { label, kind, last_updated: Default::default() } } /// The label for the secret. @@ -158,6 +160,16 @@ impl SecretMeta { &self.kind } + /// Update the last updated timestamp to now. + pub fn touch(&mut self) { + self.last_updated = Default::default(); + } + + /// The last updated date and time. + pub fn last_updated(&self) -> &Timestamp { + &self.last_updated + } + /// Get an abbreviated short name based /// on the kind of secret. pub fn short_name(&self) -> &str { @@ -176,6 +188,7 @@ impl SecretMeta { impl Encode for SecretMeta { fn encode(&self, writer: &mut BinaryWriter) -> BinaryResult<()> { writer.write_u8(self.kind)?; + self.last_updated.encode(&mut *writer)?; writer.write_string(&self.label)?; Ok(()) } @@ -184,6 +197,9 @@ impl Encode for SecretMeta { impl Decode for SecretMeta { fn decode(&mut self, reader: &mut BinaryReader) -> BinaryResult<()> { self.kind = reader.read_u8()?; + let mut last_updated: Timestamp = Default::default(); + last_updated.decode(&mut *reader)?; + self.last_updated = last_updated; self.label = reader.read_string()?; Ok(()) } diff --git a/workspace/core/src/timestamp.rs b/workspace/core/src/timestamp.rs index 1e18b9ba43..7eb651f997 100644 --- a/workspace/core/src/timestamp.rs +++ b/workspace/core/src/timestamp.rs @@ -11,14 +11,14 @@ use std::fmt; use filetime::FileTime; use time::{ - format_description::well_known::{Rfc2822, Rfc3339}, + format_description::{self, well_known::{Rfc2822, Rfc3339}}, Duration, OffsetDateTime, UtcOffset, }; use crate::Result; /// Timestamp for events and log records. -#[derive(Debug, Clone, Serialize, Deserialize, PartialOrd, Eq, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq)] pub struct Timestamp(OffsetDateTime); impl Default for Timestamp { @@ -28,6 +28,16 @@ impl Default for Timestamp { } impl Timestamp { + + /// Convert to a short human-readable date and time without + /// the timezone offset. + pub fn to_date_time(&self) -> Result { + let format = format_description::parse( + "[day] [month repr:short] [year] [hour]:[minute]:[second]", + )?; + Ok(self.0.format(&format)?) + } + /// Convert this timestamp to a RFC2822 formatted string. pub fn to_rfc2822(&self) -> Result { Ok(Timestamp::rfc2822(&self.0)?)