use crate::{
error::ApiError,
models::{OrgMember, OrgRole},
AppState,
};
use uuid::Uuid;
use super::permissions::Permission;
pub struct PermissionChecker<'a> {
state: &'a AppState,
}
impl<'a> PermissionChecker<'a> {
pub fn new(state: &'a AppState) -> Self {
Self { state }
}
pub async fn has_permission(
&self,
user_id: Uuid,
org_id: Uuid,
required: Permission,
) -> Result<bool, ApiError> {
let role = self.resolve_role(user_id, org_id).await?;
match role {
Some(role) => {
let granted = role.get_permissions();
Ok(Permission::is_granted(required, &granted))
}
None => Ok(false),
}
}
pub async fn require_permission(
&self,
user_id: Uuid,
org_id: Uuid,
required: Permission,
) -> Result<(), ApiError> {
if self.has_permission(user_id, org_id, required).await? {
Ok(())
} else {
Err(ApiError::PermissionDenied)
}
}
pub async fn get_permissions(
&self,
user_id: Uuid,
org_id: Uuid,
) -> Result<Vec<Permission>, ApiError> {
let role = self.resolve_role(user_id, org_id).await?;
match role {
Some(role) => Ok(role.get_permissions()),
None => Ok(Vec::new()),
}
}
async fn resolve_role(&self, user_id: Uuid, org_id: Uuid) -> Result<Option<OrgRole>, ApiError> {
let member = OrgMember::find(self.state.db.pool(), org_id, user_id)
.await
.map_err(ApiError::Database)?;
Ok(member.map(|m| m.role()))
}
}