feat: add statistics API and dashboard for asset metrics
All checks were successful
Rust CI / build-test (push) Successful in 1m22s
All checks were successful
Rust CI / build-test (push) Successful in 1m22s
- Implemented `/api/stats` endpoint to return JSON metrics including active assets, total uploads, storage usage, and recent activity. - Created `stats.html` page to display real-time statistics with auto-refresh functionality. - Enhanced asset logging to include uploader IP and detailed event information for uploads and deletions. - Updated asset model to store uploader IP for audit purposes. - Improved logging functionality to ensure log directory exists before writing. - Refactored asset creation and management to support new features and logging.
This commit is contained in:
@@ -3,6 +3,7 @@ use chrono::{Duration, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::DATA_STORAGE;
|
||||
use crate::logs::log_asset_event;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct Asset {
|
||||
@@ -12,10 +13,12 @@ pub struct Asset {
|
||||
expires_at: i64,
|
||||
mime: String,
|
||||
content: Vec<u8>,
|
||||
#[serde(default)]
|
||||
uploader_ip: Option<String>,
|
||||
}
|
||||
|
||||
impl Asset {
|
||||
pub fn new(share_duration: u32, mime: String, content: Vec<u8>) -> Self {
|
||||
pub fn new(share_duration: u32, mime: String, content: Vec<u8>, uploader_ip: Option<String>) -> Self {
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
let created_at = Utc::now().timestamp_millis();
|
||||
let expires_at = created_at + Duration::minutes(share_duration as i64).num_milliseconds();
|
||||
@@ -26,6 +29,7 @@ impl Asset {
|
||||
expires_at,
|
||||
mime,
|
||||
content,
|
||||
uploader_ip,
|
||||
}
|
||||
}
|
||||
pub fn is_expired(&self) -> bool {
|
||||
@@ -44,6 +48,26 @@ impl Asset {
|
||||
self.content.clone()
|
||||
}
|
||||
|
||||
pub fn share_duration(&self) -> u32 {
|
||||
self.share_duration
|
||||
}
|
||||
|
||||
pub fn created_at(&self) -> i64 {
|
||||
self.created_at
|
||||
}
|
||||
|
||||
pub fn expires_at(&self) -> i64 {
|
||||
self.expires_at
|
||||
}
|
||||
|
||||
pub fn size_bytes(&self) -> usize {
|
||||
self.content.len()
|
||||
}
|
||||
|
||||
pub fn uploader_ip(&self) -> Option<&str> {
|
||||
self.uploader_ip.as_deref()
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Result<Vec<u8>> {
|
||||
let bytes = serde_json::to_vec(self)?;
|
||||
Ok(bytes)
|
||||
@@ -68,6 +92,16 @@ pub async fn clear_assets() -> Result<()> {
|
||||
let asset = serde_json::from_slice::<Asset>(&data)?;
|
||||
if asset.is_expired() {
|
||||
println!("Removing expired asset: {}", asset.id());
|
||||
log_asset_event(
|
||||
"delete_expired",
|
||||
asset.id(),
|
||||
asset.mime(),
|
||||
asset.size_bytes(),
|
||||
asset.share_duration(),
|
||||
asset.created_at(),
|
||||
asset.expires_at(),
|
||||
asset.uploader_ip().unwrap_or("-"),
|
||||
);
|
||||
std::fs::remove_file(&path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user