fix bug where meta files where not auto-created upon starting + fix bug where meta json files were actually binary + improved access control to database instances
This commit is contained in:
		| @@ -76,9 +76,12 @@ async fn main() { | ||||
|     // new server | ||||
|     let mut server = server::Server::new(option).await; | ||||
|  | ||||
|     // Initialize the default database storage | ||||
|     // Initialize the default database storage (creates 0.db) | ||||
|     let _ = server.current_storage(); | ||||
|  | ||||
|     // Ensure default meta for DB 0 exists (public by default if missing) | ||||
|     let _ = herodb::rpc::RpcServerImpl::load_meta_static(&server.option.dir, 0).await; | ||||
|  | ||||
|     // Add a small delay to ensure the port is ready | ||||
|     tokio::time::sleep(std::time::Duration::from_millis(100)).await; | ||||
|  | ||||
|   | ||||
							
								
								
									
										96
									
								
								src/rpc.rs
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								src/rpc.rs
									
									
									
									
									
								
							| @@ -239,29 +239,25 @@ impl RpcServerImpl { | ||||
|     pub async fn load_meta_static(base_dir: &str, db_id: u64) -> Result<DatabaseMeta, jsonrpsee::types::ErrorObjectOwned> { | ||||
|         let meta_path = std::path::PathBuf::from(base_dir).join(format!("{}_meta.json", db_id)); | ||||
|  | ||||
|         // If meta file doesn't exist, return default | ||||
|         // If meta file doesn't exist, create and persist default | ||||
|         if !meta_path.exists() { | ||||
|             return Ok(DatabaseMeta { | ||||
|             let default_meta = DatabaseMeta { | ||||
|                 public: true, | ||||
|                 keys: HashMap::new(), | ||||
|             }); | ||||
|             }; | ||||
|             // Persist default metadata to disk | ||||
|             Self::save_meta_static(base_dir, db_id, &default_meta).await?; | ||||
|             return Ok(default_meta); | ||||
|         } | ||||
|  | ||||
|         // Read file | ||||
|         let content = std::fs::read(&meta_path) | ||||
|         // Read file as UTF-8 JSON | ||||
|         let json_str = std::fs::read_to_string(&meta_path) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
|                 format!("Failed to read meta file: {}", e), | ||||
|                 None::<()> | ||||
|             ))?; | ||||
|  | ||||
|         let json_str = String::from_utf8(content) | ||||
|             .map_err(|_| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
|                 "Invalid UTF-8 in meta file", | ||||
|                 None::<()> | ||||
|             ))?; | ||||
|  | ||||
|         serde_json::from_str(&json_str) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
| @@ -274,7 +270,7 @@ impl RpcServerImpl { | ||||
|     async fn load_meta(&self, db_id: u64) -> Result<DatabaseMeta, jsonrpsee::types::ErrorObjectOwned> { | ||||
|         let meta_path = std::path::PathBuf::from(&self.base_dir).join(format!("{}_meta.json", db_id)); | ||||
|  | ||||
|         // If meta file doesn't exist, create default | ||||
|         // If meta file doesn't exist, create and persist default | ||||
|         if !meta_path.exists() { | ||||
|             let default_meta = DatabaseMeta { | ||||
|                 public: true, | ||||
| @@ -284,46 +280,14 @@ impl RpcServerImpl { | ||||
|             return Ok(default_meta); | ||||
|         } | ||||
|  | ||||
|         // Read and potentially decrypt | ||||
|         let content = std::fs::read(&meta_path) | ||||
|         // Read file as UTF-8 JSON (meta files are always plain JSON) | ||||
|         let json_str = std::fs::read_to_string(&meta_path) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
|                 format!("Failed to read meta file: {}", e), | ||||
|                 None::<()> | ||||
|             ))?; | ||||
|  | ||||
|         let json_str = if db_id >= 10 { | ||||
|             // Encrypted database, decrypt meta | ||||
|             if let Some(key) = self.encryption_keys.read().await.get(&db_id).and_then(|k| k.as_ref()) { | ||||
|                 use crate::crypto::CryptoFactory; | ||||
|                 let crypto = CryptoFactory::new(key.as_bytes()); | ||||
|                 String::from_utf8(crypto.decrypt(&content) | ||||
|                     .map_err(|_| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                         -32000, | ||||
|                         "Failed to decrypt meta file", | ||||
|                         None::<()> | ||||
|                     ))?) | ||||
|                     .map_err(|_| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                         -32000, | ||||
|                         "Invalid UTF-8 in decrypted meta", | ||||
|                         None::<()> | ||||
|                     ))? | ||||
|             } else { | ||||
|                 return Err(jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                     -32000, | ||||
|                     "Encryption key not found for encrypted database", | ||||
|                     None::<()> | ||||
|                 )); | ||||
|             } | ||||
|         } else { | ||||
|             String::from_utf8(content) | ||||
|                 .map_err(|_| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                     -32000, | ||||
|                     "Invalid UTF-8 in meta file", | ||||
|                     None::<()> | ||||
|                 ))? | ||||
|         }; | ||||
|  | ||||
|         serde_json::from_str(&json_str) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
| @@ -336,7 +300,7 @@ impl RpcServerImpl { | ||||
|     pub async fn save_meta_static(base_dir: &str, db_id: u64, meta: &DatabaseMeta) -> Result<(), jsonrpsee::types::ErrorObjectOwned> { | ||||
|         let meta_path = std::path::PathBuf::from(base_dir).join(format!("{}_meta.json", db_id)); | ||||
|  | ||||
|         let json_str = serde_json::to_string(meta) | ||||
|         let json_str = serde_json::to_string_pretty(meta) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
|                 format!("Failed to serialize meta: {}", e), | ||||
| @@ -357,40 +321,20 @@ impl RpcServerImpl { | ||||
|     async fn save_meta(&self, db_id: u64, meta: &DatabaseMeta) -> Result<(), jsonrpsee::types::ErrorObjectOwned> { | ||||
|         let meta_path = std::path::PathBuf::from(&self.base_dir).join(format!("{}_meta.json", db_id)); | ||||
|  | ||||
|         let json_str = serde_json::to_string(meta) | ||||
|         let json_str = serde_json::to_string_pretty(meta) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
|                 format!("Failed to serialize meta: {}", e), | ||||
|                 None::<()> | ||||
|             ))?; | ||||
|  | ||||
|         if db_id >= 10 { | ||||
|             // Encrypted database, encrypt meta | ||||
|             if let Some(key) = self.encryption_keys.read().await.get(&db_id).and_then(|k| k.as_ref()) { | ||||
|                 use crate::crypto::CryptoFactory; | ||||
|                 let crypto = CryptoFactory::new(key.as_bytes()); | ||||
|                 let encrypted = crypto.encrypt(json_str.as_bytes()); | ||||
|                 std::fs::write(&meta_path, encrypted) | ||||
|                     .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                         -32000, | ||||
|                         format!("Failed to write encrypted meta file: {}", e), | ||||
|                         None::<()> | ||||
|                     ))?; | ||||
|             } else { | ||||
|                 return Err(jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                     -32000, | ||||
|                     "Encryption key not found for encrypted database", | ||||
|                     None::<()> | ||||
|                 )); | ||||
|             } | ||||
|         } else { | ||||
|             std::fs::write(&meta_path, json_str) | ||||
|                 .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                     -32000, | ||||
|                     format!("Failed to write meta file: {}", e), | ||||
|                     None::<()> | ||||
|                 ))?; | ||||
|         } | ||||
|         // Meta files are always stored as plain JSON (even when data DB is encrypted) | ||||
|         std::fs::write(&meta_path, json_str) | ||||
|             .map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned( | ||||
|                 -32000, | ||||
|                 format!("Failed to write meta file: {}", e), | ||||
|                 None::<()> | ||||
|             ))?; | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user