add network settings menu template and route handler, along with network settings placeholder files for routes

This commit is contained in:
glyph 2022-09-26 16:44:22 +01:00
parent c5c0bb91e4
commit 1a7bd7987b
13 changed files with 65 additions and 324 deletions

1
Cargo.lock generated
View File

@ -2346,6 +2346,7 @@ dependencies = [
"log 0.4.17",
"maud",
"peach-lib",
"peach-network",
"rouille",
"temporary",
"xdg",

View File

@ -45,7 +45,7 @@ log = "0.4"
maud = "0.23"
peach-lib = { path = "../peach-lib" }
# these will be reintroduced when the full peachcloud mode is added
#peach-network = { path = "../peach-network" }
peach-network = { path = "../peach-network" }
#peach-stats = { path = "../peach-stats" }
rouille = { version = "3.5", default-features = false }
temporary = "0.6"

View File

@ -200,6 +200,10 @@ pub fn mount_peachpub_routes(
routes::settings::scuttlebutt::default::write_config()
},
(GET) (/settings/network) => {
Response::html(routes::settings::network::menu::build_template(request)).reset_flash()
},
(GET) (/settings/theme/{theme: String}) => {
routes::settings::theme::set_theme(theme)
},

View File

@ -1,6 +1,6 @@
pub mod admin;
//pub mod dns;
pub mod menu;
//pub mod network;
pub mod network;
pub mod scuttlebutt;
pub mod theme;

View File

@ -1,322 +0,0 @@
use log::{debug, warn};
use rocket::{
form::{Form, FromForm},
get, post,
request::FlashMessage,
response::{Flash, Redirect},
uri, UriDisplayQuery,
};
use rocket_dyn_templates::{tera::Context, Template};
use peach_network::network;
use crate::{
context,
context::network::{NetworkAlertContext, NetworkDetailContext, NetworkListContext},
routes::authentication::Authenticated,
utils::{monitor, monitor::Threshold},
AP_IFACE, WLAN_IFACE,
};
// STRUCTS USED BY NETWORK ROUTES
#[derive(Debug, FromForm, UriDisplayQuery)]
pub struct Ssid {
pub ssid: String,
}
#[derive(Debug, FromForm)]
pub struct WiFi {
pub ssid: String,
pub pass: String,
}
// HELPERS AND ROUTES FOR /settings/network/wifi/usage/reset
#[get("/wifi/usage/reset")]
pub fn wifi_usage_reset(_auth: Authenticated) -> Flash<Redirect> {
let url = uri!(wifi_usage);
match monitor::reset_data() {
Ok(_) => Flash::success(Redirect::to(url), "Reset stored network traffic total"),
Err(_) => Flash::error(
Redirect::to(url),
"Failed to reset stored network traffic total",
),
}
}
#[post("/wifi/connect", data = "<network>")]
pub fn connect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &network.ssid;
let url = uri!(network_detail(ssid = ssid));
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"),
},
_ => Flash::error(Redirect::to(url), "Failed to retrieve the network ID"),
}
}
#[post("/wifi/disconnect", data = "<network>")]
pub fn disconnect_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &network.ssid;
let url = uri!(network_home);
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"),
}
}
#[post("/wifi/forget", data = "<network>")]
pub fn forget_wifi(network: Form<Ssid>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &network.ssid;
let url = uri!(network_home);
match network::forget(&*WLAN_IFACE, ssid) {
Ok(_) => Flash::success(Redirect::to(url), "WiFi credentials removed"),
Err(_) => Flash::error(
Redirect::to(url),
"Failed to remove WiFi credentials".to_string(),
),
}
}
#[get("/wifi/modify?<ssid>")]
pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
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.insert("flash_name", &Some(flash.kind().to_string()));
context.insert("flash_msg", &Some(flash.message().to_string()));
};
Template::render("settings/network/modify_ap", &context.into_json())
}
#[post("/wifi/modify", data = "<wifi>")]
pub fn wifi_set_password(wifi: Form<WiFi>, _auth: Authenticated) -> Flash<Redirect> {
let ssid = &wifi.ssid;
let pass = &wifi.pass;
let url = uri!(network_detail(ssid = ssid));
match network::update(&*WLAN_IFACE, ssid, pass) {
Ok(_) => Flash::success(Redirect::to(url), "WiFi password updated".to_string()),
Err(_) => Flash::error(
Redirect::to(url),
"Failed to update WiFi password".to_string(),
),
}
}
// HELPERS AND ROUTES FOR /settings/network
#[get("/")]
pub fn network_home(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// 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.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.into_json())
}
// HELPERS AND ROUTES FOR /settings/network/ap/activate
#[get("/ap/activate")]
pub fn deploy_ap(_auth: Authenticated) -> Flash<Redirect> {
// activate the wireless access point
debug!("Activating WiFi access point.");
match network::start_iface_service(&*AP_IFACE) {
Ok(_) => Flash::success(
Redirect::to("/settings/network"),
"Activated WiFi access point",
),
Err(_) => Flash::error(
Redirect::to("/settings/network"),
"Failed to activate WiFi access point",
),
}
}
// HELPERS AND ROUTES FOR /settings/network/wifi
#[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::render("settings/network/list_aps", &context)
}
// HELPERS AND ROUTES FOR /settings/network/wifi<ssid>
#[get("/wifi?<ssid>")]
pub fn network_detail(ssid: &str, flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
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());
if let Some(flash) = flash {
context.flash_name = Some(flash.kind().to_string());
context.flash_msg = Some(flash.message().to_string());
};
Template::render("settings/network/ap_details", &context)
}
// HELPERS AND ROUTES FOR /settings/network/wifi/activate
#[get("/wifi/activate")]
pub fn deploy_client(_auth: Authenticated) -> Flash<Redirect> {
// activate the wireless client
debug!("Activating WiFi client mode.");
match network::start_iface_service(&*WLAN_IFACE) {
Ok(_) => Flash::success(Redirect::to("/settings/network"), "Activated WiFi client"),
Err(_) => Flash::error(
Redirect::to("/settings/network"),
"Failed to activate WiFi client",
),
}
}
// HELPERS AND ROUTES FOR /settings/network/wifi/add
#[get("/wifi/add")]
pub fn add_wifi(flash: Option<FlashMessage>, _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 to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.insert("flash_name", &Some(flash.kind().to_string()));
context.insert("flash_msg", &Some(flash.message().to_string()));
};
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 = 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.insert("flash_name", &Some(flash.kind().to_string()));
context.insert("flash_msg", &Some(flash.message().to_string()));
};
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::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
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(e) => {
debug!("Failed to add WiFi credentials.");
("error".to_string(), format!("{}", e))
}
}
};
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
#[get("/wifi/usage")]
pub fn wifi_usage(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
let mut context = NetworkAlertContext::build();
// set back icon link to network route
context.back = Some("/settings/network".to_string());
context.title = Some("Network Data Usage".to_string());
// check to see if there is a flash message to display
if let Some(flash) = flash {
// 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/data_usage_limits", &context)
}
#[post("/wifi/usage", data = "<thresholds>")]
pub fn wifi_usage_alerts(thresholds: Form<Threshold>, _auth: Authenticated) -> Flash<Redirect> {
match monitor::update_store(thresholds.into_inner()) {
Ok(_) => {
debug!("WiFi data usage thresholds updated.");
Flash::success(
Redirect::to("/settings/network/wifi/usage"),
"Updated alert thresholds and flags",
)
}
Err(_) => {
warn!("Failed to update WiFi data usage thresholds.");
Flash::error(
Redirect::to("/settings/network/wifi/usage"),
"Failed to update alert thresholds and flags",
)
}
}
}

View File

@ -0,0 +1,57 @@
use maud::{html, Markup, PreEscaped};
use peach_network::network;
use rouille::Request;
use crate::{
templates,
utils::{flash::FlashRequest, theme},
};
// ROUTE: /settings/network
/// Read the wireless interface mode (WiFi AP or client) and selectively render
/// the activation button for the deactivated mode.
fn render_mode_toggle_button() -> Markup {
match network::state("ap0") {
Ok(Some(state)) if state == "up" => {
html! {
a id="connectWifi" class="button button-primary center" href="/settings/network/wifi/activate" title="Enable WiFi" { "Enable WiFi" }
}
}
_ => html! {
a id="deployAccessPoint" class="button button-primary center" href="/settings/network/ap/activate" title="Deploy Access Point" { "Deploy Access Point" }
},
}
}
/// Network settings menu template builder.
pub fn build_template(request: &Request) -> PreEscaped<String> {
let (flash_name, flash_msg) = request.retrieve_flash();
let menu_template = html! {
(PreEscaped("<!-- NETWORK SETTINGS MENU -->"))
div class="card center" {
(PreEscaped("<!-- BUTTONS -->"))
div id="buttons" {
a class="button button-primary center" href="/settings/network/wifi/add" title="Add WiFi Network" { "Add WiFi Network" }
a id="configureDNS" class="button button-primary center" href="/settings/network/dns" title="Configure DNS" { "Configure DNS" }
(PreEscaped("<!-- if ap is up, show 'Enable WiFi' button, else show 'Deplay Access Point' -->"))
(render_mode_toggle_button())
a id="listWifi" class="button button-primary center" href="/settings/network/wifi" title="List WiFi Networks" { "List WiFi Networks" }
a id="viewUsage" class="button button-primary center" href="/settings/network/wifi/usage" title="View Data Usage" { "View Data Usage" }
a id="viewStatus" class="button button-primary center" href="/status/network" title="View Network Status" { "View Network Status" }
}
// render flash message if cookies were found in the request
@if let (Some(name), Some(msg)) = (flash_name, flash_msg) {
(PreEscaped("<!-- FLASH MESSAGE -->"))
(templates::flash::build_template(name, msg))
}
}
};
let body = templates::nav::build_template(menu_template, "Network Settings", Some("/settings"));
let theme = theme::get_theme();
templates::base::build_template(body, theme)
}

View File

@ -0,0 +1 @@
pub mod menu;