Starts using LMDB

This commit is contained in:
Gregor Reitzenstein 2020-09-10 10:39:46 +02:00
parent 3ac60bacb0
commit 808386d17a
4 changed files with 67 additions and 5 deletions

View File

@ -17,6 +17,50 @@ impl PermissionsProvider {
}
/// This line documents init
pub async fn init(log: Logger, config: &Config) -> std::result::Result<PermissionsProvider, Box<dyn std::error::Error>> {
pub fn init(log: Logger, config: &Config, env: &lmdb::Environment) -> std::result::Result<PermissionsProvider, crate::error::Error> {
return Ok(PermissionsProvider::new(log));
}
type RoleIdentifier = u64;
type PermIdentifier = u64;
/// A Person, from the Authorization perspective
struct Person {
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.
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.
struct Permission {
name: String,
}

View File

@ -19,6 +19,7 @@ pub fn read(path: &Path) -> Result<Config> {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub db: PathBuf,
pub machinedb: PathBuf,
pub passdb: PathBuf,
pub(crate) access: Access,
@ -40,6 +41,7 @@ pub struct Listen {
impl Default for Config {
fn default() -> Self {
Config {
db: PathBuf::from_str("/tmp/bffh.db").unwrap(),
machinedb: PathBuf::from_str("/tmp/machines.db").unwrap(),
access: Access {
model: PathBuf::from_str("/tmp/model.conf").unwrap(),

View File

@ -12,6 +12,7 @@ pub enum Error {
IO(io::Error),
Boxed(Box<dyn std::error::Error>),
Capnp(capnp::Error),
LMDB(lmdb::Error),
}
impl fmt::Display for Error {
@ -75,4 +76,10 @@ impl From<capnp::Error> for Error {
}
}
impl From<lmdb::Error> for Error {
fn from(e: lmdb::Error) -> Error {
Error::LMDB(e)
}
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@ -35,6 +35,8 @@ use std::sync::Arc;
use error::Error;
const LMDB_MAX_DB: u32 = 16;
// Returning a `Result` from `main` allows us to use the `?` shorthand.
// In the case of an Err it will be printed using `fmt::Debug`
fn main() -> Result<(), Error> {
@ -95,11 +97,18 @@ fn main() -> Result<(), Error> {
// asyncronous fashion.
let mut exec = LocalPool::new();
// Initialize the LMDB environment. Since this would usually block untill the mmap() finishes
// we wrap it in smol::unblock which runs this as future in a different thread.
let e_config = config.clone();
let env = lmdb::Environment::new()
.set_max_dbs(LMDB_MAX_DB as libc::c_uint)
.open(&e_config.db)?;
// 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 machinedb_f = machine::init(log.new(o!("system" => "machines")), &config);
let permission_f = access::init(log.new(o!("system" => "permissions")), &config);
let pdb = access::init(log.new(o!("system" => "permissions")), &config, &env);
let authentication_f = auth::init(log.new(o!("system" => "authentication")), config.clone());
// Bind to each address in config.listen.
@ -124,15 +133,15 @@ fn main() -> Result<(), Error> {
}
}).collect();
let (mach, pdb, auth) = exec.run_until(async {
let (mach, auth) = exec.run_until(async {
// Rull all futures to completion in parallel.
// This will block until all three are done starting up.
join!(machinedb_f, permission_f, authentication_f)
join!(machinedb_f, authentication_f)
});
// Error out if any of the subsystems failed to start.
let mach = mach?;
let pdb = pdb.unwrap();
let pdb = pdb?;
let auth = auth?;
// Since the below closures will happen at a much later time we need to make sure all pointers