279 lines
13 KiB
Rust
279 lines
13 KiB
Rust
use log::{debug, warn};
|
|
use maud::{html, PreEscaped};
|
|
use peach_lib::sbot::{SbotConfig, SbotStatus};
|
|
use rouille::{post_input, try_or_400, Request, Response};
|
|
|
|
use crate::{
|
|
templates,
|
|
utils::{
|
|
flash::{FlashRequest, FlashResponse},
|
|
sbot, theme,
|
|
},
|
|
};
|
|
|
|
/// Read the status and configuration of the sbot.
|
|
/// Define fallback values if an error is returned from either read function.
|
|
fn read_status_and_config() -> (String, SbotConfig, String, String) {
|
|
// retrieve go-sbot systemd process status
|
|
let run_on_startup = if let Ok(status) = SbotStatus::read() {
|
|
// if the read is ok, return the value or "disabled" if no value is set
|
|
match status.boot_state {
|
|
Some(state) => state,
|
|
None => "disabled".to_string(),
|
|
}
|
|
} else {
|
|
// if the read returns an error, set the value to "disabled"
|
|
"disabled".to_string()
|
|
};
|
|
|
|
// retrieve sbot config parameters
|
|
let sbot_config = match SbotConfig::read() {
|
|
Ok(config) => config,
|
|
// build default config if an error is returned from the read attempt
|
|
Err(_) => SbotConfig::default(),
|
|
};
|
|
|
|
// split the listen address into ip and port
|
|
let (ip, port) = match sbot_config.lis.find(':') {
|
|
Some(index) => {
|
|
let (ip, port) = sbot_config.lis.split_at(index);
|
|
// remove the : from the port
|
|
(ip.to_string(), port.replace(':', ""))
|
|
}
|
|
// if no ':' separator is found, assume an ip has been configured (without port)
|
|
None => (sbot_config.lis.to_string(), String::new()),
|
|
};
|
|
|
|
(run_on_startup, sbot_config, ip, port)
|
|
}
|
|
|
|
/// Scuttlebutt settings menu template builder.
|
|
pub fn build_template(request: &Request) -> PreEscaped<String> {
|
|
// check for flash cookies; will be (None, None) if no flash cookies are found
|
|
let (flash_name, flash_msg) = request.retrieve_flash();
|
|
|
|
let (run_on_startup, sbot_config, ip, port) = read_status_and_config();
|
|
|
|
let menu_template = html! {
|
|
(PreEscaped("<!-- SBOT CONFIGURATION FORM -->"))
|
|
div class="card center" {
|
|
form id="sbotConfig" class="center" action="/settings/scuttlebutt/configure" method="post" {
|
|
div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Number of hops to replicate" {
|
|
label for="hops" class="label-small font-gray" { "HOPS" }
|
|
div id="hops" style="display: flex; justify-content: space-evenly;" {
|
|
div {
|
|
@if sbot_config.hops == 0 {
|
|
input type="radio" id="hops_0" name="hops" value="0" checked;
|
|
} @else {
|
|
input type="radio" id="hops_0" name="hops" value="0";
|
|
}
|
|
label class="font-normal" for="hops_0" { "0" }
|
|
}
|
|
div {
|
|
@if sbot_config.hops == 1 {
|
|
input type="radio" id="hops_1" name="hops" value="1" checked;
|
|
} @else {
|
|
input type="radio" id="hops_1" name="hops" value="1";
|
|
}
|
|
label class="font-normal" for="hops_1" { "1" }
|
|
}
|
|
div {
|
|
@if sbot_config.hops == 2 {
|
|
input type="radio" id="hops_2" name="hops" value="2" checked;
|
|
} @else {
|
|
input type="radio" id="hops_2" name="hops" value="2";
|
|
}
|
|
label class="font-normal" for="hops_2" { "2" }
|
|
}
|
|
div {
|
|
@if sbot_config.hops == 3 {
|
|
input type="radio" id="hops_3" name="hops" value="3" checked;
|
|
} @else {
|
|
input type="radio" id="hops_3" name="hops" value="3";
|
|
}
|
|
label class="font-normal" for="hops_3" { "3" }
|
|
}
|
|
div {
|
|
@if sbot_config.hops == 4 {
|
|
input type="radio" id="hops_4" name="hops" value="4" checked;
|
|
} @else {
|
|
input type="radio" id="hops_4" name="hops" value="4";
|
|
}
|
|
label class="font-normal" for="hops_4" { "4" }
|
|
}
|
|
}
|
|
}
|
|
div class="center" style="display: flex; justify-content: space-between;" {
|
|
div style="display: flex; flex-direction: column; width: 60%; margin-bottom: 2rem;" title="IP address on which the sbot runs" {
|
|
label for="ip" class="label-small font-gray" { "IP ADDRESS" }
|
|
input type="text" id="ip" name="lis_ip" value=(ip);
|
|
}
|
|
div style="display: flex; flex-direction: column; width: 20%; margin-bottom: 2rem;" title="Port on which the sbot runs" {
|
|
label for="port" class="label-small font-gray" { "PORT" }
|
|
input type="text" id="port" name="lis_port" value=(port);
|
|
}
|
|
}
|
|
div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Network key (aka 'caps key') to define the Scuttleverse in which the sbot operates in" {
|
|
label for="network_key" class="label-small font-gray" { "NETWORK KEY" }
|
|
input type="text" id="network_key" name="shscap" value=(sbot_config.shscap);
|
|
}
|
|
div class="center" style="display: flex; flex-direction: column; margin-bottom: 2rem;" title="Directory in which the sbot database is saved" {
|
|
label for="database_dir" class="label-small font-gray" { "DATABASE DIRECTORY" }
|
|
input type="text" id="database_dir" name="repo" value=(sbot_config.repo);
|
|
}
|
|
div class="center" {
|
|
@if sbot_config.enable_ebt {
|
|
input type="checkbox" id="ebtReplication" style="margin-bottom: 1rem;" name="enable_ebt" checked;
|
|
} @else {
|
|
input type="checkbox" id="ebtReplication" style="margin-bottom: 1rem;" name="enable_ebt";
|
|
}
|
|
label class="font-normal" for="ebtReplication" title="Enable Epidemic Broadcast Tree (EBT) replication instead of legacy replication" {
|
|
"Enable EBT Replication"
|
|
}
|
|
br;
|
|
@if sbot_config.localadv {
|
|
input type="checkbox" id="lanBroadcast" style="margin-bottom: 1rem;" name="localadv" checked;
|
|
} @else {
|
|
input type="checkbox" id="lanBroadcast" style="margin-bottom: 1rem;" name="localadv";
|
|
}
|
|
label class="font-normal" for="lanBroadcast" title="Broadcast the IP and port of this sbot instance so that local peers can discovery it and attempt to connect" {
|
|
"Enable LAN Broadcasting"
|
|
}
|
|
br;
|
|
@if sbot_config.localdiscov {
|
|
input type="checkbox" id="lanDiscovery" style="margin-bottom: 1rem;" name="localdiscov" checked;
|
|
} @else {
|
|
input type="checkbox" id="lanDiscovery" style="margin-bottom: 1rem;" name="localdiscov";
|
|
}
|
|
label class="font-normal" for="lanDiscovery" title="Listen for the presence of local peers and attempt to connect if found" { "Enable LAN Discovery" }
|
|
br;
|
|
@if run_on_startup == "enabled" {
|
|
input type="checkbox" id="startup" style="margin-bottom: 1rem;" name="startup" checked;
|
|
} @else {
|
|
input type="checkbox" id="startup" style="margin-bottom: 1rem;" name="startup";
|
|
}
|
|
label class="font-normal" for="startup" title="Run the pub automatically on system startup" { "Run pub when computer starts" }
|
|
br;
|
|
@if sbot_config.repair {
|
|
input type="checkbox" id="repair" name="repair" checked;
|
|
} @else {
|
|
input type="checkbox" id="repair" name="repair";
|
|
}
|
|
label class="font-normal" for="repair" title="Attempt to repair the filesystem when starting the pub" { "Attempt filesystem repair when pub starts" }
|
|
}
|
|
(PreEscaped("<!-- hidden input elements for all other config variables -->"))
|
|
input type="hidden" id="debugdir" name="debugdir" value=(sbot_config.debugdir);
|
|
input type="hidden" id="hmac" name="hmac" value=(sbot_config.hmac);
|
|
input type="hidden" id="wslis" name="wslis" value=(sbot_config.wslis);
|
|
input type="hidden" id="debuglis" name="debuglis" value=(sbot_config.debuglis);
|
|
input type="hidden" id="promisc" name="promisc" value=(sbot_config.promisc);
|
|
input type="hidden" id="nounixsock" name="nounixsock" value=(sbot_config.nounixsock);
|
|
(PreEscaped("<!-- BUTTONS -->"))
|
|
input id="saveConfig" class="button button-primary center" style="margin-top: 2rem;" type="submit" title="Save configuration parameters to file" value="Save";
|
|
input id="saveRestartConfig" class="button button-primary center" type="submit" title="Save configuration parameters to file and then (re)start the pub" value="Save & Restart" formaction="/settings/scuttlebutt/configure/restart";
|
|
a id="restoreDefaults" class="button button-warning center" href="/settings/scuttlebutt/configure/default" title="Restore default configuration parameters and save them to file" { "Restore Defaults" }
|
|
}
|
|
// 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))
|
|
}
|
|
}
|
|
};
|
|
|
|
// wrap the nav bars around the settings menu template content
|
|
// parameters are template, title and back url
|
|
let body = templates::nav::build_template(
|
|
menu_template,
|
|
"Scuttlebutt Settings",
|
|
Some("/settings/scuttlebutt"),
|
|
);
|
|
|
|
// query the current theme so we can pass it into the base template builder
|
|
let theme = theme::get_theme();
|
|
|
|
// render the base template with the provided body
|
|
templates::base::build_template(body, theme)
|
|
}
|
|
|
|
/// Parse the sbot configuration values and write to file.
|
|
pub fn handle_form(request: &Request, restart: bool) -> Response {
|
|
// query the request body for form data
|
|
// return a 400 error if the admin_id field is missing
|
|
let data = try_or_400!(post_input!(request, {
|
|
repo: String,
|
|
debugdir: String,
|
|
shscap: String,
|
|
hmac: String,
|
|
hops: u8,
|
|
lis_ip: String,
|
|
lis_port: String,
|
|
wslis: String,
|
|
debuglis: String,
|
|
localadv: bool,
|
|
localdiscov: bool,
|
|
enable_ebt: bool,
|
|
promisc: bool,
|
|
nounixsock: bool,
|
|
startup: bool,
|
|
repair: bool,
|
|
}));
|
|
|
|
// concat the ip and port for listen address
|
|
let lis = format!("{}:{}", data.lis_ip, data.lis_port);
|
|
|
|
// instantiate `SbotConfig` from form data
|
|
let config = SbotConfig {
|
|
lis,
|
|
hops: data.hops,
|
|
repo: data.repo,
|
|
debugdir: data.debugdir,
|
|
shscap: data.shscap,
|
|
localadv: data.localadv,
|
|
localdiscov: data.localdiscov,
|
|
hmac: data.hmac,
|
|
wslis: data.wslis,
|
|
debuglis: data.debuglis,
|
|
enable_ebt: data.enable_ebt,
|
|
promisc: data.promisc,
|
|
nounixsock: data.nounixsock,
|
|
repair: data.repair,
|
|
};
|
|
|
|
match data.startup {
|
|
true => {
|
|
debug!("Enabling go-sbot.service");
|
|
if let Err(e) = sbot::system_sbot_cmd("enable") {
|
|
warn!("Failed to enable go-sbot.service: {}", e)
|
|
}
|
|
}
|
|
false => {
|
|
debug!("Disabling go-sbot.service");
|
|
if let Err(e) = sbot::system_sbot_cmd("disable") {
|
|
warn!("Failed to disable go-sbot.service: {}", e)
|
|
}
|
|
}
|
|
};
|
|
|
|
// write config to file
|
|
let (name, msg) = match SbotConfig::write(config) {
|
|
Ok(_) => {
|
|
// if `restart` query parameter is `true`, attempt sbot process (re)start
|
|
if restart {
|
|
// returns a tuple of (name, msg) based on the outcome (success or error)
|
|
sbot::restart_sbot_process()
|
|
} else {
|
|
("success".to_string(), "Updated configuration".to_string())
|
|
}
|
|
}
|
|
Err(err) => (
|
|
"error".to_string(),
|
|
format!("Failed to update configuration: {}", err),
|
|
),
|
|
};
|
|
|
|
let (flash_name, flash_msg) = (format!("flash_name={}", name), format!("flash_msg={}", msg));
|
|
|
|
Response::redirect_303("/settings/scuttlebutt/configure").add_flash(flash_name, flash_msg)
|
|
}
|