Start Database restructure

This commit is contained in:
Gregor Reitzenstein 2020-10-23 16:35:10 +02:00
parent f997c93c23
commit c25983d48c
5 changed files with 84 additions and 58 deletions

View File

@ -37,7 +37,7 @@ impl connection_capnp::bootstrap::Server for Connection {
_: Params<permissions_params::Owned>, _: Params<permissions_params::Owned>,
mut res: Results<permissions_results::Owned> mut res: Results<permissions_results::Owned>
) -> Promise<(), capnp::Error> { ) -> Promise<(), capnp::Error> {
if let Some(user) = self.user { if self.user.is_some() {
} }

View File

@ -8,12 +8,13 @@ use std::convert::TryInto;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
use std::sync::Arc;
use flexbuffers; use flexbuffers;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use slog::Logger; use slog::Logger;
use lmdb::{Transaction, RwTransaction, Cursor}; use lmdb::{Environment, Transaction, RwTransaction, Cursor};
use crate::config::Settings; use crate::config::Settings;
use crate::error::Result; use crate::error::Result;
@ -23,16 +24,78 @@ pub type UserIdentifier = u64;
pub type RoleIdentifier = u64; pub type RoleIdentifier = u64;
pub type PermIdentifier = u64; pub type PermIdentifier = u64;
pub struct PermissionsProvider { #[derive(Clone, Debug)]
pub struct Permissions {
pub inner: PermissionsDB,
env: Arc<Environment>,
}
impl Permissions {
pub fn new(inner: PermissionsDB, env: Arc<Environment>) -> Permissions {
Permissions { inner, env }
}
pub fn check(&self, userID: UserIdentifier, permID: PermIdentifier) -> Result<bool> {
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<RoleIdentifier>
}
/// 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<RoleIdentifier>,
permissions: Vec<PermIdentifier>,
}
/// 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, log: Logger,
roledb: lmdb::Database, roledb: lmdb::Database,
permdb: lmdb::Database, permdb: lmdb::Database,
userdb: lmdb::Database, userdb: lmdb::Database,
} }
impl PermissionsProvider { impl PermissionsDB {
pub fn new(log: Logger, roledb: lmdb::Database, permdb: lmdb::Database, userdb: lmdb::Database) -> Self { 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 /// 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 /// Initialize the access db by loading all the lmdb databases
pub fn init(log: Logger, config: &Settings, env: &lmdb::Environment) -> std::result::Result<PermissionsProvider, crate::error::Error> { pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>) -> std::result::Result<Permissions, crate::error::Error> {
let mut flags = lmdb::DatabaseFlags::empty(); let mut flags = lmdb::DatabaseFlags::empty();
flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true); flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true);
let roledb = env.create_db(Some("role"), flags)?; 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)?; let userdb = env.create_db(Some("user"), flags)?;
debug!(&log, "Opened access database '{}' successfully.", "user"); debug!(&log, "Opened access database '{}' successfully.", "user");
info!(&log, "Opened all access databases"); info!(&log, "Opened all access databases");
return Ok(PermissionsProvider::new(log, roledb, permdb, userdb));
} let pdb = PermissionsDB::new(log, roledb, permdb, userdb);
/// A Person, from the Authorization perspective Ok(Permissions::new(pdb, env))
#[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<RoleIdentifier>
}
/// 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<RoleIdentifier>,
permissions: Vec<PermIdentifier>,
}
/// 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,
} }

1
src/db/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod access;

View File

@ -142,7 +142,7 @@ impl Machine {
pub fn request_use<T: Transaction> pub fn request_use<T: Transaction>
( &mut self ( &mut self
, txn: &T , txn: &T
, pp: &access::PermissionsProvider , pp: &access::PermissionsDB
, who: access::UserIdentifier , who: access::UserIdentifier
) -> Result<bool> ) -> Result<bool>
{ {
@ -256,7 +256,7 @@ impl MachinesProvider {
} }
} }
pub fn init(log: Logger, config: &Settings, env: &lmdb::Environment) -> Result<MachinesProvider> { pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>) -> Result<MachinesProvider> {
let mut flags = lmdb::DatabaseFlags::empty(); let mut flags = lmdb::DatabaseFlags::empty();
flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true); flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true);
let machdb = env.create_db(Some("machines"), flags)?; let machdb = env.create_db(Some("machines"), flags)?;

View File

@ -8,7 +8,6 @@ extern crate capnp_rpc;
extern crate async_trait; extern crate async_trait;
mod auth; mod auth;
mod access;
mod modules; mod modules;
mod log; mod log;
mod api; mod api;
@ -19,6 +18,9 @@ mod connection;
mod registries; mod registries;
mod network; mod network;
mod schema; mod schema;
mod db;
use db::access;
use clap::{App, Arg}; use clap::{App, Arg};
@ -143,8 +145,9 @@ fn main() -> Result<(), Error> {
// Start loading the machine database, authentication system and permission system // 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 // All of those get a custom logger so the source of a log message can be better traced and
// filtered // filtered
let mdb = machine::init(log.new(o!("system" => "machines")), &config, &env); let env = Arc::new(env);
let pdb = access::init(log.new(o!("system" => "permissions")), &config, &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()); 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 // 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 mut txn = env.begin_rw_txn()?;
let path = path.to_path_buf(); 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)?; mdb?.load_db(&mut txn, path)?;
txn.commit(); txn.commit();
} else { } else {
@ -177,7 +180,7 @@ fn main() -> Result<(), Error> {
let txn = env.begin_ro_txn()?; let txn = env.begin_ro_txn()?;
let path = path.to_path_buf(); let path = path.to_path_buf();
pdb?.dump_db(&txn, path.clone())?; pdb?.inner.dump_db(&txn, path.clone())?;
mdb?.dump_db(&txn, path)?; mdb?.dump_db(&txn, path)?;
} else { } else {
error!(log, "You must provide a directory path to dump into"); error!(log, "You must provide a directory path to dump into");