diff --git a/Cargo.toml b/Cargo.toml index 8f4e7c4..ccc5131 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,19 +2,15 @@ name = "codigocomentado" version = "0.1.0" authors = ["kirbylife <gabriel13m@gmail.com>"] -edition = "2018" +edition = "2021" [dependencies] -rocket = "0.4.11" +rocket = { version = "0.5.0", features = ["secrets"] } +rocket_dyn_templates = { version = "0.1.0", features = ["tera"] } diesel = { version = "1.0.0", features = ["postgres", "chrono"] } dotenv = "0.9.0" rand = "0.6.0" chrono = { version = "0.4.9", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } -tera = "0.11" comrak = "0.6" - -[dependencies.rocket_contrib] -version = "0.4.2" -default-features = false -features = ["json", "serve", "handlebars_templates", "tera_templates"] \ No newline at end of file +tera = "1.19.1" diff --git a/Rocket.toml b/Rocket.toml new file mode 100644 index 0000000..b6315da --- /dev/null +++ b/Rocket.toml @@ -0,0 +1,7 @@ +[default] +address = "0.0.0.0" +limits = { form = "100 MiB", json = "100 MiB" } +port = 8000 + +[release] +secret_key = "openssl rand -base64 32" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..36c419b --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +edition = "2021" \ No newline at end of file diff --git a/src/admin.rs b/src/admin.rs index 5b93cec..111d77c 100644 --- a/src/admin.rs +++ b/src/admin.rs @@ -1,11 +1,11 @@ +use crate::contexts; use crate::controllers::posts; -use crate::misc::get_context; use crate::models::NewPost; -use rocket::http::{Cookie, Cookies}; -use rocket::request::Form; +use rocket::form::Form; +use rocket::http::{Cookie, CookieJar}; use rocket::response::Redirect; use rocket::Route; -use rocket_contrib::templates::Template; +use rocket_dyn_templates::Template; use std::env; use std::vec::Vec; @@ -16,20 +16,20 @@ struct Login { } #[get("/")] -fn index(mut cookies: Cookies<'_>) -> Result<Redirect, Template> { +fn index(cookies: &CookieJar<'_>) -> Result<Redirect, Template> { let password = env::var("admin_pass").expect("admin_pass not setted"); match cookies.get_private("user") { Some(cookie) => { if cookie.value() == password { Ok(Redirect::to("/admin/panel")) } else { - let context = get_context(); + let context = contexts::Empty::new(); Err(Template::render("admin/index", context)) } } None => { - let context = get_context(); + let context = contexts::Empty::new(); Err(Template::render("admin/index", context)) } @@ -37,7 +37,7 @@ fn index(mut cookies: Cookies<'_>) -> Result<Redirect, Template> { } #[post("/", data = "<login>")] -fn login(mut cookies: Cookies<'_>, login: Form<Login>) -> Redirect { +fn login(cookies: &CookieJar<'_>, login: Form<Login>) -> Redirect { let username = env::var("admin_user").expect("admin_user not setted"); let password = env::var("admin_pass").expect("admin_pass not setted"); @@ -50,18 +50,16 @@ fn login(mut cookies: Cookies<'_>, login: Form<Login>) -> Redirect { } #[get("/panel")] -fn panel(mut cookies: Cookies<'_>) -> Result<Template, Redirect> { +fn panel(cookies: &CookieJar<'_>) -> Result<Template, Redirect> { let password = env::var("admin_pass").expect("admin_pass not setted"); match cookies.get_private("user") { Some(cookie) => { if cookie.value() == password { - let mut context = get_context(); - let (all_posts, n_posts) = posts::get_posts(None); - context.insert("posts", &all_posts); - context.insert("n_posts", &n_posts); + let context = contexts::AllPosts::new(all_posts, n_posts); + Ok(Template::render("admin/panel", context)) } else { Err(Redirect::to("/admin")) @@ -72,17 +70,15 @@ fn panel(mut cookies: Cookies<'_>) -> Result<Template, Redirect> { } #[get("/add_post")] -fn add_post(mut cookies: Cookies<'_>) -> Result<Template, Redirect> { +fn add_post(cookies: &CookieJar<'_>) -> Result<Template, Redirect> { let password = env::var("admin_pass").expect("admin_pass not setted"); match cookies.get_private("user") { Some(cookie) => { if cookie.value() == password { - let context = get_context(); + let context = contexts::Empty::new(); Ok(Template::render("admin/add_post", context)) - } else if cookie.value() == "123" { - Err(Redirect::to("/admin")) } else { Err(Redirect::to("/admin")) } @@ -92,7 +88,7 @@ fn add_post(mut cookies: Cookies<'_>) -> Result<Template, Redirect> { } #[post("/add_post", data = "<post>")] -fn write_add_post(mut cookies: Cookies<'_>, post: Form<NewPost>) -> Redirect { +fn write_add_post(cookies: &CookieJar<'_>, post: Form<NewPost>) -> Redirect { let password = env::var("admin_pass").expect("admin_pass not setted"); match cookies.get_private("user") { @@ -111,17 +107,16 @@ fn write_add_post(mut cookies: Cookies<'_>, post: Form<NewPost>) -> Redirect { } #[get("/edit_post/<id>")] -fn edit_post(mut cookies: Cookies<'_>, id: i32) -> Result<Template, Redirect> { +fn edit_post(cookies: &CookieJar<'_>, id: i32) -> Result<Template, Redirect> { let password = env::var("admin_pass").expect("admin_pass not setted"); match cookies.get_private("user") { Some(cookie) => { if cookie.value() == password { - let mut context = get_context(); - let post = posts::get_post(id).unwrap(); - context.insert("post", &post); + let context = contexts::SinglePost::new(post); + Ok(Template::render("admin/edit_post", context)) } else { Err(Redirect::to("/admin")) @@ -132,7 +127,7 @@ fn edit_post(mut cookies: Cookies<'_>, id: i32) -> Result<Template, Redirect> { } #[post("/edit_post/<id>", data = "<post>")] -fn write_edit_post(mut cookies: Cookies<'_>, id: i32, post: Form<NewPost>) -> Redirect { +fn write_edit_post(cookies: &CookieJar<'_>, id: i32, post: Form<NewPost>) -> Redirect { let password = env::var("admin_pass").expect("admin_pass not setted"); match cookies.get_private("user") { diff --git a/src/contexts.rs b/src/contexts.rs new file mode 100644 index 0000000..16e0683 --- /dev/null +++ b/src/contexts.rs @@ -0,0 +1,94 @@ +use crate::controllers::posts; +use crate::misc::gen_title; +use crate::models::Post; +use serde::Serialize; + +#[derive(Serialize)] +pub struct PageOfPosts { + title: String, + posts: Vec<Post>, + total_pages: i64, + actual_page: u64, +} + +impl PageOfPosts { + pub fn new(posts: Vec<Post>, actual_page: u64, n_posts: i64) -> Self { + let total_pages = (n_posts as f64 / posts::MAX_POSTS_PER_PAGE as f64).ceil() as i64; + + PageOfPosts { + title: gen_title(), + posts, + total_pages, + actual_page, + } + } +} + +#[derive(Serialize)] +pub struct XmlFeed { + posts: Vec<Post>, +} + +impl XmlFeed { + pub fn new(posts: Vec<Post>) -> Self { + XmlFeed { posts } + } +} + +#[derive(Serialize)] +pub struct SinglePost { + title: String, + post: Post, +} + +impl SinglePost { + pub fn new(post: Post) -> Self { + SinglePost { + title: gen_title(), + post, + } + } +} + +#[derive(Serialize)] +pub struct NotFound { + title: String, + uri: String, +} + +impl NotFound { + pub fn new(uri: String) -> Self { + NotFound { + title: gen_title(), + uri, + } + } +} + +#[derive(Serialize)] +pub struct AllPosts { + title: String, + posts: Vec<Post>, + n_posts: i64, +} + +impl AllPosts { + pub fn new(posts: Vec<Post>, n_posts: i64) -> Self { + AllPosts { + title: gen_title(), + posts, + n_posts, + } + } +} + +#[derive(Serialize)] +pub struct Empty { + title: String, +} + +impl Empty { + pub fn new() -> Self { + Empty { title: gen_title() } + } +} diff --git a/src/main.rs b/src/main.rs index 41c84ef..eed923d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ -#![feature(proc_macro_hygiene, decl_macro)] - pub mod admin; +pub mod contexts; pub mod controllers; pub mod misc; pub mod models; @@ -10,20 +9,14 @@ mod schema; extern crate rocket; #[macro_use] extern crate diesel; -extern crate comrak; -extern crate dotenv; -extern crate rocket_contrib; -extern crate tera; use comrak::{markdown_to_html, ComrakOptions}; use controllers::posts; use dotenv::dotenv; -use misc::get_context; -use rocket::response::content; -use rocket::response::NamedFile; +use rocket::fs::{FileServer, NamedFile}; +use rocket::response::content::RawXml; use rocket::Request; -use rocket_contrib::serve::StaticFiles; -use rocket_contrib::templates::Template; +use rocket_dyn_templates::Template; use std::path::Path; use std::vec::Vec; @@ -31,21 +24,15 @@ use std::vec::Vec; fn index(page: Option<u64>) -> Template { let page: u64 = page.unwrap_or(1); - let mut context = get_context(); - let (posts, n_posts) = posts::get_posts(Some(page)); - let total_pages = (n_posts as f64 / posts::MAX_POSTS_PER_PAGE as f64).ceil() as i64; + let context = contexts::PageOfPosts::new(posts, page, n_posts); - context.insert("posts", &posts); - context.insert("total_pages", &total_pages); - context.insert("actual_page", &page); Template::render("index", context) } #[get("/feed.xml")] -fn rss_feed() -> content::Xml<Template> { - let mut context = get_context(); +fn rss_feed() -> RawXml<Template> { let (mut posts, _) = posts::get_posts(None); let comrak_options = ComrakOptions { @@ -61,14 +48,13 @@ fn rss_feed() -> content::Xml<Template> { post.content = content; }); - context.insert("posts", &posts); + let context = contexts::XmlFeed::new(posts); - content::Xml(Template::render("rss", context)) + RawXml(Template::render("rss", context)) } #[get("/atom.xml")] -fn atom_feed() -> content::Xml<Template> { - let mut context = get_context(); +fn atom_feed() -> RawXml<Template> { let (mut posts, _) = posts::get_posts(None); let comrak_options = ComrakOptions { @@ -84,15 +70,13 @@ fn atom_feed() -> content::Xml<Template> { post.content = content; }); - context.insert("posts", &posts); + let context = contexts::XmlFeed::new(posts); - content::Xml(Template::render("atom", context)) + RawXml(Template::render("atom", context)) } #[get("/post/<title>")] fn show_post(title: String) -> Template { - let mut context = get_context(); - let title_splited: Vec<&str> = title.split('-').collect(); let id = title_splited.last().unwrap().parse().unwrap_or(-1); @@ -109,12 +93,15 @@ fn show_post(title: String) -> Template { let content = markdown_to_html(&post.content, &comrak_options); post.content = content; - context.insert("post", &post); + let context = contexts::SinglePost::new(post); + Template::render("post", context) } Err(_) => { let uri = format!("/post/{}", title_splited.join("-")); - context.insert("url", &uri); + + let context = contexts::NotFound::new(uri); + Template::render("404", context) } } @@ -122,27 +109,26 @@ fn show_post(title: String) -> Template { #[catch(404)] fn not_found_404(req: &Request) -> Template { - let mut context = get_context(); - let uri = format!("{}", req.uri()); - context.insert("url", &uri); + let context = contexts::NotFound::new(uri); + Template::render("404", context) } #[get("/favicon.ico")] -fn favicon() -> Option<NamedFile> { - NamedFile::open(Path::new("static/favicon.ico")).ok() +async fn favicon() -> Option<NamedFile> { + NamedFile::open(Path::new("static/favicon.ico")).await.ok() } -fn main() { +#[launch] +fn rocket() -> _ { dotenv().ok(); - rocket::ignite() + rocket::build() .attach(Template::fairing()) .mount("/", routes![index, show_post, favicon, rss_feed, atom_feed]) .mount("/admin", admin::get_routes()) - .mount("/static", StaticFiles::from("static")) - .register(catchers![not_found_404]) - .launch(); + .mount("/static", FileServer::from("static")) + .register("/", catchers![not_found_404]) } diff --git a/src/misc.rs b/src/misc.rs index 2f75928..bc5daa3 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,7 +1,4 @@ -extern crate tera; - use rand::Rng; -use tera::Context; const TITLES: [&str; 11] = [ "/* {} */", @@ -17,13 +14,9 @@ const TITLES: [&str; 11] = [ "(* {} *)", ]; -pub fn get_context() -> Context { - let mut context = Context::new(); - +pub fn gen_title() -> String { let mut rng = rand::thread_rng(); let title_fmt = TITLES[rng.gen_range(0, TITLES.len())]; let title = str::replace(title_fmt, "{}", "CódigoComentado"); - - context.insert("title", &title); - context + title.to_string() }