forked from 2sys/phonograph
30 lines
955 B
Rust
30 lines
955 B
Rust
|
|
use axum::extract::{FromRequest, Request};
|
||
|
|
use axum_extra::extract::Form;
|
||
|
|
use serde::de::DeserializeOwned;
|
||
|
|
use validator::Validate;
|
||
|
|
|
||
|
|
use crate::errors::{AppError, bad_request};
|
||
|
|
|
||
|
|
/// Wrapper around [`axum_extra::extract::Form`] which returns an
|
||
|
|
/// [`AppError::BadRequest`] if [`validator`] checks on the target type do not
|
||
|
|
/// pass.
|
||
|
|
#[derive(Debug, Clone, Copy, Default)]
|
||
|
|
pub(crate) struct ValidatedForm<T: Validate>(pub(crate) T);
|
||
|
|
|
||
|
|
impl<T, S> FromRequest<S> for ValidatedForm<T>
|
||
|
|
where
|
||
|
|
T: DeserializeOwned + Validate,
|
||
|
|
S: Send + Sync,
|
||
|
|
{
|
||
|
|
type Rejection = AppError;
|
||
|
|
|
||
|
|
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
||
|
|
let Form(form) = Form::<T>::from_request(req, state)
|
||
|
|
.await
|
||
|
|
.map_err(|err| bad_request!("couldn't parse form: {err}"))?;
|
||
|
|
form.validate()
|
||
|
|
.map_err(|err| bad_request!("couldn't validate form: {err}"))?;
|
||
|
|
Ok(ValidatedForm(form))
|
||
|
|
}
|
||
|
|
}
|