Эх сурвалжийг харах

fix(database): add parent directory validation before database creation (#1161)

- Add work directory creation check in cdk-cli main
- Add parent directory existence validation in cdk-redb wallet database
- Add parent directory check in cdk-sqlite connection manager
- Add IO error variant to cdk-redb error types for better error handling
tsk 4 долоо хоног өмнө
parent
commit
6fe65553a3

+ 5 - 0
crates/cdk-cli/src/main.rs

@@ -131,6 +131,11 @@ async fn main() -> Result<()> {
         }
     };
 
+    // Create work directory if it doesn't exist
+    if !work_dir.exists() {
+        fs::create_dir_all(&work_dir)?;
+    }
+
     let localstore: Arc<dyn WalletDatabase<Err = cdk_database::Error> + Send + Sync> =
         match args.engine.as_str() {
             "sqlite" => {

+ 3 - 0
crates/cdk-redb/src/error.rs

@@ -43,6 +43,9 @@ pub enum Error {
     /// CDK Error
     #[error(transparent)]
     CDK(#[from] cdk_common::error::Error),
+    /// IO Error
+    #[error(transparent)]
+    Io(#[from] std::io::Error),
     /// NUT00 Error
     #[error(transparent)]
     CDKNUT00(#[from] cdk_common::nuts::nut00::Error),

+ 20 - 0
crates/cdk-redb/src/wallet/mod.rs

@@ -58,6 +58,16 @@ impl WalletRedbDatabase {
     /// Create new [`WalletRedbDatabase`]
     pub fn new(path: &Path) -> Result<Self, Error> {
         {
+            // Check if parent directory exists before attempting to create database
+            if let Some(parent) = path.parent() {
+                if !parent.exists() {
+                    return Err(Error::Io(std::io::Error::new(
+                        std::io::ErrorKind::NotFound,
+                        format!("Parent directory does not exist: {:?}", parent),
+                    )));
+                }
+            }
+
             let db = Arc::new(Database::create(path)?);
 
             let db_version: Option<String>;
@@ -156,6 +166,16 @@ impl WalletRedbDatabase {
             drop(db);
         }
 
+        // Check parent directory again for final database creation
+        if let Some(parent) = path.parent() {
+            if !parent.exists() {
+                return Err(Error::Io(std::io::Error::new(
+                    std::io::ErrorKind::NotFound,
+                    format!("Parent directory does not exist: {:?}", parent),
+                )));
+            }
+        }
+
         let mut db = Database::create(path)?;
 
         db.upgrade()?;

+ 9 - 0
crates/cdk-sqlite/src/common.rs

@@ -47,6 +47,15 @@ impl DatabasePool for SqliteConnectionManager {
         _timeout: Duration,
     ) -> Result<Self::Connection, pool::Error<Self::Error>> {
         let conn = if let Some(path) = config.path.as_ref() {
+            // Check if parent directory exists before attempting to open database
+            let path_buf = PathBuf::from(path);
+            if let Some(parent) = path_buf.parent() {
+                if !parent.exists() {
+                    return Err(pool::Error::Resource(rusqlite::Error::InvalidPath(
+                        path_buf.clone(),
+                    )));
+                }
+            }
             Connection::open(path)?
         } else {
             Connection::open_in_memory()?