implemented authentication for new blog posts

This commit is contained in:
Leonard Lorenz 2020-10-22 16:52:04 +02:00
parent bc806593e3
commit b56dcdf330
2 changed files with 61 additions and 18 deletions

View file

@ -8,15 +8,19 @@ extern crate serde_derive;
extern crate tera; extern crate tera;
use actix_files as fs; use actix_files as fs;
use actix_web::{App, HttpServer}; use actix_web::{middleware, App, HttpServer};
use std::string::String;
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
//.wrap(middleware::NormalizePath::default())
.service(routes::root) .service(routes::root)
.service(routes::blog) .service(routes::blog)
.service(routes::blog_permalink) .service(routes::blog_permalink)
.service(routes::blog_submit)
.service(routes::blog_new_post)
.service(fs::Files::new("/static", "./static/")) .service(fs::Files::new("/static", "./static/"))
}) })
.bind("localhost:8000")? .bind("localhost:8000")?

View file

@ -1,7 +1,8 @@
use crate::db::*; use crate::db::*;
use actix_files as fs; 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}; use tera::{Context, Tera};
#[get("/")] #[get("/")]
@ -28,21 +29,59 @@ async fn blog() -> impl Responder {
HttpResponse::Ok().body(result) HttpResponse::Ok().body(result)
} }
#[get("/blog/{post_id}")] #[get("/blog/submit")]
async fn blog_permalink(web::Path(post_id): web::Path<u32>) -> impl Responder { async fn blog_submit() -> impl Responder {
let post = get_post_by_id(post_id as i32); HttpResponse::Ok().set_header("SameSite", "secure").body(
std::fs::read_to_string("html/submit.html")
let mut context = Context::new(); .unwrap_or_else(|e| panic!("Error, couldn't load submit html file.\n{}", e)),
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)
#[get("/blog/id/{post_id}")]
async fn blog_permalink(web::Path(post_id): web::Path<std::string::String>) -> impl Responder {
match post_id.parse::<u32>() {
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<NewPostForm>) -> 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()
} }