use axum::{ http::{header, Method}, middleware as axum_mw, routing::{get, post, put}, Router, }; use tower_http::cors::CorsLayer; use tower_http::trace::TraceLayer; use crate::app_state::AppState; use crate::handlers; use crate::middleware::auth; pub fn create_router(state: AppState) -> Router { let cors = CorsLayer::new() .allow_origin(tower_http::cors::Any) .allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE]) .allow_headers([header::CONTENT_TYPE, header::AUTHORIZATION]); // Public routes let public = Router::new() .route("/health", get(handlers::health::health_check)) .route("/api/v1/auth/register", post(handlers::auth::register)) .route("/api/v1/auth/login", post(handlers::auth::login)) .route( "/api/v1/leaderboard", get(handlers::leaderboard::get_leaderboard), ); // Authenticated routes let authenticated = Router::new() .route("/api/v1/sessions", post(handlers::session::create_session)) .route( "/api/v1/sessions/{id}", get(handlers::session::get_session), ) .route( "/api/v1/sessions/{id}/end", post(handlers::session::end_session), ) .route( "/api/v1/sessions/{id}/question", get(handlers::game::get_current_question), ) .route( "/api/v1/sessions/{id}/question/{qid}/answer", post(handlers::game::submit_answer), ) .route( "/api/v1/sessions/{id}/question/{qid}/hint", post(handlers::game::request_hint), ) .route( "/api/v1/sessions/{id}/question/next", post(handlers::game::next_question), ) .layer(axum_mw::from_fn_with_state( state.clone(), auth::require_auth, )); // Admin routes (auth + admin role) let admin = Router::new() .route( "/api/v1/admin/questions", get(handlers::admin::list_questions).post(handlers::admin::create_question), ) .route( "/api/v1/admin/questions/{id}", put(handlers::admin::update_question) .delete(handlers::admin::delete_question), ) .route( "/api/v1/admin/players", get(handlers::admin::list_players), ) .route( "/api/v1/admin/players/{id}/role", put(handlers::admin::update_player_role), ) .layer(axum_mw::from_fn(auth::require_admin)) .layer(axum_mw::from_fn_with_state( state.clone(), auth::require_auth, )); Router::new() .merge(public) .merge(authenticated) .merge(admin) .layer(TraceLayer::new_for_http()) .layer(cors) .with_state(state) }