diff --git a/src/access.rs b/src/access.rs index 52da4da..1e721de 100644 --- a/src/access.rs +++ b/src/access.rs @@ -17,6 +17,50 @@ impl PermissionsProvider { } /// This line documents init -pub async fn init(log: Logger, config: &Config) -> std::result::Result> { +pub fn init(log: Logger, config: &Config, env: &lmdb::Environment) -> std::result::Result { 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 +} + +/// 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, + 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. +struct Permission { + name: String, +} diff --git a/src/config.rs b/src/config.rs index dccc9c4..467c879 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ pub fn read(path: &Path) -> Result { #[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(), diff --git a/src/error.rs b/src/error.rs index 2ffaa48..75e0d17 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,6 +12,7 @@ pub enum Error { IO(io::Error), Boxed(Box), Capnp(capnp::Error), + LMDB(lmdb::Error), } impl fmt::Display for Error { @@ -75,4 +76,10 @@ impl From for Error { } } +impl From for Error { + fn from(e: lmdb::Error) -> Error { + Error::LMDB(e) + } +} + pub type Result = std::result::Result; diff --git a/src/main.rs b/src/main.rs index 4d65e96..a60888c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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