peach-workspace/peach-web/src/routes.rs

745 lines
31 KiB
Rust

//! Route handlers for PeachCloud web routes.
//!
//! This module contains handlers which serve templates and static assests,
//! generate flash messages, catch errors and handle redirects for PeachCloud.
//!
//! WEB ROUTES
//!
//! | Method | URL | Description |
//! | ------ | --------------------------- | --------------------------------- |
//! | GET | / | Home |
//! | GET | /device | Device statistics |
//! | GET | /device/reboot | Reboot device |
//! | GET | /device/shutdown | Shutdown device |
//! | GET | /help | Help and usage guidelines |
//! | GET | /login | Login form |
//! | POST | /login | Login form submission |
//! | POST | /logout | Logout authenticated user |
//! | GET | /network | Network overview |
//! | GET | /network/ap/activate | Activate WiFi access point mode |
//! | GET | /network/wifi | List of networks |
//! | GET | /network/wifi?<ssid> | Details of single network |
//! | GET | /network/wifi/activate | Activate WiFi client mode |
//! | GET | /network/wifi/add | Add WiFi form |
//! | POST | /network/wifi/add | WiFi form submission |
//! | GET | /network/wifi/add?<ssid> | Add WiFi form (SSID populated) |
//! | POST | /network/wifi/connect | Connect to WiFi access point |
//! | POST | /network/wifi/disconnect | Disconnect from WiFi access point |
//! | POST | /network/wifi/forget | Remove WiFi |
//! | GET | /network/wifi/modify?<ssid> | Modify WiFi password form |
//! | POST | /network/wifi/modify | Modify network password |
//! | GET | /network/wifi/usage | WiFi data usage form |
//! | POST | /network/wifi/usage | WiFi data usage form submission |
//! | GET | /network/wifi/usage/reset | Reset stored data usage total |
//! | GET | /messages | Private Scuttlebutt messages |
//! | GET | /peers | Scuttlebutt peers overview |
//! | GET | /profile | Scuttlebutt user profile |
//! | GET | /shutdown | Shutdown menu |
//! | GET | /network/dns | View DNS configurations |
//! | POST | /network/dns | Modify DNS configurations |
//! | GET | /settings/change_password | View password settings form |
//! | POST | /settings/change_password | Change admin password |
//! | GET | /reset_password | Change password using temp pass |
//! | POST | /reset_password | Rhange password using temp pass |
//! | GET | /send_password_reset | Send new password reset link |
//! | POST | /send_password_reset | Send new password reset link |
use std::path::{Path, PathBuf};
use log::{debug, info, warn};
use percent_encoding::percent_decode;
use rocket::http::RawStr;
use rocket::request::{FlashMessage, Form};
use rocket::response::{Flash, NamedFile, Redirect};
use rocket::{catch, get, post, uri};
use rocket_contrib::templates::Template;
use peach_lib::config_manager;
use peach_lib::network_client;
use peach_lib::password_utils;
use crate::common::{
save_add_admin_form, save_dns_configuration, save_password_form, save_reset_password_form,
};
use crate::context::{
AddAdminContext, ChangePasswordContext, ConfigureAdminContext, ConfigureDNSContext,
DeviceContext, ErrorContext, HelpContext, HomeContext, LoginContext, MessageContext,
NetworkAddContext, NetworkAlertContext, NetworkContext, NetworkDetailContext,
NetworkListContext, PeerContext, ProfileContext, ResetPasswordContext,
SendPasswordResetContext, ShutdownContext,
};
use crate::device;
use crate::forms::{
AddAdminForm, DeleteAdminForm, DnsForm, PasswordForm, ResetPasswordForm, Ssid, WiFi,
};
use crate::monitor;
use crate::monitor::Threshold;
#[get("/")]
pub fn index() -> Template {
let context = HomeContext {
flash_name: None,
flash_msg: None,
title: None,
};
Template::render("index", &context)
}
#[get("/device")]
pub fn device_stats(flash: Option<FlashMessage>) -> Template {
// assign context through context_builder call
let mut context = DeviceContext::build();
context.back = Some("/".to_string());
context.title = Some("Device Status".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("device", &context)
}
#[get("/device/reboot")]
pub fn reboot_cmd() -> Flash<Redirect> {
match device::reboot() {
Ok(_) => Flash::success(Redirect::to("/shutdown"), "Rebooting the device"),
Err(_) => Flash::error(Redirect::to("/shutdown"), "Failed to reboot the device"),
}
}
#[get("/device/shutdown")]
pub fn shutdown_cmd() -> Flash<Redirect> {
match device::shutdown() {
Ok(_) => Flash::success(Redirect::to("/shutdown"), "Shutting down the device"),
Err(_) => Flash::error(Redirect::to("/shutdown"), "Failed to shutdown the device"),
}
}
#[get("/help")]
pub fn help(flash: Option<FlashMessage>) -> Template {
let mut context = HelpContext::build();
context.back = Some("/".to_string());
context.title = Some("Help".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("help", &context)
}
#[get("/login")]
pub fn login(flash: Option<FlashMessage>) -> Template {
let mut context = LoginContext::build();
context.back = Some("/".to_string());
context.title = Some("Login".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("login", &context)
}
#[post("/logout")]
pub fn logout() -> Flash<Redirect> {
// logout authenticated user
debug!("Attempting deauthentication of user.");
/*
match logout_user() {
Ok(_) => Flash::success(Redirect::to("/"), "Logout success"),
Err(_) => Flash::error(
Redirect::to("/"),
"Failed to logout",
),
}
*/
Flash::success(Redirect::to("/"), "Logged out")
}
#[get("/network")]
pub fn network_home(flash: Option<FlashMessage>) -> Template {
// assign context through context_builder call
let mut context = NetworkContext::build();
// set back button (nav) url
context.back = Some("/".to_string());
// set page title
context.title = Some("Network Configuration".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_card", &context)
}
#[get("/network/ap/activate")]
pub fn deploy_ap() -> Flash<Redirect> {
// activate the wireless access point
debug!("Activating WiFi access point.");
match network_client::activate_ap() {
Ok(_) => Flash::success(Redirect::to("/network"), "Activated WiFi access point"),
Err(_) => Flash::error(
Redirect::to("/network"),
"Failed to activate WiFi access point",
),
}
}
#[get("/network/wifi")]
pub fn wifi_list(flash: Option<FlashMessage>) -> Template {
// assign context through context_builder call
let mut context = NetworkListContext::build();
context.back = Some("/network".to_string());
context.title = Some("WiFi Networks".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_list", &context)
}
#[get("/network/wifi?<ssid>")]
pub fn network_detail(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
// assign context through context_builder call
let mut context = NetworkDetailContext::build();
context.back = Some("/network/wifi".to_string());
context.title = Some("WiFi Network".to_string());
// decode ssid from url
let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap();
context.selected = Some(decoded_ssid.to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_detail", &context)
}
#[get("/network/wifi/activate")]
pub fn deploy_client() -> Flash<Redirect> {
// activate the wireless client
debug!("Activating WiFi client mode.");
match network_client::activate_client() {
Ok(_) => Flash::success(Redirect::to("/network"), "Activated WiFi client"),
Err(_) => Flash::error(Redirect::to("/network"), "Failed to activate WiFi client"),
}
}
#[get("/network/wifi/add")]
pub fn network_add_wifi(flash: Option<FlashMessage>) -> Template {
let mut context = NetworkContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Add WiFi Network".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_add", &context)
}
#[get("/network/wifi/add?<ssid>")]
pub fn network_add_ssid(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
// decode ssid from url
let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap();
let mut context = NetworkAddContext::build();
context.back = Some("/network/wifi".to_string());
context.selected = Some(decoded_ssid.to_string());
context.title = Some("Add WiFi Network".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_add", &context)
}
#[post("/network/wifi/add", data = "<wifi>")]
pub fn add_credentials(wifi: Form<WiFi>) -> Template {
// check if the credentials already exist for this access point
// note: this is nicer but it's an unstable feature:
// if check_saved_aps(&wifi.ssid).contains(true)
// use unwrap_or instead, set value to false if err is returned
let creds_exist = network_client::saved_ap(&wifi.ssid).unwrap_or(false);
if creds_exist {
let mut context = NetworkAddContext::build();
context.back = Some("/network".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg =
Some("Network credentials already exist for this access point".to_string());
context.title = Some("Add WiFi Network".to_string());
// return early from handler with "creds already exist" message
return Template::render("network_add", &context);
};
// if credentials not found, generate and write wifi config to wpa_supplicant
match network_client::add(&wifi.ssid, &wifi.pass) {
Ok(_) => {
debug!("Added WiFi credentials.");
// force reread of wpa_supplicant.conf file with new credentials
match network_client::reconfigure() {
Ok(_) => debug!("Successfully reconfigured wpa_supplicant"),
Err(_) => warn!("Failed to reconfigure wpa_supplicant"),
}
let mut context = NetworkAddContext::build();
context.back = Some("/network".to_string());
context.flash_name = Some("success".to_string());
context.flash_msg = Some("Added WiFi credentials".to_string());
context.title = Some("Add WiFi Network".to_string());
Template::render("network_add", &context)
}
Err(_) => {
debug!("Failed to add WiFi credentials.");
let mut context = NetworkAddContext::build();
context.back = Some("/network".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some("Failed to add WiFi credentials".to_string());
context.title = Some("Add WiFi Network".to_string());
Template::render("network_add", &context)
}
}
}
#[get("/network/wifi/usage")]
pub fn wifi_usage(flash: Option<FlashMessage>) -> Template {
let mut context = NetworkAlertContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Network Data Usage".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_usage", &context)
}
#[post("/network/wifi/usage", data = "<thresholds>")]
pub fn wifi_usage_alerts(thresholds: Form<Threshold>) -> Flash<Redirect> {
match monitor::update_store(thresholds.into_inner()) {
Ok(_) => {
debug!("WiFi data usage thresholds updated.");
Flash::success(
Redirect::to("/network/wifi/usage"),
"Updated alert thresholds and flags",
)
}
Err(_) => {
warn!("Failed to update WiFi data usage thresholds.");
Flash::error(
Redirect::to("/network/wifi/usage"),
"Failed to update alert thresholds and flags",
)
}
}
}
#[get("/network/dns")]
pub fn configure_dns(flash: Option<FlashMessage>) -> Template {
let mut context = ConfigureDNSContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Configure DNS".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("configure_dns", &context)
}
#[post("/network/dns", data = "<dns>")]
pub fn configure_dns_post(dns: Form<DnsForm>) -> Template {
let result = save_dns_configuration(dns.into_inner());
match result {
Ok(_) => {
let mut context = ConfigureDNSContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Configure DNS".to_string());
context.flash_name = Some("success".to_string());
context.flash_msg = Some("New dynamic dns configuration is now enabled".to_string());
Template::render("configure_dns", &context)
}
Err(err) => {
let mut context = ConfigureDNSContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Configure DNS".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to save dns configurations: {}", err));
Template::render("configure_dns", &context)
}
}
}
/// this change password route is used by a user who is already logged in
#[get("/settings/change_password")]
pub fn change_password(flash: Option<FlashMessage>) -> Template {
let mut context = ChangePasswordContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Change Password".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("password/change_password", &context)
}
/// this change password route is used by a user who is already logged in
#[post("/settings/change_password", data = "<password_form>")]
pub fn change_password_post(password_form: Form<PasswordForm>) -> Template {
let result = save_password_form(password_form.into_inner());
match result {
Ok(_) => {
let mut context = ChangePasswordContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Change Password".to_string());
context.flash_name = Some("success".to_string());
context.flash_msg = Some("New password is now saved".to_string());
// template_dir is set in Rocket.toml
Template::render("password/change_password", &context)
}
Err(err) => {
let mut context = ChangePasswordContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Configure DNS".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to save new password: {}", err));
Template::render("password/change_password", &context)
}
}
}
/// this reset password route is used by a user who is not logged in
/// and is specifically for users who have forgotten their password
/// all routes under /public/* are excluded from nginx basic auth via the nginx config
#[get("/reset_password")]
pub fn reset_password(flash: Option<FlashMessage>) -> Template {
let mut context = ResetPasswordContext::build();
context.back = Some("/".to_string());
context.title = Some("Reset Password".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("password/reset_password", &context)
}
/// this reset password route is used by a user who is not logged in
/// and is specifically for users who have forgotten their password
/// and is excluded from nginx basic auth via the nginx config
#[post("/reset_password", data = "<reset_password_form>")]
pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Template {
let result = save_reset_password_form(reset_password_form.into_inner());
match result {
Ok(_) => {
let mut context = ChangePasswordContext::build();
context.back = Some("/".to_string());
context.title = Some("Reset Password".to_string());
context.flash_name = Some("success".to_string());
let flash_msg = "New password is now saved. Return home to login".to_string();
context.flash_msg = Some(flash_msg);
Template::render("password/reset_password", &context)
}
Err(err) => {
let mut context = ChangePasswordContext::build();
// set back icon link to network route
context.back = Some("/".to_string());
context.title = Some("Reset Password".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to reset password: {}", err));
Template::render("password/reset_password", &context)
}
}
}
/// this route is used by a user who is not logged in to send a new password reset link
#[get("/send_password_reset")]
pub fn send_password_reset_page(flash: Option<FlashMessage>) -> Template {
let mut context = SendPasswordResetContext::build();
context.back = Some("/".to_string());
context.title = Some("Send Password Reset".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("password/send_password_reset", &context)
}
/// this send_password_reset route is used by a user who is not logged in
/// and is specifically for users who have forgotten their password
#[post("/send_password_reset")]
pub fn send_password_reset_post() -> Template {
info!("++ send password reset post");
let result = password_utils::send_password_reset();
match result {
Ok(_) => {
let mut context = ChangePasswordContext::build();
context.back = Some("/".to_string());
context.title = Some("Send Password Reset".to_string());
context.flash_name = Some("success".to_string());
let flash_msg =
"A password reset link has been sent to the admin of this device".to_string();
context.flash_msg = Some(flash_msg);
Template::render("password/send_password_reset", &context)
}
Err(err) => {
let mut context = ChangePasswordContext::build();
context.back = Some("/".to_string());
context.title = Some("Send Password Reset".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to send password reset link: {}", err));
Template::render("password/send_password_reset", &context)
}
}
}
/// this is a route for viewing and deleting currently configured admin
#[get("/settings/configure_admin")]
pub fn configure_admin(flash: Option<FlashMessage>) -> Template {
let mut context = ConfigureAdminContext::build();
// set back icon link to network route
context.back = Some("/network".to_string());
context.title = Some("Configure Admin".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("admin/configure_admin", &context)
}
#[get("/settings/admin/add")]
pub fn add_admin(flash: Option<FlashMessage>) -> Template {
let mut context = AddAdminContext::build();
context.back = Some("/settings/configure_admin".to_string());
context.title = Some("Add Admin".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("admin/add_admin", &context)
}
#[post("/settings/admin/add", data = "<add_admin_form>")]
pub fn add_admin_post(add_admin_form: Form<AddAdminForm>) -> Flash<Redirect> {
let result = save_add_admin_form(add_admin_form.into_inner());
let url = uri!(configure_admin);
match result {
Ok(_) => Flash::success(Redirect::to(url), "Successfully added new admin"),
Err(_) => Flash::error(Redirect::to(url), "Failed to add new admin"),
}
}
#[post("/settings/admin/delete", data = "<delete_admin_form>")]
pub fn delete_admin_post(delete_admin_form: Form<DeleteAdminForm>) -> Flash<Redirect> {
let result = config_manager::delete_ssb_admin_id(&delete_admin_form.ssb_id);
let url = uri!(configure_admin);
match result {
Ok(_) => Flash::success(Redirect::to(url), "Successfully removed admin id"),
Err(_) => Flash::error(Redirect::to(url), "Failed to remove admin id"),
}
}
#[get("/network/wifi/usage/reset")]
pub fn wifi_usage_reset() -> Flash<Redirect> {
let url = uri!(wifi_usage);
match monitor::reset_data() {
Ok(_) => Flash::success(Redirect::to(url), "Reset stored network traffic total"),
Err(_) => Flash::error(
Redirect::to(url),
"Failed to reset stored network traffic total",
),
}
}
#[post("/network/wifi/connect", data = "<network>")]
pub fn connect_wifi(network: Form<Ssid>) -> Flash<Redirect> {
let ssid = &network.ssid;
let url = uri!(network_detail: ssid);
match network_client::id("wlan0", ssid) {
Ok(id) => match network_client::connect(&id, "wlan0") {
Ok(_) => Flash::success(Redirect::to(url), "Connected to chosen network"),
Err(_) => Flash::error(Redirect::to(url), "Failed to connect to chosen network"),
},
Err(_) => Flash::error(Redirect::to(url), "Failed to retrieve the network ID"),
}
}
#[post("/network/wifi/disconnect", data = "<network>")]
pub fn disconnect_wifi(network: Form<Ssid>) -> Flash<Redirect> {
let ssid = &network.ssid;
let url = uri!(network_home);
match network_client::disable("wlan0", ssid) {
Ok(_) => Flash::success(Redirect::to(url), "Disconnected from WiFi network"),
Err(_) => Flash::error(Redirect::to(url), "Failed to disconnect from WiFi network"),
}
}
#[post("/network/wifi/forget", data = "<network>")]
pub fn forget_wifi(network: Form<Ssid>) -> Flash<Redirect> {
let ssid = &network.ssid;
let url = uri!(network_home);
match network_client::forget("wlan0", ssid) {
Ok(_) => Flash::success(Redirect::to(url), "WiFi credentials removed"),
Err(_) => Flash::error(
Redirect::to(url),
"Failed to remove WiFi credentials".to_string(),
),
}
}
#[get("/network/wifi/modify?<ssid>")]
pub fn wifi_password(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
// decode ssid from url
let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap();
let mut context = NetworkAddContext {
back: Some("/network/wifi".to_string()),
flash_name: None,
flash_msg: None,
selected: Some(decoded_ssid.to_string()),
title: Some("Update WiFi Password".to_string()),
};
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
// template_dir is set in Rocket.toml
Template::render("network_modify", &context)
}
#[post("/network/wifi/modify", data = "<wifi>")]
pub fn wifi_set_password(wifi: Form<WiFi>) -> Flash<Redirect> {
let ssid = &wifi.ssid;
let pass = &wifi.pass;
let url = uri!(network_detail: ssid);
match network_client::update("wlan0", ssid, pass) {
Ok(_) => Flash::success(Redirect::to(url), "WiFi password updated".to_string()),
Err(_) => Flash::error(
Redirect::to(url),
"Failed to update WiFi password".to_string(),
),
}
}
#[get("/messages")]
pub fn messages(flash: Option<FlashMessage>) -> Template {
let mut context = MessageContext::build();
context.back = Some("/".to_string());
context.title = Some("Private Messages".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("messages", &context)
}
#[get("/peers")]
pub fn peers(flash: Option<FlashMessage>) -> Template {
let mut context = PeerContext::build();
context.back = Some("/".to_string());
context.title = Some("Scuttlebutt Peers".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("peers", &context)
}
#[get("/profile")]
pub fn profile(flash: Option<FlashMessage>) -> Template {
let mut context = ProfileContext::build();
context.back = Some("/".to_string());
context.title = Some("Profile".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("profile", &context)
}
#[get("/shutdown")]
pub fn shutdown_menu(flash: Option<FlashMessage>) -> Template {
let mut context = ShutdownContext::build();
context.back = Some("/".to_string());
context.title = Some("Shutdown Device".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.flash_name = Some(flash.name().to_string());
context.flash_msg = Some(flash.msg().to_string());
};
Template::render("shutdown", &context)
}
#[get("/<file..>", rank = 2)]
pub fn files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("static/").join(file)).ok()
}
#[catch(404)]
pub fn not_found() -> Template {
debug!("404 Page Not Found");
let mut context = ErrorContext::build();
context.back = Some("/".to_string());
context.title = Some("404: Page Not Found".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some("No resource found for given URL".to_string());
Template::render("not_found", context)
}
#[catch(500)]
pub fn internal_error() -> Template {
debug!("500 Internal Server Error");
let mut context = ErrorContext::build();
context.back = Some("/".to_string());
context.title = Some("500: Internal Server Error".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some("Internal server error".to_string());
Template::render("internal_error", context)
}