From 513056f7118da82c8011710b65c569080e1fc2ca Mon Sep 17 00:00:00 2001 From: Jeremy Lin Date: Fri, 26 Feb 2021 19:40:12 -0800 Subject: [PATCH] Check for data folder on startup Currently, when starting up for the first time (running standalone, outside of Docker), bitwarden_rs panics when the `openssl` tool isn't able to create `data/rsa_key.pem` due to the `data` dir not existing. Instead, print a more helpful error message telling the user to create the directory. --- src/api/admin.rs | 4 ++-- src/main.rs | 25 +++++++++++++++++++++++-- src/util.rs | 9 +++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/api/admin.rs b/src/api/admin.rs index dacc1b7c..39fbc691 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -19,7 +19,7 @@ use crate::{ db::{backup_database, models::*, DbConn, DbConnType}, error::{Error, MapResult}, mail, - util::{format_naive_datetime_local, get_display_size}, + util::{format_naive_datetime_local, get_display_size, is_running_in_docker}, CONFIG, }; @@ -486,7 +486,7 @@ fn diagnostics(_token: AdminToken, _conn: DbConn) -> ApiResult> { let web_vault_version: WebVaultVersion = serde_json::from_str(&vault_version_str)?; // Execute some environment checks - let running_within_docker = std::path::Path::new("/.dockerenv").exists() || std::path::Path::new("/run/.containerenv").exists(); + let running_within_docker = is_running_in_docker(); let has_http_access = has_http_access(); let uses_proxy = env::var_os("HTTP_PROXY").is_some() || env::var_os("http_proxy").is_some() diff --git a/src/main.rs b/src/main.rs index 6263cca0..d792dba5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,6 +38,7 @@ mod util; pub use config::CONFIG; pub use error::{Error, MapResult}; +pub use util::is_running_in_docker; fn main() { parse_args(); @@ -52,6 +53,7 @@ fn main() { _ => false, }; + check_data_folder(); check_rsa_keys(); check_web_vault(); @@ -215,9 +217,28 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch { } } +fn create_dir(path: &str, description: &str) { + // Try to create the specified dir, if it doesn't already exist. + let err_msg = format!("Error creating {} directory '{}'", description, path); + create_dir_all(path).expect(&err_msg); +} + fn create_icon_cache_folder() { - // Try to create the icon cache folder, and generate an error if it could not. - create_dir_all(&CONFIG.icon_cache_folder()).expect("Error creating icon cache directory"); + create_dir(&CONFIG.icon_cache_folder(), "icon cache"); +} + +fn check_data_folder() { + let data_folder = &CONFIG.data_folder(); + let path = Path::new(data_folder); + if !path.exists() { + error!("Data folder '{}' doesn't exist.", data_folder); + if is_running_in_docker() { + error!("Verify that your data volume is mounted at the correct location."); + } else { + error!("Create the data folder and try again."); + } + exit(1); + } } fn check_rsa_keys() { diff --git a/src/util.rs b/src/util.rs index e025237c..82343bcf 100644 --- a/src/util.rs +++ b/src/util.rs @@ -358,6 +358,15 @@ pub fn format_naive_datetime_local(dt: &NaiveDateTime, fmt: &str) -> String { format_datetime_local(&Local.from_utc_datetime(dt), fmt) } +// +// Deployment environment methods +// + +/// Returns true if the program is running in Docker or Podman. +pub fn is_running_in_docker() -> bool { + Path::new("/.dockerenv").exists() || Path::new("/run/.containerenv").exists() +} + // // Deserialization methods //