Files
nora/nora-registry/src/registry/cargo_registry.rs
DevITWay 38c727491b Add dashboard metrics, activity log, and dark theme
- Add DashboardMetrics for tracking downloads/uploads/cache hits per registry
- Add ActivityLog for recent activity with bounded size (50 entries)
- Instrument Docker, npm, Maven, and Cargo handlers with metrics
- Add /api/ui/dashboard endpoint with global stats and activity
- Implement dark theme dashboard with real-time polling (5s interval)
- Add mount points table showing registry paths and proxy upstreams
2026-01-26 16:21:25 +00:00

55 lines
1.5 KiB
Rust

use crate::activity_log::{ActionType, ActivityEntry};
use crate::AppState;
use axum::{
extract::{Path, State},
http::StatusCode,
response::{IntoResponse, Response},
routing::get,
Router,
};
use std::sync::Arc;
pub fn routes() -> Router<Arc<AppState>> {
Router::new()
.route("/cargo/api/v1/crates/{crate_name}", get(get_metadata))
.route(
"/cargo/api/v1/crates/{crate_name}/{version}/download",
get(download),
)
}
async fn get_metadata(
State(state): State<Arc<AppState>>,
Path(crate_name): Path<String>,
) -> Response {
let key = format!("cargo/{}/metadata.json", crate_name);
match state.storage.get(&key).await {
Ok(data) => (StatusCode::OK, data).into_response(),
Err(_) => StatusCode::NOT_FOUND.into_response(),
}
}
async fn download(
State(state): State<Arc<AppState>>,
Path((crate_name, version)): Path<(String, String)>,
) -> Response {
let key = format!(
"cargo/{}/{}/{}-{}.crate",
crate_name, version, crate_name, version
);
match state.storage.get(&key).await {
Ok(data) => {
state.metrics.record_download("cargo");
state.metrics.record_cache_hit();
state.activity.push(ActivityEntry::new(
ActionType::Pull,
format!("{}@{}", crate_name, version),
"cargo",
"LOCAL",
));
(StatusCode::OK, data).into_response()
}
Err(_) => StatusCode::NOT_FOUND.into_response(),
}
}