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 cool_asserts::assert_matches;
use result_extended::ResultExt;
use super::*;
@ -700,7 +701,7 @@ mod test {
assert_matches!(
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 {
username: String,
password: String,
}
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())
}).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 authdb::AuthError;
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::{
handle_auth, handle_available_images, handle_connect_websocket, handle_file,
handle_get_charsheet, handle_get_users, handle_register_client, handle_server_status,
@ -26,6 +27,7 @@ mod core;
mod database;
mod handlers;
mod types;
mod filters;
#[derive(Debug)]
struct Unauthorized;
@ -109,133 +111,17 @@ pub async fn main() {
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)
.and(warp::get())
.then({
let core = core.clone();
move |file_name| handle_file(core.clone(), AssetId::from(file_name))
});
let route_available_images = warp::path!("api" / "v1" / "image").and(warp::get()).then({
let core = core.clone();
move || handle_available_images(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)
let filter = route_server_status(core.clone())
.or(route_register_client(core.clone()))
.or(route_unregister_client(core.clone()))
.or(route_websocket(core.clone()))
.or(route_image(core.clone()))
.or(route_available_images(core.clone()))
.or(route_set_bg_image(core.clone()))
.or(routes_user_management(core.clone()))
.or(route_get_charsheet(core.clone()))
.or(route_check_password(core.clone()))
.with(warp::log("visions"))
.recover(handle_rejection);