mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-22 14:57:56 +01:00
More API implementation
This commit is contained in:
parent
b8a9b64953
commit
e5903961d1
25
src/api.rs
25
src/api.rs
@ -6,6 +6,7 @@ use crate::schema::connection_capnp;
|
|||||||
use crate::connection::Session;
|
use crate::connection::Session;
|
||||||
|
|
||||||
use crate::db::Databases;
|
use crate::db::Databases;
|
||||||
|
use crate::db::user::UserId;
|
||||||
|
|
||||||
use crate::network::Network;
|
use crate::network::Network;
|
||||||
|
|
||||||
@ -55,11 +56,27 @@ impl connection_capnp::bootstrap::Server for Bootstrap {
|
|||||||
_: MachineSystemParams,
|
_: MachineSystemParams,
|
||||||
mut res: MachineSystemResults
|
mut res: MachineSystemResults
|
||||||
) -> Promise<(), capnp::Error> {
|
) -> Promise<(), capnp::Error> {
|
||||||
// TODO actual permission check and stuff
|
let session = self.session.clone();
|
||||||
let c = capnp_rpc::new_client(Machines::new(self.session.clone(), self.db.clone(), self.nw.clone()));
|
let accessdb = self.db.access.clone();
|
||||||
res.get().set_machine_system(c);
|
let nw = self.nw.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)))?;
|
||||||
|
|
||||||
Promise::ok(())
|
// 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));
|
||||||
|
res.get().set_machine_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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ impl Callback<AppData, SessionData> for CB {
|
|||||||
if b {
|
if b {
|
||||||
if let Some(s) = cap_session {
|
if let Some(s) = cap_session {
|
||||||
if let Ok(Some(user)) = appdata.userdb.get_user(authid) {
|
if let Ok(Some(user)) = appdata.userdb.get_user(authid) {
|
||||||
|
// FIXME: This should set the userid outside the callback
|
||||||
s.user.try_lock().unwrap().replace(user);
|
s.user.try_lock().unwrap().replace(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +117,7 @@ impl authentication_system::Server for Auth {
|
|||||||
_: authentication_system::MechanismsParams,
|
_: authentication_system::MechanismsParams,
|
||||||
mut res: authentication_system::MechanismsResults
|
mut res: authentication_system::MechanismsResults
|
||||||
) -> Promise<(), capnp::Error> {
|
) -> Promise<(), capnp::Error> {
|
||||||
let mechs = match self.ctx.server_mech_list() {
|
/*let mechs = match self.ctx.server_mech_list() {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Promise::err(capnp::Error {
|
return Promise::err(capnp::Error {
|
||||||
@ -131,7 +132,10 @@ impl authentication_system::Server for Auth {
|
|||||||
let mut res_mechs = res.get().init_mechs(mechvec.len() as u32);
|
let mut res_mechs = res.get().init_mechs(mechvec.len() as u32);
|
||||||
for (i, m) in mechvec.into_iter().enumerate() {
|
for (i, m) in mechvec.into_iter().enumerate() {
|
||||||
res_mechs.set(i as u32, m);
|
res_mechs.set(i as u32, m);
|
||||||
}
|
}*/
|
||||||
|
// For now, only PLAIN
|
||||||
|
let mut res_mechs = res.get().init_mechs(1);
|
||||||
|
res_mechs.set(0, "PLAIN");
|
||||||
|
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
@ -146,6 +150,13 @@ impl authentication_system::Server for Auth {
|
|||||||
// Extract the MECHANISM the client wants to use and start a session.
|
// Extract the MECHANISM the client wants to use and start a session.
|
||||||
// Or fail at that and thrown an exception TODO: return Outcome
|
// Or fail at that and thrown an exception TODO: return Outcome
|
||||||
let mech = pry!(req.get_mechanism());
|
let mech = pry!(req.get_mechanism());
|
||||||
|
if pry!(req.get_mechanism()) != "PLAIN" {
|
||||||
|
return Promise::err(capnp::Error {
|
||||||
|
kind: capnp::ErrorKind::Failed,
|
||||||
|
description: format!("Invalid SASL mech"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let mut session = match self.ctx.server_start(mech) {
|
let mut session = match self.ctx.server_start(mech) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) =>
|
Err(e) =>
|
||||||
|
@ -1,137 +1,115 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
use capnp::Error;
|
use capnp::Error;
|
||||||
|
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
|
|
||||||
use crate::schema::machine_capnp::machine::*;
|
use crate::db::access::{PrivilegesBuf, PermRule};
|
||||||
use crate::connection::Session;
|
|
||||||
use crate::db::Databases;
|
use crate::db::machine::Status;
|
||||||
use crate::db::machine::{Status, MachineState};
|
use crate::machine::Machine as NwMachine;
|
||||||
use crate::machine::{Machine as NwMachine, ReturnToken};
|
use crate::schema::machine_capnp::machine::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Perms {
|
||||||
|
pub disclose: bool,
|
||||||
|
pub read: bool,
|
||||||
|
pub write: bool,
|
||||||
|
pub manage: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Perms {
|
||||||
|
pub fn get_for<'a, I: Iterator<Item=&'a PermRule>>(privs: &'a PrivilegesBuf, rules: I) -> Self {
|
||||||
|
let mut disclose = false;
|
||||||
|
let mut read = false;
|
||||||
|
let mut write = false;
|
||||||
|
let mut manage = false;
|
||||||
|
for rule in rules {
|
||||||
|
if rule.match_perm(&privs.disclose) {
|
||||||
|
disclose = true;
|
||||||
|
}
|
||||||
|
if rule.match_perm(&privs.read) {
|
||||||
|
read = true;
|
||||||
|
}
|
||||||
|
if rule.match_perm(&privs.write) {
|
||||||
|
write = true;
|
||||||
|
}
|
||||||
|
if rule.match_perm(&privs.manage) {
|
||||||
|
manage = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { disclose, read, write, manage }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
session: Arc<Session>,
|
perms: Perms,
|
||||||
machine: NwMachine,
|
machine: NwMachine,
|
||||||
db: Databases,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub fn new(session: Arc<Session>, machine: NwMachine, db: Databases) -> Self {
|
pub fn new(perms: Perms, machine: NwMachine) -> Self {
|
||||||
Machine { session, machine, db }
|
Self { perms, machine }
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fill(self: Arc<Self>, builder: &mut Builder) {
|
|
||||||
builder.set_manage(capnp_rpc::new_client(Manage(self.clone())));
|
|
||||||
builder.set_admin(capnp_rpc::new_client(Admin(self.clone())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
impl info::Server for Machine {
|
||||||
pub struct Read(Arc<Machine>);
|
fn get_machine_info_extended(
|
||||||
|
&mut self,
|
||||||
|
_: info::GetMachineInfoExtendedParams,
|
||||||
|
_results: info::GetMachineInfoExtendedResults,
|
||||||
|
) -> capnp::capability::Promise<(), capnp::Error> {
|
||||||
|
/*if self.perms.manage {
|
||||||
|
let mut builder = results.get();
|
||||||
|
let mut extinfo = builder.init_machine_info_extended();
|
||||||
|
let mut current = extinfo.init_current_user();
|
||||||
|
// FIXME fill user
|
||||||
|
}
|
||||||
|
Promise::ok(())*/
|
||||||
|
|
||||||
impl Read {
|
Promise::err(capnp::Error::unimplemented("Extended Infos are unavailable".to_string()))
|
||||||
pub fn new(inner: Arc<Machine>) -> Self {
|
}
|
||||||
Self(inner)
|
|
||||||
|
fn get_reservation_list(
|
||||||
|
&mut self,
|
||||||
|
_: info::GetReservationListParams,
|
||||||
|
mut results: info::GetReservationListResults,
|
||||||
|
) -> capnp::capability::Promise<(), capnp::Error> {
|
||||||
|
Promise::err(capnp::Error::unimplemented("Reservations are unavailable".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_property_list(
|
||||||
|
&mut self,
|
||||||
|
_: info::GetPropertyListParams,
|
||||||
|
mut results: info::GetPropertyListResults,
|
||||||
|
) -> capnp::capability::Promise<(), capnp::Error> {
|
||||||
|
Promise::err(capnp::Error::unimplemented("Extended Properties are unavailable".to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl info::Server for Read {
|
impl use_::Server for Machine {
|
||||||
}
|
fn use_(
|
||||||
|
&mut self,
|
||||||
struct Write(Arc<Machine>);
|
_: use_::UseParams,
|
||||||
|
_: use_::UseResults
|
||||||
impl use_::Server for Write {
|
) -> capnp::capability::Promise<(), capnp::Error> {
|
||||||
fn use_(&mut self,
|
Promise::ok(())
|
||||||
_params: use_::UseParams,
|
|
||||||
mut results: use_::UseResults)
|
|
||||||
-> Promise<(), Error>
|
|
||||||
{
|
|
||||||
let uid = self.0.session.user.try_lock().unwrap().as_ref().map(|u| u.id.clone());
|
|
||||||
let new_state = MachineState::used(uid.clone());
|
|
||||||
let this = self.0.clone();
|
|
||||||
let f = async move {
|
|
||||||
let res_token = this.machine.request_state_change(
|
|
||||||
this.session.user.try_lock().unwrap().as_ref(),
|
|
||||||
new_state
|
|
||||||
).await;
|
|
||||||
|
|
||||||
match res_token {
|
|
||||||
// TODO: Do something with the token we get returned
|
|
||||||
Ok(tok) => {
|
|
||||||
return Ok(());
|
|
||||||
},
|
|
||||||
Err(e) => Err(capnp::Error::failed(format!("State change request returned {}", e))),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Promise::from_future(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reserve(&mut self,
|
|
||||||
_params: use_::ReserveParams,
|
|
||||||
_results: use_::ReserveResults)
|
|
||||||
-> Promise<(), Error>
|
|
||||||
{
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl in_use::Server for Write {
|
|
||||||
fn give_back(&mut self,
|
|
||||||
_params: in_use::GiveBackParams,
|
|
||||||
mut results: in_use::GiveBackResults)
|
|
||||||
-> Promise<(), Error>
|
|
||||||
{
|
|
||||||
let this = self.0.clone();
|
|
||||||
|
|
||||||
let f = async move {
|
|
||||||
let status = this.machine.get_status().await;
|
|
||||||
let sess = this.session.clone();
|
|
||||||
|
|
||||||
match status {
|
|
||||||
Status::InUse(Some(uid)) => {
|
|
||||||
let user = sess.user.lock().await;
|
|
||||||
if let Some(u) = user.as_ref() {
|
|
||||||
if u.id == uid {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Machine not in use
|
|
||||||
_ => {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Promise::from_future(f.map(|_| Ok(())))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Manage(Arc<Machine>);
|
impl in_use::Server for Machine {
|
||||||
|
|
||||||
impl manage::Server for Manage {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Admin(Arc<Machine>);
|
impl transfer::Server for Machine {
|
||||||
|
}
|
||||||
impl admin::Server for Admin {
|
|
||||||
fn force_set_state(&mut self,
|
impl check::Server for Machine {
|
||||||
_params: admin::ForceSetStateParams,
|
}
|
||||||
_results: admin::ForceSetStateResults)
|
|
||||||
-> Promise<(), Error>
|
impl manage::Server for Machine {
|
||||||
{
|
}
|
||||||
unimplemented!()
|
|
||||||
}
|
impl admin::Server for Machine {
|
||||||
|
|
||||||
fn force_set_user(&mut self,
|
|
||||||
_params: admin::ForceSetUserParams,
|
|
||||||
_results: admin::ForceSetUserResults)
|
|
||||||
-> Promise<(), Error>
|
|
||||||
{
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,39 @@ use std::sync::Arc;
|
|||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
use capnp::Error;
|
use capnp::Error;
|
||||||
|
|
||||||
|
use crate::db::machine::Status;
|
||||||
|
use crate::api::machine::*;
|
||||||
|
use crate::schema::machine_capnp::machine::MachineState;
|
||||||
use crate::schema::machinesystem_capnp::machine_system;
|
use crate::schema::machinesystem_capnp::machine_system;
|
||||||
use crate::schema::machinesystem_capnp::machine_system::info as machines;
|
use crate::schema::machinesystem_capnp::machine_system::info as machines;
|
||||||
use crate::connection::Session;
|
|
||||||
|
|
||||||
use crate::db::Databases;
|
|
||||||
|
|
||||||
use crate::network::Network;
|
use crate::network::Network;
|
||||||
|
use crate::db::user::UserId;
|
||||||
use super::machine::*;
|
use crate::db::access::{PermRule, admin_perm};
|
||||||
|
|
||||||
/// An implementation of the `Machines` API
|
/// An implementation of the `Machines` API
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Machines {
|
pub struct Machines {
|
||||||
/// A reference to the connection — as long as at least one API endpoint is
|
user: UserId,
|
||||||
/// still alive the session has to be as well.
|
permissions: Vec<PermRule>,
|
||||||
session: Arc<Session>,
|
|
||||||
|
|
||||||
db: Databases,
|
|
||||||
network: Arc<Network>,
|
network: Arc<Network>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Machines {
|
impl Machines {
|
||||||
pub fn new(session: Arc<Session>, db: Databases, network: Arc<Network>) -> Self {
|
pub fn new(user: UserId, permissions: Vec<PermRule>, network: Arc<Network>) -> Self {
|
||||||
info!(session.log, "Machines created");
|
Self { user, permissions, network }
|
||||||
Self { session, db, network }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl machine_system::Server for Machines {
|
impl machine_system::Server for Machines {
|
||||||
|
// This function shouldn't exist. See fabaccess-api issue #16
|
||||||
|
fn info(&mut self,
|
||||||
|
_:machine_system::InfoParams,
|
||||||
|
mut results: machine_system::InfoResults
|
||||||
|
) -> capnp::capability::Promise<(), capnp::Error>
|
||||||
|
{
|
||||||
|
results.get().set_info(capnp_rpc::new_client(self.clone()));
|
||||||
|
Promise::ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl machines::Server for Machines {
|
impl machines::Server for Machines {
|
||||||
@ -41,18 +45,61 @@ impl machines::Server for Machines {
|
|||||||
-> Promise<(), Error>
|
-> Promise<(), Error>
|
||||||
{
|
{
|
||||||
let v: Vec<(String, crate::machine::Machine)> = self.network.machines.iter()
|
let v: Vec<(String, crate::machine::Machine)> = self.network.machines.iter()
|
||||||
.map(|(n, m)| (n.clone(), m.clone()))
|
.filter(|(_name, machine)| {
|
||||||
|
let required_disclose = &machine.desc.privs.disclose;
|
||||||
|
for perm_rule in self.permissions.iter() {
|
||||||
|
if perm_rule.match_perm(required_disclose) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.map(|(n,m)| (n.clone(), m.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
/*let mut machines = results.get().init_machines(v.len() as u32);
|
let permissions = self.permissions.clone();
|
||||||
|
|
||||||
for (i, (name, machine)) in v.into_iter().enumerate() {
|
let f = async move {
|
||||||
trace!(self.session.log, "Adding machine #{} {}: {:?}", i, name, machine);
|
let mut machines = results.get().init_machine_list(v.len() as u32);
|
||||||
let machine = Arc::new(Machine::new(self.session.clone(), machine, self.db.clone()));
|
for (i, (name, machine)) in v.into_iter().enumerate() {
|
||||||
let mut builder = machines.reborrow().get(i as u32);
|
let perms = Perms::get_for(&machine.desc.privs, permissions.iter());
|
||||||
machine.fill(&mut builder);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Promise::ok(())
|
let mut builder = machines.reborrow().get(i as u32);
|
||||||
|
builder.set_name(&name);
|
||||||
|
if let Some(ref desc) = machine.desc.description {
|
||||||
|
builder.set_description(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = match machine.get_status().await {
|
||||||
|
Status::Free => MachineState::Free,
|
||||||
|
Status::Disabled => MachineState::Disabled,
|
||||||
|
Status::Blocked(_) => MachineState::Blocked,
|
||||||
|
Status::InUse(_) => MachineState::InUse,
|
||||||
|
Status::Reserved(_) => MachineState::Reserved,
|
||||||
|
Status::ToCheck(_) => MachineState::ToCheck,
|
||||||
|
};
|
||||||
|
builder.set_state(s);
|
||||||
|
|
||||||
|
if perms.write {
|
||||||
|
builder.set_use(capnp_rpc::new_client(Machine::new(perms, machine.clone())));
|
||||||
|
builder.set_inuse(capnp_rpc::new_client(Machine::new(perms, machine.clone())));
|
||||||
|
}
|
||||||
|
if perms.manage {
|
||||||
|
builder.set_transfer(capnp_rpc::new_client(Machine::new(perms, machine.clone())));
|
||||||
|
builder.set_check(capnp_rpc::new_client(Machine::new(perms, machine.clone())));
|
||||||
|
builder.set_manage(capnp_rpc::new_client(Machine::new(perms, machine.clone())));
|
||||||
|
}
|
||||||
|
if permissions.iter().any(|r| r.match_perm(&admin_perm())) {
|
||||||
|
builder.set_admin(capnp_rpc::new_client(Machine::new(perms, machine.clone())));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.set_info(capnp_rpc::new_client(Machine::new(perms, machine)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise::from_future(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,15 @@ pub struct AccessControl {
|
|||||||
pub internal: Internal,
|
pub internal: Internal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ADMINPERM: &'static str = "bffh.admin";
|
||||||
|
pub fn admin_perm() -> &'static Permission {
|
||||||
|
Permission::new(ADMINPERM)
|
||||||
|
}
|
||||||
|
|
||||||
impl AccessControl {
|
impl AccessControl {
|
||||||
pub fn new(internal: Internal) -> Self {
|
pub fn new(internal: Internal) -> Self {
|
||||||
Self {
|
Self {
|
||||||
internal: internal,
|
internal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +52,10 @@ impl AccessControl {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn collect_permrules(&self, user: &UserData) -> Result<Vec<PermRule>> {
|
||||||
|
self.internal.collect_permrules(user)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dump_roles(&self) -> Result<Vec<(RoleIdentifier, Role)>> {
|
pub fn dump_roles(&self) -> Result<Vec<(RoleIdentifier, Role)>> {
|
||||||
self.internal.dump_roles()
|
self.internal.dump_roles()
|
||||||
}
|
}
|
||||||
@ -120,6 +129,22 @@ pub trait RoleDB {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_permrules(&self, user: &UserData) -> Result<Vec<PermRule>> {
|
||||||
|
let mut roleset = HashMap::new();
|
||||||
|
for role_id in user.roles.iter() {
|
||||||
|
self.tally_role(&mut roleset, role_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::new();
|
||||||
|
|
||||||
|
// Iter all unique role->permissions we've found and early return on match.
|
||||||
|
for (_roleid, role) in roleset.iter() {
|
||||||
|
output.extend(role.permissions.iter().cloned())
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A "Role" from the Authorization perspective
|
/// A "Role" from the Authorization perspective
|
||||||
@ -310,7 +335,7 @@ impl PermissionBuf {
|
|||||||
self.inner.push_str(perm.as_str())
|
self.inner.push_str(perm.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_string(inner: String) -> Self {
|
pub const fn from_string(inner: String) -> Self {
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +454,7 @@ pub enum PermRule {
|
|||||||
|
|
||||||
impl PermRule {
|
impl PermRule {
|
||||||
// Does this rule match that permission
|
// Does this rule match that permission
|
||||||
fn match_perm<P: AsRef<Permission>>(&self, perm: &P) -> bool {
|
pub fn match_perm<P: AsRef<Permission>>(&self, perm: &P) -> bool {
|
||||||
match self {
|
match self {
|
||||||
PermRule::Base(ref base) => base.as_permission() == perm.as_ref(),
|
PermRule::Base(ref base) => base.as_permission() == perm.as_ref(),
|
||||||
PermRule::Children(ref parent) => parent.as_permission() > perm.as_ref() ,
|
PermRule::Children(ref parent) => parent.as_permission() > perm.as_ref() ,
|
||||||
|
@ -77,21 +77,19 @@ impl Index {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
pub id: uuid::Uuid,
|
pub id: uuid::Uuid,
|
||||||
pub name: String,
|
pub desc: MachineDescription,
|
||||||
pub description: String,
|
|
||||||
|
|
||||||
inner: Arc<Mutex<Inner>>,
|
inner: Arc<Mutex<Inner>>,
|
||||||
access: Arc<access::AccessControl>,
|
access: Arc<access::AccessControl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub fn new(inner: Inner, access: Arc<access::AccessControl>) -> Self {
|
pub fn new(inner: Inner, desc: MachineDescription, access: Arc<access::AccessControl>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: uuid::Uuid::default(),
|
id: uuid::Uuid::default(),
|
||||||
name: "".to_string(),
|
|
||||||
description: "".to_string(),
|
|
||||||
inner: Arc::new(Mutex::new(inner)),
|
inner: Arc::new(Mutex::new(inner)),
|
||||||
access: access,
|
access,
|
||||||
|
desc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +100,7 @@ impl Machine {
|
|||||||
, access: Arc<access::AccessControl>
|
, access: Arc<access::AccessControl>
|
||||||
) -> Machine
|
) -> Machine
|
||||||
{
|
{
|
||||||
Self::new(Inner::new(id, desc, state), access)
|
Self::new(Inner::new(id, state), desc, access)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_file<P: AsRef<Path>>(path: P, access: Arc<access::AccessControl>)
|
pub fn from_file<P: AsRef<Path>>(path: P, access: Arc<access::AccessControl>)
|
||||||
@ -129,14 +127,14 @@ impl Machine {
|
|||||||
|
|
||||||
let f = async move {
|
let f = async move {
|
||||||
if let Some(udata) = udata {
|
if let Some(udata) = udata {
|
||||||
let mut guard = this.inner.try_lock().unwrap();
|
if this.access.check(&udata, &this.desc.privs.write).await? {
|
||||||
if this.access.check(&udata, &guard.desc.privs.write).await? {
|
let mut guard = this.inner.lock().await;
|
||||||
guard.do_state_change(new_state);
|
guard.do_state_change(new_state);
|
||||||
return Ok(ReturnToken::new(this.inner.clone()))
|
return Ok(ReturnToken::new(this.inner.clone()))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if new_state == MachineState::free() {
|
if new_state == MachineState::free() {
|
||||||
let mut guard = this.inner.try_lock().unwrap();
|
let mut guard = this.inner.lock().await;
|
||||||
guard.do_state_change(new_state);
|
guard.do_state_change(new_state);
|
||||||
return Ok(ReturnToken::new(this.inner.clone()));
|
return Ok(ReturnToken::new(this.inner.clone()));
|
||||||
}
|
}
|
||||||
@ -148,6 +146,20 @@ impl Machine {
|
|||||||
Box::pin(f)
|
Box::pin(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn do_state_change(&self, new_state: MachineState)
|
||||||
|
-> BoxFuture<'static, Result<ReturnToken>>
|
||||||
|
{
|
||||||
|
let this = self.clone();
|
||||||
|
|
||||||
|
let f = async move {
|
||||||
|
let mut guard = this.inner.lock().await;
|
||||||
|
guard.do_state_change(new_state);
|
||||||
|
return Ok(ReturnToken::new(this.inner.clone()))
|
||||||
|
};
|
||||||
|
|
||||||
|
Box::pin(f)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_token(&self) -> ReturnToken {
|
pub fn create_token(&self) -> ReturnToken {
|
||||||
ReturnToken::new(self.inner.clone())
|
ReturnToken::new(self.inner.clone())
|
||||||
}
|
}
|
||||||
@ -161,6 +173,10 @@ impl Machine {
|
|||||||
let guard = self.inner.try_lock().unwrap();
|
let guard = self.inner.try_lock().unwrap();
|
||||||
guard.signal()
|
guard.signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_inner(&self) -> Arc<Mutex<Inner>> {
|
||||||
|
self.inner.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Machine {
|
impl Deref for Machine {
|
||||||
@ -182,9 +198,6 @@ pub struct Inner {
|
|||||||
/// Globally unique machine readable identifier
|
/// Globally unique machine readable identifier
|
||||||
pub id: MachineIdentifier,
|
pub id: MachineIdentifier,
|
||||||
|
|
||||||
/// Descriptor of the machine
|
|
||||||
pub desc: MachineDescription,
|
|
||||||
|
|
||||||
/// The state of the machine as bffh thinks the machine *should* be in.
|
/// The state of the machine as bffh thinks the machine *should* be in.
|
||||||
///
|
///
|
||||||
/// This is a Signal generator. Subscribers to this signal will be notified of changes. In the
|
/// This is a Signal generator. Subscribers to this signal will be notified of changes. In the
|
||||||
@ -195,13 +208,11 @@ pub struct Inner {
|
|||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
pub fn new ( id: MachineIdentifier
|
pub fn new ( id: MachineIdentifier
|
||||||
, desc: MachineDescription
|
|
||||||
, state: MachineState
|
, state: MachineState
|
||||||
) -> Inner
|
) -> Inner
|
||||||
{
|
{
|
||||||
Inner {
|
Inner {
|
||||||
id: id,
|
id,
|
||||||
desc: desc,
|
|
||||||
state: Mutable::new(state),
|
state: Mutable::new(state),
|
||||||
reset: None,
|
reset: None,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user