From e1e9c73476ba2792c3582ee7ecd14d0b39c3eef4 Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Tue, 10 Jul 2018 20:47:13 +0200 Subject: Adding an example of how to register a user and adding new metadata vault endpoints functions --- lockchain-core/examples/user_registry.rs | 33 +++++++++++++ lockchain-core/src/meta.rs | 2 +- lockchain-core/src/traits.rs | 2 + lockchain-core/src/users/mod.rs | 19 ++++++-- lockchain-files/examples/create.rs | 23 ++++++--- lockchain-files/examples/register_user.rs | 0 lockchain-files/src/lib.rs | 4 ++ lockchain-http/src/handlers.rs | 81 ++++++++++++++++++++++++++++++- lockchain-http/src/lib.rs | 17 +++---- 9 files changed, 158 insertions(+), 23 deletions(-) create mode 100644 lockchain-core/examples/user_registry.rs create mode 100644 lockchain-files/examples/register_user.rs diff --git a/lockchain-core/examples/user_registry.rs b/lockchain-core/examples/user_registry.rs new file mode 100644 index 0000000..8bb5c69 --- /dev/null +++ b/lockchain-core/examples/user_registry.rs @@ -0,0 +1,33 @@ +//! User registry in a vault is done via the metadata store +//! +//! In addition to that the `lockchain-core ` provides some simple +//! utilities to manage Users and UserStore objects, mapping them +//! onto metadata stores. +//! +//! In this example we will define a function that takes a generic +//! Vault implementation backend (because lockchain-core doesn't +//! provide a concrete way of doing this) and registering a user +//! into it. +//! +//! Please note you can't actually _run_ this code example, because +//! no concrete type can be known. The exact same example (with a type) +//! can however be found in `lockchain-files` + + +extern crate lockchain_core as lockchain; +use lockchain::users::{User, UserStore, Access, Role}; +use lockchain::traits::Vault; +use lockchain::EncryptedBody; + +fn main() { + // register(your_vault_here, "spacekookie", "password"); +} + +/// This function takes a generic Vault which MUST implement +/// the EncryptedBody backend. This would normally be the case +/// for the `DataVault` provided by `lockchain-files` +fn register>(vault: &mut V, username: &str, password: &str) { + let me = User::register(username, password); +} + + diff --git a/lockchain-core/src/meta.rs b/lockchain-core/src/meta.rs index cf3eb36..317e821 100644 --- a/lockchain-core/src/meta.rs +++ b/lockchain-core/src/meta.rs @@ -32,7 +32,7 @@ pub struct VaultMetadata { /// /// It implements a series of traits which means it's possible to easily /// interact with to store data. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] pub struct MetaDomain { /// The name of this meta domain name: String, diff --git a/lockchain-core/src/traits.rs b/lockchain-core/src/traits.rs index 4e66d8f..088ee84 100644 --- a/lockchain-core/src/traits.rs +++ b/lockchain-core/src/traits.rs @@ -148,6 +148,8 @@ where fn meta_set(&mut self, domain: &str, name: &str, data: Payload) -> Option<()>; /// Get the value of a (unique) field inside a domain fn meta_get(&mut self, domain: &str, name: &str) -> Option; + /// Check if a metadomain exists, regardless of data or depth + fn meta_exists(&self, domain: &str) -> bool; } /// Auto-implement this trait to serialise types to json diff --git a/lockchain-core/src/users/mod.rs b/lockchain-core/src/users/mod.rs index a5cf79e..630e2a8 100644 --- a/lockchain-core/src/users/mod.rs +++ b/lockchain-core/src/users/mod.rs @@ -21,7 +21,10 @@ pub use errors::AuthError; use crypto::{encoding, hashing, random}; use std::collections::HashMap; -use {meta::MetaDomain, traits::AutoEncoder}; +use { + meta::MetaDomain, + traits::{AutoEncoder, Base64AutoEncoder}, +}; /// Specifies access to a resource #[derive(Hash, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -115,6 +118,11 @@ impl UserStore { 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 { @@ -141,7 +149,7 @@ impl From for UserStore { ( k.clone(), match v { - ::Payload::Text(s) => User::decode(s).unwrap(), + ::Payload::Text(s) => User::decode(&String::from_base64(s)).unwrap(), _ => unreachable!(), }, ) @@ -156,7 +164,12 @@ impl From for MetaDomain { MetaDomain::new("userstore").fill( us.users .iter() - .map(|(name, user)| (name.clone(), ::Payload::Text(user.encode().unwrap()))) + .map(|(name, user)| { + ( + name.clone(), + ::Payload::Text(user.encode().unwrap().to_base64()), + ) + }) .collect(), ) } diff --git a/lockchain-files/examples/create.rs b/lockchain-files/examples/create.rs index f6ecb8e..db2b8e9 100644 --- a/lockchain-files/examples/create.rs +++ b/lockchain-files/examples/create.rs @@ -3,6 +3,7 @@ extern crate lockchain_files as files; use files::DataVault; use lcc::traits::Vault; +use lcc::users::{User, UserStore}; use lcc::{EncryptedBody, Payload, Record}; use std::env; @@ -12,14 +13,20 @@ fn main() { let name = env::args().nth(2).unwrap(); let mut vault: DataVault = DataVault::new(&name, &path); - vault.meta_add_domain("userstore").unwrap(); - vault - .meta_set( - "userstore", - "spacekookie", - Payload::Text("".into()), - ) - .unwrap(); + let mut store = match vault.meta_pull_domain("userstore") { + Some(m) => m.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")); + + vault.meta_push_domain(store.into()); vault.sync(); } else { eprintln!("Usage: create [FLAGS] (there are no flags)") diff --git a/lockchain-files/examples/register_user.rs b/lockchain-files/examples/register_user.rs new file mode 100644 index 0000000..e69de29 diff --git a/lockchain-files/src/lib.rs b/lockchain-files/src/lib.rs index b94c5b1..cdbfecb 100644 --- a/lockchain-files/src/lib.rs +++ b/lockchain-files/src/lib.rs @@ -141,4 +141,8 @@ impl Vault for DataVault { fn meta_get(&mut self, domain: &str, name: &str) -> Option { Some(self.metadata.get(domain)?.get_field(name)?.clone()) } + + fn meta_exists(&self, domain: &str) -> bool { + self.metadata.contains_key(domain) + } } diff --git a/lockchain-http/src/handlers.rs b/lockchain-http/src/handlers.rs index f68f158..8ce44da 100644 --- a/lockchain-http/src/handlers.rs +++ b/lockchain-http/src/handlers.rs @@ -165,8 +165,85 @@ where }) } +pub fn get_all_metadata(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + +pub fn put_metadata(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + +pub fn get_metadata(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + +pub fn update_metadata(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + +pub fn vault_register(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + +pub fn vault_login(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + +pub fn vault_logout(_req: HttpRequestState>) -> impl Responder +where + B: Body, + V: Vault, +{ + Json(OperationFailed { + explain: "Not implemented".into(), + error: LockError::Unknown, + }) +} + /// PUT /authenticate -pub fn authenticate( +pub fn login( (item, req): (Json, HttpRequestState>), ) -> impl Responder where @@ -196,7 +273,7 @@ where } /// PUT /de-authenticate -pub fn deauthenticate( +pub fn logout( (item, req): (Json, HttpRequestState>), ) -> impl Responder where diff --git a/lockchain-http/src/lib.rs b/lockchain-http/src/lib.rs index 3adb503..961ad21 100644 --- a/lockchain-http/src/lib.rs +++ b/lockchain-http/src/lib.rs @@ -75,10 +75,8 @@ where .resource("/vaults", |r| { // Get existing vaults r.method(http::Method::GET).with(handlers::get_vaults); - // Create new vault (if authorised) r.method(http::Method::PUT).with(handlers::create_vault); - // Delete entire vault (if authorised) r.method(http::Method::DELETE).with(handlers::delete_vault); }) @@ -115,31 +113,32 @@ where }) .resource("/vaults/{vaultid}/metadata/{metaid}", |r| { // Get a specific metadata field - r.method(http::Method::GET).with(handlers::get_all_records); + r.method(http::Method::GET).with(handlers::get_metadata); // Update a specific metadata field - r.method(http::Method::POST).with(handlers::get_all_records); + r.method(http::Method::POST).with(handlers::update_metadata); }) .resource("/vaults/{vaultid}/register", |r| { // Register a new user in a vault (with a registry token) - r.method(http::Method::POST).with(handlers::deauthenticate) + r.method(http::Method::POST).with(handlers::vault_register) }) .resource("/vaults/{vaultid}/login", |r| { // Login as a user for this vault - r.method(http::Method::POST).with(handlers::authenticate) + r.method(http::Method::POST).with(handlers::vault_login) }) .resource("/vaults/{vaultid}/logout", |r| { // Logout, closing an existing session - r.method(http::Method::POST).with(handlers::deauthenticate) + r.method(http::Method::POST).with(handlers::vault_logout) }) .resource("/users/login", |r| { // Request a new auth token - r.method(http::Method::POST).with(handlers::authenticate) + r.method(http::Method::POST).with(handlers::login) }) .resource("/users/logout", |r| { // Hand-in active auth token - r.method(http::Method::POST).with(handlers::deauthenticate) + r.method(http::Method::POST).with(handlers::logout) }) .resource("/api", |r| { + // Get information about this API endpoint r.method(http::Method::GET).with(handlers::api_data); }), ] -- cgit v1.2.3