From de44564ba0362776ff16cdc658b65d8a8d605705 Mon Sep 17 00:00:00 2001 From: Alphonse Paix Date: Mon, 29 Sep 2025 02:39:53 +0200 Subject: [PATCH] Templates and TLS requests Refactored HTML templates and added TLS back to issue HTTP requests --- Cargo.lock | 115 +++++++ Cargo.toml | 3 +- src/routes.rs | 15 +- src/routes/admin/change_password.rs | 4 +- src/routes/admin/newsletters.rs | 2 +- src/routes/admin/posts.rs | 8 +- src/routes/admin/subscribers.rs | 10 +- src/routes/subscriptions.rs | 5 +- src/routes/unsubscribe.rs | 19 +- src/templates.rs | 50 ++- templates/dashboard.html | 322 ------------------ templates/dashboard/change_password.html | 59 ++++ templates/dashboard/dashboard.html | 27 ++ templates/dashboard/publish.html | 50 +++ templates/dashboard/send_email.html | 60 ++++ templates/dashboard/stats.html | 73 ++++ .../subscribers/card.html} | 0 templates/dashboard/subscribers/list.html | 58 ++++ templates/error.html | 9 - templates/{ => error}/404.html | 0 templates/{ => error}/500.html | 0 templates/message.html | 14 + .../card.html} | 0 templates/{posts.html => posts/list.html} | 2 +- templates/{post.html => posts/page.html} | 0 templates/{ => subscribe}/confirm.html | 0 templates/success.html | 9 - .../confirm.html} | 0 .../form.html} | 0 29 files changed, 513 insertions(+), 401 deletions(-) delete mode 100644 templates/dashboard.html create mode 100644 templates/dashboard/change_password.html create mode 100644 templates/dashboard/dashboard.html create mode 100644 templates/dashboard/publish.html create mode 100644 templates/dashboard/send_email.html create mode 100644 templates/dashboard/stats.html rename templates/{sub_card_fragment.html => dashboard/subscribers/card.html} (100%) create mode 100644 templates/dashboard/subscribers/list.html delete mode 100644 templates/error.html rename templates/{ => error}/404.html (100%) rename templates/{ => error}/500.html (100%) create mode 100644 templates/message.html rename templates/{post_card_fragment.html => posts/card.html} (100%) rename templates/{posts.html => posts/list.html} (97%) rename templates/{post.html => posts/page.html} (100%) rename templates/{ => subscribe}/confirm.html (100%) delete mode 100644 templates/success.html rename templates/{unsubscribe_confirm.html => unsubscribe/confirm.html} (100%) rename templates/{unsubscribe.html => unsubscribe/form.html} (100%) diff --git a/Cargo.lock b/Cargo.lock index d4e4ab2..96dfc0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -339,6 +339,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.41" @@ -922,8 +928,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -933,9 +941,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1109,6 +1119,23 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.2", +] + [[package]] name = "hyper-util" version = "0.1.16" @@ -1414,6 +1441,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "markdown" version = "1.0.0" @@ -1862,6 +1895,61 @@ dependencies = [ "syn", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.5.10", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.40" @@ -2018,16 +2106,21 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2035,6 +2128,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 1.0.2", ] [[package]] @@ -2148,6 +2242,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ + "web-time", "zeroize", ] @@ -2774,6 +2869,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-rustls" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -3303,6 +3408,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.11" diff --git a/Cargo.toml b/Cargo.toml index 67dafcf..d696700 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,9 @@ config = "0.15.14" markdown = "1.0.0" rand = { version = "0.9.2", features = ["std_rng"] } reqwest = { version = "0.12.23", default-features = false, features = [ - "json", "cookies", + "json", + "rustls-tls", ] } secrecy = { version = "0.10.3", features = ["serde"] } serde = { version = "1.0.219", features = ["derive"] } diff --git a/src/routes.rs b/src/routes.rs index e81d17c..78f0914 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -27,7 +27,7 @@ pub use unsubscribe::*; use crate::{ authentication::AuthError, - templates::{HtmlTemplate, InternalErrorTemplate, MessageTemplate, NotFoundTemplate}, + templates::{ErrorTemplate, HtmlTemplate, MessageTemplate}, }; pub fn generate_token() -> String { @@ -108,19 +108,16 @@ impl IntoResponse for AppError { full_page, } => { let html = if *full_page { - Html(InternalErrorTemplate.render().unwrap()) + Html(ErrorTemplate::InternalServer.render().unwrap()) } else { - let template = MessageTemplate::Error { - message: "An internal server error occured.".into(), - }; + let template = + MessageTemplate::error("An internal server error occured.".into()); Html(template.render().unwrap()) }; html.into_response() } AppError::FormError(error) => { - let template = MessageTemplate::Error { - message: error.to_string(), - }; + let template = MessageTemplate::error(error.to_string()); Html(template.render().unwrap()).into_response() } AppError::NotAuthenticated => { @@ -164,7 +161,7 @@ pub async fn not_found() -> Response { } pub fn not_found_html() -> Response { - let template = HtmlTemplate(NotFoundTemplate); + let template = HtmlTemplate(ErrorTemplate::NotFound); (StatusCode::NOT_FOUND, template).into_response() } diff --git a/src/routes/admin/change_password.rs b/src/routes/admin/change_password.rs index 70f623b..871beee 100644 --- a/src/routes/admin/change_password.rs +++ b/src/routes/admin/change_password.rs @@ -49,9 +49,7 @@ pub async fn change_password( authentication::change_password(user_id, form.new_password, &connection_pool) .await .map_err(AdminError::ChangePassword)?; - let template = MessageTemplate::Success { - message: "Your password has been changed.".to_string(), - }; + let template = MessageTemplate::success("Your password has been changed.".to_string()); Ok(Html(template.render().unwrap()).into_response()) } } diff --git a/src/routes/admin/newsletters.rs b/src/routes/admin/newsletters.rs index 8a7c608..137dec6 100644 --- a/src/routes/admin/newsletters.rs +++ b/src/routes/admin/newsletters.rs @@ -127,7 +127,7 @@ pub async fn publish_newsletter( .context("Failed to enqueue delivery tasks.")?; let message = String::from("Your email has been queued for delivery."); - let template = MessageTemplate::Success { message }; + let template = MessageTemplate::success(message); let response = Html(template.render().unwrap()).into_response(); let response = save_response(transaction, &idempotency_key, user_id, response) .await diff --git a/src/routes/admin/posts.rs b/src/routes/admin/posts.rs index 1c1193f..ac87f6a 100644 --- a/src/routes/admin/posts.rs +++ b/src/routes/admin/posts.rs @@ -73,9 +73,7 @@ pub async fn create_post( .await .context("Failed to enqueue delivery tasks.")?; - let template = MessageTemplate::Success { - message: "Your new post has been published!".into(), - }; + let template = MessageTemplate::success("Your new post has been published!".into()); let response = Html(template.render().unwrap()).into_response(); let response = save_response(transaction, &idempotency_key, user_id, response) .await @@ -138,9 +136,7 @@ pub async fn delete_post( "We could not find the post in the database." ))) } else { - let template = MessageTemplate::Success { - message: "The subscriber has been deleted.".into(), - }; + let template = MessageTemplate::success("The subscriber has been deleted.".into()); Ok(template.render().unwrap().into_response()) } } diff --git a/src/routes/admin/subscribers.rs b/src/routes/admin/subscribers.rs index 2db78cf..c8b6eac 100644 --- a/src/routes/admin/subscribers.rs +++ b/src/routes/admin/subscribers.rs @@ -63,12 +63,10 @@ pub async fn delete_subscriber( .map_err(AppError::unexpected_message)?; if let Some(record) = res { tracing::Span::current().record("email", tracing::field::display(&record.email)); - let template = MessageTemplate::Success { - message: format!( - "The subscriber with email '{}' has been deleted.", - record.email - ), - }; + let template = MessageTemplate::success(format!( + "The subscriber with email '{}' has been deleted.", + record.email + )); Ok(template.render().unwrap().into_response()) } else { Err(AppError::unexpected_message(anyhow::anyhow!( diff --git a/src/routes/subscriptions.rs b/src/routes/subscriptions.rs index 943a3f3..e376642 100644 --- a/src/routes/subscriptions.rs +++ b/src/routes/subscriptions.rs @@ -66,9 +66,8 @@ pub async fn subscribe( .context("Failed to commit the database transaction to store a new subscriber.")?; } - let template = MessageTemplate::Success { - message: "You'll receive a confirmation email shortly.".to_string(), - }; + let template = + MessageTemplate::success("You'll receive a confirmation email shortly.".to_string()); Ok(Html(template.render().unwrap()).into_response()) } diff --git a/src/routes/unsubscribe.rs b/src/routes/unsubscribe.rs index b33a99a..3dd06b8 100644 --- a/src/routes/unsubscribe.rs +++ b/src/routes/unsubscribe.rs @@ -1,11 +1,9 @@ use crate::{ domain::SubscriberEmail, email_client::EmailClient, - routes::AppError, + routes::{AppError, not_found_html}, startup::AppState, - templates::{ - MessageTemplate, NotFoundTemplate, UnsubscribeConfirmTemplate, UnsubscribeTemplate, - }, + templates::{MessageTemplate, UnsubscribeConfirmTemplate, UnsubscribeTemplate}, }; use anyhow::Context; use askama::Template; @@ -14,7 +12,6 @@ use axum::{ extract::{Query, State}, response::{Html, IntoResponse, Response}, }; -use reqwest::StatusCode; use sqlx::{Executor, PgPool}; #[derive(serde::Deserialize)] @@ -52,9 +49,9 @@ pub async fn post_unsubscribe( .await .context("Failed to send a confirmation email.")?; } - let template = MessageTemplate::Success { - message: "If you are a subscriber, you'll receive a confirmation link shortly.".into(), - }; + let template = MessageTemplate::success( + "If you are a subscriber, you'll receive a confirmation link shortly.".into(), + ); Ok(Html(template.render().unwrap()).into_response()) } @@ -124,11 +121,7 @@ pub async fn unsubscribe_confirm( if result.rows_affected() == 0 { tracing::info!("Unsubscribe token is not tied to any confirmed user"); - Ok(( - StatusCode::NOT_FOUND, - Html(NotFoundTemplate.render().unwrap()), - ) - .into_response()) + Ok(not_found_html()) } else { tracing::info!("User successfully removed"); Ok(Html(UnsubscribeConfirmTemplate.render().unwrap()).into_response()) diff --git a/src/templates.rs b/src/templates.rs index 2421dab..f4415d6 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -21,23 +21,33 @@ where } #[derive(Template)] -pub enum MessageTemplate { - #[template(path = "../templates/success.html")] - Success { message: String }, - #[template(path = "../templates/error.html")] - Error { message: String }, +#[template(path = "message.html")] +pub struct MessageTemplate { + pub message: String, + pub error: bool, } -#[derive(Template)] -#[template(path = "../templates/500.html")] -pub struct InternalErrorTemplate; +impl MessageTemplate { + pub fn success(message: String) -> Self { + Self { + message, + error: false, + } + } + pub fn error(message: String) -> Self { + Self { + message, + error: true, + } + } +} #[derive(Template)] #[template(path = "../templates/login.html")] pub struct LoginTemplate; #[derive(Template)] -#[template(path = "../templates/dashboard.html")] +#[template(path = "dashboard/dashboard.html")] pub struct DashboardTemplate { pub username: String, pub idempotency_key_1: String, @@ -53,27 +63,27 @@ pub struct DashboardTemplate { pub struct HomeTemplate; #[derive(Template)] -#[template(path = "posts.html")] +#[template(path = "posts/list.html")] pub struct PostsTemplate { pub posts: Vec, pub next_page: Option, } #[derive(Template)] -#[template(path = "posts.html", block = "posts")] +#[template(path = "posts/list.html", block = "posts")] pub struct PostListTemplate { pub posts: Vec, pub next_page: Option, } #[derive(Template)] -#[template(path = "post.html")] +#[template(path = "posts/page.html")] pub struct PostTemplate { pub post: PostEntry, } #[derive(Template)] -#[template(path = "dashboard.html", block = "subs")] +#[template(path = "dashboard/subscribers/list.html", block = "subs")] pub struct SubListTemplate { pub subscribers: Vec, pub current_page: i64, @@ -81,19 +91,23 @@ pub struct SubListTemplate { } #[derive(Template)] -#[template(path = "confirm.html")] +#[template(path = "subscribe/confirm.html")] pub struct ConfirmTemplate; #[derive(Template)] -#[template(path = "404.html")] -pub struct NotFoundTemplate; +pub enum ErrorTemplate { + #[template(path = "error/404.html")] + NotFound, + #[template(path = "error/500.html")] + InternalServer, +} #[derive(Template)] -#[template(path = "unsubscribe_confirm.html")] +#[template(path = "unsubscribe/confirm.html")] pub struct UnsubscribeConfirmTemplate; #[derive(Template)] -#[template(path = "unsubscribe.html")] +#[template(path = "unsubscribe/form.html")] pub struct UnsubscribeTemplate; #[derive(Template)] diff --git a/templates/dashboard.html b/templates/dashboard.html deleted file mode 100644 index fff1def..0000000 --- a/templates/dashboard.html +++ /dev/null @@ -1,322 +0,0 @@ -{% extends "base.html" %} -{% block title %}Dashboard{% endblock %} -{% block content %} -
-
-

Dashboard

-

- Connected as {{ username }} -

- -
-
-
-
-
- - - - - - -
-
-

Subscribers

-

{{ stats.subscribers }}

-
-
-
-
-
-
- - - -
-
-

Posts

-

{{ stats.posts }}

-
-
-
-
-
-
- - - -
-
-

Notifications

-

{{ stats.notifications_sent }}

-
-
-
-
-
-
- - - - -
-
-

Open rate

-

{{ stats.formatted_rate() }}

-
-
-
-
-
-
-
-
-

- - - - - - - Subscribers management -

-

View and manage your subscribers.

-
-
-
-
- {% block subs %} - {% if subscribers.is_empty() %} -
-
- - - -
-

No data available

-

Content may have shifted due to recent updates or list is empty.

-
- {% else %} - {% for subscriber in subscribers %} - {% include "sub_card_fragment.html" %} - {% endfor %} - {% endif %} -
- - Page: {{ current_page }} - -
- {% endblock %} -
-
-
-
-
-

- - - - Write a new post -

-

Publish a new post online. Subscribers will be notified.

-
-
-
- -
- - -
-
- - -
- -
-
-
-
-
-
-

- - - - Send an email -

-

Contact your subscribers directly.

-
-
-
- -
- - -
-
- - -
-
- - -
- -
-
-
-
-
-
-

- - - - Change your password -

-

Set a new password for your account.

-
-
-
-
- - -
-
- - -
-
- - -
- -
-
-
-
-
-
-{% endblock %} diff --git a/templates/dashboard/change_password.html b/templates/dashboard/change_password.html new file mode 100644 index 0000000..c011dfa --- /dev/null +++ b/templates/dashboard/change_password.html @@ -0,0 +1,59 @@ +
+
+

+ + + + Change your password +

+

Set a new password for your account.

+
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
diff --git a/templates/dashboard/dashboard.html b/templates/dashboard/dashboard.html new file mode 100644 index 0000000..86be1c0 --- /dev/null +++ b/templates/dashboard/dashboard.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} +{% block title %}Dashboard{% endblock %} +{% block content %} +
+
+

Dashboard

+

+ Connected as {{ username }} +

+ +
+ {% include "stats.html" %} + {% include "subscribers/list.html" %} +
+ {% include "publish.html" %} + {% include "send_email.html" %} + {% include "change_password.html" %} +
+
+{% endblock %} diff --git a/templates/dashboard/publish.html b/templates/dashboard/publish.html new file mode 100644 index 0000000..aa360ad --- /dev/null +++ b/templates/dashboard/publish.html @@ -0,0 +1,50 @@ +
+
+

+ + + + Write a new post +

+

Publish a new post online. Subscribers will be notified.

+
+
+
+ +
+ + +
+
+ + +
+ +
+
+
+
diff --git a/templates/dashboard/send_email.html b/templates/dashboard/send_email.html new file mode 100644 index 0000000..366e15a --- /dev/null +++ b/templates/dashboard/send_email.html @@ -0,0 +1,60 @@ +
+
+

+ + + + Send an email +

+

Contact your subscribers directly.

+
+
+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
diff --git a/templates/dashboard/stats.html b/templates/dashboard/stats.html new file mode 100644 index 0000000..46efa9c --- /dev/null +++ b/templates/dashboard/stats.html @@ -0,0 +1,73 @@ +
+
+
+
+ + + + + + +
+
+

Subscribers

+

{{ stats.subscribers }}

+
+
+
+
+
+
+ + + +
+
+

Posts

+

{{ stats.posts }}

+
+
+
+
+
+
+ + + +
+
+

Notifications

+

{{ stats.notifications_sent }}

+
+
+
+
+
+
+ + + + +
+
+

Open rate

+

{{ stats.formatted_rate() }}

+
+
+
+
diff --git a/templates/sub_card_fragment.html b/templates/dashboard/subscribers/card.html similarity index 100% rename from templates/sub_card_fragment.html rename to templates/dashboard/subscribers/card.html diff --git a/templates/dashboard/subscribers/list.html b/templates/dashboard/subscribers/list.html new file mode 100644 index 0000000..4bc008a --- /dev/null +++ b/templates/dashboard/subscribers/list.html @@ -0,0 +1,58 @@ +
+
+
+
+

+ + + + + + + Subscribers management +

+

View and manage your subscribers.

+
+
+
+
+ {% block subs %} + {% if subscribers.is_empty() %} +
+
+ + + +
+

No data available

+

Content may have shifted due to recent updates or list is empty.

+
+ {% else %} + {% for subscriber in subscribers %} + {% include "dashboard/subscribers/card.html" %} + {% endfor %} + {% endif %} +
+ + Page: {{ current_page }} + +
+ {% endblock %} +
+
diff --git a/templates/error.html b/templates/error.html deleted file mode 100644 index b4a50c6..0000000 --- a/templates/error.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
- - - - - {{ message }} -
-
diff --git a/templates/404.html b/templates/error/404.html similarity index 100% rename from templates/404.html rename to templates/error/404.html diff --git a/templates/500.html b/templates/error/500.html similarity index 100% rename from templates/500.html rename to templates/error/500.html diff --git a/templates/message.html b/templates/message.html new file mode 100644 index 0000000..52d10f8 --- /dev/null +++ b/templates/message.html @@ -0,0 +1,14 @@ +
+
+ + {% if self.error %} + + + {% else %} + + + {% endif %} + + {{ message }} +
+
diff --git a/templates/post_card_fragment.html b/templates/posts/card.html similarity index 100% rename from templates/post_card_fragment.html rename to templates/posts/card.html diff --git a/templates/posts.html b/templates/posts/list.html similarity index 97% rename from templates/posts.html rename to templates/posts/list.html index 606a62b..5cb0431 100644 --- a/templates/posts.html +++ b/templates/posts/list.html @@ -24,7 +24,7 @@
{% block posts %} {% for post in posts %} - {% include "post_card_fragment.html" %} + {% include "card.html" %} {% endfor %}
{% if let Some(n) = next_page %} diff --git a/templates/post.html b/templates/posts/page.html similarity index 100% rename from templates/post.html rename to templates/posts/page.html diff --git a/templates/confirm.html b/templates/subscribe/confirm.html similarity index 100% rename from templates/confirm.html rename to templates/subscribe/confirm.html diff --git a/templates/success.html b/templates/success.html deleted file mode 100644 index f2a7f83..0000000 --- a/templates/success.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
- - - - - {{ message }} -
-
diff --git a/templates/unsubscribe_confirm.html b/templates/unsubscribe/confirm.html similarity index 100% rename from templates/unsubscribe_confirm.html rename to templates/unsubscribe/confirm.html diff --git a/templates/unsubscribe.html b/templates/unsubscribe/form.html similarity index 100% rename from templates/unsubscribe.html rename to templates/unsubscribe/form.html