123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- use chrono::prelude::Local;
- use serde::{Deserialize, Serialize};
- use tera::{Context, Tera};
- use tide::convert::json;
- use tide::http::mime;
- use tide::{Redirect, Request, Response, Result, StatusCode};
-
- use std::env;
-
- use crate::{fs, post::Post, util, State};
-
- #[derive(Debug, Serialize, Deserialize)]
- struct User {
- username: String,
- password: String,
- }
-
- pub async fn index(req: Request<State>) -> Result {
- let posts: Vec<Post> = fs::get_all_posts().await?;
- let mut context = Context::new();
- context.insert("posts", &posts);
- render_html_response("index.html", &context, req)
- }
-
- pub async fn single_post(req: Request<State>) -> Result {
- let mut context = Context::new();
- let slug = req.param("slug")?;
- let post = fs::get_one_post(slug, is_logged_in(&req)).await?;
-
- context.insert("post", &post);
- render_html_response("single.html", &context, req)
- }
-
- pub async fn new_post(req: Request<State>) -> Result {
- let context = Context::new();
- render_html_response("new.html", &context, req)
- }
-
- pub async fn edit_post(req: Request<State>) -> Result {
- let mut context = Context::new();
- let slug = req.param("slug")?;
- let mut post = fs::get_one_post(slug, is_logged_in(&req)).await?;
- post.body = post.body.replace("<br>", "\n");
- post.html = post.generate_html();
- context.insert("post", &post);
- render_html_response("edit.html", &context, req)
- }
-
- pub async fn create_post(mut req: Request<State>) -> Result {
- let mut post: Post = req.body_form().await?;
- post.date = Local::now().date().naive_local().to_string();
- post.body = post.body.trim().to_owned();
- post.html = post.generate_html();
- post.save().await?;
- Ok(Redirect::new("/").into())
- }
-
- pub async fn update_post(mut req: Request<State>) -> Result {
- let mut post: Post = req.body_form().await?;
- post.html = post.generate_html();
- post.save().await?;
- req.session_mut()
- .insert("flash_success", String::from("Post updated successfully"))?;
- redirect(&format!("/posts/{}", post.slug))
- }
-
- pub async fn delete_post(mut req: Request<State>) -> Result {
- let slug: String = req.param("slug")?;
- fs::delete_post(slug)?;
- req.session_mut()
- .insert("flash_success", String::from("Post deleted successfully"))?;
- render_json_response(json!({ "success": "true" }))
- }
-
- pub async fn preview_post(mut req: Request<State>) -> Result {
- let body: String = req.body_string().await?;
- let html = util::generate_html(&body);
- render_json_response(json!({ "body": html }))
- }
-
- pub async fn login_page(req: Request<State>) -> Result {
- render_html_response("login.html", &Context::new(), req)
- }
-
- pub async fn login(mut req: Request<State>) -> 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().insert("logged_in", true)?;
- redirect("/")
- } else {
- req.session_mut().remove("logged_in");
- req.session_mut()
- .insert("flash_error", "Invalid credentials")?;
- let login_path = req.state().login_path.clone();
- redirect(&login_path)
- }
- }
-
- pub async fn logout(mut req: Request<State>) -> Result {
- req.session_mut().insert("logged_in", false)?;
- Ok(Redirect::new("/").into())
- }
-
- pub fn render_html_response(
- template: &str,
- context: &Context,
- req: Request<State>,
- ) -> Result<Response> {
- let mut context = context.clone();
- let logged_in: bool = req.session().get("logged_in").unwrap_or(false);
- let login_path = &req.state().login_path;
- context.insert("logged_in", &logged_in);
- context.insert("login_path", login_path);
- context.extend(prepare_flash_messages(req));
-
- let html = render_template(template, &context)?;
-
- let res = Response::builder(StatusCode::Ok)
- .body(html)
- .content_type(mime::HTML)
- .build();
-
- Ok(res)
- }
-
- pub fn render_json_response(json: serde_json::Value) -> Result<Response> {
- let res = Response::builder(StatusCode::Ok)
- .body(json)
- .content_type(mime::JSON)
- .build();
-
- Ok(res)
- }
-
- fn redirect(path: &str) -> Result<Response> {
- Ok(Redirect::new(path).into())
- }
-
- pub fn render_template(template: &str, context: &Context) -> Result<String> {
- let tera = Tera::new("templates/**/*.html")?;
- let html = tera.render(template, &context)?;
- Ok(html)
- }
-
- fn prepare_flash_messages(mut req: Request<State>) -> Context {
- let mut context = Context::new();
- context.insert("flash_error", &false);
- context.insert("flash_success", &false);
-
- for key in vec!["flash_error", "flash_success"] {
- match req.session_mut().get::<String>(key) {
- Some(value) => {
- req.session_mut().remove(key);
- &context.insert(key, &value);
- }
- None => {}
- }
- }
-
- context
- }
-
- fn is_logged_in(req: &Request<State>) -> bool {
- req.session().get("logged_in").unwrap_or(false)
- }
|