mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-12-22 19:53:49 +01:00
Better user
This commit is contained in:
parent
2fe6aa41c1
commit
006ae0af68
@ -15,6 +15,7 @@ mod machine;
|
||||
mod machines;
|
||||
use machines::Machines;
|
||||
|
||||
mod user;
|
||||
mod users;
|
||||
use users::Users;
|
||||
|
||||
|
27
src/api/user.rs
Normal file
27
src/api/user.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::db::access::PermRule;
|
||||
use crate::db::user as db;
|
||||
use crate::schema::user_capnp::user::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct User {
|
||||
user: db::User,
|
||||
perms: Vec<PermRule>,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn new(user: db::User, perms: Vec<PermRule>) -> Self {
|
||||
Self { user, perms }
|
||||
}
|
||||
|
||||
pub fn fill(&self, builder: &mut Builder) {
|
||||
builder.set_username(&self.user.id.uid);
|
||||
if let Some(ref realm) = &self.user.id.realm {
|
||||
let mut space = builder.reborrow().init_space();
|
||||
space.set_name(&realm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl info::Server for User {}
|
||||
impl manage::Server for User {}
|
||||
impl admin::Server for User {}
|
@ -19,8 +19,9 @@ impl user_system::Server for Users {
|
||||
fn info(
|
||||
&mut self,
|
||||
_: user_system::InfoParams,
|
||||
_: user_system::InfoResults,
|
||||
mut results: user_system::InfoResults,
|
||||
) -> Promise<(), capnp::Error> {
|
||||
results.get().set_info(capnp_rpc::new_client(self.clone()));
|
||||
Promise::ok(())
|
||||
}
|
||||
|
||||
@ -31,13 +32,23 @@ impl user_system::Server for Users {
|
||||
) -> Promise<(), capnp::Error> {
|
||||
let perm: &Permission = Permission::new("bffh.users.manage");
|
||||
if self.perms.iter().any(|rule| rule.match_perm(perm)) {
|
||||
results.get().set_manage(capnp_rpc::new_client(self.clone()));
|
||||
results
|
||||
.get()
|
||||
.set_manage(capnp_rpc::new_client(self.clone()));
|
||||
}
|
||||
|
||||
Promise::ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl info::Server for Users {}
|
||||
impl info::Server for Users {
|
||||
fn get_user_self(
|
||||
&mut self,
|
||||
_: info::GetUserSelfParams,
|
||||
mut results: info::GetUserSelfResults,
|
||||
) -> Promise<(), capnp::Error> {
|
||||
Promise::ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl manage::Server for Users {}
|
||||
|
@ -38,6 +38,14 @@ pub struct Config {
|
||||
pub init_connections: Box<[(String, String)]>,
|
||||
|
||||
pub db_path: PathBuf,
|
||||
|
||||
pub roles: HashMap<String, RoleConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RoleConfig {
|
||||
parents: Vec<String>,
|
||||
permissions: Vec<PermRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -97,6 +105,7 @@ impl Default for Config {
|
||||
]),
|
||||
|
||||
db_path: PathBuf::from("/run/bffh/database"),
|
||||
roles: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,15 +35,6 @@ impl Session {
|
||||
|
||||
Session { log, user, accessdb }
|
||||
}
|
||||
|
||||
/// Check if the current session has a certain permission
|
||||
pub async fn check_permission<P: AsRef<Permission>>(&self, perm: &P) -> Result<bool> {
|
||||
if let Some(user) = self.user.lock().await.as_ref() {
|
||||
self.accessdb.check(&user.data, perm).await
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConnectionHandler {
|
||||
|
@ -34,24 +34,6 @@ impl AccessControl {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn check<P: AsRef<Permission>>(&self, user: &UserData, perm: &P) -> Result<bool> {
|
||||
if self.internal.check(user, perm.as_ref())? {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
pub async fn check_roles<P: AsRef<Permission>>(&self, roles: &[RoleIdentifier], perm: &P)
|
||||
-> Result<bool>
|
||||
{
|
||||
if self.internal.check_roles(roles, perm.as_ref())? {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
pub fn collect_permrules(&self, user: &UserData) -> Result<Vec<PermRule>> {
|
||||
self.internal.collect_permrules(user)
|
||||
}
|
||||
@ -59,10 +41,6 @@ impl AccessControl {
|
||||
pub fn dump_roles(&self) -> Result<Vec<(RoleIdentifier, Role)>> {
|
||||
self.internal.dump_roles()
|
||||
}
|
||||
|
||||
pub fn get_role(&self, role_id: &RoleIdentifier) -> Result<Option<Role>> {
|
||||
self.internal.get_role(role_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AccessControl {
|
||||
|
@ -40,18 +40,18 @@ impl User {
|
||||
/// method or source
|
||||
pub struct UserId {
|
||||
/// Main User ID. Generally an user name or similar. Locally unique
|
||||
uid: String,
|
||||
pub uid: String,
|
||||
/// Sub user ID.
|
||||
///
|
||||
/// Can change scopes for permissions, e.g. having a +admin account with more permissions than
|
||||
/// the default account and +dashboard et.al. accounts that have restricted permissions for
|
||||
/// their applications
|
||||
subuid: Option<String>,
|
||||
pub subuid: Option<String>,
|
||||
/// Realm this account originates.
|
||||
///
|
||||
/// The Realm is usually described by a domain name but local policy may dictate an unrelated
|
||||
/// mapping
|
||||
realm: Option<String>,
|
||||
pub realm: Option<String>,
|
||||
}
|
||||
|
||||
impl UserId {
|
||||
|
@ -123,24 +123,34 @@ impl Machine {
|
||||
-> BoxFuture<'static, Result<ReturnToken>>
|
||||
{
|
||||
let this = self.clone();
|
||||
let udata: Option<UserData> = who.map(|u| u.data.clone());
|
||||
let perms: Vec<access::PermRule> = who
|
||||
.map(|u| self.access.collect_permrules(&u.data))
|
||||
.and_then(|result| result.ok())
|
||||
.unwrap_or(vec![]);
|
||||
let write: bool = perms.iter().any(|rule| rule.match_perm(&self.desc.privs.write));
|
||||
let manage: bool = perms.iter().any(|rule| rule.match_perm(&self.desc.privs.manage));
|
||||
|
||||
let f = async move {
|
||||
if let Some(udata) = udata {
|
||||
if this.access.check(&udata, &this.desc.privs.write).await? {
|
||||
let mut guard = this.inner.lock().await;
|
||||
guard.do_state_change(new_state);
|
||||
return Ok(ReturnToken::new(this.inner.clone()))
|
||||
}
|
||||
} else {
|
||||
if new_state == MachineState::free() {
|
||||
match &new_state.state {
|
||||
Status::Free => {
|
||||
let mut guard = this.inner.lock().await;
|
||||
guard.do_state_change(new_state);
|
||||
return Ok(ReturnToken::new(this.inner.clone()));
|
||||
},
|
||||
Status::InUse(_) | Status::ToCheck(_) if manage || write => {
|
||||
let mut guard = this.inner.lock().await;
|
||||
guard.do_state_change(new_state);
|
||||
return Ok(ReturnToken::new(this.inner.clone()))
|
||||
},
|
||||
Status::Blocked(_) | Status::Disabled | Status::Reserved(_) if manage => {
|
||||
let mut guard = this.inner.lock().await;
|
||||
guard.do_state_change(new_state);
|
||||
return Ok(ReturnToken::new(this.inner.clone()))
|
||||
},
|
||||
_ => {
|
||||
return Err(Error::Denied);
|
||||
}
|
||||
}
|
||||
|
||||
return Err(Error::Denied);
|
||||
};
|
||||
|
||||
Box::pin(f)
|
||||
|
Loading…
Reference in New Issue
Block a user