forked from PeachCloud/peach-workspace
Merge pull request 'Upgrade peach-web to use rocket 0.5' (#15) from rocket0.5 into main
Reviewed-on: PeachCloud/peach-workspace#15
This commit is contained in:
commit
0249a191d1
File diff suppressed because it is too large
Load Diff
|
@ -40,7 +40,7 @@ log = "0.4"
|
|||
nest = "1.0.0"
|
||||
peach-lib = { path = "../peach-lib" }
|
||||
percent-encoding = "2.1.0"
|
||||
rocket = "0.4.6"
|
||||
rocket = { version = "0.5.0-rc.1", features = ["json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
snafu = "0.6"
|
||||
|
@ -50,7 +50,6 @@ regex = "1"
|
|||
xdg = "2.2.0"
|
||||
openssl = { version = "0.10", features = ["vendored"] }
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
version = "0.4.10"
|
||||
default-features = false
|
||||
features = ["json", "tera_templates"]
|
||||
[dependencies.rocket_dyn_templates]
|
||||
version = "0.1.0-rc.1"
|
||||
features = ["tera"]
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
//! # peach-web
|
||||
//!
|
||||
//! `peach-web` provides a web interface for monitoring and interacting with the
|
||||
//! PeachCloud device. This allows administration of the single-board computer
|
||||
//! (ie. Raspberry Pi) running PeachCloud, as well as the ssb-server and related
|
||||
//! plugins.
|
||||
//!
|
||||
//! ## Design
|
||||
//!
|
||||
//! `peach-web` is written primarily in Rust and presents a web interface for
|
||||
//! interacting with the device. The stack currently consists of Rocket (Rust
|
||||
//! web framework), Tera (Rust template engine inspired by Jinja2 and the Django
|
||||
//! template language), HTML, CSS and JavaScript. Additional functionality is
|
||||
//! provided by JSON-RPC clients for the `peach-network` and `peach-stats`
|
||||
//! microservices.
|
||||
//!
|
||||
//! HTML is rendered server-side. Request handlers call JSON-RPC microservices
|
||||
//! and serve HTML and assets. A JSON API is exposed for remote calls and
|
||||
//! dynamic client-side content updates via vanilla JavaScript following
|
||||
//! unobstructive design principles. A basic Websockets server is included,
|
||||
//! though is not currently utilised. 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.
|
||||
|
||||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod utils;
|
||||
mod ws;
|
||||
|
||||
use std::{env, thread};
|
||||
|
||||
use log::{debug, error, info};
|
||||
|
||||
use rocket::{catchers, routes};
|
||||
use rocket_contrib::templates::Template;
|
||||
|
||||
use crate::routes::authentication::*;
|
||||
use crate::routes::device::*;
|
||||
use crate::routes::helpers::*;
|
||||
use crate::routes::index::*;
|
||||
use crate::routes::ping::*;
|
||||
use crate::routes::scuttlebutt::*;
|
||||
|
||||
use crate::routes::settings::admin::*;
|
||||
use crate::routes::settings::dns::*;
|
||||
use crate::routes::settings::network::*;
|
||||
use crate::ws::*;
|
||||
|
||||
pub type BoxError = Box<dyn std::error::Error>;
|
||||
|
||||
// create rocket instance & mount web & json routes (makes testing easier)
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite()
|
||||
.mount(
|
||||
"/",
|
||||
routes![
|
||||
add_credentials, // WEB ROUTE
|
||||
connect_wifi, // WEB ROUTE
|
||||
disconnect_wifi, // WEB ROUTE
|
||||
deploy_ap, // WEB ROUTE
|
||||
deploy_client, // WEB ROUTE
|
||||
device_stats, // WEB ROUTE
|
||||
files, // WEB ROUTE
|
||||
forget_wifi, // WEB ROUTE
|
||||
help, // WEB ROUTE
|
||||
index, // WEB ROUTE
|
||||
login, // WEB ROUTE
|
||||
logout, // WEB ROUTE
|
||||
messages, // WEB ROUTE
|
||||
network_home, // WEB ROUTE
|
||||
network_add_ssid, // WEB ROUTE
|
||||
network_add_wifi, // WEB ROUTE
|
||||
network_detail, // WEB ROUTE
|
||||
peers, // WEB ROUTE
|
||||
profile, // WEB ROUTE
|
||||
reboot_cmd, // WEB ROUTE
|
||||
shutdown_cmd, // WEB ROUTE
|
||||
shutdown_menu, // WEB ROUTE
|
||||
wifi_list, // WEB ROUTE
|
||||
wifi_password, // WEB ROUTE
|
||||
wifi_set_password, // WEB ROUTE
|
||||
wifi_usage, // WEB ROUTE
|
||||
wifi_usage_alerts, // WEB ROUTE
|
||||
wifi_usage_reset, // WEB ROUTE
|
||||
configure_dns, // WEB ROUTE
|
||||
configure_dns_post, // WEB ROUTE
|
||||
change_password, // WEB ROUTE
|
||||
reset_password, // WEB ROUTE
|
||||
reset_password_post, // WEB ROUTE
|
||||
send_password_reset_page, // WEB ROUTE
|
||||
send_password_reset_post, // WEB ROUTE
|
||||
configure_admin, // WEB ROUTE
|
||||
add_admin, // WEB ROUTE
|
||||
add_admin_post, // WEB ROUTE
|
||||
delete_admin_post, // WEB ROUTE
|
||||
activate_ap, // JSON API
|
||||
activate_client, // JSON API
|
||||
add_wifi, // JSON API
|
||||
connect_ap, // JSON API
|
||||
disconnect_ap, // JSON API
|
||||
forget_ap, // JSON API
|
||||
modify_password, // JSON API
|
||||
ping_pong, // JSON API
|
||||
test_route, // JSON API
|
||||
ping_network, // JSON API
|
||||
ping_oled, // JSON API
|
||||
ping_stats, // JSON API
|
||||
reset_data_total, // JSON API
|
||||
return_ip, // JSON API
|
||||
return_rssi, // JSON API
|
||||
return_ssid, // JSON API
|
||||
return_state, // JSON API
|
||||
return_status, // JSON API
|
||||
reboot_device, // JSON API
|
||||
scan_networks, // JSON API
|
||||
shutdown_device, // JSON API
|
||||
update_wifi_alerts, // JSON API
|
||||
save_dns_configuration_endpoint, // JSON API
|
||||
save_password_form_endpoint, // JSON API
|
||||
reset_password_form_endpoint, // JSON API
|
||||
],
|
||||
)
|
||||
.register(catchers![not_found, internal_error])
|
||||
.attach(Template::fairing())
|
||||
}
|
||||
|
||||
// launch the rocket server
|
||||
pub fn run() -> Result<(), BoxError> {
|
||||
info!("Starting up.");
|
||||
|
||||
// spawn a separate thread for rocket to prevent blocking websockets
|
||||
thread::spawn(|| {
|
||||
info!("Launching Rocket server.");
|
||||
rocket().launch();
|
||||
});
|
||||
|
||||
// NOTE: websockets are not currently in use (may be in the future)
|
||||
let ws_addr = env::var("PEACH_WEB_WS").unwrap_or_else(|_| "0.0.0.0:5115".to_string());
|
||||
match websocket_server(ws_addr) {
|
||||
Ok(_) => debug!("Websocket server terminated without error."),
|
||||
Err(e) => error!("Error starting the websocket server: {}", e),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,16 +1,145 @@
|
|||
//! Initialize the logger and run the application, catching any errors.
|
||||
//! # peach-web
|
||||
//!
|
||||
//! `peach-web` provides a web interface for monitoring and interacting with the
|
||||
//! PeachCloud device. This allows administration of the single-board computer
|
||||
//! (ie. Raspberry Pi) running PeachCloud, as well as the ssb-server and related
|
||||
//! plugins.
|
||||
//!
|
||||
//! ## Design
|
||||
//!
|
||||
//! `peach-web` is written primarily in Rust and presents a web interface for
|
||||
//! interacting with the device. The stack currently consists of Rocket (Rust
|
||||
//! web framework), Tera (Rust template engine inspired by Jinja2 and the Django
|
||||
//! template language), HTML, CSS and JavaScript. Additional functionality is
|
||||
//! provided by JSON-RPC clients for the `peach-network` and `peach-stats`
|
||||
//! microservices.
|
||||
//!
|
||||
//! HTML is rendered server-side. Request handlers call JSON-RPC microservices
|
||||
//! and serve HTML and assets. A JSON API is exposed for remote calls and
|
||||
//! dynamic client-side content updates via vanilla JavaScript following
|
||||
//! unobstructive design principles. Each Tera template is passed a context
|
||||
//! object. In the case of Rust, this object is a `struct` and must implement
|
||||
//! `Serialize`. The fields of the context object are available in the context
|
||||
//! of the template to be rendered.
|
||||
|
||||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod utils;
|
||||
|
||||
use log::{info, error};
|
||||
use std::process;
|
||||
|
||||
use log::error;
|
||||
use rocket::{catchers, routes, Rocket, Build, fs::FileServer};
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
fn main() {
|
||||
// initialize the logger
|
||||
use crate::routes::authentication::*;
|
||||
use crate::routes::device::*;
|
||||
use crate::routes::helpers::*;
|
||||
use crate::routes::index::*;
|
||||
use crate::routes::ping::*;
|
||||
use crate::routes::scuttlebutt::*;
|
||||
|
||||
use crate::routes::settings::admin::*;
|
||||
use crate::routes::settings::dns::*;
|
||||
use crate::routes::settings::network::*;
|
||||
|
||||
|
||||
pub type BoxError = Box<dyn std::error::Error>;
|
||||
|
||||
/// Create rocket instance & mount all routes.
|
||||
fn init_rocket() -> Rocket<Build> {
|
||||
rocket::build()
|
||||
.mount(
|
||||
"/",
|
||||
routes![
|
||||
add_credentials, // WEB ROUTE
|
||||
connect_wifi, // WEB ROUTE
|
||||
disconnect_wifi, // WEB ROUTE
|
||||
deploy_ap, // WEB ROUTE
|
||||
deploy_client, // WEB ROUTE
|
||||
device_stats, // WEB ROUTE
|
||||
forget_wifi, // WEB ROUTE
|
||||
help, // WEB ROUTE
|
||||
index, // WEB ROUTE
|
||||
login, // WEB ROUTE
|
||||
logout, // WEB ROUTE
|
||||
messages, // WEB ROUTE
|
||||
network_home, // WEB ROUTE
|
||||
network_add_ssid, // WEB ROUTE
|
||||
network_add_wifi, // WEB ROUTE
|
||||
network_detail, // WEB ROUTE
|
||||
peers, // WEB ROUTE
|
||||
profile, // WEB ROUTE
|
||||
reboot_cmd, // WEB ROUTE
|
||||
shutdown_cmd, // WEB ROUTE
|
||||
shutdown_menu, // WEB ROUTE
|
||||
wifi_list, // WEB ROUTE
|
||||
wifi_password, // WEB ROUTE
|
||||
wifi_set_password, // WEB ROUTE
|
||||
wifi_usage, // WEB ROUTE
|
||||
wifi_usage_alerts, // WEB ROUTE
|
||||
wifi_usage_reset, // WEB ROUTE
|
||||
configure_dns, // WEB ROUTE
|
||||
configure_dns_post, // WEB ROUTE
|
||||
change_password, // WEB ROUTE
|
||||
reset_password, // WEB ROUTE
|
||||
reset_password_post, // WEB ROUTE
|
||||
send_password_reset_page, // WEB ROUTE
|
||||
send_password_reset_post, // WEB ROUTE
|
||||
configure_admin, // WEB ROUTE
|
||||
add_admin, // WEB ROUTE
|
||||
add_admin_post, // WEB ROUTE
|
||||
delete_admin_post, // WEB ROUTE
|
||||
activate_ap, // JSON API
|
||||
activate_client, // JSON API
|
||||
add_wifi, // JSON API
|
||||
connect_ap, // JSON API
|
||||
disconnect_ap, // JSON API
|
||||
forget_ap, // JSON API
|
||||
modify_password, // JSON API
|
||||
ping_pong, // JSON API
|
||||
ping_network, // JSON API
|
||||
ping_oled, // JSON API
|
||||
ping_stats, // JSON API
|
||||
reset_data_total, // JSON API
|
||||
return_ip, // JSON API
|
||||
return_rssi, // JSON API
|
||||
return_ssid, // JSON API
|
||||
return_state, // JSON API
|
||||
return_status, // JSON API
|
||||
reboot_device, // JSON API
|
||||
scan_networks, // JSON API
|
||||
shutdown_device, // JSON API
|
||||
update_wifi_alerts, // JSON API
|
||||
save_dns_configuration_endpoint, // JSON API
|
||||
save_password_form_endpoint, // JSON API
|
||||
reset_password_form_endpoint, // JSON API
|
||||
],
|
||||
)
|
||||
.mount("/", FileServer::from("static"))
|
||||
.register("/", catchers![not_found, internal_error])
|
||||
.attach(Template::fairing())
|
||||
}
|
||||
|
||||
/// Launch the peach-web rocket server.
|
||||
#[rocket::main]
|
||||
async fn main() {
|
||||
|
||||
// initialize logger
|
||||
env_logger::init();
|
||||
|
||||
// handle errors returned from `run`
|
||||
if let Err(e) = peach_web::run() {
|
||||
error!("Application error: {}", e);
|
||||
// initialize rocket
|
||||
info!("Initializing Rocket");
|
||||
let rocket = init_rocket();
|
||||
|
||||
// launch rocket
|
||||
info!("Launching Rocket");
|
||||
if let Err(e) = rocket.launch().await {
|
||||
error!("Error in Rocket application: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
use log::{debug, info};
|
||||
use rocket::request::{FlashMessage, Form, FromForm};
|
||||
use rocket::request::{FlashMessage};
|
||||
use rocket::form::{Form, FromForm};
|
||||
use rocket::response::{Flash, Redirect};
|
||||
use rocket::{get, post};
|
||||
use rocket_contrib::{json::Json, templates::Template};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket::serde::json::Json;
|
||||
use rocket_dyn_templates::Template;
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
|
||||
use peach_lib::password_utils;
|
||||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::utils::{build_json_response, JsonResponse};
|
||||
use crate::utils::build_json_response;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
// HELPERS AND ROUTES FOR /login
|
||||
|
||||
|
@ -39,8 +42,8 @@ pub fn login(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("login", &context)
|
||||
}
|
||||
|
@ -138,8 +141,8 @@ pub fn reset_password(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("password/reset_password", &context)
|
||||
}
|
||||
|
@ -178,18 +181,18 @@ pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Temp
|
|||
#[post("/public/api/v1/reset_password", data = "<reset_password_form>")]
|
||||
pub fn reset_password_form_endpoint(
|
||||
reset_password_form: Json<ResetPasswordForm>,
|
||||
) -> Json<JsonResponse> {
|
||||
) -> 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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = format!("{}", err);
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,8 +227,8 @@ pub fn send_password_reset_page(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("password/send_password_reset", &context)
|
||||
}
|
||||
|
@ -295,8 +298,8 @@ pub fn change_password(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("password/change_password", &context)
|
||||
}
|
||||
|
@ -330,18 +333,18 @@ pub fn change_password_post(password_form: Form<PasswordForm>) -> Template {
|
|||
|
||||
/// JSON change password form request handler.
|
||||
#[post("/api/v1/settings/change_password", data = "<password_form>")]
|
||||
pub fn save_password_form_endpoint(password_form: Json<PasswordForm>) -> Json<JsonResponse> {
|
||||
pub fn save_password_form_endpoint(password_form: Json<PasswordForm>) -> 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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = format!("{}", err);
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ use rocket::{
|
|||
request::FlashMessage,
|
||||
response::{Flash, Redirect},
|
||||
};
|
||||
use rocket_contrib::{json::Json, templates::Template};
|
||||
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Serialize;
|
||||
use std::{
|
||||
io,
|
||||
|
@ -15,7 +16,8 @@ use peach_lib::config_manager::load_peach_config;
|
|||
use peach_lib::stats_client::{CpuStatPercentages, DiskUsage, LoadAverage, MemStat};
|
||||
use peach_lib::{dyndns_client, network_client, oled_client, sbot_client, stats_client};
|
||||
|
||||
use crate::utils::{build_json_response, JsonResponse};
|
||||
use crate::utils::build_json_response;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
// HELPERS AND ROUTES FOR /device
|
||||
|
||||
|
@ -156,8 +158,8 @@ pub fn device_stats(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("device", &context)
|
||||
|
@ -188,19 +190,19 @@ pub fn reboot_cmd() -> Flash<Redirect> {
|
|||
|
||||
/// JSON request handler for device reboot.
|
||||
#[post("/api/v1/device/reboot")]
|
||||
pub fn reboot_device() -> Json<JsonResponse> {
|
||||
pub fn reboot_device() -> Value {
|
||||
match reboot() {
|
||||
Ok(_) => {
|
||||
debug!("Going down for reboot...");
|
||||
let status = "success".to_string();
|
||||
let msg = "Going down for reboot.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,19 +228,19 @@ pub fn shutdown_cmd() -> Flash<Redirect> {
|
|||
|
||||
// shutdown the device
|
||||
#[post("/api/v1/device/shutdown")]
|
||||
pub fn shutdown_device() -> Json<JsonResponse> {
|
||||
pub fn shutdown_device() -> Value {
|
||||
match shutdown() {
|
||||
Ok(_) => {
|
||||
debug!("Going down for shutdown...");
|
||||
let status = "success".to_string();
|
||||
let msg = "Going down for shutdown.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,8 +274,8 @@ pub fn shutdown_menu(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("shutdown", &context)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
use log::debug;
|
||||
use rocket::{catch, get, response::NamedFile};
|
||||
use rocket_contrib::templates::Template;
|
||||
use rocket::{catch};
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Serialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[get("/<file..>", rank = 2)]
|
||||
pub fn files(file: PathBuf) -> Option<NamedFile> {
|
||||
NamedFile::open(Path::new("static/").join(file)).ok()
|
||||
}
|
||||
|
||||
// HELPERS AND ROUTES FOR 404 ERROR
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rocket::{get, request::FlashMessage};
|
||||
use rocket_contrib::templates::Template;
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Serialize;
|
||||
|
||||
// HELPERS AND ROUTES FOR / (HOME PAGE)
|
||||
|
@ -60,8 +60,8 @@ pub fn help(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("help", &context)
|
||||
}
|
||||
|
|
|
@ -1,86 +1,76 @@
|
|||
//! Helper routes for pinging services to check that they are active
|
||||
use log::{debug, warn};
|
||||
use rocket::get;
|
||||
use rocket_contrib::json::Json;
|
||||
use rocket::serde::json::{Value};
|
||||
|
||||
use peach_lib::dyndns_client::is_dns_updater_online;
|
||||
use peach_lib::network_client;
|
||||
use peach_lib::oled_client;
|
||||
use peach_lib::stats_client;
|
||||
|
||||
use crate::utils::{build_json_response, JsonResponse};
|
||||
use crate::utils::build_json_response;
|
||||
|
||||
/// Status route: useful for checking connectivity from web client.
|
||||
#[get("/api/v1/ping")]
|
||||
pub fn ping_pong() -> Json<JsonResponse> {
|
||||
pub fn ping_pong() -> Value {
|
||||
// ping pong
|
||||
let status = "success".to_string();
|
||||
let msg = "pong!".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
}
|
||||
|
||||
/// Test route: useful for ad hoc testing.
|
||||
#[get("/api/v1/test")]
|
||||
pub fn test_route() -> Json<JsonResponse> {
|
||||
let val = is_dns_updater_online().unwrap();
|
||||
let status = "success".to_string();
|
||||
let msg = val.to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
|
||||
/// Status route: check availability of `peach-network` microservice.
|
||||
#[get("/api/v1/ping/network")]
|
||||
pub fn ping_network() -> Json<JsonResponse> {
|
||||
pub fn ping_network() -> Value {
|
||||
match network_client::ping() {
|
||||
Ok(_) => {
|
||||
debug!("peach-network responded successfully");
|
||||
let status = "success".to_string();
|
||||
let msg = "peach-network is available.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Status route: check availability of `peach-oled` microservice.
|
||||
#[get("/api/v1/ping/oled")]
|
||||
pub fn ping_oled() -> Json<JsonResponse> {
|
||||
pub fn ping_oled() -> Value {
|
||||
match oled_client::ping() {
|
||||
Ok(_) => {
|
||||
debug!("peach-oled responded successfully");
|
||||
let status = "success".to_string();
|
||||
let msg = "peach-oled is available.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Status route: check availability of `peach-stats` microservice.
|
||||
#[get("/api/v1/ping/stats")]
|
||||
pub fn ping_stats() -> Json<JsonResponse> {
|
||||
pub fn ping_stats() -> Value {
|
||||
match stats_client::ping() {
|
||||
Ok(_) => {
|
||||
debug!("peach-stats responded successfully");
|
||||
let status = "success".to_string();
|
||||
let msg = "peach-stats is available.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Routes for ScuttleButt related functionality.
|
||||
|
||||
use rocket::{get, request::FlashMessage};
|
||||
use rocket_contrib::templates::Template;
|
||||
use rocket_dyn_templates::Template;
|
||||
use serde::Serialize;
|
||||
|
||||
// HELPERS AND ROUTES FOR /messages
|
||||
|
@ -33,8 +33,8 @@ pub fn messages(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("messages", &context)
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ pub fn peers(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("peers", &context)
|
||||
}
|
||||
|
@ -103,8 +103,8 @@ pub fn profile(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("profile", &context)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use rocket::{
|
||||
get, post,
|
||||
request::{FlashMessage, Form, FromForm},
|
||||
request::FlashMessage,
|
||||
form::{Form, FromForm},
|
||||
response::{Flash, Redirect},
|
||||
uri,
|
||||
};
|
||||
use rocket_contrib::templates::Template;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket_dyn_templates::Template;
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
|
||||
use peach_lib::config_manager;
|
||||
use peach_lib::config_manager::load_peach_config;
|
||||
|
@ -47,8 +48,8 @@ pub fn configure_admin(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("admin/configure_admin", &context)
|
||||
}
|
||||
|
@ -93,8 +94,8 @@ pub fn add_admin(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("admin/add_admin", &context)
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use log::info;
|
||||
use rocket::{
|
||||
get, post,
|
||||
request::{FlashMessage, Form, FromForm},
|
||||
request::FlashMessage,
|
||||
form::{Form, FromForm}
|
||||
};
|
||||
use rocket_contrib::{json::Json, templates::Template};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket::serde::json::Json;
|
||||
use rocket_dyn_templates::Template;
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
|
||||
use peach_lib::config_manager;
|
||||
use peach_lib::config_manager::load_peach_config;
|
||||
|
@ -18,7 +20,8 @@ use peach_lib::jsonrpc_client_core::{Error, ErrorKind};
|
|||
use peach_lib::jsonrpc_core::types::error::ErrorCode;
|
||||
|
||||
use crate::error::PeachWebError;
|
||||
use crate::utils::{build_json_response, JsonResponse};
|
||||
use crate::utils::build_json_response;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
#[derive(Debug, Deserialize, FromForm)]
|
||||
pub struct DnsForm {
|
||||
|
@ -118,8 +121,8 @@ pub fn configure_dns(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
context.flash_name = Some(flash.kind().to_string());
|
||||
context.flash_msg = Some(flash.message().to_string());
|
||||
};
|
||||
Template::render("configure_dns", &context)
|
||||
}
|
||||
|
@ -150,18 +153,18 @@ pub fn configure_dns_post(dns: Form<DnsForm>) -> Template {
|
|||
}
|
||||
|
||||
#[post("/api/v1/dns/configure", data = "<dns_form>")]
|
||||
pub fn save_dns_configuration_endpoint(dns_form: Json<DnsForm>) -> Json<JsonResponse> {
|
||||
pub fn save_dns_configuration_endpoint(dns_form: Json<DnsForm>) -> 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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = format!("{}", err);
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
use log::{debug, warn};
|
||||
use percent_encoding::percent_decode;
|
||||
|
||||
use rocket::{
|
||||
get,
|
||||
http::RawStr,
|
||||
post,
|
||||
request::{FlashMessage, Form, FromForm},
|
||||
request::FlashMessage,
|
||||
form::{Form, FromForm},
|
||||
response::{Flash, Redirect},
|
||||
uri, UriDisplayQuery,
|
||||
};
|
||||
use rocket_contrib::{json, json::Json, templates::Template};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket::serde::json::{json, Json};
|
||||
use rocket_dyn_templates::Template;
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use peach_lib::network_client;
|
||||
|
@ -18,7 +19,8 @@ use peach_lib::stats_client::Traffic;
|
|||
|
||||
use crate::utils::monitor;
|
||||
use crate::utils::monitor::{Alert, Data, Threshold};
|
||||
use crate::utils::{build_json_response, JsonResponse};
|
||||
use crate::utils::build_json_response;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
// STRUCTS USED BY NETWORK ROUTES
|
||||
|
||||
|
@ -50,7 +52,7 @@ pub fn wifi_usage_reset() -> Flash<Redirect> {
|
|||
#[post("/network/wifi/connect", data = "<network>")]
|
||||
pub fn connect_wifi(network: Form<Ssid>) -> Flash<Redirect> {
|
||||
let ssid = &network.ssid;
|
||||
let url = uri!(network_detail: ssid);
|
||||
let url = uri!(network_detail(ssid = ssid));
|
||||
match network_client::id("wlan0", ssid) {
|
||||
Ok(id) => match network_client::connect(&id, "wlan0") {
|
||||
Ok(_) => Flash::success(Redirect::to(url), "Connected to chosen network"),
|
||||
|
@ -84,21 +86,19 @@ pub fn forget_wifi(network: Form<Ssid>) -> Flash<Redirect> {
|
|||
}
|
||||
|
||||
#[get("/network/wifi/modify?<ssid>")]
|
||||
pub fn wifi_password(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
|
||||
// decode ssid from url
|
||||
let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap();
|
||||
pub fn wifi_password(ssid: &str, flash: Option<FlashMessage>) -> Template {
|
||||
let mut context = NetworkAddContext {
|
||||
back: Some("/network/wifi".to_string()),
|
||||
flash_name: None,
|
||||
flash_msg: None,
|
||||
selected: Some(decoded_ssid.to_string()),
|
||||
selected: Some(ssid.to_string()),
|
||||
title: Some("Update WiFi Password".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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_modify", &context)
|
||||
|
@ -108,7 +108,7 @@ pub fn wifi_password(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
|
|||
pub fn wifi_set_password(wifi: Form<WiFi>) -> Flash<Redirect> {
|
||||
let ssid = &wifi.ssid;
|
||||
let pass = &wifi.pass;
|
||||
let url = uri!(network_detail: ssid);
|
||||
let url = uri!(network_detail(ssid = ssid));
|
||||
match network_client::update("wlan0", ssid, pass) {
|
||||
Ok(_) => Flash::success(Redirect::to(url), "WiFi password updated".to_string()),
|
||||
Err(_) => Flash::error(
|
||||
|
@ -283,8 +283,8 @@ pub fn network_home(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_card", &context)
|
||||
|
@ -383,8 +383,8 @@ pub fn wifi_list(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_list", &context)
|
||||
|
@ -540,19 +540,17 @@ impl NetworkDetailContext {
|
|||
}
|
||||
|
||||
#[get("/network/wifi?<ssid>")]
|
||||
pub fn network_detail(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
|
||||
pub fn network_detail(ssid: &str, flash: Option<FlashMessage>) -> Template {
|
||||
// assign context through context_builder call
|
||||
let mut context = NetworkDetailContext::build();
|
||||
context.back = Some("/network/wifi".to_string());
|
||||
context.title = Some("WiFi Network".to_string());
|
||||
// decode ssid from url
|
||||
let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap();
|
||||
context.selected = Some(decoded_ssid.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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_detail", &context)
|
||||
|
@ -581,8 +579,8 @@ pub fn network_add_wifi(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_add", &context)
|
||||
|
@ -611,18 +609,16 @@ impl NetworkAddContext {
|
|||
}
|
||||
|
||||
#[get("/network/wifi/add?<ssid>")]
|
||||
pub fn network_add_ssid(ssid: &RawStr, flash: Option<FlashMessage>) -> Template {
|
||||
// decode ssid from url
|
||||
let decoded_ssid = percent_decode(ssid.as_bytes()).decode_utf8().unwrap();
|
||||
pub fn network_add_ssid(ssid: &str, flash: Option<FlashMessage>) -> Template {
|
||||
let mut context = NetworkAddContext::build();
|
||||
context.back = Some("/network/wifi".to_string());
|
||||
context.selected = Some(decoded_ssid.to_string());
|
||||
context.selected = Some(ssid.to_string());
|
||||
context.title = Some("Add WiFi Network".to_string());
|
||||
// check to see if there is a flash message to display
|
||||
if let Some(flash) = flash {
|
||||
// add flash message contents to the context object
|
||||
context.flash_name = Some(flash.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_add", &context)
|
||||
|
@ -731,8 +727,8 @@ pub fn wifi_usage(flash: Option<FlashMessage>) -> Template {
|
|||
// 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.name().to_string());
|
||||
context.flash_msg = Some(flash.msg().to_string());
|
||||
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("network_usage", &context)
|
||||
|
@ -759,25 +755,25 @@ pub fn wifi_usage_alerts(thresholds: Form<Threshold>) -> Flash<Redirect> {
|
|||
}
|
||||
|
||||
#[post("/api/v1/network/wifi/usage", data = "<thresholds>")]
|
||||
pub fn update_wifi_alerts(thresholds: Json<Threshold>) -> Json<JsonResponse> {
|
||||
pub fn update_wifi_alerts(thresholds: Json<Threshold>) -> 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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/v1/network/wifi/usage/reset")]
|
||||
pub fn reset_data_total() -> Json<JsonResponse> {
|
||||
pub fn reset_data_total() -> Value {
|
||||
match monitor::reset_data() {
|
||||
Ok(_) => {
|
||||
debug!("Reset network data usage total.");
|
||||
|
@ -795,13 +791,13 @@ pub fn reset_data_total() -> Json<JsonResponse> {
|
|||
let data = json!(current_traffic);
|
||||
let status = "success".to_string();
|
||||
let msg = "Reset network data usage total.".to_string();
|
||||
Json(build_json_response(status, Some(data), Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -809,18 +805,18 @@ pub fn reset_data_total() -> Json<JsonResponse> {
|
|||
// HELPERS AND ROUTES FOR ACCESS POINT ACTIVATION
|
||||
|
||||
#[post("/api/v1/network/activate_ap")]
|
||||
pub fn activate_ap() -> Json<JsonResponse> {
|
||||
pub fn activate_ap() -> Value {
|
||||
// activate the wireless access point
|
||||
debug!("Activating WiFi access point.");
|
||||
match network_client::activate_ap() {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
Json(build_json_response(status, None, None))
|
||||
build_json_response(status, None, None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to activate WiFi access point.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -828,24 +824,24 @@ pub fn activate_ap() -> Json<JsonResponse> {
|
|||
// HELPERS AND ROUTES FOR WIFI CLIENT MANAGEMENT
|
||||
|
||||
#[post("/api/v1/network/activate_client")]
|
||||
pub fn activate_client() -> Json<JsonResponse> {
|
||||
pub fn activate_client() -> Value {
|
||||
// activate the wireless client
|
||||
debug!("Activating WiFi client mode.");
|
||||
match network_client::activate_client() {
|
||||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
Json(build_json_response(status, None, None))
|
||||
build_json_response(status, None, None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to activate WiFi client mode.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/v1/network/wifi", data = "<wifi>")]
|
||||
pub fn add_wifi(wifi: Json<WiFi>) -> Json<JsonResponse> {
|
||||
pub fn add_wifi(wifi: Json<WiFi>) -> Value {
|
||||
// generate and write wifi config to wpa_supplicant
|
||||
match network_client::add(&wifi.ssid, &wifi.pass) {
|
||||
Ok(_) => {
|
||||
|
@ -858,20 +854,20 @@ pub fn add_wifi(wifi: Json<WiFi>) -> Json<JsonResponse> {
|
|||
// json response for successful update
|
||||
let status = "success".to_string();
|
||||
let msg = "WiFi credentials added.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/v1/network/wifi/connect", data = "<ssid>")]
|
||||
pub fn connect_ap(ssid: Json<Ssid>) -> Json<JsonResponse> {
|
||||
pub fn connect_ap(ssid: Json<Ssid>) -> Value {
|
||||
// retrieve the id for the given network ssid
|
||||
match network_client::id("wlan0", &ssid.ssid) {
|
||||
// attempt connection with the given network
|
||||
|
@ -879,60 +875,60 @@ pub fn connect_ap(ssid: Json<Ssid>) -> Json<JsonResponse> {
|
|||
Ok(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Connected to chosen network.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to connect to chosen network.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to retrieve the network ID.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/v1/network/wifi/disconnect", data = "<ssid>")]
|
||||
pub fn disconnect_ap(ssid: Json<Ssid>) -> Json<JsonResponse> {
|
||||
pub fn disconnect_ap(ssid: Json<Ssid>) -> 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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "Failed to disconnect from WiFi network.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/v1/network/wifi/forget", data = "<network>")]
|
||||
pub fn forget_ap(network: Json<Ssid>) -> Json<JsonResponse> {
|
||||
pub fn forget_ap(network: Json<Ssid>) -> 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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/v1/network/wifi/modify", data = "<wifi>")]
|
||||
pub fn modify_password(wifi: Json<WiFi>) -> Json<JsonResponse> {
|
||||
pub fn modify_password(wifi: Json<WiFi>) -> Value {
|
||||
let ssid = &wifi.ssid;
|
||||
let pass = &wifi.pass;
|
||||
// we are using a helper function (`update`) to delete the old
|
||||
|
@ -943,13 +939,13 @@ pub fn modify_password(wifi: Json<WiFi>) -> Json<JsonResponse> {
|
|||
debug!("WiFi password updated for chosen network.");
|
||||
let status = "success".to_string();
|
||||
let msg = "WiFi password updated.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -957,7 +953,7 @@ pub fn modify_password(wifi: Json<WiFi>) -> Json<JsonResponse> {
|
|||
// HELPERS AND ROUTES FOR NETWORK STATE QUERIES
|
||||
|
||||
#[get("/api/v1/network/ip")]
|
||||
pub fn return_ip() -> Json<JsonResponse> {
|
||||
pub fn return_ip() -> 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,
|
||||
|
@ -973,45 +969,45 @@ pub fn return_ip() -> Json<JsonResponse> {
|
|||
"ap0": ap_ip
|
||||
});
|
||||
let status = "success".to_string();
|
||||
Json(build_json_response(status, Some(data), None))
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
|
||||
#[get("/api/v1/network/rssi")]
|
||||
pub fn return_rssi() -> Json<JsonResponse> {
|
||||
pub fn return_rssi() -> Value {
|
||||
// retrieve rssi for connected network
|
||||
match network_client::rssi("wlan0") {
|
||||
Ok(rssi) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(rssi);
|
||||
Json(build_json_response(status, Some(data), None))
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Not currently connected to an access point.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/api/v1/network/ssid")]
|
||||
pub fn return_ssid() -> Json<JsonResponse> {
|
||||
pub fn return_ssid() -> Value {
|
||||
// retrieve ssid for connected network
|
||||
match network_client::ssid("wlan0") {
|
||||
Ok(network) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(network);
|
||||
Json(build_json_response(status, Some(data), None))
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Not currently connected to an access point.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/api/v1/network/state")]
|
||||
pub fn return_state() -> Json<JsonResponse> {
|
||||
pub fn return_state() -> 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,
|
||||
|
@ -1027,39 +1023,39 @@ pub fn return_state() -> Json<JsonResponse> {
|
|||
"ap0": ap_state
|
||||
});
|
||||
let status = "success".to_string();
|
||||
Json(build_json_response(status, Some(data), None))
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
|
||||
#[get("/api/v1/network/status")]
|
||||
pub fn return_status() -> Json<JsonResponse> {
|
||||
pub fn return_status() -> Value {
|
||||
// retrieve status info for wlan0 interface
|
||||
match network_client::status("wlan0") {
|
||||
Ok(network) => {
|
||||
let status = "success".to_string();
|
||||
let data = json!(network);
|
||||
Json(build_json_response(status, Some(data), None))
|
||||
build_json_response(status, Some(data), None)
|
||||
}
|
||||
Err(_) => {
|
||||
let status = "success".to_string();
|
||||
let msg = "Not currently connected to an access point.".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/api/v1/network/wifi")]
|
||||
pub fn scan_networks() -> Json<JsonResponse> {
|
||||
pub fn scan_networks() -> 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);
|
||||
Json(build_json_response(status, Some(data), None))
|
||||
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();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
build_json_response(status, None, Some(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use rocket::serde::json::{Value, json};
|
||||
use rocket::http::{ContentType, Status};
|
||||
use rocket::local::Client;
|
||||
use rocket_contrib::json;
|
||||
use rocket::local::blocking::Client;
|
||||
|
||||
use crate::utils::build_json_response;
|
||||
|
||||
use super::rocket;
|
||||
use super::init_rocket;
|
||||
|
||||
// helper function to test correct retrieval and content of a file
|
||||
fn test_query_file<T>(path: &str, file: T, status: Status)
|
||||
where
|
||||
T: Into<Option<&'static str>>,
|
||||
{
|
||||
let client = Client::new(rocket()).unwrap();
|
||||
let mut response = client.get(path).dispatch();
|
||||
let client = Client::tracked(init_rocket()).unwrap();
|
||||
let response = client.get(path).dispatch();
|
||||
assert_eq!(response.status(), status);
|
||||
|
||||
let body_data = response.body().and_then(|body| body.into_bytes());
|
||||
let body_data = response.into_bytes();
|
||||
if let Some(filename) = file.into() {
|
||||
let expected_data = read_file_content(filename);
|
||||
assert!(body_data.map_or(false, |s| s == expected_data));
|
||||
|
@ -39,11 +39,11 @@ fn read_file_content(path: &str) -> Vec<u8> {
|
|||
|
||||
#[test]
|
||||
fn index_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("/peers"));
|
||||
assert!(body.contains("/profile"));
|
||||
assert!(body.contains("/messages"));
|
||||
|
@ -54,11 +54,11 @@ fn index_html() {
|
|||
|
||||
#[test]
|
||||
fn network_card_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/network").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("MODE"));
|
||||
assert!(body.contains("SSID"));
|
||||
assert!(body.contains("IP"));
|
||||
|
@ -72,11 +72,11 @@ fn network_card_html() {
|
|||
|
||||
#[test]
|
||||
fn network_list_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/network/wifi").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/wifi").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("WiFi Networks"));
|
||||
assert!(body.contains("No saved or available networks found."));
|
||||
}
|
||||
|
@ -84,21 +84,21 @@ fn network_list_html() {
|
|||
// TODO: needs further testing once template has been refactored
|
||||
#[test]
|
||||
fn network_detail_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/wifi?ssid=Home").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
//let body = response.body_string().unwrap();
|
||||
//let body = response.into_string().unwrap();
|
||||
//assert!(body.contains("Network not found"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn network_add_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/network/wifi/add").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/wifi/add").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Add WiFi Network"));
|
||||
assert!(body.contains("SSID"));
|
||||
assert!(body.contains("Password"));
|
||||
|
@ -108,11 +108,11 @@ fn network_add_html() {
|
|||
|
||||
#[test]
|
||||
fn network_add_ssid_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/network/wifi/add?ssid=Home").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/wifi/add?ssid=Home").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Add WiFi Network"));
|
||||
assert!(body.contains("Home"));
|
||||
assert!(body.contains("Password"));
|
||||
|
@ -122,11 +122,11 @@ fn network_add_ssid_html() {
|
|||
|
||||
#[test]
|
||||
fn device_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/device").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/device").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Device Status"));
|
||||
assert!(body.contains("Networking"));
|
||||
assert!(body.contains("Display"));
|
||||
|
@ -135,71 +135,71 @@ fn device_html() {
|
|||
|
||||
#[test]
|
||||
fn help_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/help").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/help").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Help"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn login_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/login").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/login").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Login"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn messages_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/messages").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/messages").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Private Messages"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peers_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/peers").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/peers").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Scuttlebutt Peers"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/profile").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/profile").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Profile"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shutdown_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/shutdown").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/shutdown").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Shutdown Device"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn network_usage_html() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client.get("/network/wifi/usage").dispatch();
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/wifi/usage").dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::HTML));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Network Data Usage"));
|
||||
assert!(body.contains("WARNING THRESHOLD"));
|
||||
assert!(body.contains("Update"));
|
||||
|
@ -208,7 +208,7 @@ fn network_usage_html() {
|
|||
|
||||
#[test]
|
||||
fn add_credentials() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/network/wifi/add")
|
||||
.header(ContentType::Form)
|
||||
|
@ -220,7 +220,7 @@ fn add_credentials() {
|
|||
|
||||
#[test]
|
||||
fn forget_wifi() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/network/wifi/forget")
|
||||
.header(ContentType::Form)
|
||||
|
@ -232,7 +232,7 @@ fn forget_wifi() {
|
|||
|
||||
#[test]
|
||||
fn modify_password() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/network/wifi/modify")
|
||||
.header(ContentType::Form)
|
||||
|
@ -244,7 +244,7 @@ fn modify_password() {
|
|||
|
||||
#[test]
|
||||
fn deploy_ap() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/ap/activate").dispatch();
|
||||
// check for 303 status (redirect)
|
||||
assert_eq!(response.status(), Status::SeeOther);
|
||||
|
@ -253,7 +253,7 @@ fn deploy_ap() {
|
|||
|
||||
#[test]
|
||||
fn deploy_client() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client.get("/network/wifi/activate").dispatch();
|
||||
// check for 303 status (redirect)
|
||||
assert_eq!(response.status(), Status::SeeOther);
|
||||
|
@ -264,7 +264,7 @@ fn deploy_client() {
|
|||
|
||||
#[test]
|
||||
fn activate_ap() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/api/v1/network/activate_ap")
|
||||
.header(ContentType::JSON)
|
||||
|
@ -275,7 +275,7 @@ fn activate_ap() {
|
|||
|
||||
#[test]
|
||||
fn activate_client() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/api/v1/network/activate_client")
|
||||
.header(ContentType::JSON)
|
||||
|
@ -286,54 +286,54 @@ fn activate_client() {
|
|||
|
||||
#[test]
|
||||
fn return_ip() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/network/ip")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("wlan0"));
|
||||
assert!(body.contains("ap0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_rssi() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/network/rssi")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Not currently connected to an access point."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_ssid() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/network/ssid")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Not currently connected to an access point."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_state() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/network/state")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("ap0"));
|
||||
assert!(body.contains("wlan0"));
|
||||
assert!(body.contains("unavailable"));
|
||||
|
@ -341,82 +341,82 @@ fn return_state() {
|
|||
|
||||
#[test]
|
||||
fn return_status() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/network/status")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Not currently connected to an access point."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scan_networks() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/network/wifi")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Unable to scan for networks. Interface may be deactivated."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_wifi() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/api/v1/network/wifi")
|
||||
.header(ContentType::JSON)
|
||||
.body(r#"{ "ssid": "Home", "pass": "Password" }"#)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Failed to add WiFi credentials."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_wifi() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/api/v1/network/wifi/forget")
|
||||
.header(ContentType::JSON)
|
||||
.body(r#"{ "ssid": "Home" }"#)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Failed to remove WiFi network credentials."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_password() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.post("/api/v1/network/wifi/modify")
|
||||
.header(ContentType::JSON)
|
||||
.body(r#"{ "ssid": "Home", "pass": "Password" }"#)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("Failed to update WiFi password."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ping_pong() {
|
||||
let client = Client::new(rocket()).expect("valid rocket instance");
|
||||
let mut response = client
|
||||
let client = Client::tracked(init_rocket()).expect("valid rocket instance");
|
||||
let response = client
|
||||
.get("/api/v1/ping")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
assert_eq!(response.content_type(), Some(ContentType::JSON));
|
||||
let body = response.body_string().unwrap();
|
||||
let body = response.into_string().unwrap();
|
||||
assert!(body.contains("pong!"));
|
||||
}
|
||||
|
||||
|
@ -426,12 +426,13 @@ fn ping_pong() {
|
|||
fn test_build_json_response() {
|
||||
let status = "success".to_string();
|
||||
let data = json!("WiFi credentials added.".to_string());
|
||||
let json = build_json_response(status, Some(data), None);
|
||||
assert_eq!(json.status, "success");
|
||||
assert_eq!(json.data, Some(json!("WiFi credentials added.")));
|
||||
assert_eq!(json.msg, None);
|
||||
let j: Value = build_json_response(status, Some(data), None);
|
||||
assert_eq!(j["status"], "success");
|
||||
assert_eq!(j["data"], "WiFi credentials added.");
|
||||
assert_eq!(j["msg"], json!(null));
|
||||
}
|
||||
|
||||
|
||||
// FILE TESTS
|
||||
|
||||
#[test]
|
||||
|
@ -471,16 +472,16 @@ fn invalid_path() {
|
|||
|
||||
#[test]
|
||||
fn invalid_get_request() {
|
||||
let client = Client::new(rocket()).unwrap();
|
||||
let client = Client::tracked(init_rocket()).unwrap();
|
||||
|
||||
// try to get a path that doesn't exist
|
||||
let mut res = client
|
||||
let res = client
|
||||
.get("/message/99")
|
||||
.header(ContentType::JSON)
|
||||
.dispatch();
|
||||
assert_eq!(res.status(), Status::NotFound);
|
||||
|
||||
let body = res.body_string().unwrap();
|
||||
let body = res.into_string().unwrap();
|
||||
assert!(body.contains("404: Page Not Found"));
|
||||
assert!(body.contains("No PeachCloud resource exists for this URL."));
|
||||
}
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
pub mod monitor;
|
||||
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use serde::Serialize;
|
||||
use rocket::serde::json::{Value, json};
|
||||
use rocket::serde::{Serialize};
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct JsonResponse {
|
||||
pub status: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub data: Option<JsonValue>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub msg: Option<String>,
|
||||
}
|
||||
|
||||
pub fn build_json_response(
|
||||
status: String,
|
||||
data: Option<JsonValue>,
|
||||
data: Option<Value>,
|
||||
msg: Option<String>,
|
||||
) -> JsonResponse {
|
||||
JsonResponse { status, data, msg }
|
||||
) -> Value {
|
||||
json!({ "status": status, "data": data, "msg": msg })
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use nest::{Error, Store, Value};
|
||||
use rocket::request::FromForm;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use rocket::form::{FromForm};
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
/// Network traffic data total
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
// NOTE: websockets are not currently in use for PeachCloud but may be in the
|
||||
// future.
|
||||
|
||||
use std::io;
|
||||
use std::thread;
|
||||
|
||||
use log::{debug, info};
|
||||
use websocket::sync::Server;
|
||||
use websocket::{Message, OwnedMessage};
|
||||
|
||||
pub fn websocket_server(address: String) -> io::Result<()> {
|
||||
// start listening for WebSocket connections
|
||||
let ws_server = Server::bind(address)?;
|
||||
|
||||
info!("Listening for WebSocket connections.");
|
||||
for connection in ws_server.filter_map(Result::ok) {
|
||||
// spawn a new thread for each connection
|
||||
thread::spawn(move || {
|
||||
if !connection
|
||||
.protocols()
|
||||
.contains(&"rust-websocket".to_string())
|
||||
{
|
||||
connection.reject().unwrap();
|
||||
return;
|
||||
}
|
||||
|
||||
let mut client = connection.use_protocol("rust-websocket").accept().unwrap();
|
||||
|
||||
let client_ip = client.peer_addr().unwrap();
|
||||
|
||||
debug!("Websocket connection from {}.", client_ip);
|
||||
|
||||
let msg_text = "Websocket successfully connected.".to_string();
|
||||
let message = Message::text(msg_text);
|
||||
client.send_message(&message).unwrap();
|
||||
|
||||
let (mut receiver, mut sender) = client.split().unwrap();
|
||||
|
||||
for message in receiver.incoming_messages() {
|
||||
let message = message.unwrap();
|
||||
|
||||
match message {
|
||||
OwnedMessage::Close(_) => {
|
||||
debug!("Received close message.");
|
||||
let message = Message::close();
|
||||
sender.send_message(&message).unwrap();
|
||||
debug!("Websocket client {} disconnected.", client_ip);
|
||||
return;
|
||||
}
|
||||
OwnedMessage::Ping(data) => {
|
||||
debug!("Received ping message.");
|
||||
let message = Message::pong(data);
|
||||
sender.send_message(&message).unwrap();
|
||||
}
|
||||
_ => {
|
||||
sender.send_message(&message).unwrap();
|
||||
debug!("Received unknown message: {:?}", message);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue