aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2018-07-12 20:25:35 +0200
committerKatharina Fey <kookie@spacekookie.de>2018-07-12 20:25:35 +0200
commit756101753bca95800ce2dfe6dcbfeedc4148b80d (patch)
tree82ae97572cd09aed8a3decc73d19dd3f3ca58bb3
parent73f788ecc9b02d7cf909f4326f6c8813cc6a39ca (diff)
Adding a new keystore to lockchain-core::crypto, composing a userstore
from two metadomains now (users, registry) to allow for a better user registry pipeline. Tweaking examples to make all this work and generally cleaning up code
-rw-r--r--lockchain-core/src/crypto/keystore.rs59
-rw-r--r--lockchain-core/src/crypto/mod.rs4
-rw-r--r--lockchain-core/src/traits.rs2
-rw-r--r--lockchain-core/src/users/mod.rs102
-rw-r--r--lockchain-files/examples/create.rs18
-rw-r--r--lockchain-files/src/lib.rs2
6 files changed, 154 insertions, 33 deletions
diff --git a/lockchain-core/src/crypto/keystore.rs b/lockchain-core/src/crypto/keystore.rs
new file mode 100644
index 0000000..0f19e30
--- /dev/null
+++ b/lockchain-core/src/crypto/keystore.rs
@@ -0,0 +1,59 @@
+//! A utility keystore module for the lockchain ecosystem
+
+use traits::{AutoEncoder, Base64AutoEncoder};
+use {crypto::Key, meta::MetaDomain};
+
+use std::collections::HashMap;
+
+#[derive(Serialize, Deserialize)]
+pub struct KeyStore {
+ keys: HashMap<String, Key>,
+}
+
+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<MetaDomain> 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<KeyStore> 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/crypto/mod.rs b/lockchain-core/src/crypto/mod.rs
index 6fa17bb..671cff0 100644
--- a/lockchain-core/src/crypto/mod.rs
+++ b/lockchain-core/src/crypto/mod.rs
@@ -13,10 +13,12 @@ mod keys {
impl AutoEncoder for KeyType {}
}
-pub mod passwords;
+// pub mod passwords;
pub mod encoding;
+pub mod keystore;
pub mod hashing;
pub mod random;
pub use self::data::PackedData;
+pub use self::keystore::KeyStore;
pub use self::keys::{Key, KeyType};
diff --git a/lockchain-core/src/traits.rs b/lockchain-core/src/traits.rs
index 088ee84..6498ac3 100644
--- a/lockchain-core/src/traits.rs
+++ b/lockchain-core/src/traits.rs
@@ -141,7 +141,7 @@ where
/// returned with a single pull request
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>;
+ fn meta_pull_domain(&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
diff --git a/lockchain-core/src/users/mod.rs b/lockchain-core/src/users/mod.rs
index 0077427..03cbcb4 100644
--- a/lockchain-core/src/users/mod.rs
+++ b/lockchain-core/src/users/mod.rs
@@ -29,22 +29,24 @@ use {
/// Specifies access to a resource
#[derive(Hash, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum Access {
- /// Allows specific access to an entire API
- Api,
/// Allows access to vault metadata & index files
- Vault(String),
+ Vault(Role),
/// Allows access to a record resource inside a vault
- Record(String, String),
+ Record(Role, String),
}
+impl AutoEncoder for Access {}
+
/// Specifies the capabilities of a user
-#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
+#[derive(Hash, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum Role {
Reader,
Editor,
Admin,
}
+impl AutoEncoder for Role {}
+
/// A generic user representation
///
/// A user has an identify check built in that can verify a passphrase
@@ -102,21 +104,38 @@ impl User {
impl AutoEncoder for User {}
-/// A utility structure that manages users and can be derived
+/// 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
+/// 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
#[derive(Serialize, Deserialize)]
pub struct UserStore {
/// A map between username – user item
users: HashMap<String, User>,
+ registry: HashMap<String, Vec<Access>>,
}
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<Access>) -> 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)
}
@@ -135,6 +154,7 @@ impl Default for UserStore {
fn default() -> Self {
Self {
users: HashMap::new(),
+ registry: HashMap::new(),
}
}
}
@@ -145,10 +165,10 @@ impl AutoEncoder for UserStore {}
/// that *are* userstores into a UserStore easily
///
/// Will most likely `panic!` if called on a non UserStore
-impl From<MetaDomain> for UserStore {
- fn from(md: MetaDomain) -> Self {
+impl From<(MetaDomain, MetaDomain)> for UserStore {
+ fn from((users, registry): (MetaDomain, MetaDomain)) -> Self {
Self {
- users: md
+ users: users
.all()
.iter()
.map(|(k, v)| {
@@ -161,22 +181,60 @@ impl From<MetaDomain> for UserStore {
)
})
.collect(),
- }
- }
-}
-
-impl From<UserStore> for MetaDomain {
- fn from(us: UserStore) -> Self {
- MetaDomain::new("userstore").fill(
- us.users
+ registry: registry
+ .all()
.iter()
- .map(|(name, user)| {
+ .map(|(k, v)| {
(
- name.clone(),
- ::Payload::Text(user.encode().unwrap().to_base64()),
+ 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<UserStore> 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 db2b8e9..4b19180 100644
--- a/lockchain-files/examples/create.rs
+++ b/lockchain-files/examples/create.rs
@@ -13,20 +13,22 @@ fn main() {
let name = env::args().nth(2).unwrap();
let mut vault: DataVault<EncryptedBody> = DataVault::new(&name, &path);
- let mut store = match vault.meta_pull_domain("userstore") {
- Some(m) => m.clone().into(),
+ let mut store = match (
+ vault.meta_pull_domain("userstore"),
+ vault.meta_pull_domain("registry"),
+ ) {
+ (Some(users), Some(registry)) => (users.clone(), registry.clone()).into(),
_ => UserStore::default(),
};
/* Some users of our vault have the same password :S */
store.add(User::register("alice", "password"));
- store.add(User::register("bob", "password"));
- store.add(User::register("carol", "password"));
- store.add(User::register("darius", "password"));
- store.add(User::register("elena", "password"));
- store.add(User::register("farah", "password"));
+ let token = store.get_token(vec!());
- vault.meta_push_domain(store.into());
+ let (users, registry) = store.into();
+
+ vault.meta_push_domain(users);
+ vault.meta_push_domain(registry);
vault.sync();
} else {
eprintln!("Usage: create <path> <name> [FLAGS] (there are no flags)")
diff --git a/lockchain-files/src/lib.rs b/lockchain-files/src/lib.rs
index cdbfecb..24f212e 100644
--- a/lockchain-files/src/lib.rs
+++ b/lockchain-files/src/lib.rs
@@ -123,7 +123,7 @@ impl<T: Body> Vault<T> for DataVault<T> {
}
}
- fn meta_pull_domain(&mut self, domain: &str) -> Option<&MetaDomain> {
+ fn meta_pull_domain(&self, domain: &str) -> Option<&MetaDomain> {
self.metadata.get(domain)
}