diff --git a/src/user_management/manager.rs b/src/user_management/manager.rs index 3ccd150..2dacd35 100644 --- a/src/user_management/manager.rs +++ b/src/user_management/manager.rs @@ -4,13 +4,16 @@ use serde::{Deserialize, Serialize, de::DeserializeOwned}; use std::path::Path; use crate::user_management::{User, Result}; -use crate::user_management::user::{SignedInUser, NotSignedInUser, UserInner}; +use crate::user_management::user::{SignedInUser, NotSignedInUser, PartialUser}; #[derive(Debug, Clone, Deserialize, Serialize)] /// Data stored in the certificate tree about a certain certificate pub struct CertificateData { #[serde(with = "CertificateDef")] + /// The certificate in question pub certificate: Certificate, + + /// The username of the user to which this certificate is registered pub owner_username: String, } @@ -71,7 +74,7 @@ impl UserManager { pub fn lookup_user<'de, UserData>( &self, username: impl AsRef<[u8]> - ) -> Result>> + ) -> Result>> where UserData: Serialize + DeserializeOwned { diff --git a/src/user_management/user.rs b/src/user_management/user.rs index 205071c..cb2d036 100644 --- a/src/user_management/user.rs +++ b/src/user_management/user.rs @@ -7,11 +7,61 @@ use crate::user_management::Result; use crate::user_management::manager::CertificateData; /// An struct corresponding to the data stored in the user tree +/// +/// In order to generate a full user obj, you need to perform a lookup with a specific +/// certificate. #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct UserInner { - data: UserData, - certificates: Vec, - pass_hash: Option, +pub struct PartialUser { + pub data: UserData, + pub certificates: Vec, + pub pass_hash: Option, +} + +impl PartialUser { + + /// A list of certificate hashes registered to this user + /// + /// Can be looked up using [`UserManager::lookup_certficate`] to get full information + pub fn certificates(&self) -> &Vec { + &self.certificates + } + + /// The bcrypt hash of the user's password + pub fn pass_hash(&self) -> Option<&str> { + self.pass_hash.as_ref().map(|s| s.as_str()) + } + + /// Write user data to the database + /// + /// This MUST be called if the user data is modified using the AsMut trait, or else + /// changes will not be written to the database + pub fn store(&self, tree: &sled::Tree, username: impl AsRef<[u8]>) -> Result<()> + where + UserData: Serialize + { + tree.insert( + &username, + bincode::serialize(&self)?, + )?; + Ok(()) + } +} + +impl AsRef for PartialUser { + /// Access any data the application has stored for the user. + fn as_ref(&self) -> &UserData { + &self.data + } +} + +impl AsMut for PartialUser { + /// Modify the data stored for a user + /// + /// IMPORTANT: Changes will not be written to the database until + /// [`PartialUser::store()`] is called + fn as_mut(&mut self) -> &mut UserData { + &mut self.data + } } /// Any information about the connecting user @@ -63,7 +113,7 @@ impl NotSignedInUser { let cert_hash = UserManager::hash_certificate(&self.certificate); let newser = SignedInUser { - inner: UserInner { + inner: PartialUser { data: UserData::default(), certificates: vec![cert_hash], pass_hash: None, @@ -127,7 +177,7 @@ pub struct SignedInUser { pub (crate) username: String, pub (crate) active_certificate: Certificate, pub (crate) manager: UserManager, - pub (crate) inner: UserInner, + pub (crate) inner: PartialUser, } impl SignedInUser { @@ -180,11 +230,7 @@ impl SignedInUser { where UserData: Serialize { - self.manager.users.insert( - &self.username, - bincode::serialize(&self.inner)?, - )?; - Ok(()) + self.inner.store(&self.manager.users, &self.username) } }