diff --git a/README.md b/README.md index f85e529..c86542e 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,14 @@ ROOT_PATH=/path/to/template/directory/and/sqliteDB ## Routes -- / site welcome -- /blog shows the last 5 posts -- /blog/id/ shows a single post by id -- /blog/all shows all posts -- /blog/submit set your submit token and create posts -- /blog/edit/ edit, delete or hide posts +| Route | Description | +| ---------- | -------------------------------------------------- | +| / | shows the last 5 posts | +| /id/ | shows a single post by id | +| /all | shows all posts | +| /submit | set your submit token and create posts | +| /edit/ | edit, delete or hide posts | +| /about | information about this blog, social media accounts | **API Routes** diff --git a/content/templates/index.html b/content/templates/about.html similarity index 89% rename from content/templates/index.html rename to content/templates/about.html index c894c0c..b52bc53 100644 --- a/content/templates/index.html +++ b/content/templates/about.html @@ -13,9 +13,11 @@

Hi, I'm {{ username }}

+

+ Back to the blog +

- I have a blog.
- If you have questions or input for me please send me an E-Mail to {{ email }} + This is my blog. If you have questions or input for me please send me an E-Mail to {{ email }}


diff --git a/content/templates/blog-all-posts.html b/content/templates/blog-all-posts.html index 6a3bcdc..7f9eeaf 100644 --- a/content/templates/blog-all-posts.html +++ b/content/templates/blog-all-posts.html @@ -13,13 +13,16 @@ -

{{ username }}' blog

-

Home Last 5 posts

+

{{ username }}' blog

+

+ About + Last 5 posts +

    {% for post in posts %}

    {{ post.title }}

    diff --git a/content/templates/blog-by-id.html b/content/templates/blog-by-id.html index 14a55cd..89f4ec4 100644 --- a/content/templates/blog-by-id.html +++ b/content/templates/blog-by-id.html @@ -13,12 +13,16 @@ -

    {{ username }}' blog

    -

    Home Last 5 Posts All Posts

    +

    {{ username }}' blog

    +

    + Home + About + All Posts +

      {{ post.title }}

      diff --git a/content/templates/blog.html b/content/templates/blog.html index 78959b5..c5a13ee 100644 --- a/content/templates/blog.html +++ b/content/templates/blog.html @@ -13,13 +13,15 @@ -

      {{ username }}' blog

      -

      Home All Posts

      +

      {{ username }}' blog

      +

      + About + All Posts

        {% for post in posts %}

        {{ post.title }}

        diff --git a/content/templates/edit.html b/content/templates/edit.html index 8a02d1a..e6a1643 100644 --- a/content/templates/edit.html +++ b/content/templates/edit.html @@ -11,11 +11,11 @@ -

        {{ username }}' blog

        +

        {{ username }}' blog

        Edit posts

        diff --git a/docker-compose.yml b/docker-compose.yml index e8a2a0c..67e9810 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.8" +version: "3.0" services: crablog: build: . diff --git a/site/Cargo.lock b/site/Cargo.lock index 205072e..d32128c 100644 --- a/site/Cargo.lock +++ b/site/Cargo.lock @@ -572,7 +572,7 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] name = "crablog" -version = "0.2.3" +version = "0.3.0" dependencies = [ "actix-files", "actix-web", diff --git a/site/Cargo.toml b/site/Cargo.toml index b593e95..8476d15 100644 --- a/site/Cargo.toml +++ b/site/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crablog" -version = "0.2.3" +version = "0.3.0" authors = ["Leonard Lorenz "] edition = "2018" diff --git a/site/src/main.rs b/site/src/main.rs index ce98ba6..ad7d5a1 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -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>> = Lazy::new(|| { let mut config: HashMap = 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 } diff --git a/site/src/routes.rs b/site/src/routes.rs index fd820de..aadc38f 100644 --- a/site/src/routes.rs +++ b/site/src/routes.rs @@ -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("
        ", "\n") } -#[get("/")] -async fn root(tmpl: web::Data) -> Result { +#[get("/about")] +async fn about(tmpl: web::Data) -> Result { 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) -> Result { 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) -> Result { 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) -> Result { 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, web::Path(post_id): web::Path) -> Result { +#[get("/id/{post_id}")] +async fn blog_by_id( + tmpl: web::Data, + web::Path(post_id): web::Path, +) -> Result { 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) -> Result { 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) -> Result { 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, web::Path(post_id): web::Path) -> Result { +#[get("/edit/{post_id}")] +async fn blog_edit_by_id( + tmpl: web::Data, + web::Path(post_id): web::Path, +) -> Result { 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, 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))