Remove json routes, utils and javascript #65
@ -4,11 +4,11 @@
|
||||
|
||||
## Web Interface for PeachCloud
|
||||
|
||||
**peach-web** provides a web interface for the PeachCloud device. It serves static assets and exposes a JSON API for programmatic interactions.
|
||||
**peach-web** provides a web interface for the PeachCloud device.
|
||||
|
||||
Initial development is focused on administration of the device itself, beginning with networking functionality, with SSB-related administration to be integrated at a later stage.
|
||||
|
||||
The peach-web stack currently consists of [Rocket](https://rocket.rs/) (Rust web framework), [Tera](http://tera.netlify.com/) (Rust template engine), HTML, CSS and JavaScript.
|
||||
The peach-web stack currently consists of [Rocket](https://rocket.rs/) (Rust web framework), [Tera](http://tera.netlify.com/) (Rust template engine), HTML and CSS.
|
||||
|
||||
_Note: This is a work-in-progress._
|
||||
|
||||
@ -95,13 +95,13 @@ Remove configuration files (not removed with `apt-get remove`):
|
||||
|
||||
### Design
|
||||
|
||||
`peach-web` is built on the Rocket webserver and Tera templating engine. It presents a web interface for interacting with the device. HTML is rendered server-side. Request handlers call JSON-RPC microservices and serve HTML and assets. A JSON API is exposed for remote calls and dynamic client-side content updates (via 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.
|
||||
`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 `peach-` libraries and serve HTML and assets. 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.
|
||||
|
||||
### Configuration
|
||||
|
||||
Configuration variables are stored in /var/lib/peachcloud/config.yml.
|
||||
Peach-web also updates this file when changes are made to configurations via
|
||||
the web interface. peach-web has no database, so all configurations are stored in this file.
|
||||
the web interface. peach-web has no database, so all configurations are stored in this file.
|
||||
|
||||
#### Dynamic DNS Configuration
|
||||
|
||||
|
@ -42,7 +42,6 @@ use crate::routes::index::*;
|
||||
use crate::routes::scuttlebutt::*;
|
||||
use crate::routes::status::device::*;
|
||||
use crate::routes::status::network::*;
|
||||
use crate::routes::status::ping::*;
|
||||
|
||||
use crate::routes::settings::admin::*;
|
||||
use crate::routes::settings::dns::*;
|
||||
@ -123,43 +122,6 @@ fn init_rocket() -> Rocket<Build> {
|
||||
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"))
|
||||
.register("/", catchers![not_found, internal_error, forbidden])
|
||||
.attach(Template::fairing())
|
||||
|
@ -3,10 +3,7 @@ use rocket::form::{Form, FromForm};
|
||||
use rocket::http::{Cookie, CookieJar, Status};
|
||||
use rocket::request::{self, FlashMessage, FromRequest, Request};
|
||||
use rocket::response::{Flash, Redirect};
|
||||
use rocket::serde::{
|
||||
json::{Json, Value},
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
use rocket::{get, post, Config};
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
@ -14,7 +11,7 @@ use peach_lib::error::PeachError;
|
||||
use peach_lib::password_utils;
|
||||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::utils::{build_json_response, TemplateOrRedirect};
|
||||
use crate::utils::TemplateOrRedirect;
|
||||
|
||||
// HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES
|
||||
|
||||
@ -260,25 +257,6 @@ pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Temp
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[post("/reset_password", data = "<reset_password_form>")]
|
||||
pub fn reset_password_form_endpoint(reset_password_form: Json<ResetPasswordForm>) -> Value {
|
||||
let result = save_reset_password_form(reset_password_form.into_inner());
|
||||
match result {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "New password is now saved. Return home to login.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = format!("{}", err);
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /send_password_reset
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@ -414,24 +392,3 @@ pub fn change_password_post(password_form: Form<PasswordForm>, _auth: Authentica
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// JSON change password form request handler.
|
||||
#[post("/change_password", data = "<password_form>")]
|
||||
pub fn save_password_form_endpoint(
|
||||
password_form: Json<PasswordForm>,
|
||||
_auth: Authenticated,
|
||||
) -> Value {
|
||||
let result = save_password_form(password_form.into_inner());
|
||||
match result {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Your password was successfully changed".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = format!("{}", err);
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,7 @@ use rocket::{
|
||||
form::{Form, FromForm},
|
||||
get, post,
|
||||
request::FlashMessage,
|
||||
serde::{
|
||||
json::{Json, Value},
|
||||
Deserialize, Serialize,
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
@ -23,7 +20,6 @@ use peach_lib::jsonrpc_core::types::error::ErrorCode;
|
||||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils::build_json_response;
|
||||
|
||||
#[derive(Debug, Deserialize, FromForm)]
|
||||
pub struct DnsForm {
|
||||
@ -153,20 +149,3 @@ pub fn configure_dns_post(dns: Form<DnsForm>, _auth: Authenticated) -> Template
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/dns/configure", data = "<dns_form>")]
|
||||
pub fn save_dns_configuration_endpoint(dns_form: Json<DnsForm>, _auth: Authenticated) -> Value {
|
||||
let result = save_dns_configuration(dns_form.into_inner());
|
||||
match result {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "New dynamic dns configuration is now enabled".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = format!("{}", err);
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,7 @@ use rocket::{
|
||||
get, post,
|
||||
request::FlashMessage,
|
||||
response::{Flash, Redirect},
|
||||
serde::{
|
||||
json::{json, Json, Value},
|
||||
Deserialize, Serialize,
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
uri, UriDisplayQuery,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
@ -19,7 +16,6 @@ use peach_lib::network_client::{AccessPoint, Networks, Scan};
|
||||
use peach_lib::stats_client::Traffic;
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils::build_json_response;
|
||||
use crate::utils::monitor;
|
||||
use crate::utils::monitor::{Alert, Data, Threshold};
|
||||
|
||||
@ -760,311 +756,3 @@ pub fn wifi_usage_alerts(thresholds: Form<Threshold>, _auth: Authenticated) -> F
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JSON ROUTES FOR NETWORK SETTINGS
|
||||
|
||||
#[post("/wifi/usage", data = "<thresholds>")]
|
||||
pub fn update_wifi_alerts(thresholds: Json<Threshold>, _auth: Authenticated) -> Value {
|
||||
match monitor::update_store(thresholds.into_inner()) {
|
||||
Ok(_) => {
|
||||
debug!("WiFi data usage thresholds updated.");
|
||||
let status = "success".to_string();
|
||||
let msg = "Updated alert threshold and flags.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Failed to update WiFi data usage thresholds.");
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to update WiFi data usage thresholds.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/wifi/usage/reset")]
|
||||
pub fn reset_data_total(_auth: Authenticated) -> Value {
|
||||
match monitor::reset_data() {
|
||||
Ok(_) => {
|
||||
debug!("Reset network data usage total.");
|
||||
let traffic = match network_client::traffic("wlan0") {
|
||||
Ok(t) => t,
|
||||
Err(_) => Traffic {
|
||||
received: 0,
|
||||
transmitted: 0,
|
||||
rx_unit: None,
|
||||
tx_unit: None,
|
||||
},
|
||||
};
|
||||
// current wifi traffic values as bytes
|
||||
let current_traffic = traffic.received + traffic.transmitted;
|
||||
let data = json!(current_traffic);
|
||||
let status = "success".to_string();
|
||||
let msg = "Reset network data usage total.".to_string();
|
||||
build_json_response(status, Some(data), Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Failed to reset network data usage total.");
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to reset network data usage total.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR ACCESS POINT ACTIVATION
|
||||
|
||||
#[post("/activate_ap")]
|
||||
pub fn activate_ap(_auth: Authenticated) -> Value {
|
||||
// activate the wireless access point
|
||||
debug!("Activating WiFi access point.");
|
||||
match network_client::activate_ap() {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
build_json_response(status, None, None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to activate WiFi access point.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR WIFI CLIENT MANAGEMENT
|
||||
|
||||
#[post("/activate_client")]
|
||||
pub fn activate_client(_auth: Authenticated) -> Value {
|
||||
// activate the wireless client
|
||||
debug!("Activating WiFi client mode.");
|
||||
match network_client::activate_client() {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
build_json_response(status, None, None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to activate WiFi client mode.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/wifi", data = "<wifi>")]
|
||||
pub fn add_wifi_credentials(wifi: Json<WiFi>, _auth: Authenticated) -> Value {
|
||||
// generate and write wifi config to wpa_supplicant
|
||||
match network_client::add(&wifi.ssid, &wifi.pass) {
|
||||
Ok(_) => {
|
||||
debug!("Added WiFi credentials.");
|
||||
// force reread of wpa_supplicant.conf file with new credentials
|
||||
match network_client::reconfigure() {
|
||||
Ok(_) => debug!("Successfully reconfigured wpa_supplicant."),
|
||||
Err(_) => warn!("Failed to reconfigure wpa_supplicant."),
|
||||
}
|
||||
// json response for successful update
|
||||
let status = "success".to_string();
|
||||
let msg = "WiFi credentials added.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
debug!("Failed to add WiFi credentials.");
|
||||
// json response for failed update
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to add WiFi credentials.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/wifi/connect", data = "<ssid>")]
|
||||
pub fn connect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value {
|
||||
// retrieve the id for the given network ssid
|
||||
match network_client::id("wlan0", &ssid.ssid) {
|
||||
// attempt connection with the given network
|
||||
Ok(id) => match network_client::connect(&id, "wlan0") {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Connected to chosen network.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to connect to chosen network.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to retrieve the network ID.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/wifi/disconnect", data = "<ssid>")]
|
||||
pub fn disconnect_ap(ssid: Json<Ssid>, _auth: Authenticated) -> Value {
|
||||
// attempt to disable the current network for wlan0 interface
|
||||
match network_client::disable("wlan0", &ssid.ssid) {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Disconnected from WiFi network.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to disconnect from WiFi network.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/wifi/forget", data = "<network>")]
|
||||
pub fn forget_ap(network: Json<Ssid>, _auth: Authenticated) -> Value {
|
||||
let ssid = &network.ssid;
|
||||
match network_client::forget("wlan0", ssid) {
|
||||
Ok(_) => {
|
||||
debug!("Removed WiFi credentials for chosen network.");
|
||||
let status = "success".to_string();
|
||||
let msg = "WiFi network credentials removed.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Failed to remove WiFi credentials.");
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to remove WiFi network credentials.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/wifi/modify", data = "<wifi>")]
|
||||
pub fn modify_password(wifi: Json<WiFi>, _auth: Authenticated) -> Value {
|
||||
let ssid = &wifi.ssid;
|
||||
let pass = &wifi.pass;
|
||||
// we are using a helper function (`update`) to delete the old
|
||||
// credentials and add the new ones. this is because the wpa_cli method
|
||||
// for updating the password does not work.
|
||||
match network_client::update("wlan0", ssid, pass) {
|
||||
Ok(_) => {
|
||||
debug!("WiFi password updated for chosen network.");
|
||||
let status = "success".to_string();
|
||||
let msg = "WiFi password updated.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Failed to update WiFi password.");
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to update WiFi password.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR NETWORK STATE QUERIES
|
||||
|
||||
#[get("/ip")]
|
||||
pub fn return_ip(_auth: Authenticated) -> Value {
|
||||
// retrieve ip for wlan0 or set to x.x.x.x if not found
|
||||
let wlan_ip = match network_client::ip("wlan0") {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => "x.x.x.x".to_string(),
|
||||
};
|
||||
// retrieve ip for ap0 or set to x.x.x.x if not found
|
||||
let ap_ip = match network_client::ip("ap0") {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => "x.x.x.x".to_string(),
|
||||
};
|
||||
let data = json!({
|
||||
"wlan0": wlan_ip,
|
||||
"ap0": ap_ip
|
||||
});
|
||||
let status = "success".to_string();
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
|
||||
#[get("/rssi")]
|
||||
pub fn return_rssi(_auth: Authenticated) -> Value {
|
||||
// retrieve rssi for connected network
|
||||
match network_client::rssi("wlan0") {
|
||||
Ok(rssi) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(rssi);
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Not currently connected to an access point.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/ssid")]
|
||||
pub fn return_ssid(_auth: Authenticated) -> Value {
|
||||
// retrieve ssid for connected network
|
||||
match network_client::ssid("wlan0") {
|
||||
Ok(network) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(network);
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Not currently connected to an access point.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/state")]
|
||||
pub fn return_state(_auth: Authenticated) -> Value {
|
||||
// retrieve state of wlan0 or set to x.x.x.x if not found
|
||||
let wlan_state = match network_client::state("wlan0") {
|
||||
Ok(state) => state,
|
||||
Err(_) => "unavailable".to_string(),
|
||||
};
|
||||
// retrieve state for ap0 or set to x.x.x.x if not found
|
||||
let ap_state = match network_client::state("ap0") {
|
||||
Ok(state) => state,
|
||||
Err(_) => "unavailable".to_string(),
|
||||
};
|
||||
let data = json!({
|
||||
"wlan0": wlan_state,
|
||||
"ap0": ap_state
|
||||
});
|
||||
let status = "success".to_string();
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
|
||||
#[get("/status")]
|
||||
pub fn return_status(_auth: Authenticated) -> Value {
|
||||
// retrieve status info for wlan0 interface
|
||||
match network_client::status("wlan0") {
|
||||
Ok(network) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(network);
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Not currently connected to an access point.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/wifi")]
|
||||
pub fn scan_networks(_auth: Authenticated) -> Value {
|
||||
// retrieve scan results for access-points within range of wlan0
|
||||
match network_client::available_networks("wlan0") {
|
||||
Ok(networks) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(networks);
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Unable to scan for networks. Interface may be deactivated.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use log::{debug, info, warn};
|
||||
use log::info;
|
||||
use rocket::{
|
||||
get, post,
|
||||
get,
|
||||
request::FlashMessage,
|
||||
response::{Flash, Redirect},
|
||||
serde::json::Value,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Serialize;
|
||||
@ -21,7 +20,6 @@ use peach_stats::{
|
||||
};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils::build_json_response;
|
||||
|
||||
// HELPERS AND ROUTES FOR /status
|
||||
|
||||
@ -189,25 +187,6 @@ pub fn reboot_cmd(_auth: Authenticated) -> Flash<Redirect> {
|
||||
}
|
||||
}
|
||||
|
||||
/// JSON request handler for device reboot.
|
||||
#[post("/api/v1/admin/reboot")]
|
||||
pub fn reboot_device(_auth: Authenticated) -> Value {
|
||||
match reboot() {
|
||||
Ok(_) => {
|
||||
debug!("Going down for reboot...");
|
||||
let status = "success".to_string();
|
||||
let msg = "Going down for reboot.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Reboot failed");
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to reboot the device.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /power/shutdown
|
||||
|
||||
/// Executes a system command to shutdown the device immediately.
|
||||
@ -227,25 +206,6 @@ pub fn shutdown_cmd(_auth: Authenticated) -> Flash<Redirect> {
|
||||
}
|
||||
}
|
||||
|
||||
// shutdown the device
|
||||
#[post("/power/shutdown")]
|
||||
pub fn shutdown_device(_auth: Authenticated) -> Value {
|
||||
match shutdown() {
|
||||
Ok(_) => {
|
||||
debug!("Going down for shutdown...");
|
||||
let status = "success".to_string();
|
||||
let msg = "Going down for shutdown.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("Shutdown failed");
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to shutdown the device.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /power
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
|
@ -1,3 +1,2 @@
|
||||
pub mod device;
|
||||
pub mod network;
|
||||
pub mod ping;
|
||||
|
@ -1,78 +0,0 @@
|
||||
//! Helper routes for pinging services to check that they are active
|
||||
use log::{debug, warn};
|
||||
use rocket::get;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
use peach_lib::network_client;
|
||||
use peach_lib::oled_client;
|
||||
use peach_lib::stats_client;
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils::build_json_response;
|
||||
|
||||
/// Status route: useful for checking connectivity from web client.
|
||||
#[get("/ping")]
|
||||
pub fn ping_pong(_auth: Authenticated) -> Value {
|
||||
//pub fn ping_pong() -> Value {
|
||||
// ping pong
|
||||
let status = "success".to_string();
|
||||
let msg = "pong!".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
|
||||
/// Status route: check availability of `peach-network` microservice.
|
||||
#[get("/ping/network")]
|
||||
pub fn ping_network(_auth: Authenticated) -> Value {
|
||||
match network_client::ping() {
|
||||
Ok(_) => {
|
||||
debug!("peach-network responded successfully");
|
||||
let status = "success".to_string();
|
||||
let msg = "peach-network is available.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("peach-network failed to respond");
|
||||
let status = "error".to_string();
|
||||
let msg = "peach-network is unavailable.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Status route: check availability of `peach-oled` microservice.
|
||||
#[get("/ping/oled")]
|
||||
pub fn ping_oled(_auth: Authenticated) -> Value {
|
||||
match oled_client::ping() {
|
||||
Ok(_) => {
|
||||
debug!("peach-oled responded successfully");
|
||||
let status = "success".to_string();
|
||||
let msg = "peach-oled is available.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("peach-oled failed to respond");
|
||||
let status = "error".to_string();
|
||||
let msg = "peach-oled is unavailable.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Status route: check availability of `peach-stats` microservice.
|
||||
#[get("/ping/stats")]
|
||||
pub fn ping_stats(_auth: Authenticated) -> Value {
|
||||
match stats_client::ping() {
|
||||
Ok(_) => {
|
||||
debug!("peach-stats responded successfully");
|
||||
let status = "success".to_string();
|
||||
let msg = "peach-stats is available.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("peach-stats failed to respond");
|
||||
let status = "error".to_string();
|
||||
let msg = "peach-stats is unavailable.".to_string();
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
@ -3,26 +3,16 @@ pub mod monitor;
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
use rocket::response::{Redirect, Responder};
|
||||
use rocket::serde::json::{Value, json};
|
||||
use rocket::serde::{Serialize};
|
||||
use rocket::serde::Serialize;
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
pub fn build_json_response(
|
||||
status: String,
|
||||
data: Option<Value>,
|
||||
msg: Option<String>,
|
||||
) -> Value {
|
||||
json!({ "status": status, "data": data, "msg": msg })
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct FlashContext {
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
/// A helper enum which allows routes to either return a Template or a Redirect
|
||||
/// from: https://github.com/SergioBenitez/Rocket/issues/253#issuecomment-532356066
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
@ -30,4 +20,4 @@ pub struct FlashContext {
|
||||
pub enum TemplateOrRedirect {
|
||||
Template(Template),
|
||||
Redirect(Redirect),
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `change_password.html.tera` template
|
||||
|
||||
- intercept button click for save (form submission of passwords)
|
||||
- perform json api call
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_AUTH.changePassword();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_AUTH = {};
|
||||
|
||||
// catch click of 'Save' button and make POST request
|
||||
PEACH_AUTH.changePassword = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.addEventListener('submit', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// capture form data
|
||||
var formElement = document.querySelector("form");
|
||||
// create form data object from the changePassword form element
|
||||
var formData = new FormData(formElement);
|
||||
var object = {};
|
||||
// assign values from form
|
||||
formData.forEach(function(value, key){
|
||||
object[key] = value;
|
||||
});
|
||||
// perform json serialization
|
||||
console.log(object);
|
||||
var jsonData = JSON.stringify(object);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Saving new password.");
|
||||
// send change_password POST request
|
||||
fetch("/api/v1/admin/change_password", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
var changePassInstance = PEACH_AUTH;
|
||||
changePassInstance.changePassword();
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Common javascript functions shared by multiple pages:
|
||||
* - flashMsg
|
||||
* - logout
|
||||
*
|
||||
*/
|
||||
|
||||
var PEACH = {};
|
||||
|
||||
// display a message by appending a paragraph element
|
||||
PEACH.flashMsg = function(status, msg) {
|
||||
// set the class of the element according to status
|
||||
var elementClass;
|
||||
if (status === "success") {
|
||||
elementClass = "capsule center-text flash-message font-success";
|
||||
} else if (status === "info") {
|
||||
elementClass = "capsule center-text flash-message font-info";
|
||||
} else {
|
||||
elementClass = "capsule center-text flash-message font-failure";
|
||||
};
|
||||
|
||||
var flashElement = document.getElementById("flashMsg");
|
||||
// if flashElement exists, update the class & text
|
||||
if (flashElement) {
|
||||
flashElement.className = elementClass;
|
||||
flashElement.innerText = msg;
|
||||
// if flashElement does not exist, create it, set id, class, text & append
|
||||
} else {
|
||||
// create new div for flash message
|
||||
var flashDiv = document.createElement("DIV");
|
||||
// set div attributes
|
||||
flashDiv.id = "flashMsg";
|
||||
flashDiv.className = elementClass;
|
||||
// add json response message to flash message div
|
||||
var flashMsg = document.createTextNode(msg);
|
||||
flashDiv.appendChild(flashMsg);
|
||||
// insert the flash message div below the button div
|
||||
var buttonDiv = document.getElementById("buttonDiv");
|
||||
// flashDiv will be added to the end since buttonDiv is the last
|
||||
// child within the parent element (card-container div)
|
||||
buttonDiv.parentNode.insertBefore(flashDiv, buttonDiv.nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
var commonInstance = PEACH;
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `configure_dns.html.tera` template,
|
||||
corresponding to the web route `/settings/network/dns`
|
||||
|
||||
- intercept button click for save (form submission of dns settings)
|
||||
- perform json api call
|
||||
- update the dom
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_DNS = {};
|
||||
|
||||
// catch click of 'Add' button and make POST request
|
||||
PEACH_DNS.configureDns = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.addEventListener('submit', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// capture form data
|
||||
var formElement = document.querySelector("form");
|
||||
// create form data object from the configureDNS form element
|
||||
var formData = new FormData(formElement);
|
||||
var object = {};
|
||||
// set checkbox to false (the value is only passed to formData if it is "on")
|
||||
object["enable_dyndns"] = false;
|
||||
// assign values from form
|
||||
formData.forEach(function(value, key){
|
||||
// convert checkbox to bool
|
||||
if (key === "enable_dyndns") {
|
||||
value = (value === "on");
|
||||
}
|
||||
object[key] = value;
|
||||
});
|
||||
// perform json serialization
|
||||
console.log(object);
|
||||
var jsonData = JSON.stringify(object);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Saving new DNS configurations");
|
||||
// send add_wifi POST request
|
||||
fetch("/api/v1/network/dns/configure", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
let statusIndicator = document.getElementById("dyndns-status-indicator");
|
||||
// only remove the "dyndns-status-indicator" element if it exists
|
||||
if (statusIndicator != null ) statusIndicator.remove();
|
||||
})
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
var configureDnsInstance = PEACH_DNS;
|
||||
configureDnsInstance.configureDns();
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `network_add.html.tera` template,
|
||||
corresponding to the web route `/network/wifi/add`
|
||||
|
||||
- intercept button click for add (form submission of credentials)
|
||||
- perform json api call
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_NETWORK.add();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_NETWORK = {};
|
||||
|
||||
// catch click of 'Add' button and make POST request
|
||||
PEACH_NETWORK.add = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.addEventListener('submit', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// capture form data
|
||||
var formElement = document.querySelector("form");
|
||||
// create form data object from the wifiCreds form element
|
||||
var formData = new FormData(formElement);
|
||||
var object = {};
|
||||
// assign ssid and pass from form
|
||||
formData.forEach(function(value, key){
|
||||
object[key] = value;
|
||||
});
|
||||
// perform json serialization
|
||||
var jsonData = JSON.stringify(object);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Adding WiFi credentials...");
|
||||
// send add_wifi POST request
|
||||
fetch("/api/v1/network/wifi", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
var addInstance = PEACH_NETWORK;
|
||||
addInstance.add();
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `network_card.html.tera` template,
|
||||
corresponding to the web route `/settings/network`
|
||||
|
||||
- intercept form submissions
|
||||
- perform json api calls
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_NETWORK.activateAp();
|
||||
PEACH_NETWORK.activateClient();
|
||||
PEACH_NETWORK.apMode();
|
||||
PEACH_NETWORK.clientMode();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_NETWORK = {};
|
||||
|
||||
// catch click of 'Deploy Access Point' and make POST request
|
||||
PEACH_NETWORK.activateAp = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var deployAP = document.getElementById('deployAccessPoint');
|
||||
if (deployAP) {
|
||||
deployAP.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Deploying access point...");
|
||||
// send activate_ap POST request
|
||||
fetch("/api/v1/network/activate_ap", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
console.log(jsonData.msg);
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
// if ap activation is successful, update the ui
|
||||
if (jsonData.status === "success") {
|
||||
PEACH_NETWORK.apMode();
|
||||
}
|
||||
})
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// catch click of 'Enable WiFi' and make POST request
|
||||
PEACH_NETWORK.activateClient = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var enableWifi = document.getElementById('connectWifi');
|
||||
if (enableWifi) {
|
||||
enableWifi.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Enabling WiFi client...");
|
||||
// send activate_ap POST request
|
||||
fetch("/api/v1/network/activate_client", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
console.log(jsonData.msg);
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
// if client activation is successful, update the ui
|
||||
if (jsonData.status === "success") {
|
||||
PEACH_NETWORK.clientMode();
|
||||
}
|
||||
})
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// replace 'Deploy Access Point' button with 'Enable WiFi' button
|
||||
PEACH_NETWORK.apMode = function() {
|
||||
// create Enable WiFi button and add it to button div
|
||||
var wifiButton = document.createElement("A");
|
||||
wifiButton.className = "button center";
|
||||
wifiButton.href = "/settings/network/wifi/activate";
|
||||
wifiButton.id = "connectWifi";
|
||||
var label = "Enable WiFi";
|
||||
var buttonText = document.createTextNode(label);
|
||||
wifiButton.appendChild(buttonText);
|
||||
|
||||
// append the new button to the buttons div
|
||||
let buttons = document.getElementById("buttons");
|
||||
buttons.appendChild(wifiButton);
|
||||
|
||||
// remove the old 'Deploy Access Point' button
|
||||
let apButton = document.getElementById("deployAccessPoint");
|
||||
apButton.remove();
|
||||
}
|
||||
|
||||
// replace 'Enable WiFi' button with 'Deploy Access Point' button
|
||||
PEACH_NETWORK.clientMode = function() {
|
||||
// create Deploy Access Point button and add it to button div
|
||||
var apButton = document.createElement("A");
|
||||
apButton.className = "button center";
|
||||
apButton.href = "/settings/network/ap/activate";
|
||||
apButton.id = "deployAccessPoint";
|
||||
var label = "Deploy Access Point";
|
||||
var buttonText = document.createTextNode(label);
|
||||
apButton.appendChild(buttonText);
|
||||
|
||||
// append the new button to the buttons div
|
||||
let buttons = document.getElementById("buttons");
|
||||
buttons.appendChild(apButton);
|
||||
|
||||
// remove the old 'Enable Wifi' button
|
||||
let wifiButton = document.getElementById("connectWifi");
|
||||
wifiButton.remove();
|
||||
}
|
||||
|
||||
var networkInstance = PEACH_NETWORK;
|
||||
networkInstance.activateAp();
|
||||
networkInstance.activateClient();
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `network_detail.html.tera` template,
|
||||
corresponding to the web route `/settings/network/wifi?<ssid>`
|
||||
|
||||
- intercept button clicks for connect, disconnect and forget
|
||||
- perform json api call
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_NETWORK.connect();
|
||||
PEACH_NETWORK.disconnect();
|
||||
PEACH_NETWORK.forget();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_NETWORK = {};
|
||||
|
||||
// catch click of 'Connect' button (form) and make POST request
|
||||
PEACH_NETWORK.connect = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var connectWifi = document.getElementById('connectWifi');
|
||||
if (connectWifi) {
|
||||
connectWifi.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// retrieve ssid value and append to form data object
|
||||
var ssid = document.getElementById('connectSsid').value;
|
||||
// create key:value pair
|
||||
var ssidData = { ssid: ssid };
|
||||
// perform json serialization
|
||||
var jsonData = JSON.stringify(ssidData);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Connecting to access point...");
|
||||
// send add_wifi POST request
|
||||
fetch("/api/v1/network/wifi/connect", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// catch click of 'Disconnect' button and make POST request
|
||||
PEACH_NETWORK.disconnect = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var disconnectWifi = document.getElementById('disconnectWifi');
|
||||
if (disconnectWifi) {
|
||||
disconnectWifi.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// retrieve ssid value and append to form data object
|
||||
var ssid = document.getElementById('disconnectSsid').value;
|
||||
// create key:value pair
|
||||
var ssidData = { ssid: ssid };
|
||||
// perform json serialization
|
||||
var jsonData = JSON.stringify(ssidData);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Disconnecting from access point...");
|
||||
// send disconnect_wifi POST request
|
||||
fetch("/api/v1/network/wifi/disconnect", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// catch click of 'Forget' button (form) and make POST request
|
||||
PEACH_NETWORK.forget = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var forgetWifi = document.getElementById('forgetWifi');
|
||||
if (forgetWifi) {
|
||||
forgetWifi.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// retrieve ssid value
|
||||
var ssid = document.getElementById('forgetSsid').value;
|
||||
// create key:value pair
|
||||
var ssidData = { ssid: ssid };
|
||||
// perform json serialization
|
||||
var jsonData = JSON.stringify(ssidData);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Removing credentials for access point...");
|
||||
// send forget_ap POST request
|
||||
fetch("/api/v1/network/wifi/forget", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var detailInstance = PEACH_NETWORK;
|
||||
detailInstance.connect();
|
||||
detailInstance.disconnect();
|
||||
detailInstance.forget();
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `network_modify.html.tera` template
|
||||
|
||||
- intercept button click for modify (form submission of credentials)
|
||||
- perform json api call
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_NETWORK.modify();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_NETWORK = {};
|
||||
|
||||
// catch click of 'Save' button and make POST request
|
||||
PEACH_NETWORK.modify = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.addEventListener('submit', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// capture form data
|
||||
var formElement = document.querySelector("form");
|
||||
// create form data object from the wifiModify form element
|
||||
var formData = new FormData(formElement);
|
||||
var object = {};
|
||||
// assign ssid and pass from form
|
||||
formData.forEach(function(value, key){
|
||||
object[key] = value;
|
||||
});
|
||||
// perform json serialization
|
||||
var jsonData = JSON.stringify(object);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Updating WiFi password...");
|
||||
// send new_password POST request
|
||||
fetch("/api/v1/network/wifi/modify", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
var modifyInstance = PEACH_NETWORK;
|
||||
modifyInstance.modify();
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `network_usage.html.tera` template,
|
||||
corresponding to the web route `/settings/network/wifi/usage`
|
||||
|
||||
- intercept form submissions
|
||||
- perform json api calls
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_NETWORK.updateAlerts();
|
||||
PEACH_NETWORK.resetUsage();
|
||||
PEACH_NETWORK.toggleWarning();
|
||||
PEACH_NETWORK.toggleCutoff();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_NETWORK = {};
|
||||
|
||||
// catch click of 'Update' and make POST request
|
||||
PEACH_NETWORK.updateAlerts = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.addEventListener('submit', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// capture form data
|
||||
var formElement = document.querySelector("form");
|
||||
let warn = formElement.elements.warn.value;
|
||||
let cut = formElement.elements.cut.value;
|
||||
let warn_flag = formElement.elements.warn_flag.checked;
|
||||
let cut_flag = formElement.elements.cut_flag.checked;
|
||||
// perform json serialization
|
||||
var jsonData = JSON.stringify({
|
||||
"warn": parseFloat(warn),
|
||||
"cut": parseFloat(cut),
|
||||
"warn_flag": warn_flag,
|
||||
"cut_flag": cut_flag,
|
||||
});
|
||||
// send update_alerts POST request
|
||||
fetch("/api/v1/network/wifi/usage", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
// catch click of 'Reset' and make POST request
|
||||
PEACH_NETWORK.resetUsage = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var resetBtn = document.getElementById('resetTotal');
|
||||
if (resetBtn) {
|
||||
resetBtn.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// send reset_data_usage POST request
|
||||
fetch("/api/v1/network/wifi/usage/reset", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
console.log(jsonData.msg);
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
// if reset is successful, update the ui
|
||||
if (jsonData.status === "success") {
|
||||
console.log(jsonData.data);
|
||||
PEACH_NETWORK.updateTotal(jsonData.data);
|
||||
}
|
||||
})
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// update data usage total in ui
|
||||
PEACH_NETWORK.updateTotal = function(data) {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log(data);
|
||||
let label = document.getElementById("dataTotal");
|
||||
// take usage total as bytes, convert to MB and round to nearest integer
|
||||
label.textContent = (data / 1024 / 1024).round();
|
||||
});
|
||||
};
|
||||
|
||||
// update ui for warning
|
||||
PEACH_NETWORK.toggleWarning = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
let i = document.getElementById("warnIcon");
|
||||
let warnCheck = document.getElementById("warnCheck");
|
||||
warnCheck.addEventListener('click', function(e) {
|
||||
console.log('Toggling warning icon state');
|
||||
if (warnCheck.checked) {
|
||||
i.className = "icon";
|
||||
} else {
|
||||
i.className = "icon icon-inactive";
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// update ui for cutoff
|
||||
PEACH_NETWORK.toggleCutoff = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
let i = document.getElementById("cutIcon");
|
||||
let cutCheck = document.getElementById("cutCheck");
|
||||
cutCheck.addEventListener('click', function(e) {
|
||||
console.log('Toggling cutoff icon state');
|
||||
if (cutCheck.checked) {
|
||||
i.className = "icon";
|
||||
} else {
|
||||
i.className = "icon icon-inactive";
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var usageInstance = PEACH_NETWORK;
|
||||
usageInstance.resetUsage();
|
||||
usageInstance.toggleWarning();
|
||||
usageInstance.toggleCutoff();
|
||||
usageInstance.updateAlerts();
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
|
||||
behavioural layer for the `power.html.tera` template,
|
||||
corresponding to the web route `/power`
|
||||
|
||||
- intercept button clicks for reboot & shutdown
|
||||
- perform json api calls
|
||||
- update the dom
|
||||
|
||||
methods:
|
||||
|
||||
PEACH_DEVICE.reboot();
|
||||
PEACH_DEVICE.shutdown();
|
||||
|
||||
*/
|
||||
|
||||
var PEACH_DEVICE = {};
|
||||
|
||||
// catch click of 'Reboot' button and make POST request
|
||||
PEACH_DEVICE.reboot = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var rebootDevice = document.getElementById('rebootBtn');
|
||||
if (rebootDevice) {
|
||||
rebootDevice.addEventListener('click', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// write reboot flash message
|
||||
PEACH.flashMsg("success", "Rebooting the device...");
|
||||
// send reboot_device POST request
|
||||
fetch("/api/v1/admin/reboot", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
console.log(jsonData.msg);
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// catch click of 'Shutdown' button and make POST request
|
||||
PEACH_DEVICE.shutdown = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var shutdownDevice = document.getElementById('shutdownBtn');
|
||||
if (shutdownDevice) {
|
||||
shutdownDevice.addEventListener('click', function(e) {
|
||||
// prevent form submission (default behavior)
|
||||
e.preventDefault();
|
||||
// write shutdown flash message
|
||||
PEACH.flashMsg("success", "Shutting down the device...");
|
||||
// send shutdown_device POST request
|
||||
fetch("/api/v1/shutdown", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
console.log(jsonData.msg);
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var deviceInstance = PEACH_DEVICE;
|
||||
deviceInstance.reboot();
|
||||
deviceInstance.shutdown();
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* behavioural layer for the `reset_password.html.tera` template,
|
||||
*/
|
||||
|
||||
var PEACH_AUTH = {};
|
||||
|
||||
// catch click of 'Save' button and make POST request
|
||||
PEACH_AUTH.resetPassword = function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.body.addEventListener('submit', function(e) {
|
||||
// prevent redirect on button press (default behavior)
|
||||
e.preventDefault();
|
||||
// capture form data
|
||||
var formElement = document.querySelector("form");
|
||||
// create form data object from the changePassword form element
|
||||
var formData = new FormData(formElement);
|
||||
var object = {};
|
||||
// assign values from form
|
||||
formData.forEach(function(value, key){
|
||||
object[key] = value;
|
||||
});
|
||||
// perform json serialization
|
||||
console.log(object);
|
||||
var jsonData = JSON.stringify(object);
|
||||
// write in-progress status message to ui
|
||||
PEACH.flashMsg("info", "Saving new password.");
|
||||
// send add_wifi POST request
|
||||
fetch("/api/v1/admin/reset_password", {
|
||||
method: "post",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: jsonData
|
||||
})
|
||||
.then( (response) => {
|
||||
return response.json()
|
||||
})
|
||||
.then( (jsonData) => {
|
||||
// write json response message to ui
|
||||
PEACH.flashMsg(jsonData.status, jsonData.msg);
|
||||
})
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
var resetPassInstance = PEACH_AUTH;
|
||||
resetPassInstance.resetPassword();
|
@ -13,5 +13,4 @@
|
||||
<body>
|
||||
{% block nav %}{% endblock nav %}
|
||||
</body>
|
||||
<script type="text/javascript" src="/js/common.js"></script>
|
||||
</html>
|
||||
|
@ -10,9 +10,6 @@
|
||||
</div>
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
<!-- NO SCRIPT FOR WHEN JS IS DISABLED -->
|
||||
{% include "snippets/noscript" %}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/power_menu.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
@ -17,9 +17,6 @@
|
||||
</form>
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
<!-- NO SCRIPT FOR WHEN JS IS DISABLED -->
|
||||
{% include "snippets/noscript" %}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/change_password.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
@ -35,14 +35,8 @@
|
||||
<input id="changePasswordButton" class="button button-primary center" title="Add" type="submit" value="Save">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
|
||||
<!-- NO SCRIPT FOR WHEN JS IS DISABLED -->
|
||||
{% include "snippets/noscript" %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/reset_password.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
@ -15,9 +15,6 @@
|
||||
</form>
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
<!-- NO SCRIPT FOR WHEN JS IS DISABLED -->
|
||||
{% include "snippets/noscript" %}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/network_add.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
@ -69,7 +69,6 @@
|
||||
{% include "snippets/flash_message" %}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/network_detail.js"></script>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
|
@ -2,9 +2,7 @@
|
||||
{%- block card %}
|
||||
<!-- CONFIGURE DNS FORM -->
|
||||
<div class="card center">
|
||||
|
||||
<div class="form-container">
|
||||
|
||||
{% if enable_dyndns %}
|
||||
<!-- DYNDNS STATUS INDICATOR -->
|
||||
<div id="dyndns-status-indicator" class="stack capsule{% if is_dyndns_online %} success-border{% else %} warning-border{% endif %}">
|
||||
@ -17,7 +15,6 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form id="configureDNS" action="/settings/network/dns" method="post">
|
||||
<div class="input-wrapper">
|
||||
<!-- input for externaldomain -->
|
||||
@ -25,7 +22,6 @@
|
||||
<label class="label-small input-label font-gray" for="external_domain" style="padding-top: 0.25rem;">External Domain (optional)</label>
|
||||
<input id="external_domain" class="form-input" style="margin-bottom: 0;"
|
||||
name="external_domain" type="text" title="external domain" value="{{ external_domain }}"></label>
|
||||
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<div>
|
||||
@ -41,16 +37,13 @@
|
||||
<label id="cut" class="label-small input-label font-near-black">
|
||||
<label class="label-small input-label font-gray" for="cut" style="padding-top: 0.25rem;">Dynamic DNS Domain</label>
|
||||
<input id="dyndns_domain" class="alert-input" name="dynamic_domain" placeholder="" type="text" title="dyndns_domain" value="{{ dyndns_subdomain }}">.dyn.peachcloud.org</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="buttonDiv">
|
||||
<input id="configureDNSButton" class="button button-primary center" title="Add" type="submit" value="Save">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- FLASH MESSAGE -->
|
||||
<!-- FLASH MESSAGE -->
|
||||
<!-- check for flash message and display accordingly -->
|
||||
{% if flash_msg and flash_name == "success" %}
|
||||
<!-- display success message -->
|
||||
@ -62,14 +55,6 @@
|
||||
<!-- display error message -->
|
||||
<div class="capsule center-text flash-message font-failure">{{ flash_msg }}.</div>
|
||||
{%- endif -%}
|
||||
|
||||
<!-- share ux information with the user if JS is disabled -->
|
||||
<noscript>
|
||||
<div class="capsule flash-message info-border">
|
||||
<p class="center-text">This website may be temporarily unresponsive while settings are being saved.</p>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/configure_dns.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
@ -43,5 +43,4 @@
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
</form>
|
||||
<script type="text/javascript" src="/js/network_usage.js"></script>
|
||||
{%- endblock card %}
|
||||
|
@ -20,5 +20,4 @@
|
||||
<!-- FLASH MESSAGE -->
|
||||
{% include "snippets/flash_message" %}
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/network_card.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
@ -17,5 +17,4 @@
|
||||
{% include "snippets/flash_message" %}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/js/network_modify.js"></script>
|
||||
{%- endblock card -%}
|
||||
|
Loading…
Reference in New Issue
Block a user