From 2f9d7060bd966007bb3ac6435463a1389073d9b3 Mon Sep 17 00:00:00 2001
From: Stefan Melmuk <stefan.melmuk@gmail.com>
Date: Tue, 22 Nov 2022 04:40:20 +0100
Subject: [PATCH] check if sqlite folder exists

instead of creating the parent folders to a sqlite database
vaultwarden should just exit if it does not.

this should fix issues like #2835 when a wrongly configured
`DATABASE_URL` falls back to using sqlite
---
 src/config.rs | 10 +++++++++-
 src/db/mod.rs | 21 +++++++--------------
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/config.rs b/src/config.rs
index 8427c37f..b8485af5 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -630,7 +630,15 @@ make_config! {
 
 fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
     // Validate connection URL is valid and DB feature is enabled
-    DbConnType::from_url(&cfg.database_url)?;
+    let url = &cfg.database_url;
+    if DbConnType::from_url(url)? == DbConnType::sqlite {
+        let path = std::path::Path::new(&url);
+        if let Some(parent) = path.parent() {
+            if !parent.exists() {
+                err!(format!("SQLite database directory `{}` does not exist", parent.display()));
+            }
+        }
+    }
 
     let limit = 256;
     if cfg.database_max_conns < 1 || cfg.database_max_conns > limit {
diff --git a/src/db/mod.rs b/src/db/mod.rs
index a84002cd..c2570d9d 100644
--- a/src/db/mod.rs
+++ b/src/db/mod.rs
@@ -424,22 +424,15 @@ mod sqlite_migrations {
     pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/sqlite");
 
     pub fn run_migrations() -> Result<(), super::Error> {
-        // Make sure the directory exists
-        let url = crate::CONFIG.database_url();
-        let path = std::path::Path::new(&url);
-
-        if let Some(parent) = path.parent() {
-            if std::fs::create_dir_all(parent).is_err() {
-                error!("Error creating database directory");
-                std::process::exit(1);
-            }
-        }
-
         use diesel::{Connection, RunQueryDsl};
-        // Make sure the database is up to date (create if it doesn't exist, or run the migrations)
-        let mut connection = diesel::sqlite::SqliteConnection::establish(&crate::CONFIG.database_url())?;
-        // Disable Foreign Key Checks during migration
+        let url = crate::CONFIG.database_url();
 
+        // Establish a connection to the sqlite database (this will create a new one, if it does
+        // not exist, and exit if there is an error).
+        let mut connection = diesel::sqlite::SqliteConnection::establish(&url)?;
+
+        // Run the migrations after successfully establishing a connection
+        // Disable Foreign Key Checks during migration
         // Scoped to a connection.
         diesel::sql_query("PRAGMA foreign_keys = OFF")
             .execute(&mut connection)