use std::any::TypeId;
use std::marker::PhantomData;
use std::sync::Arc;
use poem::http::StatusCode;
use poem::{Error, FromRequest, Request, RequestBody, Result};
use crate::{Ability, ActionMarker, Subject};
pub struct Authorize<A, S>(PhantomData<fn() -> (A, S)>);
impl<'a, A, S> FromRequest<'a> for Authorize<A, S>
where
A: ActionMarker,
S: Subject,
{
async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
let ability = req.extensions().get::<Arc<Ability>>().ok_or_else(|| {
Error::from_string(
"missing request `Ability` — is the ability guard applied to this route?",
StatusCode::INTERNAL_SERVER_ERROR,
)
})?;
if ability.can_class(A::ACTION, TypeId::of::<S>()) {
Ok(Authorize(PhantomData))
} else {
Err(Error::from_string("forbidden", StatusCode::FORBIDDEN))
}
}
}