aboutsummaryrefslogtreecommitdiff
path: root/lockchain-core/src/users
diff options
context:
space:
mode:
Diffstat (limited to 'lockchain-core/src/users')
-rw-r--r--lockchain-core/src/users/keystore.rs5
-rw-r--r--lockchain-core/src/users/mod.rs70
-rw-r--r--lockchain-core/src/users/rights.rs7
-rw-r--r--lockchain-core/src/users/secrets.rs2
-rw-r--r--lockchain-core/src/users/store.rs39
-rw-r--r--lockchain-core/src/users/user.rs80
-rw-r--r--lockchain-core/src/users/userstore.rs54
7 files changed, 154 insertions, 103 deletions
diff --git a/lockchain-core/src/users/keystore.rs b/lockchain-core/src/users/keystore.rs
index 71d7be2..7da77ec 100644
--- a/lockchain-core/src/users/keystore.rs
+++ b/lockchain-core/src/users/keystore.rs
@@ -5,12 +5,17 @@
//! - 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<String, Key>,
diff --git a/lockchain-core/src/users/mod.rs b/lockchain-core/src/users/mod.rs
index e9205d1..bad4256 100644
--- a/lockchain-core/src/users/mod.rs
+++ b/lockchain-core/src/users/mod.rs
@@ -12,18 +12,21 @@
//!
//! `User` is also a serialisable struct which contains important
//! data to load and store them into a metadata store.
+#![allow(deprecated)]
mod auth;
+mod user;
mod rights;
mod tokens;
mod keystore;
-mod store;
mod secrets;
+mod userstore;
pub use self::auth::pam_authenticate;
pub use self::keystore::KeyStore;
pub use self::tokens::Token;
+pub use self::user::User;
pub use errors::AuthError;
pub use self::rights::{Access, Role};
@@ -35,69 +38,6 @@ use {
traits::{AutoEncoder, Base64AutoEncoder},
};
-/// 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, Clone)]
-pub struct User {
- name: String,
- pw_hash: String,
- rights: HashMap<Access, Role>,
- token: Option<String>,
-}
-
-impl User {
- /// Register a new user with a name and password
- pub fn register(name: &str, pw: &str) -> Self {
- Self {
- name: name.into(),
- pw_hash: encoding::base64_encode(&hashing::blake2(pw, name).to_vec()),
- rights: HashMap::new(),
- token: None,
- }
- }
- /// 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())
- }
- /// Provides a hook to use second-factor authentication to authorise
- ///
- /// This is meant to be used with an external Yubikey
- pub fn second_auth_verify(&mut self) -> bool {
- unimplemented!()
- }
- /// Generate a token unique to this user (or return the existing one)
- pub fn token(&mut self) -> String {
- if self.token.is_none() {
- self.token = Some(encoding::base64_encode(&random::bytes(256)));
- }
-
- self.token.as_ref().unwrap().clone()
- }
- /// Verify that a user is allowed access to a piece of data
- ///
- /// `None` means "no access of any kind"
- pub fn has_access(&self, item: Access) -> Option<Role> {
- self.rights.get(&item).map(|i| i.clone())
- }
- /// Modify access to an item for a role or create a new access entry
- pub fn give_access(&mut self, item: Access, role: Role) {
- self.rights.insert(item, role);
- }
-}
-
-impl AutoEncoder for User {}
-
/// A utility structure that manages users and can be derived
/// from/into a metadata object. By default this process uses
/// base64 encoding.
@@ -106,6 +46,8 @@ impl AutoEncoder for User {}
/// 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
diff --git a/lockchain-core/src/users/rights.rs b/lockchain-core/src/users/rights.rs
index 4404253..b9ea6cd 100644
--- a/lockchain-core/src/users/rights.rs
+++ b/lockchain-core/src/users/rights.rs
@@ -1,8 +1,12 @@
+//! Permission and access system for lockchain
+
use traits::AutoEncoder;
/// Specifies access to a resource
#[derive(Hash, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum Access {
+ /// A key that is only used to re-encrypt sub-keys
+ Root,
/// Allows access to vault metadata & index files
Vault(Role),
/// Allows access to a record resource inside a vault
@@ -14,8 +18,11 @@ impl AutoEncoder for Access {}
/// Specifies the capabilities of a user
#[derive(Hash, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum Role {
+ /// Only has read access
Reader,
+ /// Can edit any field in a record
Editor,
+ /// Can modify base structure, squash and delete records
Admin,
}
diff --git a/lockchain-core/src/users/secrets.rs b/lockchain-core/src/users/secrets.rs
index 8210a09..2b4d45a 100644
--- a/lockchain-core/src/users/secrets.rs
+++ b/lockchain-core/src/users/secrets.rs
@@ -1,3 +1,5 @@
+//! A secrets type module that wraps around some user content with metadata
+
use traits::AutoEncoder;
/// Specifies the type of secret that's used to derive a vault user secret
diff --git a/lockchain-core/src/users/store.rs b/lockchain-core/src/users/store.rs
deleted file mode 100644
index d400668..0000000
--- a/lockchain-core/src/users/store.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-use super::rights::Access;
-use super::secrets::SecretType;
-use crypto::Key;
-use std::collections::HashMap;
-
-/// A thin user keystore
-///
-/// It's implementation can manage multiple keys per user, of various
-/// types and constrained for limited access rights.
-pub struct KeyStore {
- store: HashMap<String, StoreUser>,
-}
-
-struct StoreUser {
- name: String,
- keys: HashMap<Access, Key>,
-}
-
-impl KeyStore {
- /// Create a new, empty keystore
- ///
- /// This is most likely *not* what you want. Instead, transform
- /// a `MetaData` object into a keystore.
- pub fn new() -> Self {
- Self {
- store: HashMap::new(),
- }
- }
-
- pub fn add_user(&mut self) {}
-
- pub fn rm_user(&mut self) {}
-
- pub fn add_key(&mut self, user: String, k: Key, access: Access) {}
-
- pub fn get_key(&self, user: String, access: Access) -> &Key {
- unimplemented!()
- }
-}
diff --git a/lockchain-core/src/users/user.rs b/lockchain-core/src/users/user.rs
new file mode 100644
index 0000000..1f7c9a5
--- /dev/null
+++ b/lockchain-core/src/users/user.rs
@@ -0,0 +1,80 @@
+//! User representation module
+
+use super::rights::{Access, Role};
+use crypto::{encoding, hashing, random};
+use std::collections::HashMap;
+use traits::AutoEncoder;
+
+/// 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 layers.
+/// 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 to 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.
+///
+/// A user can be stored in a `UserStore`,
+/// along-side authorised keys
+#[derive(Serialize, Deserialize, Clone)]
+pub struct User {
+ #[doc(hidden)]
+ pub name: String,
+ #[doc(hidden)]
+ pub pw_hash: String,
+ #[doc(hidden)]
+ pub rights: HashMap<Access, Role>,
+ #[doc(hidden)]
+ pub token: Option<String>,
+}
+
+impl User {
+ /// Register a new user with a name and password
+ pub fn register(name: &str, pw: &str) -> Self {
+ Self {
+ name: name.into(),
+ pw_hash: encoding::base64_encode(&hashing::blake2(pw, name).to_vec()),
+ rights: HashMap::new(),
+ token: None,
+ }
+ }
+ /// 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())
+ }
+ /// Provides a hook to use second-factor authentication to authorise
+ ///
+ /// This is meant to be used with an external Yubikey
+ pub fn second_auth_verify(&mut self) -> bool {
+ unimplemented!()
+ }
+ /// Generate a token unique to this user (or return the existing one)
+ pub fn token(&mut self) -> String {
+ if self.token.is_none() {
+ self.token = Some(encoding::base64_encode(&random::bytes(256)));
+ }
+
+ self.token.as_ref().unwrap().clone()
+ }
+ /// Verify that a user is allowed access to a piece of data
+ ///
+ /// `None` means "no access of any kind"
+ pub fn has_access(&self, item: Access) -> Option<Role> {
+ self.rights.get(&item).map(|i| i.clone())
+ }
+ /// Modify access to an item for a role or create a new access entry
+ pub fn give_access(&mut self, item: Access, role: Role) {
+ self.rights.insert(item, role);
+ }
+}
+
+impl AutoEncoder for User {}
diff --git a/lockchain-core/src/users/userstore.rs b/lockchain-core/src/users/userstore.rs
new file mode 100644
index 0000000..60fee0b
--- /dev/null
+++ b/lockchain-core/src/users/userstore.rs
@@ -0,0 +1,54 @@
+use super::rights::Access;
+use super::secrets::SecretType;
+use crypto::Key;
+use std::collections::HashMap;
+
+/// A thin user keystore
+///
+/// It's implementation can manage multiple keys per user, of various
+/// types and constrained for limited access rights.
+pub struct KeyStore {
+ store: HashMap<String, StoreUser>,
+}
+
+struct StoreUser {
+ name: String,
+ keys: HashMap<Access, Key>,
+}
+
+impl KeyStore {
+ /// Create a new, empty keystore
+ ///
+ /// This is most likely *not* what you want. Instead, transform
+ /// a `MetaData` object into a keystore.
+ pub fn new() -> Self {
+ Self {
+ store: HashMap::new(),
+ }
+ }
+ /// Adds a new user to the store, with a root-key
+ pub fn add_user(&mut self, name: String, key: Key) {
+ let mut user = StoreUser {
+ name: name.clone(),
+ keys: HashMap::new(),
+ };
+ user.keys.insert(Access::Root, key);
+ self.store.insert(name, user);
+ }
+ /// Delete a user from this store
+ pub fn del_user(&mut self, name: &str) {
+ self.store.remove(name);
+ }
+ /// Add a key to an existing user
+ pub fn add_key(&mut self, user: String, k: Key, access: Access) {
+ if !self.store.contains_key(&user) {
+ return;
+ }
+
+ self.store.get_mut(&user).unwrap().keys.insert(access, k);
+ }
+
+ pub fn get_key(&self, user: String, access: Access) -> Option<&Key> {
+ self.store.get(&user).map_or(None, |u| u.keys.get(&access))
+ }
+}