use axum::{
extract::{FromRequest, FromRequestParts, Request},
http::request::Parts,
response::{IntoResponse, Response},
};
use bytes::Bytes;
use crab_vault::auth::{Permission, error::AuthError};
use crate::error::api::{ApiError, ClientError};
#[allow(dead_code)]
pub struct PermissionExtractor(pub Permission);
impl<S> FromRequestParts<S> for PermissionExtractor
where
S: Send + Sync,
{
type Rejection = AuthError;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
parts
.extensions
.get::<Permission>()
.cloned()
.map(PermissionExtractor)
.ok_or(AuthError::InvalidToken)
}
}
pub struct RestrictedBytes(pub Bytes);
impl<S> FromRequest<S> for RestrictedBytes
where
S: Send + Sync,
{
type Rejection = Response;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let permission = match req.extensions().get::<Permission>() {
Some(p) => p,
None => unreachable!(),
}
.clone();
let body_bytes = match Bytes::from_request(req, state).await {
Ok(bytes) => bytes,
Err(e) => {
let api_error: ApiError = e.into();
return Err(api_error.into_response());
}
};
if !permission.compile().check_size(body_bytes.len()) {
return Err(ApiError::Client(ClientError::BodyTooLarge).into_response());
}
Ok(RestrictedBytes(body_bytes))
}
}