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
+ }
}
}