diff --git a/src/main.rs b/src/main.rs index 483773c..e8348cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,15 +8,19 @@ extern crate serde_derive; extern crate tera; use actix_files as fs; -use actix_web::{App, HttpServer}; +use actix_web::{middleware, App, HttpServer}; +use std::string::String; #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() + //.wrap(middleware::NormalizePath::default()) .service(routes::root) .service(routes::blog) .service(routes::blog_permalink) + .service(routes::blog_submit) + .service(routes::blog_new_post) .service(fs::Files::new("/static", "./static/")) }) .bind("localhost:8000")? diff --git a/src/routes.rs b/src/routes.rs index 5aa09ac..a27b622 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,7 +1,8 @@ use crate::db::*; use actix_files as fs; -use actix_web::{get, web, HttpResponse, Responder}; +use actix_web::{get, http::StatusCode, post, web, web::Form, HttpResponse, Responder}; +use serde::Deserialize; use tera::{Context, Tera}; #[get("/")] @@ -28,21 +29,59 @@ async fn blog() -> impl Responder { HttpResponse::Ok().body(result) } -#[get("/blog/{post_id}")] -async fn blog_permalink(web::Path(post_id): web::Path) -> impl Responder { - let post = get_post_by_id(post_id as i32); - - let mut context = Context::new(); - context.insert("posts", &[post]); - - // one-off render blog template with context - let result = Tera::one_off( - &(std::fs::read_to_string("templates/blog.html") - .unwrap_or_else(|e| panic!("Error, couldn't load blog template.\n{}", e)) - .as_str()), - &context, - true, +#[get("/blog/submit")] +async fn blog_submit() -> impl Responder { + HttpResponse::Ok().set_header("SameSite", "secure").body( + std::fs::read_to_string("html/submit.html") + .unwrap_or_else(|e| panic!("Error, couldn't load submit html file.\n{}", e)), ) - .unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e)); - HttpResponse::Ok().body(result) +} + +#[get("/blog/id/{post_id}")] +async fn blog_permalink(web::Path(post_id): web::Path) -> impl Responder { + match post_id.parse::() { + Err(_) => HttpResponse::new(StatusCode::NOT_FOUND), + Ok(i) => { + let post = get_post_by_id(i as i32); + + let mut context = Context::new(); + context.insert("posts", &[post]); + + // one-off render blog template with context + let result = Tera::one_off( + &(std::fs::read_to_string("templates/blog.html") + .unwrap_or_else(|e| panic!("Error, couldn't load blog template.\n{}", e)) + .as_str()), + &context, + true, + ) + .unwrap_or_else(|e| panic!("Error, couldn't render blog template.\n{}", e)); + HttpResponse::Ok().body(result) + } + } +} + +#[derive(Deserialize)] +struct NewPostForm { + title: String, + body: String, + token: String, +} + +#[post("/blog/posts/new")] +async fn blog_new_post(form: Form) -> impl Responder { + let token: String = std::env::var("SUBMIT_TOKEN").unwrap_or_else(|_| { + panic!("Error, can't authenticate submission if no submit token was set."); + }); + + if form.token == token { + add_post(&form.title.as_str(), &form.body.as_str()); + println!("New blog post created."); + } else { + println!("Unauthorized new blog post"); + } + + HttpResponse::MovedPermanently() + .set_header("LOCATION", "/blog") + .finish() }