use hyper::{Body, Method, Request, Response}; use serde::Deserialize; use serde_urlencoded; use sqlx::sqlite::SqlitePool; use std::collections::HashMap; use std::convert::Infallible; use tera::Tera; use url::form_urlencoded; use crate::controller; use crate::controller::wallet::Wallet; use crate::db; use crate::model::config::Config; use crate::model::user::User; pub async fn routes( config: Config, pool: SqlitePool, assets: HashMap, templates: Tera, request: Request, ) -> Result, Infallible> { let method = request.method(); let uri = request.uri(); let path = &uri.path().split('/').collect::>()[1..]; let response = match (method, path) { (&Method::HEAD, ["status"]) => controller::utils::ok(), (&Method::GET, ["status"]) => controller::utils::text("ok".to_string()), (&Method::GET, ["login"]) => { controller::login::page(&assets, &templates, None).await } (&Method::POST, ["login"]) => { controller::login::login( config, &assets, &templates, body_form(request).await, pool, ) .await } (&Method::GET, ["assets", _, file]) => { controller::utils::file(&format!("assets/{}", file)).await } _ => match connected_user(&pool, &request).await { Some(user) => { let wallet = Wallet { pool, assets, templates, user, }; authenticated_routes(config, wallet, request).await } None => controller::utils::redirect("/login"), }, }; Ok(response) } async fn connected_user( pool: &SqlitePool, request: &Request, ) -> Option { let cookie = request.headers().get("COOKIE")?.to_str().ok()?; let mut xs = cookie.split('='); xs.next(); let login_token = xs.next()?; db::users::get_by_login_token(&pool, login_token.to_string()).await } async fn authenticated_routes( config: Config, wallet: Wallet, request: Request, ) -> Response { let method = request.method(); let uri = request.uri(); let path = &uri.path().split('/').collect::>()[1..]; let query = uri.query(); match (method, path) { (&Method::GET, [""]) => { controller::payments::table(&wallet, parse_query(query)).await } (&Method::GET, ["payment"]) => { controller::payments::create_form(&wallet, parse_query(query)).await } (&Method::POST, ["payment", "create"]) => { controller::payments::create( &wallet, parse_query(query), body_form(request).await, ) .await } (&Method::GET, ["payment", "category"]) => { controller::payments::search_category(&wallet, parse_query(query)) .await } (&Method::GET, ["payment", id]) => { controller::payments::update_form( parse_id(id), &wallet, parse_query(query), ) .await } (&Method::POST, ["payment", id, "update"]) => { controller::payments::update( parse_id(id), &wallet, parse_query(query), body_form(request).await, ) .await } (&Method::POST, ["payment", id, "delete"]) => { controller::payments::delete( parse_id(id), &wallet, parse_query(query), ) .await } (&Method::GET, ["incomes"]) => { controller::incomes::table(&wallet, parse_query(query)).await } (&Method::GET, ["income"]) => { controller::incomes::create_form(&wallet, parse_query(query)).await } (&Method::POST, ["income", "create"]) => { controller::incomes::create( &wallet, parse_query(query), body_form(request).await, ) .await } (&Method::GET, ["income", id]) => { controller::incomes::update_form( parse_id(id), &wallet, parse_query(query), ) .await } (&Method::POST, ["income", id, "update"]) => { controller::incomes::update( parse_id(id), &wallet, parse_query(query), body_form(request).await, ) .await } (&Method::POST, ["income", id, "delete"]) => { controller::incomes::delete( parse_id(id), &wallet, parse_query(query), ) .await } (&Method::GET, ["categories"]) => { controller::categories::table(&wallet, parse_query(query)).await } (&Method::GET, ["category"]) => { controller::categories::create_form(&wallet).await } (&Method::POST, ["category", "create"]) => { controller::categories::create(&wallet, body_form(request).await) .await } (&Method::GET, ["category", id]) => { controller::categories::update_form(parse_id(id), &wallet).await } (&Method::POST, ["category", id, "update"]) => { controller::categories::update( parse_id(id), &wallet, body_form(request).await, ) .await } (&Method::POST, ["category", id, "delete"]) => { controller::categories::delete(parse_id(id), &wallet).await } (&Method::GET, ["balance"]) => controller::balance::get(&wallet).await, (&Method::GET, ["statistics"]) => { controller::statistics::get(&wallet).await } (&Method::POST, ["logout"]) => { controller::login::logout(config, &wallet).await } _ => controller::error::error( &wallet, "Page introuvable", "La page que recherchez n’existe pas.", ), } } fn parse_query<'a, T: Deserialize<'a>>(query: Option<&'a str>) -> T { serde_urlencoded::from_str(query.unwrap_or("")).unwrap() } async fn body_form(request: Request) -> HashMap { match hyper::body::to_bytes(request).await { Ok(bytes) => form_urlencoded::parse(bytes.as_ref()) .into_owned() .collect::>(), Err(_) => HashMap::new(), } } fn parse_id(str: &str) -> i64 { str.parse::().unwrap() }