mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-14 03:07:57 +01:00
Lots of changes for better API stuffs
This commit is contained in:
parent
f8b9874f08
commit
e7bbc7e001
11
src/api.rs
11
src/api.rs
@ -7,6 +7,8 @@ use capnp::capability::{Params, Results, Promise};
|
|||||||
use crate::schema::connection_capnp;
|
use crate::schema::connection_capnp;
|
||||||
use crate::connection::Session;
|
use crate::connection::Session;
|
||||||
|
|
||||||
|
use crate::db::Databases;
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
mod machine;
|
mod machine;
|
||||||
mod machines;
|
mod machines;
|
||||||
@ -14,13 +16,14 @@ mod machines;
|
|||||||
use machines::Machines;
|
use machines::Machines;
|
||||||
|
|
||||||
pub struct Bootstrap {
|
pub struct Bootstrap {
|
||||||
session: Arc<Session>
|
session: Arc<Session>,
|
||||||
|
db: Databases,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bootstrap {
|
impl Bootstrap {
|
||||||
pub fn new(session: Arc<Session>) -> Self {
|
pub fn new(session: Arc<Session>, db: Databases) -> Self {
|
||||||
info!(session.log, "Created Bootstrap");
|
info!(session.log, "Created Bootstrap");
|
||||||
Self { session }
|
Self { session, db }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ impl connection_capnp::bootstrap::Server for Bootstrap {
|
|||||||
) -> Promise<(), capnp::Error> {
|
) -> Promise<(), capnp::Error> {
|
||||||
// TODO actual permission check and stuff
|
// TODO actual permission check and stuff
|
||||||
if self.session.user.is_some() {
|
if self.session.user.is_some() {
|
||||||
let c = capnp_rpc::new_client(Machines::new(self.session.clone()));
|
let c = capnp_rpc::new_client(Machines::new(self.session.clone(), self.db.clone()));
|
||||||
res.get().set_machines(c);
|
res.get().set_machines(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,27 @@
|
|||||||
use crate::schema::api_capnp::machine::*;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
use capnp::Error;
|
use capnp::Error;
|
||||||
|
|
||||||
|
use crate::schema::api_capnp::machine::*;
|
||||||
|
use crate::db::machine::MachineIdentifier;
|
||||||
|
use crate::connection::Session;
|
||||||
|
use crate::db::Databases;
|
||||||
|
|
||||||
struct Machine;
|
#[derive(Clone)]
|
||||||
|
pub struct Machine {
|
||||||
|
session: Arc<Session>,
|
||||||
|
id: MachineIdentifier,
|
||||||
|
db: Databases,
|
||||||
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub fn new() -> Self {
|
pub fn new(session: Arc<Session>, id: MachineIdentifier, db: Databases) -> Self {
|
||||||
Machine
|
Machine { session, id, db }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Read;
|
struct Read(Arc<Machine>);
|
||||||
|
|
||||||
impl read::Server for Read {
|
impl read::Server for Read {
|
||||||
fn info(&mut self,
|
fn info(&mut self,
|
||||||
@ -24,7 +33,7 @@ impl read::Server for Read {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Write;
|
struct Write(Arc<Machine>);
|
||||||
|
|
||||||
impl write::Server for Write {
|
impl write::Server for Write {
|
||||||
fn use_(&mut self,
|
fn use_(&mut self,
|
||||||
@ -36,7 +45,7 @@ impl write::Server for Write {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Manage;
|
struct Manage(Arc<Machine>);
|
||||||
|
|
||||||
impl manage::Server for Manage {
|
impl manage::Server for Manage {
|
||||||
fn ok(&mut self,
|
fn ok(&mut self,
|
||||||
@ -48,7 +57,7 @@ impl manage::Server for Manage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Admin;
|
struct Admin(Arc<Machine>);
|
||||||
|
|
||||||
impl admin::Server for Admin {
|
impl admin::Server for Admin {
|
||||||
fn force_set_state(&mut self,
|
fn force_set_state(&mut self,
|
||||||
|
@ -1,24 +1,30 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use slog::Logger;
|
|
||||||
|
|
||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
use capnp::Error;
|
use capnp::Error;
|
||||||
|
|
||||||
use crate::schema::api_capnp::machines;
|
use crate::schema::api_capnp::machines;
|
||||||
use crate::connection::Session;
|
use crate::connection::Session;
|
||||||
|
|
||||||
|
use crate::db::Databases;
|
||||||
|
use crate::db::machine::uuid_from_api;
|
||||||
|
use crate::db::machine::MachineDB;
|
||||||
|
|
||||||
|
use super::machine::Machine;
|
||||||
|
|
||||||
/// An implementation of the `Machines` API
|
/// An implementation of the `Machines` API
|
||||||
pub struct Machines {
|
pub struct Machines {
|
||||||
/// A reference to the connection — as long as at least one API endpoint is
|
/// A reference to the connection — as long as at least one API endpoint is
|
||||||
/// still alive the session has to be as well.
|
/// still alive the session has to be as well.
|
||||||
session: Arc<Session>,
|
session: Arc<Session>,
|
||||||
|
|
||||||
|
db: Databases,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Machines {
|
impl Machines {
|
||||||
pub fn new(session: Arc<Session>) -> Self {
|
pub fn new(session: Arc<Session>, db: Databases) -> Self {
|
||||||
info!(session.log, "Machines created");
|
info!(session.log, "Machines created");
|
||||||
Self { session }
|
Self { session, db }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,10 +38,25 @@ impl machines::Server for Machines {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_machine(&mut self,
|
fn get_machine(&mut self,
|
||||||
_params: machines::GetMachineParams,
|
params: machines::GetMachineParams,
|
||||||
mut results: machines::GetMachineResults)
|
mut results: machines::GetMachineResults)
|
||||||
-> Promise<(), Error>
|
-> Promise<(), Error>
|
||||||
{
|
{
|
||||||
|
match params.get() {
|
||||||
|
Ok(reader) => {
|
||||||
|
if let Ok(api_id) = reader.get_uuid() {
|
||||||
|
let id = uuid_from_api(api_id);
|
||||||
|
if self.db.machine.exists(id) {
|
||||||
|
// TODO check disclose permission
|
||||||
|
|
||||||
|
let builder = results.get().init_machine();
|
||||||
|
|
||||||
|
let m = Machine::new(self.session.clone(), id, self.db.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
Err(e) => Promise::err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ pub fn read(path: &Path) -> Result<Settings> {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub listens: Box<[Listen]>,
|
pub listens: Box<[Listen]>,
|
||||||
pub shelly: Option<ShellyCfg>
|
pub shelly: Option<ShellyCfg>,
|
||||||
|
pub machines: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -53,6 +54,7 @@ impl Default for Settings {
|
|||||||
shelly: Some(ShellyCfg {
|
shelly: Some(ShellyCfg {
|
||||||
mqtt_url: "127.0.0.1:1883".to_string()
|
mqtt_url: "127.0.0.1:1883".to_string()
|
||||||
}),
|
}),
|
||||||
|
machines: PathBuf::from("/etc/bffh/machines/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@ use capnp_rpc::{twoparty, rpc_twoparty_capnp};
|
|||||||
|
|
||||||
use crate::schema::connection_capnp;
|
use crate::schema::connection_capnp;
|
||||||
|
|
||||||
|
use crate::db::Databases;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
/// Connection context
|
/// Connection context
|
||||||
// TODO this should track over several connections
|
// TODO this should track over several connections
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
@ -54,12 +57,12 @@ async fn handshake(log: &Logger, stream: &mut TcpStream) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_connection(log: Logger, stream: TcpStream) -> Result<()> {
|
pub async fn handle_connection(log: Logger, stream: TcpStream, db: Databases) -> Result<()> {
|
||||||
//handshake(&log, &mut stream).await?;
|
//handshake(&log, &mut stream).await?;
|
||||||
|
|
||||||
info!(log, "New connection from on {:?}", stream);
|
info!(log, "New connection from on {:?}", stream);
|
||||||
let session = Arc::new(Session::new(log));
|
let session = Arc::new(Session::new(log));
|
||||||
let boots = Bootstrap::new(session);
|
let boots = Bootstrap::new(session, db);
|
||||||
let rpc: connection_capnp::bootstrap::Client = capnp_rpc::new_client(boots);
|
let rpc: connection_capnp::bootstrap::Client = capnp_rpc::new_client(boots);
|
||||||
|
|
||||||
let network = twoparty::VatNetwork::new(stream.clone(), stream,
|
let network = twoparty::VatNetwork::new(stream.clone(), stream,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
||||||
/// Access control storage
|
/// Access control storage
|
||||||
///
|
///
|
||||||
/// Stores&Retrieves Permissions and Roles
|
/// Stores&Retrieves Permissions and Roles
|
||||||
@ -12,7 +15,8 @@ pub mod user;
|
|||||||
/// Stores&Retrieves Machines
|
/// Stores&Retrieves Machines
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Databases {
|
pub struct Databases {
|
||||||
pub access: access::internal::Internal,
|
pub access: Arc<access::AccessControl>,
|
||||||
pub machine: machine::internal::Internal,
|
pub machine: Arc<machine::MachineDB>,
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
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 std::sync::Arc;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::convert::{TryFrom, Into};
|
use std::convert::{TryFrom, Into};
|
||||||
|
|
||||||
@ -32,6 +32,34 @@ pub mod internal;
|
|||||||
use crate::db::user::User;
|
use crate::db::user::User;
|
||||||
pub use internal::init;
|
pub use internal::init;
|
||||||
|
|
||||||
|
pub struct AccessControl {
|
||||||
|
sources: HashMap<String, Box<dyn RoleDB>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccessControl {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
sources: HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds an access control source. If a source with the same name already existed it is
|
||||||
|
/// replaced.
|
||||||
|
pub fn add_source_unchecked(&mut self, name: String, source: Box<dyn RoleDB>) {
|
||||||
|
self.sources.insert(name, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check<P: AsRef<Permission>>(&self, user: &User, perm: &P) -> Result<bool> {
|
||||||
|
for v in self.sources.values() {
|
||||||
|
if v.check(user, perm.as_ref())? {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait RoleDB {
|
pub trait RoleDB {
|
||||||
fn get_role(&self, roleID: &RoleIdentifier) -> Result<Option<Role>>;
|
fn get_role(&self, roleID: &RoleIdentifier) -> Result<Option<Role>>;
|
||||||
|
|
||||||
@ -39,7 +67,7 @@ pub trait RoleDB {
|
|||||||
///
|
///
|
||||||
/// Default implementation which adapter may overwrite with more efficient specialized
|
/// Default implementation which adapter may overwrite with more efficient specialized
|
||||||
/// implementations.
|
/// implementations.
|
||||||
fn check<P: AsRef<Permission>>(&self, user: &User, perm: &P) -> Result<bool> {
|
fn check(&self, user: &User, perm: &Permission) -> Result<bool> {
|
||||||
self.check_roles(&user.roles, perm)
|
self.check_roles(&user.roles, perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +76,7 @@ pub trait RoleDB {
|
|||||||
///
|
///
|
||||||
/// A Default implementation exists which adapter may overwrite with more efficient specialized
|
/// A Default implementation exists which adapter may overwrite with more efficient specialized
|
||||||
/// implementations.
|
/// implementations.
|
||||||
fn check_roles<P: AsRef<Permission>>(&self, roles: &[RoleIdentifier], perm: &P) -> Result<bool> {
|
fn check_roles(&self, roles: &[RoleIdentifier], perm: &Permission) -> Result<bool> {
|
||||||
// Tally all roles. Makes dependent roles easier
|
// Tally all roles. Makes dependent roles easier
|
||||||
let mut roleset = HashSet::new();
|
let mut roleset = HashSet::new();
|
||||||
for roleID in roles {
|
for roleID in roles {
|
||||||
@ -58,7 +86,7 @@ pub trait RoleDB {
|
|||||||
// Iter all unique role->permissions we've found and early return on match.
|
// Iter all unique role->permissions we've found and early return on match.
|
||||||
for role in roleset.iter() {
|
for role in roleset.iter() {
|
||||||
for perm_rule in role.permissions.iter() {
|
for perm_rule in role.permissions.iter() {
|
||||||
if perm_rule.match_perm(perm) {
|
if perm_rule.match_perm(&perm) {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,9 +150,9 @@ impl Internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RoleDB for Internal {
|
impl RoleDB for Internal {
|
||||||
fn check<P: AsRef<Permission>>(&self, user: &User, perm: &P) -> Result<bool> {
|
fn check(&self, user: &User, perm: &Permission) -> Result<bool> {
|
||||||
let txn = self.env.begin_ro_txn()?;
|
let txn = self.env.begin_ro_txn()?;
|
||||||
self._check(&txn, user, perm)
|
self._check(&txn, user, &perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_role(&self, roleID: &RoleIdentifier) -> Result<Option<Role>> {
|
fn get_role(&self, roleID: &RoleIdentifier) -> Result<Option<Role>> {
|
||||||
|
@ -32,6 +32,8 @@ use futures_signals::signal::*;
|
|||||||
use crate::registries::StatusSignal;
|
use crate::registries::StatusSignal;
|
||||||
use crate::db::user::User;
|
use crate::db::user::User;
|
||||||
|
|
||||||
|
use crate::machine::MachineDescription;
|
||||||
|
|
||||||
pub mod internal;
|
pub mod internal;
|
||||||
use internal::Internal;
|
use internal::Internal;
|
||||||
|
|
||||||
@ -54,13 +56,13 @@ pub enum Status {
|
|||||||
Reserved(UserIdentifier),
|
Reserved(UserIdentifier),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uuid_from_api(uuid: crate::schema::api_capnp::u_u_i_d::Reader) -> Uuid {
|
pub fn uuid_from_api(uuid: crate::schema::api_capnp::u_u_i_d::Reader) -> Uuid {
|
||||||
let uuid0 = uuid.get_uuid0() as u128;
|
let uuid0 = uuid.get_uuid0() as u128;
|
||||||
let uuid1 = uuid.get_uuid1() as u128;
|
let uuid1 = uuid.get_uuid1() as u128;
|
||||||
let num: u128 = (uuid1 << 64) + uuid0;
|
let num: u128 = (uuid1 << 64) + uuid0;
|
||||||
Uuid::from_u128(num)
|
Uuid::from_u128(num)
|
||||||
}
|
}
|
||||||
fn api_from_uuid(uuid: Uuid, mut wr: crate::schema::api_capnp::u_u_i_d::Builder) {
|
pub fn api_from_uuid(uuid: Uuid, mut wr: crate::schema::api_capnp::u_u_i_d::Builder) {
|
||||||
let num = uuid.to_u128_le();
|
let num = uuid.to_u128_le();
|
||||||
let uuid0 = num as u64;
|
let uuid0 = num as u64;
|
||||||
let uuid1 = (num >> 64) as u64;
|
let uuid1 = (num >> 64) as u64;
|
||||||
@ -75,6 +77,7 @@ pub struct MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>) -> Result<Internal> {
|
pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>) -> Result<Internal> {
|
||||||
|
let mut machine_descriptions = MachineDescription::load_file(&config.machines)?;
|
||||||
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)?;
|
||||||
@ -82,3 +85,29 @@ pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>) -> Resu
|
|||||||
|
|
||||||
Ok(Internal::new(log, env, machdb))
|
Ok(Internal::new(log, env, machdb))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MachMap = HashMap<MachineIdentifier, MachineDescription>;
|
||||||
|
|
||||||
|
pub struct MachineDB {
|
||||||
|
state_db: Internal,
|
||||||
|
def_db: MachMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MachineDB {
|
||||||
|
pub fn new(state_db: Internal, def_db: MachMap) -> Self {
|
||||||
|
Self { state_db, def_db }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exists(&self, id: MachineIdentifier) -> bool {
|
||||||
|
self.def_db.get(&id).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_desc(&self, id: &MachineIdentifier) -> Option<&MachineDescription> {
|
||||||
|
self.def_db.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_state(&self, id: &MachineIdentifier) -> Option<MachineState> {
|
||||||
|
// TODO: Error Handling
|
||||||
|
self.state_db.get(id).unwrap_or(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ use futures::future::Ready;
|
|||||||
use futures::stream::Iter;
|
use futures::stream::Iter;
|
||||||
|
|
||||||
use super::{MachineIdentifier, MachineState};
|
use super::{MachineIdentifier, MachineState};
|
||||||
|
use crate::machine::MachineDescription;
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -29,7 +30,7 @@ impl Internal {
|
|||||||
Self { log, env, db }
|
Self { log, env, db }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<T: Transaction>(&self, txn: &T, uuid: &Uuid)
|
pub fn get_with_txn<T: Transaction>(&self, txn: &T, uuid: &Uuid)
|
||||||
-> Result<Option<MachineState>>
|
-> Result<Option<MachineState>>
|
||||||
{
|
{
|
||||||
match txn.get(self.db, uuid.as_bytes()) {
|
match txn.get(self.db, uuid.as_bytes()) {
|
||||||
@ -42,7 +43,12 @@ impl Internal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(&self, txn: &mut RwTransaction, uuid: &Uuid, status: MachineState)
|
pub fn get(&self, id: &MachineIdentifier) -> Result<Option<MachineState>> {
|
||||||
|
let txn = self.env.begin_ro_txn()?;
|
||||||
|
self.get_with_txn(&txn, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_with_txn(&self, txn: &mut RwTransaction, uuid: &Uuid, status: MachineState)
|
||||||
-> Result<()>
|
-> Result<()>
|
||||||
{
|
{
|
||||||
let bytes = flexbuffers::to_vec(status)?;
|
let bytes = flexbuffers::to_vec(status)?;
|
||||||
@ -51,68 +57,6 @@ impl Internal {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_db(&mut self, txn: &mut RwTransaction, mut path: PathBuf) -> Result<()> {
|
|
||||||
path.push("machines");
|
|
||||||
for entry in std::fs::read_dir(path)? {
|
|
||||||
let entry = entry?;
|
|
||||||
let path = entry.path();
|
|
||||||
if path.is_file() {
|
|
||||||
// will only ever be none if the path has no file name and then how is it a file?!
|
|
||||||
let machID_str = path
|
|
||||||
.file_stem().expect("Found a file with no filename?")
|
|
||||||
.to_str().expect("Found an OsStr that isn't valid Unicode. Fix your OS!");
|
|
||||||
let machID = match uuid::Uuid::from_str(machID_str) {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(e) => {
|
|
||||||
warn!(self.log, "File {} had a invalid name. Expected an u64 in [0-9a-z] hex with optional file ending: {}. Skipping!", path.display(), e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let s = match fs::read_to_string(path.as_path()) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
warn!(self.log, "Failed to open file {}: {}, skipping!"
|
|
||||||
, path.display()
|
|
||||||
, e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mach: MachineState = match toml::from_str(&s) {
|
|
||||||
Ok(r) => r,
|
|
||||||
Err(e) => {
|
|
||||||
warn!(self.log, "Failed to parse mach at path {}: {}, skipping!"
|
|
||||||
, path.display()
|
|
||||||
, e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.put(txn, &machID, mach)?;
|
|
||||||
debug!(self.log, "Loaded machine {}", machID);
|
|
||||||
} else {
|
|
||||||
warn!(self.log, "Path {} is not a file, skipping!", path.display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dump_db<T: Transaction>(&self, txn: &T, mut path: PathBuf) -> Result<()> {
|
|
||||||
path.push("machines");
|
|
||||||
let mut mach_cursor = txn.open_ro_cursor(self.db)?;
|
|
||||||
for buf in mach_cursor.iter_start() {
|
|
||||||
let (kbuf, vbuf) = buf?;
|
|
||||||
let machID = uuid::Uuid::from_slice(kbuf).unwrap();
|
|
||||||
let mach: MachineState = flexbuffers::from_slice(vbuf)?;
|
|
||||||
let filename = format!("{}.yml", machID.to_hyphenated().to_string());
|
|
||||||
path.set_file_name(filename);
|
|
||||||
let mut fp = std::fs::File::create(&path)?;
|
|
||||||
let out = toml::to_vec(&mach)?;
|
|
||||||
fp.write_all(&out)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter<T: Transaction>(&self, txn: &T) -> Result<impl Iterator<Item=MachineState>> {
|
pub fn iter<T: Transaction>(&self, txn: &T) -> Result<impl Iterator<Item=MachineState>> {
|
||||||
let mut cursor = txn.open_ro_cursor(self.db)?;
|
let mut cursor = txn.open_ro_cursor(self.db)?;
|
||||||
Ok(cursor.iter_start().map(|buf| {
|
Ok(cursor.iter_start().map(|buf| {
|
||||||
|
@ -60,14 +60,14 @@ impl Machine {
|
|||||||
/// Requests to use a machine. Returns `true` if successful.
|
/// Requests to use a machine. Returns `true` if successful.
|
||||||
///
|
///
|
||||||
/// This will update the internal state of the machine, notifying connected actors, if any.
|
/// This will update the internal state of the machine, notifying connected actors, if any.
|
||||||
pub fn request_use<P: access::RoleDB>
|
pub async fn request_use
|
||||||
( &mut self
|
( &mut self
|
||||||
, pp: &P
|
, access: access::AccessControl
|
||||||
, who: &User
|
, who: &User
|
||||||
) -> Result<bool>
|
) -> Result<bool>
|
||||||
{
|
{
|
||||||
// TODO: Check different levels
|
// TODO: Check different levels
|
||||||
if pp.check(who, &self.desc.privs.write)? {
|
if access.check(who, &self.desc.privs.write).await? {
|
||||||
self.state.set(MachineState { state: Status::InUse(who.id.clone()) });
|
self.state.set(MachineState { state: Status::InUse(who.id.clone()) });
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
} else {
|
} else {
|
||||||
@ -97,7 +97,7 @@ pub struct MachineDescription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineDescription {
|
impl MachineDescription {
|
||||||
fn load_file<P: AsRef<Path>>(path: P) -> Result<HashMap<MachineIdentifier, MachineDescription>> {
|
pub fn load_file<P: AsRef<Path>>(path: P) -> Result<HashMap<MachineIdentifier, MachineDescription>> {
|
||||||
let content = fs::read(path)?;
|
let content = fs::read(path)?;
|
||||||
Ok(toml::from_slice(&content[..])?)
|
Ok(toml::from_slice(&content[..])?)
|
||||||
}
|
}
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -112,7 +112,7 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
|
|
||||||
// If no `config` option is given use a preset default.
|
// If no `config` option is given use a preset default.
|
||||||
let configpath = matches.value_of("config").unwrap_or("/etc/diflouroborane.toml");
|
let configpath = matches.value_of("config").unwrap_or("/etc/bffh/config.toml");
|
||||||
let config = config::read(&PathBuf::from_str(configpath).unwrap())?;
|
let config = config::read(&PathBuf::from_str(configpath).unwrap())?;
|
||||||
|
|
||||||
// Initialize the logging subsystem first to be able to better document the progress from now
|
// Initialize the logging subsystem first to be able to better document the progress from now
|
||||||
@ -153,7 +153,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?.load_db(&mut txn, path.clone())?;
|
||||||
mdb?.load_db(&mut txn, path)?;
|
//mdb?.load_db(&mut txn, path)?;
|
||||||
txn.commit()?;
|
txn.commit()?;
|
||||||
} else {
|
} else {
|
||||||
error!(log, "You must provide a directory path to load from");
|
error!(log, "You must provide a directory path to load from");
|
||||||
@ -171,7 +171,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?.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");
|
||||||
}
|
}
|
||||||
@ -210,8 +210,15 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
// Error out if any of the subsystems failed to start.
|
// Error out if any of the subsystems failed to start.
|
||||||
let mdb = mdb?;
|
let mdb = mdb?;
|
||||||
|
let defs = machine::MachineDescription::load_file(&config.machines)?;
|
||||||
|
let machdb = db::machine::MachineDB::new(mdb, defs);
|
||||||
let pdb = pdb?;
|
let pdb = pdb?;
|
||||||
//let auth = auth?;
|
let mut ac = db::access::AccessControl::new();
|
||||||
|
ac.add_source_unchecked("Internal".to_string(), Box::new(pdb));
|
||||||
|
let db = db::Databases {
|
||||||
|
access: Arc::new(db::access::AccessControl::new()),
|
||||||
|
machine: Arc::new(machdb),
|
||||||
|
};
|
||||||
|
|
||||||
// Since the below closures will happen at a much later time we need to make sure all pointers
|
// Since the below closures will happen at a much later time we need to make sure all pointers
|
||||||
// are still valid. Thus, Arc.
|
// are still valid. Thus, Arc.
|
||||||
@ -270,7 +277,7 @@ fn main() -> Result<(), Error> {
|
|||||||
let elog = log.clone();
|
let elog = log.clone();
|
||||||
|
|
||||||
// We handle the error using map_err
|
// We handle the error using map_err
|
||||||
let f = connection::handle_connection(log.clone(), socket)
|
let f = connection::handle_connection(log.clone(), socket, db.clone())
|
||||||
.map_err(move |e| {
|
.map_err(move |e| {
|
||||||
error!(log, "Error occured during protocol handling: {}", e);
|
error!(log, "Error occured during protocol handling: {}", e);
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user