mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-25 16:17: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()));
|
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 = self.resource.get_state_ref();
|
||||||
let state = state.as_ref();
|
let state = state.as_ref();
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ impl UseServer for Machine {
|
|||||||
let resource = self.resource.clone();
|
let resource = self.resource.clone();
|
||||||
let session = self.session.clone();
|
let session = self.session.clone();
|
||||||
Promise::from_future(async move {
|
Promise::from_future(async move {
|
||||||
let user = session.get_user();
|
let user = session.get_user_ref();
|
||||||
resource.try_update(session, Status::InUse(user)).await;
|
resource.try_update(session, Status::InUse(user)).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -127,7 +127,7 @@ impl UseServer for Machine {
|
|||||||
let resource = self.resource.clone();
|
let resource = self.resource.clone();
|
||||||
let session = self.session.clone();
|
let session = self.session.clone();
|
||||||
Promise::from_future(async move {
|
Promise::from_future(async move {
|
||||||
let user = session.get_user();
|
let user = session.get_user_ref();
|
||||||
resource
|
resource
|
||||||
.try_update(session, Status::Reserved(user))
|
.try_update(session, Status::Reserved(user))
|
||||||
.await;
|
.await;
|
||||||
@ -200,7 +200,7 @@ impl ManageServer for Machine {
|
|||||||
mut result: manage::GetMachineInfoExtendedResults,
|
mut result: manage::GetMachineInfoExtendedResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
let mut builder = result.get();
|
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_current_user(), builder.reborrow().init_current_user());
|
||||||
user.build_else(self.resource.get_previous_user(), builder.init_last_user());
|
user.build_else(self.resource.get_previous_user(), builder.init_last_user());
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
@ -233,7 +233,7 @@ impl ManageServer for Machine {
|
|||||||
let session = self.session.clone();
|
let session = self.session.clone();
|
||||||
Promise::from_future(async move {
|
Promise::from_future(async move {
|
||||||
resource
|
resource
|
||||||
.force_set(Status::InUse(session.get_user()))
|
.force_set(Status::InUse(session.get_user_ref()))
|
||||||
.await;
|
.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -270,7 +270,7 @@ impl ManageServer for Machine {
|
|||||||
let session = self.session.clone();
|
let session = self.session.clone();
|
||||||
Promise::from_future(async move {
|
Promise::from_future(async move {
|
||||||
resource
|
resource
|
||||||
.force_set(Status::Blocked(session.get_user()))
|
.force_set(Status::Blocked(session.get_user_ref()))
|
||||||
.await;
|
.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -295,7 +295,7 @@ impl AdminServer for Machine {
|
|||||||
_: admin::ForceSetStateResults,
|
_: admin::ForceSetStateResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
use api::schema::machine_capnp::machine::MachineState as APIMState;
|
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()) {
|
let state = match pry!(pry!(params.get()).get_state()) {
|
||||||
APIMState::Free => Status::Free,
|
APIMState::Free => Status::Free,
|
||||||
APIMState::Blocked => Status::Blocked(user),
|
APIMState::Blocked => Status::Blocked(user),
|
||||||
|
@ -1,30 +1,55 @@
|
|||||||
|
use capnp::capability::Promise;
|
||||||
|
use capnp_rpc::pry;
|
||||||
use crate::session::SessionHandle;
|
use crate::session::SessionHandle;
|
||||||
use api::user_capnp::user::{admin, info, manage, Builder};
|
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 {
|
pub struct User {
|
||||||
session: SessionHandle,
|
session: SessionHandle,
|
||||||
|
user: UserRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub fn new(session: SessionHandle) -> Self {
|
pub fn new(session: SessionHandle, user: UserRef) -> Self {
|
||||||
Self { session }
|
Self { session, user }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_else(&self, user: Option<UserRef>, mut builder: Builder) {
|
pub fn new_self(session: SessionHandle) -> Self {
|
||||||
if let Some(user) = user {
|
let user = session.get_user_ref();
|
||||||
builder.set_username(user.get_username());
|
Self::new(session, user)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_into(self, mut builder: Builder) {
|
pub fn build_else(&self, user: Option<UserRef>, builder: Builder) {
|
||||||
let user = self.session.get_user();
|
if let Some(user) = user.and_then(|u| self.session.users.get_user(u.get_username())) {
|
||||||
builder.set_username(user.get_username());
|
self.fill(user, builder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(session: SessionHandle, mut builder: Builder) {
|
pub fn build(session: SessionHandle, mut builder: Builder) {
|
||||||
let this = Self::new(session);
|
let this = Self::new_self(session);
|
||||||
this.build_into(builder)
|
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(
|
fn list_roles(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: info::ListRolesParams,
|
_: info::ListRolesParams,
|
||||||
_: info::ListRolesResults,
|
mut result: info::ListRolesResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let user = self.session.get_user();
|
||||||
"method not implemented".to_string(),
|
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 {
|
impl manage::Server for User {
|
||||||
fn pwd(
|
fn pwd(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::PwdParams,
|
params: manage::PwdParams,
|
||||||
_: manage::PwdResults,
|
mut results: manage::PwdResults,
|
||||||
) -> ::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(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -57,35 +86,55 @@ impl admin::Server for User {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_: admin::GetUserInfoExtendedParams,
|
_: admin::GetUserInfoExtendedParams,
|
||||||
_: admin::GetUserInfoExtendedResults,
|
_: admin::GetUserInfoExtendedResults,
|
||||||
) -> ::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 add_role(
|
fn add_role(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: admin::AddRoleParams,
|
param: admin::AddRoleParams,
|
||||||
_: admin::AddRoleResults,
|
_: admin::AddRoleResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let rolename = pry!(pry!(pry!(param.get()).get_role()).get_name());
|
||||||
"method not implemented".to_string(),
|
|
||||||
))
|
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(
|
fn remove_role(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: admin::RemoveRoleParams,
|
param: admin::RemoveRoleParams,
|
||||||
_: admin::RemoveRoleResults,
|
_: admin::RemoveRoleResults,
|
||||||
) -> ::capnp::capability::Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
::capnp::capability::Promise::err(::capnp::Error::unimplemented(
|
let rolename = pry!(pry!(pry!(param.get()).get_role()).get_name());
|
||||||
"method not implemented".to_string(),
|
|
||||||
))
|
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(
|
fn pwd(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: admin::PwdParams,
|
_: admin::PwdParams,
|
||||||
_: admin::PwdResults,
|
_: admin::PwdResults,
|
||||||
) -> ::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(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use capnp::capability::Promise;
|
use capnp::capability::Promise;
|
||||||
|
use capnp_rpc::pry;
|
||||||
|
use libc::user;
|
||||||
use api::usersystem_capnp::user_system::{
|
use api::usersystem_capnp::user_system::{
|
||||||
info, manage, Server as UserSystem,
|
info, manage, Server as UserSystem,
|
||||||
self as system,
|
self as system,
|
||||||
@ -7,6 +9,7 @@ use crate::authorization::permissions::Permission;
|
|||||||
use crate::capnp::user::User;
|
use crate::capnp::user::User;
|
||||||
|
|
||||||
use crate::session::SessionHandle;
|
use crate::session::SessionHandle;
|
||||||
|
use crate::users::UserRef;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Users {
|
pub struct Users {
|
||||||
@ -56,11 +59,17 @@ impl manage::Server for Users {
|
|||||||
fn get_user_list(
|
fn get_user_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: manage::GetUserListParams,
|
_: manage::GetUserListParams,
|
||||||
_: manage::GetUserListResults,
|
mut result: manage::GetUserListResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
Promise::err(::capnp::Error::unimplemented(
|
let userdb = self.session.users.into_inner();
|
||||||
"method not implemented".to_string(),
|
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(
|
fn add_user(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -167,7 +167,7 @@ impl Resource {
|
|||||||
pub async fn try_update(&self, session: SessionHandle, new: Status) {
|
pub async fn try_update(&self, session: SessionHandle, new: Status) {
|
||||||
let old = self.get_state();
|
let old = self.get_state();
|
||||||
let old: &Archived<State> = old.as_ref();
|
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
|
if session.has_manage(self) // Default allow for managers
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ impl Resource {
|
|||||||
let s: &Archived<State> = state.as_ref();
|
let s: &Archived<State> = state.as_ref();
|
||||||
let i: &Archived<MachineState> = &s.inner;
|
let i: &Archived<MachineState> = &s.inner;
|
||||||
if let ArchivedStatus::InUse(user) = &i.state {
|
if let ArchivedStatus::InUse(user) = &i.state {
|
||||||
let current = session.get_user();
|
let current = session.get_user_ref();
|
||||||
if user == ¤t {
|
if user == ¤t {
|
||||||
self.set_state(MachineState::free(Some(current)));
|
self.set_state(MachineState::free(Some(current)));
|
||||||
}
|
}
|
||||||
@ -236,7 +236,7 @@ impl Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn visible(&self, session: &SessionHandle) -> bool {
|
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 {
|
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::authorization::roles::{Roles};
|
||||||
use crate::resources::Resource;
|
use crate::resources::Resource;
|
||||||
use crate::Users;
|
use crate::Users;
|
||||||
use crate::users::UserRef;
|
use crate::users::{db, UserRef};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -40,17 +40,21 @@ impl SessionManager {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SessionHandle {
|
pub struct SessionHandle {
|
||||||
users: Users,
|
pub users: Users,
|
||||||
roles: Roles,
|
pub roles: Roles,
|
||||||
|
|
||||||
user: UserRef,
|
user: UserRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionHandle {
|
impl SessionHandle {
|
||||||
pub fn get_user(&self) -> UserRef {
|
pub fn get_user_ref(&self) -> UserRef {
|
||||||
self.user.clone()
|
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 {
|
pub fn has_disclose(&self, resource: &Resource) -> bool {
|
||||||
if let Some(user) = self.users.get_user(self.user.get_username()) {
|
if let Some(user) = self.users.get_user(self.user.get_username()) {
|
||||||
self.roles.is_permitted(&user.userdata, &resource.get_required_privs().disclose)
|
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())
|
.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<()> {
|
pub fn load_file<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
||||||
let f = std::fs::read(path)?;
|
let f = std::fs::read(path)?;
|
||||||
let map: HashMap<String, UserData> = toml::from_slice(&f)?;
|
let map: HashMap<String, UserData> = toml::from_slice(&f)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user