From 774ee3e5aebe387e4ef6c929c7edfa997efa69c8 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Mon, 19 Sep 2022 10:22:06 +0000 Subject: [PATCH] Update --- src/server/auth/mod.rs | 2 + src/server/auth/status.rs | 16 +++-- src/server/auth/user.rs | 122 ++++++++++++++++++++++++++++++++++++++ src/server/preclude.rs | 1 + src/server/route.rs | 6 +- src/server/traits.rs | 7 ++- src/server/version.rs | 16 +++-- 7 files changed, 154 insertions(+), 16 deletions(-) create mode 100644 src/server/auth/user.rs diff --git a/src/server/auth/mod.rs b/src/server/auth/mod.rs index 02d39a3..7cb9742 100644 --- a/src/server/auth/mod.rs +++ b/src/server/auth/mod.rs @@ -1,3 +1,5 @@ pub mod status; +pub mod user; pub use status::{AuthStatusContext, AuthStatusRoute}; +pub use user::{AuthUserContext, AuthUserRoute}; diff --git a/src/server/auth/status.rs b/src/server/auth/status.rs index a8de07b..c50e386 100644 --- a/src/server/auth/status.rs +++ b/src/server/auth/status.rs @@ -44,11 +44,15 @@ impl AuthStatusRoute { } impl MatchRoute for AuthStatusRoute { - fn get_route(&self, ctx: Arc) -> Box { - Box::new(AuthStatusContext::new(ctx)) - } - - fn match_route(&self, req: &http::Request) -> bool { - self.regex.is_match(req.uri().path()) + fn match_route( + &self, + ctx: &Arc, + req: &http::Request, + ) -> Option> { + if self.regex.is_match(req.uri().path()) { + Some(Box::new(AuthStatusContext::new(Arc::clone(ctx)))) + } else { + None + } } } diff --git a/src/server/auth/user.rs b/src/server/auth/user.rs new file mode 100644 index 0000000..12c519b --- /dev/null +++ b/src/server/auth/user.rs @@ -0,0 +1,122 @@ +use super::super::preclude::*; + +#[derive(Clone, Debug)] +/// Action to perform on a user. +pub enum AuthUserAction { + /// Add a new user. + Add, +} + +pub struct AuthUserContext { + ctx: Arc, + action: Option, + is_restful: bool, +} + +impl AuthUserContext { + pub fn new(ctx: Arc, action: Option, is_restful: bool) -> Self { + Self { + ctx, + action, + is_restful, + } + } +} + +#[async_trait] +impl ResponseJsonFor for AuthUserContext { + async fn response_json( + &self, + req: Request, + ) -> Result, PixivDownloaderError> { + let builder = if self.is_restful { + filter_http_methods!( + req, + json::object! {}, + true, + self.ctx, + allow_headers = [CONTENT_TYPE, X_SIGN, X_TOKEN_ID], + OPTIONS, + PUT, + ); + builder + } else { + filter_http_methods!( + req, + json::object! {}, + true, + self.ctx, + allow_headers = [CONTENT_TYPE, X_SIGN, X_TOKEN_ID], + GET, + OPTIONS, + POST, + ); + builder + }; + match &self.action { + Some(act) => {} + None => { + panic!("No action specified for AuthUserContext."); + } + } + Ok(builder.body(json::object! {})?) + } +} + +pub struct AuthUserRoute { + regex: Regex, +} + +impl AuthUserRoute { + pub fn new() -> Self { + Self { + regex: Regex::new(r"^(/+api)?/+auth/+user(/+add)?$").unwrap(), + } + } +} + +impl MatchRoute for AuthUserRoute { + fn match_route( + &self, + ctx: &Arc, + req: &http::Request, + ) -> Option> { + let path = req.uri().path(); + let pat = self.regex.captures(path); + match pat { + Some(cap) => { + if req.method() == Method::OPTIONS { + return Some(Box::new(AuthUserContext::new( + Arc::clone(ctx), + None, + cap.get(2).is_none(), + ))); + } + let cap2 = cap.get(2); + let is_restful = cap2.is_none(); + let action = match cap2 { + Some(m) => { + let m = m.as_str().trim_start_matches("/"); + match m { + "add" => Some(AuthUserAction::Add), + _ => return None, + } + } + None => { + if req.method() == Method::PUT { + Some(AuthUserAction::Add) + } else { + None + } + } + }; + Some(Box::new(AuthUserContext::new( + Arc::clone(ctx), + action, + is_restful, + ))) + } + None => None, + } + } +} diff --git a/src/server/preclude.rs b/src/server/preclude.rs index 1a46fae..412c468 100644 --- a/src/server/preclude.rs +++ b/src/server/preclude.rs @@ -4,6 +4,7 @@ pub use super::route::ResponseForType; pub use super::traits::{MatchRoute, ResponseFor, ResponseJsonFor}; pub use crate::error::PixivDownloaderError; pub use hyper::Body; +pub use hyper::Method; pub use hyper::Request; pub use hyper::Response; pub use json::JsonValue; diff --git a/src/server/route.rs b/src/server/route.rs index 5e8efba..9798d86 100644 --- a/src/server/route.rs +++ b/src/server/route.rs @@ -19,6 +19,7 @@ impl ServerRoutes { let mut routes: Vec> = Vec::new(); routes.push(Box::new(VersionRoute::new())); routes.push(Box::new(AuthStatusRoute::new())); + routes.push(Box::new(AuthUserRoute::new())); Self { routes } } @@ -28,8 +29,9 @@ impl ServerRoutes { ctx: &Arc, ) -> Option> { for i in self.routes.iter() { - if i.match_route(req) { - return Some(i.get_route(Arc::clone(ctx))); + match i.match_route(&ctx, req) { + Some(r) => return Some(r), + None => {} } } None diff --git a/src/server/traits.rs b/src/server/traits.rs index 3158f85..ac5fb6c 100644 --- a/src/server/traits.rs +++ b/src/server/traits.rs @@ -7,8 +7,11 @@ use json::JsonValue; use std::sync::Arc; pub trait MatchRoute { - fn get_route(&self, ctx: Arc) -> Box + Send + Sync>; - fn match_route(&self, req: &Request) -> bool; + fn match_route( + &self, + ctx: &Arc, + req: &Request, + ) -> Option + Send + Sync>>; } #[async_trait] diff --git a/src/server/version.rs b/src/server/version.rs index 1cb688c..49fb566 100644 --- a/src/server/version.rs +++ b/src/server/version.rs @@ -43,11 +43,15 @@ impl VersionRoute { } impl MatchRoute for VersionRoute { - fn get_route(&self, ctx: Arc) -> Box { - Box::new(VersionContext::new(ctx)) - } - - fn match_route(&self, req: &http::Request) -> bool { - self.regex.is_match(req.uri().path()) + fn match_route( + &self, + ctx: &Arc, + req: &http::Request, + ) -> Option> { + if self.regex.is_match(req.uri().path()) { + Some(Box::new(VersionContext::new(Arc::clone(ctx)))) + } else { + None + } } }