update git ignore and remove outdated code

This commit is contained in:
glyph 2022-03-24 09:19:39 +02:00
parent 07147f8a4f
commit d9019d6a4b
7 changed files with 1 additions and 807 deletions

View File

@ -1,8 +1,5 @@
*.bak
static/icons/optimized/*
api_docs.md
js_docs.md
hashmap_notes
notes
target
**/*.rs.bk
leftovers

View File

@ -1,333 +0,0 @@
use log::info;
use rocket::{
form::{Form, FromForm},
get,
http::{Cookie, CookieJar, Status},
post,
request::{self, FlashMessage, FromRequest, Request},
response::{Flash, Redirect},
};
use rocket_dyn_templates::{tera::Context, Template};
use peach_lib::{error::PeachError, password_utils};
use crate::error::PeachWebError;
use crate::utils;
use crate::utils::TemplateOrRedirect;
use crate::RocketConfig;
// HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES
pub const AUTH_COOKIE_KEY: &str = "peachweb_auth";
pub const ADMIN_USERNAME: &str = "admin";
/// Note: Currently we use an empty struct for the Authenticated request guard
/// because there is only one user to be authenticated, and no data needs to be stored here.
/// In a multi-user authentication scheme, we would store the user_id in this struct,
/// and retrieve the correct user via the user_id stored in the cookie.
pub struct Authenticated;
#[derive(Debug)]
pub enum LoginError {
UserNotLoggedIn,
}
/// Request guard which returns an empty Authenticated struct from the request
/// if and only if the user has a cookie which proves they are authenticated with peach-web.
///
/// Note that cookies.get_private uses encryption, which means that this private cookie
/// cannot be inspected, tampered with, or manufactured by clients.
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Authenticated {
type Error = LoginError;
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
// retrieve auth state from managed state (returns `Option<bool>`).
// this value is read from the Rocket.toml config file on start-up
let authentication_is_disabled: bool = *req
.rocket()
.state::<RocketConfig>()
.map(|config| (&config.disable_auth))
.unwrap_or(&false);
if authentication_is_disabled {
let auth = Authenticated {};
request::Outcome::Success(auth)
} else {
let authenticated = req
.cookies()
.get_private(AUTH_COOKIE_KEY)
.and_then(|cookie| cookie.value().parse().ok())
.map(|_value: String| Authenticated {});
match authenticated {
Some(auth) => request::Outcome::Success(auth),
None => request::Outcome::Failure((Status::Forbidden, LoginError::UserNotLoggedIn)),
}
}
}
}
// HELPERS AND ROUTES FOR /login
#[get("/login")]
pub fn login(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Login".to_string()));
// check to see if there is a flash message to display
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("login", &context.into_json())
}
#[derive(Debug, FromForm)]
pub struct LoginForm {
pub password: String,
}
/// Takes in a LoginForm and returns Ok(()) if the password is correct.
///
/// Note: there is currently only one user, therefore we don't need a username.
pub fn verify_login_form(login_form: LoginForm) -> Result<(), PeachError> {
password_utils::verify_password(&login_form.password)
}
#[post("/login", data = "<login_form>")]
pub fn login_post(login_form: Form<LoginForm>, cookies: &CookieJar<'_>) -> TemplateOrRedirect {
match verify_login_form(login_form.into_inner()) {
Ok(_) => {
// if successful login, add a cookie indicating the user is authenticated
// and redirect to home page
// NOTE: since we currently have just one user, the value of the cookie
// is just admin (this is arbitrary).
// If we had multiple users, we could put the user_id here.
cookies.add_private(Cookie::new(AUTH_COOKIE_KEY, ADMIN_USERNAME));
TemplateOrRedirect::Redirect(Redirect::to("/"))
}
Err(e) => {
let err_msg = format!("Invalid password: {}", e);
// if unsuccessful login, render /login page again
let mut context = Context::new();
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Login".to_string()));
context.insert("flash_name", &("error".to_string()));
context.insert("flash_msg", &(err_msg));
TemplateOrRedirect::Template(Template::render("login", &context.into_json()))
}
}
}
// HELPERS AND ROUTES FOR /logout
#[get("/logout")]
pub fn logout(cookies: &CookieJar<'_>) -> Flash<Redirect> {
// logout authenticated user
info!("Attempting deauthentication of user.");
cookies.remove_private(Cookie::named(AUTH_COOKIE_KEY));
Flash::success(Redirect::to("/login"), "Logged out")
}
// HELPERS AND ROUTES FOR /reset_password
#[derive(Debug, FromForm)]
pub struct ResetPasswordForm {
pub temporary_password: String,
pub new_password1: String,
pub new_password2: String,
}
/// Verify, validate and save the submitted password. This function is publicly exposed for users who have forgotten their password.
pub fn save_reset_password_form(password_form: ResetPasswordForm) -> Result<(), PeachWebError> {
info!(
"reset password!: {} {} {}",
password_form.temporary_password, password_form.new_password1, password_form.new_password2
);
password_utils::verify_temporary_password(&password_form.temporary_password)?;
// if the previous line did not throw an error, then the secret_link is correct
password_utils::validate_new_passwords(
&password_form.new_password1,
&password_form.new_password2,
)?;
// if the previous line did not throw an error, then the new password is valid
password_utils::set_new_password(&password_form.new_password1)?;
Ok(())
}
/// Password reset request handler. This route is used by a user who is not logged in
/// and is specifically for users who have forgotten their password.
#[get("/reset_password")]
pub fn reset_password(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Reset Password".to_string()));
// check to see if there is a flash message to display
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/admin/reset_password", &context.into_json())
}
/// Password reset form request handler. This route is used by a user who is not logged in
/// and is specifically for users who have forgotten their password.
#[post("/reset_password", data = "<reset_password_form>")]
pub fn reset_password_post(reset_password_form: Form<ResetPasswordForm>) -> Template {
let mut context = Context::new();
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Reset Password".to_string()));
let (flash_name, flash_msg) = match save_reset_password_form(reset_password_form.into_inner()) {
Ok(_) => (
"success".to_string(),
"New password has been saved. Return home to login".to_string(),
),
Err(err) => (
"error".to_string(),
format!("Failed to reset password: {}", err),
),
};
context.insert("flash_name", &Some(flash_name));
context.insert("flash_msg", &Some(flash_msg));
Template::render("settings/admin/reset_password", &context.into_json())
}
// HELPERS AND ROUTES FOR /send_password_reset
/// Page for users who have forgotten their password.
/// This route is used by a user who is not logged in
/// to initiate the sending of a new password reset.
#[get("/forgot_password")]
pub fn forgot_password_page(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Send Password Reset".to_string()));
// check to see if there is a flash message to display
if let Some(flash) = flash {
// add flash message contents to the context object
context.insert("flash_name", &Some(flash.kind().to_string()));
context.insert("flash_msg", &Some(flash.message().to_string()));
};
Template::render("settings/admin/forgot_password", &context.into_json())
}
/// Send password reset request handler. This route is used by a user who is not logged in
/// and is specifically for users who have forgotten their password. A successful request results
/// in a Scuttlebutt private message being sent to the account of the device admin.
#[post("/send_password_reset")]
pub fn send_password_reset_post() -> Template {
info!("++ send password reset post");
let mut context = Context::new();
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Send Password Reset".to_string()));
let (flash_name, flash_msg) = match password_utils::send_password_reset() {
Ok(_) => (
"success".to_string(),
"A password reset link has been sent to the admin of this device".to_string(),
),
Err(err) => (
"error".to_string(),
format!("Failed to send password reset link: {}", err),
),
};
context.insert("flash_name", &Some(flash_name));
context.insert("flash_msg", &Some(flash_msg));
Template::render("settings/admin/forgot_password", &context.into_json())
}
// HELPERS AND ROUTES FOR /settings/change_password
#[derive(Debug, FromForm)]
pub struct PasswordForm {
pub current_password: String,
pub new_password1: String,
pub new_password2: String,
}
/// Password save form request handler. This function is for use by a user who is already logged in to change their password.
pub fn save_password_form(password_form: PasswordForm) -> Result<(), PeachWebError> {
info!(
"change password!: {} {} {}",
password_form.current_password, password_form.new_password1, password_form.new_password2
);
password_utils::verify_password(&password_form.current_password)?;
// if the previous line did not throw an error, then the old password is correct
password_utils::validate_new_passwords(
&password_form.new_password1,
&password_form.new_password2,
)?;
// if the previous line did not throw an error, then the new password is valid
password_utils::set_new_password(&password_form.new_password1)?;
Ok(())
}
/// Change password request handler. This is used by a user who is already logged in.
#[get("/change_password")]
pub fn change_password(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings/admin".to_string()));
context.insert("title", &Some("Change 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.insert("flash_name", &Some(flash.kind().to_string()));
context.insert("flash_msg", &Some(flash.message().to_string()));
};
Template::render("settings/admin/change_password", &context.into_json())
}
/// Change password form request handler. This route is used by a user who is already logged in.
#[post("/change_password", data = "<password_form>")]
pub fn change_password_post(password_form: Form<PasswordForm>, _auth: Authenticated) -> Template {
let mut context = Context::new();
context.insert("back", &Some("/settings/admin".to_string()));
context.insert("title", &Some("Change Password".to_string()));
let (flash_name, flash_msg) = match save_password_form(password_form.into_inner()) {
Ok(_) => (
"success".to_string(),
"New password has been saved".to_string(),
),
Err(err) => (
"error".to_string(),
format!("Failed to save new password: {}", err),
),
};
context.insert("flash_name", &Some(flash_name));
context.insert("flash_msg", &Some(flash_msg));
Template::render("settings/admin/change_password", &context.into_json())
}

View File

@ -1,60 +0,0 @@
use log::debug;
use rocket::catch;
use rocket::response::Redirect;
use rocket_dyn_templates::Template;
use serde::Serialize;
// HELPERS AND ROUTES FOR 404 ERROR
#[derive(Debug, Serialize)]
pub struct ErrorContext {
pub back: Option<String>,
pub flash_name: Option<String>,
pub flash_msg: Option<String>,
pub title: Option<String>,
}
impl ErrorContext {
pub fn build() -> ErrorContext {
ErrorContext {
back: None,
flash_name: None,
flash_msg: None,
title: None,
}
}
}
#[catch(404)]
pub fn not_found() -> Template {
debug!("404 Page Not Found");
let mut context = ErrorContext::build();
context.back = Some("/".to_string());
context.title = Some("404: Page Not Found".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some("No resource found for given URL".to_string());
Template::render("catchers/not_found", context)
}
// HELPERS AND ROUTES FOR 500 ERROR
#[catch(500)]
pub fn internal_error() -> Template {
debug!("500 Internal Server Error");
let mut context = ErrorContext::build();
context.back = Some("/".to_string());
context.title = Some("500: Internal Server Error".to_string());
context.flash_name = Some("error".to_string());
context.flash_msg = Some("Internal server error".to_string());
Template::render("catchers/internal_error", context)
}
// HELPERS AND ROUTES FOR 403 FORBIDDEN
#[catch(403)]
pub fn forbidden() -> Redirect {
debug!("403 Forbidden");
Redirect::to("/login")
}

View File

@ -1,51 +0,0 @@
use peach_lib::sbot::SbotStatus;
use rocket::{get, request::FlashMessage, State};
use rocket_dyn_templates::{tera::Context, Template};
use crate::routes::authentication::Authenticated;
use crate::utils;
use crate::RocketConfig;
// HELPERS AND ROUTES FOR / (HOME PAGE)
#[get("/")]
pub fn home(_auth: Authenticated, config: &State<RocketConfig>) -> 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("flash_name", &None::<()>);
context.insert("flash_msg", &None::<()>);
context.insert("title", &None::<()>);
// pass in mode from managed state so we can define appropriate urls in template
context.insert("standalone_mode", &config.standalone_mode);
Template::render("home", &context.into_json())
}
// HELPERS AND ROUTES FOR /guide
#[get("/guide")]
pub fn guide(flash: Option<FlashMessage>) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/".to_string()));
context.insert("title", &Some("Guide".to_string()));
// check to see if there is a flash message to display
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("guide", &context.into_json())
}

View File

@ -1,124 +0,0 @@
/*
use rocket::{
form::{Form, FromForm},
get, post,
request::FlashMessage,
response::{Flash, Redirect},
uri,
};
use rocket_dyn_templates::{tera::Context, Template};
use peach_lib::config_manager;
use crate::error::PeachWebError;
use crate::routes::authentication::Authenticated;
use crate::utils;
// HELPERS AND ROUTES FOR /settings/admin
/// Administrator settings menu.
#[get("/")]
pub fn admin_menu(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings".to_string()));
context.insert("title", &Some("Administrator Settings".to_string()));
// check to see if there is a flash message to display
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/admin/menu", &context.into_json())
}
// HELPERS AND ROUTES FOR /settings/admin/configure
/// View and delete currently configured admin.
#[get("/configure")]
pub fn configure_admin(flash: Option<FlashMessage>, _auth: Authenticated) -> Template {
// retrieve current ui theme
let theme = utils::get_theme();
let mut context = Context::new();
context.insert("theme", &theme);
context.insert("back", &Some("/settings/admin".to_string()));
context.insert("title", &Some("Configure Admin".to_string()));
// check to see if there is a flash message to display
if let Some(flash) = flash {
context.insert("flash_name", &Some(flash.kind().to_string()));
context.insert("flash_msg", &Some(flash.message().to_string()));
};
// load the peach configuration vector
match config_manager::load_peach_config() {
Ok(config) => {
// retrieve the vector of ssb admin ids
let ssb_admin_ids = config.ssb_admin_ids;
context.insert("ssb_admin_ids", &ssb_admin_ids);
}
// if load fails, overwrite the flash_name and flash_msg
Err(e) => {
context.insert("flash_name", &Some("error".to_string()));
context.insert(
"flash_msg",
&Some(format!("Failed to load Peach config: {}", e)),
);
}
}
Template::render("settings/admin/configure_admin", &context.into_json())
}
// HELPERS AND ROUTES FOR /settings/admin/add
#[derive(Debug, FromForm)]
pub struct AddAdminForm {
pub ssb_id: String,
}
pub fn save_add_admin_form(admin_form: AddAdminForm) -> Result<(), PeachWebError> {
let _result = config_manager::add_ssb_admin_id(&admin_form.ssb_id)?;
// if the previous line didn't throw an error then it was a success
Ok(())
}
#[post("/add", data = "<add_admin_form>")]
pub fn add_admin_post(add_admin_form: Form<AddAdminForm>, _auth: Authenticated) -> Flash<Redirect> {
let result = save_add_admin_form(add_admin_form.into_inner());
let url = uri!("/settings/admin/configure");
match result {
Ok(_) => Flash::success(Redirect::to(url), "Added SSB administrator"),
Err(e) => Flash::error(Redirect::to(url), format!("Failed to add new admin: {}", e)),
}
}
// HELPERS AND ROUTES FOR /settings/admin/delete
#[derive(Debug, FromForm)]
pub struct DeleteAdminForm {
pub ssb_id: String,
}
#[post("/delete", data = "<delete_admin_form>")]
pub fn delete_admin_post(
delete_admin_form: Form<DeleteAdminForm>,
_auth: Authenticated,
) -> Flash<Redirect> {
let result = config_manager::delete_ssb_admin_id(&delete_admin_form.ssb_id);
let url = uri!("/settings/admin", configure_admin);
match result {
Ok(_) => Flash::success(Redirect::to(url), "Removed SSB administrator"),
Err(e) => Flash::error(
Redirect::to(url),
format!("Failed to remove admin id: {}", e),
),
}
}
*/

View File

@ -1,37 +0,0 @@
use rocket::{get, State};
use rocket_dyn_templates::Template;
use crate::routes::authentication::Authenticated;
use crate::{context::scuttlebutt::StatusContext, RocketConfig};
// HELPERS AND ROUTES FOR /status/scuttlebutt
#[get("/scuttlebutt")]
pub async fn scuttlebutt_status(_auth: Authenticated, config: &State<RocketConfig>) -> Template {
let context = StatusContext::build().await;
let back = if config.standalone_mode {
// return to home page
Some("/".to_string())
} else {
// return to status menu
Some("/status".to_string())
};
match context {
Ok(mut context) => {
// define back arrow url based on mode
context.back = back;
Template::render("status/scuttlebutt", &context)
}
Err(_) => {
let mut context = StatusContext::default();
// define back arrow url based on mode
context.back = back;
Template::render("status/scuttlebutt", &context)
}
}
}

View File

@ -1,198 +0,0 @@
// Monitor data transmission totals, set thresholds and check alert flags
use std::convert::TryInto;
use nest::{Error, Store, Value};
use rocket::form::FromForm;
use rocket::serde::{Deserialize, Serialize};
use serde_json::json;
/// Network traffic data total
#[derive(Debug, Serialize)]
pub struct Data {
pub total: u64, // total traffic in bytes
}
impl Data {
/// Retrieve network traffic data values from the store
fn get(store: &Store) -> Data {
// retrieve previous network traffic statistics
let data_stored = match store.get(&["net", "traffic", "total"]) {
Ok(total) => total,
// return 0 if no value exists
Err(_) => Value::Uint(u64::MIN),
};
let mut data = Vec::new();
// retrieve u64 from Value type
if let Value::Uint(total) = data_stored {
data.push(total);
};
Data { total: data[0] }
}
}
/// Network traffic notification thresholds and flags (user-defined)
#[derive(Debug, Deserialize, Serialize, FromForm)]
pub struct Threshold {
warn: u64, // traffic warning threshold
cut: u64, // traffic cutoff threshold
warn_flag: bool, // traffic warning notification flag
cut_flag: bool, // traffic cutoff notification flag
}
impl Threshold {
/// Retrieve notification thresholds and flags from the store
fn get(store: &Store) -> Threshold {
let mut threshold = Vec::new();
let warn_val = store
.get(&["net", "notify", "warn"])
.unwrap_or(Value::Uint(0));
if let Value::Uint(val) = warn_val {
threshold.push(val);
};
let cut_val = store
.get(&["net", "notify", "cut"])
.unwrap_or(Value::Uint(0));
if let Value::Uint(val) = cut_val {
threshold.push(val);
};
let mut flag = Vec::new();
let warn_flag = store
.get(&["net", "notify", "warn_flag"])
.unwrap_or(Value::Bool(false));
if let Value::Bool(state) = warn_flag {
flag.push(state);
}
let cut_flag = store
.get(&["net", "notify", "cut_flag"])
.unwrap_or(Value::Bool(false));
if let Value::Bool(state) = cut_flag {
flag.push(state);
}
Threshold {
warn: threshold[0],
cut: threshold[1],
warn_flag: flag[0],
cut_flag: flag[1],
}
}
/// Store notification flags from user data
fn set(self, store: &Store) {
store
.set(&["net", "notify", "warn"], &Value::Uint(self.warn))
.unwrap();
store
.set(&["net", "notify", "cut"], &Value::Uint(self.cut))
.unwrap();
store
.set(
&["net", "notify", "warn_flag"],
&Value::Bool(self.warn_flag),
)
.unwrap();
store
.set(&["net", "notify", "cut_flag"], &Value::Bool(self.cut_flag))
.unwrap();
}
}
/// Warning and cutoff network traffic alert flags (programatically-defined)
#[derive(Debug, Serialize)]
pub struct Alert {
warn: bool,
cut: bool,
}
impl Alert {
/// Retrieve latest alert flags from the store
fn get(store: &Store) -> Alert {
let mut alert = Vec::new();
let warn_flag = store
.get(&["net", "alert", "warn"])
.unwrap_or(Value::Bool(false));
if let Value::Bool(flag) = warn_flag {
alert.push(flag);
}
let cut_flag = store
.get(&["net", "alert", "cut"])
.unwrap_or(Value::Bool(false));
if let Value::Bool(flag) = cut_flag {
alert.push(flag);
}
Alert {
warn: alert[0],
cut: alert[1],
}
}
}
fn create_store() -> std::result::Result<Store, Error> {
// define the path
let path = xdg::BaseDirectories::new()
.unwrap()
.create_data_directory("peachcloud")
.unwrap();
// define the schema
let schema = json!({
"net": {
"traffic": "json",
"alert": "json",
"notify": "json",
}
})
.try_into()?;
// create the data store
let store = Store::new(path, schema);
Ok(store)
}
pub fn get_alerts() -> std::result::Result<Alert, Error> {
let store = create_store()?;
let alerts = Alert::get(&store);
Ok(alerts)
}
pub fn get_data() -> std::result::Result<Data, Error> {
let store = create_store()?;
let data = Data::get(&store);
Ok(data)
}
pub fn get_thresholds() -> std::result::Result<Threshold, Error> {
let store = create_store()?;
let thresholds = Threshold::get(&store);
Ok(thresholds)
}
// set stored traffic total to 0
pub fn reset_data() -> std::result::Result<(), Error> {
let store = create_store()?;
store.set(&["net", "traffic", "total"], &Value::Uint(0))?;
Ok(())
}
pub fn update_store(threshold: Threshold) -> std::result::Result<(), Error> {
let store = create_store()?;
Threshold::set(threshold, &store);
Ok(())
}