diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index a9045f27..5c8039d5 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -31,6 +31,7 @@ pub fn services(cfg: &mut ServiceConfig) { auth::services(cfg); account::services(cfg); mcaptcha::services(cfg); + pow::services(cfg); } #[cfg(test)] diff --git a/src/api/v1/pow/get_config.rs b/src/api/v1/pow/get_config.rs index 82c07bce..3cf2591b 100644 --- a/src/api/v1/pow/get_config.rs +++ b/src/api/v1/pow/get_config.rs @@ -16,7 +16,7 @@ */ use actix::prelude::*; -use actix_web::{post, web, HttpResponse, Responder}; +use actix_web::{web, HttpResponse, Responder}; use m_captcha::{defense::LevelBuilder, master::AddSiteBuilder, DefenseBuilder, MCaptchaBuilder}; use serde::{Deserialize, Serialize}; @@ -39,8 +39,6 @@ pub struct GetConfigPayload { // API keys are mcaptcha actor names -#[post("/config")] -//#[post("/pow/config")] pub async fn get_config( payload: web::Json, data: web::Data, @@ -154,8 +152,6 @@ mod tests { const NAME: &str = "powusrworks"; const PASSWORD: &str = "testingpas"; const EMAIL: &str = "randomuser@a.com"; - const GET_URL: &str = "/api/v1/pow/config"; - // const UPDATE_URL: &str = "/api/v1/mcaptcha/domain/token/duration/update"; { let data = Data::new().await; @@ -175,7 +171,7 @@ mod tests { let get_config_resp = test::call_service( &mut app, - post_request!(&get_config_payload, GET_URL) + post_request!(&get_config_payload, V1_API_ROUTES.pow.get_config) .cookie(cookies.clone()) .to_request(), ) diff --git a/src/api/v1/pow/mod.rs b/src/api/v1/pow/mod.rs index bb61a4dd..906a9fc4 100644 --- a/src/api/v1/pow/mod.rs +++ b/src/api/v1/pow/mod.rs @@ -25,27 +25,46 @@ pub mod verify_token; pub use super::mcaptcha::duration::GetDurationResp; pub use super::mcaptcha::levels::I32Levels; -// middleware protected by scope pub fn services(cfg: &mut web::ServiceConfig) { - let captcha_api_cors = Cors::default() - .allow_any_origin() - .allowed_methods(vec!["POST"]) - .allow_any_header() - .max_age(0) - .send_wildcard(); + use crate::define_resource; + use crate::V1_API_ROUTES; - cfg.service( - web::scope("/api/v1/pow/") - .wrap(captcha_api_cors) - .configure(intenral_services), + define_resource!( + cfg, + V1_API_ROUTES.pow.verify_pow, + Methods::CorsAllowAllPost, + verify_pow::verify_pow + ); + + define_resource!( + cfg, + V1_API_ROUTES.pow.get_config, + Methods::CorsAllowAllPost, + get_config::get_config + ); + + define_resource!( + cfg, + V1_API_ROUTES.pow.validate_captcha_token, + Methods::CorsAllowAllPost, + verify_token::validate_captcha_token ); } -// internal route aggregator, it's easy to use macros -// to denote paths than having to type it out -// but remember, final path = scope + macro path -fn intenral_services(cfg: &mut web::ServiceConfig) { - cfg.service(get_config::get_config); - cfg.service(verify_pow::verify_pow); - cfg.service(verify_token::validate_captcha_token); +pub mod routes { + pub struct PoW { + pub get_config: &'static str, + pub verify_pow: &'static str, + pub validate_captcha_token: &'static str, + } + + impl PoW { + pub const fn new() -> Self { + PoW { + get_config: "/api/v1/pow/config", + verify_pow: "/api/v1/pow/verify", + validate_captcha_token: "/api/v1/pow/siteverify", + } + } + } } diff --git a/src/api/v1/pow/verify_pow.rs b/src/api/v1/pow/verify_pow.rs index 5f443fb3..52af58f6 100644 --- a/src/api/v1/pow/verify_pow.rs +++ b/src/api/v1/pow/verify_pow.rs @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -use actix_web::{post, web, HttpResponse, Responder}; +use actix_web::{web, HttpResponse, Responder}; use m_captcha::pow::Work; use serde::{Deserialize, Serialize}; @@ -29,7 +29,6 @@ pub struct ValidationToken { // API keys are mcaptcha actor names -#[post("/verify")] pub async fn verify_pow( payload: web::Json, data: web::Data, @@ -55,9 +54,6 @@ mod tests { const NAME: &str = "powverifyusr"; const PASSWORD: &str = "testingpas"; const EMAIL: &str = "verifyuser@a.com"; - const VERIFY_URL: &str = "/api/v1/pow/verify"; - const GET_URL: &str = "/api/v1/pow/config"; - // const UPDATE_URL: &str = "/api/v1/mcaptcha/domain/token/duration/update"; { let data = Data::new().await; @@ -76,7 +72,7 @@ mod tests { let get_config_resp = test::call_service( &mut app, - post_request!(&get_config_payload, GET_URL).to_request(), + post_request!(&get_config_payload, V1_API_ROUTES.pow.get_config).to_request(), ) .await; assert_eq!(get_config_resp.status(), StatusCode::OK); @@ -97,12 +93,18 @@ mod tests { key: token_key.key.clone(), }; - let pow_verify_resp = - test::call_service(&mut app, post_request!(&work, VERIFY_URL).to_request()).await; + let pow_verify_resp = test::call_service( + &mut app, + post_request!(&work, V1_API_ROUTES.pow.verify_pow).to_request(), + ) + .await; assert_eq!(pow_verify_resp.status(), StatusCode::OK); - let string_not_found = - test::call_service(&mut app, post_request!(&work, VERIFY_URL).to_request()).await; + let string_not_found = test::call_service( + &mut app, + post_request!(&work, V1_API_ROUTES.pow.verify_pow).to_request(), + ) + .await; assert_eq!(string_not_found.status(), StatusCode::BAD_REQUEST); let err: ErrorToResponse = test::read_body_json(string_not_found).await; assert_eq!( @@ -113,12 +115,12 @@ mod tests { ) ); - let pow_config_resp = test::call_service( - &mut app, - post_request!(&get_config_payload, GET_URL).to_request(), - ) - .await; - assert_eq!(pow_config_resp.status(), StatusCode::OK); + // let pow_config_resp = test::call_service( + // &mut app, + // post_request!(&get_config_payload, V1_API_ROUTES.pow.get_config).to_request(), + // ) + // .await; + // assert_eq!(pow_config_resp.status(), StatusCode::OK); // I'm not checking for errors because changing work.result triggered // InssuficientDifficulty, which is possible becuase m_captcha calculates // difficulty with the submitted result. Besides, this endpoint is merely diff --git a/src/api/v1/pow/verify_token.rs b/src/api/v1/pow/verify_token.rs index f64b37fc..1b80ebf9 100644 --- a/src/api/v1/pow/verify_token.rs +++ b/src/api/v1/pow/verify_token.rs @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -use actix_web::{post, web, HttpResponse, Responder}; +use actix_web::{web, HttpResponse, Responder}; use m_captcha::cache::messages::VerifyCaptchaResult; use serde::{Deserialize, Serialize}; @@ -29,7 +29,6 @@ pub struct CaptchaValidateResp { // API keys are mcaptcha actor names -#[post("/siteverify")] pub async fn validate_captcha_token( payload: web::Json, data: web::Data, diff --git a/src/api/v1/routes.rs b/src/api/v1/routes.rs index 1190167b..3236c0f6 100644 --- a/src/api/v1/routes.rs +++ b/src/api/v1/routes.rs @@ -21,6 +21,7 @@ use super::mcaptcha::duration::routes::Duration; use super::mcaptcha::levels::routes::Levels; use super::mcaptcha::mcaptcha::routes::MCaptcha; use super::meta::routes::Meta; +use super::pow::routes::PoW; pub const ROUTES: Routes = Routes::new(); @@ -31,6 +32,7 @@ pub struct Routes { pub mcaptcha: MCaptcha, pub duration: Duration, pub meta: Meta, + pub pow: PoW, } impl Routes { @@ -42,6 +44,7 @@ impl Routes { mcaptcha: MCaptcha::new(), duration: Duration::new(), meta: Meta::new(), + pow: PoW::new(), } } } diff --git a/src/main.rs b/src/main.rs index 98e81465..8c49b6fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,7 +88,6 @@ async fn main() -> std::io::Result<()> { .wrap(actix_middleware::NormalizePath::new( actix_middleware::normalize::TrailingSlash::Trim, )) - .configure(v1::pow::services) .configure(v1::services) .configure(docs::services) .configure(static_assets::services) diff --git a/src/routes.rs b/src/routes.rs index c9dcd1b4..32e29df6 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -17,12 +17,21 @@ #[allow(dead_code)] pub enum Methods { + /// GET hander Get, + /// POST handler Post, + /// Protected GET handler ProtectGet, + /// Protected POST handler ProtectPost, + /// CORS allow all orgin GET handler + CorsAllowAllGet, + /// CORS allow all orgin PST handler + CorsAllowAllPost, } +/// Defines resoures for [Methods] #[macro_export] macro_rules! define_resource { ($cfg:expr, $path:expr, Methods::Get, $to:expr) => { @@ -58,4 +67,29 @@ macro_rules! define_resource { .to($to), ); }; + + ($cfg:expr, $path:expr, Methods::CorsAllowAllGet, $cors:expr, $to:expr) => { + $cfg.service( + actix_web::web::resource($path) + .wrap($cors) + .guard(actix_web::guard::Get()) + .to($to), + ); + }; + + ($cfg:expr, $path:expr, Methods::CorsAllowAllPost, $to:expr) => { + let cors = Cors::default() + .allow_any_origin() + .allowed_methods(vec!["POST"]) + .allow_any_header() + .max_age(0) + .send_wildcard(); + + $cfg.service( + actix_web::web::resource($path) + .wrap(cors) + .guard(actix_web::guard::Post()) + .to($to), + ); + }; }