use askama_axum::{Response, Template}; use axum::{ extract::{Path, State}, response::{Html, IntoResponse, Redirect}, Extension, }; use http::StatusCode; use sqlx::SqlitePool; use crate::{ middlewares::is_authorized, user::{get_other_roles_display, get_user_roles_display}, UserData, }; #[derive(Template)] #[template(path = "profile.html")] struct ProfileTemplate { logged_in: bool, name: String, user: UserData, user_roles: Vec, } #[derive(Template)] #[template(path = "user.html")] struct UserProfileTemplate { logged_in: bool, name: String, user_roles: Vec, profile: UserData, profile_roles: Vec, non_profile_roles: Vec, } struct HtmlTemplate(T); impl IntoResponse for HtmlTemplate where T: Template, { fn into_response(self) -> Response { match self.0.render() { Ok(html) => Html(html).into_response(), Err(err) => ( StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to render template. Error: {}", err), ) .into_response(), } } } #[derive(Template)] #[template(path = "index.html")] struct IndexTemplate { logged_in: bool, name: String, } #[derive(Template)] #[template(path = "dashboard.html")] struct DashboardTemplate { logged_in: bool, name: String, user_roles: Vec, } pub async fn index( State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); let logged_in = user_data.is_some(); if is_authorized("/dashboard", user_data, db_pool).await { Redirect::to("/dashboard").into_response() } else { let template = IndexTemplate { logged_in, name }; HtmlTemplate(template).into_response() } } pub async fn dashboard( State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); let logged_in = user_data.is_some(); if is_authorized("/dashboard", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; let template = DashboardTemplate { logged_in, name, user_roles }; HtmlTemplate(template).into_response() } else { Redirect::to("/").into_response() } } /// Handles the profile page. pub async fn profile( State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { // Extract the user's name from the user data. let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); let logged_in = user_data.is_some(); if logged_in { // Extract the user data. let user = user_data.as_ref().unwrap().clone(); if is_authorized("/profile", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; // Create the profile template. let template = ProfileTemplate { logged_in, name, user: user.clone(), user_roles, }; return HtmlTemplate(template).into_response(); } else { Redirect::to("/").into_response() } } else { Redirect::to("/").into_response() } } pub async fn user_profile( Path(user_id): Path, State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { // Extract the user's name from the user data. let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); let logged_in = user_data.is_some(); // Extract the user data. let user = sqlx::query_as!(UserData, "SELECT * FROM users WHERE id = ?", user_id) .fetch_one(&db_pool) .await .unwrap(); if is_authorized("/users", user_data, db_pool.clone()).await { // Get logged in user roles let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; // Get user roles let profile_roles = get_user_roles_display(user_id, &db_pool.clone()).await; // Get roles user does not have let non_profile_roles = get_other_roles_display(user_id, &db_pool.clone()).await; // Create the profile template. let template = UserProfileTemplate { logged_in, name, user_roles, profile: user, profile_roles, non_profile_roles, }; return HtmlTemplate(template).into_response(); } else { Redirect::to("/").into_response() } } #[derive(Template)] #[template(path = "useradmin.html")] struct UserAdminTemplate { logged_in: bool, name: String, users: Vec, user_roles: Vec, } pub async fn useradmin( Extension(user_data): Extension>, State(db_pool): State, ) -> impl IntoResponse { let user_name = user_data.as_ref().map(|s| s.name.clone()); let logged_in = user_name.is_some(); let name = user_name.unwrap_or_default(); let users = sqlx::query_as::<_, UserData>("SELECT * FROM users") .fetch_all(&db_pool) .await .unwrap(); let user_id = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); if is_authorized("/useradmin", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(user_id, &db_pool.clone()).await; let template = UserAdminTemplate { logged_in, name, users, user_roles, }; HtmlTemplate(template).into_response() } else { Redirect::to("/").into_response() } } #[derive(Template)] #[template(path = "about.html")] struct AboutTemplate { logged_in: bool, name: String, } pub async fn about(Extension(user_data): Extension>) -> impl IntoResponse { let user_name = user_data.map(|s| s.name); let logged_in = user_name.is_some(); let name = user_name.unwrap_or_default(); let template = AboutTemplate { logged_in, name }; HtmlTemplate(template) } #[derive(Template)] #[template(path = "contactus.html")] struct ContactTemplate { logged_in: bool, name: String, } pub async fn contact(Extension(user_data): Extension>) -> impl IntoResponse { let user_name = user_data.map(|s| s.name); let logged_in = user_name.is_some(); let name = user_name.unwrap_or_default(); let template = ContactTemplate { logged_in, name }; HtmlTemplate(template) } #[derive(Template)] #[template(path = "cottagecalendar.html")] struct CottageCalendarTemplate { logged_in: bool, name: String, user_roles: Vec, } pub async fn cottagecalendar( Extension(user_data): Extension>, State(db_pool): State, ) -> impl IntoResponse { let user_name = user_data.as_ref().map(|s| s.name.clone()); let logged_in = user_name.is_some(); let name = user_name.unwrap_or_default(); let user_id = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); if is_authorized("/cottagecalendar", user_data, db_pool.clone()).await { // Get user roles let user_roles = get_user_roles_display(user_id, &db_pool.clone()).await; let template = CottageCalendarTemplate { logged_in, name, user_roles }; HtmlTemplate(template).into_response() } else { Redirect::to("/").into_response() } }