mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-10 17:43:23 +01:00
Better user
This commit is contained in:
parent
2fe6aa41c1
commit
006ae0af68
@ -15,6 +15,7 @@ mod machine;
|
|||||||
mod machines;
|
mod machines;
|
||||||
use machines::Machines;
|
use machines::Machines;
|
||||||
|
|
||||||
|
mod user;
|
||||||
mod users;
|
mod users;
|
||||||
use users::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(
|
fn info(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: user_system::InfoParams,
|
_: user_system::InfoParams,
|
||||||
_: user_system::InfoResults,
|
mut results: user_system::InfoResults,
|
||||||
) -> Promise<(), capnp::Error> {
|
) -> Promise<(), capnp::Error> {
|
||||||
|
results.get().set_info(capnp_rpc::new_client(self.clone()));
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,13 +32,23 @@ impl user_system::Server for Users {
|
|||||||
) -> Promise<(), capnp::Error> {
|
) -> Promise<(), capnp::Error> {
|
||||||
let perm: &Permission = Permission::new("bffh.users.manage");
|
let perm: &Permission = Permission::new("bffh.users.manage");
|
||||||
if self.perms.iter().any(|rule| rule.match_perm(perm)) {
|
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(())
|
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 {}
|
impl manage::Server for Users {}
|
||||||
|
@ -38,6 +38,14 @@ pub struct Config {
|
|||||||
pub init_connections: Box<[(String, String)]>,
|
pub init_connections: Box<[(String, String)]>,
|
||||||
|
|
||||||
pub db_path: PathBuf,
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -97,6 +105,7 @@ impl Default for Config {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
db_path: PathBuf::from("/run/bffh/database"),
|
db_path: PathBuf::from("/run/bffh/database"),
|
||||||
|
roles: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,15 +35,6 @@ impl Session {
|
|||||||
|
|
||||||
Session { log, user, accessdb }
|
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 {
|
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>> {
|
pub fn collect_permrules(&self, user: &UserData) -> Result<Vec<PermRule>> {
|
||||||
self.internal.collect_permrules(user)
|
self.internal.collect_permrules(user)
|
||||||
}
|
}
|
||||||
@ -59,10 +41,6 @@ impl AccessControl {
|
|||||||
pub fn dump_roles(&self) -> Result<Vec<(RoleIdentifier, Role)>> {
|
pub fn dump_roles(&self) -> Result<Vec<(RoleIdentifier, Role)>> {
|
||||||
self.internal.dump_roles()
|
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 {
|
impl fmt::Debug for AccessControl {
|
||||||
|
@ -40,18 +40,18 @@ impl User {
|
|||||||
/// method or source
|
/// method or source
|
||||||
pub struct UserId {
|
pub struct UserId {
|
||||||
/// Main User ID. Generally an user name or similar. Locally unique
|
/// Main User ID. Generally an user name or similar. Locally unique
|
||||||
uid: String,
|
pub uid: String,
|
||||||
/// Sub user ID.
|
/// Sub user ID.
|
||||||
///
|
///
|
||||||
/// Can change scopes for permissions, e.g. having a +admin account with more permissions than
|
/// 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
|
/// the default account and +dashboard et.al. accounts that have restricted permissions for
|
||||||
/// their applications
|
/// their applications
|
||||||
subuid: Option<String>,
|
pub subuid: Option<String>,
|
||||||
/// Realm this account originates.
|
/// Realm this account originates.
|
||||||
///
|
///
|
||||||
/// The Realm is usually described by a domain name but local policy may dictate an unrelated
|
/// The Realm is usually described by a domain name but local policy may dictate an unrelated
|
||||||
/// mapping
|
/// mapping
|
||||||
realm: Option<String>,
|
pub realm: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserId {
|
impl UserId {
|
||||||
|
@ -123,24 +123,34 @@ impl Machine {
|
|||||||
-> BoxFuture<'static, Result<ReturnToken>>
|
-> BoxFuture<'static, Result<ReturnToken>>
|
||||||
{
|
{
|
||||||
let this = self.clone();
|
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 {
|
let f = async move {
|
||||||
if let Some(udata) = udata {
|
match &new_state.state {
|
||||||
if this.access.check(&udata, &this.desc.privs.write).await? {
|
Status::Free => {
|
||||||
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() {
|
|
||||||
let mut guard = this.inner.lock().await;
|
let mut guard = this.inner.lock().await;
|
||||||
guard.do_state_change(new_state);
|
guard.do_state_change(new_state);
|
||||||
return Ok(ReturnToken::new(this.inner.clone()));
|
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)
|
Box::pin(f)
|
||||||
|
Loading…
Reference in New Issue
Block a user