From b0cdd1ba5c464573ee3b7e358e8ff855545628e6 Mon Sep 17 00:00:00 2001 From: notplants Date: Thu, 4 Nov 2021 14:10:41 +0100 Subject: [PATCH] Upgrade to 0.5 complete --- peach-web/src/lib.rs | 150 ----------------------- peach-web/src/main.rs | 148 ++++++++++++++++++++-- peach-web/src/routes/authentication.rs | 3 +- peach-web/src/routes/helpers.rs | 8 +- peach-web/src/routes/settings/admin.rs | 3 +- peach-web/src/routes/settings/dns.rs | 3 +- peach-web/src/routes/settings/network.rs | 25 ++-- peach-web/src/utils/monitor.rs | 2 +- 8 files changed, 157 insertions(+), 185 deletions(-) delete mode 100644 peach-web/src/lib.rs diff --git a/peach-web/src/lib.rs b/peach-web/src/lib.rs deleted file mode 100644 index eff8c14..0000000 --- a/peach-web/src/lib.rs +++ /dev/null @@ -1,150 +0,0 @@ -//! # peach-web -//! -//! `peach-web` provides a web interface for monitoring and interacting with the -//! PeachCloud device. This allows administration of the single-board computer -//! (ie. Raspberry Pi) running PeachCloud, as well as the ssb-server and related -//! plugins. -//! -//! ## Design -//! -//! `peach-web` is written primarily in Rust and presents a web interface for -//! interacting with the device. The stack currently consists of Rocket (Rust -//! web framework), Tera (Rust template engine inspired by Jinja2 and the Django -//! template language), HTML, CSS and JavaScript. Additional functionality is -//! provided by JSON-RPC clients for the `peach-network` and `peach-stats` -//! microservices. -//! -//! HTML is rendered server-side. Request handlers call JSON-RPC microservices -//! and serve HTML and assets. A JSON API is exposed for remote calls and -//! dynamic client-side content updates via vanilla JavaScript following -//! unobstructive design principles. A basic Websockets server is included, -//! though is not currently utilised. Each Tera template is passed a context -//! object. In the case of Rust, this object is a `struct` and must implement -//! `Serialize`. The fields of the context object are available in the context -//! of the template to be rendered. - -#![feature(proc_macro_hygiene, decl_macro)] - -pub mod error; -pub mod routes; -#[cfg(test)] -mod tests; -pub mod utils; -mod ws; - -use std::{env, thread}; - -use log::{debug, error, info}; - -use rocket::{catchers, routes, Rocket, Build}; -use rocket_dyn_templates::Template; - -use crate::routes::authentication::*; -use crate::routes::device::*; -use crate::routes::helpers::*; -use crate::routes::index::*; -use crate::routes::ping::*; -use crate::routes::scuttlebutt::*; - -use crate::routes::settings::admin::*; -use crate::routes::settings::dns::*; -use crate::routes::settings::network::*; -use crate::ws::*; - -pub type BoxError = Box; - -// create rocket instance & mount web & json routes (makes testing easier) -fn rocket() -> Rocket { - rocket::build() - .mount( - "/", - routes![ - add_credentials, // WEB ROUTE - connect_wifi, // WEB ROUTE - disconnect_wifi, // WEB ROUTE - deploy_ap, // WEB ROUTE - deploy_client, // WEB ROUTE - device_stats, // WEB ROUTE - files, // WEB ROUTE - forget_wifi, // WEB ROUTE - help, // WEB ROUTE - index, // WEB ROUTE - login, // WEB ROUTE - logout, // WEB ROUTE - messages, // WEB ROUTE - network_home, // WEB ROUTE - network_add_ssid, // WEB ROUTE - network_add_wifi, // WEB ROUTE - network_detail, // WEB ROUTE - peers, // WEB ROUTE - profile, // WEB ROUTE - reboot_cmd, // WEB ROUTE - shutdown_cmd, // WEB ROUTE - shutdown_menu, // WEB ROUTE - wifi_list, // WEB ROUTE - wifi_password, // WEB ROUTE - wifi_set_password, // WEB ROUTE - wifi_usage, // WEB ROUTE - wifi_usage_alerts, // WEB ROUTE - wifi_usage_reset, // WEB ROUTE - configure_dns, // WEB ROUTE - configure_dns_post, // WEB ROUTE - change_password, // WEB ROUTE - reset_password, // WEB ROUTE - reset_password_post, // WEB ROUTE - send_password_reset_page, // WEB ROUTE - send_password_reset_post, // WEB ROUTE - configure_admin, // WEB ROUTE - add_admin, // WEB ROUTE - add_admin_post, // WEB ROUTE - delete_admin_post, // WEB ROUTE - activate_ap, // JSON API - activate_client, // JSON API - add_wifi, // JSON API - connect_ap, // JSON API - disconnect_ap, // JSON API - forget_ap, // JSON API - modify_password, // JSON API - ping_pong, // JSON API - test_route, // JSON API - ping_network, // JSON API - ping_oled, // JSON API - ping_stats, // JSON API - reset_data_total, // JSON API - return_ip, // JSON API - return_rssi, // JSON API - return_ssid, // JSON API - return_state, // JSON API - return_status, // JSON API - reboot_device, // JSON API - scan_networks, // JSON API - shutdown_device, // JSON API - update_wifi_alerts, // JSON API - save_dns_configuration_endpoint, // JSON API - save_password_form_endpoint, // JSON API - reset_password_form_endpoint, // JSON API - ], - ) - .register("/", catchers![not_found, internal_error]) - .attach(Template::fairing()) -} - -// launch the rocket server -pub fn run() -> Result<(), BoxError> { - info!("Starting up."); - - // spawn a separate thread for rocket to prevent blocking websockets - thread::spawn(|| { - info!("Launching Rocket server."); - rocket().launch(); - }); - - // NOTE: websockets are not currently in use (may be in the future) - let ws_addr = env::var("PEACH_WEB_WS").unwrap_or_else(|_| "0.0.0.0:5115".to_string()); - match websocket_server(ws_addr) { - Ok(_) => debug!("Websocket server terminated without error."), - Err(e) => error!("Error starting the websocket server: {}", e), - }; - - Ok(()) -} diff --git a/peach-web/src/main.rs b/peach-web/src/main.rs index 4588e5d..f52a2f7 100644 --- a/peach-web/src/main.rs +++ b/peach-web/src/main.rs @@ -1,16 +1,144 @@ -//! Initialize the logger and run the application, catching any errors. +//! # peach-web +//! +//! `peach-web` provides a web interface for monitoring and interacting with the +//! PeachCloud device. This allows administration of the single-board computer +//! (ie. Raspberry Pi) running PeachCloud, as well as the ssb-server and related +//! plugins. +//! +//! ## Design +//! +//! `peach-web` is written primarily in Rust and presents a web interface for +//! interacting with the device. The stack currently consists of Rocket (Rust +//! web framework), Tera (Rust template engine inspired by Jinja2 and the Django +//! template language), HTML, CSS and JavaScript. Additional functionality is +//! provided by JSON-RPC clients for the `peach-network` and `peach-stats` +//! microservices. +//! +//! HTML is rendered server-side. Request handlers call JSON-RPC microservices +//! and serve HTML and assets. A JSON API is exposed for remote calls and +//! dynamic client-side content updates via vanilla JavaScript following +//! unobstructive design principles. A basic Websockets server is included, +//! though is not currently utilised. Each Tera template is passed a context +//! object. In the case of Rust, this object is a `struct` and must implement +//! `Serialize`. The fields of the context object are available in the context +//! of the template to be rendered. -use std::process; +#![feature(proc_macro_hygiene, decl_macro)] -use log::error; +pub mod error; +pub mod routes; +#[cfg(test)] +mod tests; +pub mod utils; +mod ws; -fn main() { - // initialize the logger +use std::{env, thread}; +use log::{debug, error, info}; + +use rocket::{catchers, routes, Rocket, Build, fs::FileServer}; +use rocket_dyn_templates::Template; + +use crate::routes::authentication::*; +use crate::routes::device::*; +use crate::routes::helpers::*; +use crate::routes::index::*; +use crate::routes::ping::*; +use crate::routes::scuttlebutt::*; + +use crate::routes::settings::admin::*; +use crate::routes::settings::dns::*; +use crate::routes::settings::network::*; +use crate::ws::*; + +pub type BoxError = Box; + +/// Create rocket instance & mount all routes. +fn init_rocket() -> Rocket { + rocket::build() + .mount( + "/", + routes![ + add_credentials, // WEB ROUTE + connect_wifi, // WEB ROUTE + disconnect_wifi, // WEB ROUTE + deploy_ap, // WEB ROUTE + deploy_client, // WEB ROUTE + device_stats, // WEB ROUTE + forget_wifi, // WEB ROUTE + help, // WEB ROUTE + index, // WEB ROUTE + login, // WEB ROUTE + logout, // WEB ROUTE + messages, // WEB ROUTE + network_home, // WEB ROUTE + network_add_ssid, // WEB ROUTE + network_add_wifi, // WEB ROUTE + network_detail, // WEB ROUTE + peers, // WEB ROUTE + profile, // WEB ROUTE + reboot_cmd, // WEB ROUTE + shutdown_cmd, // WEB ROUTE + shutdown_menu, // WEB ROUTE + wifi_list, // WEB ROUTE + wifi_password, // WEB ROUTE + wifi_set_password, // WEB ROUTE + wifi_usage, // WEB ROUTE + wifi_usage_alerts, // WEB ROUTE + wifi_usage_reset, // WEB ROUTE + configure_dns, // WEB ROUTE + configure_dns_post, // WEB ROUTE + change_password, // WEB ROUTE + reset_password, // WEB ROUTE + reset_password_post, // WEB ROUTE + send_password_reset_page, // WEB ROUTE + send_password_reset_post, // WEB ROUTE + configure_admin, // WEB ROUTE + add_admin, // WEB ROUTE + add_admin_post, // WEB ROUTE + delete_admin_post, // WEB ROUTE + activate_ap, // JSON API + activate_client, // JSON API + add_wifi, // JSON API + connect_ap, // JSON API + disconnect_ap, // JSON API + forget_ap, // JSON API + modify_password, // JSON API + ping_pong, // JSON API + test_route, // JSON API + ping_network, // JSON API + ping_oled, // JSON API + ping_stats, // JSON API + reset_data_total, // JSON API + return_ip, // JSON API + return_rssi, // JSON API + return_ssid, // JSON API + return_state, // JSON API + return_status, // JSON API + reboot_device, // JSON API + scan_networks, // JSON API + shutdown_device, // JSON API + update_wifi_alerts, // JSON API + save_dns_configuration_endpoint, // JSON API + save_password_form_endpoint, // JSON API + reset_password_form_endpoint, // JSON API + ], + ) + .mount("/", FileServer::from("static")) + .register("/", catchers![not_found, internal_error]) + .attach(Template::fairing()) +} + +/// Launch the peach-web rocket server. +#[rocket::main] +async fn main() { + + // initialize logger env_logger::init(); - // handle errors returned from `run` - if let Err(e) = peach_web::run() { - error!("Application error: {}", e); - process::exit(1); - } + // initialize and launch rocket + info!("Initializing Rocket"); + let rocket = init_rocket(); + + info!("Launching Rocket"); + rocket.launch().await; } diff --git a/peach-web/src/routes/authentication.rs b/peach-web/src/routes/authentication.rs index 9f8d367..a82bcba 100644 --- a/peach-web/src/routes/authentication.rs +++ b/peach-web/src/routes/authentication.rs @@ -1,5 +1,6 @@ use log::{debug, info}; -use rocket::request::{FlashMessage, Form, FromForm}; +use rocket::request::{FlashMessage}; +use rocket::form::{Form, FromForm}; use rocket::response::{Flash, Redirect}; use rocket::{get, post}; use rocket::serde::json::Json; diff --git a/peach-web/src/routes/helpers.rs b/peach-web/src/routes/helpers.rs index da5786a..5ef54d7 100644 --- a/peach-web/src/routes/helpers.rs +++ b/peach-web/src/routes/helpers.rs @@ -1,13 +1,7 @@ use log::debug; -use rocket::{catch, get, response::NamedFile}; +use rocket::{catch, get}; use rocket_dyn_templates::Template; use serde::Serialize; -use std::path::{Path, PathBuf}; - -#[get("/", rank = 2)] -pub fn files(file: PathBuf) -> Option { - NamedFile::open(Path::new("static/").join(file)).ok() -} // HELPERS AND ROUTES FOR 404 ERROR diff --git a/peach-web/src/routes/settings/admin.rs b/peach-web/src/routes/settings/admin.rs index cf02564..a688744 100644 --- a/peach-web/src/routes/settings/admin.rs +++ b/peach-web/src/routes/settings/admin.rs @@ -1,6 +1,7 @@ use rocket::{ get, post, - request::{FlashMessage, Form, FromForm}, + request::FlashMessage, + form::{Form, FromForm}, response::{Flash, Redirect}, uri, }; diff --git a/peach-web/src/routes/settings/dns.rs b/peach-web/src/routes/settings/dns.rs index b7ff5f0..6b021a3 100644 --- a/peach-web/src/routes/settings/dns.rs +++ b/peach-web/src/routes/settings/dns.rs @@ -1,7 +1,8 @@ use log::info; use rocket::{ get, post, - request::{FlashMessage, Form, FromForm}, + request::FlashMessage, + form::{Form, FromForm} }; use rocket::serde::json::Json; use rocket_dyn_templates::Template; diff --git a/peach-web/src/routes/settings/network.rs b/peach-web/src/routes/settings/network.rs index 3462313..f63300d 100644 --- a/peach-web/src/routes/settings/network.rs +++ b/peach-web/src/routes/settings/network.rs @@ -2,9 +2,9 @@ use log::{debug, warn}; use percent_encoding::percent_decode; use rocket::{ get, - http::RawStr, post, - request::{FlashMessage, Form, FromForm}, + request::FlashMessage, + form::{Form, FromForm}, response::{Flash, Redirect}, uri, UriDisplayQuery, }; @@ -52,7 +52,7 @@ pub fn wifi_usage_reset() -> Flash { #[post("/network/wifi/connect", data = "")] pub fn connect_wifi(network: Form) -> Flash { let ssid = &network.ssid; - let url = uri!(network_detail: ssid); + let url = uri!(network_detail(ssid = 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"), @@ -86,14 +86,12 @@ pub fn forget_wifi(network: Form) -> Flash { } #[get("/network/wifi/modify?")] -pub fn wifi_password(ssid: &RawStr, flash: Option) -> Template { - // decode ssid from url - let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap(); +pub fn wifi_password(ssid: &str, flash: Option) -> Template { let mut context = NetworkAddContext { back: Some("/network/wifi".to_string()), flash_name: None, flash_msg: None, - selected: Some(decoded_ssid.to_string()), + selected: Some(ssid.to_string()), title: Some("Update WiFi Password".to_string()), }; // check to see if there is a flash message to display @@ -110,7 +108,7 @@ pub fn wifi_password(ssid: &RawStr, flash: Option) -> Template { pub fn wifi_set_password(wifi: Form) -> Flash { let ssid = &wifi.ssid; let pass = &wifi.pass; - let url = uri!(network_detail: ssid); + let url = uri!(network_detail(ssid = ssid)); match network_client::update("wlan0", ssid, pass) { Ok(_) => Flash::success(Redirect::to(url), "WiFi password updated".to_string()), Err(_) => Flash::error( @@ -542,14 +540,12 @@ impl NetworkDetailContext { } #[get("/network/wifi?")] -pub fn network_detail(ssid: &RawStr, flash: Option) -> Template { +pub fn network_detail(ssid: &str, flash: Option) -> 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()); + context.selected = Some(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 @@ -613,9 +609,10 @@ impl NetworkAddContext { } #[get("/network/wifi/add?")] -pub fn network_add_ssid(ssid: &RawStr, flash: Option) -> Template { +pub fn network_add_ssid(ssid: &str, flash: Option) -> Template { // decode ssid from url - let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap(); + let decoded_ssid = ssid; +// 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()); diff --git a/peach-web/src/utils/monitor.rs b/peach-web/src/utils/monitor.rs index 619ffe3..6b87d15 100644 --- a/peach-web/src/utils/monitor.rs +++ b/peach-web/src/utils/monitor.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use nest::{Error, Store, Value}; -use rocket::request::FromForm; +use rocket::form::{Form, FromForm}; use rocket::serde::{Deserialize, Serialize}; use serde_json::json;