fix: resolve clippy warnings and format code

This commit is contained in:
2026-01-26 08:31:00 +00:00
parent 97eaa364ae
commit 00fbd20112
10 changed files with 31 additions and 32 deletions

View File

@@ -405,7 +405,9 @@ mod tests {
// Protected paths // Protected paths
assert!(!is_public_path("/v2/myimage/blobs/sha256:abc")); assert!(!is_public_path("/v2/myimage/blobs/sha256:abc"));
assert!(!is_public_path("/v2/library/nginx/manifests/latest")); assert!(!is_public_path("/v2/library/nginx/manifests/latest"));
assert!(!is_public_path("/maven2/com/example/artifact/1.0/artifact.jar")); assert!(!is_public_path(
"/maven2/com/example/artifact/1.0/artifact.jar"
));
assert!(!is_public_path("/npm/lodash")); assert!(!is_public_path("/npm/lodash"));
} }

View File

@@ -1,3 +1,4 @@
#![allow(dead_code)]
//! Application error handling with HTTP response conversion //! Application error handling with HTTP response conversion
//! //!
//! Provides a unified error type that can be converted to HTTP responses //! Provides a unified error type that can be converted to HTTP responses

View File

@@ -29,11 +29,7 @@ pub use storage::Storage;
use tokens::TokenStore; use tokens::TokenStore;
#[derive(Parser)] #[derive(Parser)]
#[command( #[command(name = "nora", version, about = "Multi-protocol artifact registry")]
name = "nora",
version,
about = "Multi-protocol artifact registry"
)]
struct Cli { struct Cli {
#[command(subcommand)] #[command(subcommand)]
command: Option<Commands>, command: Option<Commands>,

View File

@@ -8,17 +8,12 @@ use indicatif::{ProgressBar, ProgressStyle};
use tracing::{info, warn}; use tracing::{info, warn};
/// Migration options /// Migration options
#[derive(Default)]
pub struct MigrateOptions { pub struct MigrateOptions {
/// If true, show what would be migrated without copying /// If true, show what would be migrated without copying
pub dry_run: bool, pub dry_run: bool,
} }
impl Default for MigrateOptions {
fn default() -> Self {
Self { dry_run: false }
}
}
/// Migration statistics /// Migration statistics
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct MigrateStats { pub struct MigrateStats {
@@ -64,7 +59,9 @@ pub async fn migrate(
let pb = ProgressBar::new(keys.len() as u64); let pb = ProgressBar::new(keys.len() as u64);
pb.set_style( pb.set_style(
ProgressStyle::default_bar() ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})") .template(
"{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})",
)
.expect("Invalid progress bar template") .expect("Invalid progress bar template")
.progress_chars("#>-"), .progress_chars("#>-"),
); );

View File

@@ -1,3 +1,4 @@
#![allow(dead_code)]
//! Rate limiting configuration and middleware //! Rate limiting configuration and middleware
//! //!
//! Provides rate limiting to protect against: //! Provides rate limiting to protect against:
@@ -27,11 +28,11 @@ pub struct RateLimitConfig {
impl Default for RateLimitConfig { impl Default for RateLimitConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
auth_rps: 1, // 1 req/sec for auth (strict) auth_rps: 1, // 1 req/sec for auth (strict)
auth_burst: 5, // Allow burst of 5 auth_burst: 5, // Allow burst of 5
upload_rps: 10, // 10 req/sec for uploads upload_rps: 10, // 10 req/sec for uploads
upload_burst: 20, // Allow burst of 20 upload_burst: 20, // Allow burst of 20
general_rps: 100, // 100 req/sec general general_rps: 100, // 100 req/sec general
general_burst: 200, // Allow burst of 200 general_burst: 200, // Allow burst of 200
} }
} }

View File

@@ -178,10 +178,7 @@ async fn put_manifest(
} }
} }
async fn list_tags( async fn list_tags(State(state): State<Arc<AppState>>, Path(name): Path<String>) -> Response {
State(state): State<Arc<AppState>>,
Path(name): Path<String>,
) -> Response {
if let Err(e) = validate_docker_name(&name) { if let Err(e) = validate_docker_name(&name) {
return (StatusCode::BAD_REQUEST, e.to_string()).into_response(); return (StatusCode::BAD_REQUEST, e.to_string()).into_response();
} }

View File

@@ -76,10 +76,8 @@ impl Storage {
pub async fn list(&self, prefix: &str) -> Vec<String> { pub async fn list(&self, prefix: &str) -> Vec<String> {
// Empty prefix is valid for listing all // Empty prefix is valid for listing all
if !prefix.is_empty() { if !prefix.is_empty() && validate_storage_key(prefix).is_err() {
if let Err(_) = validate_storage_key(prefix) { return Vec::new();
return Vec::new();
}
} }
self.inner.list(prefix).await self.inner.list(prefix).await
} }

View File

@@ -59,7 +59,13 @@ pub fn render_dashboard(stats: &RegistryStats) -> String {
</div> </div>
</div> </div>
"##, "##,
stat_card("Docker", icons::DOCKER, stats.docker, "/ui/docker", "images"), stat_card(
"Docker",
icons::DOCKER,
stats.docker,
"/ui/docker",
"images"
),
stat_card("Maven", icons::MAVEN, stats.maven, "/ui/maven", "artifacts"), stat_card("Maven", icons::MAVEN, stats.maven, "/ui/maven", "artifacts"),
stat_card("npm", icons::NPM, stats.npm, "/ui/npm", "packages"), stat_card("npm", icons::NPM, stats.npm, "/ui/npm", "packages"),
stat_card("Cargo", icons::CARGO, stats.cargo, "/ui/cargo", "crates"), stat_card("Cargo", icons::CARGO, stats.cargo, "/ui/cargo", "crates"),
@@ -455,7 +461,9 @@ fn get_registry_icon(registry_type: &str) -> &'static str {
"npm" => icons::NPM, "npm" => icons::NPM,
"cargo" => icons::CARGO, "cargo" => icons::CARGO,
"pypi" => icons::PYPI, "pypi" => icons::PYPI,
_ => r#"<path fill="currentColor" d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>"#, _ => {
r#"<path fill="currentColor" d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>"#
}
} }
} }

View File

@@ -1,3 +1,4 @@
#![allow(dead_code)]
//! Input validation for artifact registry paths and identifiers //! Input validation for artifact registry paths and identifiers
//! //!
//! Provides security validation to prevent path traversal attacks and //! Provides security validation to prevent path traversal attacks and
@@ -92,7 +93,7 @@ pub fn validate_storage_key(key: &str) -> Result<(), ValidationError> {
// Check each segment // Check each segment
for segment in key.split('/') { for segment in key.split('/') {
if segment.is_empty() && key != "" { if segment.is_empty() && !key.is_empty() {
// Allow trailing slash but not double slashes // Allow trailing slash but not double slashes
continue; continue;
} }

View File

@@ -133,9 +133,7 @@ async fn main() {
.expect("Failed to bind to address"); .expect("Failed to bind to address");
info!("nora-storage (S3 compatible) running on http://{}", addr); info!("nora-storage (S3 compatible) running on http://{}", addr);
axum::serve(listener, app) axum::serve(listener, app).await.expect("Server error");
.await
.expect("Server error");
} }
async fn list_buckets(State(state): State<Arc<AppState>>) -> Response { async fn list_buckets(State(state): State<Arc<AppState>>) -> Response {