Refactor route and template organisation #28

Merged
glyph merged 16 commits from route_reorganisation into main 2021-11-16 07:43:38 +00:00
51 changed files with 602 additions and 441 deletions

View File

@ -12,62 +12,30 @@ The peach-web stack currently consists of [Rocket](https://rocket.rs/) (Rust web
_Note: This is a work-in-progress._ _Note: This is a work-in-progress._
### WEB ROUTES (`src/routes.rs`) ### Setup
| Endpoint | Method | Parameters | Description | Clone the `peach-workspace` repo:
| --- | --- | --- | --- |
| `/` | 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?<ssid>` | 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?<ssid>` | 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 |
### 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 | `cd peach-workspace/peach-web`
| --- | --- | --- | --- | `cargo build --release`
| `device/reboot` | POST | | Reboot device |
| `device/shutdown` | POST | | Shutdown device | Run the tests:
| `network/activate_ap` | POST | | Activate WiFi access point mode |
| `network/activate_client` | POST | | Activate WiFi client mode | `cargo test`
| `network/ip` | GET | | Returns IP address values for wlan0 & ap0 interfaces |
| `network/rssi` | GET | | Returns RSSI for connected WiFi network | Move back to the `peach-workspace` directory:
| `network/ssid` | GET | | Returns SSID for connected WiFi network |
| `network/state` | GET | | Returns state of wlan0 & ap0 interfaces | `cd ..`
| `network/status` | GET | | Returns status object for connected WiFi network |
| `network/wifi` | GET | | Returns scan results for in-range access-points | Run the binary:
| `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 | `./target/release/peach-web`
| `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 | _Note: Networking functionality requires peach-network microservice to be running._
| `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 |
### Environment ### Environment
@ -75,13 +43,7 @@ The web application deployment mode is configured with the `ROCKET_ENV` environm
`export ROCKET_ENV=stage` `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. 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.
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`.
Logging is made available with `env_logger`: 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`. 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 ### 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. 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 ### 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 ### Licensing

View File

@ -38,100 +38,124 @@ use rocket_dyn_templates::Template;
use crate::routes::authentication::*; use crate::routes::authentication::*;
use crate::routes::catchers::*; use crate::routes::catchers::*;
use crate::routes::device::*;
use crate::routes::index::*; use crate::routes::index::*;
use crate::routes::ping::*;
use crate::routes::scuttlebutt::*; use crate::routes::scuttlebutt::*;
use crate::routes::status::device::*;
use crate::routes::status::ping::*;
use crate::routes::settings::admin::*; use crate::routes::settings::admin::*;
use crate::routes::settings::dns::*; use crate::routes::settings::dns::*;
use crate::routes::settings::menu::*;
use crate::routes::settings::network::*; use crate::routes::settings::network::*;
use crate::routes::settings::scuttlebutt::*;
pub type BoxError = Box<dyn std::error::Error>; pub type BoxError = Box<dyn std::error::Error>;
/// Create rocket instance & mount all routes. /// Create rocket instance & mount all routes.
fn init_rocket() -> Rocket<Build> { fn init_rocket() -> Rocket<Build> {
rocket::build() rocket::build()
.mount( // GENERAL HTML ROUTES
"/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
],
)
.mount( .mount(
"/", "/",
routes![ routes![
add_credentials, // WEB ROUTE device_status,
connect_wifi, // WEB ROUTE help,
disconnect_wifi, // WEB ROUTE home,
deploy_ap, // WEB ROUTE login,
deploy_client, // WEB ROUTE login_post,
device_stats, // WEB ROUTE logout,
forget_wifi, // WEB ROUTE reboot_cmd,
help, // WEB ROUTE shutdown_cmd,
index, // WEB ROUTE power_menu,
login, // WEB ROUTE settings_menu,
login_post, // WEB ROUTE ],
logout, // WEB ROUTE )
network_home, // WEB ROUTE // ADMIN SETTINGS HTML ROUTES
network_add_ssid, // WEB ROUTE .mount(
network_add_wifi, // WEB ROUTE "/settings/admin",
network_detail, // WEB ROUTE routes![
reboot_cmd, // WEB ROUTE admin_menu,
shutdown_cmd, // WEB ROUTE configure_admin,
shutdown_menu, // WEB ROUTE add_admin,
wifi_list, // WEB ROUTE add_admin_post,
wifi_password, // WEB ROUTE delete_admin_post,
wifi_set_password, // WEB ROUTE change_password,
wifi_usage, // WEB ROUTE change_password_post,
wifi_usage_alerts, // WEB ROUTE reset_password,
wifi_usage_reset, // WEB ROUTE reset_password_post,
configure_dns, // WEB ROUTE forgot_password_page,
configure_dns_post, // WEB ROUTE send_password_reset_post,
change_password, // WEB ROUTE ],
change_password_post, // WEB ROUTE )
reset_password, // WEB ROUTE // NETWORK SETTINGS HTML ROUTES
reset_password_post, // WEB ROUTE .mount(
forgot_password_page, // WEB ROUTE "/settings/network",
send_password_reset_post, // WEB ROUTE routes![
configure_admin, // WEB ROUTE add_credentials,
add_admin, // WEB ROUTE connect_wifi,
add_admin_post, // WEB ROUTE configure_dns,
delete_admin_post, // WEB ROUTE configure_dns_post,
activate_ap, // JSON API disconnect_wifi,
activate_client, // JSON API deploy_ap,
add_wifi, // JSON API deploy_client,
connect_ap, // JSON API forget_wifi,
disconnect_ap, // JSON API network_home,
forget_ap, // JSON API add_ssid,
modify_password, // JSON API add_wifi,
ping_pong, // JSON API network_detail,
ping_network, // JSON API wifi_list,
ping_oled, // JSON API wifi_password,
ping_stats, // JSON API wifi_set_password,
reset_data_total, // JSON API wifi_usage,
return_ip, // JSON API wifi_usage_alerts,
return_rssi, // JSON API wifi_usage_reset,
return_ssid, // JSON API ],
return_state, // JSON API )
return_status, // JSON API // SCUTTLEBUTT SETTINGS HTML ROUTES
reboot_device, // JSON API .mount("/settings/scuttlebutt", routes![ssb_settings_menu])
scan_networks, // JSON API // SCUTTLEBUTT SOCIAL HTML ROUTES
shutdown_device, // JSON API .mount(
update_wifi_alerts, // JSON API "/scuttlebutt",
save_dns_configuration_endpoint, // JSON API routes![
save_password_form_endpoint, // JSON API peers, friends, follows, followers, blocks, profile, private, follow, unfollow,
reset_password_form_endpoint, // JSON API 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")) .mount("/", FileServer::from("static"))

View File

@ -1,23 +1,20 @@
use log::{info}; use log::info;
use rocket::request::{FlashMessage};
use rocket::form::{Form, FromForm}; use rocket::form::{Form, FromForm};
use rocket::request::FlashMessage;
use rocket::response::{Flash, Redirect}; use rocket::response::{Flash, Redirect};
use rocket::{get, post};
use rocket::serde::json::Json; use rocket::serde::json::Json;
use rocket_dyn_templates::Template;
use rocket::serde::{Deserialize, Serialize}; 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::error::PeachError;
use peach_lib::password_utils;
use crate::error::PeachWebError; use crate::error::PeachWebError;
use crate::utils::{build_json_response, TemplateOrRedirect}; 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::request::{self, FromRequest, Request};
use rocket::http::{Cookie, CookieJar, Status}; use rocket::serde::json::Value;
// HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES // HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES
@ -32,7 +29,7 @@ pub struct Authenticated;
#[derive(Debug)] #[derive(Debug)]
pub enum LoginError { pub enum LoginError {
UserNotLoggedIn UserNotLoggedIn,
} }
/// Request guard which returns an empty Authenticated struct from the request /// Request guard which returns an empty Authenticated struct from the request
@ -49,14 +46,10 @@ impl<'r> FromRequest<'r> for Authenticated {
.cookies() .cookies()
.get_private(AUTH_COOKIE_KEY) .get_private(AUTH_COOKIE_KEY)
.and_then(|cookie| cookie.value().parse().ok()) .and_then(|cookie| cookie.value().parse().ok())
.map(|_value: String| { Authenticated { } }); .map(|_value: String| Authenticated {});
match authenticated { match authenticated {
Some(auth) => { Some(auth) => request::Outcome::Success(auth),
request::Outcome::Success(auth) None => request::Outcome::Failure((Status::Forbidden, LoginError::UserNotLoggedIn)),
},
None => {
request::Outcome::Failure((Status::Forbidden, LoginError::UserNotLoggedIn))
}
} }
} }
} }
@ -96,7 +89,6 @@ pub fn login(flash: Option<FlashMessage>) -> Template {
Template::render("login", &context) Template::render("login", &context)
} }
#[derive(Debug, Deserialize, FromForm)] #[derive(Debug, Deserialize, FromForm)]
pub struct LoginForm { pub struct LoginForm {
pub username: String, pub username: String,
@ -112,7 +104,7 @@ pub fn verify_login_form(login_form: LoginForm) -> Result<(), PeachError> {
password_utils::verify_password(&login_form.password) password_utils::verify_password(&login_form.password)
} }
#[post("/login", data="<login_form>")] #[post("/login", data = "<login_form>")]
pub fn login_post(login_form: Form<LoginForm>, cookies: &CookieJar<'_>) -> TemplateOrRedirect { pub fn login_post(login_form: Form<LoginForm>, cookies: &CookieJar<'_>) -> TemplateOrRedirect {
let result = verify_login_form(login_form.into_inner()); let result = verify_login_form(login_form.into_inner());
match result { match result {
@ -138,7 +130,6 @@ pub fn login_post(login_form: Form<LoginForm>, cookies: &CookieJar<'_>) -> Templ
} }
} }
// HELPERS AND ROUTES FOR /logout // HELPERS AND ROUTES FOR /logout
#[get("/logout")] #[get("/logout")]
@ -149,7 +140,6 @@ pub fn logout(cookies: &CookieJar<'_>) -> Flash<Redirect> {
Flash::success(Redirect::to("/login"), "Logged out") Flash::success(Redirect::to("/login"), "Logged out")
} }
// HELPERS AND ROUTES FOR /reset_password // HELPERS AND ROUTES FOR /reset_password
#[derive(Debug, Deserialize, FromForm)] #[derive(Debug, Deserialize, FromForm)]
@ -228,7 +218,7 @@ pub fn reset_password(flash: Option<FlashMessage>) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("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 /// 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<ResetPasswordForm>) -> Temp
context.flash_name = Some("success".to_string()); context.flash_name = Some("success".to_string());
let flash_msg = "New password is now saved. Return home to login".to_string(); let flash_msg = "New password is now saved. Return home to login".to_string();
context.flash_msg = Some(flash_msg); context.flash_msg = Some(flash_msg);
Template::render("password/reset_password", &context) Template::render("settings/admin/reset_password", &context)
} }
Err(err) => { Err(err) => {
let mut context = ChangePasswordContext::build(); let mut context = ChangePasswordContext::build();
@ -254,18 +244,15 @@ pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Temp
context.title = Some("Reset Password".to_string()); context.title = Some("Reset Password".to_string());
context.flash_name = Some("error".to_string()); context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to reset password: {}", err)); 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 /// 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. /// 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("/reset_password", data = "<reset_password_form>")]
#[post("/public/api/v1/reset_password", data = "<reset_password_form>")] pub fn reset_password_form_endpoint(reset_password_form: Json<ResetPasswordForm>) -> Value {
pub fn reset_password_form_endpoint(
reset_password_form: Json<ResetPasswordForm>,
) -> Value {
let result = save_reset_password_form(reset_password_form.into_inner()); let result = save_reset_password_form(reset_password_form.into_inner());
match result { match result {
Ok(_) => { Ok(_) => {
@ -316,7 +303,7 @@ pub fn forgot_password_page(flash: Option<FlashMessage>) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("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 /// 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 = let flash_msg =
"A password reset link has been sent to the admin of this device".to_string(); "A password reset link has been sent to the admin of this device".to_string();
context.flash_msg = Some(flash_msg); context.flash_msg = Some(flash_msg);
Template::render("password/forgot_password", &context) Template::render("settings/admin/forgot_password", &context)
} }
Err(err) => { Err(err) => {
let mut context = ChangePasswordContext::build(); 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.title = Some("Send Password Reset".to_string());
context.flash_name = Some("error".to_string()); context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to send password reset link: {}", err)); 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. /// 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<FlashMessage>, _auth: Authenticated) -> Template { pub fn change_password(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = ChangePasswordContext::build(); let mut context = ChangePasswordContext::build();
// set back icon link to network route // 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.title = Some("Change Password".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -387,39 +374,42 @@ pub fn change_password(flash: Option<FlashMessage>, _auth: Authenticated) -> Tem
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("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. /// Change password form request handler. This route is used by a user who is already logged in.
#[post("/settings/change_password", data = "<password_form>")] #[post("/change_password", data = "<password_form>")]
pub fn change_password_post(password_form: Form<PasswordForm>, _auth: Authenticated) -> Template { pub fn change_password_post(password_form: Form<PasswordForm>, _auth: Authenticated) -> Template {
let result = save_password_form(password_form.into_inner()); let result = save_password_form(password_form.into_inner());
match result { match result {
Ok(_) => { Ok(_) => {
let mut context = ChangePasswordContext::build(); let mut context = ChangePasswordContext::build();
// set back icon link to network route // 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.title = Some("Change Password".to_string());
context.flash_name = Some("success".to_string()); context.flash_name = Some("success".to_string());
context.flash_msg = Some("New password is now saved".to_string()); context.flash_msg = Some("New password is now saved".to_string());
// template_dir is set in Rocket.toml // template_dir is set in Rocket.toml
Template::render("password/change_password", &context) Template::render("settings/admin/change_password", &context)
} }
Err(err) => { Err(err) => {
let mut context = ChangePasswordContext::build(); let mut context = ChangePasswordContext::build();
// set back icon link to network route // 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.title = Some("Configure DNS".to_string());
context.flash_name = Some("error".to_string()); context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to save new password: {}", err)); 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. /// JSON change password form request handler.
#[post("/api/v1/settings/change_password", data = "<password_form>")] #[post("/change_password", data = "<password_form>")]
pub fn save_password_form_endpoint(password_form: Json<PasswordForm>, _auth: Authenticated) -> Value { pub fn save_password_form_endpoint(
password_form: Json<PasswordForm>,
_auth: Authenticated,
) -> Value {
let result = save_password_form(password_form.into_inner()); let result = save_password_form(password_form.into_inner());
match result { match result {
Ok(_) => { Ok(_) => {

View File

@ -1,7 +1,7 @@
use log::debug; use log::debug;
use rocket::{catch}; use rocket::catch;
use rocket_dyn_templates::Template;
use rocket::response::Redirect; use rocket::response::Redirect;
use rocket_dyn_templates::Template;
use serde::Serialize; use serde::Serialize;
// HELPERS AND ROUTES FOR 404 ERROR // HELPERS AND ROUTES FOR 404 ERROR
@ -34,7 +34,7 @@ pub fn not_found() -> Template {
context.flash_name = Some("error".to_string()); context.flash_name = Some("error".to_string());
context.flash_msg = Some("No resource found for given URL".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 // HELPERS AND ROUTES FOR 500 ERROR
@ -48,7 +48,7 @@ pub fn internal_error() -> Template {
context.flash_name = Some("error".to_string()); context.flash_name = Some("error".to_string());
context.flash_msg = Some("Internal server 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 // HELPERS AND ROUTES FOR 403 FORBIDDEN
@ -57,4 +57,4 @@ pub fn internal_error() -> Template {
pub fn forbidden() -> Redirect { pub fn forbidden() -> Redirect {
debug!("403 Forbidden"); debug!("403 Forbidden");
Redirect::to("/login") Redirect::to("/login")
} }

View File

@ -24,13 +24,13 @@ impl HomeContext {
} }
#[get("/")] #[get("/")]
pub fn index(_auth: Authenticated) -> Template { pub fn home(_auth: Authenticated) -> Template {
let context = HomeContext { let context = HomeContext {
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
title: None, title: None,
}; };
Template::render("index", &context) Template::render("home", &context)
} }
// HELPERS AND ROUTES FOR /help // HELPERS AND ROUTES FOR /help

View File

@ -1,7 +1,6 @@
pub mod authentication; pub mod authentication;
pub mod device;
pub mod catchers; pub mod catchers;
pub mod index; pub mod index;
pub mod ping;
pub mod scuttlebutt; pub mod scuttlebutt;
pub mod settings; pub mod settings;
pub mod status;

View File

@ -45,7 +45,7 @@ pub fn private(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("messages", &context) Template::render("scuttlebutt/messages", &context)
} }
// HELPERS AND ROUTES FOR /peers // HELPERS AND ROUTES FOR /peers
@ -81,7 +81,7 @@ pub fn peers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("peers", &context) Template::render("scuttlebutt/peers", &context)
} }
// HELPERS AND ROUTES FOR /post/publish // HELPERS AND ROUTES FOR /post/publish
@ -209,7 +209,7 @@ pub fn profile(
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("profile", &context) Template::render("scuttlebutt/profile", &context)
} }
// HELPERS AND ROUTES FOR /friends // HELPERS AND ROUTES FOR /friends
@ -247,7 +247,7 @@ pub fn friends(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }
// HELPERS AND ROUTES FOR /follows // HELPERS AND ROUTES FOR /follows
@ -285,7 +285,7 @@ pub fn follows(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }
// HELPERS AND ROUTES FOR /followers // HELPERS AND ROUTES FOR /followers
@ -323,7 +323,7 @@ pub fn followers(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }
// HELPERS AND ROUTES FOR /blocks // HELPERS AND ROUTES FOR /blocks
@ -361,5 +361,5 @@ pub fn blocks(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("peers_list", &context) Template::render("scuttlebutt/peers_list", &context)
} }

View File

@ -1,12 +1,12 @@
use rocket::serde::{Deserialize, Serialize};
use rocket::{ use rocket::{
form::{Form, FromForm},
get, post, get, post,
request::FlashMessage, request::FlashMessage,
form::{Form, FromForm},
response::{Flash, Redirect}, response::{Flash, Redirect},
uri, uri,
}; };
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use rocket::serde::{Deserialize, Serialize};
use peach_lib::config_manager; use peach_lib::config_manager;
use peach_lib::config_manager::load_peach_config; 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::error::PeachWebError;
use crate::routes::authentication::Authenticated; 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<String>,
pub title: Option<String>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
}
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<FlashMessage>, _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)] #[derive(Debug, Serialize)]
pub struct ConfigureAdminContext { pub struct ConfigureAdminContext {
@ -40,11 +77,11 @@ impl ConfigureAdminContext {
} }
/// View and delete currently configured admin. /// View and delete currently configured admin.
#[get("/settings/configure_admin")] #[get("/configure")]
pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = ConfigureAdminContext::build(); let mut context = ConfigureAdminContext::build();
// set back icon link to network route // set back icon link to settings route
context.back = Some("/network".to_string()); context.back = Some("/settings/admin".to_string());
context.title = Some("Configure Admin".to_string()); context.title = Some("Configure Admin".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -52,7 +89,7 @@ pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Tem
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("admin/configure_admin", &context) Template::render("settings/admin/configure_admin", &context)
} }
// HELPERS AND ROUTES FOR /settings/admin/add // HELPERS AND ROUTES FOR /settings/admin/add
@ -83,14 +120,14 @@ impl AddAdminContext {
pub fn save_add_admin_form(admin_form: AddAdminForm) -> Result<(), PeachWebError> { pub fn save_add_admin_form(admin_form: AddAdminForm) -> Result<(), PeachWebError> {
let _result = config_manager::add_ssb_admin_id(&admin_form.ssb_id)?; 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(()) Ok(())
} }
#[get("/settings/admin/add")] #[get("/add")]
pub fn add_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn add_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = AddAdminContext::build(); 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()); context.title = Some("Add Admin".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -99,10 +136,10 @@ pub fn add_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // 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 = "<add_admin_form>")] #[post("/add", data = "<add_admin_form>")]
pub fn add_admin_post(add_admin_form: Form<AddAdminForm>, _auth: Authenticated) -> Flash<Redirect> { pub fn add_admin_post(add_admin_form: Form<AddAdminForm>, _auth: Authenticated) -> Flash<Redirect> {
let result = save_add_admin_form(add_admin_form.into_inner()); let result = save_add_admin_form(add_admin_form.into_inner());
let url = uri!(configure_admin); let url = uri!(configure_admin);
@ -119,8 +156,11 @@ pub struct DeleteAdminForm {
pub ssb_id: String, pub ssb_id: String,
} }
#[post("/settings/admin/delete", data = "<delete_admin_form>")] #[post("/delete", data = "<delete_admin_form>")]
pub fn delete_admin_post(delete_admin_form: Form<DeleteAdminForm>, _auth: Authenticated) -> Flash<Redirect> { pub fn delete_admin_post(
delete_admin_form: Form<DeleteAdminForm>,
_auth: Authenticated,
) -> Flash<Redirect> {
let result = config_manager::delete_ssb_admin_id(&delete_admin_form.ssb_id); let result = config_manager::delete_ssb_admin_id(&delete_admin_form.ssb_id);
let url = uri!(configure_admin); let url = uri!(configure_admin);
match result { match result {

View File

@ -1,12 +1,14 @@
use log::info; use log::info;
use rocket::{ use rocket::{
form::{Form, FromForm},
get, post, get, post,
request::FlashMessage, request::FlashMessage,
form::{Form, FromForm} serde::{
json::{Json, Value},
Deserialize, Serialize,
},
}; };
use rocket::serde::json::Json;
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use rocket::serde::{Deserialize, Serialize};
use peach_lib::config_manager; use peach_lib::config_manager;
use peach_lib::config_manager::load_peach_config; 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::error::PeachWebError;
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils::build_json_response; use crate::utils::build_json_response;
use rocket::serde::json::Value;
#[derive(Debug, Deserialize, FromForm)] #[derive(Debug, Deserialize, FromForm)]
pub struct DnsForm { pub struct DnsForm {
@ -113,11 +114,11 @@ impl ConfigureDNSContext {
} }
} }
#[get("/network/dns")] #[get("/dns")]
pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = ConfigureDNSContext::build(); let mut context = ConfigureDNSContext::build();
// set back icon link to network route // 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.title = Some("Configure DNS".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -125,35 +126,35 @@ pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Templ
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("configure_dns", &context) Template::render("settings/network/configure_dns", &context)
} }
#[post("/network/dns", data = "<dns>")] #[post("/dns", data = "<dns>")]
pub fn configure_dns_post(dns: Form<DnsForm>, _auth: Authenticated) -> Template { pub fn configure_dns_post(dns: Form<DnsForm>, _auth: Authenticated) -> Template {
let result = save_dns_configuration(dns.into_inner()); let result = save_dns_configuration(dns.into_inner());
match result { match result {
Ok(_) => { Ok(_) => {
let mut context = ConfigureDNSContext::build(); let mut context = ConfigureDNSContext::build();
// set back icon link to network route // 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.title = Some("Configure DNS".to_string());
context.flash_name = Some("success".to_string()); context.flash_name = Some("success".to_string());
context.flash_msg = Some("New dynamic dns configuration is now enabled".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) => { Err(err) => {
let mut context = ConfigureDNSContext::build(); let mut context = ConfigureDNSContext::build();
// set back icon link to network route // 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.title = Some("Configure DNS".to_string());
context.flash_name = Some("error".to_string()); context.flash_name = Some("error".to_string());
context.flash_msg = Some(format!("Failed to save dns configurations: {}", err)); 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 = "<dns_form>")] #[post("/dns/configure", data = "<dns_form>")]
pub fn save_dns_configuration_endpoint(dns_form: Json<DnsForm>, _auth: Authenticated) -> Value { pub fn save_dns_configuration_endpoint(dns_form: Json<DnsForm>, _auth: Authenticated) -> Value {
let result = save_dns_configuration(dns_form.into_inner()); let result = save_dns_configuration(dns_form.into_inner());
match result { match result {

View File

@ -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<String>,
pub title: Option<String>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
}
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<FlashMessage>, _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)
}

View File

@ -1,3 +1,5 @@
pub mod admin; pub mod admin;
pub mod dns; pub mod dns;
pub mod network; pub mod menu;
pub mod network;
pub mod scuttlebutt;

View File

@ -1,27 +1,27 @@
use log::{debug, warn}; use log::{debug, warn};
use rocket::{ use rocket::{
get,
post,
request::FlashMessage,
form::{Form, FromForm}, form::{Form, FromForm},
get, post,
request::FlashMessage,
response::{Flash, Redirect}, response::{Flash, Redirect},
serde::{
json::{json, Json, Value},
Deserialize, Serialize,
},
uri, UriDisplayQuery, uri, UriDisplayQuery,
}; };
use rocket::serde::json::{json, Json};
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use rocket::serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use peach_lib::network_client; use peach_lib::network_client;
use peach_lib::network_client::{AccessPoint, Networks, Scan}; use peach_lib::network_client::{AccessPoint, Networks, Scan};
use peach_lib::stats_client::Traffic; 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;
use crate::utils::monitor::{Alert, Data, Threshold}; 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 // STRUCTS USED BY NETWORK ROUTES
@ -36,9 +36,9 @@ pub struct WiFi {
pub pass: String, 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<Redirect> { pub fn wifi_usage_reset(_auth: Authenticated) -> Flash<Redirect> {
let url = uri!(wifi_usage); let url = uri!(wifi_usage);
match monitor::reset_data() { match monitor::reset_data() {
@ -50,7 +50,7 @@ pub fn wifi_usage_reset(_auth: Authenticated) -> Flash<Redirect> {
} }
} }
#[post("/network/wifi/connect", data = "<network>")] #[post("/wifi/connect", data = "<network>")]
pub fn connect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> { pub fn connect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &network.ssid; let ssid = &network.ssid;
let url = uri!(network_detail(ssid = ssid)); let url = uri!(network_detail(ssid = ssid));
@ -63,7 +63,7 @@ pub fn connect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect
} }
} }
#[post("/network/wifi/disconnect", data = "<network>")] #[post("/wifi/disconnect", data = "<network>")]
pub fn disconnect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> { pub fn disconnect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &network.ssid; let ssid = &network.ssid;
let url = uri!(network_home); let url = uri!(network_home);
@ -73,7 +73,7 @@ pub fn disconnect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redir
} }
} }
#[post("/network/wifi/forget", data = "<network>")] #[post("/wifi/forget", data = "<network>")]
pub fn forget_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> { pub fn forget_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &network.ssid; let ssid = &network.ssid;
let url = uri!(network_home); let url = uri!(network_home);
@ -86,10 +86,10 @@ pub fn forget_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect>
} }
} }
#[get("/network/wifi/modify?<ssid>")] #[get("/wifi/modify?<ssid>")]
pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = NetworkAddContext { let mut context = NetworkAddContext {
back: Some("/network/wifi".to_string()), back: Some("/settings/network/wifi".to_string()),
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
selected: Some(ssid.to_string()), selected: Some(ssid.to_string()),
@ -102,10 +102,10 @@ pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticat
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // template_dir is set in Rocket.toml
Template::render("network_modify", &context) Template::render("settings/network/network_modify", &context)
} }
#[post("/network/wifi/modify", data = "<wifi>")] #[post("/wifi/modify", data = "<wifi>")]
pub fn wifi_set_password(wifi: Form<WiFi>, _auth: Authenticated) -> Flash<Redirect> { pub fn wifi_set_password(wifi: Form<WiFi>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &wifi.ssid; let ssid = &wifi.ssid;
let pass = &wifi.pass; let pass = &wifi.pass;
@ -119,7 +119,7 @@ pub fn wifi_set_password(wifi: Form<WiFi>, _auth: Authenticated) -> Flash<Redire
} }
} }
// HELPERS AND ROUTES FOR /network // HELPERS AND ROUTES FOR /settings/network
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct NetworkContext { pub struct NetworkContext {
@ -273,12 +273,12 @@ impl NetworkContext {
} }
} }
#[get("/network")] #[get("/")]
pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// assign context through context_builder call // assign context through context_builder call
let mut context = NetworkContext::build(); let mut context = NetworkContext::build();
// set back button (nav) url // set back button (nav) url
context.back = Some("/".to_string()); context.back = Some("/settings".to_string());
// set page title // set page title
context.title = Some("Network Configuration".to_string()); context.title = Some("Network Configuration".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
@ -288,25 +288,28 @@ pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Templa
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // 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<Redirect> { pub fn deploy_ap(_auth: Authenticated) -> Flash<Redirect> {
// activate the wireless access point // activate the wireless access point
debug!("Activating WiFi access point."); debug!("Activating WiFi access point.");
match network_client::activate_ap() { 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( Err(_) => Flash::error(
Redirect::to("/network"), Redirect::to("/settings/network"),
"Failed to activate WiFi access point", "Failed to activate WiFi access point",
), ),
} }
} }
// HELPERS AND ROUTES FOR /network/wifi // HELPERS AND ROUTES FOR /settings/network/wifi
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct NetworkListContext { pub struct NetworkListContext {
@ -375,11 +378,11 @@ impl NetworkListContext {
} }
} }
#[get("/network/wifi")] #[get("/wifi")]
pub fn wifi_list(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn wifi_list(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// assign context through context_builder call // assign context through context_builder call
let mut context = NetworkListContext::build(); 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()); context.title = Some("WiFi Networks".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -388,10 +391,10 @@ pub fn wifi_list(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // 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<ssid> // HELPERS AND ROUTES FOR /settings/network/wifi<ssid>
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct NetworkDetailContext { pub struct NetworkDetailContext {
@ -540,11 +543,11 @@ impl NetworkDetailContext {
} }
} }
#[get("/network/wifi?<ssid>")] #[get("/wifi?<ssid>")]
pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// assign context through context_builder call // assign context through context_builder call
let mut context = NetworkDetailContext::build(); 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.title = Some("WiFi Network".to_string());
context.selected = Some(ssid.to_string()); context.selected = Some(ssid.to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
@ -554,28 +557,31 @@ pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authentica
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // 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<Redirect> { pub fn deploy_client(_auth: Authenticated) -> Flash<Redirect> {
// activate the wireless client // activate the wireless client
debug!("Activating WiFi client mode."); debug!("Activating WiFi client mode.");
match network_client::activate_client() { match network_client::activate_client() {
Ok(_) => Flash::success(Redirect::to("/network"), "Activated WiFi client"), Ok(_) => Flash::success(Redirect::to("/settings/network"), "Activated WiFi client"),
Err(_) => Flash::error(Redirect::to("/network"), "Failed to activate 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")] #[get("/wifi/add")]
pub fn network_add_wifi(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn add_wifi(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = NetworkContext::build(); let mut context = NetworkContext::build();
// set back icon link to network route // 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()); context.title = Some("Add WiFi Network".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -584,10 +590,10 @@ pub fn network_add_wifi(flash: Option<FlashMessage>, _auth: Authenticated) -> Te
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // template_dir is set in Rocket.toml
Template::render("network_add", &context) Template::render("settings/network/network_add", &context)
} }
// used in /network/wifi/add?<ssid> // used in /settings/network/wifi/add?<ssid>
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct NetworkAddContext { pub struct NetworkAddContext {
pub back: Option<String>, pub back: Option<String>,
@ -609,10 +615,10 @@ impl NetworkAddContext {
} }
} }
#[get("/network/wifi/add?<ssid>")] #[get("/wifi/add?<ssid>")]
pub fn network_add_ssid(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn add_ssid(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = NetworkAddContext::build(); 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.selected = Some(ssid.to_string());
context.title = Some("Add WiFi Network".to_string()); context.title = Some("Add WiFi Network".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
@ -622,10 +628,10 @@ pub fn network_add_ssid(ssid: &str, flash: Option<FlashMessage>, _auth: Authenti
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // template_dir is set in Rocket.toml
Template::render("network_add", &context) Template::render("settings/network/network_add", &context)
} }
#[post("/network/wifi/add", data = "<wifi>")] #[post("/wifi/add", data = "<wifi>")]
pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template { pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
// check if the credentials already exist for this access point // check if the credentials already exist for this access point
// note: this is nicer but it's an unstable feature: // note: this is nicer but it's an unstable feature:
@ -634,13 +640,13 @@ pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
let creds_exist = network_client::saved_ap(&wifi.ssid).unwrap_or(false); let creds_exist = network_client::saved_ap(&wifi.ssid).unwrap_or(false);
if creds_exist { if creds_exist {
let mut context = NetworkAddContext::build(); 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_name = Some("error".to_string());
context.flash_msg = context.flash_msg =
Some("Network credentials already exist for this access point".to_string()); Some("Network credentials already exist for this access point".to_string());
context.title = Some("Add WiFi Network".to_string()); context.title = Some("Add WiFi Network".to_string());
// return early from handler with "creds already exist" message // 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 // if credentials not found, generate and write wifi config to wpa_supplicant
@ -653,20 +659,20 @@ pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
Err(_) => warn!("Failed to reconfigure wpa_supplicant"), Err(_) => warn!("Failed to reconfigure wpa_supplicant"),
} }
let mut context = NetworkAddContext::build(); 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_name = Some("success".to_string());
context.flash_msg = Some("Added WiFi credentials".to_string()); context.flash_msg = Some("Added WiFi credentials".to_string());
context.title = Some("Add WiFi Network".to_string()); context.title = Some("Add WiFi Network".to_string());
Template::render("network_add", &context) Template::render("settings/network/network_add", &context)
} }
Err(_) => { Err(_) => {
debug!("Failed to add WiFi credentials."); debug!("Failed to add WiFi credentials.");
let mut context = NetworkAddContext::build(); 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_name = Some("error".to_string());
context.flash_msg = Some("Failed to add WiFi credentials".to_string()); context.flash_msg = Some("Failed to add WiFi credentials".to_string());
context.title = Some("Add WiFi Network".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<FlashMessage>, _auth: Authenticated) -> Template { pub fn wifi_usage(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = NetworkAlertContext::build(); let mut context = NetworkAlertContext::build();
// set back icon link to network route // 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()); context.title = Some("Network Data Usage".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
@ -732,30 +738,32 @@ pub fn wifi_usage(flash: Option<FlashMessage>, _auth: Authenticated) -> Template
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
// template_dir is set in Rocket.toml // template_dir is set in Rocket.toml
Template::render("network_usage", &context) Template::render("settings/network/network_usage", &context)
} }
#[post("/network/wifi/usage", data = "<thresholds>")] #[post("/wifi/usage", data = "<thresholds>")]
pub fn wifi_usage_alerts(thresholds: Form<Threshold>, _auth: Authenticated) -> Flash<Redirect> { pub fn wifi_usage_alerts(thresholds: Form<Threshold>, _auth: Authenticated) -> Flash<Redirect> {
match monitor::update_store(thresholds.into_inner()) { match monitor::update_store(thresholds.into_inner()) {
Ok(_) => { Ok(_) => {
debug!("WiFi data usage thresholds updated."); debug!("WiFi data usage thresholds updated.");
Flash::success( Flash::success(
Redirect::to("/network/wifi/usage"), Redirect::to("/settings/network/wifi/usage"),
"Updated alert thresholds and flags", "Updated alert thresholds and flags",
) )
} }
Err(_) => { Err(_) => {
warn!("Failed to update WiFi data usage thresholds."); warn!("Failed to update WiFi data usage thresholds.");
Flash::error( Flash::error(
Redirect::to("/network/wifi/usage"), Redirect::to("/settings/network/wifi/usage"),
"Failed to update alert thresholds and flags", "Failed to update alert thresholds and flags",
) )
} }
} }
} }
#[post("/api/v1/network/wifi/usage", data = "<thresholds>")] // JSON ROUTES FOR NETWORK SETTINGS
#[post("/wifi/usage", data = "<thresholds>")]
pub fn update_wifi_alerts(thresholds: Json<Threshold>, _auth: Authenticated) -> Value { pub fn update_wifi_alerts(thresholds: Json<Threshold>, _auth: Authenticated) -> Value {
match monitor::update_store(thresholds.into_inner()) { match monitor::update_store(thresholds.into_inner()) {
Ok(_) => { Ok(_) => {
@ -773,7 +781,7 @@ pub fn update_wifi_alerts(thresholds: Json<Threshold>, _auth: Authenticated) ->
} }
} }
#[post("/api/v1/network/wifi/usage/reset")] #[post("/wifi/usage/reset")]
pub fn reset_data_total(_auth: Authenticated) -> Value { pub fn reset_data_total(_auth: Authenticated) -> Value {
match monitor::reset_data() { match monitor::reset_data() {
Ok(_) => { Ok(_) => {
@ -805,7 +813,7 @@ pub fn reset_data_total(_auth: Authenticated) -> Value {
// HELPERS AND ROUTES FOR ACCESS POINT ACTIVATION // HELPERS AND ROUTES FOR ACCESS POINT ACTIVATION
#[post("/api/v1/network/activate_ap")] #[post("/activate_ap")]
pub fn activate_ap(_auth: Authenticated) -> Value { pub fn activate_ap(_auth: Authenticated) -> Value {
// activate the wireless access point // activate the wireless access point
debug!("Activating WiFi 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 // HELPERS AND ROUTES FOR WIFI CLIENT MANAGEMENT
#[post("/api/v1/network/activate_client")] #[post("/activate_client")]
pub fn activate_client(_auth: Authenticated) -> Value { pub fn activate_client(_auth: Authenticated) -> Value {
// activate the wireless client // activate the wireless client
debug!("Activating WiFi client mode."); debug!("Activating WiFi client mode.");
@ -841,8 +849,8 @@ pub fn activate_client(_auth: Authenticated) -> Value {
} }
} }
#[post("/api/v1/network/wifi", data = "<wifi>")] #[post("/wifi", data = "<wifi>")]
pub fn add_wifi(wifi: Json<WiFi>, _auth: Authenticated) -> Value { pub fn add_wifi_credentials(wifi: Json<WiFi>, _auth: Authenticated) -> Value {
// generate and write wifi config to wpa_supplicant // generate and write wifi config to wpa_supplicant
match network_client::add(&wifi.ssid, &wifi.pass) { match network_client::add(&wifi.ssid, &wifi.pass) {
Ok(_) => { Ok(_) => {
@ -867,7 +875,7 @@ pub fn add_wifi(wifi: Json<WiFi>, _auth: Authenticated) -> Value {
} }
} }
#[post("/api/v1/network/wifi/connect", data = "<ssid>")] #[post("/wifi/connect", data = "<ssid>")]
pub fn connect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value { pub fn connect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value {
// retrieve the id for the given network ssid // retrieve the id for the given network ssid
match network_client::id("wlan0", &ssid.ssid) { match network_client::id("wlan0", &ssid.ssid) {
@ -892,7 +900,7 @@ pub fn connect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value {
} }
} }
#[post("/api/v1/network/wifi/disconnect", data = "<ssid>")] #[post("/wifi/disconnect", data = "<ssid>")]
pub fn disconnect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value { pub fn disconnect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value {
// attempt to disable the current network for wlan0 interface // attempt to disable the current network for wlan0 interface
match network_client::disable("wlan0", &ssid.ssid) { match network_client::disable("wlan0", &ssid.ssid) {
@ -909,7 +917,7 @@ pub fn disconnect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value {
} }
} }
#[post("/api/v1/network/wifi/forget", data = "<network>")] #[post("/wifi/forget", data = "<network>")]
pub fn forget_ap(network: Json<Ssid>, _auth: Authenticated) -> Value { pub fn forget_ap(network: Json<Ssid>, _auth: Authenticated) -> Value {
let ssid = &network.ssid; let ssid = &network.ssid;
match network_client::forget("wlan0", ssid) { match network_client::forget("wlan0", ssid) {
@ -928,7 +936,7 @@ pub fn forget_ap(network: Json<Ssid>, _auth: Authenticated) -> Value {
} }
} }
#[post("/api/v1/network/wifi/modify", data = "<wifi>")] #[post("/wifi/modify", data = "<wifi>")]
pub fn modify_password(wifi: Json<WiFi>, _auth: Authenticated) -> Value { pub fn modify_password(wifi: Json<WiFi>, _auth: Authenticated) -> Value {
let ssid = &wifi.ssid; let ssid = &wifi.ssid;
let pass = &wifi.pass; let pass = &wifi.pass;
@ -953,7 +961,7 @@ pub fn modify_password(wifi: Json<WiFi>, _auth: Authenticated) -> Value {
// HELPERS AND ROUTES FOR NETWORK STATE QUERIES // HELPERS AND ROUTES FOR NETWORK STATE QUERIES
#[get("/api/v1/network/ip")] #[get("/ip")]
pub fn return_ip(_auth: Authenticated) -> Value { pub fn return_ip(_auth: Authenticated) -> Value {
// retrieve ip for wlan0 or set to x.x.x.x if not found // retrieve ip for wlan0 or set to x.x.x.x if not found
let wlan_ip = match network_client::ip("wlan0") { 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) build_json_response(status, Some(data), None)
} }
#[get("/api/v1/network/rssi")] #[get("/rssi")]
pub fn return_rssi(_auth: Authenticated) -> Value { pub fn return_rssi(_auth: Authenticated) -> Value {
// retrieve rssi for connected network // retrieve rssi for connected network
match network_client::rssi("wlan0") { 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 { pub fn return_ssid(_auth: Authenticated) -> Value {
// retrieve ssid for connected network // retrieve ssid for connected network
match network_client::ssid("wlan0") { 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 { pub fn return_state(_auth: Authenticated) -> Value {
// retrieve state of wlan0 or set to x.x.x.x if not found // retrieve state of wlan0 or set to x.x.x.x if not found
let wlan_state = match network_client::state("wlan0") { 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) build_json_response(status, Some(data), None)
} }
#[get("/api/v1/network/status")] #[get("/status")]
pub fn return_status(_auth: Authenticated) -> Value { pub fn return_status(_auth: Authenticated) -> Value {
// retrieve status info for wlan0 interface // retrieve status info for wlan0 interface
match network_client::status("wlan0") { 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 { pub fn scan_networks(_auth: Authenticated) -> Value {
// retrieve scan results for access-points within range of wlan0 // retrieve scan results for access-points within range of wlan0
match network_client::available_networks("wlan0") { match network_client::available_networks("wlan0") {

View File

@ -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<String>,
pub title: Option<String>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
}
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<FlashMessage>, _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)
}

View File

@ -16,15 +16,15 @@ use peach_lib::config_manager::load_peach_config;
use peach_lib::stats_client::{CpuStatPercentages, DiskUsage, LoadAverage, MemStat}; use peach_lib::stats_client::{CpuStatPercentages, DiskUsage, LoadAverage, MemStat};
use peach_lib::{dyndns_client, network_client, oled_client, sbot_client, stats_client}; 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::routes::authentication::Authenticated;
use crate::utils::build_json_response;
use rocket::serde::json::Value; use rocket::serde::json::Value;
// HELPERS AND ROUTES FOR /device // HELPERS AND ROUTES FOR /status
/// System statistics data. /// System statistics data.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct DeviceContext { pub struct StatusContext {
pub back: Option<String>, pub back: Option<String>,
pub cpu_stat_percent: Option<CpuStatPercentages>, pub cpu_stat_percent: Option<CpuStatPercentages>,
pub disk_stats: Vec<DiskUsage>, pub disk_stats: Vec<DiskUsage>,
@ -43,8 +43,8 @@ pub struct DeviceContext {
pub uptime: Option<i32>, pub uptime: Option<i32>,
} }
impl DeviceContext { impl StatusContext {
pub fn build() -> DeviceContext { pub fn build() -> StatusContext {
// convert result to Option<CpuStatPercentages>, discard any error // convert result to Option<CpuStatPercentages>, discard any error
let cpu_stat_percent = stats_client::cpu_stats_percent().ok(); let cpu_stat_percent = stats_client::cpu_stats_percent().ok();
let load_average = stats_client::load_average().ok(); let load_average = stats_client::load_average().ok();
@ -129,7 +129,7 @@ impl DeviceContext {
} }
} }
DeviceContext { StatusContext {
back: None, back: None,
cpu_stat_percent, cpu_stat_percent,
disk_stats, disk_stats,
@ -150,10 +150,10 @@ impl DeviceContext {
} }
} }
#[get("/device")] #[get("/status")]
pub fn device_stats(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn device_status(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// assign context through context_builder call // assign context through context_builder call
let mut context = DeviceContext::build(); let mut context = StatusContext::build();
context.back = Some("/".to_string()); context.back = Some("/".to_string());
context.title = Some("Device Status".to_string()); context.title = Some("Device Status".to_string());
// check to see if there is a flash message to display // check to see if there is a flash message to display
@ -166,7 +166,7 @@ pub fn device_stats(flash: Option<FlashMessage>, _auth: Authenticated) -> Templa
Template::render("device", &context) 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. /// Executes a system command to reboot the device immediately.
pub fn reboot() -> io::Result<Output> { pub fn reboot() -> io::Result<Output> {
@ -181,16 +181,16 @@ pub fn reboot() -> io::Result<Output> {
.output() .output()
} }
#[get("/device/reboot")] #[get("/power/reboot")]
pub fn reboot_cmd(_auth: Authenticated) -> Flash<Redirect> { pub fn reboot_cmd(_auth: Authenticated) -> Flash<Redirect> {
match reboot() { match reboot() {
Ok(_) => Flash::success(Redirect::to("/shutdown"), "Rebooting the device"), Ok(_) => Flash::success(Redirect::to("/power"), "Rebooting the device"),
Err(_) => Flash::error(Redirect::to("/shutdown"), "Failed to reboot the device"), Err(_) => Flash::error(Redirect::to("/power"), "Failed to reboot the device"),
} }
} }
/// JSON request handler for device reboot. /// JSON request handler for device reboot.
#[post("/api/v1/device/reboot")] #[post("/api/v1/admin/reboot")]
pub fn reboot_device(_auth: Authenticated) -> Value { pub fn reboot_device(_auth: Authenticated) -> Value {
match reboot() { match reboot() {
Ok(_) => { 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. /// Executes a system command to shutdown the device immediately.
pub fn shutdown() -> io::Result<Output> { pub fn shutdown() -> io::Result<Output> {
@ -219,16 +219,16 @@ pub fn shutdown() -> io::Result<Output> {
Command::new("sudo").arg("shutdown").arg("now").output() Command::new("sudo").arg("shutdown").arg("now").output()
} }
#[get("/device/shutdown")] #[get("/power/shutdown")]
pub fn shutdown_cmd(_auth: Authenticated) -> Flash<Redirect> { pub fn shutdown_cmd(_auth: Authenticated) -> Flash<Redirect> {
match shutdown() { match shutdown() {
Ok(_) => Flash::success(Redirect::to("/shutdown"), "Shutting down the device"), Ok(_) => Flash::success(Redirect::to("/power"), "Shutting down the device"),
Err(_) => Flash::error(Redirect::to("/shutdown"), "Failed to shutdown the device"), Err(_) => Flash::error(Redirect::to("/power"), "Failed to shutdown the device"),
} }
} }
// shutdown the device // shutdown the device
#[post("/api/v1/device/shutdown")] #[post("/power/shutdown")]
pub fn shutdown_device(_auth: Authenticated) -> Value { pub fn shutdown_device(_auth: Authenticated) -> Value {
match shutdown() { match shutdown() {
Ok(_) => { 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)] #[derive(Debug, Serialize)]
pub struct ShutdownContext { pub struct PowerContext {
pub back: Option<String>, pub back: Option<String>,
pub flash_name: Option<String>, pub flash_name: Option<String>,
pub flash_msg: Option<String>, pub flash_msg: Option<String>,
pub title: Option<String>, pub title: Option<String>,
} }
impl ShutdownContext { impl PowerContext {
pub fn build() -> ShutdownContext { pub fn build() -> PowerContext {
ShutdownContext { PowerContext {
back: None, back: None,
flash_name: None, flash_name: None,
flash_msg: None, flash_msg: None,
@ -267,16 +267,16 @@ impl ShutdownContext {
} }
} }
#[get("/shutdown")] #[get("/power")]
pub fn shutdown_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template { pub fn power_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = ShutdownContext::build(); let mut context = PowerContext::build();
context.back = Some("/".to_string()); 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 // check to see if there is a flash message to display
if let Some(flash) = flash { if let Some(flash) = flash {
// add flash message contents to the context object // add flash message contents to the context object
context.flash_name = Some(flash.kind().to_string()); context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string()); context.flash_msg = Some(flash.message().to_string());
}; };
Template::render("shutdown", &context) Template::render("power", &context)
} }

View File

@ -0,0 +1,2 @@
pub mod device;
pub mod ping;

View File

@ -1,19 +1,19 @@
//! Helper routes for pinging services to check that they are active //! Helper routes for pinging services to check that they are active
use log::{debug, warn}; use log::{debug, warn};
use rocket::get; use rocket::get;
use rocket::serde::json::{Value}; use rocket::serde::json::Value;
use peach_lib::network_client; use peach_lib::network_client;
use peach_lib::oled_client; use peach_lib::oled_client;
use peach_lib::stats_client; use peach_lib::stats_client;
use crate::utils::build_json_response;
use crate::routes::authentication::Authenticated; use crate::routes::authentication::Authenticated;
use crate::utils::build_json_response;
/// Status route: useful for checking connectivity from web client. /// 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(_auth: Authenticated) -> Value {
//pub fn ping_pong() -> Value { //pub fn ping_pong() -> Value {
// ping pong // ping pong
let status = "success".to_string(); let status = "success".to_string();
let msg = "pong!".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. /// Status route: check availability of `peach-network` microservice.
#[get("/api/v1/ping/network")] #[get("/ping/network")]
pub fn ping_network(_auth: Authenticated) -> Value { pub fn ping_network(_auth: Authenticated) -> Value {
match network_client::ping() { match network_client::ping() {
Ok(_) => { Ok(_) => {
@ -40,7 +40,7 @@ pub fn ping_network(_auth: Authenticated) -> Value {
} }
/// Status route: check availability of `peach-oled` microservice. /// Status route: check availability of `peach-oled` microservice.
#[get("/api/v1/ping/oled")] #[get("/ping/oled")]
pub fn ping_oled(_auth: Authenticated) -> Value { pub fn ping_oled(_auth: Authenticated) -> Value {
match oled_client::ping() { match oled_client::ping() {
Ok(_) => { Ok(_) => {
@ -59,7 +59,7 @@ pub fn ping_oled(_auth: Authenticated) -> Value {
} }
/// Status route: check availability of `peach-stats` microservice. /// Status route: check availability of `peach-stats` microservice.
#[get("/api/v1/ping/stats")] #[get("/ping/stats")]
pub fn ping_stats(_auth: Authenticated) -> Value { pub fn ping_stats(_auth: Authenticated) -> Value {
match stats_client::ping() { match stats_client::ping() {
Ok(_) => { Ok(_) => {

View File

@ -47,15 +47,15 @@ fn index_html() {
assert!(body.contains("/peers")); assert!(body.contains("/peers"));
assert!(body.contains("/profile")); assert!(body.contains("/profile"));
assert!(body.contains("/private")); assert!(body.contains("/private"));
assert!(body.contains("/device")); assert!(body.contains("/status"));
assert!(body.contains("/help")); assert!(body.contains("/help"));
assert!(body.contains("/network")); assert!(body.contains("/settings"));
} }
#[test] #[test]
fn network_card_html() { fn network_card_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -73,7 +73,7 @@ fn network_card_html() {
#[test] #[test]
fn network_list_html() { fn network_list_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -85,7 +85,7 @@ fn network_list_html() {
#[test] #[test]
fn network_detail_html() { fn network_detail_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
//let body = response.into_string().unwrap(); //let body = response.into_string().unwrap();
@ -95,7 +95,7 @@ fn network_detail_html() {
#[test] #[test]
fn network_add_html() { fn network_add_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -109,7 +109,9 @@ fn network_add_html() {
#[test] #[test]
fn network_add_ssid_html() { fn network_add_ssid_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -121,9 +123,9 @@ fn network_add_ssid_html() {
} }
#[test] #[test]
fn device_html() { fn status_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -269,9 +271,9 @@ fn profile_html() {
} }
#[test] #[test]
fn shutdown_html() { fn power_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -281,7 +283,7 @@ fn shutdown_html() {
#[test] #[test]
fn network_usage_html() { fn network_usage_html() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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.status(), Status::Ok);
assert_eq!(response.content_type(), Some(ContentType::HTML)); assert_eq!(response.content_type(), Some(ContentType::HTML));
let body = response.into_string().unwrap(); let body = response.into_string().unwrap();
@ -295,7 +297,7 @@ fn network_usage_html() {
fn add_credentials() { fn add_credentials() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client let response = client
.post("/network/wifi/add") .post("/settings/network/wifi/add")
.header(ContentType::Form) .header(ContentType::Form)
.body("ssid=Home&pass=Password") .body("ssid=Home&pass=Password")
.dispatch(); .dispatch();
@ -307,7 +309,7 @@ fn add_credentials() {
fn forget_wifi() { fn forget_wifi() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client let response = client
.post("/network/wifi/forget") .post("/settings/network/wifi/forget")
.header(ContentType::Form) .header(ContentType::Form)
.body("ssid=Home") .body("ssid=Home")
.dispatch(); .dispatch();
@ -319,7 +321,7 @@ fn forget_wifi() {
fn modify_password() { fn modify_password() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); let client = Client::tracked(init_rocket()).expect("valid rocket instance");
let response = client let response = client
.post("/network/wifi/modify") .post("/settings/network/wifi/modify")
.header(ContentType::Form) .header(ContentType::Form)
.body("ssid=Home&pass=Password") .body("ssid=Home&pass=Password")
.dispatch(); .dispatch();
@ -330,7 +332,7 @@ fn modify_password() {
#[test] #[test]
fn deploy_ap() { fn deploy_ap() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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) // check for 303 status (redirect)
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
assert_eq!(response.content_type(), None); assert_eq!(response.content_type(), None);
@ -339,7 +341,7 @@ fn deploy_ap() {
#[test] #[test]
fn deploy_client() { fn deploy_client() {
let client = Client::tracked(init_rocket()).expect("valid rocket instance"); 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) // check for 303 status (redirect)
assert_eq!(response.status(), Status::SeeOther); assert_eq!(response.status(), Status::SeeOther);
assert_eq!(response.content_type(), None); assert_eq!(response.content_type(), None);

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 984 B

View File

@ -23,7 +23,7 @@ PEACH.add = function() {
// write in-progress status message to ui // write in-progress status message to ui
PEACH.flashMsg("info", "Saving new password."); PEACH.flashMsg("info", "Saving new password.");
// send add_wifi POST request // send add_wifi POST request
fetch("/api/v1/settings/change_password", { fetch("/api/v1/admin/change_password", {
method: "post", method: "post",
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@ -38,7 +38,7 @@ PEACH_DNS.add = function() {
// write in-progress status message to ui // write in-progress status message to ui
PEACH_DNS.flashMsg("info", "Saving new DNS configurations"); PEACH_DNS.flashMsg("info", "Saving new DNS configurations");
// send add_wifi POST request // send add_wifi POST request
fetch("/api/v1/dns/configure", { fetch("/api/v1/network/dns/configure", {
method: "post", method: "post",
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@ -1,7 +1,7 @@
/* /*
behavioural layer for the `shutdown.html.tera` template, behavioural layer for the `power.html.tera` template,
corresponding to the web route `/shutdown` corresponding to the web route `/power`
- intercept button clicks for reboot & shutdown - intercept button clicks for reboot & shutdown
- perform json api calls - perform json api calls
@ -28,7 +28,7 @@ PEACH_DEVICE.reboot = function() {
// write reboot flash message // write reboot flash message
PEACH_DEVICE.flashMsg("success", "Rebooting the device..."); PEACH_DEVICE.flashMsg("success", "Rebooting the device...");
// send reboot_device POST request // send reboot_device POST request
fetch("/api/v1/device/reboot", { fetch("/api/v1/admin/reboot", {
method: "post", method: "post",
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -59,7 +59,7 @@ PEACH_DEVICE.shutdown = function() {
// write shutdown flash message // write shutdown flash message
PEACH_DEVICE.flashMsg("success", "Shutting down the device..."); PEACH_DEVICE.flashMsg("success", "Shutting down the device...");
// send shutdown_device POST request // send shutdown_device POST request
fetch("/api/v1/device/shutdown", { fetch("/api/v1/shutdown", {
method: "post", method: "post",
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',

View File

@ -23,7 +23,7 @@ PEACH.add = function() {
// write in-progress status message to ui // write in-progress status message to ui
PEACH.flashMsg("info", "Saving new password."); PEACH.flashMsg("info", "Saving new password.");
// send add_wifi POST request // send add_wifi POST request
fetch("/public/api/v1/reset_password", { fetch("/api/v1/admin/reset_password", {
method: "post", method: "post",
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@ -25,7 +25,7 @@
<div class="three-grid" style="padding-top: 1rem;"> <div class="three-grid" style="padding-top: 1rem;">
<!-- PEACH-NETWORK STATUS STACK --> <!-- PEACH-NETWORK STATUS STACK -->
<div class="stack capsule{% if network_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}"> <div class="stack capsule{% if network_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if network_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Network" title="Network microservice status" src="icons/wifi.svg"> <img id="networkIcon" class="icon{% if network_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Network" title="Network microservice status" src="/icons/wifi.svg">
<div class="stack" style="padding-top: 0.5rem;"> <div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Networking</label> <label class="label-small font-near-black">Networking</label>
<label class="label-small font-near-black">{{ network_ping }}</label> <label class="label-small font-near-black">{{ network_ping }}</label>
@ -33,7 +33,7 @@
</div> </div>
<!-- PEACH-OLED STATUS STACK --> <!-- PEACH-OLED STATUS STACK -->
<div class="stack capsule{% if oled_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}"> <div class="stack capsule{% if oled_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="oledIcon" class="icon{% if oled_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Display" title="OLED display microservice status" src="icons/lcd.svg"> <img id="oledIcon" class="icon{% if oled_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Display" title="OLED display microservice status" src="/icons/lcd.svg">
<div class="stack" style="padding-top: 0.5rem;"> <div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Display</label> <label class="label-small font-near-black">Display</label>
<label class="label-small font-near-black">{{ oled_ping }}</label> <label class="label-small font-near-black">{{ oled_ping }}</label>
@ -41,7 +41,7 @@
</div> </div>
<!-- PEACH-STATS STATUS STACK --> <!-- PEACH-STATS STATUS STACK -->
<div class="stack capsule{% if stats_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}"> <div class="stack capsule{% if stats_ping == "ONLINE" %} success-border{% else %} warning-border{% endif %}">
<img id="statsIcon" class="icon{% if stats_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Stats" title="System statistics microservice status" src="icons/chart.svg"> <img id="statsIcon" class="icon{% if stats_ping == "OFFLINE" %} icon-inactive{% endif %} icon-medium" alt="Stats" title="System statistics microservice status" src="/icons/chart.svg">
<div class="stack" style="padding-top: 0.5rem;"> <div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Statistics</label> <label class="label-small font-near-black">Statistics</label>
<label class="label-small font-near-black">{{ stats_ping }}</label> <label class="label-small font-near-black">{{ stats_ping }}</label>
@ -51,7 +51,7 @@
<div class="three-grid" style="padding-bottom: 1rem; margin-top: 0px;"> <div class="three-grid" style="padding-bottom: 1rem; margin-top: 0px;">
<!-- DYNDNS STATUS STACK --> <!-- DYNDNS STATUS STACK -->
<div class="stack capsule{% if dyndns_is_online %} success-border{% else %} warning-border{% endif %}"> <div class="stack capsule{% if dyndns_is_online %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if dyndns_is_online != true %} icon-inactive {% endif %} icon-medium" alt="Dyndns" title="Dyndns status" src="icons/wifi.svg"> <img id="networkIcon" class="icon{% if dyndns_is_online != true %} icon-inactive{% endif %} icon-medium" alt="Dyndns" title="Dyndns status" src="/icons/dns.png">
<div class="stack" style="padding-top: 0.5rem;"> <div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Dyn DNS</label> <label class="label-small font-near-black">Dyn DNS</label>
<label class="label-small font-near-black">{% if dyndns_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label> <label class="label-small font-near-black">{% if dyndns_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label>
@ -59,7 +59,7 @@
</div> </div>
<!-- CONFIG STATUS STACK --> <!-- CONFIG STATUS STACK -->
<div class="stack capsule{% if config_is_valid %} success-border{% else %} warning-border{% endif %}"> <div class="stack capsule{% if config_is_valid %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if config_is_valid != true %} icon-inactive {% endif %} icon-medium" alt="Config" title="Config status" src="icons/wifi.svg"> <img id="networkIcon" class="icon{% if config_is_valid != true %} icon-inactive{% endif %} icon-medium" alt="Config" title="Config status" src="/icons/clipboard.png">
<div class="stack" style="padding-top: 0.5rem;"> <div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Config</label> <label class="label-small font-near-black">Config</label>
<label class="label-small font-near-black">{% if config_is_valid %} LOADED {% else %} INVALID {% endif %} </label> <label class="label-small font-near-black">{% if config_is_valid %} LOADED {% else %} INVALID {% endif %} </label>
@ -67,7 +67,7 @@
</div> </div>
<!-- SBOT STATUS STACK --> <!-- SBOT STATUS STACK -->
<div class="stack capsule{% if sbot_is_online %} success-border{% else %} warning-border{% endif %}"> <div class="stack capsule{% if sbot_is_online %} success-border{% else %} warning-border{% endif %}">
<img id="networkIcon" class="icon{% if sbot_is_online != true %} icon-inactive {% endif %} icon-medium" alt="Sbot" title="Sbot status" src="icons/wifi.svg"> <img id="networkIcon" class="icon{% if sbot_is_online != true %} icon-inactive{% endif %} icon-medium" alt="Sbot" title="Sbot status" src="/icons/hermies.svg">
<div class="stack" style="padding-top: 0.5rem;"> <div class="stack" style="padding-top: 0.5rem;">
<label class="label-small font-near-black">Sbot</label> <label class="label-small font-near-black">Sbot</label>
<label class="label-small font-near-black">{% if sbot_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label> <label class="label-small font-near-black">{% if sbot_is_online %} ONLINE {% else %} OFFLINE {% endif %} </label>

View File

@ -6,21 +6,21 @@
<!-- PEERS LINK AND ICON --> <!-- PEERS LINK AND ICON -->
<a class="top-left" href="/scuttlebutt/peers" title="Scuttlebutt Peers"> <a class="top-left" href="/scuttlebutt/peers" title="Scuttlebutt Peers">
<div class="circle circle-small"> <div class="circle circle-small">
<img class="icon-medium" src="icons/users.svg"> <img class="icon-medium" src="/icons/users.svg">
</div> </div>
</a> </a>
<!-- top-middle --> <!-- top-middle -->
<!-- CURRENT USER LINK AND ICON --> <!-- CURRENT USER LINK AND ICON -->
<a class="top-middle" href="/scuttlebutt/profile" title="Profile"> <a class="top-middle" href="/scuttlebutt/profile" title="Profile">
<div class="circle circle-small"> <div class="circle circle-small">
<img class="icon-medium" src="icons/user.svg"> <img class="icon-medium" src="/icons/user.svg">
</div> </div>
</a> </a>
<!-- top-right --> <!-- top-right -->
<!-- MESSAGES LINK AND ICON --> <!-- MESSAGES LINK AND ICON -->
<a class="top-right" href="/scuttlebutt/private" title="Private Messages"> <a class="top-right" href="/scuttlebutt/private" title="Private Messages">
<div class="circle circle-small"> <div class="circle circle-small">
<img class="icon-medium" src="icons/envelope.svg"> <img class="icon-medium" src="/icons/envelope.svg">
</div> </div>
</a> </a>
<!-- middle --> <!-- middle -->
@ -30,23 +30,23 @@
</a> </a>
<!-- bottom-left --> <!-- bottom-left -->
<!-- SYSTEM STATUS LINK AND ICON --> <!-- SYSTEM STATUS LINK AND ICON -->
<a class="bottom-left" href="/device" title="Device Status"> <a class="bottom-left" href="/status" title="Status">
<div class="circle circle-small"> <div class="circle circle-small">
<img class="icon-medium" src="icons/heart-pulse.svg"> <img class="icon-medium" src="/icons/heart-pulse.svg">
</div> </div>
</a> </a>
<!-- bottom-middle --> <!-- bottom-middle -->
<!-- PEACHCLOUD GUIDEBOOK LINK AND ICON --> <!-- PEACHCLOUD GUIDEBOOK LINK AND ICON -->
<a class="bottom-middle" href="/help" title="Help Menu"> <a class="bottom-middle" href="/help" title="Help Menu">
<div class="circle circle-small"> <div class="circle circle-small">
<img class="icon-medium" src="icons/book.svg"> <img class="icon-medium" src="/icons/book.svg">
</div> </div>
</a> </a>
<!-- bottom-right --> <!-- bottom-right -->
<!-- SYSTEM SETTINGS LINK AND ICON --> <!-- SYSTEM SETTINGS LINK AND ICON -->
<a class="bottom-right" href="/network" title="Network Configuration"> <a class="bottom-right" href="/settings" title="Settings Menu">
<div class="circle circle-small"> <div class="circle circle-small">
<img class="icon-medium" src="icons/cog.svg"> <img class="icon-medium" src="/icons/cog.svg">
</div> </div>
</a> </a>
</div> </div>

View File

@ -17,7 +17,7 @@
{% include "snippets/flash_message" %} {% include "snippets/flash_message" %}
<div class="center-text" style="margin-top: 25px;"> <div class="center-text" style="margin-top: 25px;">
<a href="/forgot_password" class="label-small link">Forgot Password?</a> <a href="/settings/admin/forgot_password" class="label-small link">Forgot Password?</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -22,8 +22,8 @@
<a class="nav-item" href="/"> <a class="nav-item" href="/">
<img class="icon nav-icon-left" src="/icons/peach-icon.png" alt="PeachCloud" title="Home"> <img class="icon nav-icon-left" src="/icons/peach-icon.png" alt="PeachCloud" title="Home">
</a> </a>
<a class="nav-item" href="/help"> <a class="nav-item" href="/power">
<img class="icon-medium nav-icon-right icon-active" title="Help" src="/icons/question-circle.svg" alt="Question mark"> <img class="icon-medium nav-icon-right icon-active" title="Shutdown" src="/icons/power.svg" alt="Power switch">
</a> </a>
</nav> </nav>
{%- endblock nav -%} {%- endblock nav -%}

View File

@ -5,8 +5,8 @@
<div class="card-container"> <div class="card-container">
<!-- BUTTONS --> <!-- BUTTONS -->
<div id="buttonDiv"> <div id="buttonDiv">
<a id="rebootBtn" class="button button-primary center" href="/device/reboot" title="Reboot Device">Reboot</a> <a id="rebootBtn" class="button button-primary center" href="/power/reboot" title="Reboot Device">Reboot</a>
<a id="shutdownBtn" class="button button-warning center" href="/device/shutdown" title="Shutdown Device">Shutdown</a> <a id="shutdownBtn" class="button button-warning center" href="/power/shutdown" title="Shutdown Device">Shutdown</a>
<a id="cancelBtn" class="button button-secondary center" href="/" title="Cancel">Cancel</a> <a id="cancelBtn" class="button button-secondary center" href="/" title="Cancel">Cancel</a>
</div> </div>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->
@ -15,5 +15,5 @@
{% include "snippets/noscript" %} {% include "snippets/noscript" %}
</div> </div>
</div> </div>
<script type="text/javascript" src="/js/shutdown_menu.js"></script> <script type="text/javascript" src="/js/power_menu.js"></script>
{%- endblock card -%} {%- endblock card -%}

View File

@ -7,7 +7,7 @@
<input id="ssb_id" name="ssb_id" class="center input" type="text" placeholder="SSB ID" title="SSB ID of Admin" value=""/> <input id="ssb_id" name="ssb_id" class="center input" type="text" placeholder="SSB ID" title="SSB ID of Admin" value=""/>
<div id="buttonDiv"> <div id="buttonDiv">
<input id="addAdmin" class="button button-primary center" title="Add" type="submit" value="Add"> <input id="addAdmin" class="button button-primary center" title="Add" type="submit" value="Add">
<a class="button button-secondary center" href="/settings/configure_admin" title="Cancel">Cancel</a> <a class="button button-secondary center" href="/settings/admin/configure" title="Cancel">Cancel</a>
</div> </div>
</form> </form>

View File

@ -0,0 +1,13 @@
{%- extends "nav" -%}
{%- block card %}
<!-- ADMIN SETTINGS MENU -->
<div class="card center">
<div class="card-container">
<!-- BUTTONS -->
<div id="settingsButtons">
<a id="change" class="button button-primary center" href="/settings/admin/change_password" title="Change Password">Change Password</a>
<a id="configure" class="button button-primary center" href="/settings/admin/configure" title="Configure Admin">Configure Admin</a>
</div>
</div>
</div>
{%- endblock card -%}

View File

@ -18,7 +18,7 @@
</div> </div>
{% endif %} {% endif %}
<form id="configureDNS" action="/network/dns" method="post"> <form id="configureDNS" action="/settings/network/dns" method="post">
<div class="input-wrapper"> <div class="input-wrapper">
<!-- input for externaldomain --> <!-- input for externaldomain -->
<label id="external_domain" class="label-small input-label font-near-black"> <label id="external_domain" class="label-small input-label font-near-black">

View File

@ -10,7 +10,7 @@
<input id="pass" name="pass" class="center input" type="password" placeholder="Password" title="Password for WiFi access point"> <input id="pass" name="pass" class="center input" type="password" placeholder="Password" title="Password for WiFi access point">
<div id="buttonDiv"> <div id="buttonDiv">
<input id="addWifi" class="button button-primary center" title="Add" type="submit" value="Add"> <input id="addWifi" class="button button-primary center" title="Add" type="submit" value="Add">
<a class="button button-secondary center" href="/network" title="Cancel">Cancel</a> <a class="button button-secondary center" href="/settings/network" title="Cancel">Cancel</a>
</div> </div>
</form> </form>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->

View File

@ -11,7 +11,7 @@
<!-- left column --> <!-- left column -->
<!-- network mode icon with label --> <!-- network mode icon with label -->
<div class="grid-column-1"> <div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-active" src="icons/router.svg" alt="WiFi router"> <img id="netModeIcon" class="center icon icon-active" src="/icons/router.svg" alt="WiFi router">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="Access Point Online">ONLINE</label> <label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="Access Point Online">ONLINE</label>
</div> </div>
<!-- right column --> <!-- right column -->
@ -27,10 +27,10 @@
</div> </div>
<!-- BUTTONS --> <!-- BUTTONS -->
<div id="buttons"> <div id="buttons">
<a class="button button-primary center" href="/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a> <a class="button button-primary center" href="/settings/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a>
<a id="connectWifi" class="button button-primary center" href="/network/wifi/activate" title="Enable WiFi">Enable WiFi</a> <a id="connectWifi" class="button button-primary center" href="/settings/network/wifi/activate" title="Enable WiFi">Enable WiFi</a>
<a id="listWifi" class="button button-primary center" href="/network/wifi" title="List WiFi Networks">List WiFi Networks</a> <a id="listWifi" class="button button-primary center" href="/settings/network/wifi" title="List WiFi Networks">List WiFi Networks</a>
<a id="viewUsage" class="button button-primary center" href="/network/wifi/usage" title="View Data Usage">View Data Usage</a> <a id="viewUsage" class="button button-primary center" href="/settings/network/wifi/usage" title="View Data Usage">View Data Usage</a>
</div> </div>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %} {% include "snippets/flash_message" %}
@ -38,14 +38,14 @@
<div class="card-container"> <div class="card-container">
<div class="three-grid"> <div class="three-grid">
<div class="stack"> <div class="stack">
<img id="devices" class="icon icon-medium" title="Connected devices" src="icons/devices.svg" alt="Digital devices"> <img id="devices" class="icon icon-medium" title="Connected devices" src="/icons/devices.svg" alt="Digital devices">
<div class="flex-grid" style="padding-top: 0.5rem;"> <div class="flex-grid" style="padding-top: 0.5rem;">
<label class="label-medium" for="devices" style="padding-right: 3px;" title="Number of connected devices"></label> <label class="label-medium" for="devices" style="padding-right: 3px;" title="Number of connected devices"></label>
</div> </div>
<label class="label-small font-gray">DEVICES</label> <label class="label-small font-gray">DEVICES</label>
</div> </div>
<div class="stack"> <div class="stack">
<img id="dataDownload" class="icon icon-medium" title="Download" src="icons/down-arrow.svg" alt="Download"> <img id="dataDownload" class="icon icon-medium" title="Download" src="/icons/down-arrow.svg" alt="Download">
<div class="flex-grid" style="padding-top: 0.5rem;"> <div class="flex-grid" style="padding-top: 0.5rem;">
{%- if ap_traffic -%} {%- if ap_traffic -%}
<label class="label-medium" for="dataDownload" style="padding-right: 3px;" title="Data download total in {{ ap_traffic.rx_unit }}">{{ ap_traffic.received }}</label> <label class="label-medium" for="dataDownload" style="padding-right: 3px;" title="Data download total in {{ ap_traffic.rx_unit }}">{{ ap_traffic.received }}</label>
@ -58,7 +58,7 @@
<label class="label-small font-gray">DOWNLOAD</label> <label class="label-small font-gray">DOWNLOAD</label>
</div> </div>
<div class="stack"> <div class="stack">
<img id="dataUpload" class="icon icon-medium" title="Upload" src="icons/up-arrow.svg" alt="Upload"> <img id="dataUpload" class="icon icon-medium" title="Upload" src="/icons/up-arrow.svg" alt="Upload">
<div class="flex-grid" style="padding-top: 0.5rem;"> <div class="flex-grid" style="padding-top: 0.5rem;">
{%- if ap_traffic -%} {%- if ap_traffic -%}
<label class="label-medium" for="dataUpload" style="padding-right: 3px;" title="Data upload total in {{ ap_traffic.tx_unit }}">{{ ap_traffic.transmitted }}</label> <label class="label-medium" for="dataUpload" style="padding-right: 3px;" title="Data upload total in {{ ap_traffic.tx_unit }}">{{ ap_traffic.transmitted }}</label>
@ -83,12 +83,12 @@
<!-- left column --> <!-- left column -->
<!-- network mode icon with label --> <!-- network mode icon with label -->
<div class="grid-column-1"> <div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-active" src="icons/wifi.svg" alt="WiFi online"> <img id="netModeIcon" class="center icon icon-active" src="/icons/wifi.svg" alt="WiFi online">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">ONLINE</label> <label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">ONLINE</label>
{%- else %} {%- else %}
<div id="netInfoBox" class="two-grid capsule warning-border" title="PeachCloud network mode and status"> <div id="netInfoBox" class="two-grid capsule warning-border" title="PeachCloud network mode and status">
<div class="grid-column-1"> <div class="grid-column-1">
<img id="netModeIcon" class="center icon icon-inactive" src="icons/wifi.svg" alt="WiFi offline"> <img id="netModeIcon" class="center icon icon-inactive" src="/icons/wifi.svg" alt="WiFi offline">
<label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">OFFLINE</label> <label id="netModeLabel" for="netModeIcon" class="center label-small font-gray" title="WiFi Client Status">OFFLINE</label>
{%- endif %} {%- endif %}
</div> </div>
@ -105,13 +105,13 @@
</div> </div>
<!-- BUTTONS --> <!-- BUTTONS -->
<div id="buttons"> <div id="buttons">
<a class="button button-primary center" href="/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a> <a class="button button-primary center" href="/settings/network/wifi/add" title="Add WiFi Network">Add WiFi Network</a>
<a id="deployAccessPoint" class="button button-primary center" href="/network/ap/activate" title="Deploy Access Point">Deploy Access Point</a> <a id="deployAccessPoint" class="button button-primary center" href="/settings/network/ap/activate" title="Deploy Access Point">Deploy Access Point</a>
<a id="listWifi" class="button button-primary center" href="/network/wifi" title="List WiFi Networks">List WiFi Networks</a> <a id="listWifi" class="button button-primary center" href="/settings/network/wifi" title="List WiFi Networks">List WiFi Networks</a>
<a id="viewUsage" class="button button-primary center" href="/network/wifi/usage" title="View Data Usage">View Data Usage</a> <a id="viewUsage" class="button button-primary center" href="/settings/network/wifi/usage" title="View Data Usage">View Data Usage</a>
<a id="configureDNS" class="button button-primary center" href="/network/dns" title="Configure DNS">Configure DNS</a> <a id="configureDNS" class="button button-primary center" href="/settings/network/dns" title="Configure DNS">Configure DNS</a>
<a id="changePassword" class="button button-primary center" href="/settings/change_password" title="Change Password">Change Password</a> <a id="changePassword" class="button button-primary center" href="/settings/admin/change_password" title="Change Password">Change Password</a>
<a id="configureAdmin" class="button button-primary center" href="/settings/configure_admin" title="Configure Admin">Configure Admin</a> <a id="configureAdmin" class="button button-primary center" href="/settings/admin/configure_admin" title="Configure Admin">Configure Admin</a>
</div> </div>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %} {% include "snippets/flash_message" %}
@ -120,14 +120,14 @@
<!-- row of icons representing network statistics --> <!-- row of icons representing network statistics -->
<div class="three-grid"> <div class="three-grid">
<div class="stack"> <div class="stack">
<img id="netSignal" class="icon icon-medium" alt="Signal" title="WiFi Signal (%)" src="icons/low-signal.svg"> <img id="netSignal" class="icon icon-medium" alt="Signal" title="WiFi Signal (%)" src="/icons/low-signal.svg">
<div class="flex-grid" style="padding-top: 0.5rem;"> <div class="flex-grid" style="padding-top: 0.5rem;">
<label class="label-medium" for="netSignal" style="padding-right: 3px;" title="Signal strength of WiFi connection (%)">{% if wlan_rssi %}{{ wlan_rssi }}{% else %}0{% endif %}%</label> <label class="label-medium" for="netSignal" style="padding-right: 3px;" title="Signal strength of WiFi connection (%)">{% if wlan_rssi %}{{ wlan_rssi }}{% else %}0{% endif %}%</label>
</div> </div>
<label class="label-small font-gray">SIGNAL</label> <label class="label-small font-gray">SIGNAL</label>
</div> </div>
<div class="stack"> <div class="stack">
<img id="dataDownload" class="icon icon-medium" alt="Download" title="WiFi download total" src="icons/down-arrow.svg"> <img id="dataDownload" class="icon icon-medium" alt="Download" title="WiFi download total" src="/icons/down-arrow.svg">
<div class="flex-grid" style="padding-top: 0.5rem;"> <div class="flex-grid" style="padding-top: 0.5rem;">
{%- if wlan_traffic %} {%- if wlan_traffic %}
<!-- display wlan traffic data --> <!-- display wlan traffic data -->
@ -142,7 +142,7 @@
<label class="label-small font-gray">DOWNLOAD</label> <label class="label-small font-gray">DOWNLOAD</label>
</div> </div>
<div class="stack"> <div class="stack">
<img id="dataUpload" class="icon icon-medium" alt="Upload" title="WiFi upload total" src="icons/up-arrow.svg"> <img id="dataUpload" class="icon icon-medium" alt="Upload" title="WiFi upload total" src="/icons/up-arrow.svg">
<div class="flex-grid" style="padding-top: 0.5rem;"> <div class="flex-grid" style="padding-top: 0.5rem;">
{%- if wlan_traffic %} {%- if wlan_traffic %}
<!-- display wlan traffic data --> <!-- display wlan traffic data -->

View File

@ -29,7 +29,7 @@
<div class="card-container" style="padding-top: 0;"> <div class="card-container" style="padding-top: 0;">
<div id="buttonDiv"> <div id="buttonDiv">
{%- if wlan_ssid == selected -%} {%- if wlan_ssid == selected -%}
<form id="wifiDisconnect" action="/network/wifi/disconnect" method="post"> <form id="wifiDisconnect" action="/settings/network/wifi/disconnect" method="post">
<!-- hidden element: allows ssid to be sent in request --> <!-- hidden element: allows ssid to be sent in request -->
<input id="disconnectSsid" name="ssid" type="text" value="{{ ssid }}" style="display: none;"> <input id="disconnectSsid" name="ssid" type="text" value="{{ ssid }}" style="display: none;">
<input id="disconnectWifi" class="button button-warning center" title="Disconnect from Network" type="submit" value="Disconnect"> <input id="disconnectWifi" class="button button-warning center" title="Disconnect from Network" type="submit" value="Disconnect">
@ -44,14 +44,14 @@
{# Set 'in_list' to true to allow correct Add button display #} {# Set 'in_list' to true to allow correct Add button display #}
{% set_global in_list = true %} {% set_global in_list = true %}
{%- if wlan_ssid != selected and ap.state == "Available" -%} {%- if wlan_ssid != selected and ap.state == "Available" -%}
<form id="wifiConnect" action="/network/wifi/connect" method="post"> <form id="wifiConnect" action="/settings/network/wifi/connect" method="post">
<!-- hidden element: allows ssid to be sent in request --> <!-- hidden element: allows ssid to be sent in request -->
<input id="connectSsid" name="ssid" type="text" value="{{ ap.ssid }}" style="display: none;"> <input id="connectSsid" name="ssid" type="text" value="{{ ap.ssid }}" style="display: none;">
<input id="connectWifi" class="button button-primary center" title="Connect to Network" type="submit" value="Connect"> <input id="connectWifi" class="button button-primary center" title="Connect to Network" type="submit" value="Connect">
</form> </form>
{%- endif -%} {%- endif -%}
<a class="button button-primary center" href="/network/wifi/modify?ssid={{ ssid }}">Modify</a> <a class="button button-primary center" href="/settings/network/wifi/modify?ssid={{ ssid }}">Modify</a>
<form id="wifiForget" action="/network/wifi/forget" method="post"> <form id="wifiForget" action="/settings/network/wifi/forget" method="post">
<!-- hidden element: allows ssid to be sent in request --> <!-- hidden element: allows ssid to be sent in request -->
<input id="forgetSsid" name="ssid" type="text" value="{{ ap.ssid }}" style="display: none;"> <input id="forgetSsid" name="ssid" type="text" value="{{ ap.ssid }}" style="display: none;">
<input id="forgetWifi" class="button button-warning center" title="Forget Network" type="submit" value="Forget"> <input id="forgetWifi" class="button button-warning center" title="Forget Network" type="submit" value="Forget">
@ -61,9 +61,9 @@
{%- endif -%} {%- endif -%}
{%- if in_list == false -%} {%- if in_list == false -%}
{# Display the Add button if AP creds not already in saved networks list #} {# Display the Add button if AP creds not already in saved networks list #}
<a class="button button-primary center" href="/network/wifi/add?ssid={{ ssid }}">Add</a> <a class="button button-primary center" href="/settings/network/wifi/add?ssid={{ ssid }}">Add</a>
{%- endif -%} {%- endif -%}
<a class="button button-secondary center" href="/network/wifi" title="Cancel">Cancel</a> <a class="button button-secondary center" href="/settings/network/wifi" title="Cancel">Cancel</a>
</div> </div>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %} {% include "snippets/flash_message" %}

View File

@ -9,19 +9,19 @@
{%- for ssid, state in wlan_networks %} {%- for ssid, state in wlan_networks %}
<li> <li>
{%- if ssid == wlan_ssid %} {%- if ssid == wlan_ssid %}
<a class="list-item link primary-bg" href="/network/wifi?ssid={{ wlan_ssid }}"> <a class="list-item link primary-bg" href="/settings/network/wifi?ssid={{ wlan_ssid }}">
<img id="netStatus" class="icon icon-active icon-medium list-icon" src="/icons/wifi.svg" alt="WiFi online"> <img id="netStatus" class="icon icon-active icon-medium list-icon" src="/icons/wifi.svg" alt="WiFi online">
<p class="list-text">{{ wlan_ssid }}</p> <p class="list-text">{{ wlan_ssid }}</p>
<label class="label-small list-label font-gray" for="netStatus" title="Status">Connected</label> <label class="label-small list-label font-gray" for="netStatus" title="Status">Connected</label>
</a> </a>
{%- elif state == "Available" %} {%- elif state == "Available" %}
<a class="list-item link light-bg" href="/network/wifi?ssid={{ ssid }}"> <a class="list-item link light-bg" href="/settings/network/wifi?ssid={{ ssid }}">
<img id="netStatus" class="icon icon-inactive icon-medium list-icon" src="/icons/wifi.svg" alt="WiFi offline"> <img id="netStatus" class="icon icon-inactive icon-medium list-icon" src="/icons/wifi.svg" alt="WiFi offline">
<p class="list-text">{{ ssid }}</p> <p class="list-text">{{ ssid }}</p>
<label class="label-small list-label font-gray" for="netStatus" title="Status">{{ state }}</label> <label class="label-small list-label font-gray" for="netStatus" title="Status">{{ state }}</label>
</a> </a>
{%- else %} {%- else %}
<a class="list-item link" href="/network/wifi?ssid={{ ssid }}"> <a class="list-item link" href="/settings/network/wifi?ssid={{ ssid }}">
<img id="netStatus" class="icon icon-inactive icon-medium list-icon" src="/icons/wifi.svg" alt="WiFi offline"> <img id="netStatus" class="icon icon-inactive icon-medium list-icon" src="/icons/wifi.svg" alt="WiFi offline">
<p class="list-text">{{ ssid }}</p> <p class="list-text">{{ ssid }}</p>
<label class="label-small list-label font-gray" for="netStatus" title="Status">{{ state }}</label> <label class="label-small list-label font-gray" for="netStatus" title="Status">{{ state }}</label>

View File

@ -3,14 +3,14 @@
<!-- NETWORK MODIFY AP PASSWORD FORM --> <!-- NETWORK MODIFY AP PASSWORD FORM -->
<div class="card center"> <div class="card center">
<div class="card-container"> <div class="card-container">
<form id="wifiModify" action="/network/wifi/modify" method="post"> <form id="wifiModify" action="/settings/network/wifi/modify" method="post">
<!-- input for network ssid --> <!-- input for network ssid -->
<input id="ssid" name="ssid" class="center input" type="text" placeholder="SSID" title="Network name (SSID) for WiFi access point" value="{% if selected %}{{ selected }}{% endif %}" autofocus> <input id="ssid" name="ssid" class="center input" type="text" placeholder="SSID" title="Network name (SSID) for WiFi access point" value="{% if selected %}{{ selected }}{% endif %}" autofocus>
<!-- input for network password --> <!-- input for network password -->
<input id="pass" name="pass" class="center input" type="password" placeholder="Password" title="Password for WiFi access point"> <input id="pass" name="pass" class="center input" type="password" placeholder="Password" title="Password for WiFi access point">
<div id="buttonDiv"> <div id="buttonDiv">
<input id="savePassword" class="button button-primary center" title="Save" type="submit" value="Save"> <input id="savePassword" class="button button-primary center" title="Save" type="submit" value="Save">
<a class="button button-secondary center" href="/network" title="Cancel">Cancel</a> <a class="button button-secondary center" href="/settings/network" title="Cancel">Cancel</a>
</div> </div>
</form> </form>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->

View File

@ -1,7 +1,7 @@
{%- extends "nav" -%} {%- extends "nav" -%}
{%- block card -%} {%- block card -%}
<!-- NETWORK DATA ALERTS VIEW --> <!-- NETWORK DATA ALERTS VIEW -->
<form id="wifiAlerts" action="/network/wifi/usage" class="card center" method="post"> <form id="wifiAlerts" action="/settings/network/wifi/usage" class="card center" method="post">
<div class="stack capsule" style="margin-left: 2rem; margin-right: 2rem;"> <div class="stack capsule" style="margin-left: 2rem; margin-right: 2rem;">
<div class="flex-grid"> <div class="flex-grid">
<label id="dataTotal" class="label-large" title="Data download total in MB">{{ data_total.total / 1024 / 1024 | round }}</label> <label id="dataTotal" class="label-large" title="Data download total in MB">{{ data_total.total / 1024 / 1024 | round }}</label>
@ -37,8 +37,8 @@
</div> </div>
<div id="buttonDiv" class="button-div"> <div id="buttonDiv" class="button-div">
<input id="updateAlerts" class="button button-primary center" title="Update" type="submit" value="Update"> <input id="updateAlerts" class="button button-primary center" title="Update" type="submit" value="Update">
<a id="resetTotal" class="button button-warning center" href="/network/wifi/usage/reset" title="Reset stored usage total to zero">Reset</a> <a id="resetTotal" class="button button-warning center" href="/settings/network/wifi/usage/reset" title="Reset stored usage total to zero">Reset</a>
<a class="button button-secondary center" href="/network" title="Cancel">Cancel</a> <a class="button button-secondary center" href="/settings/network" title="Cancel">Cancel</a>
</div> </div>
<!-- FLASH MESSAGE --> <!-- FLASH MESSAGE -->
{% include "snippets/flash_message" %} {% include "snippets/flash_message" %}