use chrono::prelude::Local; use serde::{Deserialize, Serialize}; use tera::{Context, Tera}; use tide::http::mime; use tide::{Redirect, Request, Response, Result, StatusCode}; use uuid::Uuid; use std::env; use crate::{fs, post::Post}; #[derive(Debug, Serialize, Deserialize)] struct User { username: String, password: String, } pub async fn index(req: Request<()>) -> Result { let posts: Vec = fs::get_all_posts().await?; let mut context = Context::new(); context.insert("posts", &posts); render_response("index.html", &context, &req) } pub async fn single_post(req: Request<()>) -> Result { let mut context = Context::new(); let post_id = req.param("id")?; let post = fs::get_one_post(post_id).await?; context.insert("post", &post); render_response("single.html", &context, &req) } pub async fn edit_post(req: Request<()>) -> Result { let mut context = Context::new(); let post_id = req.param("id")?; let mut post = fs::get_one_post(post_id).await?; post.body = post.body.replace("
", "\n"); context.insert("post", &post); render_response("edit.html", &context, &req) } pub async fn create_post(mut req: Request<()>) -> Result { let mut post: Post = req.body_form().await?; post.id = Uuid::new_v4().to_string(); post.date = Local::now().date().naive_local().to_string(); post.body = post.body.trim().to_owned(); post.save().await?; Ok(Redirect::new("/").into()) } pub async fn update_post(mut req: Request<()>) -> Result { let mut post: Post = req.body_form().await?; post.save().await?; Ok(Redirect::new(format!("/posts/{}", post.id)).into()) } pub async fn delete_post(req: Request<()>) -> Result { let id: String = req.param("id")?; fs::delete_post(id)?; let mut res = Response::new(StatusCode::Ok); res.set_body("{\"success\": \"true\"}"); res.set_content_type(mime::JSON); Ok(res) } pub async fn login_page(mut req: Request<()>) -> Result { let mut context = Context::new(); match req.session_mut().get::("flash_error") { Some(error) => { req.session_mut().remove("flash_error"); &context.insert("error", &error); } None => {} } render_response("login.html", &context, &req) } pub async fn login(mut req: Request<()>) -> Result { let username = env::var("ADMIN_USERNAME")?; let password = env::var("ADMIN_PASSWORD")?; let user: User = req.body_form().await?; if user.username == username && user.password == password { req.session_mut().remove("logged_in"); req.session_mut().insert("logged_in", true)?; Ok(Redirect::new("/").into()) } else { req.session_mut().remove("logged_in"); req.session_mut() .insert("flash_error", "Invalid credentials")?; Ok(Redirect::new("/login").into()) } } pub async fn logout(mut req: Request<()>) -> Result { req.session_mut().remove("logged_in"); req.session_mut().insert("logged_in", false)?; Ok(Redirect::new("/").into()) } pub fn render_response(template: &str, context: &Context, req: &Request<()>) -> Result { let mut context = context.clone(); let logged_in: bool = req.session().get("logged_in").unwrap_or(false); context.insert("logged_in", &logged_in); let html = render_template(template, &context)?; let mut res = Response::new(StatusCode::Ok); res.set_body(html); res.set_content_type(mime::HTML); Ok(res) } pub fn render_template(template: &str, context: &Context) -> Result { let tera = Tera::new("templates/**/*.html")?; let html = tera.render(template, &context)?; Ok(html) }