use std::env; mod database; mod routes; mod utils; use axum::{ routing::{get, post}, Router, }; use routes::problem::{get_problem, get_problems, create_problem}; use routes::user::{create_user, me}; use routes::auth::{login, logout}; use tower_http::services::ServeDir; use crate::{database::Database, routes::submission::{create_submission, get_display_submission, get_display_submissions, get_submissions_by_problem_id}, utils::register_admin}; #[derive(Clone)] struct AppState { secret: String, database: Database, } #[tokio::main] async fn main() { let database = Database::new_in_memory().unwrap(); database.initialize().unwrap(); // TODO: generically load environment variables, this is tedious let Ok(secret) = env::var("JWT_SECRET") else { eprintln!("missing environment variable JWT_SECRET"); return; }; let Ok(admin_email) = env::var("ADMIN_EMAIL") else { eprintln!("missing environment variable ADMIN_EMAIL"); return; }; let Ok(admin_username) = env::var("ADMIN_USERNAME") else { eprintln!("missing environment variable ADMIN_USERNAME"); return; }; let Ok(admin_password) = env::var("ADMIN_PASSWORD") else { eprintln!("missing environment variable ADMIN_PASSWORD"); return; }; let Ok(()) = register_admin(&database, &admin_email, &admin_username, &admin_password) else { eprintln!("failed to register admin user"); return; }; let state = AppState { secret: secret, database: database, }; let static_files = ServeDir::new("./static"); let app = Router::new() .route("/login", post(login)) .route("/logout", post(logout)) .route("/problem/{problem_id}", get(get_problem)) .route("/problem/{problem_id}/submission", get(get_display_submissions)) .route("/problem", get(get_problems)) .route("/problem", post(create_problem)) .route("/submission", post(create_submission)) .route("/submission/{submission_id}", get(get_display_submission)) .route("/user", post(create_user)) .route("/me", get(me)) .nest_service("/static", static_files) .with_state(state); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); axum::serve(listener, app).await.unwrap(); }