mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-22 14:57:56 +01:00
Api framework impl
This commit is contained in:
parent
999463e0e9
commit
df5ee9a0a1
@ -1,15 +1,25 @@
|
|||||||
use api::machine_capnp::machine::{
|
use crate::resources::modules::fabaccess::MachineState;
|
||||||
admin, admin::Server as AdminServer,
|
use crate::resources::Resource;
|
||||||
check, check::Server as CheckServer,
|
|
||||||
info, info::Server as InfoServer,
|
|
||||||
in_use as inuse, in_use::Server as InUseServer,
|
|
||||||
manage, manage::Server as ManageServer,
|
|
||||||
use_, use_::Server as UseServer,
|
|
||||||
};
|
|
||||||
use crate::session::SessionHandle;
|
use crate::session::SessionHandle;
|
||||||
|
use api::machine_capnp::machine::{
|
||||||
|
admin, admin::Server as AdminServer, check, check::Server as CheckServer, in_use as inuse,
|
||||||
|
in_use::Server as InUseServer, info, info::Server as InfoServer, manage,
|
||||||
|
manage::Server as ManageServer, use_, use_::Server as UseServer, Builder,
|
||||||
|
};
|
||||||
|
use capnp::capability::Promise;
|
||||||
|
use capnp_rpc::pry;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
session: SessionHandle,
|
session: SessionHandle,
|
||||||
|
resource: Resource,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Machine {
|
||||||
|
/// Builds a machine into the given builder. Re
|
||||||
|
pub fn build(session: SessionHandle, resource: Resource, builder: Builder) {
|
||||||
|
if resource.visible(&session) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InfoServer for Machine {
|
impl InfoServer for Machine {
|
||||||
@ -17,8 +27,8 @@ impl InfoServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: info::GetPropertyListParams,
|
_: info::GetPropertyListParams,
|
||||||
_: info::GetPropertyListResults,
|
_: info::GetPropertyListResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -26,38 +36,46 @@ impl InfoServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: info::GetReservationListParams,
|
_: info::GetReservationListParams,
|
||||||
_: info::GetReservationListResults,
|
_: info::GetReservationListResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UseServer for Machine {
|
impl UseServer for Machine {
|
||||||
fn use_(
|
fn use_(&mut self, _: use_::UseParams, _: use_::UseResults) -> Promise<(), ::capnp::Error> {
|
||||||
&mut self,
|
let resource = self.resource.clone();
|
||||||
_: use_::UseParams,
|
let session = self.session.clone();
|
||||||
_: use_::UseResults,
|
Promise::from_future(async move {
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
let user = session.get_user();
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
resource.try_update(session, MachineState::used(user)).await;
|
||||||
"method not implemented".to_string(),
|
Ok(())
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reserve(
|
fn reserve(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: use_::ReserveParams,
|
_: use_::ReserveParams,
|
||||||
_: use_::ReserveResults,
|
_: use_::ReserveResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let resource = self.resource.clone();
|
||||||
"method not implemented".to_string(),
|
let session = self.session.clone();
|
||||||
))
|
Promise::from_future(async move {
|
||||||
|
let user = session.get_user();
|
||||||
|
resource
|
||||||
|
.try_update(session, MachineState::reserved(user))
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reserveto(
|
fn reserveto(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: use_::ReservetoParams,
|
_: use_::ReservetoParams,
|
||||||
_: use_::ReservetoResults,
|
_: use_::ReservetoResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -68,17 +86,21 @@ impl InUseServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: inuse::GiveBackParams,
|
_: inuse::GiveBackParams,
|
||||||
_: inuse::GiveBackResults,
|
_: inuse::GiveBackResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let resource = self.resource.clone();
|
||||||
"method not implemented".to_string(),
|
let session = self.session.clone();
|
||||||
))
|
Promise::from_future(async move {
|
||||||
|
resource.give_back(session.clone()).await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_raw_data(
|
fn send_raw_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: inuse::SendRawDataParams,
|
_: inuse::SendRawDataParams,
|
||||||
_: inuse::SendRawDataResults,
|
_: inuse::SendRawDataResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -89,17 +111,18 @@ impl CheckServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: check::CheckParams,
|
_: check::CheckParams,
|
||||||
_: check::CheckResults,
|
_: check::CheckResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reject(
|
fn reject(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: check::RejectParams,
|
_: check::RejectParams,
|
||||||
_: check::RejectResults,
|
_: check::RejectResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -110,8 +133,8 @@ impl ManageServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: manage::GetMachineInfoExtendedParams,
|
_: manage::GetMachineInfoExtendedParams,
|
||||||
_: manage::GetMachineInfoExtendedResults,
|
_: manage::GetMachineInfoExtendedResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -119,8 +142,8 @@ impl ManageServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: manage::SetPropertyParams,
|
_: manage::SetPropertyParams,
|
||||||
_: manage::SetPropertyResults,
|
_: manage::SetPropertyResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -128,74 +151,104 @@ impl ManageServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: manage::RemovePropertyParams,
|
_: manage::RemovePropertyParams,
|
||||||
_: manage::RemovePropertyResults,
|
_: manage::RemovePropertyResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn force_use(
|
fn force_use(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::ForceUseParams,
|
_: manage::ForceUseParams,
|
||||||
_: manage::ForceUseResults,
|
_: manage::ForceUseResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let resource = self.resource.clone();
|
||||||
"method not implemented".to_string(),
|
let session = self.session.clone();
|
||||||
))
|
Promise::from_future(async move {
|
||||||
|
resource
|
||||||
|
.force_set(MachineState::used(session.get_user()))
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn force_free(
|
fn force_free(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::ForceFreeParams,
|
_: manage::ForceFreeParams,
|
||||||
_: manage::ForceFreeResults,
|
_: manage::ForceFreeResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let resource = self.resource.clone();
|
||||||
"method not implemented".to_string(),
|
let session = self.session.clone();
|
||||||
))
|
Promise::from_future(async move {
|
||||||
|
resource.force_set(MachineState::free()).await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn force_transfer(
|
fn force_transfer(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::ForceTransferParams,
|
_: manage::ForceTransferParams,
|
||||||
_: manage::ForceTransferResults,
|
_: manage::ForceTransferResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(
|
fn block(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::BlockParams,
|
_: manage::BlockParams,
|
||||||
_: manage::BlockResults,
|
_: manage::BlockResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let resource = self.resource.clone();
|
||||||
"method not implemented".to_string(),
|
let session = self.session.clone();
|
||||||
))
|
Promise::from_future(async move {
|
||||||
|
resource
|
||||||
|
.force_set(MachineState::blocked(session.get_user()))
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn disabled(
|
fn disabled(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::DisabledParams,
|
_: manage::DisabledParams,
|
||||||
_: manage::DisabledResults,
|
_: manage::DisabledResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let mut resource = self.resource.clone();
|
||||||
"method not implemented".to_string(),
|
Promise::from_future(async move {
|
||||||
))
|
resource.force_set(MachineState::disabled()).await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AdminServer for Machine {
|
impl AdminServer for Machine {
|
||||||
fn force_set_state(
|
fn force_set_state(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: admin::ForceSetStateParams,
|
params: admin::ForceSetStateParams,
|
||||||
_: admin::ForceSetStateResults,
|
_: admin::ForceSetStateResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
use api::schema::machine_capnp::machine::MachineState as APIMState;
|
||||||
"method not implemented".to_string(),
|
let user = self.session.get_user();
|
||||||
))
|
let state = match pry!(pry!(params.get()).get_state()) {
|
||||||
|
APIMState::Free => MachineState::free(),
|
||||||
|
APIMState::Blocked => MachineState::blocked(user),
|
||||||
|
APIMState::Disabled => MachineState::disabled(),
|
||||||
|
APIMState::InUse => MachineState::used(user),
|
||||||
|
APIMState::Reserved => MachineState::reserved(user),
|
||||||
|
APIMState::ToCheck => MachineState::check(user),
|
||||||
|
APIMState::Totakeover => return Promise::err(::capnp::Error::unimplemented(
|
||||||
|
"totakeover not implemented".to_string(),
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
self.resource.force_set(state);
|
||||||
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
fn force_set_user(
|
fn force_set_user(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: admin::ForceSetUserParams,
|
_: admin::ForceSetUserParams,
|
||||||
_: admin::ForceSetUserResults,
|
_: admin::ForceSetUserResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -203,8 +256,8 @@ impl AdminServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: admin::GetAdminPropertyListParams,
|
_: admin::GetAdminPropertyListParams,
|
||||||
_: admin::GetAdminPropertyListResults,
|
_: admin::GetAdminPropertyListResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -212,8 +265,8 @@ impl AdminServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: admin::SetAdminPropertyParams,
|
_: admin::SetAdminPropertyParams,
|
||||||
_: admin::SetAdminPropertyResults,
|
_: admin::SetAdminPropertyResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -221,8 +274,8 @@ impl AdminServer for Machine {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: admin::RemoveAdminPropertyParams,
|
_: admin::RemoveAdminPropertyParams,
|
||||||
_: admin::RemoveAdminPropertyResults,
|
_: admin::RemoveAdminPropertyResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
Promise::err(::capnp::Error::unimplemented(
|
||||||
"method not implemented".to_string(),
|
"method not implemented".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,29 @@ use api::machinesystem_capnp::machine_system::{
|
|||||||
info, InfoParams, InfoResults, Server as MachineSystem,
|
info, InfoParams, InfoResults, Server as MachineSystem,
|
||||||
};
|
};
|
||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
|
use capnp_rpc::pry;
|
||||||
|
use crate::capnp::machine::Machine;
|
||||||
|
use crate::resources::Resource;
|
||||||
|
use crate::resources::search::ResourcesHandle;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Machines {
|
pub struct Machines {
|
||||||
session: SessionHandle,
|
session: SessionHandle,
|
||||||
|
resources: ResourcesHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Machines {
|
impl Machines {
|
||||||
pub fn new(session: SessionHandle) -> Self {
|
pub fn new(session: SessionHandle) -> Self {
|
||||||
Self { session }
|
let resources = ResourcesHandle::new();
|
||||||
|
Self { session, resources }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineSystem for Machines {
|
impl MachineSystem for Machines {
|
||||||
fn info(&mut self, _: InfoParams, _: InfoResults) -> Promise<(), ::capnp::Error> {
|
fn info(&mut self, _: InfoParams, mut result: InfoResults) -> Promise<(), ::capnp::Error> {
|
||||||
Promise::err(::capnp::Error::unimplemented(
|
// TODO permission checking
|
||||||
"method not implemented".to_string(),
|
result.get().set_info(capnp_rpc::new_client(self.clone()));
|
||||||
))
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,28 +34,52 @@ impl info::Server for Machines {
|
|||||||
fn get_machine_list(
|
fn get_machine_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: info::GetMachineListParams,
|
_: info::GetMachineListParams,
|
||||||
_: info::GetMachineListResults,
|
mut result: info::GetMachineListResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
Promise::err(::capnp::Error::unimplemented(
|
let machine_list: Vec<(usize, &Resource)> = self.resources.list_all()
|
||||||
"method not implemented".to_string(),
|
.into_iter()
|
||||||
))
|
.filter(|resource| resource.visible(&self.session))
|
||||||
|
.enumerate()
|
||||||
|
.collect();
|
||||||
|
let mut builder = result.get().init_machine_list(machine_list.len() as u32);
|
||||||
|
for (i, m) in machine_list {
|
||||||
|
let resource = m.clone();
|
||||||
|
let mut mbuilder = builder.reborrow().get(i as u32);
|
||||||
|
Machine::build(self.session.clone(), resource, mbuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_machine(
|
fn get_machine(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: info::GetMachineParams,
|
params: info::GetMachineParams,
|
||||||
_: info::GetMachineResults,
|
mut result: info::GetMachineResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
Promise::err(::capnp::Error::unimplemented(
|
let params = pry!(params.get());
|
||||||
"method not implemented".to_string(),
|
let id = pry!(params.get_id());
|
||||||
))
|
|
||||||
|
if let Some(resource) = self.resources.get_by_id(id) {
|
||||||
|
let mut builder = result.get();
|
||||||
|
Machine::build(self.session.clone(), resource.clone(), builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_machine_u_r_n(
|
fn get_machine_u_r_n(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: info::GetMachineURNParams,
|
params: info::GetMachineURNParams,
|
||||||
_: info::GetMachineURNResults,
|
mut result: info::GetMachineURNResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
Promise::err(::capnp::Error::unimplemented(
|
let params = pry!(params.get());
|
||||||
"method not implemented".to_string(),
|
let urn = pry!(params.get_urn());
|
||||||
))
|
|
||||||
|
if let Some(resource) = self.resources.get_by_urn(urn) {
|
||||||
|
let mut builder = result.get();
|
||||||
|
Machine::build(self.session.clone(), resource.clone(), builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ use rkyv::Deserialize;
|
|||||||
use rkyv::ser::serializers::AlignedSerializer;
|
use rkyv::ser::serializers::AlignedSerializer;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::users::{User, UserDB};
|
use crate::users::db::{User, UserDB};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::resources::state::{OwnedEntry, State, db::StateDB};
|
use crate::resources::state::{OwnedEntry, State, db::StateDB};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
@ -5,7 +5,7 @@ use async_channel as channel;
|
|||||||
use async_oneshot as oneshot;
|
use async_oneshot as oneshot;
|
||||||
use futures_signals::signal::Signal;
|
use futures_signals::signal::Signal;
|
||||||
use futures_util::future::BoxFuture;
|
use futures_util::future::BoxFuture;
|
||||||
use crate::resources::{Error, Update};
|
use crate::resources::driver::{Error, Update};
|
||||||
use crate::resources::claim::{ResourceID, UserID};
|
use crate::resources::claim::{ResourceID, UserID};
|
||||||
use crate::resources::state::State;
|
use crate::resources::state::State;
|
||||||
|
|
||||||
|
@ -87,6 +87,8 @@ impl Diflouroborane {
|
|||||||
SIGTERM,
|
SIGTERM,
|
||||||
]).context("Failed to construct signal handler")?;
|
]).context("Failed to construct signal handler")?;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let tlsconfig = TlsConfig::new(config.tlskeylog.as_ref(), !config.is_quiet())?;
|
let tlsconfig = TlsConfig::new(config.tlskeylog.as_ref(), !config.is_quiet())?;
|
||||||
let acceptor = tlsconfig.make_tls_acceptor(&config.tlsconfig)?;
|
let acceptor = tlsconfig.make_tls_acceptor(&config.tlsconfig)?;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use async_channel::Sender;
|
use async_channel::Sender;
|
||||||
use lmdb::Environment;
|
use lmdb::Environment;
|
||||||
use crate::resources::Update;
|
use crate::resources::driver::Update;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// Database of currently valid claims, interests and notify, as far as applicable
|
/// Database of currently valid claims, interests and notify, as far as applicable
|
||||||
|
140
bffhd/resources/driver.rs
Normal file
140
bffhd/resources/driver.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use futures_signals::signal::Mutable;
|
||||||
|
use async_oneshot::Sender;
|
||||||
|
use async_channel::Receiver;
|
||||||
|
|
||||||
|
use super::state::State;
|
||||||
|
use super::state::db::StateAccessor;
|
||||||
|
|
||||||
|
/// A resources in BFFH has to contain several different parts;
|
||||||
|
/// - Currently set state
|
||||||
|
/// - Execution state of attached actors (⇒ BFFH's job)
|
||||||
|
/// - Output of interal logic of a resources
|
||||||
|
/// ⇒ Resource logic gets read access to set state and write access to output state.
|
||||||
|
/// ⇒ state `update` happens via resources logic. This logic should do access control. If the update
|
||||||
|
/// succeeds then BFFH stores those input parameters ("set" state) and results / output state.
|
||||||
|
/// Storing input parameters is relevant so that BFFH can know that an "update" is a no-op
|
||||||
|
/// without having to run the module code.
|
||||||
|
/// ⇒ in fact actors only really care about the output state, and shouldn't (need to) see "set"
|
||||||
|
/// state.
|
||||||
|
/// ⇒ example reserving:
|
||||||
|
/// - Claimant sends 'update' message with a new state
|
||||||
|
/// - Doesn't set the state until `update` has returned Ok.
|
||||||
|
/// - This runs the `update` function with that new state and the claimants user context returning
|
||||||
|
/// either an Ok or an Error.
|
||||||
|
/// - Error is returned to Claimant to show user, stop.
|
||||||
|
/// - On ok:
|
||||||
|
/// - Commit new "set" state, storing it and making it visible to all other claimants
|
||||||
|
/// - Commit new output state, storing it and notifying all connected actors / Notify
|
||||||
|
/// ⇒ BFFHs job in this whole ordeal is:
|
||||||
|
/// - Message passing primitives so that update message are queued
|
||||||
|
/// - As reliable as possible storage system for input and output state
|
||||||
|
/// - Again message passing so that updates are broadcasted to all Notify and Actors.
|
||||||
|
/// ⇒ Resource module's job is:
|
||||||
|
/// - Validating updates semantically i.e. are the types correct
|
||||||
|
/// - Check authorization of updates i.e. is this user allowed to do that
|
||||||
|
#[async_trait]
|
||||||
|
pub trait ResourceModel: Debug {
|
||||||
|
/// Run whatever internal logic this resources has for the given State update, and return the
|
||||||
|
/// new output state that this update produces.
|
||||||
|
async fn on_update(&mut self, input: &State) -> Result<State, Error>;
|
||||||
|
async fn shutdown(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Passthrough;
|
||||||
|
#[async_trait]
|
||||||
|
impl ResourceModel for Passthrough {
|
||||||
|
async fn on_update(&mut self, input: &State) -> Result<State, Error> {
|
||||||
|
Ok(input.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn shutdown(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error type a resources implementation can produce
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Internal(Box<dyn std::error::Error + Send>),
|
||||||
|
Denied,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: more message context
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Update {
|
||||||
|
pub state: State,
|
||||||
|
pub errchan: Sender<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ResourceDriver {
|
||||||
|
// putput
|
||||||
|
res: Box<dyn ResourceModel>,
|
||||||
|
|
||||||
|
// input
|
||||||
|
rx: Receiver<Update>,
|
||||||
|
|
||||||
|
// output
|
||||||
|
db: StateAccessor,
|
||||||
|
|
||||||
|
signal: Mutable<State>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceDriver {
|
||||||
|
pub async fn drive_to_end(&mut self) {
|
||||||
|
while let Ok(update) = self.rx.recv().await {
|
||||||
|
let state = update.state;
|
||||||
|
let mut errchan = update.errchan;
|
||||||
|
|
||||||
|
match self.res.on_update(&state).await {
|
||||||
|
Ok(outstate) => {
|
||||||
|
// FIXME: Send any error here to some global error collector. A failed write to
|
||||||
|
// the DB is not necessarily fatal, but it means that BFFH is now in an
|
||||||
|
// inconsistent state until a future update succeeds with writing to the DB.
|
||||||
|
// Not applying the new state isn't correct either since we don't know what the
|
||||||
|
// internal logic of the resources has done to make this happen.
|
||||||
|
// Another half right solution is to unwrap and recreate everything.
|
||||||
|
// "Best" solution would be to tell the resources to rollback their interal
|
||||||
|
// changes on a fatal failure and then notify the Claimant, while simply trying
|
||||||
|
// again for temporary failures.
|
||||||
|
let _ = self.db.set(&state, &outstate);
|
||||||
|
self.signal.set(outstate);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
let _ = errchan.send(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::Poll;
|
||||||
|
use std::future::Future;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[futures_test::test]
|
||||||
|
async fn test_passthrough_is_id() {
|
||||||
|
let inp = state::tests::gen_random();
|
||||||
|
|
||||||
|
let mut res = Passthrough;
|
||||||
|
let out = res.on_update(&inp).await.unwrap();
|
||||||
|
assert_eq!(inp, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_passthrough_is_always_ready() {
|
||||||
|
let inp = State::build().finish();
|
||||||
|
|
||||||
|
let mut res = Passthrough;
|
||||||
|
let mut cx = futures_test::task::panic_context();
|
||||||
|
if let Poll::Ready(_) = Pin::new(&mut res.on_update(&inp)).poll(&mut cx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
panic!("Passthrough returned Poll::Pending")
|
||||||
|
}
|
||||||
|
}
|
@ -1,145 +1,113 @@
|
|||||||
use std::fmt::Debug;
|
use crate::resources::modules::fabaccess::{MachineState, Status};
|
||||||
use async_trait::async_trait;
|
use crate::resources::state::State;
|
||||||
|
use crate::session::SessionHandle;
|
||||||
|
use crate::users::User;
|
||||||
|
|
||||||
use futures_signals::signal::Mutable;
|
|
||||||
use async_oneshot::Sender;
|
|
||||||
use async_channel::Receiver;
|
|
||||||
|
|
||||||
use state::State;
|
|
||||||
use state::db::StateAccessor;
|
|
||||||
|
|
||||||
pub mod state;
|
|
||||||
pub mod claim;
|
pub mod claim;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
|
pub mod driver;
|
||||||
|
pub mod search;
|
||||||
|
pub mod state;
|
||||||
|
|
||||||
|
pub mod modules;
|
||||||
|
|
||||||
/// A resources in BFFH has to contain several different parts;
|
pub struct PermissionDenied;
|
||||||
/// - Currently set state
|
|
||||||
/// - Execution state of attached actors (⇒ BFFH's job)
|
|
||||||
/// - Output of interal logic of a resources
|
|
||||||
/// ⇒ Resource logic gets read access to set state and write access to output state.
|
|
||||||
/// ⇒ state `update` happens via resources logic. This logic should do access control. If the update
|
|
||||||
/// succeeds then BFFH stores those input parameters ("set" state) and results / output state.
|
|
||||||
/// Storing input parameters is relevant so that BFFH can know that an "update" is a no-op
|
|
||||||
/// without having to run the module code.
|
|
||||||
/// ⇒ in fact actors only really care about the output state, and shouldn't (need to) see "set"
|
|
||||||
/// state.
|
|
||||||
/// ⇒ example reserving:
|
|
||||||
/// - Claimant sends 'update' message with a new state
|
|
||||||
/// - Doesn't set the state until `update` has returned Ok.
|
|
||||||
/// - This runs the `update` function with that new state and the claimants user context returning
|
|
||||||
/// either an Ok or an Error.
|
|
||||||
/// - Error is returned to Claimant to show user, stop.
|
|
||||||
/// - On ok:
|
|
||||||
/// - Commit new "set" state, storing it and making it visible to all other claimants
|
|
||||||
/// - Commit new output state, storing it and notifying all connected actors / Notify
|
|
||||||
/// ⇒ BFFHs job in this whole ordeal is:
|
|
||||||
/// - Message passing primitives so that update message are queued
|
|
||||||
/// - As reliable as possible storage system for input and output state
|
|
||||||
/// - Again message passing so that updates are broadcasted to all Notify and Actors.
|
|
||||||
/// ⇒ Resource module's job is:
|
|
||||||
/// - Validating updates semantically i.e. are the types correct
|
|
||||||
/// - Check authorization of updates i.e. is this user allowed to do that
|
|
||||||
#[async_trait]
|
|
||||||
pub trait ResourceModel: Debug {
|
|
||||||
/// Run whatever internal logic this resources has for the given State update, and return the
|
|
||||||
/// new output state that this update produces.
|
|
||||||
async fn on_update(&mut self, input: &State) -> Result<State, Error>;
|
|
||||||
async fn shutdown(&mut self);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone)]
|
||||||
pub struct Passthrough;
|
pub struct Resource {}
|
||||||
#[async_trait]
|
|
||||||
impl ResourceModel for Passthrough {
|
impl Resource {
|
||||||
async fn on_update(&mut self, input: &State) -> Result<State, Error> {
|
pub fn get_state(&self) -> MachineState {
|
||||||
Ok(input.clone())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown(&mut self) {}
|
fn set_state(&self, state: MachineState) {
|
||||||
}
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Error type a resources implementation can produce
|
fn set_previous_user(&self, user: User) {
|
||||||
#[derive(Debug)]
|
unimplemented!()
|
||||||
pub enum Error {
|
}
|
||||||
Internal(Box<dyn std::error::Error + Send>),
|
|
||||||
Denied,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: more message context
|
pub async fn try_update(&self, session: SessionHandle, new: MachineState) {
|
||||||
#[derive(Debug)]
|
let old = self.get_state();
|
||||||
pub struct Update {
|
let user = session.get_user();
|
||||||
pub state: State,
|
|
||||||
pub errchan: Sender<Error>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
if session.has_manage(self) // Default allow for managers
|
||||||
pub struct ResourceDriver {
|
|
||||||
// putput
|
|
||||||
res: Box<dyn ResourceModel>,
|
|
||||||
|
|
||||||
// input
|
|| (session.has_write(self) // Decision tree for writers
|
||||||
rx: Receiver<Update>,
|
&& match (old.state, &new.state) {
|
||||||
|
// Going from available to used by the person requesting is okay.
|
||||||
|
(Status::Free, Status::InUse(who))
|
||||||
|
// Check that the person requesting does not request for somebody else.
|
||||||
|
// *That* is manage privilege.
|
||||||
|
if who == &user => true,
|
||||||
|
|
||||||
// output
|
// Reserving things for ourself is okay.
|
||||||
db: StateAccessor,
|
(Status::Free, Status::Reserved(whom))
|
||||||
|
if &user == whom => true,
|
||||||
|
|
||||||
signal: Mutable<State>,
|
// Returning things we've been using is okay. This includes both if
|
||||||
}
|
// they're being freed or marked as to be checked.
|
||||||
|
(Status::InUse(who), Status::Free | Status::ToCheck(_))
|
||||||
|
if who == user => true,
|
||||||
|
|
||||||
impl ResourceDriver {
|
// Un-reserving things we reserved is okay
|
||||||
pub async fn drive_to_end(&mut self) {
|
(Status::Reserved(whom), Status::Free)
|
||||||
while let Ok(update) = self.rx.recv().await {
|
if user == whom => true,
|
||||||
let state = update.state;
|
// Using things that we've reserved is okay. But the person requesting
|
||||||
let mut errchan = update.errchan;
|
// that has to be the person that reserved the machine. Otherwise
|
||||||
|
// somebody could make a machine reserved by a different user as used by
|
||||||
|
// that different user but use it themself.
|
||||||
|
(Status::Reserved(whom), Status::InUse(who))
|
||||||
|
if user == whom && who == &whom => true,
|
||||||
|
|
||||||
match self.res.on_update(&state).await {
|
// Default is deny.
|
||||||
Ok(outstate) => {
|
_ => false
|
||||||
// FIXME: Send any error here to some global error collector. A failed write to
|
})
|
||||||
// the DB is not necessarily fatal, but it means that BFFH is now in an
|
|
||||||
// inconsistent state until a future update succeeds with writing to the DB.
|
// Default permissions everybody has
|
||||||
// Not applying the new state isn't correct either since we don't know what the
|
|| match (old.state, &new.state) {
|
||||||
// internal logic of the resources has done to make this happen.
|
// Returning things we've been using is okay. This includes both if
|
||||||
// Another half right solution is to unwrap and recreate everything.
|
// they're being freed or marked as to be checked.
|
||||||
// "Best" solution would be to tell the resources to rollback their interal
|
(Status::InUse(who), Status::Free | Status::ToCheck(_)) if who == user => true,
|
||||||
// changes on a fatal failure and then notify the Claimant, while simply trying
|
|
||||||
// again for temporary failures.
|
// Un-reserving things we reserved is okay
|
||||||
let _ = self.db.set(&state, &outstate);
|
(Status::Reserved(whom), Status::Free) if user == whom => true,
|
||||||
self.signal.set(outstate);
|
|
||||||
},
|
// Default is deny.
|
||||||
Err(e) => {
|
_ => false,
|
||||||
let _ = errchan.send(e);
|
}
|
||||||
}
|
{
|
||||||
|
self.set_state(new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn give_back(&self, session: SessionHandle) {
|
||||||
|
if let Status::InUse(user) = self.get_state().state {
|
||||||
|
if user == session.get_user() {
|
||||||
|
self.set_state(MachineState::free());
|
||||||
|
self.set_previous_user(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
pub async fn force_set(&self, new: MachineState) {
|
||||||
mod tests {
|
unimplemented!()
|
||||||
use std::pin::Pin;
|
|
||||||
use std::task::Poll;
|
|
||||||
use std::future::Future;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[futures_test::test]
|
|
||||||
async fn test_passthrough_is_id() {
|
|
||||||
let inp = state::tests::gen_random();
|
|
||||||
|
|
||||||
let mut res = Passthrough;
|
|
||||||
let out = res.on_update(&inp).await.unwrap();
|
|
||||||
assert_eq!(inp, out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn visible(&self, session: &SessionHandle) -> bool {
|
||||||
fn test_passthrough_is_always_ready() {
|
session.has_disclose(self) || self.is_owned_by(session.get_user())
|
||||||
let inp = State::build().finish();
|
}
|
||||||
|
|
||||||
let mut res = Passthrough;
|
pub fn is_owned_by(&self, owner: User) -> bool {
|
||||||
let mut cx = futures_test::task::panic_context();
|
match self.get_state().state {
|
||||||
if let Poll::Ready(_) = Pin::new(&mut res.on_update(&inp)).poll(&mut cx) {
|
Status::Free | Status::Disabled => false,
|
||||||
return;
|
|
||||||
|
Status::InUse(user)
|
||||||
|
| Status::ToCheck(user)
|
||||||
|
| Status::Blocked(user)
|
||||||
|
| Status::Reserved(user) => user == owner,
|
||||||
}
|
}
|
||||||
panic!("Passthrough returned Poll::Pending")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
114
bffhd/resources/modules/fabaccess.rs
Normal file
114
bffhd/resources/modules/fabaccess.rs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
use crate::utils::oid::ObjectIdentifier;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
|
use rkyv_dyn::{DynError, DynSerializer};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::oidvalue;
|
||||||
|
use crate::session::SessionHandle;
|
||||||
|
use crate::users::User;
|
||||||
|
|
||||||
|
/// Status of a Machine
|
||||||
|
#[derive(
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Debug,
|
||||||
|
Archive,
|
||||||
|
rkyv::Serialize,
|
||||||
|
rkyv::Deserialize,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
)]
|
||||||
|
#[archive_attr(derive(Debug, PartialEq, serde::Serialize, serde::Deserialize))]
|
||||||
|
pub enum Status {
|
||||||
|
/// Not currently used by anybody
|
||||||
|
Free,
|
||||||
|
/// Used by somebody
|
||||||
|
InUse(User),
|
||||||
|
/// Was used by somebody and now needs to be checked for cleanliness
|
||||||
|
ToCheck(User),
|
||||||
|
/// Not used by anybody but also can not be used. E.g. down for maintenance
|
||||||
|
Blocked(User),
|
||||||
|
/// Disabled for some other reason
|
||||||
|
Disabled,
|
||||||
|
/// Reserved
|
||||||
|
Reserved(User),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Debug,
|
||||||
|
Archive,
|
||||||
|
rkyv::Serialize,
|
||||||
|
rkyv::Deserialize,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
)]
|
||||||
|
#[archive_attr(derive(Debug, PartialEq, serde::Serialize, serde::Deserialize))]
|
||||||
|
/// The status of the machine
|
||||||
|
pub struct MachineState {
|
||||||
|
pub state: Status,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MachineState {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::Free,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from(state: Status) -> Self {
|
||||||
|
Self { state }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free() -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::Free,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn used(user: User) -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::InUse(user),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn blocked(user: User) -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::Blocked(user),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disabled() -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::Disabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reserved(user: User) -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::Reserved(user),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check(user: User) -> Self {
|
||||||
|
Self {
|
||||||
|
state: Status::ToCheck(user),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_used(&mut self, session: SessionHandle) -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static OID_TYPE: Lazy<ObjectIdentifier> =
|
||||||
|
Lazy::new(|| ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.14").unwrap());
|
||||||
|
static OID_VALUE: Lazy<ObjectIdentifier> =
|
||||||
|
Lazy::new(|| ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.2.4").unwrap());
|
||||||
|
oidvalue!(OID_TYPE, MachineState, ArchivedMachineState);
|
2
bffhd/resources/modules/mod.rs
Normal file
2
bffhd/resources/modules/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
pub mod fabaccess;
|
38
bffhd/resources/search.rs
Normal file
38
bffhd/resources/search.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use crate::resources::Resource;
|
||||||
|
|
||||||
|
struct Inner {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Inner {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ResourcesHandle {
|
||||||
|
inner: Arc<Inner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourcesHandle {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: Arc::new(Inner::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_all(&self) -> impl IntoIterator<Item=&Resource> {
|
||||||
|
unimplemented!();
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_by_id(&self, id: &str) -> Option<&Resource> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_by_urn(&self, urn: &str) -> Option<&Resource> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,21 @@
|
|||||||
use std::{
|
use std::{any::Any, fmt, hash::Hash, ptr, str::FromStr};
|
||||||
fmt,
|
|
||||||
ptr,
|
|
||||||
any::Any,
|
|
||||||
hash::Hash,
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized, };
|
|
||||||
use rkyv_dyn::{DynSerializer, DynError, DynDeserializer};
|
|
||||||
use rkyv_typename::TypeName;
|
|
||||||
use ptr_meta::{DynMetadata, Pointee};
|
use ptr_meta::{DynMetadata, Pointee};
|
||||||
|
use rkyv::{
|
||||||
|
out_field, Archive, ArchivePointee, ArchiveUnsized, Archived, ArchivedMetadata, Deserialize,
|
||||||
|
DeserializeUnsized, Fallible, Serialize, SerializeUnsized,
|
||||||
|
};
|
||||||
|
use rkyv_dyn::{DynDeserializer, DynError, DynSerializer};
|
||||||
|
use rkyv_typename::TypeName;
|
||||||
|
|
||||||
use inventory;
|
|
||||||
use crate::utils::oid::ObjectIdentifier;
|
use crate::utils::oid::ObjectIdentifier;
|
||||||
use rkyv::ser::{Serializer, ScratchSpace};
|
use inventory;
|
||||||
use std::collections::HashMap;
|
use rkyv::ser::{ScratchSpace, Serializer};
|
||||||
use std::alloc::Layout;
|
|
||||||
use serde::ser::SerializeMap;
|
|
||||||
use std::fmt::Formatter;
|
|
||||||
use serde::de::Error as SerdeError;
|
use serde::de::Error as SerdeError;
|
||||||
|
use serde::ser::SerializeMap;
|
||||||
|
use std::alloc::Layout;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Formatter;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
/// Adding a custom type to BFFH state management:
|
/// Adding a custom type to BFFH state management:
|
||||||
@ -28,7 +25,7 @@ use std::mem::MaybeUninit;
|
|||||||
/// 2. Implement rkyv's [`Serialize`](rkyv::Serialize).
|
/// 2. Implement rkyv's [`Serialize`](rkyv::Serialize).
|
||||||
/// 3. Implement TypeOid on your Archived type (i.e. `<T as Archive>::Archived`)
|
/// 3. Implement TypeOid on your Archived type (i.e. `<T as Archive>::Archived`)
|
||||||
/// 4. Implement this
|
/// 4. Implement this
|
||||||
pub trait Value: Any + fmt::Debug + erased_serde::Serialize + Sync {
|
pub trait Value: Any + fmt::Debug + erased_serde::Serialize + Sync {
|
||||||
/// Initialize `&mut self` from `deserializer`
|
/// Initialize `&mut self` from `deserializer`
|
||||||
///
|
///
|
||||||
/// At the point this is called &mut self is of undefined value but guaranteed to be well
|
/// At the point this is called &mut self is of undefined value but guaranteed to be well
|
||||||
@ -37,8 +34,10 @@ pub trait Value: Any + fmt::Debug + erased_serde::Serialize + Sync {
|
|||||||
/// To this end you *must* initialize `self` **completely**. Serde will do the right thing if
|
/// To this end you *must* initialize `self` **completely**. Serde will do the right thing if
|
||||||
/// you directly deserialize the type you're implementing `Value` for, but for manual
|
/// you directly deserialize the type you're implementing `Value` for, but for manual
|
||||||
/// implementations this is important to keep in mind.
|
/// implementations this is important to keep in mind.
|
||||||
fn deserialize_init<'de>(&mut self, deserializer: &mut dyn erased_serde::Deserializer<'de>)
|
fn deserialize_init<'de>(
|
||||||
-> Result<(), erased_serde::Error>;
|
&mut self,
|
||||||
|
deserializer: &mut dyn erased_serde::Deserializer<'de>,
|
||||||
|
) -> Result<(), erased_serde::Error>;
|
||||||
|
|
||||||
/// Implement `PartialEq` dynamically.
|
/// Implement `PartialEq` dynamically.
|
||||||
///
|
///
|
||||||
@ -55,19 +54,27 @@ erased_serde::serialize_trait_object!(SerializeValue);
|
|||||||
erased_serde::serialize_trait_object!(DeserializeValue);
|
erased_serde::serialize_trait_object!(DeserializeValue);
|
||||||
|
|
||||||
impl<T> Value for T
|
impl<T> Value for T
|
||||||
where T: Any + fmt::Debug + PartialEq + Sync
|
where
|
||||||
+ erased_serde::Serialize
|
T: Any
|
||||||
+ for<'de> serde::Deserialize<'de>
|
+ fmt::Debug
|
||||||
|
+ PartialEq
|
||||||
|
+ Sync
|
||||||
|
+ erased_serde::Serialize
|
||||||
|
+ for<'de> serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn deserialize_init<'de>(&mut self, deserializer: &mut dyn erased_serde::Deserializer<'de>)
|
fn deserialize_init<'de>(
|
||||||
-> Result<(), erased_serde::Error>
|
&mut self,
|
||||||
{
|
deserializer: &mut dyn erased_serde::Deserializer<'de>,
|
||||||
|
) -> Result<(), erased_serde::Error> {
|
||||||
*self = erased_serde::deserialize(deserializer)?;
|
*self = erased_serde::deserialize(deserializer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dyn_eq(&self, other: &dyn Value) -> bool {
|
fn dyn_eq(&self, other: &dyn Value) -> bool {
|
||||||
other.as_any().downcast_ref().map_or(false, |other: &T| other == self)
|
other
|
||||||
|
.as_any()
|
||||||
|
.downcast_ref()
|
||||||
|
.map_or(false, |other: &T| other == self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_value(&self) -> &dyn Value {
|
fn as_value(&self) -> &dyn Value {
|
||||||
@ -89,7 +96,8 @@ impl PartialEq for dyn Value {
|
|||||||
pub(super) struct DynVal<'a>(pub &'a dyn SerializeValue);
|
pub(super) struct DynVal<'a>(pub &'a dyn SerializeValue);
|
||||||
impl<'a> serde::Serialize for DynVal<'a> {
|
impl<'a> serde::Serialize for DynVal<'a> {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where S: serde::Serializer
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
let mut ser = serializer.serialize_map(Some(1))?;
|
let mut ser = serializer.serialize_map(Some(1))?;
|
||||||
let oid = self.0.archived_type_oid();
|
let oid = self.0.archived_type_oid();
|
||||||
@ -101,7 +109,8 @@ impl<'a> serde::Serialize for DynVal<'a> {
|
|||||||
pub(super) struct DynOwnedVal(pub Box<dyn SerializeValue>);
|
pub(super) struct DynOwnedVal(pub Box<dyn SerializeValue>);
|
||||||
impl<'de> serde::Deserialize<'de> for DynOwnedVal {
|
impl<'de> serde::Deserialize<'de> for DynOwnedVal {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where D: serde::Deserializer<'de>
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_map(DynValVisitor)
|
deserializer.deserialize_map(DynValVisitor)
|
||||||
}
|
}
|
||||||
@ -116,22 +125,21 @@ impl<'de> serde::de::Visitor<'de> for DynValVisitor {
|
|||||||
write!(formatter, "an one entry map from OID to some value object")
|
write!(formatter, "an one entry map from OID to some value object")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<A: serde::de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error>
|
fn visit_map<A: serde::de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
|
||||||
{
|
|
||||||
// Bad magic code. Problem we have to solve: We only know how to parse whatever comes
|
// Bad magic code. Problem we have to solve: We only know how to parse whatever comes
|
||||||
// after the OID after having looked at the OID. We have zero static type info available
|
// after the OID after having looked at the OID. We have zero static type info available
|
||||||
// during deserialization. So:
|
// during deserialization. So:
|
||||||
|
|
||||||
// Get OID first. That's easy, we know it's the key, we know how to read it.
|
// Get OID first. That's easy, we know it's the key, we know how to read it.
|
||||||
let oid: ObjectIdentifier = map.next_key()?
|
let oid: ObjectIdentifier = map.next_key()?.ok_or(A::Error::missing_field("oid"))?;
|
||||||
.ok_or(A::Error::missing_field("oid"))?;
|
|
||||||
|
|
||||||
// Get the Value vtable for that OID. Or fail because we don't know that OID, either works.
|
// Get the Value vtable for that OID. Or fail because we don't know that OID, either works.
|
||||||
let valimpl = IMPL_REGISTRY.get(ImplId::from_type_oid(&oid))
|
let valimpl = IMPL_REGISTRY.get(ImplId::from_type_oid(&oid)).ok_or(
|
||||||
.ok_or(serde::de::Error::invalid_value(
|
serde::de::Error::invalid_value(
|
||||||
serde::de::Unexpected::Other("unknown oid"),
|
serde::de::Unexpected::Other("unknown oid"),
|
||||||
&"oid an implementation was registered for",
|
&"oid an implementation was registered for",
|
||||||
))?;
|
),
|
||||||
|
)?;
|
||||||
|
|
||||||
// Casting random usize you find on the side of the road as vtable on unchecked pointers.
|
// Casting random usize you find on the side of the road as vtable on unchecked pointers.
|
||||||
// What could possibly go wrong? >:D
|
// What could possibly go wrong? >:D
|
||||||
@ -151,9 +159,7 @@ impl<'de> serde::de::Visitor<'de> for DynValVisitor {
|
|||||||
// validate in any other way if this is sane?
|
// validate in any other way if this is sane?
|
||||||
// Well...
|
// Well...
|
||||||
let ptr: *mut () = std::alloc::alloc(layout).cast::<()>();
|
let ptr: *mut () = std::alloc::alloc(layout).cast::<()>();
|
||||||
let b = Box::from_raw(ptr_meta::from_raw_parts_mut(
|
let b = Box::from_raw(ptr_meta::from_raw_parts_mut(ptr, meta));
|
||||||
ptr,
|
|
||||||
meta));
|
|
||||||
|
|
||||||
// We make this a MaybeUninit so `Drop` is never called on the uninitialized value
|
// We make this a MaybeUninit so `Drop` is never called on the uninitialized value
|
||||||
MaybeUninit::new(b)
|
MaybeUninit::new(b)
|
||||||
@ -173,7 +179,8 @@ impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf {
|
|||||||
type Value = Box<dyn SerializeValue>;
|
type Value = Box<dyn SerializeValue>;
|
||||||
|
|
||||||
fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error>
|
fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
where D: serde::Deserializer<'de>
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let mut deser = <dyn erased_serde::Deserializer>::erase(deserializer);
|
let mut deser = <dyn erased_serde::Deserializer>::erase(deserializer);
|
||||||
|
|
||||||
@ -182,8 +189,9 @@ impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf {
|
|||||||
let selfptr = unsafe { &mut *self.0.as_mut_ptr() };
|
let selfptr = unsafe { &mut *self.0.as_mut_ptr() };
|
||||||
|
|
||||||
// Hey, better initialize late than never.
|
// Hey, better initialize late than never.
|
||||||
selfptr.deserialize_init(&mut deser).map_err(|e|
|
selfptr
|
||||||
D::Error::custom(e))?;
|
.deserialize_init(&mut deser)
|
||||||
|
.map_err(|e| D::Error::custom(e))?;
|
||||||
|
|
||||||
// Assuming `deserialize_init` didn't error and did its job this is now safe.
|
// Assuming `deserialize_init` didn't error and did its job this is now safe.
|
||||||
unsafe { Ok(self.0.assume_init()) }
|
unsafe { Ok(self.0.assume_init()) }
|
||||||
@ -208,7 +216,6 @@ impl<S: ScratchSpace + Serializer + ?Sized> SerializeUnsized<S> for dyn Serializ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Serialize dynamic types by storing an OID alongside
|
/// Serialize dynamic types by storing an OID alongside
|
||||||
pub trait SerializeDynOid {
|
pub trait SerializeDynOid {
|
||||||
fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError>;
|
fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError>;
|
||||||
@ -216,8 +223,9 @@ pub trait SerializeDynOid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SerializeDynOid for T
|
impl<T> SerializeDynOid for T
|
||||||
where T: for<'a> Serialize<dyn DynSerializer + 'a>,
|
where
|
||||||
T::Archived: TypeOid,
|
T: for<'a> Serialize<dyn DynSerializer + 'a>,
|
||||||
|
T::Archived: TypeOid,
|
||||||
{
|
{
|
||||||
fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError> {
|
fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError> {
|
||||||
serializer.serialize_value(self)
|
serializer.serialize_value(self)
|
||||||
@ -247,8 +255,8 @@ pub trait SerializeValue: Value + SerializeDynOid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Archive + Value + SerializeDynOid + Clone> SerializeValue for T
|
impl<T: Archive + Value + SerializeDynOid + Clone> SerializeValue for T
|
||||||
where
|
where
|
||||||
T::Archived: RegisteredImpl
|
T::Archived: RegisteredImpl,
|
||||||
{
|
{
|
||||||
fn dyn_clone(&self) -> Box<dyn SerializeValue> {
|
fn dyn_clone(&self) -> Box<dyn SerializeValue> {
|
||||||
Box::new(self.clone())
|
Box::new(self.clone())
|
||||||
@ -278,17 +286,21 @@ impl ArchivePointee for dyn DeserializeValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<D: Fallible + ?Sized> DeserializeUnsized<dyn SerializeValue, D> for dyn DeserializeValue {
|
impl<D: Fallible + ?Sized> DeserializeUnsized<dyn SerializeValue, D> for dyn DeserializeValue {
|
||||||
unsafe fn deserialize_unsized(&self,
|
unsafe fn deserialize_unsized(
|
||||||
mut deserializer: &mut D,
|
&self,
|
||||||
mut alloc: impl FnMut(Layout) -> *mut u8
|
mut deserializer: &mut D,
|
||||||
|
mut alloc: impl FnMut(Layout) -> *mut u8,
|
||||||
) -> Result<*mut (), D::Error> {
|
) -> Result<*mut (), D::Error> {
|
||||||
self.deserialize_dynoid(&mut deserializer, &mut alloc).map_err(|e| *e.downcast().unwrap())
|
self.deserialize_dynoid(&mut deserializer, &mut alloc)
|
||||||
|
.map_err(|e| *e.downcast().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_metadata(&self, mut deserializer: &mut D)
|
fn deserialize_metadata(
|
||||||
-> Result<<dyn SerializeValue as Pointee>::Metadata, D::Error>
|
&self,
|
||||||
{
|
mut deserializer: &mut D,
|
||||||
self.deserialize_dynoid_metadata(&mut deserializer).map_err(|e| *e.downcast().unwrap())
|
) -> Result<<dyn SerializeValue as Pointee>::Metadata, D::Error> {
|
||||||
|
self.deserialize_dynoid_metadata(&mut deserializer)
|
||||||
|
.map_err(|e| *e.downcast().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +308,12 @@ impl ArchiveUnsized for dyn SerializeValue {
|
|||||||
type Archived = dyn DeserializeValue;
|
type Archived = dyn DeserializeValue;
|
||||||
type MetadataResolver = <ObjectIdentifier as Archive>::Resolver;
|
type MetadataResolver = <ObjectIdentifier as Archive>::Resolver;
|
||||||
|
|
||||||
unsafe fn resolve_metadata(&self, pos: usize, resolver: Self::MetadataResolver, out: *mut ArchivedMetadata<Self>) {
|
unsafe fn resolve_metadata(
|
||||||
|
&self,
|
||||||
|
pos: usize,
|
||||||
|
resolver: Self::MetadataResolver,
|
||||||
|
out: *mut ArchivedMetadata<Self>,
|
||||||
|
) {
|
||||||
let (oid_pos, oid) = out_field!(out.type_oid);
|
let (oid_pos, oid) = out_field!(out.type_oid);
|
||||||
let type_oid = self.archived_type_oid();
|
let type_oid = self.archived_type_oid();
|
||||||
type_oid.resolve(pos + oid_pos, resolver, oid);
|
type_oid.resolve(pos + oid_pos, resolver, oid);
|
||||||
@ -316,10 +333,14 @@ impl ArchivedValueMetadata {
|
|||||||
|
|
||||||
pub fn vtable(&self) -> usize {
|
pub fn vtable(&self) -> usize {
|
||||||
IMPL_REGISTRY
|
IMPL_REGISTRY
|
||||||
.get(ImplId::from_type_oid(&self.type_oid)).expect(&format!("Unregistered \
|
.get(ImplId::from_type_oid(&self.type_oid))
|
||||||
|
.expect(&format!(
|
||||||
|
"Unregistered \
|
||||||
type \
|
type \
|
||||||
oid \
|
oid \
|
||||||
{:?}", self.type_oid))
|
{:?}",
|
||||||
|
self.type_oid
|
||||||
|
))
|
||||||
.vtable
|
.vtable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +363,7 @@ impl<'a> ImplId<'a> {
|
|||||||
impl ImplId<'static> {
|
impl ImplId<'static> {
|
||||||
fn new<T: TypeOid>() -> Self {
|
fn new<T: TypeOid>() -> Self {
|
||||||
Self {
|
Self {
|
||||||
type_oid: &T::type_oid()
|
type_oid: &T::type_oid(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,15 +383,6 @@ pub struct ImplDebugInfo {
|
|||||||
pub line: u32,
|
pub line: u32,
|
||||||
pub column: u32,
|
pub column: u32,
|
||||||
}
|
}
|
||||||
macro_rules! debug_info {
|
|
||||||
() => {
|
|
||||||
ImplDebugInfo {
|
|
||||||
file: core::file!(),
|
|
||||||
line: core::line!(),
|
|
||||||
column: core::column!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImplData<'_> {
|
impl ImplData<'_> {
|
||||||
pub unsafe fn pointer_metadata<T: ?Sized>(&self) -> DynMetadata<T> {
|
pub unsafe fn pointer_metadata<T: ?Sized>(&self) -> DynMetadata<T> {
|
||||||
@ -407,7 +419,9 @@ struct ImplRegistry {
|
|||||||
|
|
||||||
impl ImplRegistry {
|
impl ImplRegistry {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self { oid_to_data: HashMap::new() }
|
Self {
|
||||||
|
oid_to_data: HashMap::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_entry(&mut self, entry: &'static ImplEntry) {
|
fn add_entry(&mut self, entry: &'static ImplEntry) {
|
||||||
@ -415,10 +429,14 @@ impl ImplRegistry {
|
|||||||
|
|
||||||
if let Some(old) = old_val {
|
if let Some(old) = old_val {
|
||||||
eprintln!("Value impl oid conflict for {:?}", entry.id.type_oid);
|
eprintln!("Value impl oid conflict for {:?}", entry.id.type_oid);
|
||||||
eprintln!("Existing impl registered at {}:{}:{}",
|
eprintln!(
|
||||||
old.info.file, old.info.line, old.info.column);
|
"Existing impl registered at {}:{}:{}",
|
||||||
eprintln!("New impl registered at {}:{}:{}",
|
old.info.file, old.info.line, old.info.column
|
||||||
entry.data.info.file, entry.data.info.line, entry.data.info.column);
|
);
|
||||||
|
eprintln!(
|
||||||
|
"New impl registered at {}:{}:{}",
|
||||||
|
entry.data.info.file, entry.data.info.line, entry.data.info.column
|
||||||
|
);
|
||||||
}
|
}
|
||||||
assert!(old_val.is_none());
|
assert!(old_val.is_none());
|
||||||
}
|
}
|
||||||
@ -444,64 +462,89 @@ pub unsafe trait RegisteredImpl {
|
|||||||
fn debug_info() -> ImplDebugInfo;
|
fn debug_info() -> ImplDebugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! oiddeser {
|
#[macro_use]
|
||||||
( $y:ty, $z:ty ) => {
|
pub mod macros {
|
||||||
impl DeserializeDynOid for $y
|
#[macro_export]
|
||||||
where $y: for<'a> Deserialize<$z, (dyn DynDeserializer + 'a)>
|
macro_rules! debug_info {
|
||||||
{
|
() => {
|
||||||
unsafe fn deserialize_dynoid(&self, deserializer: &mut dyn DynDeserializer, alloc: &mut dyn FnMut(Layout) -> *mut u8) -> Result<*mut (), DynError> {
|
$crate::resources::state::value::ImplDebugInfo {
|
||||||
let ptr = alloc(Layout::new::<$z>()).cast::<$z>();
|
file: ::core::file!(),
|
||||||
ptr.write(self.deserialize(deserializer)?);
|
line: ::core::line!(),
|
||||||
Ok(ptr as *mut ())
|
column: ::core::column!(),
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! oiddeser {
|
||||||
|
( $y:ty, $z:ty ) => {
|
||||||
|
impl $crate::resources::state::value::DeserializeDynOid for $y
|
||||||
|
where
|
||||||
|
$y: for<'a> ::rkyv::Deserialize<$z, (dyn ::rkyv_dyn::DynDeserializer + 'a)>,
|
||||||
|
{
|
||||||
|
unsafe fn deserialize_dynoid(
|
||||||
|
&self,
|
||||||
|
deserializer: &mut dyn ::rkyv_dyn::DynDeserializer,
|
||||||
|
alloc: &mut dyn FnMut(::core::alloc::Layout) -> *mut u8,
|
||||||
|
) -> Result<*mut (), ::rkyv_dyn::DynError> {
|
||||||
|
let ptr = alloc(::core::alloc::Layout::new::<$z>()).cast::<$z>();
|
||||||
|
ptr.write(self.deserialize(deserializer)?);
|
||||||
|
Ok(ptr as *mut ())
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_dynoid_metadata(&self, _: &mut dyn DynDeserializer) -> Result<<dyn
|
fn deserialize_dynoid_metadata(
|
||||||
SerializeValue as Pointee>::Metadata, DynError> {
|
&self,
|
||||||
unsafe {
|
_: &mut dyn ::rkyv_dyn::DynDeserializer,
|
||||||
Ok(core::mem::transmute(ptr_meta::metadata(
|
) -> ::std::result::Result<<dyn $crate::resources::state::value::SerializeValue
|
||||||
core::ptr::null::<$z>() as *const dyn SerializeValue
|
as
|
||||||
)))
|
::ptr_meta::Pointee>::Metadata, ::rkyv_dyn::DynError> {
|
||||||
|
unsafe {
|
||||||
|
Ok(core::mem::transmute(ptr_meta::metadata(
|
||||||
|
::core::ptr::null::<$z>() as *const dyn $crate::resources::state::value::SerializeValue,
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
#[macro_export]
|
||||||
macro_rules! oidvalue {
|
macro_rules! oidvalue {
|
||||||
( $x:ident, $y:ty ) => {
|
( $x:ident, $y:ty ) => {
|
||||||
oidvalue! {$x, $y, $y}
|
$crate::oidvalue! {$x, $y, $y}
|
||||||
};
|
};
|
||||||
( $x:ident, $y:ty, $z:ty ) => {
|
( $x:ident, $y:ty, $z:ty ) => {
|
||||||
oiddeser! {$z, $y}
|
$crate::oiddeser! {$z, $y}
|
||||||
|
|
||||||
impl TypeOid for $z {
|
impl $crate::resources::state::value::TypeOid for $z {
|
||||||
fn type_oid() -> &'static ObjectIdentifier {
|
fn type_oid() -> &'static $crate::utils::oid::ObjectIdentifier {
|
||||||
&$x
|
&$x
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
stringify!($y)
|
stringify!($y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_desc() -> &'static str {
|
fn type_desc() -> &'static str {
|
||||||
"builtin"
|
"builtin"
|
||||||
}
|
|
||||||
}
|
|
||||||
unsafe impl RegisteredImpl for $z {
|
|
||||||
fn vtable() -> usize {
|
|
||||||
unsafe {
|
|
||||||
core::mem::transmute(ptr_meta::metadata(
|
|
||||||
core::ptr::null::<$z>() as *const dyn DeserializeValue
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn debug_info() -> ImplDebugInfo {
|
unsafe impl $crate::resources::state::value::RegisteredImpl for $z {
|
||||||
debug_info!()
|
fn vtable() -> usize {
|
||||||
|
unsafe {
|
||||||
|
::core::mem::transmute(ptr_meta::metadata(
|
||||||
|
::core::ptr::null::<$z>() as *const dyn $crate::resources::state::value::DeserializeValue
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn debug_info() -> $crate::resources::state::value::ImplDebugInfo {
|
||||||
|
$crate::debug_info!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inventory::submit! {ImplEntry::new::<$z>()}
|
::inventory::submit! {$crate::resources::state::value::ImplEntry::new::<$z>()}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
use macros::*;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref OID_BOOL: ObjectIdentifier = {
|
pub static ref OID_BOOL: ObjectIdentifier = {
|
||||||
@ -563,9 +606,20 @@ oidvalue!(OID_I32, i32);
|
|||||||
oidvalue!(OID_I64, i64);
|
oidvalue!(OID_I64, i64);
|
||||||
oidvalue!(OID_I128, i128);
|
oidvalue!(OID_I128, i128);
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
|
serde::Serialize,
|
||||||
#[archive_attr(derive(TypeName, Debug, PartialEq, serde::Serialize, serde::Deserialize))]
|
serde::Deserialize,
|
||||||
|
Debug,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
rkyv::Archive,
|
||||||
|
rkyv::Serialize,
|
||||||
|
rkyv::Deserialize,
|
||||||
|
)]
|
||||||
|
#[archive_attr(derive(Debug, PartialEq, serde::Serialize, serde::Deserialize))]
|
||||||
pub struct Vec3u8 {
|
pub struct Vec3u8 {
|
||||||
pub a: u8,
|
pub a: u8,
|
||||||
pub b: u8,
|
pub b: u8,
|
||||||
@ -576,9 +630,9 @@ oidvalue!(OID_VEC3U8, Vec3u8, ArchivedVec3u8);
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use rand::Rng;
|
|
||||||
use rand::distributions::Standard;
|
use rand::distributions::Standard;
|
||||||
use rand::prelude::Distribution;
|
use rand::prelude::Distribution;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
impl Distribution<Vec3u8> for Standard {
|
impl Distribution<Vec3u8> for Standard {
|
||||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3u8 {
|
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3u8 {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use crate::authorization::roles::Role;
|
||||||
|
use crate::resources::Resource;
|
||||||
|
use crate::users::User;
|
||||||
|
|
||||||
struct Inner {
|
struct Inner {
|
||||||
|
|
||||||
@ -29,4 +32,20 @@ pub struct SessionHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SessionHandle {
|
impl SessionHandle {
|
||||||
|
pub fn get_user(&self) -> User {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_disclose(&self, resource: &Resource) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
pub fn has_read(&self, resource: &Resource) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
pub fn has_write(&self, resource: &Resource) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
pub fn has_manage(&self, resource: &Resource) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,11 +1,27 @@
|
|||||||
|
use crate::db::{AllocAdapter, Environment, RawDB, Result, DB};
|
||||||
|
use crate::db::{DatabaseFlags, LMDBorrow, RoTransaction, WriteFlags};
|
||||||
|
use lmdb::{RwTransaction, Transaction};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use lmdb::{RwTransaction, Transaction};
|
|
||||||
use crate::db::{RawDB, DB, AllocAdapter, Environment, Result};
|
|
||||||
use crate::db::{DatabaseFlags, LMDBorrow, RoTransaction, WriteFlags, };
|
|
||||||
use super::User;
|
|
||||||
|
|
||||||
use rkyv::{Deserialize, Archived};
|
use rkyv::{Archived, Deserialize};
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Debug,
|
||||||
|
rkyv::Archive,
|
||||||
|
rkyv::Serialize,
|
||||||
|
rkyv::Deserialize,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
)]
|
||||||
|
pub struct User {
|
||||||
|
id: u128,
|
||||||
|
username: String,
|
||||||
|
roles: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
type Adapter = AllocAdapter<User>;
|
type Adapter = AllocAdapter<User>;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -64,59 +80,3 @@ impl UserDB {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserIndex {
|
|
||||||
env: Arc<Environment>,
|
|
||||||
usernames: RawDB,
|
|
||||||
roles: RawDB,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserIndex {
|
|
||||||
pub fn update(&self, old: &User, new: &User) -> Result<()> {
|
|
||||||
assert_eq!(old.id, new.id);
|
|
||||||
let mut txn = self.env.begin_rw_txn()?;
|
|
||||||
if old.username != new.username {
|
|
||||||
self.update_username(&mut txn, new.id, &old.username, &new.username)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut to_remove: HashSet<&String> = old.roles.iter().collect();
|
|
||||||
let mut to_add: HashSet<&String> = HashSet::new();
|
|
||||||
for role in new.roles.iter() {
|
|
||||||
// If a role wasn't found in the old ones it's a new one that's being added
|
|
||||||
if !to_remove.remove(role) {
|
|
||||||
to_add.insert(role);
|
|
||||||
}
|
|
||||||
// Otherwise it's in both sets so we just ignore it.
|
|
||||||
}
|
|
||||||
|
|
||||||
self.update_roles(&mut txn, new.id, to_remove, to_add)?;
|
|
||||||
txn.commit()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_username(&self, txn: &mut RwTransaction, uid: u128, old: &String, new: &String)
|
|
||||||
-> Result<()>
|
|
||||||
{
|
|
||||||
let flags = WriteFlags::empty();
|
|
||||||
self.usernames.del(txn, &old.as_bytes(), Some(&uid.to_ne_bytes()))?;
|
|
||||||
self.usernames.put(txn, &new.as_bytes(), &uid.to_ne_bytes(), flags)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_roles(&self,
|
|
||||||
txn: &mut RwTransaction,
|
|
||||||
uid: u128,
|
|
||||||
remove: HashSet<&String>,
|
|
||||||
add: HashSet<&String>
|
|
||||||
) -> Result<()>
|
|
||||||
{
|
|
||||||
let flags = WriteFlags::empty();
|
|
||||||
for role in remove.iter() {
|
|
||||||
self.roles.del(txn, &role.as_bytes(), Some(&uid.to_ne_bytes()))?;
|
|
||||||
}
|
|
||||||
for role in add.iter() {
|
|
||||||
self.roles.put(txn, &role.as_bytes(), &uid.to_ne_bytes(), flags)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,24 +14,43 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use rkyv::{Archive, Deserialize, Infallible, Serialize};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use rkyv::{Archive, Serialize, Deserialize, Infallible};
|
|
||||||
|
|
||||||
mod db;
|
pub mod db;
|
||||||
|
|
||||||
pub use db::UserDB;
|
|
||||||
pub use crate::authentication::db::PassDB;
|
pub use crate::authentication::db::PassDB;
|
||||||
|
use crate::authorization::roles::Role;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Archive, Serialize, Deserialize, serde::Serialize, serde::Deserialize)]
|
#[derive(
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Debug,
|
||||||
|
Archive,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
)]
|
||||||
|
#[archive_attr(derive(Debug, PartialEq, serde::Serialize, serde::Deserialize))]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
id: u128,
|
id: u64
|
||||||
username: String,
|
|
||||||
roles: Vec<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub fn new(id: u128, username: String, roles: Vec<String>) -> Self {
|
pub fn new(id: u64) -> Self {
|
||||||
User { id, username, roles }
|
User { id }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_username(&self) -> &str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_roles(&self) -> impl IntoIterator<Item=Role> {
|
||||||
|
unimplemented!();
|
||||||
|
[]
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user