#[macro_use] extern crate justerror; #[cfg(test)] pub mod test_utils; /// Some public interfaces for interacting with the database outside of the web /// app pub use db::get_db_pool; pub use db_id::DbId; pub mod import_utils; pub use users::User; pub use watches::{ShowKind, Watch, WatchQuest}; // everything else is private to the crate mod db; mod db_id; mod generic_handlers; mod login; mod signup; mod templates; mod users; mod util; mod watches; // things we want in the crate namespace use optional_optional_user::OptionalOptionalUser; use templates::*; use watches::templates::*; type AuthContext = axum_login::extractors::AuthContext>; /// Returns the router to be used as a service or test object, you do you. pub async fn app(db_pool: sqlx::SqlitePool, session_secret: &[u8]) -> axum::Router { use axum::{middleware, routing::get}; let session_layer = db::session_layer(db_pool.clone(), session_secret).await; let auth_layer = db::auth_layer(db_pool.clone(), session_secret).await; // don't bother bringing handlers into the whole crate namespace use generic_handlers::{handle_slash, handle_slash_redir}; use login::{get_login, get_logout, post_login, post_logout}; use signup::{get_create_user, get_signup_success, post_create_user}; use watches::handlers::{ get_add_new_watch, get_search_watch, get_watch, get_watches, post_add_existing_watch, post_add_new_watch, }; axum::Router::new() .route("/", get(handle_slash).post(handle_slash)) .route("/signup", get(get_create_user).post(post_create_user)) .route("/signup_success/:id", get(get_signup_success)) .route("/login", get(get_login).post(post_login)) .route("/logout", get(get_logout).post(post_logout)) .route("/watches", get(get_watches)) .route("/watch", get(get_watch)) .route("/watch/:id", get(get_watch)) .route("/search", get(get_search_watch)) .route("/add", get(get_add_new_watch).post(post_add_new_watch)) .route( "/add/watch", get(get_search_watch).post(post_add_existing_watch), ) .fallback(handle_slash_redir) .layer(middleware::from_fn_with_state( db_pool.clone(), users::handle_update_last_seen, )) .layer(auth_layer) .layer(session_layer) .with_state(db_pool) } //-************************************************************************ // tests for the proc macro for optional user //-************************************************************************ #[cfg(test)] mod test { use super::{MainPage, OptionalOptionalUser, SignupSuccessPage, User}; #[test] fn main_page_has_optional_user() { assert!(MainPage::default().has_optional_user()); } #[test] fn signup_success_has_no_optional_user() { assert!(!SignupSuccessPage::default().has_optional_user()); } #[test] fn user_is_not_optional() { #[derive(Default, OptionalOptionalUser)] struct TestThing { user: User, } assert!(!TestThing::default().has_optional_user()); } #[test] fn user_is_not_user() { #[derive(Default, OptionalOptionalUser)] struct TestThing { user: Option, } assert!(!TestThing::default().has_optional_user()); } }