aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2018-06-30 12:02:40 +0200
committerKatharina Fey <kookie@spacekookie.de>2018-06-30 12:02:40 +0200
commit88e5d4b6cf147df85915dce5de6037e1801d64e0 (patch)
treedd470acbfdafd71117883e0003c092806ef53011
parent23019c494588a63babd45bb70730ab8076df9154 (diff)
Adding userstore API and `meta_push_vault` to the vault trait
-rw-r--r--lockchain-core/src/meta.rs13
-rw-r--r--lockchain-core/src/traits.rs2
-rw-r--r--lockchain-core/src/users.rs77
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(),
+ )
+ }
+}