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>,
mut res: Results<permissions_results::Owned>
) -> 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::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<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,
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<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();
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<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,
let pdb = PermissionsDB::new(log, roledb, permdb, userdb);
Ok(Permissions::new(pdb, env))
}

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>
( &mut self
, txn: &T
, pp: &access::PermissionsProvider
, pp: &access::PermissionsDB
, who: access::UserIdentifier
) -> 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();
flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true);
let machdb = env.create_db(Some("machines"), flags)?;

View File

@ -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");