mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-22 06:47:56 +01:00
User admin methods
This commit is contained in:
parent
3eab5b8702
commit
5538dd6751
@ -40,7 +40,7 @@ impl Machine {
|
||||
builder.set_urn(&format!("urn:fabaccess:resource:{}", self.resource.get_id()));
|
||||
|
||||
{
|
||||
let user = self.session.get_user();
|
||||
let user = self.session.get_user_ref();
|
||||
let state = self.resource.get_state_ref();
|
||||
let state = state.as_ref();
|
||||
|
||||
@ -113,7 +113,7 @@ impl UseServer for Machine {
|
||||
let resource = self.resource.clone();
|
||||
let session = self.session.clone();
|
||||
Promise::from_future(async move {
|
||||
let user = session.get_user();
|
||||
let user = session.get_user_ref();
|
||||
resource.try_update(session, Status::InUse(user)).await;
|
||||
Ok(())
|
||||
})
|
||||
@ -127,7 +127,7 @@ impl UseServer for Machine {
|
||||
let resource = self.resource.clone();
|
||||
let session = self.session.clone();
|
||||
Promise::from_future(async move {
|
||||
let user = session.get_user();
|
||||
let user = session.get_user_ref();
|
||||
resource
|
||||
.try_update(session, Status::Reserved(user))
|
||||
.await;
|
||||
@ -200,7 +200,7 @@ impl ManageServer for Machine {
|
||||
mut result: manage::GetMachineInfoExtendedResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
let mut builder = result.get();
|
||||
let user = User::new(self.session.clone());
|
||||
let user = User::new_self(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(())
|
||||
@ -233,7 +233,7 @@ impl ManageServer for Machine {
|
||||
let session = self.session.clone();
|
||||
Promise::from_future(async move {
|
||||
resource
|
||||
.force_set(Status::InUse(session.get_user()))
|
||||
.force_set(Status::InUse(session.get_user_ref()))
|
||||
.await;
|
||||
Ok(())
|
||||
})
|
||||
@ -270,7 +270,7 @@ impl ManageServer for Machine {
|
||||
let session = self.session.clone();
|
||||
Promise::from_future(async move {
|
||||
resource
|
||||
.force_set(Status::Blocked(session.get_user()))
|
||||
.force_set(Status::Blocked(session.get_user_ref()))
|
||||
.await;
|
||||
Ok(())
|
||||
})
|
||||
@ -295,7 +295,7 @@ impl AdminServer for Machine {
|
||||
_: admin::ForceSetStateResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
use api::schema::machine_capnp::machine::MachineState as APIMState;
|
||||
let user = self.session.get_user();
|
||||
let user = self.session.get_user_ref();
|
||||
let state = match pry!(pry!(params.get()).get_state()) {
|
||||
APIMState::Free => Status::Free,
|
||||
APIMState::Blocked => Status::Blocked(user),
|
||||
|
@ -1,30 +1,55 @@
|
||||
use capnp::capability::Promise;
|
||||
use capnp_rpc::pry;
|
||||
use crate::session::SessionHandle;
|
||||
use api::user_capnp::user::{admin, info, manage, Builder};
|
||||
use crate::users::UserRef;
|
||||
use crate::authorization::permissions::Permission;
|
||||
use crate::users::{db, UserRef};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct User {
|
||||
session: SessionHandle,
|
||||
user: UserRef,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn new(session: SessionHandle) -> Self {
|
||||
Self { session }
|
||||
pub fn new(session: SessionHandle, user: UserRef) -> Self {
|
||||
Self { session, user }
|
||||
}
|
||||
|
||||
pub fn build_else(&self, user: Option<UserRef>, mut builder: Builder) {
|
||||
if let Some(user) = user {
|
||||
builder.set_username(user.get_username());
|
||||
}
|
||||
pub fn new_self(session: SessionHandle) -> Self {
|
||||
let user = session.get_user_ref();
|
||||
Self::new(session, user)
|
||||
}
|
||||
|
||||
pub fn build_into(self, mut builder: Builder) {
|
||||
let user = self.session.get_user();
|
||||
builder.set_username(user.get_username());
|
||||
pub fn build_else(&self, user: Option<UserRef>, builder: Builder) {
|
||||
if let Some(user) = user.and_then(|u| self.session.users.get_user(u.get_username())) {
|
||||
self.fill(user, builder);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(session: SessionHandle, mut builder: Builder) {
|
||||
let this = Self::new(session);
|
||||
this.build_into(builder)
|
||||
let this = Self::new_self(session);
|
||||
let user = this.session.get_user();
|
||||
this.fill(user, builder);
|
||||
}
|
||||
|
||||
pub fn fill(&self, user: db::User, mut builder: Builder) {
|
||||
builder.set_username(user.id.as_str());
|
||||
|
||||
let client = Self::new(self.session.clone(), UserRef::new(user.id.clone()));
|
||||
|
||||
// We have permissions on ourself
|
||||
let is_me = &self.session.get_user_ref().id == &user.id;
|
||||
|
||||
if is_me || self.session.has_perm(Permission::new("bffh.users.info")) {
|
||||
builder.set_info(capnp_rpc::new_client(client.clone()));
|
||||
}
|
||||
if is_me {
|
||||
builder.set_manage(capnp_rpc::new_client(client.clone()));
|
||||
}
|
||||
if self.session.has_perm(Permission::new("bffh.users.admin")) {
|
||||
builder.set_admin(capnp_rpc::new_client(client.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,21 +57,25 @@ 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(),
|
||||
))
|
||||
mut result: info::ListRolesResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
let user = self.session.get_user();
|
||||
let mut builder = result.get().init_roles(user.userdata.roles.len() as u32);
|
||||
for (i, role) in user.userdata.roles.into_iter().enumerate() {
|
||||
let mut b = builder.reborrow().get(i as u32);
|
||||
b.set_name(role.as_str());
|
||||
}
|
||||
Promise::ok(())
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
params: manage::PwdParams,
|
||||
mut results: manage::PwdResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
Promise::err(::capnp::Error::unimplemented(
|
||||
"method not implemented".to_string(),
|
||||
))
|
||||
}
|
||||
@ -57,35 +86,55 @@ impl admin::Server for User {
|
||||
&mut self,
|
||||
_: admin::GetUserInfoExtendedParams,
|
||||
_: admin::GetUserInfoExtendedResults,
|
||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
Promise::err(::capnp::Error::unimplemented(
|
||||
"method not implemented".to_string(),
|
||||
))
|
||||
}
|
||||
fn add_role(
|
||||
&mut self,
|
||||
_: admin::AddRoleParams,
|
||||
param: admin::AddRoleParams,
|
||||
_: admin::AddRoleResults,
|
||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
||||
"method not implemented".to_string(),
|
||||
))
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
let rolename = pry!(pry!(pry!(param.get()).get_role()).get_name());
|
||||
|
||||
if let Some(_role) = self.session.roles.get(rolename) {
|
||||
let mut target = self.session.users.get_user(self.user.get_username()).unwrap();
|
||||
|
||||
// Only update if needed
|
||||
if !target.userdata.roles.iter().any(|r| r.as_str() == rolename) {
|
||||
target.userdata.roles.push(rolename.to_string());
|
||||
self.session.users.put_user(self.user.get_username(), &target);
|
||||
}
|
||||
}
|
||||
|
||||
Promise::ok(())
|
||||
}
|
||||
fn remove_role(
|
||||
&mut self,
|
||||
_: admin::RemoveRoleParams,
|
||||
param: admin::RemoveRoleParams,
|
||||
_: admin::RemoveRoleResults,
|
||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
||||
"method not implemented".to_string(),
|
||||
))
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
let rolename = pry!(pry!(pry!(param.get()).get_role()).get_name());
|
||||
|
||||
if let Some(_role) = self.session.roles.get(rolename) {
|
||||
let mut target = self.session.users.get_user(self.user.get_username()).unwrap();
|
||||
|
||||
// Only update if needed
|
||||
if target.userdata.roles.iter().any(|r| r.as_str() == rolename) {
|
||||
target.userdata.roles.retain(|r| r.as_str() != rolename);
|
||||
self.session.users.put_user(self.user.get_username(), &target);
|
||||
}
|
||||
}
|
||||
|
||||
Promise::ok(())
|
||||
}
|
||||
fn pwd(
|
||||
&mut self,
|
||||
_: admin::PwdParams,
|
||||
_: admin::PwdResults,
|
||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
Promise::err(::capnp::Error::unimplemented(
|
||||
"method not implemented".to_string(),
|
||||
))
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
use capnp::capability::Promise;
|
||||
use capnp_rpc::pry;
|
||||
use libc::user;
|
||||
use api::usersystem_capnp::user_system::{
|
||||
info, manage, Server as UserSystem,
|
||||
self as system,
|
||||
@ -7,6 +9,7 @@ use crate::authorization::permissions::Permission;
|
||||
use crate::capnp::user::User;
|
||||
|
||||
use crate::session::SessionHandle;
|
||||
use crate::users::UserRef;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Users {
|
||||
@ -56,11 +59,17 @@ impl manage::Server for Users {
|
||||
fn get_user_list(
|
||||
&mut self,
|
||||
_: manage::GetUserListParams,
|
||||
_: manage::GetUserListResults,
|
||||
mut result: manage::GetUserListResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
Promise::err(::capnp::Error::unimplemented(
|
||||
"method not implemented".to_string(),
|
||||
))
|
||||
let userdb = self.session.users.into_inner();
|
||||
let users = pry!(userdb.get_all()
|
||||
.map_err(|e| capnp::Error::failed(format!("UserDB error: {:?}", e))));
|
||||
let mut builder = result.get().init_user_list(users.len() as u32);
|
||||
let me = User::new_self(self.session.clone());
|
||||
for (i, (_, user)) in users.into_iter().enumerate() {
|
||||
me.fill(user, builder.reborrow().get(i as u32));
|
||||
}
|
||||
Promise::ok(())
|
||||
}
|
||||
fn add_user(
|
||||
&mut self,
|
||||
|
@ -167,7 +167,7 @@ impl Resource {
|
||||
pub async fn try_update(&self, session: SessionHandle, new: Status) {
|
||||
let old = self.get_state();
|
||||
let old: &Archived<State> = old.as_ref();
|
||||
let user = session.get_user();
|
||||
let user = session.get_user_ref();
|
||||
|
||||
if session.has_manage(self) // Default allow for managers
|
||||
|
||||
@ -224,7 +224,7 @@ impl Resource {
|
||||
let s: &Archived<State> = state.as_ref();
|
||||
let i: &Archived<MachineState> = &s.inner;
|
||||
if let ArchivedStatus::InUse(user) = &i.state {
|
||||
let current = session.get_user();
|
||||
let current = session.get_user_ref();
|
||||
if user == ¤t {
|
||||
self.set_state(MachineState::free(Some(current)));
|
||||
}
|
||||
@ -236,7 +236,7 @@ impl Resource {
|
||||
}
|
||||
|
||||
pub fn visible(&self, session: &SessionHandle) -> bool {
|
||||
session.has_disclose(self) || self.is_owned_by(session.get_user())
|
||||
session.has_disclose(self) || self.is_owned_by(session.get_user_ref())
|
||||
}
|
||||
|
||||
pub fn is_owned_by(&self, owner: UserRef) -> bool {
|
||||
|
@ -7,7 +7,7 @@ use crate::authorization::permissions::Permission;
|
||||
use crate::authorization::roles::{Roles};
|
||||
use crate::resources::Resource;
|
||||
use crate::Users;
|
||||
use crate::users::UserRef;
|
||||
use crate::users::{db, UserRef};
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -40,17 +40,21 @@ impl SessionManager {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SessionHandle {
|
||||
users: Users,
|
||||
roles: Roles,
|
||||
pub users: Users,
|
||||
pub roles: Roles,
|
||||
|
||||
user: UserRef,
|
||||
}
|
||||
|
||||
impl SessionHandle {
|
||||
pub fn get_user(&self) -> UserRef {
|
||||
pub fn get_user_ref(&self) -> UserRef {
|
||||
self.user.clone()
|
||||
}
|
||||
|
||||
pub fn get_user(&self) -> db::User {
|
||||
self.users.get_user(self.user.get_username()).expect("Failed to get user self")
|
||||
}
|
||||
|
||||
pub fn has_disclose(&self, resource: &Resource) -> bool {
|
||||
if let Some(user) = self.users.get_user(self.user.get_username()) {
|
||||
self.roles.is_permitted(&user.userdata, &resource.get_required_privs().disclose)
|
||||
|
@ -93,6 +93,11 @@ impl Users {
|
||||
.map(|user| Deserialize::<db::User, _>::deserialize(user.as_ref(), &mut Infallible).unwrap())
|
||||
}
|
||||
|
||||
pub fn put_user(&self, uid: &str, user: &db::User) -> Result<(), lmdb::Error> {
|
||||
tracing::trace!(uid, ?user, "Updating user");
|
||||
self.userdb.put(uid, user)
|
||||
}
|
||||
|
||||
pub fn load_file<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
||||
let f = std::fs::read(path)?;
|
||||
let map: HashMap<String, UserData> = toml::from_slice(&f)?;
|
||||
|
Loading…
Reference in New Issue
Block a user