diff --git a/src/api.rs b/src/api.rs index 0ef8e53..9c5895e 100644 --- a/src/api.rs +++ b/src/api.rs @@ -6,7 +6,7 @@ use serde_json::json; use crate::{ data_mgt::AssetTracker, - logs::{LogEventBody, LogEventLine, LogEventType, log_event}, + logs::{ LogEvent, LogEventType, log_event}, }; #[derive(Deserialize, Debug)] @@ -45,7 +45,7 @@ async fn api_upload( Some(uploader_ip.clone()), ); - log_event(LogEventType::AssetUploaded(&asset)); + log_event(LogEventType::AssetUploaded(asset.clone())); let id = asset.id(); assets.add_asset(asset).await; let response_body = json!({ "link": format!("/bhs/{}", id) }); @@ -58,7 +58,7 @@ async fn api_get_asset( path: web::Path, assets: web::Data, ) -> Result { - log_event(LogEventType::HttpRequest(&req.into())); + log_event(LogEventType::HttpRequest(req.into())); match assets.get_asset(&path.into_inner()).await { None => Ok(HttpResponse::NotFound().body("Asset not found")), @@ -104,26 +104,26 @@ async fn api_stats(assets: web::Data) -> Result(line) { + if let Ok(entry) = serde_json::from_str::(line) { match entry.event { - LogEventBody::HttpRequest(_req) => { + LogEventType::HttpRequest(_req) => { request_count += 1; } - LogEventBody::AssetUploaded(asset) => { + LogEventType::AssetUploaded(asset) => { total_uploads += 1; recent_activity.push(ActivityItem { action: "upload".to_string(), - mime: asset.mime, - share_duration: asset.share_duration, + mime: asset.mime(), + share_duration: asset.share_duration(), timestamp: entry.time, }); } - LogEventBody::AssetDeleted(asset) => { + LogEventType::AssetDeleted(asset) => { total_deleted += 1; recent_activity.push(ActivityItem { action: "delete".to_string(), - mime: asset.mime, - share_duration: asset.share_duration, + mime: asset.mime(), + share_duration: asset.share_duration(), timestamp: entry.time, }); } diff --git a/src/data_mgt.rs b/src/data_mgt.rs index a377341..134a076 100644 --- a/src/data_mgt.rs +++ b/src/data_mgt.rs @@ -5,11 +5,12 @@ use anyhow::Result; use chrono::{Duration, Utc}; use futures::lock::Mutex; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::DATA_STORAGE; use crate::logs::{LogEventType, log_event}; -#[derive(Debug, Serialize, Deserialize, Default, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct Asset { id: String, share_duration: u32, @@ -45,8 +46,8 @@ impl Asset { self.id.clone() } - pub fn mime(&self) -> &str { - &self.mime + pub fn mime(&self) -> String { + self.mime.clone() } pub fn content(&self) -> Vec { @@ -65,6 +66,10 @@ impl Asset { self.expires_at } + pub fn mime_type(&self) -> &str { + &self.mime + } + pub fn size_bytes(&self) -> usize { self.content.len() } @@ -85,8 +90,16 @@ impl Asset { std::fs::write(&path, self.to_bytes()?)?; Ok(id) } + } +impl From for Value { + fn from(asset: Asset) -> Self { + serde_json::to_value(asset).unwrap() + } +} + + #[derive(Clone)] pub struct AssetTracker { assets: Arc>>, @@ -110,8 +123,8 @@ impl AssetTracker { let mut assets = self.assets.lock().await; let removed_assets = assets.extract_if(.., |asset| asset.is_expired()); for asset in removed_assets { - log_event(LogEventType::AssetDeleted(&asset)); println!("[{}] Removing asset: {}", chrono::Local::now().to_rfc3339(), asset.id()); + log_event(LogEventType::AssetDeleted(asset)); } } diff --git a/src/logs.rs b/src/logs.rs index 6f6da40..d8ae894 100644 --- a/src/logs.rs +++ b/src/logs.rs @@ -6,31 +6,6 @@ use serde::{Deserialize, Serialize}; use crate::{LOG_DIR, data_mgt::Asset}; -#[derive(Deserialize)] -pub struct LogEventLine { - pub time: String, - pub event: LogEventBody, -} - -#[derive(Deserialize)] -pub enum LogEventBody { - AssetUploaded(LogAsset), - AssetDeleted(LogAsset), - HttpRequest(LogHttpRequest), -} - -#[derive(Deserialize)] -pub struct LogAsset { - pub id: String, - pub share_duration: u32, - pub created_at: i64, - pub expires_at: i64, - pub mime: String, - pub uploader_ip: Option, -} - - - #[derive(Debug, Serialize, Deserialize)] pub struct LogHttpRequest { pub method: String, @@ -72,21 +47,21 @@ impl From for LogHttpRequest { } } -#[derive(Debug, Serialize)] -pub enum LogEventType<'a> { - AssetUploaded(&'a Asset), - AssetDeleted(&'a Asset), - HttpRequest(&'a LogHttpRequest), +#[derive(Debug, Serialize, Deserialize)] +pub enum LogEventType { + AssetUploaded(Asset), + AssetDeleted(Asset), + HttpRequest(LogHttpRequest), } -#[derive(Debug, Serialize)] -pub struct LogEvent<'a> { +#[derive(Debug, Serialize, Deserialize)] +pub struct LogEvent { pub time: String, - pub event: LogEventType<'a>, + pub event: LogEventType, } -impl<'a> From> for LogEvent<'a> { - fn from(event: LogEventType<'a>) -> Self { +impl From for LogEvent { + fn from(event: LogEventType) -> Self { let time = chrono::Utc::now().to_rfc3339(); LogEvent { time, event } } diff --git a/src/main.rs b/src/main.rs index 6f87a33..7424b94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,21 +51,21 @@ use crate::{ #[get("/")] async fn index(req: HttpRequest) -> actix_web::Result { let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "index.html"); - log_event(LogEventType::HttpRequest(&req.into())); + log_event(LogEventType::HttpRequest(req.into())); Ok(NamedFile::open(path)?) } #[get("/stats")] async fn stats(req: HttpRequest) -> actix_web::Result { let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "stats.html"); - log_event(LogEventType::HttpRequest(&req.into())); + log_event(LogEventType::HttpRequest(req.into())); Ok(NamedFile::open(path)?) } #[get("/bhs/{id}")] async fn view_asset(req: HttpRequest) -> actix_web::Result { let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "view.html"); - log_event(LogEventType::HttpRequest(&req.into())); + log_event(LogEventType::HttpRequest(req.into())); Ok(NamedFile::open(path)?) } @@ -82,7 +82,7 @@ async fn catch_all(req: HttpRequest, _payload: Option>) -> acti } }; - log_event(LogEventType::HttpRequest(&req.into())); + log_event(LogEventType::HttpRequest(req.into())); response }