diff --git a/peach-web/README.md b/peach-web/README.md index e8956cf..f8185cd 100644 --- a/peach-web/README.md +++ b/peach-web/README.md @@ -12,62 +12,30 @@ The peach-web stack currently consists of [Rocket](https://rocket.rs/) (Rust web _Note: This is a work-in-progress._ -### WEB ROUTES (`src/routes.rs`) +### Setup -| Endpoint | Method | Parameters | Description | -| --- | --- | --- | --- | -| `/` | GET | | Home | -| `/device` | GET | | Device status overview | -| `/device/reboot` | GET | | Reboot device | -| `/device/shutdown` | GET | | Shutdown device | -| `/login` | GET | | Login form | -| `/network` | GET | | Network status overview | -| `/network/ap/activate` | GET | | Activate WiFi access point mode | -| `/network/wifi` | GET | | List of networks | -| `/network/wifi?` | GET | `ssid` | Details of a single network | -| `/network/wifi/activate` | GET | | Activate WiFi client mode | -| `/network/wifi/add` | GET | `ssid` (optional - prepopulation value of SSID in form) | Add a WiFi network | -| `/network/wifi/add` | POST | `ssid` & `pass` | Submit form to add a WiFi network | -| `/network/wifi/connect` | POST | `ssid` | Connect to the given WiFi network | -| `/network/wifi/disconnect` | POST | `ssid` | Disconnect from currently associated WiFi network | -| `/network/wifi/forget` | POST | `ssid` | Submit form to forget a saved WiFi network | -| `/network/wifi/modify?` | GET | `ssid` | Form for updating a WiFi network password | -| `/network/wifi/modify` | POST | `ssid` & `pass` | Submit form to update a WiFi network password | -| `/network/wifi/usage` | GET | | Network data usage values and a form to update alert thresholds | -| `/network/wifi/usage` | POST | `rx_warn`, `rx_cut`, `tx_warn`, `tx_cut`, `rx_warn_flag`, `rx_cut_flag`, `tx_warn_flag`, `tx_cut_flag` | Submit form to update alert thresholds & set flags | -| `/network/wifi/usage/reset` | GET | | Reset the stored network data usage total to zero | -| `/network/dns` | GET | | View current DNS configurations | -| `/network/dns` | POST | | Modify DNS configurations | -| `/shutdown` | GET | | Shutdown menu | +Clone the `peach-workspace` repo: -### JSON API (`src/json_api.rs`) +`git clone https://git.coopcloud.tech/PeachCloud/peach-workspace` -All JSON API calls are prefixed by `/api/v1/`. This has been excluded from the table below to keep the table compact. +Move into the repo and compile: -| Endpoint | Method | Parameters | Description | -| --- | --- | --- | --- | -| `device/reboot` | POST | | Reboot device | -| `device/shutdown` | POST | | Shutdown device | -| `network/activate_ap` | POST | | Activate WiFi access point mode | -| `network/activate_client` | POST | | Activate WiFi client mode | -| `network/ip` | GET | | Returns IP address values for wlan0 & ap0 interfaces | -| `network/rssi` | GET | | Returns RSSI for connected WiFi network | -| `network/ssid` | GET | | Returns SSID for connected WiFi network | -| `network/state` | GET | | Returns state of wlan0 & ap0 interfaces | -| `network/status` | GET | | Returns status object for connected WiFi network | -| `network/wifi` | GET | | Returns scan results for in-range access-points | -| `network/wifi` | POST | `ssid` & `pass` | Submit SSID & password to create new WiFi connection | -| `network/wifi/connect` | POST | `ssid` | Submit SSID to connect to a given WiFi network | -| `network/wifi/disconnect` | POST | `ssid` | Disconnect from the currently associated WiFi network | -| `network/wifi/forget` | POST | `ssid` | Submit SSID to delete credentials for given WiFi network | -| `network/wifi/modify` | POST | `ssid` & `pass` | Submit SSID & password to update the credentials for given WiFi network | -| `/network/wifi/usage` | POST | `rx_warn`, `rx_cut`, `tx_warn`, `tx_cut`, `rx_warn_flag`, `rx_cut_flag`, `tx_warn_flag`, `tx_cut_flag` | Submit form to update alert thresholds & set flags | -| `/network/wifi/usage/reset` | POST | | Reset network data usage total | -| `ping` | GET | | Returns `pong!` if `peach-web` is running | -| `ping/network` | GET | | Returns `pong!` if `peach-network` microservice is running | -| `ping/oled` | GET | | Returns `pong!` if `peach-oled` microservice is running | -| `ping/stats` | GET | | Returns `pong!` if `peach-stats` microservice is running | -| `dns/configure` | POST | | Modify dns configurations | +`cd peach-workspace/peach-web` +`cargo build --release` + +Run the tests: + +`cargo test` + +Move back to the `peach-workspace` directory: + +`cd ..` + +Run the binary: + +`./target/release/peach-web` + +_Note: Networking functionality requires peach-network microservice to be running._ ### Environment @@ -75,13 +43,7 @@ The web application deployment mode is configured with the `ROCKET_ENV` environm `export ROCKET_ENV=stage` -Other deployment modes are `dev` and `prod`. Read the [Rocket Environment Configurations docs](https://rocket.rs/v0.4/guide/configuration/#environment) for further information. - -The WebSocket server port can be configured with `PEACH_WEB_WS` environment variable: - -`export PEACH_WEB_WS=2333` - -When not set, the value defaults to `5115`. +Other deployment modes are `dev` and `prod`. Read the [Rocket Environment Configurations docs](https://rocket.rs/v0.5-rc/guide/configuration/#environment-variables) for further information. Logging is made available with `env_logger`: @@ -89,27 +51,6 @@ Logging is made available with `env_logger`: Other logging levels include `debug`, `warn` and `error`. -### Setup - -Clone this repo: - -`git clone https://github.com/peachcloud/peach-web.git` - -Move into the repo and compile: - -`cd peach-web` -`cargo build --release` - -Run the tests: - -`cargo test` - -Run the binary: - -`./target/release/peach-web` - -_Note: Networking functionality requires peach-network microservice to be running._ - ### Debian Packaging A `systemd` service file and Debian maintainer scripts are included in the `debian` directory, allowing `peach-web` to be easily bundled as a Debian package (`.deb`). The `cargo-deb` [crate](https://crates.io/crates/cargo-deb) can be used to achieve this. @@ -144,7 +85,7 @@ Remove configuration files (not removed with `apt-get remove`): ### Design -`peach-web` is built on the Rocket webserver and Tera templating engine. It presents a web interface for interacting with the device. 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). 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. +`peach-web` is built on the Rocket webserver and Tera templating engine. It presents a web interface for interacting with the device. 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 plain JavaScript following unobstructive design principles). 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. ### Licensing diff --git a/peach-web/src/main.rs b/peach-web/src/main.rs index ab1941f..f950665 100644 --- a/peach-web/src/main.rs +++ b/peach-web/src/main.rs @@ -38,100 +38,124 @@ use rocket_dyn_templates::Template; use crate::routes::authentication::*; use crate::routes::catchers::*; -use crate::routes::device::*; use crate::routes::index::*; -use crate::routes::ping::*; use crate::routes::scuttlebutt::*; +use crate::routes::status::device::*; +use crate::routes::status::ping::*; use crate::routes::settings::admin::*; use crate::routes::settings::dns::*; +use crate::routes::settings::menu::*; use crate::routes::settings::network::*; +use crate::routes::settings::scuttlebutt::*; pub type BoxError = Box; /// Create rocket instance & mount all routes. fn init_rocket() -> Rocket { rocket::build() - .mount( - "/scuttlebutt", - routes![ - peers, // WEB ROUTE - friends, // WEB ROUTE - follows, // WEB ROUTE - followers, // WEB ROUTE - blocks, // WEB ROUTE - profile, // WEB ROUTE - private, // WEB ROUTE - follow, // WEB ROUTE - unfollow, // WEB ROUTE - block, // WEB ROUTE - publish, // WEB ROUTE - ], - ) + // GENERAL HTML ROUTES .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 - login_post, // WEB ROUTE - logout, // WEB ROUTE - network_home, // WEB ROUTE - network_add_ssid, // WEB ROUTE - network_add_wifi, // WEB ROUTE - network_detail, // 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 - change_password_post, // WEB ROUTE - reset_password, // WEB ROUTE - reset_password_post, // WEB ROUTE - forgot_password_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 - 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 + device_status, + help, + home, + login, + login_post, + logout, + reboot_cmd, + shutdown_cmd, + power_menu, + settings_menu, + ], + ) + // ADMIN SETTINGS HTML ROUTES + .mount( + "/settings/admin", + routes![ + admin_menu, + configure_admin, + add_admin, + add_admin_post, + delete_admin_post, + change_password, + change_password_post, + reset_password, + reset_password_post, + forgot_password_page, + send_password_reset_post, + ], + ) + // NETWORK SETTINGS HTML ROUTES + .mount( + "/settings/network", + routes![ + add_credentials, + connect_wifi, + configure_dns, + configure_dns_post, + disconnect_wifi, + deploy_ap, + deploy_client, + forget_wifi, + network_home, + add_ssid, + add_wifi, + network_detail, + wifi_list, + wifi_password, + wifi_set_password, + wifi_usage, + wifi_usage_alerts, + wifi_usage_reset, + ], + ) + // SCUTTLEBUTT SETTINGS HTML ROUTES + .mount("/settings/scuttlebutt", routes![ssb_settings_menu]) + // SCUTTLEBUTT SOCIAL HTML ROUTES + .mount( + "/scuttlebutt", + routes![ + peers, friends, follows, followers, blocks, profile, private, follow, unfollow, + block, publish, + ], + ) + // GENERAL JSON API ROUTES + .mount( + "/api/v1", + routes![ping_pong, ping_network, ping_oled, ping_stats,], + ) + // ADMIN JSON API ROUTES + .mount( + "/api/v1/admin", + routes![ + save_password_form_endpoint, + reset_password_form_endpoint, + reboot_device, + shutdown_device, + ], + ) + // NETWORK JSON API ROUTES + .mount( + "/api/v1/network", + routes![ + activate_ap, + activate_client, + add_wifi_credentials, + connect_ap, + disconnect_ap, + forget_ap, + modify_password, + reset_data_total, + return_ip, + return_rssi, + return_ssid, + return_state, + return_status, + scan_networks, + update_wifi_alerts, + save_dns_configuration_endpoint, ], ) .mount("/", FileServer::from("static")) diff --git a/peach-web/src/routes/authentication.rs b/peach-web/src/routes/authentication.rs index 7c71799..1d1a9b6 100644 --- a/peach-web/src/routes/authentication.rs +++ b/peach-web/src/routes/authentication.rs @@ -1,23 +1,20 @@ -use log::{info}; -use rocket::request::{FlashMessage}; +use log::info; use rocket::form::{Form, FromForm}; +use rocket::request::FlashMessage; use rocket::response::{Flash, Redirect}; -use rocket::{get, post}; use rocket::serde::json::Json; -use rocket_dyn_templates::Template; use rocket::serde::{Deserialize, Serialize}; +use rocket::{get, post}; +use rocket_dyn_templates::Template; -use peach_lib::password_utils; use peach_lib::error::PeachError; +use peach_lib::password_utils; use crate::error::PeachWebError; use crate::utils::{build_json_response, TemplateOrRedirect}; -use rocket::serde::json::Value; +use rocket::http::{Cookie, CookieJar, Status}; use rocket::request::{self, FromRequest, Request}; -use rocket::http::{Cookie, CookieJar, Status}; - - - +use rocket::serde::json::Value; // HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES @@ -32,7 +29,7 @@ pub struct Authenticated; #[derive(Debug)] pub enum LoginError { - UserNotLoggedIn + UserNotLoggedIn, } /// Request guard which returns an empty Authenticated struct from the request @@ -49,14 +46,10 @@ impl<'r> FromRequest<'r> for Authenticated { .cookies() .get_private(AUTH_COOKIE_KEY) .and_then(|cookie| cookie.value().parse().ok()) - .map(|_value: String| { Authenticated { } }); + .map(|_value: String| Authenticated {}); match authenticated { - Some(auth) => { - request::Outcome::Success(auth) - }, - None => { - request::Outcome::Failure((Status::Forbidden, LoginError::UserNotLoggedIn)) - } + Some(auth) => request::Outcome::Success(auth), + None => request::Outcome::Failure((Status::Forbidden, LoginError::UserNotLoggedIn)), } } } @@ -96,7 +89,6 @@ pub fn login(flash: Option) -> Template { Template::render("login", &context) } - #[derive(Debug, Deserialize, FromForm)] pub struct LoginForm { pub username: String, @@ -112,7 +104,7 @@ pub fn verify_login_form(login_form: LoginForm) -> Result<(), PeachError> { password_utils::verify_password(&login_form.password) } -#[post("/login", data="")] +#[post("/login", data = "")] pub fn login_post(login_form: Form, cookies: &CookieJar<'_>) -> TemplateOrRedirect { let result = verify_login_form(login_form.into_inner()); match result { @@ -138,7 +130,6 @@ pub fn login_post(login_form: Form, cookies: &CookieJar<'_>) -> Templ } } - // HELPERS AND ROUTES FOR /logout #[get("/logout")] @@ -149,7 +140,6 @@ pub fn logout(cookies: &CookieJar<'_>) -> Flash { Flash::success(Redirect::to("/login"), "Logged out") } - // HELPERS AND ROUTES FOR /reset_password #[derive(Debug, Deserialize, FromForm)] @@ -228,7 +218,7 @@ pub fn reset_password(flash: Option) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("password/reset_password", &context) + Template::render("settings/admin/reset_password", &context) } /// Password reset form request handler. This route is used by a user who is not logged in @@ -245,7 +235,7 @@ pub fn reset_password_post(reset_password_form: Form) -> Temp 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) + Template::render("settings/admin/reset_password", &context) } Err(err) => { let mut context = ChangePasswordContext::build(); @@ -254,18 +244,15 @@ pub fn reset_password_post(reset_password_form: Form) -> Temp 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) + Template::render("settings/admin/reset_password", &context) } } } /// JSON password reset form request handler. This 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. -#[post("/public/api/v1/reset_password", data = "")] -pub fn reset_password_form_endpoint( - reset_password_form: Json, -) -> Value { +#[post("/reset_password", data = "")] +pub fn reset_password_form_endpoint(reset_password_form: Json) -> Value { let result = save_reset_password_form(reset_password_form.into_inner()); match result { Ok(_) => { @@ -316,7 +303,7 @@ pub fn forgot_password_page(flash: Option) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("password/forgot_password", &context) + Template::render("settings/admin/forgot_password", &context) } /// Send password reset request handler. This route is used by a user who is not logged in @@ -335,7 +322,7 @@ pub fn send_password_reset_post() -> Template { 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/forgot_password", &context) + Template::render("settings/admin/forgot_password", &context) } Err(err) => { let mut context = ChangePasswordContext::build(); @@ -343,7 +330,7 @@ pub fn send_password_reset_post() -> Template { 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/forgot_password", &context) + Template::render("settings/admin/forgot_password", &context) } } } @@ -375,11 +362,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. -#[get("/settings/change_password")] +#[get("/change_password")] pub fn change_password(flash: Option, _auth: Authenticated) -> Template { let mut context = ChangePasswordContext::build(); // set back icon link to network route - context.back = Some("/network".to_string()); + context.back = Some("/settings/admin".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 { @@ -387,39 +374,42 @@ pub fn change_password(flash: Option, _auth: Authenticated) -> Tem context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("password/change_password", &context) + Template::render("settings/admin/change_password", &context) } /// Change password form request handler. This route is used by a user who is already logged in. -#[post("/settings/change_password", data = "")] +#[post("/change_password", data = "")] pub fn change_password_post(password_form: Form, _auth: Authenticated) -> 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.back = Some("/settings/admin".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) + Template::render("settings/admin/change_password", &context) } Err(err) => { let mut context = ChangePasswordContext::build(); // set back icon link to network route - context.back = Some("/network".to_string()); + context.back = Some("/settings/admin".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) + Template::render("settings/admin/change_password", &context) } } } /// JSON change password form request handler. -#[post("/api/v1/settings/change_password", data = "")] -pub fn save_password_form_endpoint(password_form: Json, _auth: Authenticated) -> Value { +#[post("/change_password", data = "")] +pub fn save_password_form_endpoint( + password_form: Json, + _auth: Authenticated, +) -> Value { let result = save_password_form(password_form.into_inner()); match result { Ok(_) => { diff --git a/peach-web/src/routes/catchers.rs b/peach-web/src/routes/catchers.rs index a096cac..0c3523e 100644 --- a/peach-web/src/routes/catchers.rs +++ b/peach-web/src/routes/catchers.rs @@ -1,7 +1,7 @@ use log::debug; -use rocket::{catch}; -use rocket_dyn_templates::Template; +use rocket::catch; use rocket::response::Redirect; +use rocket_dyn_templates::Template; use serde::Serialize; // HELPERS AND ROUTES FOR 404 ERROR @@ -34,7 +34,7 @@ pub fn not_found() -> Template { context.flash_name = Some("error".to_string()); context.flash_msg = Some("No resource found for given URL".to_string()); - Template::render("not_found", context) + Template::render("catchers/not_found", context) } // HELPERS AND ROUTES FOR 500 ERROR @@ -48,7 +48,7 @@ pub fn internal_error() -> Template { context.flash_name = Some("error".to_string()); context.flash_msg = Some("Internal server error".to_string()); - Template::render("internal_error", context) + Template::render("catchers/internal_error", context) } // HELPERS AND ROUTES FOR 403 FORBIDDEN @@ -57,4 +57,4 @@ pub fn internal_error() -> Template { pub fn forbidden() -> Redirect { debug!("403 Forbidden"); Redirect::to("/login") -} \ No newline at end of file +} diff --git a/peach-web/src/routes/index.rs b/peach-web/src/routes/index.rs index 1ca4443..aa1113e 100644 --- a/peach-web/src/routes/index.rs +++ b/peach-web/src/routes/index.rs @@ -24,13 +24,13 @@ impl HomeContext { } #[get("/")] -pub fn index(_auth: Authenticated) -> Template { +pub fn home(_auth: Authenticated) -> Template { let context = HomeContext { flash_name: None, flash_msg: None, title: None, }; - Template::render("index", &context) + Template::render("home", &context) } // HELPERS AND ROUTES FOR /help diff --git a/peach-web/src/routes/mod.rs b/peach-web/src/routes/mod.rs index be18d09..830e23b 100644 --- a/peach-web/src/routes/mod.rs +++ b/peach-web/src/routes/mod.rs @@ -1,7 +1,6 @@ pub mod authentication; -pub mod device; pub mod catchers; pub mod index; -pub mod ping; pub mod scuttlebutt; -pub mod settings; \ No newline at end of file +pub mod settings; +pub mod status; diff --git a/peach-web/src/routes/scuttlebutt.rs b/peach-web/src/routes/scuttlebutt.rs index ec8d826..ede8699 100644 --- a/peach-web/src/routes/scuttlebutt.rs +++ b/peach-web/src/routes/scuttlebutt.rs @@ -45,7 +45,7 @@ pub fn private(flash: Option, _auth: Authenticated) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("messages", &context) + Template::render("scuttlebutt/messages", &context) } // HELPERS AND ROUTES FOR /peers @@ -81,7 +81,7 @@ pub fn peers(flash: Option, _auth: Authenticated) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("peers", &context) + Template::render("scuttlebutt/peers", &context) } // HELPERS AND ROUTES FOR /post/publish @@ -209,7 +209,7 @@ pub fn profile( context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("profile", &context) + Template::render("scuttlebutt/profile", &context) } // HELPERS AND ROUTES FOR /friends @@ -247,7 +247,7 @@ pub fn friends(flash: Option, _auth: Authenticated) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("peers_list", &context) + Template::render("scuttlebutt/peers_list", &context) } // HELPERS AND ROUTES FOR /follows @@ -285,7 +285,7 @@ pub fn follows(flash: Option, _auth: Authenticated) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("peers_list", &context) + Template::render("scuttlebutt/peers_list", &context) } // HELPERS AND ROUTES FOR /followers @@ -323,7 +323,7 @@ pub fn followers(flash: Option, _auth: Authenticated) -> Template context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("peers_list", &context) + Template::render("scuttlebutt/peers_list", &context) } // HELPERS AND ROUTES FOR /blocks @@ -361,5 +361,5 @@ pub fn blocks(flash: Option, _auth: Authenticated) -> Template { context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("peers_list", &context) + Template::render("scuttlebutt/peers_list", &context) } diff --git a/peach-web/src/routes/settings/admin.rs b/peach-web/src/routes/settings/admin.rs index 4f8980a..118fa0a 100644 --- a/peach-web/src/routes/settings/admin.rs +++ b/peach-web/src/routes/settings/admin.rs @@ -1,12 +1,12 @@ +use rocket::serde::{Deserialize, Serialize}; use rocket::{ + form::{Form, FromForm}, get, post, request::FlashMessage, - form::{Form, FromForm}, response::{Flash, Redirect}, uri, }; use rocket_dyn_templates::Template; -use rocket::serde::{Deserialize, Serialize}; use peach_lib::config_manager; use peach_lib::config_manager::load_peach_config; @@ -14,7 +14,44 @@ use peach_lib::config_manager::load_peach_config; use crate::error::PeachWebError; use crate::routes::authentication::Authenticated; -// HELPERS AND ROUTES FOR /settings/configure_admin +// HELPERS AND ROUTES FOR /settings/admin + +#[derive(Debug, Serialize)] +pub struct AdminMenuContext { + pub back: Option, + pub title: Option, + pub flash_name: Option, + pub flash_msg: Option, +} + +impl AdminMenuContext { + pub fn build() -> AdminMenuContext { + AdminMenuContext { + back: None, + title: None, + flash_name: None, + flash_msg: None, + } + } +} + +/// Administrator settings menu. +#[get("/")] +pub fn admin_menu(flash: Option, _auth: Authenticated) -> Template { + let mut context = AdminMenuContext::build(); + // set back icon link to settings route + context.back = Some("/settings".to_string()); + context.title = Some("Administrator Settings".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.kind().to_string()); + context.flash_msg = Some(flash.message().to_string()); + }; + Template::render("settings/admin/menu", &context) +} + +// HELPERS AND ROUTES FOR /settings/admin/configure #[derive(Debug, Serialize)] pub struct ConfigureAdminContext { @@ -40,11 +77,11 @@ impl ConfigureAdminContext { } /// View and delete currently configured admin. -#[get("/settings/configure_admin")] +#[get("/configure")] pub fn configure_admin(flash: Option, _auth: Authenticated) -> Template { let mut context = ConfigureAdminContext::build(); - // set back icon link to network route - context.back = Some("/network".to_string()); + // set back icon link to settings route + context.back = Some("/settings/admin".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 { @@ -52,7 +89,7 @@ pub fn configure_admin(flash: Option, _auth: Authenticated) -> Tem context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("admin/configure_admin", &context) + Template::render("settings/admin/configure_admin", &context) } // HELPERS AND ROUTES FOR /settings/admin/add @@ -83,14 +120,14 @@ impl AddAdminContext { pub fn save_add_admin_form(admin_form: AddAdminForm) -> Result<(), PeachWebError> { let _result = config_manager::add_ssb_admin_id(&admin_form.ssb_id)?; - // if the previous line didn't throw an error then it was a success + // if the previous line didn't throw an error then it was a success Ok(()) } -#[get("/settings/admin/add")] +#[get("/add")] pub fn add_admin(flash: Option, _auth: Authenticated) -> Template { let mut context = AddAdminContext::build(); - context.back = Some("/settings/configure_admin".to_string()); + context.back = Some("/settings/admin/configure".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 { @@ -99,10 +136,10 @@ pub fn add_admin(flash: Option, _auth: Authenticated) -> Template context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("admin/add_admin", &context) + Template::render("settings/admin/add_admin", &context) } -#[post("/settings/admin/add", data = "")] +#[post("/add", data = "")] pub fn add_admin_post(add_admin_form: Form, _auth: Authenticated) -> Flash { let result = save_add_admin_form(add_admin_form.into_inner()); let url = uri!(configure_admin); @@ -119,8 +156,11 @@ pub struct DeleteAdminForm { pub ssb_id: String, } -#[post("/settings/admin/delete", data = "")] -pub fn delete_admin_post(delete_admin_form: Form, _auth: Authenticated) -> Flash { +#[post("/delete", data = "")] +pub fn delete_admin_post( + delete_admin_form: Form, + _auth: Authenticated, +) -> Flash { let result = config_manager::delete_ssb_admin_id(&delete_admin_form.ssb_id); let url = uri!(configure_admin); match result { diff --git a/peach-web/src/routes/settings/dns.rs b/peach-web/src/routes/settings/dns.rs index 7bca89c..8ef3e21 100644 --- a/peach-web/src/routes/settings/dns.rs +++ b/peach-web/src/routes/settings/dns.rs @@ -1,12 +1,14 @@ use log::info; use rocket::{ + form::{Form, FromForm}, get, post, request::FlashMessage, - form::{Form, FromForm} + serde::{ + json::{Json, Value}, + Deserialize, Serialize, + }, }; -use rocket::serde::json::Json; use rocket_dyn_templates::Template; -use rocket::serde::{Deserialize, Serialize}; use peach_lib::config_manager; use peach_lib::config_manager::load_peach_config; @@ -22,7 +24,6 @@ use peach_lib::jsonrpc_core::types::error::ErrorCode; use crate::error::PeachWebError; use crate::routes::authentication::Authenticated; use crate::utils::build_json_response; -use rocket::serde::json::Value; #[derive(Debug, Deserialize, FromForm)] pub struct DnsForm { @@ -113,11 +114,11 @@ impl ConfigureDNSContext { } } -#[get("/network/dns")] +#[get("/dns")] pub fn configure_dns(flash: Option, _auth: Authenticated) -> Template { let mut context = ConfigureDNSContext::build(); // set back icon link to network route - context.back = Some("/network".to_string()); + context.back = Some("/settings/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 { @@ -125,35 +126,35 @@ pub fn configure_dns(flash: Option, _auth: Authenticated) -> Templ context.flash_name = Some(flash.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("configure_dns", &context) + Template::render("settings/network/configure_dns", &context) } -#[post("/network/dns", data = "")] +#[post("/dns", data = "")] pub fn configure_dns_post(dns: Form, _auth: Authenticated) -> 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.back = Some("/settings/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) + Template::render("settings/network/configure_dns", &context) } Err(err) => { let mut context = ConfigureDNSContext::build(); // set back icon link to network route - context.back = Some("/network".to_string()); + context.back = Some("/settings/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) + Template::render("settings/network/configure_dns", &context) } } } -#[post("/api/v1/dns/configure", data = "")] +#[post("/dns/configure", data = "")] pub fn save_dns_configuration_endpoint(dns_form: Json, _auth: Authenticated) -> Value { let result = save_dns_configuration(dns_form.into_inner()); match result { diff --git a/peach-web/src/routes/settings/menu.rs b/peach-web/src/routes/settings/menu.rs new file mode 100644 index 0000000..e5abe1c --- /dev/null +++ b/peach-web/src/routes/settings/menu.rs @@ -0,0 +1,41 @@ +use rocket::{get, request::FlashMessage, serde::Serialize}; +use rocket_dyn_templates::Template; + +use crate::routes::authentication::Authenticated; + +// HELPERS AND ROUTES FOR /settings + +#[derive(Debug, Serialize)] +pub struct SettingsMenuContext { + pub back: Option, + pub title: Option, + pub flash_name: Option, + pub flash_msg: Option, +} + +impl SettingsMenuContext { + pub fn build() -> SettingsMenuContext { + SettingsMenuContext { + back: None, + title: None, + flash_name: None, + flash_msg: None, + } + } +} + +/// View and delete currently configured admin. +#[get("/settings")] +pub fn settings_menu(flash: Option, _auth: Authenticated) -> Template { + let mut context = SettingsMenuContext::build(); + // set back icon link to network route + context.back = Some("/".to_string()); + context.title = Some("Settings".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.kind().to_string()); + context.flash_msg = Some(flash.message().to_string()); + }; + Template::render("settings/menu", &context) +} diff --git a/peach-web/src/routes/settings/mod.rs b/peach-web/src/routes/settings/mod.rs index 8fee4d7..1096c8d 100644 --- a/peach-web/src/routes/settings/mod.rs +++ b/peach-web/src/routes/settings/mod.rs @@ -1,3 +1,5 @@ pub mod admin; pub mod dns; -pub mod network; \ No newline at end of file +pub mod menu; +pub mod network; +pub mod scuttlebutt; diff --git a/peach-web/src/routes/settings/network.rs b/peach-web/src/routes/settings/network.rs index 9b80a37..61ae7be 100644 --- a/peach-web/src/routes/settings/network.rs +++ b/peach-web/src/routes/settings/network.rs @@ -1,27 +1,27 @@ use log::{debug, warn}; use rocket::{ - get, - post, - request::FlashMessage, form::{Form, FromForm}, + get, post, + request::FlashMessage, response::{Flash, Redirect}, + serde::{ + json::{json, Json, Value}, + Deserialize, Serialize, + }, uri, UriDisplayQuery, }; -use rocket::serde::json::{json, Json}; use rocket_dyn_templates::Template; -use rocket::serde::{Deserialize, Serialize}; use std::collections::HashMap; use peach_lib::network_client; use peach_lib::network_client::{AccessPoint, Networks, Scan}; use peach_lib::stats_client::Traffic; +use crate::routes::authentication::Authenticated; +use crate::utils::build_json_response; use crate::utils::monitor; use crate::utils::monitor::{Alert, Data, Threshold}; -use crate::utils::build_json_response; -use crate::routes::authentication::Authenticated; -use rocket::serde::json::Value; // STRUCTS USED BY NETWORK ROUTES @@ -36,9 +36,9 @@ pub struct WiFi { pub pass: String, } -// HELPERS AND ROUTES FOR /network/wifi/usage/reset +// HELPERS AND ROUTES FOR /settings/network/wifi/usage/reset -#[get("/network/wifi/usage/reset")] +#[get("/wifi/usage/reset")] pub fn wifi_usage_reset(_auth: Authenticated) -> Flash { let url = uri!(wifi_usage); match monitor::reset_data() { @@ -50,7 +50,7 @@ pub fn wifi_usage_reset(_auth: Authenticated) -> Flash { } } -#[post("/network/wifi/connect", data = "")] +#[post("/wifi/connect", data = "")] pub fn connect_wifi(network: Form, _auth: Authenticated) -> Flash { let ssid = &network.ssid; let url = uri!(network_detail(ssid = ssid)); @@ -63,7 +63,7 @@ pub fn connect_wifi(network: Form, _auth: Authenticated) -> Flash, _auth: Authenticated) -> Flash { let ssid = &network.ssid; let url = uri!(network_home); @@ -73,7 +73,7 @@ pub fn disconnect_wifi(network: Form, _auth: Authenticated) -> Flash, _auth: Authenticated) -> Flash { let ssid = &network.ssid; let url = uri!(network_home); @@ -86,10 +86,10 @@ pub fn forget_wifi(network: Form, _auth: Authenticated) -> Flash } } -#[get("/network/wifi/modify?")] +#[get("/wifi/modify?")] pub fn wifi_password(ssid: &str, flash: Option, _auth: Authenticated) -> Template { let mut context = NetworkAddContext { - back: Some("/network/wifi".to_string()), + back: Some("/settings/network/wifi".to_string()), flash_name: None, flash_msg: None, selected: Some(ssid.to_string()), @@ -102,10 +102,10 @@ pub fn wifi_password(ssid: &str, flash: Option, _auth: Authenticat context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_modify", &context) + Template::render("settings/network/network_modify", &context) } -#[post("/network/wifi/modify", data = "")] +#[post("/wifi/modify", data = "")] pub fn wifi_set_password(wifi: Form, _auth: Authenticated) -> Flash { let ssid = &wifi.ssid; let pass = &wifi.pass; @@ -119,7 +119,7 @@ pub fn wifi_set_password(wifi: Form, _auth: Authenticated) -> Flash, _auth: Authenticated) -> Template { // assign context through context_builder call let mut context = NetworkContext::build(); // set back button (nav) url - context.back = Some("/".to_string()); + context.back = Some("/settings".to_string()); // set page title context.title = Some("Network Configuration".to_string()); // check to see if there is a flash message to display @@ -288,25 +288,28 @@ pub fn network_home(flash: Option, _auth: Authenticated) -> Templa context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_card", &context) + Template::render("settings/network/network_card", &context) } -// HELPERS AND ROUTES FOR /network/ap/activate +// HELPERS AND ROUTES FOR /settings/network/ap/activate -#[get("/network/ap/activate")] +#[get("/ap/activate")] pub fn deploy_ap(_auth: Authenticated) -> Flash { // 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"), + Ok(_) => Flash::success( + Redirect::to("/settings/network"), + "Activated WiFi access point", + ), Err(_) => Flash::error( - Redirect::to("/network"), + Redirect::to("/settings/network"), "Failed to activate WiFi access point", ), } } -// HELPERS AND ROUTES FOR /network/wifi +// HELPERS AND ROUTES FOR /settings/network/wifi #[derive(Debug, Serialize)] pub struct NetworkListContext { @@ -375,11 +378,11 @@ impl NetworkListContext { } } -#[get("/network/wifi")] +#[get("/wifi")] pub fn wifi_list(flash: Option, _auth: Authenticated) -> Template { // assign context through context_builder call let mut context = NetworkListContext::build(); - context.back = Some("/network".to_string()); + context.back = Some("/settings/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 { @@ -388,10 +391,10 @@ pub fn wifi_list(flash: Option, _auth: Authenticated) -> Template context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_list", &context) + Template::render("settings/network/network_list", &context) } -// HELPERS AND ROUTES FOR /network/wifi +// HELPERS AND ROUTES FOR /settings/network/wifi #[derive(Debug, Serialize)] pub struct NetworkDetailContext { @@ -540,11 +543,11 @@ impl NetworkDetailContext { } } -#[get("/network/wifi?")] +#[get("/wifi?")] pub fn network_detail(ssid: &str, flash: Option, _auth: Authenticated) -> Template { // assign context through context_builder call let mut context = NetworkDetailContext::build(); - context.back = Some("/network/wifi".to_string()); + context.back = Some("/settings/network/wifi".to_string()); context.title = Some("WiFi Network".to_string()); context.selected = Some(ssid.to_string()); // check to see if there is a flash message to display @@ -554,28 +557,31 @@ pub fn network_detail(ssid: &str, flash: Option, _auth: Authentica context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_detail", &context) + Template::render("settings/network/network_detail", &context) } -// HELPERS AND ROUTES FOR /network/wifi/activate +// HELPERS AND ROUTES FOR /settings/network/wifi/activate -#[get("/network/wifi/activate")] +#[get("/wifi/activate")] pub fn deploy_client(_auth: Authenticated) -> Flash { // 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"), + Ok(_) => Flash::success(Redirect::to("/settings/network"), "Activated WiFi client"), + Err(_) => Flash::error( + Redirect::to("/settings/network"), + "Failed to activate WiFi client", + ), } } -// HELPERS AND ROUTES FOR /network/wifi/add +// HELPERS AND ROUTES FOR /settings/network/wifi/add -#[get("/network/wifi/add")] -pub fn network_add_wifi(flash: Option, _auth: Authenticated) -> Template { +#[get("/wifi/add")] +pub fn add_wifi(flash: Option, _auth: Authenticated) -> Template { let mut context = NetworkContext::build(); // set back icon link to network route - context.back = Some("/network".to_string()); + context.back = Some("/settings/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 { @@ -584,10 +590,10 @@ pub fn network_add_wifi(flash: Option, _auth: Authenticated) -> Te context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_add", &context) + Template::render("settings/network/network_add", &context) } -// used in /network/wifi/add? +// used in /settings/network/wifi/add? #[derive(Debug, Serialize)] pub struct NetworkAddContext { pub back: Option, @@ -609,10 +615,10 @@ impl NetworkAddContext { } } -#[get("/network/wifi/add?")] -pub fn network_add_ssid(ssid: &str, flash: Option, _auth: Authenticated) -> Template { +#[get("/wifi/add?")] +pub fn add_ssid(ssid: &str, flash: Option, _auth: Authenticated) -> Template { let mut context = NetworkAddContext::build(); - context.back = Some("/network/wifi".to_string()); + context.back = Some("/settings/network/wifi".to_string()); context.selected = Some(ssid.to_string()); context.title = Some("Add WiFi Network".to_string()); // check to see if there is a flash message to display @@ -622,10 +628,10 @@ pub fn network_add_ssid(ssid: &str, flash: Option, _auth: Authenti context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_add", &context) + Template::render("settings/network/network_add", &context) } -#[post("/network/wifi/add", data = "")] +#[post("/wifi/add", data = "")] pub fn add_credentials(wifi: Form, _auth: Authenticated) -> Template { // check if the credentials already exist for this access point // note: this is nicer but it's an unstable feature: @@ -634,13 +640,13 @@ pub fn add_credentials(wifi: Form, _auth: Authenticated) -> Template { 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.back = Some("/settings/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); + return Template::render("settings/network/network_add", &context); }; // if credentials not found, generate and write wifi config to wpa_supplicant @@ -653,20 +659,20 @@ pub fn add_credentials(wifi: Form, _auth: Authenticated) -> Template { Err(_) => warn!("Failed to reconfigure wpa_supplicant"), } let mut context = NetworkAddContext::build(); - context.back = Some("/network".to_string()); + context.back = Some("/settings/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) + Template::render("settings/network/network_add", &context) } Err(_) => { debug!("Failed to add WiFi credentials."); let mut context = NetworkAddContext::build(); - context.back = Some("/network".to_string()); + context.back = Some("/settings/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) + Template::render("settings/network/network_add", &context) } } } @@ -719,11 +725,11 @@ impl NetworkAlertContext { } } -#[get("/network/wifi/usage")] +#[get("/wifi/usage")] pub fn wifi_usage(flash: Option, _auth: Authenticated) -> Template { let mut context = NetworkAlertContext::build(); // set back icon link to network route - context.back = Some("/network".to_string()); + context.back = Some("/settings/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 { @@ -732,30 +738,32 @@ pub fn wifi_usage(flash: Option, _auth: Authenticated) -> Template context.flash_msg = Some(flash.message().to_string()); }; // template_dir is set in Rocket.toml - Template::render("network_usage", &context) + Template::render("settings/network/network_usage", &context) } -#[post("/network/wifi/usage", data = "")] +#[post("/wifi/usage", data = "")] pub fn wifi_usage_alerts(thresholds: Form, _auth: Authenticated) -> Flash { match monitor::update_store(thresholds.into_inner()) { Ok(_) => { debug!("WiFi data usage thresholds updated."); Flash::success( - Redirect::to("/network/wifi/usage"), + Redirect::to("/settings/network/wifi/usage"), "Updated alert thresholds and flags", ) } Err(_) => { warn!("Failed to update WiFi data usage thresholds."); Flash::error( - Redirect::to("/network/wifi/usage"), + Redirect::to("/settings/network/wifi/usage"), "Failed to update alert thresholds and flags", ) } } } -#[post("/api/v1/network/wifi/usage", data = "")] +// JSON ROUTES FOR NETWORK SETTINGS + +#[post("/wifi/usage", data = "")] pub fn update_wifi_alerts(thresholds: Json, _auth: Authenticated) -> Value { match monitor::update_store(thresholds.into_inner()) { Ok(_) => { @@ -773,7 +781,7 @@ pub fn update_wifi_alerts(thresholds: Json, _auth: Authenticated) -> } } -#[post("/api/v1/network/wifi/usage/reset")] +#[post("/wifi/usage/reset")] pub fn reset_data_total(_auth: Authenticated) -> Value { match monitor::reset_data() { Ok(_) => { @@ -805,7 +813,7 @@ pub fn reset_data_total(_auth: Authenticated) -> Value { // HELPERS AND ROUTES FOR ACCESS POINT ACTIVATION -#[post("/api/v1/network/activate_ap")] +#[post("/activate_ap")] pub fn activate_ap(_auth: Authenticated) -> Value { // activate the wireless access point debug!("Activating WiFi access point."); @@ -824,7 +832,7 @@ pub fn activate_ap(_auth: Authenticated) -> Value { // HELPERS AND ROUTES FOR WIFI CLIENT MANAGEMENT -#[post("/api/v1/network/activate_client")] +#[post("/activate_client")] pub fn activate_client(_auth: Authenticated) -> Value { // activate the wireless client debug!("Activating WiFi client mode."); @@ -841,8 +849,8 @@ pub fn activate_client(_auth: Authenticated) -> Value { } } -#[post("/api/v1/network/wifi", data = "")] -pub fn add_wifi(wifi: Json, _auth: Authenticated) -> Value { +#[post("/wifi", data = "")] +pub fn add_wifi_credentials(wifi: Json, _auth: Authenticated) -> Value { // generate and write wifi config to wpa_supplicant match network_client::add(&wifi.ssid, &wifi.pass) { Ok(_) => { @@ -867,7 +875,7 @@ pub fn add_wifi(wifi: Json, _auth: Authenticated) -> Value { } } -#[post("/api/v1/network/wifi/connect", data = "")] +#[post("/wifi/connect", data = "")] pub fn connect_ap(ssid: Json, _auth: Authenticated) -> Value { // retrieve the id for the given network ssid match network_client::id("wlan0", &ssid.ssid) { @@ -892,7 +900,7 @@ pub fn connect_ap(ssid: Json, _auth: Authenticated) -> Value { } } -#[post("/api/v1/network/wifi/disconnect", data = "")] +#[post("/wifi/disconnect", data = "")] pub fn disconnect_ap(ssid: Json, _auth: Authenticated) -> Value { // attempt to disable the current network for wlan0 interface match network_client::disable("wlan0", &ssid.ssid) { @@ -909,7 +917,7 @@ pub fn disconnect_ap(ssid: Json, _auth: Authenticated) -> Value { } } -#[post("/api/v1/network/wifi/forget", data = "")] +#[post("/wifi/forget", data = "")] pub fn forget_ap(network: Json, _auth: Authenticated) -> Value { let ssid = &network.ssid; match network_client::forget("wlan0", ssid) { @@ -928,7 +936,7 @@ pub fn forget_ap(network: Json, _auth: Authenticated) -> Value { } } -#[post("/api/v1/network/wifi/modify", data = "")] +#[post("/wifi/modify", data = "")] pub fn modify_password(wifi: Json, _auth: Authenticated) -> Value { let ssid = &wifi.ssid; let pass = &wifi.pass; @@ -953,7 +961,7 @@ pub fn modify_password(wifi: Json, _auth: Authenticated) -> Value { // HELPERS AND ROUTES FOR NETWORK STATE QUERIES -#[get("/api/v1/network/ip")] +#[get("/ip")] pub fn return_ip(_auth: Authenticated) -> Value { // retrieve ip for wlan0 or set to x.x.x.x if not found let wlan_ip = match network_client::ip("wlan0") { @@ -973,7 +981,7 @@ pub fn return_ip(_auth: Authenticated) -> Value { build_json_response(status, Some(data), None) } -#[get("/api/v1/network/rssi")] +#[get("/rssi")] pub fn return_rssi(_auth: Authenticated) -> Value { // retrieve rssi for connected network match network_client::rssi("wlan0") { @@ -990,7 +998,7 @@ pub fn return_rssi(_auth: Authenticated) -> Value { } } -#[get("/api/v1/network/ssid")] +#[get("/ssid")] pub fn return_ssid(_auth: Authenticated) -> Value { // retrieve ssid for connected network match network_client::ssid("wlan0") { @@ -1007,7 +1015,7 @@ pub fn return_ssid(_auth: Authenticated) -> Value { } } -#[get("/api/v1/network/state")] +#[get("/state")] pub fn return_state(_auth: Authenticated) -> Value { // retrieve state of wlan0 or set to x.x.x.x if not found let wlan_state = match network_client::state("wlan0") { @@ -1027,7 +1035,7 @@ pub fn return_state(_auth: Authenticated) -> Value { build_json_response(status, Some(data), None) } -#[get("/api/v1/network/status")] +#[get("/status")] pub fn return_status(_auth: Authenticated) -> Value { // retrieve status info for wlan0 interface match network_client::status("wlan0") { @@ -1044,7 +1052,7 @@ pub fn return_status(_auth: Authenticated) -> Value { } } -#[get("/api/v1/network/wifi")] +#[get("/wifi")] pub fn scan_networks(_auth: Authenticated) -> Value { // retrieve scan results for access-points within range of wlan0 match network_client::available_networks("wlan0") { diff --git a/peach-web/src/routes/settings/scuttlebutt.rs b/peach-web/src/routes/settings/scuttlebutt.rs new file mode 100644 index 0000000..bd1a129 --- /dev/null +++ b/peach-web/src/routes/settings/scuttlebutt.rs @@ -0,0 +1,41 @@ +use rocket::{get, request::FlashMessage, serde::Serialize}; +use rocket_dyn_templates::Template; + +use crate::routes::authentication::Authenticated; + +// HELPERS AND ROUTES FOR /settings/scuttlebutt + +#[derive(Debug, Serialize)] +pub struct ScuttlebuttSettingsContext { + pub back: Option, + pub title: Option, + pub flash_name: Option, + pub flash_msg: Option, +} + +impl ScuttlebuttSettingsContext { + pub fn build() -> ScuttlebuttSettingsContext { + ScuttlebuttSettingsContext { + back: None, + title: None, + flash_name: None, + flash_msg: None, + } + } +} + +/// Scuttlebutt settings menu. +#[get("/")] +pub fn ssb_settings_menu(flash: Option, _auth: Authenticated) -> Template { + let mut context = ScuttlebuttSettingsContext::build(); + // set back icon link to network route + context.back = Some("/settings".to_string()); + context.title = Some("Scuttlebutt Settings".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.kind().to_string()); + context.flash_msg = Some(flash.message().to_string()); + }; + Template::render("settings/scuttlebutt", &context) +} diff --git a/peach-web/src/routes/device.rs b/peach-web/src/routes/status/device.rs similarity index 86% rename from peach-web/src/routes/device.rs rename to peach-web/src/routes/status/device.rs index d06983b..f67c9aa 100644 --- a/peach-web/src/routes/device.rs +++ b/peach-web/src/routes/status/device.rs @@ -16,15 +16,15 @@ use peach_lib::config_manager::load_peach_config; use peach_lib::stats_client::{CpuStatPercentages, DiskUsage, LoadAverage, MemStat}; use peach_lib::{dyndns_client, network_client, oled_client, sbot_client, stats_client}; -use crate::utils::build_json_response; use crate::routes::authentication::Authenticated; +use crate::utils::build_json_response; use rocket::serde::json::Value; -// HELPERS AND ROUTES FOR /device +// HELPERS AND ROUTES FOR /status /// System statistics data. #[derive(Debug, Serialize)] -pub struct DeviceContext { +pub struct StatusContext { pub back: Option, pub cpu_stat_percent: Option, pub disk_stats: Vec, @@ -43,8 +43,8 @@ pub struct DeviceContext { pub uptime: Option, } -impl DeviceContext { - pub fn build() -> DeviceContext { +impl StatusContext { + pub fn build() -> StatusContext { // convert result to Option, discard any error let cpu_stat_percent = stats_client::cpu_stats_percent().ok(); let load_average = stats_client::load_average().ok(); @@ -129,7 +129,7 @@ impl DeviceContext { } } - DeviceContext { + StatusContext { back: None, cpu_stat_percent, disk_stats, @@ -150,10 +150,10 @@ impl DeviceContext { } } -#[get("/device")] -pub fn device_stats(flash: Option, _auth: Authenticated) -> Template { +#[get("/status")] +pub fn device_status(flash: Option, _auth: Authenticated) -> Template { // assign context through context_builder call - let mut context = DeviceContext::build(); + let mut context = StatusContext::build(); context.back = Some("/".to_string()); context.title = Some("Device Status".to_string()); // check to see if there is a flash message to display @@ -166,7 +166,7 @@ pub fn device_stats(flash: Option, _auth: Authenticated) -> Templa Template::render("device", &context) } -// HELPERS AND ROUTES FOR /device/reboot +// HELPERS AND ROUTES FOR /power/reboot /// Executes a system command to reboot the device immediately. pub fn reboot() -> io::Result { @@ -181,16 +181,16 @@ pub fn reboot() -> io::Result { .output() } -#[get("/device/reboot")] +#[get("/power/reboot")] pub fn reboot_cmd(_auth: Authenticated) -> Flash { match reboot() { - Ok(_) => Flash::success(Redirect::to("/shutdown"), "Rebooting the device"), - Err(_) => Flash::error(Redirect::to("/shutdown"), "Failed to reboot the device"), + Ok(_) => Flash::success(Redirect::to("/power"), "Rebooting the device"), + Err(_) => Flash::error(Redirect::to("/power"), "Failed to reboot the device"), } } /// JSON request handler for device reboot. -#[post("/api/v1/device/reboot")] +#[post("/api/v1/admin/reboot")] pub fn reboot_device(_auth: Authenticated) -> Value { match reboot() { Ok(_) => { @@ -208,7 +208,7 @@ pub fn reboot_device(_auth: Authenticated) -> Value { } } -// HELPERS AND ROUTES FOR /device/shutdown +// HELPERS AND ROUTES FOR /power/shutdown /// Executes a system command to shutdown the device immediately. pub fn shutdown() -> io::Result { @@ -219,16 +219,16 @@ pub fn shutdown() -> io::Result { Command::new("sudo").arg("shutdown").arg("now").output() } -#[get("/device/shutdown")] +#[get("/power/shutdown")] pub fn shutdown_cmd(_auth: Authenticated) -> Flash { match shutdown() { - Ok(_) => Flash::success(Redirect::to("/shutdown"), "Shutting down the device"), - Err(_) => Flash::error(Redirect::to("/shutdown"), "Failed to shutdown the device"), + Ok(_) => Flash::success(Redirect::to("/power"), "Shutting down the device"), + Err(_) => Flash::error(Redirect::to("/power"), "Failed to shutdown the device"), } } // shutdown the device -#[post("/api/v1/device/shutdown")] +#[post("/power/shutdown")] pub fn shutdown_device(_auth: Authenticated) -> Value { match shutdown() { Ok(_) => { @@ -246,19 +246,19 @@ pub fn shutdown_device(_auth: Authenticated) -> Value { } } -// HELPERS AND ROUTES FOR /shutdown +// HELPERS AND ROUTES FOR /power #[derive(Debug, Serialize)] -pub struct ShutdownContext { +pub struct PowerContext { pub back: Option, pub flash_name: Option, pub flash_msg: Option, pub title: Option, } -impl ShutdownContext { - pub fn build() -> ShutdownContext { - ShutdownContext { +impl PowerContext { + pub fn build() -> PowerContext { + PowerContext { back: None, flash_name: None, flash_msg: None, @@ -267,16 +267,16 @@ impl ShutdownContext { } } -#[get("/shutdown")] -pub fn shutdown_menu(flash: Option, _auth: Authenticated) -> Template { - let mut context = ShutdownContext::build(); +#[get("/power")] +pub fn power_menu(flash: Option, _auth: Authenticated) -> Template { + let mut context = PowerContext::build(); context.back = Some("/".to_string()); - context.title = Some("Shutdown Device".to_string()); + context.title = Some("Power Menu".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.kind().to_string()); context.flash_msg = Some(flash.message().to_string()); }; - Template::render("shutdown", &context) + Template::render("power", &context) } diff --git a/peach-web/src/routes/status/mod.rs b/peach-web/src/routes/status/mod.rs new file mode 100644 index 0000000..cd4d59c --- /dev/null +++ b/peach-web/src/routes/status/mod.rs @@ -0,0 +1,2 @@ +pub mod device; +pub mod ping; diff --git a/peach-web/src/routes/ping.rs b/peach-web/src/routes/status/ping.rs similarity index 93% rename from peach-web/src/routes/ping.rs rename to peach-web/src/routes/status/ping.rs index aed39ec..3f83002 100644 --- a/peach-web/src/routes/ping.rs +++ b/peach-web/src/routes/status/ping.rs @@ -1,19 +1,19 @@ //! Helper routes for pinging services to check that they are active use log::{debug, warn}; use rocket::get; -use rocket::serde::json::{Value}; +use rocket::serde::json::Value; use peach_lib::network_client; use peach_lib::oled_client; use peach_lib::stats_client; -use crate::utils::build_json_response; use crate::routes::authentication::Authenticated; +use crate::utils::build_json_response; /// Status route: useful for checking connectivity from web client. -#[get("/api/v1/ping")] +#[get("/ping")] pub fn ping_pong(_auth: Authenticated) -> Value { -//pub fn ping_pong() -> Value { + //pub fn ping_pong() -> Value { // ping pong let status = "success".to_string(); let msg = "pong!".to_string(); @@ -21,7 +21,7 @@ pub fn ping_pong(_auth: Authenticated) -> Value { } /// Status route: check availability of `peach-network` microservice. -#[get("/api/v1/ping/network")] +#[get("/ping/network")] pub fn ping_network(_auth: Authenticated) -> Value { match network_client::ping() { Ok(_) => { @@ -40,7 +40,7 @@ pub fn ping_network(_auth: Authenticated) -> Value { } /// Status route: check availability of `peach-oled` microservice. -#[get("/api/v1/ping/oled")] +#[get("/ping/oled")] pub fn ping_oled(_auth: Authenticated) -> Value { match oled_client::ping() { Ok(_) => { @@ -59,7 +59,7 @@ pub fn ping_oled(_auth: Authenticated) -> Value { } /// Status route: check availability of `peach-stats` microservice. -#[get("/api/v1/ping/stats")] +#[get("/ping/stats")] pub fn ping_stats(_auth: Authenticated) -> Value { match stats_client::ping() { Ok(_) => { diff --git a/peach-web/src/tests.rs b/peach-web/src/tests.rs index 931af3e..251de09 100644 --- a/peach-web/src/tests.rs +++ b/peach-web/src/tests.rs @@ -47,15 +47,15 @@ fn index_html() { assert!(body.contains("/peers")); assert!(body.contains("/profile")); assert!(body.contains("/private")); - assert!(body.contains("/device")); + assert!(body.contains("/status")); assert!(body.contains("/help")); - assert!(body.contains("/network")); + assert!(body.contains("/settings")); } #[test] fn network_card_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network").dispatch(); + let response = client.get("/settings/network").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -73,7 +73,7 @@ fn network_card_html() { #[test] fn network_list_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/wifi").dispatch(); + let response = client.get("/settings/network/wifi").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -85,7 +85,7 @@ fn network_list_html() { #[test] fn network_detail_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/wifi?ssid=Home").dispatch(); + let response = client.get("/settings/network/wifi?ssid=Home").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); //let body = response.into_string().unwrap(); @@ -95,7 +95,7 @@ fn network_detail_html() { #[test] fn network_add_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/wifi/add").dispatch(); + let response = client.get("/settings/network/wifi/add").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -109,7 +109,9 @@ fn network_add_html() { #[test] fn network_add_ssid_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/wifi/add?ssid=Home").dispatch(); + let response = client + .get("/settings/network/wifi/add?ssid=Home") + .dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -121,9 +123,9 @@ fn network_add_ssid_html() { } #[test] -fn device_html() { +fn status_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/device").dispatch(); + let response = client.get("/status").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -269,9 +271,9 @@ fn profile_html() { } #[test] -fn shutdown_html() { +fn power_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/shutdown").dispatch(); + let response = client.get("/power").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -281,7 +283,7 @@ fn shutdown_html() { #[test] fn network_usage_html() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/wifi/usage").dispatch(); + let response = client.get("/settings/network/wifi/usage").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::HTML)); let body = response.into_string().unwrap(); @@ -295,7 +297,7 @@ fn network_usage_html() { fn add_credentials() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); let response = client - .post("/network/wifi/add") + .post("/settings/network/wifi/add") .header(ContentType::Form) .body("ssid=Home&pass=Password") .dispatch(); @@ -307,7 +309,7 @@ fn add_credentials() { fn forget_wifi() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); let response = client - .post("/network/wifi/forget") + .post("/settings/network/wifi/forget") .header(ContentType::Form) .body("ssid=Home") .dispatch(); @@ -319,7 +321,7 @@ fn forget_wifi() { fn modify_password() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); let response = client - .post("/network/wifi/modify") + .post("/settings/network/wifi/modify") .header(ContentType::Form) .body("ssid=Home&pass=Password") .dispatch(); @@ -330,7 +332,7 @@ fn modify_password() { #[test] fn deploy_ap() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/ap/activate").dispatch(); + let response = client.get("/settings/network/ap/activate").dispatch(); // check for 303 status (redirect) assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.content_type(), None); @@ -339,7 +341,7 @@ fn deploy_ap() { #[test] fn deploy_client() { let client = Client::tracked(init_rocket()).expect("valid rocket instance"); - let response = client.get("/network/wifi/activate").dispatch(); + let response = client.get("/settings/network/wifi/activate").dispatch(); // check for 303 status (redirect) assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.content_type(), None); diff --git a/peach-web/static/icons/clipboard.png b/peach-web/static/icons/clipboard.png new file mode 100644 index 0000000..642db7b Binary files /dev/null and b/peach-web/static/icons/clipboard.png differ diff --git a/peach-web/static/icons/dns.png b/peach-web/static/icons/dns.png new file mode 100644 index 0000000..568bf3c Binary files /dev/null and b/peach-web/static/icons/dns.png differ diff --git a/peach-web/static/icons/hermies.svg b/peach-web/static/icons/hermies.svg new file mode 100644 index 0000000..490f67f --- /dev/null +++ b/peach-web/static/icons/hermies.svg @@ -0,0 +1,57 @@ + + + + + + + + + + diff --git a/peach-web/static/icons/power-switch.svg b/peach-web/static/icons/power.svg similarity index 100% rename from peach-web/static/icons/power-switch.svg rename to peach-web/static/icons/power.svg diff --git a/peach-web/static/js/change_password.js b/peach-web/static/js/change_password.js index 9361d56..85bc2b1 100644 --- a/peach-web/static/js/change_password.js +++ b/peach-web/static/js/change_password.js @@ -23,7 +23,7 @@ PEACH.add = function() { // write in-progress status message to ui PEACH.flashMsg("info", "Saving new password."); // send add_wifi POST request - fetch("/api/v1/settings/change_password", { + fetch("/api/v1/admin/change_password", { method: "post", headers: { 'Content-Type': 'application/json', diff --git a/peach-web/static/js/configure_dns.js b/peach-web/static/js/configure_dns.js index 835be63..8abef30 100644 --- a/peach-web/static/js/configure_dns.js +++ b/peach-web/static/js/configure_dns.js @@ -38,7 +38,7 @@ PEACH_DNS.add = function() { // write in-progress status message to ui PEACH_DNS.flashMsg("info", "Saving new DNS configurations"); // send add_wifi POST request - fetch("/api/v1/dns/configure", { + fetch("/api/v1/network/dns/configure", { method: "post", headers: { 'Content-Type': 'application/json', diff --git a/peach-web/static/js/shutdown_menu.js b/peach-web/static/js/power_menu.js similarity index 95% rename from peach-web/static/js/shutdown_menu.js rename to peach-web/static/js/power_menu.js index 0d40dff..91e22e0 100644 --- a/peach-web/static/js/shutdown_menu.js +++ b/peach-web/static/js/power_menu.js @@ -1,7 +1,7 @@ /* -behavioural layer for the `shutdown.html.tera` template, -corresponding to the web route `/shutdown` +behavioural layer for the `power.html.tera` template, +corresponding to the web route `/power` - intercept button clicks for reboot & shutdown - perform json api calls @@ -28,7 +28,7 @@ PEACH_DEVICE.reboot = function() { // write reboot flash message PEACH_DEVICE.flashMsg("success", "Rebooting the device..."); // send reboot_device POST request - fetch("/api/v1/device/reboot", { + fetch("/api/v1/admin/reboot", { method: "post", headers: { 'Accept': 'application/json', @@ -59,7 +59,7 @@ PEACH_DEVICE.shutdown = function() { // write shutdown flash message PEACH_DEVICE.flashMsg("success", "Shutting down the device..."); // send shutdown_device POST request - fetch("/api/v1/device/shutdown", { + fetch("/api/v1/shutdown", { method: "post", headers: { 'Accept': 'application/json', diff --git a/peach-web/static/js/reset_password.js b/peach-web/static/js/reset_password.js index 1b4eb09..bf1c2ec 100644 --- a/peach-web/static/js/reset_password.js +++ b/peach-web/static/js/reset_password.js @@ -23,7 +23,7 @@ PEACH.add = function() { // write in-progress status message to ui PEACH.flashMsg("info", "Saving new password."); // send add_wifi POST request - fetch("/public/api/v1/reset_password", { + fetch("/api/v1/admin/reset_password", { method: "post", headers: { 'Content-Type': 'application/json', diff --git a/peach-web/templates/internal_error.html.tera b/peach-web/templates/catchers/internal_error.html.tera similarity index 100% rename from peach-web/templates/internal_error.html.tera rename to peach-web/templates/catchers/internal_error.html.tera diff --git a/peach-web/templates/not_found.html.tera b/peach-web/templates/catchers/not_found.html.tera similarity index 100% rename from peach-web/templates/not_found.html.tera rename to peach-web/templates/catchers/not_found.html.tera diff --git a/peach-web/templates/device.html.tera b/peach-web/templates/device.html.tera index 9b31333..96d1cc7 100644 --- a/peach-web/templates/device.html.tera +++ b/peach-web/templates/device.html.tera @@ -25,7 +25,7 @@
- Network + Network
@@ -33,7 +33,7 @@
- Display + Display
@@ -41,7 +41,7 @@
- Stats + Stats
@@ -51,7 +51,7 @@
- Dyndns + Dyndns
@@ -59,7 +59,7 @@
- Config + Config
@@ -67,7 +67,7 @@
- Sbot + Sbot
diff --git a/peach-web/templates/index.html.tera b/peach-web/templates/home.html.tera similarity index 73% rename from peach-web/templates/index.html.tera rename to peach-web/templates/home.html.tera index b7142ae..14edce6 100644 --- a/peach-web/templates/index.html.tera +++ b/peach-web/templates/home.html.tera @@ -6,21 +6,21 @@
- +
- +
- +
@@ -30,23 +30,23 @@ - +
- +
- +
- +
- +
diff --git a/peach-web/templates/login.html.tera b/peach-web/templates/login.html.tera index 072e5fb..504b242 100644 --- a/peach-web/templates/login.html.tera +++ b/peach-web/templates/login.html.tera @@ -17,7 +17,7 @@ {% include "snippets/flash_message" %}
diff --git a/peach-web/templates/nav.html.tera b/peach-web/templates/nav.html.tera index 33c50e7..e89e50a 100644 --- a/peach-web/templates/nav.html.tera +++ b/peach-web/templates/nav.html.tera @@ -22,8 +22,8 @@ PeachCloud - - Question mark + + Power switch {%- endblock nav -%} diff --git a/peach-web/templates/shutdown.html.tera b/peach-web/templates/power.html.tera similarity index 77% rename from peach-web/templates/shutdown.html.tera rename to peach-web/templates/power.html.tera index 12b450c..ffd0a1e 100644 --- a/peach-web/templates/shutdown.html.tera +++ b/peach-web/templates/power.html.tera @@ -5,8 +5,8 @@
@@ -15,5 +15,5 @@ {% include "snippets/noscript" %}
- + {%- endblock card -%} diff --git a/peach-web/templates/messages.html.tera b/peach-web/templates/scuttlebutt/messages.html.tera similarity index 100% rename from peach-web/templates/messages.html.tera rename to peach-web/templates/scuttlebutt/messages.html.tera diff --git a/peach-web/templates/peers.html.tera b/peach-web/templates/scuttlebutt/peers.html.tera similarity index 100% rename from peach-web/templates/peers.html.tera rename to peach-web/templates/scuttlebutt/peers.html.tera diff --git a/peach-web/templates/peers_list.html.tera b/peach-web/templates/scuttlebutt/peers_list.html.tera similarity index 100% rename from peach-web/templates/peers_list.html.tera rename to peach-web/templates/scuttlebutt/peers_list.html.tera diff --git a/peach-web/templates/profile.html.tera b/peach-web/templates/scuttlebutt/profile.html.tera similarity index 100% rename from peach-web/templates/profile.html.tera rename to peach-web/templates/scuttlebutt/profile.html.tera diff --git a/peach-web/templates/admin/add_admin.html.tera b/peach-web/templates/settings/admin/add_admin.html.tera similarity index 94% rename from peach-web/templates/admin/add_admin.html.tera rename to peach-web/templates/settings/admin/add_admin.html.tera index a99badb..5c04908 100644 --- a/peach-web/templates/admin/add_admin.html.tera +++ b/peach-web/templates/settings/admin/add_admin.html.tera @@ -7,7 +7,7 @@ diff --git a/peach-web/templates/password/change_password.html.tera b/peach-web/templates/settings/admin/change_password.html.tera similarity index 100% rename from peach-web/templates/password/change_password.html.tera rename to peach-web/templates/settings/admin/change_password.html.tera diff --git a/peach-web/templates/admin/configure_admin.html.tera b/peach-web/templates/settings/admin/configure_admin.html.tera similarity index 100% rename from peach-web/templates/admin/configure_admin.html.tera rename to peach-web/templates/settings/admin/configure_admin.html.tera diff --git a/peach-web/templates/password/forgot_password.html.tera b/peach-web/templates/settings/admin/forgot_password.html.tera similarity index 100% rename from peach-web/templates/password/forgot_password.html.tera rename to peach-web/templates/settings/admin/forgot_password.html.tera diff --git a/peach-web/templates/settings/admin/menu.html.tera b/peach-web/templates/settings/admin/menu.html.tera new file mode 100644 index 0000000..98716a3 --- /dev/null +++ b/peach-web/templates/settings/admin/menu.html.tera @@ -0,0 +1,13 @@ +{%- extends "nav" -%} +{%- block card %} + + +{%- endblock card -%} diff --git a/peach-web/templates/password/reset_password.html.tera b/peach-web/templates/settings/admin/reset_password.html.tera similarity index 100% rename from peach-web/templates/password/reset_password.html.tera rename to peach-web/templates/settings/admin/reset_password.html.tera diff --git a/peach-web/templates/settings.html.tera b/peach-web/templates/settings/menu.html.tera similarity index 100% rename from peach-web/templates/settings.html.tera rename to peach-web/templates/settings/menu.html.tera diff --git a/peach-web/templates/configure_dns.html.tera b/peach-web/templates/settings/network/configure_dns.html.tera similarity index 97% rename from peach-web/templates/configure_dns.html.tera rename to peach-web/templates/settings/network/configure_dns.html.tera index 019bc5b..b9ceb84 100644 --- a/peach-web/templates/configure_dns.html.tera +++ b/peach-web/templates/settings/network/configure_dns.html.tera @@ -18,7 +18,7 @@
{% endif %} -
+
{% include "snippets/flash_message" %} @@ -38,14 +38,14 @@
- Digital devices + Digital devices
- Download + Download
{%- if ap_traffic -%} @@ -58,7 +58,7 @@
- Upload + Upload
{%- if ap_traffic -%} @@ -83,12 +83,12 @@
- WiFi online + WiFi online {%- else %}
- WiFi offline + WiFi offline {%- endif %}
@@ -105,13 +105,13 @@
{% include "snippets/flash_message" %} @@ -120,14 +120,14 @@
- Signal + Signal
- Download + Download
{%- if wlan_traffic %} @@ -142,7 +142,7 @@
- Upload + Upload
{%- if wlan_traffic %} diff --git a/peach-web/templates/network_detail.html.tera b/peach-web/templates/settings/network/network_detail.html.tera similarity index 86% rename from peach-web/templates/network_detail.html.tera rename to peach-web/templates/settings/network/network_detail.html.tera index c58b5de..1839687 100644 --- a/peach-web/templates/network_detail.html.tera +++ b/peach-web/templates/settings/network/network_detail.html.tera @@ -29,7 +29,7 @@
{%- if wlan_ssid == selected -%} -
+ @@ -44,14 +44,14 @@ {# Set 'in_list' to true to allow correct Add button display #} {% set_global in_list = true %} {%- if wlan_ssid != selected and ap.state == "Available" -%} - +
{%- endif -%} - Modify -
+ Modify + @@ -61,9 +61,9 @@ {%- endif -%} {%- if in_list == false -%} {# Display the Add button if AP creds not already in saved networks list #} - Add + Add {%- endif -%} - Cancel + Cancel
{% include "snippets/flash_message" %} diff --git a/peach-web/templates/network_list.html.tera b/peach-web/templates/settings/network/network_list.html.tera similarity index 86% rename from peach-web/templates/network_list.html.tera rename to peach-web/templates/settings/network/network_list.html.tera index 45d8227..852af77 100644 --- a/peach-web/templates/network_list.html.tera +++ b/peach-web/templates/settings/network/network_list.html.tera @@ -9,19 +9,19 @@ {%- for ssid, state in wlan_networks %}
  • {%- if ssid == wlan_ssid %} - + WiFi online

    {{ wlan_ssid }}

    {%- elif state == "Available" %} - + WiFi offline

    {{ ssid }}

    {%- else %} - + WiFi offline

    {{ ssid }}

    diff --git a/peach-web/templates/network_modify.html.tera b/peach-web/templates/settings/network/network_modify.html.tera similarity index 89% rename from peach-web/templates/network_modify.html.tera rename to peach-web/templates/settings/network/network_modify.html.tera index 3c9b18c..43cf19f 100644 --- a/peach-web/templates/network_modify.html.tera +++ b/peach-web/templates/settings/network/network_modify.html.tera @@ -3,14 +3,14 @@
    - + diff --git a/peach-web/templates/network_usage.html.tera b/peach-web/templates/settings/network/network_usage.html.tera similarity index 90% rename from peach-web/templates/network_usage.html.tera rename to peach-web/templates/settings/network/network_usage.html.tera index 2c0ac65..0d4dec1 100644 --- a/peach-web/templates/network_usage.html.tera +++ b/peach-web/templates/settings/network/network_usage.html.tera @@ -1,7 +1,7 @@ {%- extends "nav" -%} {%- block card -%} -
    +
    @@ -37,8 +37,8 @@
    {% include "snippets/flash_message" %} diff --git a/peach-web/templates/ssb_settings.html.tera b/peach-web/templates/settings/scuttlebutt.html.tera similarity index 100% rename from peach-web/templates/ssb_settings.html.tera rename to peach-web/templates/settings/scuttlebutt.html.tera