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
|
// new server
|
||||||
let mut server = server::Server::new(option).await;
|
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();
|
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
|
// Add a small delay to ensure the port is ready
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
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> {
|
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));
|
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() {
|
if !meta_path.exists() {
|
||||||
return Ok(DatabaseMeta {
|
let default_meta = DatabaseMeta {
|
||||||
public: true,
|
public: true,
|
||||||
keys: HashMap::new(),
|
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
|
// Read file as UTF-8 JSON
|
||||||
let content = std::fs::read(&meta_path)
|
let json_str = std::fs::read_to_string(&meta_path)
|
||||||
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
-32000,
|
-32000,
|
||||||
format!("Failed to read meta file: {}", e),
|
format!("Failed to read meta file: {}", e),
|
||||||
None::<()>
|
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)
|
serde_json::from_str(&json_str)
|
||||||
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
-32000,
|
-32000,
|
||||||
@@ -274,7 +270,7 @@ impl RpcServerImpl {
|
|||||||
async fn load_meta(&self, db_id: u64) -> Result<DatabaseMeta, jsonrpsee::types::ErrorObjectOwned> {
|
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));
|
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() {
|
if !meta_path.exists() {
|
||||||
let default_meta = DatabaseMeta {
|
let default_meta = DatabaseMeta {
|
||||||
public: true,
|
public: true,
|
||||||
@@ -284,46 +280,14 @@ impl RpcServerImpl {
|
|||||||
return Ok(default_meta);
|
return Ok(default_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and potentially decrypt
|
// Read file as UTF-8 JSON (meta files are always plain JSON)
|
||||||
let content = std::fs::read(&meta_path)
|
let json_str = std::fs::read_to_string(&meta_path)
|
||||||
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
-32000,
|
-32000,
|
||||||
format!("Failed to read meta file: {}", e),
|
format!("Failed to read meta file: {}", e),
|
||||||
None::<()>
|
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)
|
serde_json::from_str(&json_str)
|
||||||
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
-32000,
|
-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> {
|
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 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(
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
-32000,
|
-32000,
|
||||||
format!("Failed to serialize meta: {}", e),
|
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> {
|
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 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(
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
-32000,
|
-32000,
|
||||||
format!("Failed to serialize meta: {}", e),
|
format!("Failed to serialize meta: {}", e),
|
||||||
None::<()>
|
None::<()>
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
if db_id >= 10 {
|
// Meta files are always stored as plain JSON (even when data DB is encrypted)
|
||||||
// Encrypted database, encrypt meta
|
std::fs::write(&meta_path, json_str)
|
||||||
if let Some(key) = self.encryption_keys.read().await.get(&db_id).and_then(|k| k.as_ref()) {
|
.map_err(|e| jsonrpsee::types::ErrorObjectOwned::owned(
|
||||||
use crate::crypto::CryptoFactory;
|
-32000,
|
||||||
let crypto = CryptoFactory::new(key.as_bytes());
|
format!("Failed to write meta file: {}", e),
|
||||||
let encrypted = crypto.encrypt(json_str.as_bytes());
|
None::<()>
|
||||||
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::<()>
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user