move context objects and builders to dedicated directory
This commit is contained in:
parent
a5f0d991fa
commit
166f4d25ae
@ -3,7 +3,7 @@ use rocket::{
|
||||
form::{Form, FromForm},
|
||||
get, post,
|
||||
request::FlashMessage,
|
||||
serde::{Deserialize, Serialize},
|
||||
serde::Deserialize,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
@ -14,8 +14,9 @@ use peach_lib::{
|
||||
jsonrpc_core::types::error::ErrorCode,
|
||||
};
|
||||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::{
|
||||
context::dns::ConfigureDNSContext, error::PeachWebError, routes::authentication::Authenticated,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, FromForm)]
|
||||
pub struct DnsForm {
|
||||
@ -73,40 +74,6 @@ pub fn save_dns_configuration(dns_form: DnsForm) -> Result<(), PeachWebError> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ConfigureDNSContext {
|
||||
pub external_domain: String,
|
||||
pub dyndns_subdomain: String,
|
||||
pub enable_dyndns: bool,
|
||||
pub is_dyndns_online: bool,
|
||||
pub back: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
}
|
||||
|
||||
impl ConfigureDNSContext {
|
||||
pub fn build() -> ConfigureDNSContext {
|
||||
// TODO: replace `unwrap` with resilient error handling
|
||||
let peach_config = config_manager::load_peach_config().unwrap();
|
||||
let dyndns_fulldomain = peach_config.dyn_domain;
|
||||
let is_dyndns_online = dyndns_client::is_dns_updater_online().unwrap();
|
||||
let dyndns_subdomain =
|
||||
dyndns_client::get_dyndns_subdomain(&dyndns_fulldomain).unwrap_or(dyndns_fulldomain);
|
||||
|
||||
ConfigureDNSContext {
|
||||
external_domain: peach_config.external_domain,
|
||||
dyndns_subdomain,
|
||||
enable_dyndns: peach_config.dyn_enabled,
|
||||
is_dyndns_online,
|
||||
back: None,
|
||||
title: None,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/dns")]
|
||||
pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
let mut context = ConfigureDNSContext::build();
|
||||
@ -128,28 +95,23 @@ pub fn configure_dns(flash: Option<FlashMessage>, _auth: Authenticated) -> Templ
|
||||
#[post("/dns", data = "<dns>")]
|
||||
pub fn configure_dns_post(dns: Form<DnsForm>, _auth: Authenticated) -> Template {
|
||||
let result = save_dns_configuration(dns.into_inner());
|
||||
|
||||
let mut context = ConfigureDNSContext::build();
|
||||
|
||||
// set back icon link to network route
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.title = Some("Configure DNS".to_string());
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
let mut context = ConfigureDNSContext::build();
|
||||
|
||||
// set back icon link to network route
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.title = Some("Configure DNS".to_string());
|
||||
context.flash_name = Some("success".to_string());
|
||||
context.flash_msg = Some("New dynamic dns configuration is now enabled".to_string());
|
||||
|
||||
Template::render("settings/network/configure_dns", &context)
|
||||
}
|
||||
Err(err) => {
|
||||
let mut context = ConfigureDNSContext::build();
|
||||
|
||||
// set back icon link to network route
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.title = Some("Configure DNS".to_string());
|
||||
context.flash_name = Some("error".to_string());
|
||||
context.flash_msg = Some(format!("Failed to save dns configurations: {}", err));
|
||||
|
||||
Template::render("settings/network/configure_dns", &context)
|
||||
}
|
||||
}
|
||||
|
||||
Template::render("settings/network/configure_dns", &context)
|
||||
}
|
||||
|
@ -1,25 +1,24 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use log::{debug, warn};
|
||||
use rocket::{
|
||||
form::{Form, FromForm},
|
||||
get, post,
|
||||
request::FlashMessage,
|
||||
response::{Flash, Redirect},
|
||||
serde::{Deserialize, Serialize},
|
||||
serde::Deserialize,
|
||||
uri, UriDisplayQuery,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
use rocket_dyn_templates::{tera::Context, Template};
|
||||
|
||||
use peach_lib::{
|
||||
// TODO: replace this with peach_network::network
|
||||
network_client::{AccessPoint, Networks, Scan},
|
||||
stats_client::Traffic,
|
||||
use peach_network::network;
|
||||
|
||||
use crate::{
|
||||
context,
|
||||
context::network::{NetworkAlertContext, NetworkDetailContext, NetworkListContext},
|
||||
routes::authentication::Authenticated,
|
||||
utils::{monitor, monitor::Threshold},
|
||||
AP_IFACE, WLAN_IFACE,
|
||||
};
|
||||
|
||||
use crate::routes::authentication::Authenticated;
|
||||
use crate::utils::monitor::{Alert, Data, Threshold};
|
||||
|
||||
// STRUCTS USED BY NETWORK ROUTES
|
||||
|
||||
#[derive(Debug, Deserialize, FromForm, UriDisplayQuery)]
|
||||
@ -51,12 +50,12 @@ pub fn wifi_usage_reset(_auth: Authenticated) -> Flash<Redirect> {
|
||||
pub fn connect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let ssid = &network.ssid;
|
||||
let url = uri!(network_detail(ssid = ssid));
|
||||
match network_client::id("wlan0", ssid) {
|
||||
Ok(id) => match network_client::connect(&id, "wlan0") {
|
||||
match network::id(&*WLAN_IFACE, ssid) {
|
||||
Ok(Some(id)) => match network::connect(&id, &*WLAN_IFACE) {
|
||||
Ok(_) => Flash::success(Redirect::to(url), "Connected to chosen network"),
|
||||
Err(_) => Flash::error(Redirect::to(url), "Failed to connect to chosen network"),
|
||||
},
|
||||
Err(_) => Flash::error(Redirect::to(url), "Failed to retrieve the network ID"),
|
||||
_ => Flash::error(Redirect::to(url), "Failed to retrieve the network ID"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +63,7 @@ pub fn connect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect
|
||||
pub fn disconnect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let ssid = &network.ssid;
|
||||
let url = uri!(network_home);
|
||||
match network_client::disable("wlan0", ssid) {
|
||||
match network::disable(&*WLAN_IFACE, ssid) {
|
||||
Ok(_) => Flash::success(Redirect::to(url), "Disconnected from WiFi network"),
|
||||
Err(_) => Flash::error(Redirect::to(url), "Failed to disconnect from WiFi network"),
|
||||
}
|
||||
@ -74,7 +73,7 @@ pub fn disconnect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redir
|
||||
pub fn forget_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
|
||||
let ssid = &network.ssid;
|
||||
let url = uri!(network_home);
|
||||
match network_client::forget("wlan0", ssid) {
|
||||
match network::forget(&*WLAN_IFACE, ssid) {
|
||||
Ok(_) => Flash::success(Redirect::to(url), "WiFi credentials removed"),
|
||||
Err(_) => Flash::error(
|
||||
Redirect::to(url),
|
||||
@ -85,21 +84,19 @@ pub fn forget_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect>
|
||||
|
||||
#[get("/wifi/modify?<ssid>")]
|
||||
pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
let mut context = NetworkAddContext {
|
||||
back: Some("/settings/network/wifi".to_string()),
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
selected: Some(ssid.to_string()),
|
||||
title: Some("Update WiFi Password".to_string()),
|
||||
};
|
||||
let mut context = Context::new();
|
||||
context.insert("back", &Some("/settings/network/wifi".to_string()));
|
||||
context.insert("title", &Some("Update WiFi Password".to_string()));
|
||||
context.insert("selected", &Some(ssid.to_string()));
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
// add flash message contents to the context object
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
context.insert("flash_name", &Some(flash.kind().to_string()));
|
||||
context.insert("flash_msg", &Some(flash.message().to_string()));
|
||||
};
|
||||
// template_dir is set in Rocket.toml
|
||||
Template::render("settings/network/modify_ap", &context)
|
||||
|
||||
Template::render("settings/network/modify_ap", &context.into_json())
|
||||
}
|
||||
|
||||
#[post("/wifi/modify", data = "<wifi>")]
|
||||
@ -107,7 +104,7 @@ pub fn wifi_set_password(wifi: Form<WiFi>, _auth: Authenticated) -> Flash<Redire
|
||||
let ssid = &wifi.ssid;
|
||||
let pass = &wifi.pass;
|
||||
let url = uri!(network_detail(ssid = ssid));
|
||||
match network_client::update("wlan0", ssid, pass) {
|
||||
match network::update(&*WLAN_IFACE, ssid, pass) {
|
||||
Ok(_) => Flash::success(Redirect::to(url), "WiFi password updated".to_string()),
|
||||
Err(_) => Flash::error(
|
||||
Redirect::to(url),
|
||||
@ -118,174 +115,23 @@ pub fn wifi_set_password(wifi: Form<WiFi>, _auth: Authenticated) -> Flash<Redire
|
||||
|
||||
// HELPERS AND ROUTES FOR /settings/network
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct NetworkContext {
|
||||
pub ap_ip: String,
|
||||
pub ap_ssid: String,
|
||||
pub ap_state: String,
|
||||
pub ap_traffic: Option<Traffic>,
|
||||
pub wlan_ip: String,
|
||||
pub wlan_rssi: Option<String>,
|
||||
pub wlan_scan: Option<Vec<Scan>>,
|
||||
pub wlan_ssid: String,
|
||||
pub wlan_state: String,
|
||||
pub wlan_status: String,
|
||||
pub wlan_traffic: Option<Traffic>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
// allows for passing in the ssid of a chosen access point
|
||||
// this is used in the network_detail template
|
||||
pub selected: Option<String>,
|
||||
// page title for header in navbar
|
||||
pub title: Option<String>,
|
||||
// url for back-arrow link
|
||||
pub back: Option<String>,
|
||||
}
|
||||
|
||||
impl NetworkContext {
|
||||
pub fn build() -> NetworkContext {
|
||||
let ap_ip = match network_client::ip("ap0") {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => "x.x.x.x".to_string(),
|
||||
};
|
||||
let ap_ssid = match network_client::ssid("ap0") {
|
||||
Ok(ssid) => ssid,
|
||||
Err(_) => "Not currently activated".to_string(),
|
||||
};
|
||||
let ap_state = match network_client::state("ap0") {
|
||||
Ok(state) => state,
|
||||
Err(_) => "Interface unavailable".to_string(),
|
||||
};
|
||||
let ap_traffic = match network_client::traffic("ap0") {
|
||||
Ok(traffic) => {
|
||||
let mut t = traffic;
|
||||
// modify traffic values & assign measurement unit
|
||||
// based on received and transmitted values
|
||||
// if received > 999 MB, convert it to GB
|
||||
if t.received > 1_047_527_424 {
|
||||
t.received /= 1_073_741_824;
|
||||
t.rx_unit = Some("GB".to_string());
|
||||
} else if t.received > 0 {
|
||||
// otherwise, convert it to MB
|
||||
t.received = (t.received / 1024) / 1024;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.received = 0;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
}
|
||||
|
||||
if t.transmitted > 1_047_527_424 {
|
||||
t.transmitted /= 1_073_741_824;
|
||||
t.tx_unit = Some("GB".to_string());
|
||||
} else if t.transmitted > 0 {
|
||||
t.transmitted = (t.transmitted / 1024) / 1024;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.transmitted = 0;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
}
|
||||
Some(t)
|
||||
}
|
||||
Err(_) => None,
|
||||
};
|
||||
let wlan_ip = match network_client::ip("wlan0") {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => "x.x.x.x".to_string(),
|
||||
};
|
||||
let wlan_rssi = match network_client::rssi_percent("wlan0") {
|
||||
Ok(rssi) => Some(rssi),
|
||||
Err(_) => None,
|
||||
};
|
||||
let wlan_scan = match network_client::available_networks("wlan0") {
|
||||
Ok(networks) => {
|
||||
let scan: Vec<Scan> = serde_json::from_str(networks.as_str())
|
||||
.expect("Failed to deserialize scan_networks response");
|
||||
Some(scan)
|
||||
}
|
||||
Err(_) => None,
|
||||
};
|
||||
let wlan_ssid = match network_client::ssid("wlan0") {
|
||||
Ok(ssid) => ssid,
|
||||
Err(_) => "Not connected".to_string(),
|
||||
};
|
||||
let wlan_state = match network_client::state("wlan0") {
|
||||
Ok(state) => state,
|
||||
Err(_) => "Interface unavailable".to_string(),
|
||||
};
|
||||
let wlan_status = match network_client::status("wlan0") {
|
||||
Ok(status) => status,
|
||||
Err(_) => "Interface unavailable".to_string(),
|
||||
};
|
||||
let wlan_traffic = match network_client::traffic("wlan0") {
|
||||
Ok(traffic) => {
|
||||
let mut t = traffic;
|
||||
// modify traffic values & assign measurement unit
|
||||
// based on received and transmitted values
|
||||
// if received > 999 MB, convert it to GB
|
||||
if t.received > 1_047_527_424 {
|
||||
t.received /= 1_073_741_824;
|
||||
t.rx_unit = Some("GB".to_string());
|
||||
} else if t.received > 0 {
|
||||
// otherwise, convert it to MB
|
||||
t.received = (t.received / 1024) / 1024;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.received = 0;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
}
|
||||
|
||||
if t.transmitted > 1_047_527_424 {
|
||||
t.transmitted /= 1_073_741_824;
|
||||
t.tx_unit = Some("GB".to_string());
|
||||
} else if t.transmitted > 0 {
|
||||
t.transmitted = (t.transmitted / 1024) / 1024;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.transmitted = 0;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
}
|
||||
Some(t)
|
||||
}
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
NetworkContext {
|
||||
ap_ip,
|
||||
ap_ssid,
|
||||
ap_state,
|
||||
ap_traffic,
|
||||
wlan_ip,
|
||||
wlan_rssi,
|
||||
wlan_scan,
|
||||
wlan_ssid,
|
||||
wlan_state,
|
||||
wlan_status,
|
||||
wlan_traffic,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
selected: None,
|
||||
title: None,
|
||||
back: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// assign context through context_builder call
|
||||
let mut context = NetworkContext::build();
|
||||
// set back button (nav) url
|
||||
context.back = Some("/settings".to_string());
|
||||
// set page title
|
||||
context.title = Some("Network Configuration".to_string());
|
||||
// assign context
|
||||
let mut context = Context::new();
|
||||
context.insert("back", &Some("/settings"));
|
||||
context.insert("title", &Some("Network Configuration"));
|
||||
context.insert("ap_state", &context::network::ap_state());
|
||||
|
||||
// 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());
|
||||
context.insert("flash_name", &Some(flash.kind().to_string()));
|
||||
context.insert("flash_msg", &Some(flash.message().to_string()));
|
||||
};
|
||||
|
||||
// template_dir is set in Rocket.toml
|
||||
Template::render("settings/network/menu", &context)
|
||||
Template::render("settings/network/menu", &context.into_json())
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /settings/network/ap/activate
|
||||
@ -294,7 +140,7 @@ pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Templa
|
||||
pub fn deploy_ap(_auth: Authenticated) -> Flash<Redirect> {
|
||||
// activate the wireless access point
|
||||
debug!("Activating WiFi access point.");
|
||||
match network_client::activate_ap() {
|
||||
match network::start_iface_service(&*AP_IFACE) {
|
||||
Ok(_) => Flash::success(
|
||||
Redirect::to("/settings/network"),
|
||||
"Activated WiFi access point",
|
||||
@ -308,252 +154,37 @@ pub fn deploy_ap(_auth: Authenticated) -> Flash<Redirect> {
|
||||
|
||||
// HELPERS AND ROUTES FOR /settings/network/wifi
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct NetworkListContext {
|
||||
pub ap_state: String,
|
||||
pub back: Option<String>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub wlan_networks: HashMap<String, String>,
|
||||
pub wlan_ssid: String,
|
||||
}
|
||||
|
||||
impl NetworkListContext {
|
||||
pub fn build() -> NetworkListContext {
|
||||
// list of networks saved in the wpa_supplicant.conf
|
||||
let wlan_list = match network_client::saved_networks() {
|
||||
Ok(ssids) => {
|
||||
let networks: Vec<Networks> = serde_json::from_str(ssids.as_str())
|
||||
.expect("Failed to deserialize scan_list response");
|
||||
networks
|
||||
}
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
|
||||
// list of networks currently in range (online & accessible)
|
||||
let wlan_scan = match network_client::available_networks("wlan0") {
|
||||
Ok(networks) => {
|
||||
let scan: Vec<Networks> = serde_json::from_str(networks.as_str())
|
||||
.expect("Failed to deserialize scan_networks response");
|
||||
scan
|
||||
}
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
|
||||
let wlan_ssid = match network_client::ssid("wlan0") {
|
||||
Ok(ssid) => ssid,
|
||||
Err(_) => "Not connected".to_string(),
|
||||
};
|
||||
|
||||
// create a hashmap to combine wlan_list & wlan_scan without repetition
|
||||
let mut wlan_networks = HashMap::new();
|
||||
for ap in wlan_scan {
|
||||
wlan_networks.insert(ap.ssid, "Available".to_string());
|
||||
}
|
||||
for network in wlan_list {
|
||||
// insert ssid (with state) only if it doesn't already exist
|
||||
wlan_networks
|
||||
.entry(network.ssid)
|
||||
.or_insert_with(|| "Not in range".to_string());
|
||||
}
|
||||
|
||||
let ap_state = match network_client::state("ap0") {
|
||||
Ok(state) => state,
|
||||
Err(_) => "Interface unavailable".to_string(),
|
||||
};
|
||||
|
||||
NetworkListContext {
|
||||
ap_state,
|
||||
back: None,
|
||||
flash_msg: None,
|
||||
flash_name: None,
|
||||
title: None,
|
||||
wlan_networks,
|
||||
wlan_ssid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/wifi")]
|
||||
pub fn wifi_list(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// assign context through context_builder call
|
||||
let mut context = NetworkListContext::build();
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.title = Some("WiFi Networks".to_string());
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
// 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_dir is set in Rocket.toml
|
||||
|
||||
Template::render("settings/network/list_aps", &context)
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR /settings/network/wifi<ssid>
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct NetworkDetailContext {
|
||||
pub back: Option<String>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub saved_aps: Vec<Networks>,
|
||||
pub selected: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub wlan_ip: String,
|
||||
pub wlan_networks: HashMap<String, AccessPoint>,
|
||||
pub wlan_rssi: Option<String>,
|
||||
pub wlan_ssid: String,
|
||||
pub wlan_state: String,
|
||||
pub wlan_status: String,
|
||||
pub wlan_traffic: Option<Traffic>,
|
||||
}
|
||||
|
||||
impl NetworkDetailContext {
|
||||
pub fn build() -> NetworkDetailContext {
|
||||
let wlan_ip = match network_client::ip("wlan0") {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => "x.x.x.x".to_string(),
|
||||
};
|
||||
// list of networks saved in wpa_supplicant.conf
|
||||
let wlan_list = match network_client::saved_networks() {
|
||||
Ok(ssids) => {
|
||||
let networks: Vec<Networks> = serde_json::from_str(ssids.as_str())
|
||||
.expect("Failed to deserialize scan_list response");
|
||||
networks
|
||||
}
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
// list of networks saved in wpa_supplicant.conf
|
||||
// HACK: we're running the same function twice (wlan_list)
|
||||
// see if we can implement clone for Vec<Networks> instead
|
||||
let saved_aps = match network_client::saved_networks() {
|
||||
Ok(ssids) => {
|
||||
let networks: Vec<Networks> = serde_json::from_str(ssids.as_str())
|
||||
.expect("Failed to deserialize scan_list response");
|
||||
networks
|
||||
}
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
let wlan_rssi = match network_client::rssi_percent("wlan0") {
|
||||
Ok(rssi) => Some(rssi),
|
||||
Err(_) => None,
|
||||
};
|
||||
// list of networks currently in range (online & accessible)
|
||||
let wlan_scan = match network_client::available_networks("wlan0") {
|
||||
Ok(networks) => {
|
||||
let scan: Vec<Scan> = serde_json::from_str(networks.as_str())
|
||||
.expect("Failed to deserialize scan_networks response");
|
||||
scan
|
||||
}
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
let wlan_ssid = match network_client::ssid("wlan0") {
|
||||
Ok(ssid) => ssid,
|
||||
Err(_) => "Not connected".to_string(),
|
||||
};
|
||||
let wlan_state = match network_client::state("wlan0") {
|
||||
Ok(state) => state,
|
||||
Err(_) => "Interface unavailable".to_string(),
|
||||
};
|
||||
let wlan_status = match network_client::status("wlan0") {
|
||||
Ok(status) => status,
|
||||
Err(_) => "Interface unavailable".to_string(),
|
||||
};
|
||||
let wlan_traffic = match network_client::traffic("wlan0") {
|
||||
Ok(traffic) => {
|
||||
let mut t = traffic;
|
||||
// modify traffic values & assign measurement unit
|
||||
// based on received and transmitted values
|
||||
// if received > 999 MB, convert it to GB
|
||||
if t.received > 1_047_527_424 {
|
||||
t.received /= 1_073_741_824;
|
||||
t.rx_unit = Some("GB".to_string());
|
||||
} else if t.received > 0 {
|
||||
// otherwise, convert it to MB
|
||||
t.received = (t.received / 1024) / 1024;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.received = 0;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
}
|
||||
|
||||
if t.transmitted > 1_047_527_424 {
|
||||
t.transmitted /= 1_073_741_824;
|
||||
t.tx_unit = Some("GB".to_string());
|
||||
} else if t.transmitted > 0 {
|
||||
t.transmitted = (t.transmitted / 1024) / 1024;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.transmitted = 0;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
}
|
||||
Some(t)
|
||||
}
|
||||
Err(_) => None,
|
||||
};
|
||||
// create a hashmap to combine wlan_list & wlan_scan without repetition
|
||||
let mut wlan_networks = HashMap::new();
|
||||
for ap in wlan_scan {
|
||||
let ssid = ap.ssid.clone();
|
||||
let rssi = ap.signal_level.clone();
|
||||
// parse the string to a signed integer (for math)
|
||||
let rssi_parsed = rssi.parse::<i32>().unwrap();
|
||||
// perform rssi (dBm) to quality (%) conversion
|
||||
let quality_percent = 2 * (rssi_parsed + 100);
|
||||
let ap_detail = AccessPoint {
|
||||
detail: Some(ap),
|
||||
state: "Available".to_string(),
|
||||
signal: Some(quality_percent),
|
||||
};
|
||||
wlan_networks.insert(ssid, ap_detail);
|
||||
}
|
||||
for network in wlan_list {
|
||||
// avoid repetition by checking that ssid is not already in list
|
||||
if !wlan_networks.contains_key(&network.ssid) {
|
||||
let ssid = network.ssid.clone();
|
||||
let net_detail = AccessPoint {
|
||||
detail: None,
|
||||
state: "Not in range".to_string(),
|
||||
signal: None,
|
||||
};
|
||||
wlan_networks.insert(ssid, net_detail);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkDetailContext {
|
||||
back: None,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
saved_aps,
|
||||
selected: None,
|
||||
title: None,
|
||||
wlan_ip,
|
||||
wlan_networks,
|
||||
wlan_rssi,
|
||||
wlan_ssid,
|
||||
wlan_state,
|
||||
wlan_status,
|
||||
wlan_traffic,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/wifi?<ssid>")]
|
||||
pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// assign context through context_builder call
|
||||
let mut context = NetworkDetailContext::build();
|
||||
context.back = Some("/settings/network/wifi".to_string());
|
||||
context.title = Some("WiFi Network".to_string());
|
||||
context.selected = Some(ssid.to_string());
|
||||
// check to see if there is a flash message to display
|
||||
|
||||
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_dir is set in Rocket.toml
|
||||
|
||||
Template::render("settings/network/ap_details", &context)
|
||||
}
|
||||
|
||||
@ -563,7 +194,7 @@ pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authentica
|
||||
pub fn deploy_client(_auth: Authenticated) -> Flash<Redirect> {
|
||||
// activate the wireless client
|
||||
debug!("Activating WiFi client mode.");
|
||||
match network_client::activate_client() {
|
||||
match network::start_iface_service(&*WLAN_IFACE) {
|
||||
Ok(_) => Flash::success(Redirect::to("/settings/network"), "Activated WiFi client"),
|
||||
Err(_) => Flash::error(
|
||||
Redirect::to("/settings/network"),
|
||||
@ -576,153 +207,88 @@ pub fn deploy_client(_auth: Authenticated) -> Flash<Redirect> {
|
||||
|
||||
#[get("/wifi/add")]
|
||||
pub fn add_wifi(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// TODO: use simple context (no need to build entire NetworkContext)
|
||||
let mut context = NetworkContext::build();
|
||||
// set back icon link to network route
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.title = Some("Add WiFi Network".to_string());
|
||||
let mut context = Context::new();
|
||||
context.insert("back", &Some("/settings/network".to_string()));
|
||||
context.insert("title", &Some("Add WiFi Network".to_string()));
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
// add flash message contents to the context object
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
context.insert("flash_name", &Some(flash.kind().to_string()));
|
||||
context.insert("flash_msg", &Some(flash.message().to_string()));
|
||||
};
|
||||
// template_dir is set in Rocket.toml
|
||||
Template::render("settings/network/add_ap", &context)
|
||||
}
|
||||
|
||||
// used in /settings/network/wifi/add?<ssid>
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct NetworkAddContext {
|
||||
pub back: Option<String>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub selected: Option<String>,
|
||||
pub title: Option<String>,
|
||||
}
|
||||
|
||||
impl NetworkAddContext {
|
||||
pub fn build() -> NetworkAddContext {
|
||||
NetworkAddContext {
|
||||
back: None,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
selected: None,
|
||||
title: None,
|
||||
}
|
||||
}
|
||||
Template::render("settings/network/add_ap", &context.into_json())
|
||||
}
|
||||
|
||||
#[get("/wifi/add?<ssid>")]
|
||||
pub fn add_ssid(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
let mut context = NetworkAddContext::build();
|
||||
context.back = Some("/settings/network/wifi".to_string());
|
||||
context.selected = Some(ssid.to_string());
|
||||
context.title = Some("Add WiFi Network".to_string());
|
||||
let mut context = Context::new();
|
||||
context.insert("back", &Some("/settings/network".to_string()));
|
||||
context.insert("title", &Some("Add WiFi Network".to_string()));
|
||||
context.insert("selected", &Some(ssid.to_string()));
|
||||
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
// add flash message contents to the context object
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
context.insert("flash_name", &Some(flash.kind().to_string()));
|
||||
context.insert("flash_msg", &Some(flash.message().to_string()));
|
||||
};
|
||||
// template_dir is set in Rocket.toml
|
||||
Template::render("settings/network/add_ap", &context)
|
||||
|
||||
Template::render("settings/network/add_ap", &context.into_json())
|
||||
}
|
||||
|
||||
#[post("/wifi/add", data = "<wifi>")]
|
||||
pub fn add_credentials(wifi: Form<WiFi>, _auth: Authenticated) -> Template {
|
||||
let mut context = Context::new();
|
||||
context.insert("back", &Some("/settings/network".to_string()));
|
||||
context.insert("title", &Some("Add WiFi Network".to_string()));
|
||||
|
||||
// check if the credentials already exist for this access point
|
||||
// note: this is nicer but it's an unstable feature:
|
||||
// if check_saved_aps(&wifi.ssid).contains(true)
|
||||
// use unwrap_or instead, set value to false if err is returned
|
||||
let creds_exist = network_client::saved_ap(&wifi.ssid).unwrap_or(false);
|
||||
if creds_exist {
|
||||
let mut context = NetworkAddContext::build();
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.flash_name = Some("error".to_string());
|
||||
context.flash_msg =
|
||||
Some("Network credentials already exist for this access point".to_string());
|
||||
context.title = Some("Add WiFi Network".to_string());
|
||||
// return early from handler with "creds already exist" message
|
||||
return Template::render("settings/network/add_ap", &context);
|
||||
//let creds_exist = network::saved_networks(&wifi.ssid).unwrap_or(false);
|
||||
let creds_exist = match network::saved_networks() {
|
||||
Ok(Some(networks)) => networks.contains(&wifi.ssid),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// if credentials not found, generate and write wifi config to wpa_supplicant
|
||||
match network_client::add(&wifi.ssid, &wifi.pass) {
|
||||
Ok(_) => {
|
||||
debug!("Added WiFi credentials.");
|
||||
// force reread of wpa_supplicant.conf file with new credentials
|
||||
match network_client::reconfigure() {
|
||||
Ok(_) => debug!("Successfully reconfigured wpa_supplicant"),
|
||||
Err(_) => warn!("Failed to reconfigure wpa_supplicant"),
|
||||
let (flash_name, flash_msg) = if creds_exist {
|
||||
(
|
||||
"error".to_string(),
|
||||
"Network credentials already exist for this access point".to_string(),
|
||||
)
|
||||
} else {
|
||||
match network::add(&*WLAN_IFACE, &wifi.ssid, &wifi.pass) {
|
||||
Ok(_) => {
|
||||
debug!("Added WiFi credentials.");
|
||||
// force reread of wpa_supplicant.conf file with new credentials
|
||||
match network::reconfigure() {
|
||||
Ok(_) => debug!("Successfully reconfigured wpa_supplicant"),
|
||||
Err(_) => warn!("Failed to reconfigure wpa_supplicant"),
|
||||
}
|
||||
("success".to_string(), "Added WiFi credentials".to_string())
|
||||
}
|
||||
Err(_) => {
|
||||
debug!("Failed to add WiFi credentials.");
|
||||
(
|
||||
"error".to_string(),
|
||||
"Failed to add WiFi credentials".to_string(),
|
||||
)
|
||||
}
|
||||
let mut context = NetworkAddContext::build();
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.flash_name = Some("success".to_string());
|
||||
context.flash_msg = Some("Added WiFi credentials".to_string());
|
||||
context.title = Some("Add WiFi Network".to_string());
|
||||
Template::render("settings/network/add_ap", &context)
|
||||
}
|
||||
Err(_) => {
|
||||
debug!("Failed to add WiFi credentials.");
|
||||
let mut context = NetworkAddContext::build();
|
||||
context.back = Some("/settings/network".to_string());
|
||||
context.flash_name = Some("error".to_string());
|
||||
context.flash_msg = Some("Failed to add WiFi credentials".to_string());
|
||||
context.title = Some("Add WiFi Network".to_string());
|
||||
Template::render("settings/network/add_ap", &context)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
context.insert("flash_name", &Some(flash_name));
|
||||
context.insert("flash_msg", &Some(flash_msg));
|
||||
|
||||
Template::render("settings/network/add_ap", &context.into_json())
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR WIFI USAGE
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct NetworkAlertContext {
|
||||
pub alert: Alert,
|
||||
pub back: Option<String>,
|
||||
pub data_total: Data, // combined stored and current wifi traffic in bytes
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
pub threshold: Threshold,
|
||||
pub title: Option<String>,
|
||||
pub traffic: Traffic, // current wifi traffic in bytes (since boot)
|
||||
}
|
||||
|
||||
impl NetworkAlertContext {
|
||||
pub fn build() -> NetworkAlertContext {
|
||||
let alert = monitor::get_alerts().unwrap();
|
||||
// stored wifi data values as bytes
|
||||
let stored_traffic = monitor::get_data().unwrap();
|
||||
let threshold = monitor::get_thresholds().unwrap();
|
||||
// current wifi traffic values as bytes
|
||||
let traffic = match network_client::traffic("wlan0") {
|
||||
Ok(t) => t,
|
||||
Err(_) => Traffic {
|
||||
received: 0,
|
||||
transmitted: 0,
|
||||
rx_unit: None,
|
||||
tx_unit: None,
|
||||
},
|
||||
};
|
||||
|
||||
let current_traffic = traffic.received + traffic.transmitted;
|
||||
let total = stored_traffic.total + current_traffic;
|
||||
let data_total = Data { total };
|
||||
|
||||
NetworkAlertContext {
|
||||
alert,
|
||||
back: None,
|
||||
data_total,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
threshold,
|
||||
title: None,
|
||||
traffic,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/wifi/usage")]
|
||||
pub fn wifi_usage(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
let mut context = NetworkAlertContext::build();
|
||||
|
@ -1,162 +1,21 @@
|
||||
use rocket::{get, request::FlashMessage};
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Serialize;
|
||||
|
||||
use peach_network::{
|
||||
network,
|
||||
network::{Status, Traffic},
|
||||
};
|
||||
|
||||
use crate::context::network::NetworkStatusContext;
|
||||
use crate::routes::authentication::Authenticated;
|
||||
|
||||
// HELPERS AND ROUTES FOR /status/network
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct IfaceTraffic {
|
||||
pub rx: u64,
|
||||
pub rx_unit: Option<String>,
|
||||
pub tx: u64,
|
||||
pub tx_unit: Option<String>,
|
||||
}
|
||||
|
||||
impl IfaceTraffic {
|
||||
fn default() -> Self {
|
||||
IfaceTraffic {
|
||||
rx: 0,
|
||||
rx_unit: None,
|
||||
tx: 0,
|
||||
tx_unit: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_traffic(traffic: Traffic) -> Option<IfaceTraffic> {
|
||||
let mut t = IfaceTraffic::default();
|
||||
// modify traffic values & assign measurement units
|
||||
// based on received and transmitted values.
|
||||
// if received > 999 MB, convert it to GB
|
||||
if traffic.received > 1_047_527_424 {
|
||||
t.rx = traffic.received / 1_073_741_824;
|
||||
t.rx_unit = Some("GB".to_string());
|
||||
} else if traffic.received > 0 {
|
||||
// otherwise, convert it to MB
|
||||
t.rx = (traffic.received / 1024) / 1024;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.rx = 0;
|
||||
t.rx_unit = Some("MB".to_string());
|
||||
}
|
||||
|
||||
if traffic.transmitted > 1_047_527_424 {
|
||||
t.tx = traffic.transmitted / 1_073_741_824;
|
||||
t.tx_unit = Some("GB".to_string());
|
||||
} else if traffic.transmitted > 0 {
|
||||
t.tx = (traffic.transmitted / 1024) / 1024;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
} else {
|
||||
t.tx = 0;
|
||||
t.tx_unit = Some("MB".to_string());
|
||||
}
|
||||
|
||||
Some(t)
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct NetworkContext {
|
||||
pub ap_ip: String,
|
||||
pub ap_ssid: String,
|
||||
pub ap_state: String,
|
||||
pub ap_traffic: Option<IfaceTraffic>,
|
||||
pub wlan_ip: String,
|
||||
pub wlan_rssi: Option<String>,
|
||||
pub wlan_ssid: String,
|
||||
pub wlan_state: String,
|
||||
pub wlan_status: Option<Status>,
|
||||
pub wlan_traffic: Option<IfaceTraffic>,
|
||||
pub flash_name: Option<String>,
|
||||
pub flash_msg: Option<String>,
|
||||
// page title for header in navbar
|
||||
pub title: Option<String>,
|
||||
// url for back-arrow link
|
||||
pub back: Option<String>,
|
||||
}
|
||||
|
||||
impl NetworkContext {
|
||||
pub fn build() -> NetworkContext {
|
||||
let ap_ip = match network::ip("ap0") {
|
||||
Ok(Some(ip)) => ip,
|
||||
_ => "x.x.x.x".to_string(),
|
||||
};
|
||||
let ap_ssid = match network::ssid("ap0") {
|
||||
Ok(Some(ssid)) => ssid,
|
||||
_ => "Not currently activated".to_string(),
|
||||
};
|
||||
let ap_state = match network::state("ap0") {
|
||||
Ok(Some(state)) => state,
|
||||
_ => "Interface unavailable".to_string(),
|
||||
};
|
||||
let ap_traffic = match network::traffic("ap0") {
|
||||
// convert bytes to mb or gb and add appropriate units
|
||||
Ok(Some(traffic)) => convert_traffic(traffic),
|
||||
_ => None,
|
||||
};
|
||||
let wlan_ip = match network::ip("wlan0") {
|
||||
Ok(Some(ip)) => ip,
|
||||
_ => "x.x.x.x".to_string(),
|
||||
};
|
||||
let wlan_rssi = match network::rssi_percent("wlan0") {
|
||||
Ok(rssi) => rssi,
|
||||
_ => None,
|
||||
};
|
||||
let wlan_ssid = match network::ssid("wlan0") {
|
||||
Ok(Some(ssid)) => ssid,
|
||||
_ => "Not connected".to_string(),
|
||||
};
|
||||
let wlan_state = match network::state("wlan0") {
|
||||
Ok(Some(state)) => state,
|
||||
_ => "Interface unavailable".to_string(),
|
||||
};
|
||||
let wlan_status = match network::status("wlan0") {
|
||||
Ok(status) => status,
|
||||
_ => None,
|
||||
};
|
||||
let wlan_traffic = match network::traffic("wlan0") {
|
||||
// convert bytes to mb or gb and add appropriate units
|
||||
Ok(Some(traffic)) => convert_traffic(traffic),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
NetworkContext {
|
||||
ap_ip,
|
||||
ap_ssid,
|
||||
ap_state,
|
||||
ap_traffic,
|
||||
wlan_ip,
|
||||
wlan_rssi,
|
||||
wlan_ssid,
|
||||
wlan_state,
|
||||
wlan_status,
|
||||
wlan_traffic,
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
title: None,
|
||||
back: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/network")]
|
||||
pub fn network_status(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
||||
// assign context through context_builder call
|
||||
let mut context = NetworkContext::build();
|
||||
let mut context = NetworkStatusContext::build();
|
||||
context.back = Some("/status".to_string());
|
||||
context.title = Some("Network Status".to_string());
|
||||
// check to see if there is a flash message to display
|
||||
|
||||
if let Some(flash) = flash {
|
||||
// add flash message contents to the context object
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
// template_dir is set in Rocket.toml
|
||||
|
||||
Template::render("status/network", &context)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user