From 33e8a62d2a0dec60ba462c763cde9731b80c981b Mon Sep 17 00:00:00 2001 From: Nadja Reitzenstein Date: Wed, 16 Mar 2022 20:17:59 +0100 Subject: [PATCH] Implement more API to make Borepin happier --- bffhd/capnp/machine.rs | 11 +++-- bffhd/capnp/user.rs | 97 +++++++++++++++++++++++++++++++------- bffhd/capnp/user_system.rs | 79 +++++++++++++++++++++++++------ bffhd/resources/mod.rs | 29 +++++++++++- bffhd/session/mod.rs | 8 ++++ 5 files changed, 187 insertions(+), 37 deletions(-) diff --git a/bffhd/capnp/machine.rs b/bffhd/capnp/machine.rs index 952bdc4..35423ee 100644 --- a/bffhd/capnp/machine.rs +++ b/bffhd/capnp/machine.rs @@ -10,6 +10,7 @@ use api::machine_capnp::machine::{ }; use capnp::capability::Promise; use capnp_rpc::pry; +use crate::capnp::user::User; #[derive(Clone)] pub struct Machine { @@ -196,11 +197,13 @@ impl ManageServer for Machine { fn get_machine_info_extended( &mut self, _: manage::GetMachineInfoExtendedParams, - _: manage::GetMachineInfoExtendedResults, + mut result: manage::GetMachineInfoExtendedResults, ) -> Promise<(), ::capnp::Error> { - Promise::err(::capnp::Error::unimplemented( - "method not implemented".to_string(), - )) + let mut builder = result.get(); + let user = User::new(self.session.clone()); + user.build_else(self.resource.get_current_user(), builder.reborrow().init_current_user()); + user.build_else(self.resource.get_previous_user(), builder.init_last_user()); + Promise::ok(()) } fn set_property( &mut self, diff --git a/bffhd/capnp/user.rs b/bffhd/capnp/user.rs index 701eb21..4fbcb71 100644 --- a/bffhd/capnp/user.rs +++ b/bffhd/capnp/user.rs @@ -1,29 +1,92 @@ - -use api::user_capnp::user::{ - info, - manage, - admin, -}; use crate::session::SessionHandle; +use api::user_capnp::user::{admin, info, manage, Builder}; +use crate::users::UserRef; -struct User { +pub struct User { session: SessionHandle, } -impl info::Server for User { +impl User { + pub fn new(session: SessionHandle) -> Self { + Self { session } + } - fn list_roles(&mut self, _: info::ListRolesParams<>, _: info::ListRolesResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } + pub fn build_else(&self, user: Option, mut builder: Builder) { + if let Some(user) = user { + builder.set_username(user.get_username()); + } + } + + pub fn build_into(self, mut builder: Builder) { + let user = self.session.get_user(); + builder.set_username(user.get_username()); + } + + pub fn build(session: SessionHandle, mut builder: Builder) { + let this = Self::new(session); + this.build_into(builder) + } +} + +impl info::Server for User { + fn list_roles( + &mut self, + _: info::ListRolesParams, + _: info::ListRolesResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } } impl manage::Server for User { - - fn pwd(&mut self, _: manage::PwdParams<>, _: manage::PwdResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } + fn pwd( + &mut self, + _: manage::PwdParams, + _: manage::PwdResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } } impl admin::Server for User { - - fn get_user_info_extended(&mut self, _: admin::GetUserInfoExtendedParams<>, _: admin::GetUserInfoExtendedResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } - fn add_role(&mut self, _: admin::AddRoleParams<>, _: admin::AddRoleResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } - fn remove_role(&mut self, _: admin::RemoveRoleParams<>, _: admin::RemoveRoleResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } - fn pwd(&mut self, _: admin::PwdParams<>, _: admin::PwdResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } -} \ No newline at end of file + fn get_user_info_extended( + &mut self, + _: admin::GetUserInfoExtendedParams, + _: admin::GetUserInfoExtendedResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn add_role( + &mut self, + _: admin::AddRoleParams, + _: admin::AddRoleResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn remove_role( + &mut self, + _: admin::RemoveRoleParams, + _: admin::RemoveRoleResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn pwd( + &mut self, + _: admin::PwdParams, + _: admin::PwdResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} diff --git a/bffhd/capnp/user_system.rs b/bffhd/capnp/user_system.rs index 0ed628c..78f05b3 100644 --- a/bffhd/capnp/user_system.rs +++ b/bffhd/capnp/user_system.rs @@ -1,10 +1,10 @@ - - - - +use capnp::capability::Promise; use api::usersystem_capnp::user_system::{ - Server as UserSystem, info::Server as InfoServer, manage::Server as ManageServer, + info, manage, Server as UserSystem, + self as system, }; +use crate::authorization::permissions::Permission; +use crate::capnp::user::User; use crate::session::SessionHandle; @@ -15,20 +15,69 @@ pub struct Users { impl Users { pub fn new(session: SessionHandle) -> Self { - Self { - session, - } + Self { session } } } -impl UserSystem for Users { - +impl system::Server for Users { + fn info( + &mut self, + _: system::InfoParams, + mut result: system::InfoResults, + ) -> Promise<(), ::capnp::Error> { + result.get().set_info(capnp_rpc::new_client(self.clone())); + Promise::ok(()) + } + fn manage( + &mut self, + _: system::ManageParams, + mut result: system::ManageResults, + ) -> Promise<(), ::capnp::Error> { + if self.session.has_perm(Permission::new("bffh.users.manage")) { + result.get().set_manage(capnp_rpc::new_client(self.clone())); + } + Promise::ok(()) + } } -impl InfoServer for Users { - +impl info::Server for Users { + fn get_user_self( + &mut self, + _: info::GetUserSelfParams, + mut result: info::GetUserSelfResults, + ) -> Promise<(), ::capnp::Error> { + let builder = result.get().init_user(); + User::build(self.session.clone(), builder); + Promise::ok(()) + } } -impl ManageServer for Users { - -} \ No newline at end of file +impl manage::Server for Users { + fn get_user_list( + &mut self, + _: manage::GetUserListParams, + _: manage::GetUserListResults, + ) -> Promise<(), ::capnp::Error> { + Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn add_user( + &mut self, + _: manage::AddUserParams, + _: manage::AddUserResults, + ) -> Promise<(), ::capnp::Error> { + Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn remove_user( + &mut self, + _: manage::RemoveUserParams, + _: manage::RemoveUserResults, + ) -> Promise<(), ::capnp::Error> { + Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} diff --git a/bffhd/resources/mod.rs b/bffhd/resources/mod.rs index 2c5acb6..1b42f68 100644 --- a/bffhd/resources/mod.rs +++ b/bffhd/resources/mod.rs @@ -1,9 +1,10 @@ -use std::convert::Infallible; +use rkyv::Infallible; use std::ops::Deref; use std::sync::Arc; use futures_signals::signal::{Mutable, Signal, SignalExt}; use lmdb::RoTransaction; use rkyv::{Archived, Deserialize}; +use rkyv::option::ArchivedOption; use rkyv::ser::Serializer; use rkyv::ser::serializers::AllocSerializer; use crate::authorization::permissions::PrivilegesBuf; @@ -117,6 +118,32 @@ impl Resource { &self.inner.desc } + pub fn get_current_user(&self) -> Option { + let state = self.get_state_ref(); + let state: &Archived = state.as_ref(); + match &state.inner.state { + ArchivedStatus::Blocked(user) | + ArchivedStatus::InUse(user) | + ArchivedStatus::Reserved(user) | + ArchivedStatus::ToCheck(user) => { + let user = Deserialize::::deserialize(user, &mut Infallible).unwrap(); + Some(user) + }, + _ => None, + } + } + + pub fn get_previous_user(&self) -> Option { + let state = self.get_state_ref(); + let state: &Archived = state.as_ref(); + if let ArchivedOption::Some(user) = &state.inner.previous { + let user = Deserialize::::deserialize(user, &mut Infallible).unwrap(); + Some(user) + } else { + None + } + } + fn set_state(&self, state: MachineState) { let mut serializer = AllocSerializer::<1024>::default(); serializer.serialize_value(&state); diff --git a/bffhd/session/mod.rs b/bffhd/session/mod.rs index 64a700a..1ff81b4 100644 --- a/bffhd/session/mod.rs +++ b/bffhd/session/mod.rs @@ -3,6 +3,7 @@ use once_cell::sync::OnceCell; +use crate::authorization::permissions::Permission; use crate::authorization::roles::{Roles}; use crate::resources::Resource; use crate::Users; @@ -78,4 +79,11 @@ impl SessionHandle { false } } + pub fn has_perm(&self, perm: impl AsRef) -> bool { + if let Some(user) = self.users.get_user(self.user.get_username()) { + self.roles.is_permitted(&user.userdata, perm) + } else { + false + } + } } \ No newline at end of file