From 8b9c8668e9a3aaa56a41be04859a05abb94db60c Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Thu, 6 Sep 2018 00:26:02 +0200 Subject: Refactoring the vault trait to consume a generator struct --- lockchain-core/src/initialise.rs | 55 ++++++++++++++ lockchain-core/src/lib.rs | 2 + lockchain-core/src/traits.rs | 20 +++-- lockchain-core/src/users/keystore.rs | 70 ------------------ lockchain-core/src/users/mod.rs | 137 ----------------------------------- lockchain-files/examples/create.rs | 4 +- 6 files changed, 75 insertions(+), 213 deletions(-) create mode 100644 lockchain-core/src/initialise.rs delete mode 100644 lockchain-core/src/users/keystore.rs diff --git a/lockchain-core/src/initialise.rs b/lockchain-core/src/initialise.rs new file mode 100644 index 0000000..6ae48a9 --- /dev/null +++ b/lockchain-core/src/initialise.rs @@ -0,0 +1,55 @@ +//! A shared initialisation block for vaults +//! +//! All vaults, regardless of backends +//! or persistence layer +//! share the same common principles +//! of users and permissions. +//! +//! This means that intiailisation is shared, +//! regardless of what backend implements it. +//! +//! A `VaultGenerator` takes arguments +//! for a generic backend, +//! calls functions provided by said backend +//! and then returns the actual backend. + +use traits::{Body, Vault}; + +/// A generator is initialised with a generic backend +/// which can then chain-call functions to setup the +/// base functionality of a Vault, and then yield +/// a working and initialised instance of the +/// generic vault backend. +pub struct Generator { + #[doc(hidden)] + pub name: Option, + #[doc(hidden)] + pub location: Option, +} + +impl Generator { + /// Start a new generator for a generic type + pub fn new() -> Self { + Self { + name: None, + location: None, + } + } + + pub fn path>(self, name: S, location: S) -> Self { + Self { + name: Some(name.into()), + location: Some(location.into()), + ..self + } + } + + /// Finally call this function to construct the vault + pub fn finalise(self) -> V + where + V: Vault, + B: Body, + { + V::new(self) + } +} diff --git a/lockchain-core/src/lib.rs b/lockchain-core/src/lib.rs index 2ec812e..9c9ba95 100644 --- a/lockchain-core/src/lib.rs +++ b/lockchain-core/src/lib.rs @@ -76,6 +76,8 @@ mod record; pub mod traits; pub mod users; +mod initialise; + pub use self::crypto::PackedData; pub use self::meta::{MetaDomain, VaultMetadata}; pub use self::record::{EncryptedBody, Header, Payload, Record}; diff --git a/lockchain-core/src/traits.rs b/lockchain-core/src/traits.rs index 58b63b2..efde578 100644 --- a/lockchain-core/src/traits.rs +++ b/lockchain-core/src/traits.rs @@ -11,10 +11,11 @@ //! compilation work without external crates but not calling //! functions at runtime. +use initialise::Generator; use meta::{MetaDomain, VaultMetadata}; use record::{EncryptedBody, Header, Payload, Record}; use serde::{de::DeserializeOwned, Serialize}; -use users::Token; +use users::{Access, Token}; use base64; use serde_json::{self, Error as SerdeError}; @@ -117,19 +118,28 @@ pub trait FileIO: AutoEncoder { /// authentication will need to be backed by some persistence layer /// (i.e. lockchain-files) /// -/// pub trait Vault: Send + LoadRecord where T: Body, { - /// A shared constructor for all vault implementations - fn new(name: &str, location: &str) -> Self; + /// Consumes a vault generator to construct a vault + fn new(cfg: Generator) -> Self; /// Load and open an existing vault fn load(name: &str, location: &str) -> Option>; /// Unlock the vault for a specific user fn authenticate(&mut self, username: &str, secret: &str) -> Token; /// End a specific user session fn deauthenticate(&mut self, username: &str, _: Token); + /// Create a new user with a list of initial access rights + fn create_user( + &mut self, + token: Token, + username: &str, + secret: &str, + access: Vec, + ) -> Result<(), ()>; + /// Delete a user + fn delete_user(&mut self, token: Token, username: &str); /// Get basic vault metadata fn metadata(&self) -> VaultMetadata; @@ -138,7 +148,7 @@ where /// Pull a specific record from the backend fn pull(&mut self, name: &str); /// Sync all changes back to the backend - /// + /// /// Ultimately it's up to the backend to decide /// how changes are synced. /// It's free to ignore any sync requests diff --git a/lockchain-core/src/users/keystore.rs b/lockchain-core/src/users/keystore.rs deleted file mode 100644 index 7da77ec..0000000 --- a/lockchain-core/src/users/keystore.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! A keystore is a specific implementation of a metadata store -//! -//! At it's core it provides three simple functions -//! -//! - Adding keys for a user -//! - Removing keys -//! - Retrieving keys -//! -//! **This module is meant to be used by lockchain-library implementations** - -#![deprecated(since="0.10.0", note="Use the `userstore::UserStore` structure instead")] - -use traits::{AutoEncoder, Base64AutoEncoder}; -use {crypto::Key, meta::MetaDomain}; - -use std::collections::HashMap; - -/// A utility wrapper around a Username -> Key collection -#[derive(Serialize, Deserialize)] -pub struct KeyStore { - keys: HashMap, -} - -impl KeyStore { - pub fn add_key(&mut self, user: &str, key: Key) { - self.keys.insert(user.into(), key); - } - - pub fn revoke_key(&mut self, user: &str) { - self.keys.remove(user); - } -} - -impl AutoEncoder for KeyStore {} - -impl From for KeyStore { - fn from(d: MetaDomain) -> Self { - Self { - keys: d - .all() - .iter() - .map(|(k, v)| { - ( - k.clone(), - match v { - ::Payload::Text(s) => Key::decode(&String::from_base64(s)).unwrap(), - _ => unreachable!(), - }, - ) - }) - .collect(), - } - } -} - -impl From for MetaDomain { - fn from(ks: KeyStore) -> Self { - MetaDomain::new("keystore").fill( - ks.keys - .iter() - .map(|(name, key)| { - ( - name.clone(), - ::Payload::Text(key.encode().unwrap().to_base64()), - ) - }) - .collect(), - ) - } -} diff --git a/lockchain-core/src/users/mod.rs b/lockchain-core/src/users/mod.rs index 6482264..3fce31c 100644 --- a/lockchain-core/src/users/mod.rs +++ b/lockchain-core/src/users/mod.rs @@ -36,140 +36,3 @@ use { meta::MetaDomain, traits::{AutoEncoder, Base64AutoEncoder}, }; - -/// A utility structure that manages users and can be derived -/// from/into a metadata object. By default this process uses -/// base64 encoding. -/// -/// The workflow for this is to create a new `UserStore`, add -/// users and then use `meta_push_domain` and give it the -/// `UserStore::into()` which is then encoded automatically. -/// The reverse action works the same way -#[deprecated(since="0.10.0", note="Use the `userstore::UserStore` structure instead")] -#[allow(deprecated)] -#[derive(Serialize, Deserialize)] -pub struct UserStore { - /// A map between username – user item - users: HashMap, - registry: HashMap>, -} - -impl UserStore { - /// Generate a sign-up token for a new user which needs to be - /// provided in order for them to create an account. - pub fn get_token(&mut self, access: Vec) -> String { - let token = ::crypto::encoding::base64_encode(&::crypto::random::bytes(128)); - self.registry.insert( - token.clone(), - if access.is_empty() { - vec![Access::Vault(Role::Reader)] - } else { - access - }, - ); - - token - } - - pub fn get_user(&self, name: &str) -> Option<&User> { - self.users.get(name) - } - - pub fn get_all(&self) -> &HashMap { - &self.users - } - - pub fn add(&mut self, user: User) -> Option<()> { - self.users.insert(user.name.clone(), user); - Some(()) - } -} - -impl Default for UserStore { - fn default() -> Self { - Self { - users: HashMap::new(), - registry: HashMap::new(), - } - } -} - -impl AutoEncoder for UserStore {} - -/// Allow users to turn MetaDomains -/// that *are* userstores into a UserStore easily -/// -/// Will most likely `panic!` if called on a non UserStore -impl From<(MetaDomain, MetaDomain)> for UserStore { - fn from((users, registry): (MetaDomain, MetaDomain)) -> Self { - Self { - users: users - .all() - .iter() - .map(|(k, v)| { - ( - k.clone(), - match v { - ::Payload::Text(s) => User::decode(&String::from_base64(s)).unwrap(), - _ => unreachable!(), - }, - ) - }) - .collect(), - registry: registry - .all() - .iter() - .map(|(k, v)| { - ( - k.clone(), - match v { - ::Payload::List(regs) => regs - .iter() - .map(|reg| { - Access::decode(&String::from_base64(match reg { - ::Payload::Text(s) => s, - _ => unreachable!(), - })).unwrap() - }) - .collect(), - _ => unreachable!(), - }, - ) - }) - .collect(), - } - } -} - -impl From for (MetaDomain, MetaDomain) { - fn from(us: UserStore) -> Self { - ( - MetaDomain::new("userstore").fill( - us.users - .iter() - .map(|(name, user)| { - ( - name.clone(), - ::Payload::Text(user.encode().unwrap().to_base64()), - ) - }) - .collect(), - ), - MetaDomain::new("registry").fill( - us.registry - .iter() - .map(|(name, reg)| { - ( - name.clone(), - ::Payload::List( - reg.iter() - .map(|reg| ::Payload::Text(reg.encode().unwrap().to_base64())) - .collect(), - ), - ) - }) - .collect(), - ), - ) - } -} diff --git a/lockchain-files/examples/create.rs b/lockchain-files/examples/create.rs index 5ced78a..b152cac 100644 --- a/lockchain-files/examples/create.rs +++ b/lockchain-files/examples/create.rs @@ -12,7 +12,9 @@ fn main() { let path = env::args().nth(1).unwrap(); let name = env::args().nth(2).unwrap(); - let _vault: DataVault = DataVault::new(&name, &path); + let vault: DataVault = DataVault::new(&name, &path); + + -- cgit v1.2.3