This commit is contained in:
2022-09-19 10:22:06 +00:00
committed by GitHub
parent a04429838c
commit 774ee3e5ae
7 changed files with 154 additions and 16 deletions

View File

@@ -1,3 +1,5 @@
pub mod status;
pub mod user;
pub use status::{AuthStatusContext, AuthStatusRoute};
pub use user::{AuthUserContext, AuthUserRoute};

View File

@@ -44,11 +44,15 @@ impl AuthStatusRoute {
}
impl MatchRoute<Body, Body> for AuthStatusRoute {
fn get_route(&self, ctx: Arc<ServerContext>) -> Box<ResponseForType> {
Box::new(AuthStatusContext::new(ctx))
}
fn match_route(&self, req: &http::Request<Body>) -> bool {
self.regex.is_match(req.uri().path())
fn match_route(
&self,
ctx: &Arc<ServerContext>,
req: &http::Request<Body>,
) -> Option<Box<ResponseForType>> {
if self.regex.is_match(req.uri().path()) {
Some(Box::new(AuthStatusContext::new(Arc::clone(ctx))))
} else {
None
}
}
}

122
src/server/auth/user.rs Normal file
View File

@@ -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<ServerContext>,
action: Option<AuthUserAction>,
is_restful: bool,
}
impl AuthUserContext {
pub fn new(ctx: Arc<ServerContext>, action: Option<AuthUserAction>, is_restful: bool) -> Self {
Self {
ctx,
action,
is_restful,
}
}
}
#[async_trait]
impl ResponseJsonFor<Body> for AuthUserContext {
async fn response_json(
&self,
req: Request<Body>,
) -> Result<Response<JsonValue>, 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<Body, Body> for AuthUserRoute {
fn match_route(
&self,
ctx: &Arc<ServerContext>,
req: &http::Request<Body>,
) -> Option<Box<ResponseForType>> {
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,
}
}
}

View File

@@ -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;

View File

@@ -19,6 +19,7 @@ impl ServerRoutes {
let mut routes: Vec<Box<RouteType>> = 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<ServerContext>,
) -> Option<Box<ResponseForType>> {
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

View File

@@ -7,8 +7,11 @@ use json::JsonValue;
use std::sync::Arc;
pub trait MatchRoute<T, R> {
fn get_route(&self, ctx: Arc<ServerContext>) -> Box<dyn ResponseFor<T, R> + Send + Sync>;
fn match_route(&self, req: &Request<T>) -> bool;
fn match_route(
&self,
ctx: &Arc<ServerContext>,
req: &Request<T>,
) -> Option<Box<dyn ResponseFor<T, R> + Send + Sync>>;
}
#[async_trait]

View File

@@ -43,11 +43,15 @@ impl VersionRoute {
}
impl MatchRoute<Body, Body> for VersionRoute {
fn get_route(&self, ctx: Arc<ServerContext>) -> Box<ResponseForType> {
Box::new(VersionContext::new(ctx))
}
fn match_route(&self, req: &http::Request<Body>) -> bool {
self.regex.is_match(req.uri().path())
fn match_route(
&self,
ctx: &Arc<ServerContext>,
req: &http::Request<Body>,
) -> Option<Box<ResponseForType>> {
if self.regex.is_match(req.uri().path()) {
Some(Box::new(VersionContext::new(Arc::clone(ctx))))
} else {
None
}
}
}