diff --git a/peach-web/Cargo.toml b/peach-web/Cargo.toml index ddd4b0d..90e0295 100644 --- a/peach-web/Cargo.toml +++ b/peach-web/Cargo.toml @@ -36,7 +36,6 @@ maintenance = { status = "actively-developed" } [dependencies] env_logger = "0.8" -lazy_static = "1.4.0" log = "0.4" nest = "1.0.0" peach-lib = { path = "../peach-lib" } diff --git a/peach-web/README.md b/peach-web/README.md index ec03092..b686101 100644 --- a/peach-web/README.md +++ b/peach-web/README.md @@ -25,7 +25,7 @@ Move into the repo and compile: Run the tests: -`ROCKET_DISABLE_AUTH=true PEACH_STANDALONE_MODE=false cargo test` +`ROCKET_DISABLE_AUTH=true ROCKET_STANDALONE_MODE=false cargo test` Move back to the `peach-workspace` directory: @@ -37,21 +37,23 @@ Run the binary: ### Environment -**Deployment Mode** +**Deployment Profile** -The web application deployment mode is configured with the `ROCKET_ENV` environment variable: +The web application deployment profile can be configured with the `ROCKET_ENV` environment variable: `export ROCKET_ENV=stage` -Other deployment modes are `dev` and `prod`. Read the [Rocket Environment Configurations docs](https://rocket.rs/v0.5-rc/guide/configuration/#environment-variables) for further information. +Default configuration parameters are defined in `Rocket.toml`. This file defines a set of default parameters, some of which are overwritten when running in `debug` mode (ie. `cargo run` or `cargo build`) or `release` mode (ie. `cargo run --release` or `cargo build --release`). + +Read the [Rocket Environment Configurations docs](https://rocket.rs/v0.5-rc/guide/configuration/#environment-variables) for further information. **Configuration Mode** -The web application can be run with a minimal set of routes and functionality (PeachPub - a simple sbot manager) or with the full-suite of capabilities, including network management and access to device statistics (PeachCloud). The mode is configured with the `PEACH_STANDALONE_MODE` environment variable: `true` or `false`. If the variable is unset or the value is incorrectly set, the application defaults to standalone mode. +The web application can be run with a minimal set of routes and functionality (PeachPub - a simple sbot manager) or with the full-suite of capabilities, including network management and access to device statistics (PeachCloud). The mode is enabled by default (as defined in `Rocket.toml`) but can be overwritten using the `ROCKET_STANDALONE_MODE` environment variable: `true` or `false`. If the variable is unset or the value is incorrectly set, the application defaults to standalone mode. **Authentication** -Authentication is disabled in `development` mode and enabled by default when running the application in `production` mode. It can be disabled by setting the `ROCKET_DISABLE_AUTH` environment variable to `true`: +Authentication is disabled in `debug` mode and enabled by default when running the application in `release` mode. It can be disabled by setting the `ROCKET_DISABLE_AUTH` environment variable to `true`: `export ROCKET_DISABLE_AUTH=true` diff --git a/peach-web/Rocket.toml b/peach-web/Rocket.toml index 1af1b71..c1f285e 100644 --- a/peach-web/Rocket.toml +++ b/peach-web/Rocket.toml @@ -1,10 +1,11 @@ [default] secret_key = "VYVUDivXvu8g6llxeJd9F92pMfocml5xl/Jjv5Sk4yw=" +disable_auth = false +standalone_mode = true -[development] +[debug] template_dir = "templates/" disable_auth = true -[production] +[release] template_dir = "templates/" -disable_auth = false diff --git a/peach-web/src/main.rs b/peach-web/src/main.rs index ded1686..238e561 100644 --- a/peach-web/src/main.rs +++ b/peach-web/src/main.rs @@ -32,21 +32,23 @@ pub mod routes; mod tests; pub mod utils; -use std::{env, process}; +use std::process; -use lazy_static::lazy_static; -use log::{error, info}; -use rocket::{Build, Rocket}; +use log::{debug, error, info}; +use rocket::{fairing::AdHoc, serde::Deserialize, Build, Rocket}; pub type BoxError = Box; -lazy_static! { - // determine run-mode from env var; default to standalone mode (aka peachpub) - static ref STANDALONE_MODE: bool = match env::var("PEACH_STANDALONE_MODE") { - // parse the value to a boolean; default to true for any error - Ok(val) => val.parse().unwrap_or(true), - Err(_) => true - }; +/// Application configuration parameters. +/// These values are extracted from Rocket's default configuration provider: +/// `Config::figment()`. As such, the values are drawn from `Rocket.toml` or +/// the TOML file path in the `ROCKET_CONFIG` environment variable. The TOML +/// file parameters are automatically overruled by any `ROCKET_` variables +/// which might be set. +#[derive(Debug, Deserialize)] +pub struct RocketConfig { + disable_auth: bool, + standalone_mode: bool, } static WLAN_IFACE: &str = "wlan0"; @@ -54,11 +56,27 @@ static AP_IFACE: &str = "ap0"; pub fn init_rocket() -> Rocket { info!("Initializing Rocket"); - if *STANDALONE_MODE { - router::mount_peachpub_routes() + // build a basic rocket instance + let rocket = rocket::build(); + + // return the default provider figment used by `rocket::build()` + let figment = rocket.figment(); + + // deserialize configuration parameters into our `RocketConfig` struct (defined above) + // since we're in the intialisation phase, panic if the extraction fails + let config: RocketConfig = figment.extract().expect("configuration extraction failed"); + + debug!("{:?}", config); + + info!("Mounting Rocket routes"); + let mounted_rocket = if config.standalone_mode { + router::mount_peachpub_routes(rocket) } else { - router::mount_peachcloud_routes() - } + router::mount_peachcloud_routes(rocket) + }; + + info!("Attaching application configuration to managed state"); + mounted_rocket.attach(AdHoc::config::()) } /// Launch the peach-web rocket server. diff --git a/peach-web/src/router.rs b/peach-web/src/router.rs index 341d9aa..99bcb7b 100644 --- a/peach-web/src/router.rs +++ b/peach-web/src/router.rs @@ -14,8 +14,8 @@ use crate::routes::{ /// catchers. This gives us everything we need to run PeachPub and excludes /// settings and status routes related to networking and the device (memory, /// hard disk, CPU etc.). -pub fn mount_peachpub_routes() -> Rocket { - rocket::build() +pub fn mount_peachpub_routes(rocket: Rocket) -> Rocket { + rocket .mount( "/", routes![ @@ -66,8 +66,8 @@ pub fn mount_peachpub_routes() -> Rocket { /// Create a Rocket instance with PeachPub routes, fileserver and catchers by /// calling `mount_peachpub_routes()` and then mount all additional routes /// required to run a complete PeachCloud build. -pub fn mount_peachcloud_routes() -> Rocket { - mount_peachpub_routes() +pub fn mount_peachcloud_routes(rocket: Rocket) -> Rocket { + mount_peachpub_routes(rocket) .mount( "/settings/network", routes![ diff --git a/peach-web/src/routes/authentication.rs b/peach-web/src/routes/authentication.rs index 97ea167..e3e51a3 100644 --- a/peach-web/src/routes/authentication.rs +++ b/peach-web/src/routes/authentication.rs @@ -7,7 +7,6 @@ use rocket::{ request::{self, FlashMessage, FromRequest, Request}, response::{Flash, Redirect}, serde::Deserialize, - Config, }; use rocket_dyn_templates::{tera::Context, Template}; @@ -15,6 +14,8 @@ use peach_lib::{error::PeachError, password_utils}; use crate::error::PeachWebError; use crate::utils::TemplateOrRedirect; +//use crate::DisableAuth; +use crate::RocketConfig; // HELPERS AND STRUCTS FOR AUTHENTICATION WITH COOKIES @@ -42,14 +43,14 @@ impl<'r> FromRequest<'r> for Authenticated { type Error = LoginError; async fn from_request(req: &'r Request<'_>) -> request::Outcome { - // check for `disable_auth` config value; set to `false` if unset - // can be set via the `ROCKET_DISABLE_AUTH` environment variable - // - env var, if set, takes precedence over value defined in `Rocket.toml` - let authentication_is_disabled: bool = match Config::figment().find_value("disable_auth") { - // deserialize the boolean value; set to `false` if an error is encountered - Ok(value) => value.deserialize().unwrap_or(false), - Err(_) => false, - }; + // retrieve auth state from managed state (returns `Option`). + // this value is read from the Rocket.toml config file on start-up + let authentication_is_disabled: bool = *req + .rocket() + .state::() + .map(|config| (&config.disable_auth)) + .unwrap_or(&false); + if authentication_is_disabled { let auth = Authenticated {}; request::Outcome::Success(auth) diff --git a/peach-web/src/routes/index.rs b/peach-web/src/routes/index.rs index 54867b7..a703ed1 100644 --- a/peach-web/src/routes/index.rs +++ b/peach-web/src/routes/index.rs @@ -1,19 +1,20 @@ -use rocket::{get, request::FlashMessage}; +use rocket::{get, request::FlashMessage, State}; use rocket_dyn_templates::{tera::Context, Template}; use crate::routes::authentication::Authenticated; -use crate::STANDALONE_MODE; +use crate::RocketConfig; // HELPERS AND ROUTES FOR / (HOME PAGE) #[get("/")] -pub fn home(_auth: Authenticated) -> Template { +pub fn home(_auth: Authenticated, config: &State) -> Template { let mut context = Context::new(); context.insert("flash_name", &None::<()>); context.insert("flash_msg", &None::<()>); context.insert("title", &None::<()>); - // pass in mode so we can define appropriate urls in template - context.insert("standalone_mode", &*STANDALONE_MODE); + + // 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()) } diff --git a/peach-web/src/routes/status/scuttlebutt.rs b/peach-web/src/routes/status/scuttlebutt.rs index c1f532a..5ed3df1 100644 --- a/peach-web/src/routes/status/scuttlebutt.rs +++ b/peach-web/src/routes/status/scuttlebutt.rs @@ -1,4 +1,4 @@ -use rocket::{get, request::FlashMessage}; +use rocket::get; use rocket_dyn_templates::{tera::Context, Template}; use crate::routes::authentication::Authenticated;