From 41bd39d4223981b248dc0e4486559a543a155979 Mon Sep 17 00:00:00 2001 From: glyph Date: Wed, 23 Mar 2022 11:41:21 +0200 Subject: [PATCH] add themes, add public and private msg publishing --- peach-web/src/routes/authentication/change.rs | 10 +- peach-web/src/routes/authentication/login.rs | 10 +- peach-web/src/routes/authentication/reset.rs | 10 +- peach-web/src/routes/guide.rs | 7 +- peach-web/src/routes/home.rs | 7 +- peach-web/src/routes/scuttlebutt/blocks.rs | 10 +- peach-web/src/routes/scuttlebutt/follows.rs | 10 +- peach-web/src/routes/scuttlebutt/friends.rs | 10 +- peach-web/src/routes/scuttlebutt/invites.rs | 7 +- peach-web/src/routes/scuttlebutt/mod.rs | 2 + peach-web/src/routes/scuttlebutt/peers.rs | 7 +- peach-web/src/routes/scuttlebutt/private.rs | 131 ++++++++++++++++++ peach-web/src/routes/scuttlebutt/profile.rs | 19 +-- .../src/routes/scuttlebutt/profile_update.rs | 6 +- peach-web/src/routes/scuttlebutt/publish.rs | 41 ++++++ peach-web/src/routes/scuttlebutt/search.rs | 7 +- .../src/routes/settings/admin/configure.rs | 10 +- peach-web/src/routes/settings/admin/menu.rs | 7 +- peach-web/src/routes/settings/menu.rs | 7 +- peach-web/src/routes/settings/mod.rs | 2 +- .../routes/settings/scuttlebutt/configure.rs | 9 +- .../src/routes/settings/scuttlebutt/menu.rs | 10 +- peach-web/src/routes/settings/theme.rs | 18 +-- peach-web/src/routes/status/scuttlebutt.rs | 11 +- peach-web/src/templates/base.rs | 4 +- peach-web/src/templates/mod.rs | 1 + peach-web/src/templates/nav.rs | 4 +- peach-web/src/templates/not_found.rs | 34 +++++ peach-web/src/templates/peers_list.rs | 7 +- peach-web/src/utils/sbot.rs | 53 +++++++ peach-web/src/utils/theme.rs | 109 --------------- 31 files changed, 410 insertions(+), 170 deletions(-) create mode 100644 peach-web/src/routes/scuttlebutt/private.rs create mode 100644 peach-web/src/routes/scuttlebutt/publish.rs create mode 100644 peach-web/src/templates/not_found.rs diff --git a/peach-web/src/routes/authentication/change.rs b/peach-web/src/routes/authentication/change.rs index c33abad..50e7b69 100644 --- a/peach-web/src/routes/authentication/change.rs +++ b/peach-web/src/routes/authentication/change.rs @@ -6,7 +6,10 @@ use rouille::{post_input, try_or_400, Request, Response}; use crate::{ error::PeachWebError, templates, - utils::flash::{FlashRequest, FlashResponse}, + utils::{ + flash::{FlashRequest, FlashResponse}, + theme, + }, }; // HELPER AND ROUTES FOR /auth/change (GET and POST) @@ -48,8 +51,11 @@ pub fn build_template(request: &Request) -> PreEscaped { let body = templates::nav::build_template(form_template, "Change Password", Some("/settings/admin")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } /// Verify, validate and set a new password, overwriting the current password. diff --git a/peach-web/src/routes/authentication/login.rs b/peach-web/src/routes/authentication/login.rs index aa643c9..0ad8b9d 100644 --- a/peach-web/src/routes/authentication/login.rs +++ b/peach-web/src/routes/authentication/login.rs @@ -5,7 +5,10 @@ use rouille::{post_input, try_or_400, Request, Response}; use crate::{ templates, - utils::flash::{FlashRequest, FlashResponse}, + utils::{ + flash::{FlashRequest, FlashResponse}, + theme, + }, }; // HELPER AND ROUTES FOR /auth/login (GET and POST) @@ -42,8 +45,11 @@ pub fn build_template(request: &Request) -> PreEscaped { // parameters are template, title and back url let body = templates::nav::build_template(form_template, "Login", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } /// Parse and verify the submitted password. If verification succeeds, set the diff --git a/peach-web/src/routes/authentication/reset.rs b/peach-web/src/routes/authentication/reset.rs index 6d19afd..3464ae0 100644 --- a/peach-web/src/routes/authentication/reset.rs +++ b/peach-web/src/routes/authentication/reset.rs @@ -6,7 +6,10 @@ use rouille::{post_input, try_or_400, Request, Response}; use crate::{ error::PeachWebError, templates, - utils::flash::{FlashRequest, FlashResponse}, + utils::{ + flash::{FlashRequest, FlashResponse}, + theme, + }, }; // HELPER AND ROUTES FOR /auth/reset (GET and POST) @@ -48,8 +51,11 @@ pub fn build_template(request: &Request) -> PreEscaped { let body = templates::nav::build_template(form_template, "Reset Password", Some("/settings/admin")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } /// Verify, validate and set a new password, overwriting the current password. diff --git a/peach-web/src/routes/guide.rs b/peach-web/src/routes/guide.rs index 2898d0f..5babd7c 100644 --- a/peach-web/src/routes/guide.rs +++ b/peach-web/src/routes/guide.rs @@ -1,6 +1,6 @@ use maud::{html, PreEscaped}; -use crate::templates; +use crate::{templates, utils::theme}; /// Guide template builder. pub fn build_template() -> PreEscaped { @@ -98,6 +98,9 @@ pub fn build_template() -> PreEscaped { // title is "" and back button link is `None` because this is the homepage let body = templates::nav::build_template(guide_template, "Guide", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/home.rs b/peach-web/src/routes/home.rs index eaaf060..4b085be 100644 --- a/peach-web/src/routes/home.rs +++ b/peach-web/src/routes/home.rs @@ -1,7 +1,7 @@ use maud::{html, PreEscaped}; use peach_lib::sbot::SbotStatus; -use crate::templates; +use crate::{templates, utils::theme}; /// Read the state of the go-sbot process and define status-related /// elements accordingly. @@ -97,6 +97,9 @@ pub fn build_template() -> PreEscaped { // title is "" and back button link is `None` because this is the homepage let body = templates::nav::build_template(home_template, "", None); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/scuttlebutt/blocks.rs b/peach-web/src/routes/scuttlebutt/blocks.rs index f22fbb4..c7cd069 100644 --- a/peach-web/src/routes/scuttlebutt/blocks.rs +++ b/peach-web/src/routes/scuttlebutt/blocks.rs @@ -1,6 +1,9 @@ use maud::PreEscaped; -use crate::{templates, utils::sbot}; +use crate::{ + templates, + utils::{sbot, theme}, +}; // ROUTE: /scuttlebutt/blocks @@ -16,8 +19,11 @@ pub fn build_template() -> PreEscaped { // wrap the nav bars around the error template content let body = templates::nav::build_template(error_template, "Blocks", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } } } diff --git a/peach-web/src/routes/scuttlebutt/follows.rs b/peach-web/src/routes/scuttlebutt/follows.rs index 258d85b..517e1c3 100644 --- a/peach-web/src/routes/scuttlebutt/follows.rs +++ b/peach-web/src/routes/scuttlebutt/follows.rs @@ -1,6 +1,9 @@ use maud::PreEscaped; -use crate::{templates, utils::sbot}; +use crate::{ + templates, + utils::{sbot, theme}, +}; // ROUTE: /scuttlebutt/follows @@ -16,8 +19,11 @@ pub fn build_template() -> PreEscaped { // wrap the nav bars around the error template content let body = templates::nav::build_template(error_template, "Follows", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } } } diff --git a/peach-web/src/routes/scuttlebutt/friends.rs b/peach-web/src/routes/scuttlebutt/friends.rs index 0279c62..761d661 100644 --- a/peach-web/src/routes/scuttlebutt/friends.rs +++ b/peach-web/src/routes/scuttlebutt/friends.rs @@ -1,6 +1,9 @@ use maud::PreEscaped; -use crate::{templates, utils::sbot}; +use crate::{ + templates, + utils::{sbot, theme}, +}; // ROUTE: /scuttlebutt/friends @@ -16,8 +19,11 @@ pub fn build_template() -> PreEscaped { // wrap the nav bars around the error template content let body = templates::nav::build_template(error_template, "Friends", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } } } diff --git a/peach-web/src/routes/scuttlebutt/invites.rs b/peach-web/src/routes/scuttlebutt/invites.rs index b5372c8..f2cc5d1 100644 --- a/peach-web/src/routes/scuttlebutt/invites.rs +++ b/peach-web/src/routes/scuttlebutt/invites.rs @@ -6,7 +6,7 @@ use crate::{ templates, utils::{ flash::{FlashRequest, FlashResponse}, - sbot, + sbot, theme, }, }; @@ -73,7 +73,10 @@ pub fn build_template(request: &Request) -> PreEscaped { let body = templates::nav::build_template(invite_form_template, "Invites", Some("/scuttlebutt/peers")); - templates::base::build_template(body) + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + + templates::base::build_template(body, theme) } /// Parse the invite uses data and attempt to generate an invite code. diff --git a/peach-web/src/routes/scuttlebutt/mod.rs b/peach-web/src/routes/scuttlebutt/mod.rs index 9b221a2..6f77fd3 100644 --- a/peach-web/src/routes/scuttlebutt/mod.rs +++ b/peach-web/src/routes/scuttlebutt/mod.rs @@ -3,6 +3,8 @@ pub mod follows; pub mod friends; pub mod invites; pub mod peers; +pub mod private; pub mod profile; pub mod profile_update; +pub mod publish; pub mod search; diff --git a/peach-web/src/routes/scuttlebutt/peers.rs b/peach-web/src/routes/scuttlebutt/peers.rs index 9c004db..39bb64a 100644 --- a/peach-web/src/routes/scuttlebutt/peers.rs +++ b/peach-web/src/routes/scuttlebutt/peers.rs @@ -1,7 +1,7 @@ use maud::{html, PreEscaped}; use peach_lib::sbot::SbotStatus; -use crate::templates; +use crate::{templates, utils::theme}; /// Scuttlebutt peer menu template builder. /// @@ -37,6 +37,9 @@ pub fn build_template() -> PreEscaped { // parameters are template, title and back url let body = templates::nav::build_template(menu_template, "Scuttlebutt Peers", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/scuttlebutt/private.rs b/peach-web/src/routes/scuttlebutt/private.rs new file mode 100644 index 0000000..737bbe8 --- /dev/null +++ b/peach-web/src/routes/scuttlebutt/private.rs @@ -0,0 +1,131 @@ +use maud::{html, Markup, PreEscaped}; +use peach_lib::sbot::SbotStatus; +use rouille::{post_input, try_or_400, Request, Response}; + +use crate::{ + templates, + utils::{ + flash::{FlashRequest, FlashResponse}, + sbot, theme, + }, +}; + +// ROUTE: /scuttlebutt/private + +fn public_key_input_template(ssb_id: &Option) -> Markup { + match ssb_id { + Some(id) => { + html! { input type="text" id="publicKey" name="recipient" placeholder="@xYz...=.ed25519" value=(id); } + } + // render the input with autofocus if no ssb_id has been provided + None => { + html! { input type="text" id="publicKey" name="recipient" placeholder="@xYz...=.ed25519" autofocus; } + } + } +} + +fn private_message_textarea_template(ssb_id: &Option) -> Markup { + match ssb_id { + Some(_) => { + html! { textarea id="privatePost" class="center input message-input" name="text" title="Compose a private message" placeholder="Write a private message..." autofocus { "" } } + } + // render the textarea with autofocus if an ssb_id has been provided + None => { + html! { textarea id="privatePost" class="center input message-input" name="text" title="Compose a private message" placeholder="Write a private message..." { "" } } + } + } +} + +/// Scuttlebutt private message template builder. +/// +/// Render a form for publishing a provate message. The recipient input field +/// is populated with the provided ssb_id. If no recipient is provided, the +/// template autofocuses on the recipient input field. +pub fn build_template(request: &Request, ssb_id: Option) -> PreEscaped { + // check for flash cookies; will be (None, None) if no flash cookies are found + let (flash_name, flash_msg) = request.retrieve_flash(); + + let profile_template = match SbotStatus::read() { + // only render the private message elements if the sbot is active + Ok(status) if status.state == Some("active".to_string()) => { + // retrieve the local public key (set to blank if an error is returned) + let local_id = match sbot::get_local_id() { + Ok(id) => id, + Err(_) => "".to_string(), + }; + + html! { + (PreEscaped("")) + div class="card card-wide center" { + form id="sbotConfig" class="center" action="/scuttlebutt/private" method="post" { + div class="center" style="display: flex; flex-direction: column; margin-bottom: 1rem;" title="Public key (ID) of the peer being written to" { + label for="publicKey" class="label-small font-gray" { + "PUBLIC KEY" + } + (public_key_input_template(&ssb_id)) + } + (PreEscaped("")) + (private_message_textarea_template(&ssb_id)) + (PreEscaped("")) + input type="hidden" id="localId" name="id" value=(local_id); + (PreEscaped("")) + input id="publish" class="button button-primary center" type="submit" style="margin-top: 1rem;" title="Publish private message to peer" value="Publish"; + } + // render flash message if cookies were found in the request + @if let (Some(name), Some(msg)) = (flash_name, flash_msg) { + (PreEscaped("")) + (templates::flash::build_template(name, msg)) + } + } + } + } + _ => templates::inactive::build_template("Private messaging is unavailable."), + }; + + let body = templates::nav::build_template(profile_template, "Profile", Some("/")); + + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + + templates::base::build_template(body, theme) +} + +/// Publish a private message. +/// +/// Parse the public key and private message text from the submitted form +/// and publish the message. Set a flash message communicating the outcome +/// of the publishing attempt and redirect to the private message page. +pub fn handle_form(request: &Request) -> Response { + // query the request body for form data + // return a 400 error if the admin_id field is missing + let data = try_or_400!(post_input!(request, { + id: String, + text: String, + recipient: String + })); + + // now we need to add the local id to the recipients vector, + // otherwise the local id will not be able to read the message. + let recipients = vec![data.id, data.recipient]; + + let (flash_name, flash_msg) = match SbotStatus::read() { + Ok(status) if status.state == Some("active".to_string()) => { + match sbot::publish_private_msg(data.text, recipients) { + Ok(success_msg) => ( + "flash_name=success".to_string(), + format!("flash_msg={}", success_msg), + ), + Err(error_msg) => ( + "flash_name=error".to_string(), + format!("flash_msg={}", error_msg), + ), + } + } + _ => ( + "flash_name=warning".to_string(), + "Private messaging is unavailable.".to_string(), + ), + }; + + Response::redirect_303("/scuttlebutt/private").add_flash(flash_name, flash_msg) +} diff --git a/peach-web/src/routes/scuttlebutt/profile.rs b/peach-web/src/routes/scuttlebutt/profile.rs index 2fd11e9..2d2f048 100644 --- a/peach-web/src/routes/scuttlebutt/profile.rs +++ b/peach-web/src/routes/scuttlebutt/profile.rs @@ -4,7 +4,7 @@ use rouille::Request; use crate::{ templates, - utils::{flash::FlashRequest, sbot, sbot::Profile}, + utils::{flash::FlashRequest, sbot, sbot::Profile, theme}, }; // ROUTE: /scuttlebutt/profile @@ -112,7 +112,7 @@ fn social_interaction_buttons_template(profile: &Profile) -> Markup { } @if let Some(ssb_id) = &profile.id { form class="center" { - a id="privateMessage" class="button button-primary center" href={ "/scuttlebutt/private?public_key=" (ssb_id) } title="Private Message" { + a id="privateMessage" class="button button-primary center" href={ "/scuttlebutt/private/" (ssb_id) } title="Private Message" { "Send Private Message" } } @@ -152,11 +152,11 @@ pub fn build_template(request: &Request, ssb_id: Option) -> PreEscaped")) - (templates::flash::build_template(name, msg)) + // render flash message if cookies were found in the request + @if let (Some(name), Some(msg)) = (flash_name, flash_msg) { + (PreEscaped("")) + (templates::flash::build_template(name, msg)) + } } } } @@ -171,5 +171,8 @@ pub fn build_template(request: &Request, ssb_id: Option) -> PreEscaped PreEscaped { Some("/scuttlebutt/profile"), ); - templates::base::build_template(body) + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + + templates::base::build_template(body, theme) } /// Update the name, description and picture for the local Scuttlebutt profile. diff --git a/peach-web/src/routes/scuttlebutt/publish.rs b/peach-web/src/routes/scuttlebutt/publish.rs new file mode 100644 index 0000000..3d1b0a9 --- /dev/null +++ b/peach-web/src/routes/scuttlebutt/publish.rs @@ -0,0 +1,41 @@ +use peach_lib::sbot::SbotStatus; +use rouille::{post_input, try_or_400, Request, Response}; + +use crate::utils::{flash::FlashResponse, sbot}; + +// ROUTE: /scuttlebutt/publish + +/// Publish a public Scuttlebutt post. +/// +/// Parse the post text from the submitted form and publish the message. +/// Redirect to the profile page of the PeachCloud local identity with a flash +/// message describing the outcome of the action (may be successful or +/// unsuccessful). +pub fn handle_form(request: &Request) -> Response { + // query the request body for form data + // return a 400 error if the admin_id field is missing + let data = try_or_400!(post_input!(request, { + text: String, + })); + + let (flash_name, flash_msg) = match SbotStatus::read() { + Ok(status) if status.state == Some("active".to_string()) => { + match sbot::publish_public_post(data.text) { + Ok(success_msg) => ( + "flash_name=success".to_string(), + format!("flash_msg={}", success_msg), + ), + Err(error_msg) => ( + "flash_name=error".to_string(), + format!("flash_msg={}", error_msg), + ), + } + } + _ => ( + "flash_name=warning".to_string(), + "Public posting is unavailable.".to_string(), + ), + }; + + Response::redirect_303("/scuttlebutt/profile").add_flash(flash_name, flash_msg) +} diff --git a/peach-web/src/routes/scuttlebutt/search.rs b/peach-web/src/routes/scuttlebutt/search.rs index b8055c0..eb71acb 100644 --- a/peach-web/src/routes/scuttlebutt/search.rs +++ b/peach-web/src/routes/scuttlebutt/search.rs @@ -5,7 +5,7 @@ use crate::{ templates, utils::{ flash::{FlashRequest, FlashResponse}, - sbot, + sbot, theme, }, }; @@ -38,7 +38,10 @@ pub fn build_template(request: &Request) -> PreEscaped { let body = templates::nav::build_template(search_template, "Search", Some("/scuttlebutt/peers")); - templates::base::build_template(body) + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + + templates::base::build_template(body, theme) } /// Parse the public key, verify that it's valid and then redirect to the diff --git a/peach-web/src/routes/settings/admin/configure.rs b/peach-web/src/routes/settings/admin/configure.rs index f984d36..fdb8621 100644 --- a/peach-web/src/routes/settings/admin/configure.rs +++ b/peach-web/src/routes/settings/admin/configure.rs @@ -2,7 +2,10 @@ use maud::{html, PreEscaped}; use peach_lib::config_manager; use rouille::Request; -use crate::{templates, utils::flash::FlashRequest}; +use crate::{ + templates, + utils::{flash::FlashRequest, theme}, +}; /// Administrator settings menu template builder. pub fn build_template(request: &Request) -> PreEscaped { @@ -68,6 +71,9 @@ pub fn build_template(request: &Request) -> PreEscaped { Some("/settings/admin"), ); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/settings/admin/menu.rs b/peach-web/src/routes/settings/admin/menu.rs index 036fea0..49470d5 100644 --- a/peach-web/src/routes/settings/admin/menu.rs +++ b/peach-web/src/routes/settings/admin/menu.rs @@ -1,6 +1,6 @@ use maud::{html, PreEscaped}; -use crate::templates; +use crate::{templates, utils::theme}; /// Administrator settings menu template builder. pub fn build_template() -> PreEscaped { @@ -22,6 +22,9 @@ pub fn build_template() -> PreEscaped { let body = templates::nav::build_template(menu_template, "Administrator Settings", Some("/settings")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/settings/menu.rs b/peach-web/src/routes/settings/menu.rs index dddfd94..c49218d 100644 --- a/peach-web/src/routes/settings/menu.rs +++ b/peach-web/src/routes/settings/menu.rs @@ -1,6 +1,6 @@ use maud::{html, PreEscaped}; -use crate::{templates, CONFIG}; +use crate::{templates, utils::theme, CONFIG}; // ROUTE: /settings @@ -25,6 +25,9 @@ pub fn build_template() -> PreEscaped { // parameters are template, title and back url let body = templates::nav::build_template(menu_template, "Settings", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/settings/mod.rs b/peach-web/src/routes/settings/mod.rs index 2088ee3..d910549 100644 --- a/peach-web/src/routes/settings/mod.rs +++ b/peach-web/src/routes/settings/mod.rs @@ -3,4 +3,4 @@ pub mod admin; pub mod menu; //pub mod network; pub mod scuttlebutt; -//pub mod theme; +pub mod theme; diff --git a/peach-web/src/routes/settings/scuttlebutt/configure.rs b/peach-web/src/routes/settings/scuttlebutt/configure.rs index bc24403..d546a73 100644 --- a/peach-web/src/routes/settings/scuttlebutt/configure.rs +++ b/peach-web/src/routes/settings/scuttlebutt/configure.rs @@ -7,7 +7,7 @@ use crate::{ templates, utils::{ flash::{FlashRequest, FlashResponse}, - sbot, + sbot, theme, }, }; @@ -38,7 +38,7 @@ fn read_status_and_config() -> (String, SbotConfig, String, String) { Some(index) => { let (ip, port) = sbot_config.lis.split_at(index); // remove the : from the port - (ip.to_string(), port.replace(':', "").to_string()) + (ip.to_string(), port.replace(':', "")) } // if no ':' separator is found, assume an ip has been configured (without port) None => (sbot_config.lis.to_string(), String::new()), @@ -178,8 +178,11 @@ pub fn build_template(request: &Request) -> PreEscaped { let body = templates::nav::build_template(menu_template, "Scuttlebutt Settings", Some("/settings")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } /// Parse the sbot configuration values and write to file. diff --git a/peach-web/src/routes/settings/scuttlebutt/menu.rs b/peach-web/src/routes/settings/scuttlebutt/menu.rs index fd6d989..66997fd 100644 --- a/peach-web/src/routes/settings/scuttlebutt/menu.rs +++ b/peach-web/src/routes/settings/scuttlebutt/menu.rs @@ -2,7 +2,10 @@ use maud::{html, PreEscaped}; use peach_lib::sbot::SbotStatus; use rouille::Request; -use crate::{templates, utils::flash::FlashRequest}; +use crate::{ + templates, + utils::{flash::FlashRequest, theme}, +}; /// Read the status of the go-sbot service and render buttons accordingly. fn render_process_buttons() -> PreEscaped { @@ -55,6 +58,9 @@ pub fn build_template(request: &Request) -> PreEscaped { let body = templates::nav::build_template(menu_template, "Scuttlebutt Settings", Some("/settings")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/routes/settings/theme.rs b/peach-web/src/routes/settings/theme.rs index 3b28e2a..438b463 100644 --- a/peach-web/src/routes/settings/theme.rs +++ b/peach-web/src/routes/settings/theme.rs @@ -1,16 +1,16 @@ -use rocket::{get, response::Redirect}; +use rouille::Response; -use crate::routes::authentication::Authenticated; -use crate::{utils, utils::Theme}; +use crate::utils::{theme, theme::Theme}; + +// ROUTE: /settings/theme/{theme} /// Set the user-interface theme according to the query parameter value. -#[get("/theme?")] -pub fn set_theme(_auth: Authenticated, theme: &str) -> Redirect { - match theme { - "light" => utils::set_theme(Theme::Light), - "dark" => utils::set_theme(Theme::Dark), +pub fn set_theme(theme: String) -> Response { + match theme.as_str() { + "light" => theme::set_theme(Theme::Light), + "dark" => theme::set_theme(Theme::Dark), _ => (), } - Redirect::to("/") + Response::redirect_303("/") } diff --git a/peach-web/src/routes/status/scuttlebutt.rs b/peach-web/src/routes/status/scuttlebutt.rs index 101c88d..083703f 100644 --- a/peach-web/src/routes/status/scuttlebutt.rs +++ b/peach-web/src/routes/status/scuttlebutt.rs @@ -1,8 +1,10 @@ use maud::{html, Markup, PreEscaped}; use peach_lib::sbot::{SbotConfig, SbotStatus}; -use crate::templates; -use crate::utils::sbot; +use crate::{ + templates, + utils::{sbot, theme}, +}; // HTML RENDERING FOR ELEMENTS @@ -274,6 +276,9 @@ pub fn build_template() -> PreEscaped { // parameters are template, title and back url let body = templates::nav::build_template(status_template, "Settings", Some("/")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/templates/base.rs b/peach-web/src/templates/base.rs index 20019a0..db8304e 100644 --- a/peach-web/src/templates/base.rs +++ b/peach-web/src/templates/base.rs @@ -3,10 +3,10 @@ use maud::{html, PreEscaped, DOCTYPE}; /// Base template builder. /// /// Takes an HTML body as input and splices it into the base template. -pub fn build_template(body: PreEscaped) -> PreEscaped { +pub fn build_template(body: PreEscaped, theme: String) -> PreEscaped { html! { (DOCTYPE) - html lang="en" data-theme="light"; + html lang="en" data-theme=(theme); head { meta charset="utf-8"; meta name="description" content="PeachCloud web interface"; diff --git a/peach-web/src/templates/mod.rs b/peach-web/src/templates/mod.rs index 8711a46..77c1d32 100644 --- a/peach-web/src/templates/mod.rs +++ b/peach-web/src/templates/mod.rs @@ -3,4 +3,5 @@ pub mod error; pub mod flash; pub mod inactive; pub mod nav; +pub mod not_found; pub mod peers_list; diff --git a/peach-web/src/templates/nav.rs b/peach-web/src/templates/nav.rs index 98136c4..6650eff 100644 --- a/peach-web/src/templates/nav.rs +++ b/peach-web/src/templates/nav.rs @@ -19,7 +19,7 @@ pub fn build_template( "dark" => ( "/icons/hermies_hex_light.svg", html! { - a class="nav-item" href="/theme?theme=light" { + a class="nav-item" href="/settings/theme/light" { img class="icon-medium nav-icon-right icon-active" title="Toggle theme" src="/icons/sun.png" alt="Sun"; } }, @@ -28,7 +28,7 @@ pub fn build_template( _ => ( "/icons/hermies_hex.svg", html! { - a class="nav-item" href="/theme?theme=dark" { + a class="nav-item" href="/settings/theme/dark" { img class="icon-medium nav-icon-right icon-active" title="Toggle theme" src="/icons/moon.png" alt="Moon"; } }, diff --git a/peach-web/src/templates/not_found.rs b/peach-web/src/templates/not_found.rs new file mode 100644 index 0000000..3526a94 --- /dev/null +++ b/peach-web/src/templates/not_found.rs @@ -0,0 +1,34 @@ +use maud::{html, PreEscaped}; + +use crate::{templates, utils::theme}; + +// 404 ROUTE NOT FOUND CATCHER + +/// 404 template builder. +pub fn build_template() -> PreEscaped { + let not_found_template = html! { + div class="card center" { + div class="capsule-container" { + div class="capsule info-border" { + p { + "No PeachCloud resource exists for this URL. Please ensure that the URL in the address bar is correct." + } + p { + "Click the back arrow in the top-left or the PeachCloud logo at the bottom of your screen to return Home." + } + } + } + } + }; + + // wrap the nav bars around the settings menu template content + // parameters are template, title and back url + let body = + templates::nav::build_template(not_found_template, "404: Route Not Found", Some("/")); + + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + + // render the base template with the provided body + templates::base::build_template(body, theme) +} diff --git a/peach-web/src/templates/peers_list.rs b/peach-web/src/templates/peers_list.rs index c9fea13..01e40d2 100644 --- a/peach-web/src/templates/peers_list.rs +++ b/peach-web/src/templates/peers_list.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use maud::{html, Markup, PreEscaped}; use peach_lib::sbot::SbotStatus; -use crate::templates; +use crate::{templates, utils::theme}; /// Render an unordered list of peers with one list element for each peer. fn peers_template(peers: Vec>) -> Markup { @@ -71,6 +71,9 @@ pub fn build_template(peers: Vec>, title: &str) -> PreEs let body = templates::nav::build_template(peer_list_template, title, Some("/scuttlebutt/peers")); + // query the current theme so we can pass it into the base template builder + let theme = theme::get_theme(); + // render the base template with the provided body - templates::base::build_template(body) + templates::base::build_template(body, theme) } diff --git a/peach-web/src/utils/sbot.rs b/peach-web/src/utils/sbot.rs index 0390ff7..0852662 100644 --- a/peach-web/src/utils/sbot.rs +++ b/peach-web/src/utils/sbot.rs @@ -497,6 +497,59 @@ pub fn get_friends_list() -> Result>, Box }) } +/// Retrieve the local public key (id). +pub fn get_local_id() -> Result> { + // retrieve latest go-sbot configuration parameters + let sbot_config = SbotConfig::read().ok(); + + task::block_on(async { + let mut sbot_client = init_sbot_with_config(&sbot_config).await?; + + let local_id = sbot_client.whoami().await?; + + Ok(local_id) + }) +} + +/// Publish a public post. +pub fn publish_public_post(text: String) -> Result { + // retrieve latest go-sbot configuration parameters + let sbot_config = SbotConfig::read().ok(); + + task::block_on(async { + let mut sbot_client = init_sbot_with_config(&sbot_config) + .await + .map_err(|e| e.to_string())?; + + // TODO: debug!("Publishing new Scuttlebutt public post"); + match sbot_client.publish_post(&text).await { + Ok(_) => Ok("Published post".to_string()), + Err(e) => Err(format!("Failed to publish post: {}", e)), + } + }) +} + +/// Publish a private message. +pub fn publish_private_msg(text: String, recipients: Vec) -> Result { + // retrieve latest go-sbot configuration parameters + let sbot_config = SbotConfig::read().ok(); + + task::block_on(async { + let mut sbot_client = init_sbot_with_config(&sbot_config) + .await + .map_err(|e| e.to_string())?; + + // TODO: debug!("Publishing a new Scuttlebutt private message"); + match sbot_client + .publish_private(text.to_string(), recipients) + .await + { + Ok(_) => Ok("Published private message".to_string()), + Err(e) => Err(format!("Failed to publish private message: {}", e)), + } + }) +} + // FILEPATH FUNCTIONS /// Return the path of the ssb-go directory. diff --git a/peach-web/src/utils/theme.rs b/peach-web/src/utils/theme.rs index 9f99492..e65fe2f 100644 --- a/peach-web/src/utils/theme.rs +++ b/peach-web/src/utils/theme.rs @@ -23,112 +23,3 @@ pub fn set_theme(theme: Theme) { let mut writable_theme = THEME.write().unwrap(); *writable_theme = theme; } - -// get_cookie - -// set_cookie - -/* -pub mod monitor; - -use std::io::prelude::*; -use std::{fs, fs::File, path::Path}; - -use dirs; -use golgi::blobs; -use log::info; -use peach_lib::sbot::SbotConfig; -use rocket::{ - fs::TempFile, - response::{Redirect, Responder}, - serde::Serialize, -}; -use rocket_dyn_templates::Template; -use temporary::Directory; - -use crate::{error::PeachWebError, THEME}; - -// FILEPATH FUNCTIONS - -// return the path of the ssb-go directory -pub fn get_go_ssb_path() -> Result { - let go_ssb_path = match SbotConfig::read() { - Ok(conf) => conf.repo, - // return the default path if unable to read `config.toml` - Err(_) => { - // determine the home directory - let mut home_path = dirs::home_dir().ok_or_else(|| PeachWebError::HomeDir)?; - // add the go-ssb subdirectory - home_path.push(".ssb-go"); - // convert the PathBuf to a String - home_path - .into_os_string() - .into_string() - .map_err(|_| PeachWebError::OsString)? - } - }; - - Ok(go_ssb_path) -} - -// check whether a blob is in the blobstore -pub async fn blob_is_stored_locally(blob_path: &str) -> Result { - let go_ssb_path = get_go_ssb_path()?; - let complete_path = format!("{}/blobs/sha256/{}", go_ssb_path, blob_path); - let blob_exists_locally = Path::new(&complete_path).exists(); - - Ok(blob_exists_locally) -} - -// take the path to a file, add it to the blobstore and return the blob id -pub async fn write_blob_to_store(file: &mut TempFile<'_>) -> Result { - // create temporary directory and path - let temp_dir = Directory::new("blob")?; - // we performed a `file.name().is_some()` check before calling `write_blob_to_store` - // so it should be safe to do a simple unwrap here - let filename = file.name().expect("retrieving filename from uploaded file"); - let temp_path = temp_dir.join(filename); - - // write file to temporary path - file.persist_to(&temp_path).await?; - - // open the file and read it into a buffer - let mut file = File::open(&temp_path)?; - let mut buffer = Vec::new(); - file.read_to_end(&mut buffer)?; - - // hash the bytes representing the file - let (hex_hash, blob_id) = blobs::hash_blob(&buffer)?; - - // define the blobstore path and blob filename - let (blob_dir, blob_filename) = hex_hash.split_at(2); - let go_ssb_path = get_go_ssb_path()?; - let blobstore_sub_dir = format!("{}/blobs/sha256/{}", go_ssb_path, blob_dir); - - // create the blobstore sub-directory - fs::create_dir_all(&blobstore_sub_dir)?; - - // copy the file to the blobstore - let blob_path = format!("{}/{}", blobstore_sub_dir, blob_filename); - fs::copy(temp_path, blob_path)?; - - Ok(blob_id) -} - -// HELPER FUNCTIONS - -#[derive(Debug, Serialize)] -pub struct FlashContext { - pub flash_name: Option, - pub flash_msg: Option, -} - -/// A helper enum which allows routes to either return a Template or a Redirect -/// from: https://github.com/SergioBenitez/Rocket/issues/253#issuecomment-532356066 -#[allow(clippy::large_enum_variant)] -#[derive(Debug, Responder)] -pub enum TemplateOrRedirect { - Template(Template), - Redirect(Redirect), -} -*/