diff options
Diffstat (limited to 'src/web/extract.rs')
-rw-r--r-- | src/web/extract.rs | 139 |
1 files changed, 0 insertions, 139 deletions
diff --git a/src/web/extract.rs b/src/web/extract.rs deleted file mode 100644 index 4b6cd7c..0000000 --- a/src/web/extract.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::{ - io::Read, - net::{IpAddr, SocketAddr}, -}; - -use axum::{ - async_trait, - body::HttpBody, - extract::{ConnectInfo, FromRequest, FromRequestParts}, - http::{request::Parts, Request}, - response::Response, - BoxError, -}; -use bytes::Bytes; -use moka::future::Cache; -use tower_cookies::Cookies; - -use super::http::text; - -pub struct Authorized; - -#[async_trait] -impl<S> FromRequestParts<S> for Authorized -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { - let Ok(Some(cookies)) = Option::<Cookies>::from_request_parts(parts, state).await else { - return Err(text(403, "No cookies provided")) - }; - - let Some(token) = cookies.get("auth") else { - return Err(text(403, "No auth token provided")) - }; - - let auth_ip: IpAddr; - { - let Some(cache) = parts.extensions.get::<Cache<String, IpAddr>>() else { - return Err(text(500, "Failed to load auth store")) - }; - - let Some(ip) = cache.get(token.value()) else { - return Err(text(401, "Unauthorized")) - }; - - auth_ip = ip - } - - let Ok(Some(RequestIp(ip))) = Option::<RequestIp>::from_request_parts(parts, state).await else { - return Err(text(403, "You have no ip")) - }; - - if auth_ip != ip { - return Err(text(403, "Auth token does not match current ip")); - } - - Ok(Self) - } -} - -pub struct RequestIp(pub IpAddr); - -#[async_trait] -impl<S> FromRequestParts<S> for RequestIp -where - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> { - let headers = &parts.headers; - - let forwardedfor = headers - .get("x-forwarded-for") - .and_then(|h| h.to_str().ok()) - .and_then(|h| { - h.split(',') - .rev() - .find_map(|s| s.trim().parse::<IpAddr>().ok()) - }); - - if let Some(forwardedfor) = forwardedfor { - return Ok(Self(forwardedfor)); - } - - let realip = headers - .get("x-real-ip") - .and_then(|hv| hv.to_str().ok()) - .and_then(|s| s.parse::<IpAddr>().ok()); - - if let Some(realip) = realip { - return Ok(Self(realip)); - } - - let realip = headers - .get("x-real-ip") - .and_then(|hv| hv.to_str().ok()) - .and_then(|s| s.parse::<IpAddr>().ok()); - - if let Some(realip) = realip { - return Ok(Self(realip)); - } - - let info = parts.extensions.get::<ConnectInfo<SocketAddr>>(); - - if let Some(info) = info { - return Ok(Self(info.0.ip())); - } - - Err(text(403, "You have no ip")) - } -} - -pub struct Body(pub String); - -#[async_trait] -impl<S, B> FromRequest<S, B> for Body -where - B: HttpBody + Sync + Send + 'static, - B::Data: Send, - B::Error: Into<BoxError>, - S: Send + Sync, -{ - type Rejection = Response; - - async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { - let Ok(bytes) = Bytes::from_request(req, state).await else { - return Err(text(413, "Payload too large")); - }; - - let Ok(body) = String::from_utf8(bytes.bytes().flatten().collect()) else { - return Err(text(400, "Invalid utf8 body")) - }; - - Ok(Self(body)) - } -} |