fabaccess-bffh/bffhd/resources/mod.rs

266 lines
8.7 KiB
Rust
Raw Permalink Normal View History

2022-05-05 15:50:44 +02:00
use futures_signals::signal::{Mutable, Signal};
use rkyv::Infallible;
2022-03-16 18:10:59 +01:00
use std::ops::Deref;
2022-03-13 20:11:37 +01:00
use std::sync::Arc;
2022-04-26 23:21:43 +02:00
2022-03-20 22:46:04 +01:00
use crate::audit::AUDIT;
2022-03-15 19:14:04 +01:00
use crate::authorization::permissions::PrivilegesBuf;
2022-03-13 20:33:26 +01:00
use crate::config::MachineDescription;
2022-03-16 18:10:59 +01:00
use crate::db::ArchivedValue;
2022-05-05 15:50:44 +02:00
use crate::resources::modules::fabaccess::{ArchivedStatus, MachineState, Status};
2022-03-13 20:11:37 +01:00
use crate::resources::state::db::StateDB;
2022-03-13 17:29:21 +01:00
use crate::resources::state::State;
use crate::session::SessionHandle;
2022-03-15 17:52:47 +01:00
use crate::users::UserRef;
2022-05-05 15:50:44 +02:00
use rkyv::option::ArchivedOption;
use rkyv::ser::serializers::AllocSerializer;
use rkyv::ser::Serializer;
use rkyv::{Archived, Deserialize};
2022-03-08 18:52:49 +01:00
pub mod db;
2022-03-13 17:29:21 +01:00
pub mod search;
pub mod state;
2021-11-26 02:25:48 +01:00
2022-03-13 17:29:21 +01:00
pub mod modules;
2021-11-26 21:01:43 +01:00
2022-03-13 17:29:21 +01:00
pub struct PermissionDenied;
2021-10-27 21:32:50 +02:00
2022-06-07 14:05:46 +02:00
#[derive(Debug)]
2022-03-13 20:11:37 +01:00
pub(crate) struct Inner {
id: String,
2022-03-16 18:10:59 +01:00
db: StateDB,
signal: Mutable<ArchivedValue<State>>,
2022-03-13 20:33:26 +01:00
desc: MachineDescription,
2022-03-13 20:11:37 +01:00
}
impl Inner {
2022-03-16 18:10:59 +01:00
pub fn new(id: String, db: StateDB, desc: MachineDescription) -> Self {
let state = if let Some(previous) = db.get(id.as_bytes()).unwrap() {
tracing::info!(%id, ?previous, "Found previous state");
previous
2022-03-13 20:11:37 +01:00
} else {
2022-03-16 19:01:09 +01:00
let state = MachineState::free(None);
tracing::info!(%id, ?state, "No previous state found, setting default");
2022-03-16 18:10:59 +01:00
2022-03-15 21:24:21 +01:00
let update = state.to_state();
2022-03-16 18:10:59 +01:00
let mut serializer = AllocSerializer::<1024>::default();
2022-05-05 15:50:44 +02:00
serializer
.serialize_value(&update)
.expect("failed to serialize new default state");
2022-03-16 18:10:59 +01:00
let val = ArchivedValue::new(serializer.into_serializer().into_inner());
db.put(&id.as_bytes(), &val).unwrap();
val
2022-03-13 20:11:37 +01:00
};
2022-03-16 18:10:59 +01:00
let signal = Mutable::new(state);
2022-03-13 20:11:37 +01:00
2022-05-05 15:50:44 +02:00
Self {
id,
db,
signal,
desc,
}
2022-03-13 20:11:37 +01:00
}
2022-05-05 15:50:44 +02:00
pub fn signal(&self) -> impl Signal<Item = ArchivedValue<State>> {
2022-03-16 18:10:59 +01:00
Box::pin(self.signal.signal_cloned())
2022-03-13 20:11:37 +01:00
}
2022-03-16 18:10:59 +01:00
fn get_state(&self) -> ArchivedValue<State> {
2022-05-05 15:50:44 +02:00
self.db
.get(self.id.as_bytes())
2022-03-16 18:10:59 +01:00
.expect("lmdb error")
.expect("state should never be None")
2022-03-13 20:11:37 +01:00
}
2022-05-05 15:50:44 +02:00
fn get_state_ref(&self) -> impl Deref<Target = ArchivedValue<State>> + '_ {
2022-03-16 18:10:59 +01:00
self.signal.lock_ref()
2022-03-13 20:11:37 +01:00
}
2022-03-16 18:10:59 +01:00
fn set_state(&self, state: ArchivedValue<State>) {
let span = tracing::debug_span!("set_state", id = %self.id, ?state);
2022-03-13 20:11:37 +01:00
let _guard = span.enter();
tracing::debug!("Updating state");
2022-03-16 18:10:59 +01:00
2022-03-13 20:11:37 +01:00
tracing::trace!("Updating DB");
2022-03-16 18:10:59 +01:00
self.db.put(&self.id.as_bytes(), &state).unwrap();
2022-03-13 20:11:37 +01:00
tracing::trace!("Updated DB, sending update signal");
2022-03-16 18:10:59 +01:00
2022-05-05 15:50:44 +02:00
AUDIT
.get()
.unwrap()
.log(self.id.as_str(), &format!("{}", state));
2022-03-20 22:46:04 +01:00
2022-03-16 18:10:59 +01:00
self.signal.set(state);
2022-03-13 20:11:37 +01:00
tracing::trace!("Sent update signal");
}
}
2022-06-07 14:05:46 +02:00
#[derive(Clone, Debug)]
2022-03-13 20:11:37 +01:00
pub struct Resource {
2022-05-05 15:50:44 +02:00
inner: Arc<Inner>,
2022-03-13 20:11:37 +01:00
}
2022-03-13 17:29:21 +01:00
impl Resource {
2022-03-13 20:11:37 +01:00
pub(crate) fn new(inner: Arc<Inner>) -> Self {
Self { inner }
}
2022-03-16 18:10:59 +01:00
pub fn get_state(&self) -> ArchivedValue<State> {
2022-03-13 20:11:37 +01:00
self.inner.get_state()
}
2022-05-05 15:50:44 +02:00
pub fn get_state_ref(&self) -> impl Deref<Target = ArchivedValue<State>> + '_ {
2022-03-16 19:01:09 +01:00
self.inner.get_state_ref()
}
2022-03-13 20:11:37 +01:00
pub fn get_id(&self) -> &str {
&self.inner.id
2022-03-13 17:29:21 +01:00
}
2022-03-16 19:01:09 +01:00
pub fn get_name(&self) -> &str {
self.inner.desc.name.as_str()
}
2022-05-05 15:50:44 +02:00
pub fn get_signal(&self) -> impl Signal<Item = ArchivedValue<State>> {
2022-03-13 21:30:26 +01:00
self.inner.signal()
}
2022-03-15 19:14:04 +01:00
pub fn get_required_privs(&self) -> &PrivilegesBuf {
&self.inner.desc.privs
}
2022-03-16 19:01:09 +01:00
pub fn get_description(&self) -> &MachineDescription {
&self.inner.desc
}
pub fn get_current_user(&self) -> Option<UserRef> {
let state = self.get_state_ref();
let state: &Archived<State> = state.as_ref();
match &state.inner.state {
2022-05-05 15:50:44 +02:00
ArchivedStatus::Blocked(user)
| ArchivedStatus::InUse(user)
| ArchivedStatus::Reserved(user)
| ArchivedStatus::ToCheck(user) => {
let user = Deserialize::<UserRef, _>::deserialize(user, &mut Infallible).unwrap();
Some(user)
2022-05-05 15:50:44 +02:00
}
_ => None,
}
}
pub fn get_previous_user(&self) -> Option<UserRef> {
let state = self.get_state_ref();
let state: &Archived<State> = state.as_ref();
if let ArchivedOption::Some(user) = &state.inner.previous {
let user = Deserialize::<UserRef, _>::deserialize(user, &mut Infallible).unwrap();
Some(user)
} else {
None
}
}
2022-03-13 17:29:21 +01:00
fn set_state(&self, state: MachineState) {
2022-03-16 18:10:59 +01:00
let mut serializer = AllocSerializer::<1024>::default();
serializer.serialize_value(&state);
let archived = ArchivedValue::new(serializer.into_serializer().into_inner());
self.inner.set_state(archived)
2022-03-13 20:11:37 +01:00
}
fn set_status(&self, state: Status) {
2022-03-15 16:28:11 +01:00
let old = self.inner.get_state();
2022-03-16 18:10:59 +01:00
let oldref: &Archived<State> = old.as_ref();
let previous: &Archived<Option<UserRef>> = &oldref.inner.previous;
2022-05-05 15:50:44 +02:00
let previous =
Deserialize::<Option<UserRef>, _>::deserialize(previous, &mut rkyv::Infallible)
.expect("Infallible deserializer failed");
2022-03-16 18:10:59 +01:00
let new = MachineState { state, previous };
2022-03-15 16:28:11 +01:00
self.set_state(new);
2022-03-13 17:29:21 +01:00
}
2022-03-13 20:11:37 +01:00
pub async fn try_update(&self, session: SessionHandle, new: Status) {
2022-03-13 17:29:21 +01:00
let old = self.get_state();
2022-03-16 18:10:59 +01:00
let old: &Archived<State> = old.as_ref();
2022-03-21 00:01:50 +01:00
let user = session.get_user_ref();
2022-03-13 17:29:21 +01:00
if session.has_manage(self) // Default allow for managers
|| (session.has_write(self) // Decision tree for writers
2022-03-16 18:10:59 +01:00
&& match (&old.inner.state, &new) {
2022-03-13 17:29:21 +01:00
// Going from available to used by the person requesting is okay.
2022-03-16 18:10:59 +01:00
(ArchivedStatus::Free, Status::InUse(who))
2022-03-13 17:29:21 +01:00
// Check that the person requesting does not request for somebody else.
// *That* is manage privilege.
if who == &user => true,
// Reserving things for ourself is okay.
2022-03-16 18:10:59 +01:00
(ArchivedStatus::Free, Status::Reserved(whom))
2022-03-13 17:29:21 +01:00
if &user == whom => true,
// Returning things we've been using is okay. This includes both if
// they're being freed or marked as to be checked.
2022-03-16 18:10:59 +01:00
(ArchivedStatus::InUse(who), Status::Free | Status::ToCheck(_))
2022-03-13 22:50:37 +01:00
if who == &user => true,
2022-03-13 17:29:21 +01:00
// Un-reserving things we reserved is okay
2022-03-16 18:10:59 +01:00
(ArchivedStatus::Reserved(whom), Status::Free)
2022-03-13 22:50:37 +01:00
if whom == &user => true,
2022-03-13 17:29:21 +01:00
// Using things that we've reserved is okay. But the person requesting
// 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.
2022-03-16 18:10:59 +01:00
(ArchivedStatus::Reserved(whom), Status::InUse(who))
2022-03-13 22:50:37 +01:00
if whom == &user && who == whom => true,
2022-03-13 17:29:21 +01:00
// Default is deny.
_ => false
})
// Default permissions everybody has
2022-03-16 18:10:59 +01:00
|| match (&old.inner.state, &new) {
2022-03-13 17:29:21 +01:00
// Returning things we've been using is okay. This includes both if
// they're being freed or marked as to be checked.
2022-03-16 18:10:59 +01:00
(ArchivedStatus::InUse(who), Status::Free | Status::ToCheck(_)) if who == &user => true,
2022-03-13 17:29:21 +01:00
// Un-reserving things we reserved is okay
2022-03-16 18:10:59 +01:00
(ArchivedStatus::Reserved(whom), Status::Free) if whom == &user => true,
2022-03-13 17:29:21 +01:00
// Default is deny.
_ => false,
}
2022-03-13 17:29:21 +01:00
{
2022-03-13 20:11:37 +01:00
self.set_status(new);
}
}
2021-10-27 21:32:50 +02:00
2022-03-13 17:29:21 +01:00
pub async fn give_back(&self, session: SessionHandle) {
2022-03-16 18:10:59 +01:00
let state = self.get_state();
let s: &Archived<State> = state.as_ref();
let i: &Archived<MachineState> = &s.inner;
2022-03-16 19:01:09 +01:00
if let ArchivedStatus::InUse(user) = &i.state {
2022-03-21 00:01:50 +01:00
let current = session.get_user_ref();
2022-03-16 19:01:09 +01:00
if user == &current {
self.set_state(MachineState::free(Some(current)));
2022-03-13 17:29:21 +01:00
}
2022-03-16 19:01:09 +01:00
}
2022-03-13 17:29:21 +01:00
}
2021-10-27 21:32:50 +02:00
2022-03-13 20:11:37 +01:00
pub async fn force_set(&self, new: Status) {
2022-03-15 16:28:11 +01:00
self.set_status(new);
2022-03-13 17:29:21 +01:00
}
2021-10-27 21:32:50 +02:00
2022-03-13 17:29:21 +01:00
pub fn visible(&self, session: &SessionHandle) -> bool {
2022-03-21 00:01:50 +01:00
session.has_disclose(self) || self.is_owned_by(session.get_user_ref())
2021-10-27 21:32:50 +02:00
}
2022-03-15 17:52:47 +01:00
pub fn is_owned_by(&self, owner: UserRef) -> bool {
2022-03-16 18:10:59 +01:00
match &self.get_state().as_ref().inner.state {
ArchivedStatus::Free | ArchivedStatus::Disabled => false,
2021-10-27 21:32:50 +02:00
2022-03-16 18:10:59 +01:00
ArchivedStatus::InUse(user)
| ArchivedStatus::ToCheck(user)
| ArchivedStatus::Blocked(user)
| ArchivedStatus::Reserved(user) => user == &owner,
2021-10-27 21:32:50 +02:00
}
}
2022-03-13 17:29:21 +01:00
}