Skip to content

Commit

Permalink
editoast: fix grant and revoke role to group using CLI
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Amsallem <[email protected]>
  • Loading branch information
flomonster committed Nov 8, 2024
1 parent b777099 commit ee8a74d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 18 deletions.
15 changes: 15 additions & 0 deletions editoast/editoast_authz/src/authorizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ use crate::roles::BuiltinRoleSet;

pub type UserIdentity = String;
pub type UserName = String;
pub type GroupName = String;

#[derive(Debug, Clone)]
pub struct UserInfo {
pub identity: UserIdentity,
pub name: UserName,
}

#[derive(Debug, Clone)]
pub struct GroupInfo {
pub name: GroupName,
}

#[derive(Clone)]
pub struct Authorizer<S: StorageDriver> {
user: UserInfo,
Expand All @@ -37,6 +43,11 @@ pub trait StorageDriver: Clone {
user_id: i64,
) -> impl Future<Output = Result<Option<UserInfo>, Self::Error>> + Send;

fn get_group_info(
&self,
group_id: i64,
) -> impl Future<Output = Result<Option<GroupInfo>, Self::Error>> + Send;

fn ensure_user(&self, user: &UserInfo)
-> impl Future<Output = Result<i64, Self::Error>> + Send;

Expand Down Expand Up @@ -339,5 +350,9 @@ mod tests {
});
Ok(user_info)
}

async fn get_group_info(&self, _group_id: i64) -> Result<Option<GroupInfo>, Self::Error> {
Ok(None)
}
}
}
51 changes: 39 additions & 12 deletions editoast/src/client/roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{collections::HashSet, fmt::Display, sync::Arc};
use anyhow::{anyhow, bail};
use clap::{Args, Subcommand};
use editoast_authz::{
authorizer::{StorageDriver, UserInfo},
authorizer::{GroupInfo, StorageDriver, UserInfo},
roles::BuiltinRoleSet,
BuiltinRole,
};
Expand Down Expand Up @@ -55,16 +55,41 @@ pub fn list_roles() {
#[derive(Debug)]
struct Subject {
id: i64,
info: UserInfo,
info: SubjectInfo,
}
impl Subject {
/// Create a new subject representing a user
pub fn new_user(id: i64, info: UserInfo) -> Self {
Self {
id,
info: SubjectInfo::User(info),
}
}

/// Create a new subject representing a group
pub fn new_group(id: i64, info: GroupInfo) -> Self {
Self {
id,
info: SubjectInfo::Group(info),
}
}
}

#[derive(Debug)]
enum SubjectInfo {
User(UserInfo),
Group(GroupInfo),
}

impl Display for Subject {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
id,
info: UserInfo { identity, name },
} = self;
write!(f, "{identity}#{id} ({name})")
let Self { id, info } = self;
match info {
SubjectInfo::User(UserInfo { name, identity }) => {
write!(f, "User {}#{} ({})", identity, id, name)
}
SubjectInfo::Group(info) => write!(f, "Group #{} ({})", id, info.name),
}
}
}

Expand All @@ -78,13 +103,15 @@ async fn parse_and_fetch_subject(
let uid = driver.get_user_id(subject).await?;
uid.ok_or_else(|| anyhow!("No subject with identity '{subject}' found"))?
};
if let Some(info) = driver.get_user_info(id).await? {
let subject = Subject { id, info };
info!("Subject {subject}");
Ok(subject)
let subject = if let Some(info) = driver.get_user_info(id).await? {
Subject::new_user(id, info)
} else if let Some(info) = driver.get_group_info(id).await? {
Subject::new_group(id, info)
} else {
bail!("No subject found with ID {id}");
}
};
info!("{subject}");
Ok(subject)
}

pub async fn list_subject_roles(
Expand Down
25 changes: 19 additions & 6 deletions editoast/src/models/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{collections::HashSet, sync::Arc};
use diesel::{dsl, prelude::*};
use diesel_async::{scoped_futures::ScopedFutureExt as _, RunQueryDsl};
use editoast_authz::{
authorizer::{StorageDriver, UserIdentity, UserInfo},
authorizer::{GroupInfo, StorageDriver, UserIdentity, UserInfo},
roles::BuiltinRoleSet,
};
use editoast_models::DbConnectionPoolV2;
Expand Down Expand Up @@ -60,13 +60,26 @@ impl<B: BuiltinRoleSet + Send + Sync> StorageDriver for PgAuthDriver<B> {
.filter(authn_user::id.eq(user_id))
.first::<(String, Option<String>)>(conn.write().await.deref_mut())
.await
.optional()
.map(|res| {
res.map(|(identity, name)| UserInfo {
.optional()?
.map(|(identity, name)| {
UserInfo {
identity,
name: name.unwrap_or_default(), // FIXME: make the column non-nullable
})
})?;
}
});
Ok(info)
}

#[tracing::instrument(skip_all, fields(%group_id), ret(level = Level::DEBUG), err)]
async fn get_group_info(&self, group_id: i64) -> Result<Option<GroupInfo>, Self::Error> {
let conn = self.pool.get().await?;
let info = authn_group::table
.select(authn_group::name)
.filter(authn_group::id.eq(group_id))
.first::<String>(conn.write().await.deref_mut())
.await
.optional()?
.map(|name| GroupInfo { name });
Ok(info)
}

Expand Down

0 comments on commit ee8a74d

Please sign in to comment.