mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-12-22 19:53:49 +01:00
Stuff to make work
This commit is contained in:
parent
abc9126137
commit
ba7a59c3de
@ -39,4 +39,5 @@
|
||||
}
|
||||
}
|
||||
, mqtt_url = "tcp://localhost:1883"
|
||||
, db_path = "/tmp/bffh"
|
||||
}
|
||||
|
44
src/api.rs
44
src/api.rs
@ -13,9 +13,11 @@ use crate::network::Network;
|
||||
pub mod auth;
|
||||
mod machine;
|
||||
mod machines;
|
||||
|
||||
use machines::Machines;
|
||||
|
||||
mod users;
|
||||
use users::Users;
|
||||
|
||||
// TODO Session restoration by making the Bootstrap cap a SturdyRef
|
||||
pub struct Bootstrap {
|
||||
session: Arc<Session>,
|
||||
@ -45,13 +47,6 @@ impl connection_capnp::bootstrap::Server for Bootstrap {
|
||||
Promise::ok(())
|
||||
}
|
||||
|
||||
fn permission_system(&mut self,
|
||||
_: PermissionSystemParams,
|
||||
_: PermissionSystemResults
|
||||
) -> Promise<(), capnp::Error> {
|
||||
Promise::ok(())
|
||||
}
|
||||
|
||||
fn machine_system(&mut self,
|
||||
_: MachineSystemParams,
|
||||
mut res: MachineSystemResults
|
||||
@ -65,6 +60,11 @@ impl connection_capnp::bootstrap::Server for Bootstrap {
|
||||
let perms = accessdb.collect_permrules(&user.data)
|
||||
.map_err(|e| capnp::Error::failed(format!("AccessDB lookup failed: {}", e)))?;
|
||||
|
||||
debug!(session.log, "Giving MachineSystem cap to user {} with perms:", user.id);
|
||||
for r in perms.iter() {
|
||||
debug!(session.log, " {}", r);
|
||||
}
|
||||
|
||||
// TODO actual permission check and stuff
|
||||
// Right now we only check that the user has authenticated at all.
|
||||
let c = capnp_rpc::new_client(Machines::new(user.id, perms, nw));
|
||||
@ -78,5 +78,31 @@ impl connection_capnp::bootstrap::Server for Bootstrap {
|
||||
|
||||
Promise::from_future(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn user_system(
|
||||
&mut self,
|
||||
_: UserSystemParams,
|
||||
mut results: UserSystemResults
|
||||
) -> Promise<(), capnp::Error> {
|
||||
let session = self.session.clone();
|
||||
let accessdb = self.db.access.clone();
|
||||
let f = async move {
|
||||
// Ensure the lock is dropped as soon as possible
|
||||
if let Some(user) = { session.user.lock().await.clone() } {
|
||||
let perms = accessdb.collect_permrules(&user.data)
|
||||
.map_err(|e| capnp::Error::failed(format!("AccessDB lookup failed: {}", e)))?;
|
||||
|
||||
// TODO actual permission check and stuff
|
||||
// Right now we only check that the user has authenticated at all.
|
||||
let c = capnp_rpc::new_client(Users::new(perms));
|
||||
results.get().set_user_system(c);
|
||||
}
|
||||
|
||||
// Promise is Ok either way, just the machine system may not be set, indicating as
|
||||
// usual a lack of permission.
|
||||
Ok(())
|
||||
};
|
||||
|
||||
Promise::from_future(f)
|
||||
}
|
||||
}
|
||||
|
43
src/api/users.rs
Normal file
43
src/api/users.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use capnp::capability::Promise;
|
||||
|
||||
use crate::db::access::{PermRule, Permission};
|
||||
use crate::schema::usersystem_capnp::user_system;
|
||||
use crate::schema::usersystem_capnp::user_system::{info, manage};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Users {
|
||||
perms: Vec<PermRule>,
|
||||
}
|
||||
|
||||
impl Users {
|
||||
pub fn new(perms: Vec<PermRule>) -> Self {
|
||||
Self { perms }
|
||||
}
|
||||
}
|
||||
|
||||
impl user_system::Server for Users {
|
||||
fn info(
|
||||
&mut self,
|
||||
_: user_system::InfoParams,
|
||||
_: user_system::InfoResults,
|
||||
) -> Promise<(), capnp::Error> {
|
||||
Promise::ok(())
|
||||
}
|
||||
|
||||
fn manage(
|
||||
&mut self,
|
||||
_: user_system::ManageParams,
|
||||
mut results: user_system::ManageResults,
|
||||
) -> Promise<(), capnp::Error> {
|
||||
let perm: &Permission = Permission::new("bffh.users.manage");
|
||||
if self.perms.iter().any(|rule| rule.match_perm(perm)) {
|
||||
results.get().set_manage(capnp_rpc::new_client(self.clone()));
|
||||
}
|
||||
|
||||
Promise::ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl info::Server for Users {}
|
||||
|
||||
impl manage::Server for Users {}
|
@ -1,5 +1,5 @@
|
||||
use std::default::Default;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
@ -36,6 +36,8 @@ pub struct Config {
|
||||
|
||||
pub actor_connections: Box<[(String, String)]>,
|
||||
pub init_connections: Box<[(String, String)]>,
|
||||
|
||||
pub db_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -83,9 +85,9 @@ impl Default for Config {
|
||||
port: Some(DEFAULT_PORT),
|
||||
}
|
||||
]),
|
||||
machines: machines,
|
||||
actors: actors,
|
||||
initiators: initiators,
|
||||
machines,
|
||||
actors,
|
||||
initiators,
|
||||
mqtt_url: "tcp://localhost:1883".to_string(),
|
||||
actor_connections: Box::new([
|
||||
("Testmachine".to_string(), "Actor".to_string()),
|
||||
@ -93,6 +95,8 @@ impl Default for Config {
|
||||
init_connections: Box::new([
|
||||
("Initiator".to_string(), "Testmachine".to_string()),
|
||||
]),
|
||||
|
||||
db_path: PathBuf::from("/run/bffh/database"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ impl Databases {
|
||||
let env = lmdb::Environment::new()
|
||||
.set_flags(lmdb::EnvironmentFlags::MAP_ASYNC | lmdb::EnvironmentFlags::NO_SUB_DIR)
|
||||
.set_max_dbs(LMDB_MAX_DB as libc::c_uint)
|
||||
.open(&PathBuf::from_str("/tmp/a.db").unwrap())?;
|
||||
.open(config.db_path.as_path())?;
|
||||
|
||||
// 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
|
||||
|
@ -186,6 +186,31 @@ impl Role {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Role {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "parents:")?;
|
||||
if self.parents.is_empty() {
|
||||
writeln!(f, " []")?;
|
||||
} else {
|
||||
writeln!(f, "")?;
|
||||
for p in self.parents.iter() {
|
||||
writeln!(f, " - {}", p)?;
|
||||
}
|
||||
}
|
||||
write!(f, "permissions:")?;
|
||||
if self.permissions.is_empty() {
|
||||
writeln!(f, " []")?;
|
||||
} else {
|
||||
writeln!(f, "")?;
|
||||
for p in self.permissions.iter() {
|
||||
writeln!(f, " - {}", p)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
type SourceID = String;
|
||||
|
||||
fn split_once(s: &str, split: char) -> Option<(&str, &str)> {
|
||||
@ -454,7 +479,7 @@ pub enum PermRule {
|
||||
|
||||
impl PermRule {
|
||||
// Does this rule match that permission
|
||||
pub fn match_perm<P: AsRef<Permission>>(&self, perm: &P) -> bool {
|
||||
pub fn match_perm<P: AsRef<Permission> + ?Sized>(&self, perm: &P) -> bool {
|
||||
match self {
|
||||
PermRule::Base(ref base) => base.as_permission() == perm.as_ref(),
|
||||
PermRule::Children(ref parent) => parent.as_permission() > perm.as_ref() ,
|
||||
|
@ -69,16 +69,15 @@ impl Internal {
|
||||
roles.insert(role_id.clone(), role);
|
||||
}
|
||||
} else {
|
||||
info!(self.log, "Did not find role {} while trying to tally", role_id);
|
||||
warn!(self.log, "Did not find role {} while trying to tally", role_id);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn _get_role<'txn, T: Transaction>(&self, txn: &'txn T, role_id: &RoleIdentifier) -> Result<Option<Role>> {
|
||||
let string = format!("{}", role_id);
|
||||
debug!(self.log, "Reading role '{}'", &string);
|
||||
match txn.get(self.roledb, &string.as_bytes()) {
|
||||
debug!(self.log, "Reading role '{}'", role_id.name);
|
||||
match txn.get(self.roledb, &role_id.name.as_bytes()) {
|
||||
Ok(bytes) => {
|
||||
Ok(Some(flexbuffers::from_slice(bytes)?))
|
||||
},
|
||||
@ -89,8 +88,7 @@ impl Internal {
|
||||
|
||||
fn put_role(&self, txn: &mut RwTransaction, role_id: &RoleIdentifier, role: Role) -> Result<()> {
|
||||
let bytes = flexbuffers::to_vec(role)?;
|
||||
let string = format!("{}", role_id);
|
||||
txn.put(self.roledb, &string.as_bytes(), &bytes, lmdb::WriteFlags::empty())?;
|
||||
txn.put(self.roledb, &role_id.name.as_bytes(), &bytes, lmdb::WriteFlags::empty())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -107,8 +105,8 @@ impl Internal {
|
||||
for r in cursor.iter_start() {
|
||||
match r {
|
||||
Ok( (k,v) ) => {
|
||||
let role_id_str = unsafe { std::str::from_utf8_unchecked(k) };
|
||||
let role_id = role_id_str.parse::<RoleIdentifier>().unwrap();
|
||||
let role_name_str = unsafe { std::str::from_utf8_unchecked(k) };
|
||||
let role_id = RoleIdentifier::local_from_str(role_name_str.to_string(), "lmdb".to_string());
|
||||
match flexbuffers::from_slice(v) {
|
||||
Ok(role) => vec.push((role_id, role)),
|
||||
Err(e) => error!(self.log, "Bad format for roleid {}: {}", role_id, e),
|
||||
@ -126,7 +124,7 @@ impl Internal {
|
||||
self.load_roles_txn(&mut txn, path.as_ref())?;
|
||||
|
||||
// In case the above didn't error, commit.
|
||||
txn.commit();
|
||||
txn.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
fn load_roles_txn(&self, txn: &mut RwTransaction, path: &Path) -> Result<()> {
|
||||
|
@ -141,8 +141,10 @@ fn maybe(matches: clap::ArgMatches, log: Arc<Logger>) -> Result<(), Error> {
|
||||
|
||||
if matches.is_present("dump") {
|
||||
let db = db::Databases::new(&log, &config)?;
|
||||
let v = db.access.dump_roles();
|
||||
info!(log, "Roles {:?}", v);
|
||||
let v = db.access.dump_roles().unwrap();
|
||||
for (id, role) in v.iter() {
|
||||
info!(log, "Role {}:\n{}", id, role);
|
||||
}
|
||||
Ok(())
|
||||
} else if matches.is_present("load") {
|
||||
let db = db::Databases::new(&log, &config)?;
|
||||
|
Loading…
Reference in New Issue
Block a user