diff --git a/src/api.rs b/src/api.rs index 3cfb86f..7621844 100644 --- a/src/api.rs +++ b/src/api.rs @@ -15,6 +15,7 @@ mod machine; mod machines; use machines::Machines; +mod user; mod users; use users::Users; diff --git a/src/api/user.rs b/src/api/user.rs new file mode 100644 index 0000000..34bf8e5 --- /dev/null +++ b/src/api/user.rs @@ -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, +} + +impl User { + pub fn new(user: db::User, perms: Vec) -> 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 {} diff --git a/src/api/users.rs b/src/api/users.rs index c86e6c6..ad5cce3 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -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 {} diff --git a/src/config.rs b/src/config.rs index d0f114c..a78cb5c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,14 @@ pub struct Config { pub init_connections: Box<[(String, String)]>, pub db_path: PathBuf, + + pub roles: HashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RoleConfig { + parents: Vec, + permissions: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -97,6 +105,7 @@ impl Default for Config { ]), db_path: PathBuf::from("/run/bffh/database"), + roles: HashMap::new(), } } } diff --git a/src/connection.rs b/src/connection.rs index 00cac66..a3af8ac 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -35,15 +35,6 @@ impl Session { Session { log, user, accessdb } } - - /// Check if the current session has a certain permission - pub async fn check_permission>(&self, perm: &P) -> Result { - if let Some(user) = self.user.lock().await.as_ref() { - self.accessdb.check(&user.data, perm).await - } else { - Ok(false) - } - } } pub struct ConnectionHandler { diff --git a/src/db/access.rs b/src/db/access.rs index af5efc0..dae67d0 100644 --- a/src/db/access.rs +++ b/src/db/access.rs @@ -34,24 +34,6 @@ impl AccessControl { } } - pub async fn check>(&self, user: &UserData, perm: &P) -> Result { - if self.internal.check(user, perm.as_ref())? { - return Ok(true); - } - - return Ok(false); - } - - pub async fn check_roles>(&self, roles: &[RoleIdentifier], perm: &P) - -> Result - { - if self.internal.check_roles(roles, perm.as_ref())? { - return Ok(true); - } - - return Ok(false); - } - pub fn collect_permrules(&self, user: &UserData) -> Result> { self.internal.collect_permrules(user) } @@ -59,10 +41,6 @@ impl AccessControl { pub fn dump_roles(&self) -> Result> { self.internal.dump_roles() } - - pub fn get_role(&self, role_id: &RoleIdentifier) -> Result> { - self.internal.get_role(role_id) - } } impl fmt::Debug for AccessControl { diff --git a/src/db/user.rs b/src/db/user.rs index 2a174e0..f807776 100644 --- a/src/db/user.rs +++ b/src/db/user.rs @@ -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, + pub subuid: Option, /// Realm this account originates. /// /// The Realm is usually described by a domain name but local policy may dictate an unrelated /// mapping - realm: Option, + pub realm: Option, } impl UserId { diff --git a/src/machine.rs b/src/machine.rs index fe1884a..1c25407 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -123,24 +123,34 @@ impl Machine { -> BoxFuture<'static, Result> { let this = self.clone(); - let udata: Option = who.map(|u| u.data.clone()); + let perms: Vec = 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)