From c25983d48cfdb58b9d52e6580cca5339ddd7c55b Mon Sep 17 00:00:00 2001 From: Gregor Reitzenstein Date: Fri, 23 Oct 2020 16:35:10 +0200 Subject: [PATCH] Start Database restructure --- src/connection.rs | 2 +- src/{ => db}/access.rs | 122 ++++++++++++++++++++++++----------------- src/db/mod.rs | 1 + src/machine.rs | 4 +- src/main.rs | 13 +++-- 5 files changed, 84 insertions(+), 58 deletions(-) rename src/{ => db}/access.rs (95%) create mode 100644 src/db/mod.rs diff --git a/src/connection.rs b/src/connection.rs index c28fa2c..4d018da 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -37,7 +37,7 @@ impl connection_capnp::bootstrap::Server for Connection { _: Params, mut res: Results ) -> Promise<(), capnp::Error> { - if let Some(user) = self.user { + if self.user.is_some() { } diff --git a/src/access.rs b/src/db/access.rs similarity index 95% rename from src/access.rs rename to src/db/access.rs index 8c29d31..3f8d6a1 100644 --- a/src/access.rs +++ b/src/db/access.rs @@ -8,12 +8,13 @@ use std::convert::TryInto; use std::path::{Path, PathBuf}; use std::fs; use std::io::Write; +use std::sync::Arc; use flexbuffers; use serde::{Serialize, Deserialize}; use slog::Logger; -use lmdb::{Transaction, RwTransaction, Cursor}; +use lmdb::{Environment, Transaction, RwTransaction, Cursor}; use crate::config::Settings; use crate::error::Result; @@ -23,16 +24,78 @@ pub type UserIdentifier = u64; pub type RoleIdentifier = u64; pub type PermIdentifier = u64; -pub struct PermissionsProvider { +#[derive(Clone, Debug)] +pub struct Permissions { + pub inner: PermissionsDB, + env: Arc, +} + +impl Permissions { + pub fn new(inner: PermissionsDB, env: Arc) -> Permissions { + Permissions { inner, env } + } + + pub fn check(&self, userID: UserIdentifier, permID: PermIdentifier) -> Result { + let txn = self.env.begin_ro_txn()?; + self.inner.check(&txn, userID, permID) + } +} + +/// A Person, from the Authorization perspective +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +struct User { + name: String, + + /// A Person has N ≥ 0 roles. + /// Persons are only ever given roles, not permissions directly + roles: Vec +} + +/// A "Role" from the Authorization perspective +/// +/// You can think of a role as a bundle of permissions relating to other roles. In most cases a +/// role represents a real-world education or apprenticeship, which gives a person the education +/// necessary to use a machine safely. +/// Roles are assigned permissions which in most cases evaluate to granting a person the right to +/// use certain (potentially) dangerous machines. +/// Using this indirection makes administration easier in certain ways; instead of maintaining +/// permissions on users directly the user is given a role after having been educated on the safety +/// of a machine; if later on a similar enough machine is put to use the administrator can just add +/// the permission for that machine to an already existing role instead of manually having to +/// assign to all users. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +struct Role { + name: String, + + /// A Role can have parents, inheriting all permissions + /// + /// This makes situations where different levels of access are required easier: Each higher + /// level of access sets the lower levels of access as parent, inheriting their permission; if + /// you are allowed to manage a machine you are then also allowed to use it and so on + parents: Vec, + permissions: Vec, +} + +/// A Permission from the Authorization perspective +/// +/// Permissions are rather simple flags. A person can have or not have a permission, dictated by +/// its roles and the permissions assigned to those roles. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +struct Perm { + name: String, +} + +#[derive(Clone, Debug)] +pub struct PermissionsDB { log: Logger, roledb: lmdb::Database, permdb: lmdb::Database, userdb: lmdb::Database, } -impl PermissionsProvider { +impl PermissionsDB { pub fn new(log: Logger, roledb: lmdb::Database, permdb: lmdb::Database, userdb: lmdb::Database) -> Self { - Self { log, roledb, permdb, userdb } + PermissionsDB { log, roledb, permdb, userdb } } /// Check if a given user has the given permission @@ -408,7 +471,7 @@ impl PermissionsProvider { } /// Initialize the access db by loading all the lmdb databases -pub fn init(log: Logger, config: &Settings, env: &lmdb::Environment) -> std::result::Result { +pub fn init(log: Logger, config: &Settings, env: Arc) -> std::result::Result { let mut flags = lmdb::DatabaseFlags::empty(); flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true); let roledb = env.create_db(Some("role"), flags)?; @@ -418,49 +481,8 @@ pub fn init(log: Logger, config: &Settings, env: &lmdb::Environment) -> std::res let userdb = env.create_db(Some("user"), flags)?; debug!(&log, "Opened access database '{}' successfully.", "user"); info!(&log, "Opened all access databases"); - return Ok(PermissionsProvider::new(log, roledb, permdb, userdb)); -} - -/// A Person, from the Authorization perspective -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -struct User { - name: String, - - /// A Person has N ≥ 0 roles. - /// Persons are only ever given roles, not permissions directly - roles: Vec -} - -/// A "Role" from the Authorization perspective -/// -/// You can think of a role as a bundle of permissions relating to other roles. In most cases a -/// role represents a real-world education or apprenticeship, which gives a person the education -/// necessary to use a machine safely. -/// Roles are assigned permissions which in most cases evaluate to granting a person the right to -/// use certain (potentially) dangerous machines. -/// Using this indirection makes administration easier in certain ways; instead of maintaining -/// permissions on users directly the user is given a role after having been educated on the safety -/// of a machine; if later on a similar enough machine is put to use the administrator can just add -/// the permission for that machine to an already existing role instead of manually having to -/// assign to all users. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -struct Role { - name: String, - - /// A Role can have parents, inheriting all permissions - /// - /// This makes situations where different levels of access are required easier: Each higher - /// level of access sets the lower levels of access as parent, inheriting their permission; if - /// you are allowed to manage a machine you are then also allowed to use it and so on - parents: Vec, - permissions: Vec, -} - -/// A Permission from the Authorization perspective -/// -/// Permissions are rather simple flags. A person can have or not have a permission, dictated by -/// its roles and the permissions assigned to those roles. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -struct Perm { - name: String, + + let pdb = PermissionsDB::new(log, roledb, permdb, userdb); + + Ok(Permissions::new(pdb, env)) } diff --git a/src/db/mod.rs b/src/db/mod.rs new file mode 100644 index 0000000..3750845 --- /dev/null +++ b/src/db/mod.rs @@ -0,0 +1 @@ +pub mod access; diff --git a/src/machine.rs b/src/machine.rs index 3cd8a62..359e280 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -142,7 +142,7 @@ impl Machine { pub fn request_use ( &mut self , txn: &T - , pp: &access::PermissionsProvider + , pp: &access::PermissionsDB , who: access::UserIdentifier ) -> Result { @@ -256,7 +256,7 @@ impl MachinesProvider { } } -pub fn init(log: Logger, config: &Settings, env: &lmdb::Environment) -> Result { +pub fn init(log: Logger, config: &Settings, env: Arc) -> Result { let mut flags = lmdb::DatabaseFlags::empty(); flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true); let machdb = env.create_db(Some("machines"), flags)?; diff --git a/src/main.rs b/src/main.rs index 58024ef..2fe0bfc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,6 @@ extern crate capnp_rpc; extern crate async_trait; mod auth; -mod access; mod modules; mod log; mod api; @@ -19,6 +18,9 @@ mod connection; mod registries; mod network; mod schema; +mod db; + +use db::access; use clap::{App, Arg}; @@ -143,8 +145,9 @@ fn main() -> Result<(), Error> { // Start loading the machine database, authentication system and permission system // All of those get a custom logger so the source of a log message can be better traced and // filtered - let mdb = machine::init(log.new(o!("system" => "machines")), &config, &env); - let pdb = access::init(log.new(o!("system" => "permissions")), &config, &env); + let env = Arc::new(env); + let mdb = machine::init(log.new(o!("system" => "machines")), &config, env.clone()); + let pdb = access::init(log.new(o!("system" => "permissions")), &config, env.clone()); let authentication_f = auth::init(log.new(o!("system" => "authentication")), config.clone()); // If --load or --dump is given we can stop at this point and load/dump the database and then @@ -159,7 +162,7 @@ fn main() -> Result<(), Error> { let mut txn = env.begin_rw_txn()?; let path = path.to_path_buf(); - pdb?.load_db(&mut txn, path.clone())?; + pdb?.inner.load_db(&mut txn, path.clone())?; mdb?.load_db(&mut txn, path)?; txn.commit(); } else { @@ -177,7 +180,7 @@ fn main() -> Result<(), Error> { let txn = env.begin_ro_txn()?; let path = path.to_path_buf(); - pdb?.dump_db(&txn, path.clone())?; + pdb?.inner.dump_db(&txn, path.clone())?; mdb?.dump_db(&txn, path)?; } else { error!(log, "You must provide a directory path to dump into");