Start wrapping routes into standalone functions

This commit is contained in:
Savanni D'Gerinel 2024-12-24 14:37:37 -05:00
parent e62ff9aa7a
commit 1d400ce38b
5 changed files with 195 additions and 127 deletions

View File

@ -668,6 +668,7 @@ mod test {
use std::path::PathBuf; use std::path::PathBuf;
use cool_asserts::assert_matches; use cool_asserts::assert_matches;
use result_extended::ResultExt;
use super::*; use super::*;
@ -700,7 +701,7 @@ mod test {
assert_matches!( assert_matches!(
conn.character(CharacterId::from("1")).await, conn.character(CharacterId::from("1")).await,
ResultExt::Ok(None) Ok(None)
); );
} }
} }

View File

@ -0,0 +1,125 @@
mod user_management;
pub use user_management::routes_user_management;
use warp::{
filters::cors::Builder,
http::{header::CONTENT_TYPE, HeaderName, Method, Response},
reply::*,
Filter,
};
use crate::{
asset_db::AssetId, core::Core, handlers::{handle_auth, handle_available_images, handle_connect_websocket, handle_file, handle_get_charsheet, handle_get_users, handle_register_client, handle_server_status, handle_set_admin_password, handle_set_background_image, handle_unregister_client, RegisterRequest}
};
fn cors<H, M>(methods: Vec<M>, headers: Vec<H>) -> Builder
where
M: Into<Method>,
H: Into<HeaderName>,
{
warp::cors()
.allow_credentials(true)
.allow_methods(methods)
.allow_headers(headers)
}
pub fn route_server_status(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "status")
.and(warp::get())
.then(move || handle_server_status(core.clone()))
}
pub fn route_set_bg_image(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "tabletop" / "bg_image")
.and(warp::put())
.and(warp::body::json())
.then({
let core = core.clone();
move |body| handle_set_background_image(core.clone(), body)
})
.with(cors::<HeaderName, Method>(vec![Method::PUT], vec![]))
}
pub fn route_image(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "image" / String)
.and(warp::get())
.then({
let core = core.clone();
move |file_name| handle_file(core.clone(), AssetId::from(file_name))
})
}
pub fn route_available_images(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "image").and(warp::get()).then({
let core = core.clone();
move || handle_available_images(core.clone())
})
}
pub fn route_register_client(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "client")
.and(warp::post())
.then({
let core = core.clone();
move || handle_register_client(core.clone(), RegisterRequest {})
})
}
pub fn route_unregister_client(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "client" / String)
.and(warp::delete())
.then({
let core = core.clone();
move |client_id| handle_unregister_client(core.clone(), client_id)
})
}
pub fn route_websocket(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path("ws")
.and(warp::ws())
.and(warp::path::param())
.then({
let core = core.clone();
move |ws, client_id| handle_connect_websocket(core.clone(), ws, client_id)
})
}
pub fn route_get_charsheet(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "charsheet" / String)
.and(warp::get())
.then({
let core = core.clone();
move |charid| handle_get_charsheet(core.clone(), charid)
})
}
pub fn route_check_password(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "auth")
.and(warp::put())
.and(warp::body::json())
.then({
let core = core.clone();
move |body| handle_auth(core.clone(), body)
})
}

View File

@ -0,0 +1,39 @@
use warp::{
http::{header::CONTENT_TYPE, Method},
reply::Reply,
Filter,
};
use crate::{
core::Core,
handlers::{handle_get_users, handle_set_admin_password},
};
use super::cors;
fn route_get_users(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "users")
.and(warp::get())
.then(move || handle_get_users(core.clone()))
}
fn route_set_admin_password(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
warp::path!("api" / "v1" / "admin_password")
.and(warp::put())
.and(warp::body::json())
.then({
let core = core.clone();
move |body| handle_set_admin_password(core.clone(), body)
})
.with(cors(vec![Method::PUT], vec![CONTENT_TYPE]))
}
pub fn routes_user_management(
core: Core,
) -> impl Filter<Extract = (impl Reply,), Error = warp::Rejection> + Clone {
route_get_users(core.clone()).or(route_set_admin_password(core.clone()))
}

View File

@ -262,6 +262,7 @@ pub async fn handle_set_admin_password(core: Core, password: String) -> impl Rep
pub struct AuthRequest { pub struct AuthRequest {
username: String, username: String,
password: String, password: String,
} }
pub async fn handle_auth(core: Core, auth_request: AuthRequest) -> impl Reply { pub async fn handle_auth(core: Core, auth_request: AuthRequest) -> impl Reply {
@ -277,3 +278,19 @@ pub async fn handle_auth(core: Core, auth_request: AuthRequest) -> impl Reply {
.unwrap()) .unwrap())
}).await }).await
} }
#[cfg(test)]
mod test {
use std::path::PathBuf;
use crate::{asset_db::mocks::MemoryAssets, database::DbConn};
use super::*;
fn setup() -> Core {
let asset_store = MemoryAssets::new(vec![]);
let memory_file: Option<PathBuf> = None;
let db = DbConn::new(memory_file);
Core::new(asset_store, db)
}
}

View File

@ -7,6 +7,7 @@ use std::{
use asset_db::{AssetId, FsAssets}; use asset_db::{AssetId, FsAssets};
use authdb::AuthError; use authdb::AuthError;
use database::DbConn; use database::DbConn;
use filters::{route_available_images, route_check_password, route_get_charsheet, route_image, route_register_client, route_server_status, route_set_bg_image, route_unregister_client, route_websocket, routes_user_management};
use handlers::{ use handlers::{
handle_auth, handle_available_images, handle_connect_websocket, handle_file, handle_auth, handle_available_images, handle_connect_websocket, handle_file,
handle_get_charsheet, handle_get_users, handle_register_client, handle_server_status, handle_get_charsheet, handle_get_users, handle_register_client, handle_server_status,
@ -26,6 +27,7 @@ mod core;
mod database; mod database;
mod handlers; mod handlers;
mod types; mod types;
mod filters;
#[derive(Debug)] #[derive(Debug)]
struct Unauthorized; struct Unauthorized;
@ -109,133 +111,17 @@ pub async fn main() {
let core = core::Core::new(FsAssets::new(PathBuf::from("/home/savanni/Pictures")), conn); let core = core::Core::new(FsAssets::new(PathBuf::from("/home/savanni/Pictures")), conn);
let route_server_status = warp::path!("api" / "v1" / "status").and(warp::get()).then({
let core = core.clone();
move || handle_server_status(core.clone())
});
let route_image = warp::path!("api" / "v1" / "image" / String) let filter = route_server_status(core.clone())
.and(warp::get()) .or(route_register_client(core.clone()))
.then({ .or(route_unregister_client(core.clone()))
let core = core.clone(); .or(route_websocket(core.clone()))
move |file_name| handle_file(core.clone(), AssetId::from(file_name)) .or(route_image(core.clone()))
}); .or(route_available_images(core.clone()))
.or(route_set_bg_image(core.clone()))
let route_available_images = warp::path!("api" / "v1" / "image").and(warp::get()).then({ .or(routes_user_management(core.clone()))
let core = core.clone(); .or(route_get_charsheet(core.clone()))
move || handle_available_images(core.clone()) .or(route_check_password(core.clone()))
});
let route_register_client = warp::path!("api" / "v1" / "client")
.and(warp::post())
.then({
let core = core.clone();
move || handle_register_client(core.clone(), RegisterRequest {})
});
let route_unregister_client = warp::path!("api" / "v1" / "client" / String)
.and(warp::delete())
.then({
let core = core.clone();
move |client_id| handle_unregister_client(core.clone(), client_id)
});
let route_websocket = warp::path("ws")
.and(warp::ws())
.and(warp::path::param())
.then({
let core = core.clone();
move |ws, client_id| handle_connect_websocket(core.clone(), ws, client_id)
});
let route_set_bg_image_options = warp::path!("api" / "v1" / "tabletop" / "bg_image")
.and(warp::options())
.map({
move || {
Response::builder()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "PUT")
.header("Access-Control-Allow-Headers", "content-type")
.header("Content-Type", "application/json")
.body("")
.unwrap()
}
});
let route_set_bg_image = warp::path!("api" / "v1" / "tabletop" / "bg_image")
.and(warp::put())
.and(warp::body::json())
.then({
let core = core.clone();
move |body| handle_set_background_image(core.clone(), body)
});
let route_get_users = warp::path!("api" / "v1" / "users").and(warp::get()).then({
let core = core.clone();
move || handle_get_users(core.clone())
});
let route_get_charsheet = warp::path!("api" / "v1" / "charsheet" / String)
.and(warp::get())
.then({
let core = core.clone();
move |charid| handle_get_charsheet(core.clone(), charid)
});
let route_set_admin_password_options = warp::path!("api" / "v1" / "admin_password")
.and(warp::options())
.map({
move || {
Response::builder()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "PUT")
.header("Access-Control-Allow-Headers", "content-type")
.header("Content-Type", "application/json")
.body("")
.unwrap()
}
});
let route_set_admin_password = warp::path!("api" / "v1" / "admin_password")
.and(warp::put())
.and(warp::body::json())
.then({
let core = core.clone();
move |body| handle_set_admin_password(core.clone(), body)
});
let route_check_password_options = warp::path!("api" / "v1" / "auth")
.and(warp::options())
.map({
move || {
Response::builder()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "PUT")
.header("Access-Control-Allow-Headers", "content-type")
.body("")
.unwrap()
}
});
let route_check_password = warp::path!("api" / "v1" / "auth")
.and(warp::put())
.and(warp::body::json())
.then({
let core = core.clone();
move |body| handle_auth(core.clone(), body)
});
let filter = route_server_status
.or(route_register_client)
.or(route_unregister_client)
.or(route_websocket)
.or(route_image)
.or(route_available_images)
.or(route_set_bg_image_options)
.or(route_set_bg_image)
.or(route_get_users)
.or(route_get_charsheet)
.or(route_set_admin_password_options)
.or(route_set_admin_password)
.or(route_check_password_options)
.or(route_check_password)
.with(warp::log("visions")) .with(warp::log("visions"))
.recover(handle_rejection); .recover(handle_rejection);