add theme setter and getter, update route handlers

This commit is contained in:
glyph 2022-02-03 16:29:20 +02:00
parent 435e819648
commit 0737c435a8
15 changed files with 193 additions and 17 deletions

View File

@ -36,6 +36,7 @@ maintenance = { status = "actively-developed" }
[dependencies] [dependencies]
env_logger = "0.8" env_logger = "0.8"
lazy_static = "1.4.0"
log = "0.4" log = "0.4"
nest = "1.0.0" nest = "1.0.0"
peach-lib = { path = "../peach-lib" } peach-lib = { path = "../peach-lib" }

View File

@ -32,11 +32,14 @@ pub mod routes;
mod tests; mod tests;
pub mod utils; pub mod utils;
use std::process; use std::{process, sync::RwLock};
use lazy_static::lazy_static;
use log::{debug, error, info}; use log::{debug, error, info};
use rocket::{fairing::AdHoc, serde::Deserialize, Build, Rocket}; use rocket::{fairing::AdHoc, serde::Deserialize, Build, Rocket};
use utils::Theme;
pub type BoxError = Box<dyn std::error::Error>; pub type BoxError = Box<dyn std::error::Error>;
/// Application configuration parameters. /// Application configuration parameters.
@ -51,6 +54,10 @@ pub struct RocketConfig {
standalone_mode: bool, standalone_mode: bool,
} }
lazy_static! {
static ref THEME: RwLock<Theme> = RwLock::new(Theme::Light);
}
static WLAN_IFACE: &str = "wlan0"; static WLAN_IFACE: &str = "wlan0";
static AP_IFACE: &str = "ap0"; static AP_IFACE: &str = "ap0";

View File

@ -6,7 +6,7 @@ use crate::routes::{
catchers::*, catchers::*,
index::*, index::*,
scuttlebutt::*, scuttlebutt::*,
settings::{admin::*, dns::*, menu::*, network::*, scuttlebutt::*}, settings::{admin::*, dns::*, menu::*, network::*, scuttlebutt::*, theme::*},
status::{device::*, network::*, scuttlebutt::*}, status::{device::*, network::*, scuttlebutt::*},
}; };
@ -28,6 +28,7 @@ pub fn mount_peachpub_routes(rocket: Rocket<Build>) -> Rocket<Build> {
shutdown_cmd, shutdown_cmd,
power_menu, power_menu,
settings_menu, settings_menu,
set_theme,
], ],
) )
.mount( .mount(

View File

@ -13,8 +13,8 @@ use rocket_dyn_templates::{tera::Context, Template};
use peach_lib::{error::PeachError, password_utils}; use peach_lib::{error::PeachError, password_utils};
use crate::error::PeachWebError; use crate::error::PeachWebError;
use crate::utils;
use crate::utils::TemplateOrRedirect; use crate::utils::TemplateOrRedirect;
//use crate::DisableAuth;
use crate::RocketConfig; use crate::RocketConfig;
// HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES // HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES
@ -72,7 +72,11 @@ impl<'r> FromRequest<'r> for Authenticated {
#[get("/login")] #[get("/login")]
pub fn login(flash: Option<FlashMessage>) -> Template { pub fn login(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string())); context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Login".to_string())); context.insert("title", &Some("Login".to_string()));
@ -166,7 +170,11 @@ pub fn save_reset_password_form(password_form: ResetPasswordForm) -> Result<(),
/// and is specifically for users who have forgotten their password. /// and is specifically for users who have forgotten their password.
#[get("/reset_password")] #[get("/reset_password")]
pub fn reset_password(flash: Option<FlashMessage>) -> Template { pub fn reset_password(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string())); context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Reset Password".to_string())); context.insert("title", &Some("Reset Password".to_string()));
@ -211,7 +219,11 @@ pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Temp
/// to initiate the sending of a new password reset. /// to initiate the sending of a new password reset.
#[get("/forgot_password")] #[get("/forgot_password")]
pub fn forgot_password_page(flash: Option<FlashMessage>) -> Template { pub fn forgot_password_page(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string())); context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Send Password Reset".to_string())); context.insert("title", &Some("Send Password Reset".to_string()));
@ -281,7 +293,11 @@ pub fn save_password_form(password_form: PasswordForm) -> Result<(), PeachWebErr
/// Change password request handler. This is used by a user who is already logged in. /// Change password request handler. This is used by a user who is already logged in.
#[get("/change_password")] #[get("/change_password")]
pub fn change_password(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn change_password(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings/admin".to_string())); context.insert("back", &Some("/settings/admin".to_string()));
context.insert("title", &Some("Change Password".to_string())); context.insert("title", &Some("Change Password".to_string()));

View File

@ -3,16 +3,21 @@ use rocket::{get, request::FlashMessage, State};
use rocket_dyn_templates::{tera::Context, Template}; use rocket_dyn_templates::{tera::Context, Template};
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils;
use crate::RocketConfig; use crate::RocketConfig;
// HELPERS AND ROUTES FOR / (HOME PAGE) // HELPERS AND ROUTES FOR / (HOME PAGE)
#[get("/")] #[get("/")]
pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template { pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
// retrieve go-sbot systemd process status // retrieve go-sbot systemd process status
let sbot_status = SbotStatus::read().ok(); let sbot_status = SbotStatus::read().ok();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("sbot_status", &sbot_status); context.insert("sbot_status", &sbot_status);
context.insert("flash_name", &None::<()>); context.insert("flash_name", &None::<()>);
context.insert("flash_msg", &None::<()>); context.insert("flash_msg", &None::<()>);
@ -28,7 +33,11 @@ pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
#[get("/help")] #[get("/help")]
pub fn help(flash: Option<FlashMessage>) -> Template { pub fn help(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string())); context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Help".to_string())); context.insert("title", &Some("Help".to_string()));

View File

@ -11,6 +11,7 @@ use rocket::{
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils;
// HELPERS AND ROUTES FOR /private // HELPERS AND ROUTES FOR /private
@ -20,6 +21,7 @@ pub struct PrivateContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl PrivateContext { impl PrivateContext {
@ -29,6 +31,7 @@ impl PrivateContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -36,15 +39,21 @@ impl PrivateContext {
/// A private message composition and publication page. /// A private message composition and publication page.
#[get("/private")] #[get("/private")]
pub fn private(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn private(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = PrivateContext::build(); let mut context = PrivateContext::build();
context.back = Some("/".to_string()); context.back = Some("/".to_string());
context.title = Some("Private Messages".to_string()); context.title = Some("Private Messages".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
// add flash message contents to the context object // add flash message contents to the context object
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/messages", &context) Template::render("scuttlebutt/messages", &context)
} }
@ -56,6 +65,7 @@ pub struct PeerContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl PeerContext { impl PeerContext {
@ -65,6 +75,7 @@ impl PeerContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -72,15 +83,21 @@ impl PeerContext {
/// A peer menu which allows navigating to lists of friends, follows, followers and blocks. /// A peer menu which allows navigating to lists of friends, follows, followers and blocks.
#[get("/peers")] #[get("/peers")]
pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = PeerContext::build(); let mut context = PeerContext::build();
context.back = Some("/".to_string()); context.back = Some("/".to_string());
context.title = Some("Scuttlebutt Peers".to_string()); context.title = Some("Scuttlebutt Peers".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
// add flash message contents to the context object // add flash message contents to the context object
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/peers", &context) Template::render("scuttlebutt/peers", &context)
} }
@ -91,7 +108,10 @@ pub struct Post {
pub text: String, pub text: String,
} }
/// Publish a public Scuttlebutt post. Redirects to profile page of the PeachCloud local identity with a flash message describing the outcome of the action (may be successful or unsuccessful). /// Publish a public Scuttlebutt post.
/// Redirects to profile page of the PeachCloud local identity with a flash
/// message describing the outcome of the action (may be successful or
/// unsuccessful).
#[post("/publish", data = "<post>")] #[post("/publish", data = "<post>")]
pub fn publish(post: Form<Post>, _auth: Authenticated) -> Flash<Redirect> { pub fn publish(post: Form<Post>, _auth: Authenticated) -> Flash<Redirect> {
let post_text = &post.text; let post_text = &post.text;
@ -101,6 +121,7 @@ pub fn publish(post: Form<Post>, _auth: Authenticated) -> Flash<Redirect> {
// redirect to the profile template without public key ("home" / local profile) // redirect to the profile template without public key ("home" / local profile)
let pub_key: std::option::Option<&str> = None; let pub_key: std::option::Option<&str> = None;
let profile_url = uri!(profile(pub_key)); let profile_url = uri!(profile(pub_key));
// consider adding the message reference to the flash message (or render it in the template for // consider adding the message reference to the flash message (or render it in the template for
// `profile` // `profile`
Flash::success(Redirect::to(profile_url), "Published public post") Flash::success(Redirect::to(profile_url), "Published public post")
@ -113,7 +134,9 @@ pub struct PublicKey {
pub key: String, pub key: String,
} }
/// Follow a Scuttlebutt profile specified by the given public key. Redirects to the appropriate profile page with a flash message describing the outcome of the action (may be successful or unsuccessful). /// Follow a Scuttlebutt profile specified by the given public key.
/// Redirects to the appropriate profile page with a flash message describing
/// the outcome of the action (may be successful or unsuccessful).
#[post("/follow", data = "<pub_key>")] #[post("/follow", data = "<pub_key>")]
pub fn follow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> { pub fn follow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> {
let public_key = &pub_key.key; let public_key = &pub_key.key;
@ -123,12 +146,15 @@ pub fn follow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect>
// redirect to the profile template with provided public key // redirect to the profile template with provided public key
let profile_url = uri!(profile(Some(public_key))); let profile_url = uri!(profile(Some(public_key)));
let success_msg = format!("Followed {}", public_key); let success_msg = format!("Followed {}", public_key);
Flash::success(Redirect::to(profile_url), success_msg) Flash::success(Redirect::to(profile_url), success_msg)
} }
// HELPERS AND ROUTES FOR /unfollow // HELPERS AND ROUTES FOR /unfollow
/// Unfollow a Scuttlebutt profile specified by the given public key. Redirects to the appropriate profile page with a flash message describing the outcome of the action (may be successful or unsuccessful). /// Unfollow a Scuttlebutt profile specified by the given public key.
/// Redirects to the appropriate profile page with a flash message describing
/// the outcome of the action (may be successful or unsuccessful).
#[post("/unfollow", data = "<pub_key>")] #[post("/unfollow", data = "<pub_key>")]
pub fn unfollow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> { pub fn unfollow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> {
let public_key = &pub_key.key; let public_key = &pub_key.key;
@ -138,12 +164,15 @@ pub fn unfollow(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirec
// redirect to the profile template with provided public key // redirect to the profile template with provided public key
let profile_url = uri!(profile(Some(public_key))); let profile_url = uri!(profile(Some(public_key)));
let success_msg = format!("Unfollowed {}", public_key); let success_msg = format!("Unfollowed {}", public_key);
Flash::success(Redirect::to(profile_url), success_msg) Flash::success(Redirect::to(profile_url), success_msg)
} }
// HELPERS AND ROUTES FOR /block // HELPERS AND ROUTES FOR /block
/// Block a Scuttlebutt profile specified by the given public key. Redirects to the appropriate profile page with a flash message describing the outcome of the action (may be successful or unsuccessful). /// Block a Scuttlebutt profile specified by the given public key.
/// Redirects to the appropriate profile page with a flash message describing
/// the outcome of the action (may be successful or unsuccessful).
#[post("/block", data = "<pub_key>")] #[post("/block", data = "<pub_key>")]
pub fn block(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> { pub fn block(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect> {
let public_key = &pub_key.key; let public_key = &pub_key.key;
@ -153,6 +182,7 @@ pub fn block(pub_key: Form<PublicKey>, _auth: Authenticated) -> Flash<Redirect>
// redirect to the profile template with provided public key // redirect to the profile template with provided public key
let profile_url = uri!(profile(Some(public_key))); let profile_url = uri!(profile(Some(public_key)));
let success_msg = format!("Blocked {}", public_key); let success_msg = format!("Blocked {}", public_key);
Flash::success(Redirect::to(profile_url), success_msg) Flash::success(Redirect::to(profile_url), success_msg)
} }
@ -164,6 +194,7 @@ pub struct ProfileContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl ProfileContext { impl ProfileContext {
@ -173,6 +204,7 @@ impl ProfileContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -184,15 +216,21 @@ pub fn profile(
flash: Option<FlashMessage>, flash: Option<FlashMessage>,
_auth: Authenticated, _auth: Authenticated,
) -> Template { ) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = ProfileContext::build(); let mut context = ProfileContext::build();
context.back = Some("/".to_string()); context.back = Some("/".to_string());
context.title = Some("Profile".to_string()); context.title = Some("Profile".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
// add flash message contents to the context object // add flash message contents to the context object
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/profile", &context) Template::render("scuttlebutt/profile", &context)
} }
@ -204,6 +242,7 @@ pub struct FriendsContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl FriendsContext { impl FriendsContext {
@ -213,6 +252,7 @@ impl FriendsContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -221,9 +261,13 @@ impl FriendsContext {
/// key of the peer. /// key of the peer.
#[get("/friends")] #[get("/friends")]
pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = FriendsContext::build(); let mut context = FriendsContext::build();
context.back = Some("/scuttlebutt/peers".to_string()); context.back = Some("/scuttlebutt/peers".to_string());
context.title = Some("Friends".to_string()); context.title = Some("Friends".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -231,6 +275,7 @@ pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }
@ -242,6 +287,7 @@ pub struct FollowsContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl FollowsContext { impl FollowsContext {
@ -251,6 +297,7 @@ impl FollowsContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -259,9 +306,13 @@ impl FollowsContext {
/// key of the peer. /// key of the peer.
#[get("/follows")] #[get("/follows")]
pub fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = FollowsContext::build(); let mut context = FollowsContext::build();
context.back = Some("/scuttlebutt/peers".to_string()); context.back = Some("/scuttlebutt/peers".to_string());
context.title = Some("Follows".to_string()); context.title = Some("Follows".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -269,6 +320,7 @@ pub fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }
@ -280,6 +332,7 @@ pub struct FollowersContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl FollowersContext { impl FollowersContext {
@ -289,6 +342,7 @@ impl FollowersContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -297,9 +351,13 @@ impl FollowersContext {
/// key of the peer. /// key of the peer.
#[get("/followers")] #[get("/followers")]
pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = FollowersContext::build(); let mut context = FollowersContext::build();
context.back = Some("/scuttlebutt/peers".to_string()); context.back = Some("/scuttlebutt/peers".to_string());
context.title = Some("Followers".to_string()); context.title = Some("Followers".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -307,6 +365,7 @@ pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }
@ -318,6 +377,7 @@ pub struct BlocksContext {
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub theme: Option<String>,
} }
impl BlocksContext { impl BlocksContext {
@ -327,6 +387,7 @@ impl BlocksContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
theme: None,
} }
} }
} }
@ -335,9 +396,13 @@ impl BlocksContext {
/// key of the peer. /// key of the peer.
#[get("/blocks")] #[get("/blocks")]
pub fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = BlocksContext::build(); let mut context = BlocksContext::build();
context.back = Some("/scuttlebutt/peers".to_string()); context.back = Some("/scuttlebutt/peers".to_string());
context.title = Some("Blocks".to_string()); context.title = Some("Blocks".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -345,5 +410,6 @@ pub fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("scuttlebutt/peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }

View File

@ -12,13 +12,18 @@ use peach_lib::config_manager;
use crate::error::PeachWebError; use crate::error::PeachWebError;
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils;
// HELPERS AND ROUTES FOR /settings/admin // HELPERS AND ROUTES FOR /settings/admin
/// Administrator settings menu. /// Administrator settings menu.
#[get("/")] #[get("/")]
pub fn admin_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn admin_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings".to_string())); context.insert("back", &Some("/settings".to_string()));
context.insert("title", &Some("Administrator Settings".to_string())); context.insert("title", &Some("Administrator Settings".to_string()));
@ -36,7 +41,11 @@ pub fn admin_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
/// View and delete currently configured admin. /// View and delete currently configured admin.
#[get("/configure")] #[get("/configure")]
pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings/admin".to_string())); context.insert("back", &Some("/settings/admin".to_string()));
context.insert("title", &Some("Configure Admin".to_string())); context.insert("title", &Some("Configure Admin".to_string()));
@ -81,7 +90,11 @@ pub fn save_add_admin_form(admin_form: AddAdminForm) -> Result<(), PeachWebError
#[get("/add")] #[get("/add")]
pub fn add_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn add_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings/admin/configure".to_string())); context.insert("back", &Some("/settings/admin/configure".to_string()));
context.insert("title", &Some("Add Admin".to_string())); context.insert("title", &Some("Add Admin".to_string()));

View File

@ -16,6 +16,7 @@ use peach_lib::{
use crate::{ use crate::{
context::dns::ConfigureDNSContext, error::PeachWebError, routes::authentication::Authenticated, context::dns::ConfigureDNSContext, error::PeachWebError, routes::authentication::Authenticated,
utils,
}; };
#[derive(Debug, Deserialize, FromForm)] #[derive(Debug, Deserialize, FromForm)]
@ -76,11 +77,14 @@ pub fn save_dns_configuration(dns_form: DnsForm) -> Result<(), PeachWebError> {
#[get("/dns")] #[get("/dns")]
pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = ConfigureDNSContext::build(); // retrieve current ui theme
let theme = utils::get_theme();
let mut context = ConfigureDNSContext::build();
// set back icon link to network route // set back icon link to network route
context.back = Some("/settings/network".to_string()); context.back = Some("/settings/network".to_string());
context.title = Some("Configure DNS".to_string()); context.title = Some("Configure DNS".to_string());
context.theme = Some(theme);
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {

View File

@ -2,6 +2,7 @@ use rocket::{get, request::FlashMessage, State};
use rocket_dyn_templates::{tera::Context, Template}; use rocket_dyn_templates::{tera::Context, Template};
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils;
use crate::RocketConfig; use crate::RocketConfig;
// HELPERS AND ROUTES FOR /settings // HELPERS AND ROUTES FOR /settings
@ -13,7 +14,11 @@ pub fn settings_menu(
flash: Option<FlashMessage>, flash: Option<FlashMessage>,
config: &State<RocketConfig>, config: &State<RocketConfig>,
) -> Template { ) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string())); context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Settings".to_string())); context.insert("title", &Some("Settings".to_string()));

View File

@ -3,3 +3,4 @@ pub mod dns;
pub mod menu; pub mod menu;
pub mod network; pub mod network;
pub mod scuttlebutt; pub mod scuttlebutt;
pub mod theme;

View File

@ -15,6 +15,7 @@ use rocket::{
use rocket_dyn_templates::{tera::Context, Template}; use rocket_dyn_templates::{tera::Context, Template};
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils;
#[derive(Debug, Deserialize, FromForm)] #[derive(Debug, Deserialize, FromForm)]
pub struct SbotConfigForm { pub struct SbotConfigForm {
@ -58,10 +59,14 @@ pub struct SbotConfigForm {
/// Scuttlebutt settings menu. /// Scuttlebutt settings menu.
#[get("/")] #[get("/")]
pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
// retrieve go-sbot systemd process status // retrieve go-sbot systemd process status
let sbot_status = SbotStatus::read().ok(); let sbot_status = SbotStatus::read().ok();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("sbot_status", &sbot_status); context.insert("sbot_status", &sbot_status);
context.insert("back", &Some("/settings".to_string())); context.insert("back", &Some("/settings".to_string()));
context.insert("title", &Some("Scuttlebutt Settings".to_string())); context.insert("title", &Some("Scuttlebutt Settings".to_string()));
@ -77,6 +82,9 @@ pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> T
/// Sbot configuration page (includes form for updating configuration parameters). /// Sbot configuration page (includes form for updating configuration parameters).
#[get("/configure")] #[get("/configure")]
pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
// retrieve go-sbot systemd process status // retrieve go-sbot systemd process status
let sbot_status = SbotStatus::read().ok(); let sbot_status = SbotStatus::read().ok();
let run_on_startup = sbot_status.map(|status| status.boot_state); let run_on_startup = sbot_status.map(|status| status.boot_state);
@ -85,6 +93,7 @@ pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Temp
let sbot_config = SbotConfig::read().ok(); let sbot_config = SbotConfig::read().ok();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings/scuttlebutt".to_string())); context.insert("back", &Some("/settings/scuttlebutt".to_string()));
context.insert("title", &Some("Sbot Configuration".to_string())); context.insert("title", &Some("Sbot Configuration".to_string()));
context.insert("sbot_config", &sbot_config); context.insert("sbot_config", &sbot_config);
@ -135,16 +144,14 @@ pub fn configure_sbot_post(
match owned_config.startup { match owned_config.startup {
true => { true => {
info!("Enabling go-sbot.service"); info!("Enabling go-sbot.service");
match systemctl_sbot_cmd("enable") { if let Err(e) = systemctl_sbot_cmd("enable") {
Err(e) => warn!("Failed to enable go-sbot.service: {}", e), warn!("Failed to enable go-sbot.service: {}", e)
_ => (),
} }
} }
false => { false => {
info!("Disabling go-sbot.service"); info!("Disabling go-sbot.service");
match systemctl_sbot_cmd("disable") { if let Err(e) = systemctl_sbot_cmd("disable") {
Err(e) => warn!("Failed to disable go-sbot.service: {}", e), warn!("Failed to disable go-sbot.service: {}", e)
_ => (),
} }
} }
}; };

View File

@ -0,0 +1,16 @@
use rocket::{get, response::Redirect};
use crate::routes::authentication::Authenticated;
use crate::{utils, utils::Theme};
/// Set the user-interface theme according to the query parameter value.
#[get("/theme?<theme>")]
pub fn set_theme(_auth: Authenticated, theme: &str) -> Redirect {
match theme {
"light" => utils::set_theme(Theme::Light),
"dark" => utils::set_theme(Theme::Dark),
_ => (),
}
Redirect::to("/")
}

View File

@ -3,18 +3,24 @@ use rocket::{get, State};
use rocket_dyn_templates::{tera::Context, Template}; use rocket_dyn_templates::{tera::Context, Template};
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils;
use crate::RocketConfig; use crate::RocketConfig;
// HELPERS AND ROUTES FOR /status/scuttlebutt // HELPERS AND ROUTES FOR /status/scuttlebutt
#[get("/scuttlebutt")] #[get("/scuttlebutt")]
pub fn scuttlebutt_status(_auth: Authenticated, config: &State<RocketConfig>) -> Template { pub fn scuttlebutt_status(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
// retrieve go-sbot systemd process status // retrieve go-sbot systemd process status
let sbot_status = SbotStatus::read().ok(); let sbot_status = SbotStatus::read().ok();
// retrieve go-sbot configuration parameters // retrieve go-sbot configuration parameters
let sbot_config = SbotConfig::read().ok(); let sbot_config = SbotConfig::read().ok();
let mut context = Context::new(); let mut context = Context::new();
context.insert("theme", &theme);
context.insert("sbot_status", &sbot_status); context.insert("sbot_status", &sbot_status);
context.insert("sbot_config", &sbot_config); context.insert("sbot_config", &sbot_config);
context.insert("flash_name", &None::<()>); context.insert("flash_name", &None::<()>);

View File

@ -1,9 +1,33 @@
pub mod monitor; pub mod monitor;
use rocket_dyn_templates::Template; use log::info;
use rocket::response::{Redirect, Responder}; use rocket::response::{Redirect, Responder};
use rocket::serde::Serialize; use rocket::serde::Serialize;
use rocket_dyn_templates::Template;
use crate::THEME;
// THEME FUNCTIONS
#[derive(Debug, Copy, Clone)]
pub enum Theme {
Light,
Dark,
}
pub fn get_theme() -> String {
let current_theme = THEME.read().unwrap();
match *current_theme {
Theme::Dark => "dark".to_string(),
_ => "light".to_string(),
}
}
pub fn set_theme(theme: Theme) {
info!("set ui theme to: {:?}", theme);
let mut writable_theme = THEME.write().unwrap();
*writable_theme = theme;
}
// HELPER FUNCTIONS // HELPER FUNCTIONS

View File

@ -1,6 +1,6 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en"{% if theme %} data-theme="{{ theme }}"{% endif %}>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>PeachCloud</title> <title>PeachCloud</title>