mod memory;
#[cfg(feature = "db-sqlite")]
mod sqlite;
#[cfg(feature = "db-postgres")]
mod postgres;
pub use memory::MemoryDatabase;
#[cfg(feature = "db-sqlite")]
pub use sqlite::SqliteDatabase;
#[cfg(feature = "db-postgres")]
pub use postgres::PostgresDatabase;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UploadRecord {
pub sha256: String,
pub size: u64,
pub mime_type: String,
pub pubkey: String,
pub created_at: u64,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub phash: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserRecord {
pub pubkey: String,
#[serde(default = "default_role")]
pub role: String,
pub quota_bytes: Option<u64>,
pub used_bytes: u64,
}
fn default_role() -> String {
"member".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileStats {
pub sha256: String,
pub egress_bytes: u64,
pub last_accessed: u64,
}
#[derive(Debug, thiserror::Error)]
pub enum DbError {
#[error("quota exceeded: used {used} + {requested} > limit {limit}")]
QuotaExceeded {
used: u64,
requested: u64,
limit: u64,
},
#[error("not found")]
NotFound,
#[error("database error: {0}")]
Internal(String),
}
pub trait BlobDatabase: Send + Sync {
fn record_upload(&mut self, record: &UploadRecord) -> Result<(), DbError>;
fn get_upload(&self, sha256: &str) -> Result<UploadRecord, DbError>;
fn list_uploads_by_pubkey(&self, pubkey: &str) -> Result<Vec<UploadRecord>, DbError>;
fn delete_upload(&mut self, sha256: &str) -> Result<bool, DbError>;
fn get_or_create_user(&mut self, pubkey: &str) -> Result<UserRecord, DbError>;
fn set_quota(&mut self, pubkey: &str, quota_bytes: Option<u64>) -> Result<(), DbError>;
fn check_quota(&self, pubkey: &str, additional_bytes: u64) -> Result<(), DbError>;
fn update_used_bytes(&mut self, pubkey: &str, used_bytes: u64) -> Result<(), DbError>;
fn record_access(&mut self, sha256: &str, bytes_served: u64) -> Result<(), DbError>;
fn get_stats(&self, sha256: &str) -> Result<FileStats, DbError>;
fn upload_count(&self) -> usize;
fn user_count(&self) -> usize;
fn set_role(&mut self, pubkey: &str, role: &str) -> Result<(), DbError>;
fn get_role(&self, pubkey: &str) -> String;
fn list_users_by_role(&self, role: &str) -> Result<Vec<UserRecord>, DbError>;
fn find_by_phash(&self, phash: u64) -> Result<Vec<UploadRecord>, DbError> {
let _ = phash;
Ok(vec![])
}
}