diff options
author | Katharina Fey <kookie@spacekookie.de> | 2018-06-30 12:02:40 +0200 |
---|---|---|
committer | Katharina Fey <kookie@spacekookie.de> | 2018-06-30 12:02:40 +0200 |
commit | 88e5d4b6cf147df85915dce5de6037e1801d64e0 (patch) | |
tree | dd470acbfdafd71117883e0003c092806ef53011 | |
parent | 23019c494588a63babd45bb70730ab8076df9154 (diff) |
Adding userstore API and `meta_push_vault` to the vault trait
-rw-r--r-- | lockchain-core/src/meta.rs | 13 | ||||
-rw-r--r-- | lockchain-core/src/traits.rs | 2 | ||||
-rw-r--r-- | lockchain-core/src/users.rs | 77 |
3 files changed, 87 insertions, 5 deletions
diff --git a/lockchain-core/src/meta.rs b/lockchain-core/src/meta.rs index 503c7ff..cf3eb36 100644 --- a/lockchain-core/src/meta.rs +++ b/lockchain-core/src/meta.rs @@ -51,6 +51,19 @@ impl MetaDomain { } } + /// Return a MetaDomain that is filled with pre-existing data + pub fn fill(self, new_body: HashMap<String, Payload>) -> Self { + Self { + body: new_body, + ..self + } + } + + /// Return a read-only reference to the entire body + pub fn all(&self) -> &HashMap<String, Payload> { + &self.body + } + /// Return the domain name for easy comparison pub fn name(&self) -> &str { &self.name diff --git a/lockchain-core/src/traits.rs b/lockchain-core/src/traits.rs index 9ef2903..b6b81d8 100644 --- a/lockchain-core/src/traits.rs +++ b/lockchain-core/src/traits.rs @@ -115,6 +115,8 @@ where fn meta_add_domain(&mut self, domain: &str) -> Option<()>; /// Returns all records from a meta domain fn meta_pull_domain(&mut self, domain: &str) -> Option<&MetaDomain>; + /// Entirely replace a meta domain in the store + fn meta_push_domain(&mut self, domain: MetaDomain) -> Option<()>; /// Set the value of a field inside a domain. Field names **must not** collide fn meta_set(&mut self, domain: &str, name: &str, data: Payload) -> Option<()>; /// Get the value of a (unique) field inside a domain diff --git a/lockchain-core/src/users.rs b/lockchain-core/src/users.rs index 654b924..581bcce 100644 --- a/lockchain-core/src/users.rs +++ b/lockchain-core/src/users.rs @@ -17,7 +17,8 @@ mod auth; pub use self::auth::Token; use crypto::{encoding, hashing}; -use traits::AutoEncoder; +use std::collections::HashMap; +use {meta::MetaDomain, traits::AutoEncoder}; /// Specifies access to a resource #[derive(Serialize, Deserialize)] @@ -39,12 +40,23 @@ pub enum Role { } /// A generic user representation +/// +/// A user has an identify check built in that can verify a passphrase +/// but is ultimately only a metadata item for a API layer. Any layer is +/// free to disregard these access rights (as such, they should not be +/// considered security, only obscurity/ management control) +/// +/// A company might not want allow non-admins to create new vaults or +/// users to delete records. This does not cryptographically stop anyone +/// from breaking into the company server, swapping the source code and +/// changing the rules! +/// +/// An user can have multiple role-access pairs #[derive(Serialize, Deserialize)] pub struct User { name: String, pw_hash: String, - role: Role, - access: Vec<Access>, + rights: Vec<(Access, Role)>, } impl User { @@ -53,10 +65,65 @@ impl User { Self { name: name.into(), pw_hash: encoding::base64_encode(&hashing::blake2(pw, name).to_vec()), - role: Role::Reader, - access: Vec::new(), + rights: Vec::new(), } } + /// Verify a user password input + pub fn verify(&self, pw: &str) -> bool { + self.pw_hash == encoding::base64_encode(&hashing::blake2(pw, &self.name).to_vec()) + } } impl AutoEncoder for User {} + +/// A utility structure that loads user data +/// from a metadata store backend +#[derive(Serialize, Deserialize)] +pub struct UserStore { + /// A map between username – user item + users: HashMap<String, User>, +} + +impl UserStore { + pub fn get_user(&self, name: &str) -> Option<&User> { + self.users.get(name) + } +} + +impl AutoEncoder for UserStore {} + +/// Allow users to turn MetaDomains +/// that *are* userstores into a UserStore easily +/// +/// Will `panic!` if called on a non UserStore +impl From<MetaDomain> for UserStore { + fn from(md: MetaDomain) -> Self { + use Payload; + Self { + users: md + .all() + .iter() + .map(|(k, v)| { + ( + k.clone(), + match v { + Payload::Text(s) => User::decode(s).unwrap(), + _ => unreachable!(), + }, + ) + }) + .collect(), + } + } +} + +impl From<UserStore> for MetaDomain { + fn from(us: UserStore) -> Self { + MetaDomain::new("userstore").fill( + us.users + .iter() + .map(|(name, user)| (name.clone(), ::Payload::Text(user.encode().unwrap()))) + .collect(), + ) + } +} |