what2watch/src/lib.rs
2023-07-28 16:15:27 -07:00

114 lines
3.5 KiB
Rust

use axum::routing::IntoMakeService;
use sqlx::SqlitePool;
#[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 mod import_utils;
pub use users::User;
pub use watches::{ShowKind, Watch, WatchQuest};
pub type WWRouter = axum::Router<SqlitePool>;
// everything else is private to the crate
mod db;
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<julid::Julid, User, axum_login::SqliteStore<User>>;
/// Returns the router to be used as a service or test object, you do you.
pub async fn app(db_pool: sqlx::SqlitePool, secret: &[u8]) -> IntoMakeService<axum::Router> {
use axum::{middleware, routing::get};
// 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_new_watch,
post_add_watch_quest,
};
let (session_layer, auth_layer) = {
let session_layer = db::session_layer(db_pool.clone(), secret).await;
let auth_layer = db::auth_layer(db_pool.clone(), secret).await;
(session_layer, auth_layer)
};
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_watch_quest),
)
.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)
.into_make_service()
}
//-************************************************************************
// 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<bool>,
}
assert!(!TestThing::default().has_optional_user());
}
}