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:
Maxime Van Hees
2025-09-15 10:34:03 +02:00
parent bdf363016a
commit da325a9659
2 changed files with 24 additions and 77 deletions

View File

@@ -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;

View File

@@ -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(())
}