Bumped to 0.3.0. Switched /blog routes to / prefix and moved preevious / route to /about. Changed some env var loading code.

This commit is contained in:
Leonard Lorenz 2021-04-03 23:26:10 +02:00
parent 5c1c0de1b1
commit accbdb6f7a
11 changed files with 167 additions and 77 deletions

2
site/Cargo.lock generated
View file

@ -572,7 +572,7 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]]
name = "crablog"
version = "0.2.3"
version = "0.3.0"
dependencies = [
"actix-files",
"actix-web",

View file

@ -1,6 +1,6 @@
[package]
name = "crablog"
version = "0.2.3"
version = "0.3.0"
authors = ["Leonard Lorenz <dev@leonardlorenz.de>"]
edition = "2018"

View file

@ -9,50 +9,89 @@ extern crate serde_derive;
extern crate tera;
use actix_files as fs;
use actix_web::{App, HttpServer, middleware::Logger};
use actix_web::{middleware::Logger, App, HttpServer};
use env_logger::Env;
use tera::Tera;
use std::{env, sync::RwLock, collections::HashMap};
use once_cell::sync::Lazy;
use std::{collections::HashMap, env, sync::RwLock};
use tera::Tera;
pub static CONFIG_MAP: Lazy<RwLock<HashMap<String, String>>> = Lazy::new(|| {
let mut config: HashMap<String, String> = HashMap::new();
config.insert(String::from("SUBMIT_TOKEN"), env::var("SUBMIT_TOKEN").expect("SUBMIT_TOKEN variable not set."));
config.insert(String::from("ROOT_PATH"), env::var("ROOT_PATH").expect("ROOT_PATH variable not set."));
config.insert(String::from("USERNAME"), env::var("USERNAME").expect("USERNAME variable not set."));
config.insert(String::from("EMAIL"), env::var("EMAIL").expect("EMAIL variable not set."));
config.insert(String::from("BIND_PORT"), env::var("BIND_PORT").expect("BIND_PORT variable not set."));
if let Ok(acc) = env::var("GITHUB_ACCOUNT") {
config.insert(String::from("GITHUB_ACCOUNT"), acc.clone());
let required_env_vars = [
"SUBMIT_TOKEN",
"ROOT_PATH",
"USERNAME",
"EMAIL",
"BIND_PORT",
];
let optional_env_vars = [
"GITHUB_ACCOUNT",
"TWITTER_ACCOUNT",
"MASTODON_ACCOUNT",
"DISCORD_ACCOUNT",
"REDDIT_ACCOUNT",
];
// Test if variable is set. If not, panic.
let mut insert_required_env = |env: &str| {
let env_string = String::from(env);
config.insert(
env_string.clone(), // env var name
env::var(env_string).expect(format!("`{}` variable not set.", env).as_str()), // env var content
)
};
for var in required_env_vars.iter() {
insert_required_env(var);
}
if let Ok(acc) = env::var("TWITTER_ACCOUNT") {
config.insert(String::from("TWITTER_ACCOUNT"), acc.clone());
}
if let Ok(acc) = env::var("MASTODON_ACCOUNT") {
config.insert(String::from("MASTODON_ACCOUNT"), acc.clone());
}
if let Ok(acc) = env::var("DISCORD_ACCOUNT") {
config.insert(String::from("DISCORD_ACCOUNT"), acc.clone());
}
if let Ok(acc) = env::var("REDDIT_ACCOUNT") {
config.insert(String::from("REDDIT_ACCOUNT"), acc.clone());
// Test if variable is set. If it is insert into config.
let mut insert_optional_env = |env: &str| {
if let Ok(var_content) = env::var(String::from(env)) {
config.insert(String::from(env), var_content.clone());
}
};
for var in optional_env_vars.iter() {
insert_optional_env(var);
}
// Print some info about the current configuration
println!("Submit token = `{}`", config.get("SUBMIT_TOKEN").unwrap());
println!(
"Current working directory = `{}`",
env::current_dir().unwrap().to_str().unwrap()
);
println!("Root path = `{}`", config.get("ROOT_PATH").unwrap());
println!(
"Template path = `{}/templates/*`",
config.get("ROOT_PATH").unwrap()
);
println!("Launching on 0.0.0.0:{}", config.get("BIND_PORT").unwrap());
RwLock::new(config)
});
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let mut tera = Tera::new(format!("{}{}", CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(), "/templates/*").as_str()).unwrap();
let mut tera = Tera::new(
format!(
"{}{}",
CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(),
"/templates/*"
)
.as_str(),
)
.unwrap();
tera.autoescape_on(vec![".sql"]);
env_logger::Builder::from_env(Env::default().default_filter_or("info"));
App::new()
.data(tera)
.service(routes::root)
.service(routes::about)
.service(routes::blog)
.service(routes::blog_all)
.service(routes::blog_by_id)
@ -64,10 +103,20 @@ async fn main() -> std::io::Result<()> {
.service(api::blog_edit_post)
.service(api::blog_hide_post)
.service(api::blog_delete_post)
.service(fs::Files::new("/static", format!("{}{}", CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(), "/static")))
.service(fs::Files::new(
"/static",
format!(
"{}{}",
CONFIG_MAP.read().unwrap().get("ROOT_PATH").unwrap(),
"/static"
),
))
.wrap(Logger::new("%a %r %t"))
})
.bind(format!("0.0.0.0:{}", CONFIG_MAP.read().unwrap().get("BIND_PORT").unwrap()))?
.bind(format!(
"0.0.0.0:{}",
CONFIG_MAP.read().unwrap().get("BIND_PORT").unwrap()
))?
.run()
.await
}

View file

@ -1,8 +1,8 @@
use crate::db;
use actix_web::{get, http::StatusCode, web, HttpResponse, Error, error};
use tera::Context;
use super::CONFIG_MAP;
use actix_web::{error, get, http::StatusCode, web, Error, HttpResponse};
use tera::Context;
/// tests if the post id is a valid i32 integer bigger than zero
/// assert(!(id_valid("2147483648").0))
@ -33,10 +33,13 @@ pub fn replace_br_tags(x: &str) -> String {
x.replace("<br>", "\n")
}
#[get("/")]
async fn root(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
#[get("/about")]
async fn about(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let mut context = Context::new();
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
context.insert("email", CONFIG_MAP.read().unwrap().get("EMAIL").unwrap());
if let Some(acc) = CONFIG_MAP.read().unwrap().get("GITHUB_ACCOUNT") {
context.insert("github_account", acc);
@ -54,89 +57,113 @@ async fn root(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
context.insert("reddit_account", acc);
}
let result = tmpl.render("index.html", &context)
let result = tmpl
.render("about.html", &context)
.map_err(|e| error::ErrorInternalServerError(format!("Template error\n{}", e)))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/blog")]
#[get("/")]
async fn blog(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let posts = db::get_last_five_posts();
let mut context = Context::new();
context.insert("posts", &posts);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
let result = tmpl.render("blog.html", &context)
let result = tmpl
.render("blog.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/blog/all")]
#[get("/all")]
async fn blog_all(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let posts = db::get_all_posts();
let mut context = Context::new();
context.insert("posts", &posts);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
let result = tmpl.render("blog-all-posts.html", &context)
let result = tmpl
.render("blog-all-posts.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/blog/id/{post_id}")]
async fn blog_by_id(tmpl: web::Data<tera::Tera>, web::Path(post_id): web::Path<std::string::String>) -> Result<HttpResponse, Error> {
#[get("/id/{post_id}")]
async fn blog_by_id(
tmpl: web::Data<tera::Tera>,
web::Path(post_id): web::Path<std::string::String>,
) -> Result<HttpResponse, Error> {
let (valid, id) = id_valid(post_id);
if valid {
let post = db::get_post_by_id(id as i32);
if !post.published {
return Ok(HttpResponse::new(StatusCode::UNAUTHORIZED))
return Ok(HttpResponse::new(StatusCode::UNAUTHORIZED));
}
let mut context = Context::new();
context.insert("post", &post);
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
let result = tmpl.render("blog-by-id.html", &context)
let result = tmpl
.render("blog-by-id.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
return Ok(HttpResponse::Ok().content_type("text/html").body(result))
return Ok(HttpResponse::Ok().content_type("text/html").body(result));
} else {
return Ok(HttpResponse::new(StatusCode::NOT_FOUND))
return Ok(HttpResponse::new(StatusCode::NOT_FOUND));
}
}
#[get("/blog/submit")]
#[get("/submit")]
async fn blog_submit(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let mut context = Context::new();
context.insert("title", "");
context.insert("body", "");
let result = tmpl.render("submit.html", &context)
let result = tmpl
.render("submit.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
return Ok(HttpResponse::Ok().content_type("text/html").body(result))
return Ok(HttpResponse::Ok().content_type("text/html").body(result));
}
#[get("/blog/edit")]
#[get("/edit")]
async fn blog_edit(tmpl: web::Data<tera::Tera>) -> Result<HttpResponse, Error> {
let mut context = Context::new();
context.insert("posts", &db::get_all_posts());
context.insert("username", CONFIG_MAP.read().unwrap().get("USERNAME").unwrap());
context.insert(
"username",
CONFIG_MAP.read().unwrap().get("USERNAME").unwrap(),
);
let result = tmpl.render("edit.html", &context)
let result = tmpl
.render("edit.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))
}
#[get("/blog/edit/{post_id}")]
async fn blog_edit_by_id(tmpl: web::Data<tera::Tera>, web::Path(post_id): web::Path<std::string::String>) -> Result<HttpResponse, Error> {
#[get("/edit/{post_id}")]
async fn blog_edit_by_id(
tmpl: web::Data<tera::Tera>,
web::Path(post_id): web::Path<std::string::String>,
) -> Result<HttpResponse, Error> {
let (valid, id) = id_valid(post_id);
if valid {
let mut post = db::get_post_by_id(id as i32);
@ -149,7 +176,8 @@ async fn blog_edit_by_id(tmpl: web::Data<tera::Tera>, web::Path(post_id): web::P
context.insert("body", &post.body);
context.insert("id", &id);
let result = tmpl.render("edit-form.html", &context)
let result = tmpl
.render("edit-form.html", &context)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(result))