Skip to content
Clone
eeff292
104 lines 2.5 KB Rust
use std::collections::HashSet;
use models::space::spaces;
use crate::authority;
use crate::errors::SpaceError;
use crate::services::service::SpaceService;
pub const VIEW_SPACE: &str = "view_space";
pub const READ: &str = "read";
pub const MESSAGE: &str = "message";
pub const MANAGE_MEMBERS: &str = "manage_members";
pub const MANAGE_ROLES: &str = "manage_roles";
pub const MANAGE_INVITES: &str = "manage_invites";
pub const MANAGE_BANS: &str = "manage_bans";
pub const MANAGE_CHANNELS: &str = "manage_channels";
pub const ALL_PERMISSIONS: [&str; 8] = [
VIEW_SPACE,
READ,
MESSAGE,
MANAGE_MEMBERS,
MANAGE_ROLES,
MANAGE_INVITES,
MANAGE_BANS,
MANAGE_CHANNELS,
];
#[derive(Debug, Clone, Default)]
pub struct Permissions {
granted: HashSet<String>,
}
impl Permissions {
pub fn owner() -> Self {
Self {
granted: ALL_PERMISSIONS.into_iter().map(String::from).collect(),
}
}
pub fn from_vec(values: Vec<String>) -> Self {
Self {
granted: values.into_iter().collect(),
}
}
pub fn has(&self, action: &str) -> bool {
self.granted.contains(action)
}
pub fn into_vec(self) -> Vec<String> {
let mut v: Vec<String> = self.granted.into_iter().collect();
v.sort();
v.dedup();
v
}
}
pub async fn assert_not_banned(
state: &SpaceService,
space_id: uuid::Uuid,
user_id: i64,
) -> Result<(), SpaceError> {
if let Ok(Some(member)) = authority::member(state, space_id, user_id).await
&& member.status() == models::space::MemberStatus::Banned
{
return Err(SpaceError::Forbidden);
}
Ok(())
}
pub async fn effective_permissions(
state: &SpaceService,
space: &spaces::Model,
user_id: i64,
) -> Result<Permissions, SpaceError> {
let granted = crate::services::permission::effective_for(
&state.access.database,
&state.access.cache,
space.id,
user_id,
)
.await?
.into_iter()
.filter_map(|permission| permission.strip_prefix("space.").map(str::to_owned))
.collect::<Vec<_>>();
if granted.is_empty() {
return Err(SpaceError::Forbidden);
}
Ok(Permissions::from_vec(granted))
}
pub async fn require_perm(
service: &SpaceService,
space: &spaces::Model,
caller: i64,
action: &str,
) -> Result<(), SpaceError> {
let perms = effective_permissions(service, space, caller).await?;
if !perms.has(action) {
return Err(SpaceError::Forbidden);
}
Ok(())
}