diff --git a/flake.nix b/flake.nix index da894d6..49665ea 100644 --- a/flake.nix +++ b/flake.nix @@ -48,7 +48,7 @@ buildInputs = [ bacon cargo-nextest - cargo-shuttle + # cargo-shuttle jq nixpkgs-fmt openssl diff --git a/src/data/mod.rs b/src/data/mod.rs index 0135551..6d541db 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,2 +1,2 @@ pub mod router; -mod service; +pub mod service; diff --git a/src/data/router/auth.rs b/src/data/router/auth.rs new file mode 100644 index 0000000..b91312b --- /dev/null +++ b/src/data/router/auth.rs @@ -0,0 +1,19 @@ +use std::sync::Arc; + +use askama_axum::IntoResponse; +use axum::{extract::State, routing::post, Json, Router}; + +use crate::{auth::AuthSession, hypermedia::schema::auth::MfaTokenForm, AppState}; + +pub fn private_router() -> Router> { + Router::new().route("/api/auth/mfa", post(mfa_verify)) +} + +async fn mfa_verify( + auth_session: AuthSession, + State(shared_state): State>, + Json(mfa_token): Json, +) -> impl IntoResponse { + crate::hypermedia::service::auth::mfa_verify(auth_session, &shared_state.pool, mfa_token.token) + .await +} diff --git a/src/data/router.rs b/src/data/router/expenses.rs similarity index 97% rename from src/data/router.rs rename to src/data/router/expenses.rs index de11e19..74e6d62 100644 --- a/src/data/router.rs +++ b/src/data/router/expenses.rs @@ -13,7 +13,7 @@ use crate::{ AppState, }; -pub fn data_router() -> Router> { +pub fn router() -> Router> { Router::new() .route("/api/expenses", get(get_expenses).post(insert_expense)) .route( diff --git a/src/data/router/mod.rs b/src/data/router/mod.rs new file mode 100644 index 0000000..32ec6f3 --- /dev/null +++ b/src/data/router/mod.rs @@ -0,0 +1,2 @@ +pub mod auth; +pub mod expenses; diff --git a/src/hypermedia/mod.rs b/src/hypermedia/mod.rs index 15e5b69..194a004 100644 --- a/src/hypermedia/mod.rs +++ b/src/hypermedia/mod.rs @@ -1,3 +1,3 @@ pub mod router; -mod schema; -mod service; +pub mod schema; +pub mod service; diff --git a/src/main.rs b/src/main.rs index 2cf371e..a39761a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -121,13 +121,14 @@ async fn axum( let shared_state = Arc::new(AppState { pool, secret_store }); let router = Router::new() - .merge(data::router::data_router()) + .merge(data::router::expenses::router()) .merge(hypermedia::router::expenses::router()) .route_layer(permission_required!( Backend, login_url = "/auth/mfa", "restricted:read", )) + .merge(data::router::auth::private_router()) .merge(hypermedia::router::auth::private_router()) .route_layer(permission_required!( Backend, @@ -161,7 +162,7 @@ async fn axum( if res.headers().get("content-security-policy").is_none() { res.headers_mut().insert( "content-security-policy", - generate_defaut_csp() + generate_default_csp() .to_string() .parse() .unwrap_or_else(|_| { @@ -231,7 +232,7 @@ fn generate_general_helmet_headers() -> Helmet { /// Returns a default strict Content Security Policy. /// It's used whenever a custom CSP is not set. -fn generate_defaut_csp() -> ContentSecurityPolicy<'static> { +fn generate_default_csp() -> ContentSecurityPolicy<'static> { return ContentSecurityPolicy::new() .default_src(vec!["'self'"]) .base_uri(vec!["'none'"])