286 lines
9.6 KiB
Rust
286 lines
9.6 KiB
Rust
use std::{
|
|
io,
|
|
process::{Command, Output},
|
|
};
|
|
|
|
use log::{info, warn};
|
|
use peach_lib::sbot::{SbotConfig, SbotStatus};
|
|
use rocket::{
|
|
form::{Form, FromForm},
|
|
get, post,
|
|
request::FlashMessage,
|
|
response::{Flash, Redirect},
|
|
};
|
|
use rocket_dyn_templates::{tera::Context, Template};
|
|
|
|
use crate::routes::authentication::Authenticated;
|
|
use crate::utils;
|
|
|
|
#[derive(Debug, FromForm)]
|
|
pub struct SbotConfigForm {
|
|
/// Directory path for the log and indexes.
|
|
repo: String,
|
|
/// Directory path for writing debug output.
|
|
debugdir: String,
|
|
/// Secret-handshake app-key (aka. network key).
|
|
shscap: String,
|
|
/// HMAC hash used to sign messages.
|
|
hmac: String,
|
|
/// Replication hops (1: friends, 2: friends of friends).
|
|
hops: u8,
|
|
/// IP address to listen on.
|
|
lis_ip: String,
|
|
/// Port to listen on.
|
|
lis_port: String,
|
|
/// Address to listen on for WebSocket connections.
|
|
wslis: String,
|
|
/// Address to for metrics and pprof HTTP server.
|
|
debuglis: String,
|
|
/// Enable sending local UDP broadcasts.
|
|
localadv: bool,
|
|
/// Enable listening for UDP broadcasts and connecting.
|
|
localdiscov: bool,
|
|
/// Enable syncing by using epidemic-broadcast-trees (EBT).
|
|
enable_ebt: bool,
|
|
/// Bypass graph auth and fetch remote's feed (useful for pubs that are restoring their data
|
|
/// from peer; user beware - caveats about).
|
|
promisc: bool,
|
|
/// Disable the UNIX socket RPC interface.
|
|
nounixsock: bool,
|
|
/// Run the go-sbot on system start-up (systemd service enabled).
|
|
startup: bool,
|
|
/// Attempt to repair the filesystem before starting.
|
|
repair: bool,
|
|
}
|
|
|
|
// HELPERS AND ROUTES FOR /settings/scuttlebutt
|
|
|
|
/// Scuttlebutt settings menu.
|
|
#[get("/")]
|
|
pub fn ssb_settings_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|
// retrieve current ui theme
|
|
let theme = utils::get_theme();
|
|
|
|
// retrieve go-sbot systemd process status
|
|
let sbot_status = SbotStatus::read().ok();
|
|
|
|
let mut context = Context::new();
|
|
context.insert("theme", &theme);
|
|
context.insert("sbot_status", &sbot_status);
|
|
context.insert("back", &Some("/settings".to_string()));
|
|
context.insert("title", &Some("Scuttlebutt Settings".to_string()));
|
|
|
|
if let Some(flash) = flash {
|
|
context.insert("flash_name", &Some(flash.kind().to_string()));
|
|
context.insert("flash_msg", &Some(flash.message().to_string()));
|
|
};
|
|
|
|
Template::render("settings/scuttlebutt/menu", &context.into_json())
|
|
}
|
|
|
|
/// Sbot configuration page (includes form for updating configuration parameters).
|
|
#[get("/configure")]
|
|
pub fn configure_sbot(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
|
|
// retrieve current ui theme
|
|
let theme = utils::get_theme();
|
|
|
|
// retrieve go-sbot systemd process status
|
|
let sbot_status = SbotStatus::read().ok();
|
|
let run_on_startup = sbot_status.map(|status| status.boot_state);
|
|
|
|
// retrieve sbot config parameters
|
|
let sbot_config = SbotConfig::read().ok();
|
|
|
|
let mut context = Context::new();
|
|
context.insert("theme", &theme);
|
|
context.insert("back", &Some("/settings/scuttlebutt".to_string()));
|
|
context.insert("title", &Some("Sbot Configuration".to_string()));
|
|
context.insert("sbot_config", &sbot_config);
|
|
context.insert("run_on_startup", &Some(run_on_startup));
|
|
|
|
if let Some(flash) = flash {
|
|
context.insert("flash_name", &Some(flash.kind().to_string()));
|
|
context.insert("flash_msg", &Some(flash.message().to_string()));
|
|
};
|
|
|
|
Template::render("settings/scuttlebutt/configure_sbot", &context.into_json())
|
|
}
|
|
|
|
// TODO: consider using `Contextual` here to collect all submitted form
|
|
// fields to re-render forms with submitted values on error
|
|
|
|
/// Receive the sbot configuration form data and save it to file.
|
|
#[post("/configure?<restart>", data = "<config>")]
|
|
pub fn configure_sbot_post(
|
|
restart: bool,
|
|
config: Form<SbotConfigForm>,
|
|
_auth: Authenticated,
|
|
) -> Flash<Redirect> {
|
|
// call `into_inner()` to take ownership of the `config` data
|
|
let owned_config = config.into_inner();
|
|
|
|
// concat the ip and port for listen address
|
|
let lis = format!("{}:{}", owned_config.lis_ip, owned_config.lis_port);
|
|
|
|
// instantiate `SbotConfig` from form data
|
|
let config = SbotConfig {
|
|
lis,
|
|
hops: owned_config.hops,
|
|
repo: owned_config.repo,
|
|
debugdir: owned_config.debugdir,
|
|
shscap: owned_config.shscap,
|
|
localadv: owned_config.localadv,
|
|
localdiscov: owned_config.localdiscov,
|
|
hmac: owned_config.hmac,
|
|
wslis: owned_config.wslis,
|
|
debuglis: owned_config.debuglis,
|
|
enable_ebt: owned_config.enable_ebt,
|
|
promisc: owned_config.promisc,
|
|
nounixsock: owned_config.nounixsock,
|
|
repair: owned_config.repair,
|
|
};
|
|
|
|
match owned_config.startup {
|
|
true => {
|
|
info!("Enabling go-sbot.service");
|
|
if let Err(e) = systemctl_sbot_cmd("enable") {
|
|
warn!("Failed to enable go-sbot.service: {}", e)
|
|
}
|
|
}
|
|
false => {
|
|
info!("Disabling go-sbot.service");
|
|
if let Err(e) = systemctl_sbot_cmd("disable") {
|
|
warn!("Failed to disable go-sbot.service: {}", e)
|
|
}
|
|
}
|
|
};
|
|
|
|
// write config to file
|
|
match SbotConfig::write(config) {
|
|
Ok(_) => {
|
|
// if `restart` query parameter is `true`, attempt sbot process (re)start
|
|
if restart {
|
|
restart_sbot_process(
|
|
// redirect url
|
|
"/settings/scuttlebutt/configure",
|
|
// success flash msg
|
|
"Updated configuration and restarted the sbot process",
|
|
// first failed flash msg
|
|
"Updated configuration but failed to start the sbot process",
|
|
// second failed flash msg
|
|
"Updated configuration but failed to stop the sbot process",
|
|
)
|
|
} else {
|
|
Flash::success(
|
|
Redirect::to("/settings/scuttlebutt/configure"),
|
|
"Updated configuration",
|
|
)
|
|
}
|
|
}
|
|
Err(e) => Flash::error(
|
|
Redirect::to("/settings/scuttlebutt/configure"),
|
|
format!("Failed to update configuration: {}", e),
|
|
),
|
|
}
|
|
}
|
|
|
|
/// Set default configuration parameters for the go-sbot and save them to file.
|
|
#[get("/configure/default")]
|
|
pub fn configure_sbot_default(_auth: Authenticated) -> Flash<Redirect> {
|
|
let default_config = SbotConfig::default();
|
|
|
|
// write default config to file
|
|
match SbotConfig::write(default_config) {
|
|
Ok(_) => Flash::success(
|
|
Redirect::to("/settings/scuttlebutt/configure"),
|
|
"Restored default configuration",
|
|
),
|
|
Err(e) => Flash::error(
|
|
Redirect::to("/settings/scuttlebutt/configure"),
|
|
format!("Failed to restore default configuration: {}", e),
|
|
),
|
|
}
|
|
}
|
|
|
|
/// Attempt to start the go-sbot.service process.
|
|
/// Redirect to the Scuttlebutt settings menu and communicate the outcome of
|
|
/// the attempt via a flash message.
|
|
#[get("/start")]
|
|
pub fn start_sbot(_auth: Authenticated) -> Flash<Redirect> {
|
|
info!("Starting go-sbot.service");
|
|
match systemctl_sbot_cmd("start") {
|
|
Ok(_) => Flash::success(
|
|
Redirect::to("/settings/scuttlebutt"),
|
|
"Sbot process has been started",
|
|
),
|
|
Err(_) => Flash::error(
|
|
Redirect::to("/settings/scuttlebutt"),
|
|
"Failed to start the sbot process",
|
|
),
|
|
}
|
|
}
|
|
|
|
/// Attempt to stop the go-sbot.service process.
|
|
/// Redirect to the Scuttlebutt settings menu and communicate the outcome of
|
|
/// the attempt via a flash message.
|
|
#[get("/stop")]
|
|
pub fn stop_sbot(_auth: Authenticated) -> Flash<Redirect> {
|
|
info!("Stopping go-sbot.service");
|
|
match systemctl_sbot_cmd("stop") {
|
|
Ok(_) => Flash::success(
|
|
Redirect::to("/settings/scuttlebutt"),
|
|
"Sbot process has been stopped",
|
|
),
|
|
Err(_) => Flash::error(
|
|
Redirect::to("/settings/scuttlebutt"),
|
|
"Failed to stop the sbot process",
|
|
),
|
|
}
|
|
}
|
|
|
|
/// Attempt to restart the go-sbot.service process.
|
|
/// Redirect to the Scuttlebutt settings menu and communicate the outcome of
|
|
/// the attempt via a flash message.
|
|
#[get("/restart")]
|
|
pub fn restart_sbot(_auth: Authenticated) -> Flash<Redirect> {
|
|
restart_sbot_process(
|
|
"/settings/scuttlebutt",
|
|
"Sbot process has been restarted",
|
|
"Failed to start the sbot process",
|
|
"Failed to stop the sbot process",
|
|
)
|
|
}
|
|
|
|
// HELPER FUNCTIONS
|
|
|
|
/// Executes a systemctl command for the go-sbot.service process.
|
|
pub fn systemctl_sbot_cmd(cmd: &str) -> io::Result<Output> {
|
|
Command::new("systemctl")
|
|
.arg("--user")
|
|
.arg(cmd)
|
|
.arg("go-sbot.service")
|
|
.output()
|
|
}
|
|
|
|
/// Executes a systemctl stop command followed by start command.
|
|
/// Returns a redirect with a flash message stating the output of the restart attempt.
|
|
fn restart_sbot_process(
|
|
redirect_url: &str,
|
|
success_msg: &str,
|
|
start_failed_msg: &str,
|
|
stop_failed_msg: &str,
|
|
) -> Flash<Redirect> {
|
|
let url = redirect_url.to_string();
|
|
|
|
info!("Restarting go-sbot.service");
|
|
match systemctl_sbot_cmd("stop") {
|
|
// if stop was successful, try to start the process
|
|
Ok(_) => match systemctl_sbot_cmd("start") {
|
|
Ok(_) => Flash::success(Redirect::to(url), success_msg),
|
|
|
|
Err(e) => Flash::error(Redirect::to(url), format!("{}: {}", start_failed_msg, e)),
|
|
},
|
|
Err(e) => Flash::error(Redirect::to(url), format!("{}: {}", stop_failed_msg, e)),
|
|
}
|
|
}
|