refactor: apply clippy auto-fixes (162 warnings resolved)
- Fix needless borrows and references - Collapse nested if statements - Replace manual strip_prefix with str::strip_prefix() - Remove redundant closures in map/unwrap_or_else - Use Iterator::next_back() instead of rev().next() - Simplify map_or patterns - Use std::io::Error::other() instead of new(ErrorKind::Other, ..) - Use div_ceil() instead of manual ceiling division - Consolidate format! string arguments - Various other idiomatic Rust improvements 39 files changed, 220 insertions(+), 320 deletions(-)
This commit is contained in:
@@ -51,7 +51,7 @@ async fn admin_guard(state: &AppState, headers: &HeaderMap) -> Result<(String, S
|
||||
.ok_or_else(|| AppError::unauthorized("Authorization token required"))?;
|
||||
|
||||
let claims = auth.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(format!("Invalid token: {}", e)))?;
|
||||
|
||||
if claims.role != "admin" {
|
||||
return Err(AppError::new(
|
||||
@@ -75,7 +75,7 @@ async fn get_oidc_settings(
|
||||
.ok_or_else(|| AppError::internal_error("Admin settings service not available"))?;
|
||||
|
||||
let settings = svc.get_oidc_settings().await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to load settings: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to load settings: {}", e)))?;
|
||||
|
||||
Ok(Json(settings))
|
||||
}
|
||||
@@ -92,7 +92,7 @@ async fn save_oidc_settings(
|
||||
.ok_or_else(|| AppError::internal_error("Admin settings service not available"))?;
|
||||
|
||||
svc.save_oidc_settings(dto, &user_id).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to save settings: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to save settings: {}", e)))?;
|
||||
|
||||
Ok((StatusCode::OK, Json(serde_json::json!({
|
||||
"message": "OIDC settings saved and applied successfully"
|
||||
@@ -111,7 +111,7 @@ async fn test_oidc_connection(
|
||||
.ok_or_else(|| AppError::internal_error("Admin settings service not available"))?;
|
||||
|
||||
let result = svc.test_oidc_connection(dto).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Connection test failed: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Connection test failed: {}", e)))?;
|
||||
|
||||
Ok(Json(result))
|
||||
}
|
||||
@@ -173,7 +173,7 @@ async fn get_dashboard_stats(
|
||||
)
|
||||
.fetch_one(db_pool.as_ref())
|
||||
.await
|
||||
.map_err(|e| AppError::internal_error(&format!("Database query failed: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Database query failed: {}", e)))?;
|
||||
|
||||
use sqlx::Row;
|
||||
let total_quota: i64 = stats_row.get("total_quota_bytes");
|
||||
@@ -228,7 +228,7 @@ async fn list_users(
|
||||
let offset = query.offset.unwrap_or(0);
|
||||
|
||||
let users = auth.auth_application_service.list_users(limit, offset).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to list users: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to list users: {}", e)))?;
|
||||
|
||||
let total = auth.auth_application_service.count_users_efficient().await.unwrap_or(0);
|
||||
|
||||
@@ -252,7 +252,7 @@ async fn get_user(
|
||||
.ok_or_else(|| AppError::internal_error("Auth service not configured"))?;
|
||||
|
||||
let user = auth.auth_application_service.get_user_admin(&id).await
|
||||
.map_err(|e| AppError::not_found(&format!("User not found: {}", e)))?;
|
||||
.map_err(|e| AppError::not_found(format!("User not found: {}", e)))?;
|
||||
|
||||
Ok(Json(user))
|
||||
}
|
||||
@@ -278,7 +278,7 @@ async fn delete_user(
|
||||
.ok_or_else(|| AppError::internal_error("Auth service not configured"))?;
|
||||
|
||||
auth.auth_application_service.delete_user_admin(&id).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to delete user: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to delete user: {}", e)))?;
|
||||
|
||||
Ok((StatusCode::OK, Json(serde_json::json!({
|
||||
"message": "User deleted successfully"
|
||||
@@ -307,7 +307,7 @@ async fn update_user_role(
|
||||
.ok_or_else(|| AppError::internal_error("Auth service not configured"))?;
|
||||
|
||||
auth.auth_application_service.change_user_role(&id, &dto.role).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to change role: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to change role: {}", e)))?;
|
||||
|
||||
Ok((StatusCode::OK, Json(serde_json::json!({
|
||||
"message": format!("User role updated to '{}'", dto.role)
|
||||
@@ -336,7 +336,7 @@ async fn update_user_active(
|
||||
.ok_or_else(|| AppError::internal_error("Auth service not configured"))?;
|
||||
|
||||
auth.auth_application_service.set_user_active(&id, dto.active).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to update user status: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to update user status: {}", e)))?;
|
||||
|
||||
let status = if dto.active { "activated" } else { "deactivated" };
|
||||
Ok((StatusCode::OK, Json(serde_json::json!({
|
||||
@@ -357,7 +357,7 @@ async fn update_user_quota(
|
||||
.ok_or_else(|| AppError::internal_error("Auth service not configured"))?;
|
||||
|
||||
auth.auth_application_service.update_user_quota(&id, dto.quota_bytes).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to update quota: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to update quota: {}", e)))?;
|
||||
|
||||
Ok((StatusCode::OK, Json(serde_json::json!({
|
||||
"message": "User quota updated",
|
||||
@@ -383,7 +383,7 @@ async fn create_user(
|
||||
let user = auth.auth_application_service.admin_create_user(dto).await
|
||||
.map_err(|e| AppError::new(
|
||||
StatusCode::BAD_REQUEST,
|
||||
&format!("Failed to create user: {}", e),
|
||||
format!("Failed to create user: {}", e),
|
||||
"CreateUserFailed",
|
||||
))?;
|
||||
|
||||
@@ -405,7 +405,7 @@ async fn reset_user_password(
|
||||
auth.auth_application_service.admin_reset_password(&id, &dto.new_password).await
|
||||
.map_err(|e| AppError::new(
|
||||
StatusCode::BAD_REQUEST,
|
||||
&format!("Failed to reset password: {}", e),
|
||||
format!("Failed to reset password: {}", e),
|
||||
"ResetPasswordFailed",
|
||||
))?;
|
||||
|
||||
@@ -455,7 +455,7 @@ async fn set_registration_setting(
|
||||
.ok_or_else(|| AppError::internal_error("Admin settings service not available"))?;
|
||||
|
||||
svc.set_registration_enabled(enabled, &admin_id).await
|
||||
.map_err(|e| AppError::internal_error(&format!("Failed to save setting: {}", e)))?;
|
||||
.map_err(|e| AppError::internal_error(format!("Failed to save setting: {}", e)))?;
|
||||
|
||||
Ok((StatusCode::OK, Json(serde_json::json!({
|
||||
"message": format!("Public registration {}", if enabled { "enabled" } else { "disabled" }),
|
||||
|
||||
@@ -67,15 +67,14 @@ async fn register(
|
||||
}
|
||||
|
||||
// Check if public registration has been disabled by the admin
|
||||
if let Some(admin_svc) = state.admin_settings_service.as_ref() {
|
||||
if !admin_svc.get_registration_enabled().await {
|
||||
if let Some(admin_svc) = state.admin_settings_service.as_ref()
|
||||
&& !admin_svc.get_registration_enabled().await {
|
||||
return Err(AppError::new(
|
||||
StatusCode::FORBIDDEN,
|
||||
"Public registration has been disabled by the administrator.",
|
||||
"RegistrationDisabled",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Registration logic (admin detection, fresh-install handling, duplicate
|
||||
// checks) is all inside the service layer. Call it directly.
|
||||
@@ -178,7 +177,7 @@ async fn get_current_user(
|
||||
|
||||
// Validate the token and get claims
|
||||
let claims = auth_service.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(format!("Invalid token: {}", e)))?;
|
||||
|
||||
let user_id = claims.sub;
|
||||
|
||||
@@ -220,7 +219,7 @@ async fn change_password(
|
||||
|
||||
// Validate the token and get claims
|
||||
let claims = auth_service.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(format!("Invalid token: {}", e)))?;
|
||||
|
||||
auth_service.auth_application_service.change_password(&claims.sub, dto).await?;
|
||||
|
||||
@@ -243,7 +242,7 @@ async fn logout(
|
||||
|
||||
// Validate the token and get claims
|
||||
let claims = auth_service.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(format!("Invalid token: {}", e)))?;
|
||||
|
||||
// Use access token for logout (we don't have refresh token in headers)
|
||||
auth_service.auth_application_service.logout(&claims.sub, token).await?;
|
||||
|
||||
@@ -320,7 +320,7 @@ async fn handle_mkcalendar(
|
||||
.map_err(|e| AppError::bad_request(format!("Failed to read request body: {}", e)))?;
|
||||
|
||||
let (name, description, color) = if body_bytes.is_empty() {
|
||||
let name = path.split('/').last().unwrap_or("New Calendar").to_string();
|
||||
let name = path.split('/').next_back().unwrap_or("New Calendar").to_string();
|
||||
(name, None, None)
|
||||
} else {
|
||||
CalDavAdapter::parse_mkcalendar(body_bytes.reader())
|
||||
|
||||
@@ -335,7 +335,7 @@ async fn handle_mkcol(
|
||||
.map_err(|e| AppError::bad_request(format!("Failed to read request body: {}", e)))?;
|
||||
|
||||
let (name, description, color) = if body_bytes.is_empty() {
|
||||
let name = path.split('/').last().unwrap_or("New Address Book").to_string();
|
||||
let name = path.split('/').next_back().unwrap_or("New Address Book").to_string();
|
||||
(name, None, None)
|
||||
} else {
|
||||
CardDavAdapter::parse_mkaddressbook(body_bytes.reader())
|
||||
|
||||
@@ -271,7 +271,7 @@ impl FileHandler {
|
||||
};
|
||||
|
||||
// ── Metadata-only request ────────────────────────────────────
|
||||
if params.get("metadata").map_or(false, |v| v == "true" || v == "1") {
|
||||
if params.get("metadata").is_some_and(|v| v == "true" || v == "1") {
|
||||
return (StatusCode::OK, Json(serde_json::json!({
|
||||
"id": file_dto.id,
|
||||
"name": file_dto.name,
|
||||
@@ -287,9 +287,9 @@ impl FileHandler {
|
||||
let etag = format!("\"{}-{}\"", id, file_dto.modified_at);
|
||||
|
||||
// ── ETag (304 Not Modified) ──────────────────────────────────
|
||||
if let Some(inm) = headers.get(header::IF_NONE_MATCH) {
|
||||
if let Ok(client_etag) = inm.to_str() {
|
||||
if client_etag == etag || client_etag == "*" {
|
||||
if let Some(inm) = headers.get(header::IF_NONE_MATCH)
|
||||
&& let Ok(client_etag) = inm.to_str()
|
||||
&& (client_etag == etag || client_etag == "*") {
|
||||
return Response::builder()
|
||||
.status(StatusCode::NOT_MODIFIED)
|
||||
.header(header::ETAG, &etag)
|
||||
@@ -297,13 +297,11 @@ impl FileHandler {
|
||||
.unwrap()
|
||||
.into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Range Requests ───────────────────────────────────────────
|
||||
if let Some(range_header) = headers.get(header::RANGE) {
|
||||
if let Ok(range_str) = range_header.to_str() {
|
||||
if let Ok(ranges) = parse_range_header(range_str) {
|
||||
if let Some(range_header) = headers.get(header::RANGE)
|
||||
&& let Ok(range_str) = range_header.to_str()
|
||||
&& let Ok(ranges) = parse_range_header(range_str) {
|
||||
let validated = ranges.validate(file_dto.size);
|
||||
if let Ok(valid_ranges) = validated {
|
||||
if let Some(range) = valid_ranges.first() {
|
||||
@@ -342,16 +340,14 @@ impl FileHandler {
|
||||
.into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Normal download (delegated to service) ───────────────────
|
||||
let disposition = Self::content_disposition(&file_dto.name, &file_dto.mime_type, ¶ms);
|
||||
|
||||
let accept_webp = headers.get(header::ACCEPT)
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.map_or(false, |a| a.contains("image/webp"));
|
||||
let prefer_original = params.get("original").map_or(false, |v| v == "true" || v == "1");
|
||||
.is_some_and(|a| a.contains("image/webp"));
|
||||
let prefer_original = params.get("original").is_some_and(|v| v == "true" || v == "1");
|
||||
|
||||
match retrieval.get_file_optimized(&id, accept_webp, prefer_original).await {
|
||||
Ok((_file, content)) => match content {
|
||||
@@ -447,9 +443,9 @@ impl FileHandler {
|
||||
if let Ok(body_bytes) = axum::body::to_bytes(
|
||||
response.into_response().into_body(),
|
||||
10 * 1024,
|
||||
).await {
|
||||
if let Ok(file_info) = serde_json::from_slice::<serde_json::Value>(&body_bytes) {
|
||||
if let (Some(file_id), Some(mime_type), Some(file_path_str)) = (
|
||||
).await
|
||||
&& let Ok(file_info) = serde_json::from_slice::<serde_json::Value>(&body_bytes)
|
||||
&& let (Some(file_id), Some(mime_type), Some(file_path_str)) = (
|
||||
file_info.get("id").and_then(|v| v.as_str()),
|
||||
file_info.get("mime_type").and_then(|v| v.as_str()),
|
||||
file_info.get("path").and_then(|v| v.as_str()),
|
||||
@@ -477,8 +473,6 @@ impl FileHandler {
|
||||
.unwrap()
|
||||
.into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for errors
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Upload processing error").into_response()
|
||||
@@ -676,7 +670,7 @@ impl FileHandler {
|
||||
|
||||
/// Build a Content-Disposition header value.
|
||||
fn content_disposition(name: &str, mime: &str, params: &HashMap<String, String>) -> String {
|
||||
let force_inline = params.get("inline").map_or(false, |v| v == "true" || v == "1");
|
||||
let force_inline = params.get("inline").is_some_and(|v| v == "true" || v == "1");
|
||||
if force_inline
|
||||
|| mime.starts_with("image/")
|
||||
|| mime == "application/pdf"
|
||||
@@ -750,7 +744,7 @@ impl FileHandler {
|
||||
.header(header::VARY, "Accept-Encoding");
|
||||
|
||||
if should_compress {
|
||||
match compression_service.compress_data(&content.to_vec(), compression_level).await {
|
||||
match compression_service.compress_data(&content, compression_level).await {
|
||||
Ok(compressed) => {
|
||||
builder
|
||||
.header(header::CONTENT_TYPE, mime_type)
|
||||
|
||||
@@ -409,7 +409,7 @@ async fn handle_get(
|
||||
.header(header::CONTENT_LENGTH, content.len())
|
||||
.header(header::ETAG, format!("\"{}\"", file.id))
|
||||
.header(header::LAST_MODIFIED, chrono::DateTime::<Utc>::from_timestamp(file.created_at as i64, 0)
|
||||
.unwrap_or_else(|| Utc::now())
|
||||
.unwrap_or_else(Utc::now)
|
||||
.to_rfc2822())
|
||||
.body(Body::from(content))
|
||||
.unwrap())
|
||||
@@ -463,7 +463,7 @@ async fn handle_head(
|
||||
.header(header::CONTENT_LENGTH, content.len())
|
||||
.header(header::ETAG, format!("\"{}\"", file.id))
|
||||
.header(header::LAST_MODIFIED, chrono::DateTime::<Utc>::from_timestamp(file.created_at as i64, 0)
|
||||
.unwrap_or_else(|| Utc::now())
|
||||
.unwrap_or_else(Utc::now)
|
||||
.to_rfc2822())
|
||||
.body(Body::empty())
|
||||
.unwrap())
|
||||
@@ -573,7 +573,7 @@ async fn handle_mkcol(
|
||||
}
|
||||
|
||||
// Extract folder name from path
|
||||
let folder_name = path.split('/').last().unwrap_or("unnamed");
|
||||
let folder_name = path.split('/').next_back().unwrap_or("unnamed");
|
||||
|
||||
// Get parent folder path
|
||||
let parent_path = if let Some(idx) = path.rfind('/') {
|
||||
@@ -715,7 +715,7 @@ async fn handle_move(
|
||||
|
||||
if let Ok(folder) = folder_result {
|
||||
// Move folder
|
||||
let dest_folder_name = destination_path.split('/').last().unwrap_or(&destination_path);
|
||||
let dest_folder_name = destination_path.split('/').next_back().unwrap_or(&destination_path);
|
||||
let dest_parent_path = if let Some(idx) = destination_path.rfind('/') {
|
||||
&destination_path[..idx]
|
||||
} else {
|
||||
@@ -753,7 +753,7 @@ async fn handle_move(
|
||||
AppError::not_found(format!("Resource not found: {}", source_path))
|
||||
})?;
|
||||
|
||||
let dest_filename = destination_path.split('/').last().unwrap_or(&destination_path);
|
||||
let dest_filename = destination_path.split('/').next_back().unwrap_or(&destination_path);
|
||||
let dest_parent_path = if let Some(idx) = destination_path.rfind('/') {
|
||||
&destination_path[..idx]
|
||||
} else {
|
||||
@@ -854,7 +854,7 @@ async fn handle_copy(
|
||||
// Copy folder
|
||||
let recursive = depth != "0";
|
||||
|
||||
let dest_folder_name = destination_path.split('/').last().unwrap_or(&destination_path);
|
||||
let dest_folder_name = destination_path.split('/').next_back().unwrap_or(&destination_path);
|
||||
let dest_parent_path = if let Some(idx) = destination_path.rfind('/') {
|
||||
&destination_path[..idx]
|
||||
} else {
|
||||
@@ -908,7 +908,7 @@ async fn handle_copy(
|
||||
})?;
|
||||
|
||||
// Get destination parent path and filename
|
||||
let dest_filename = destination_path.split('/').last().unwrap_or(&destination_path);
|
||||
let dest_filename = destination_path.split('/').next_back().unwrap_or(&destination_path);
|
||||
let dest_parent_path = if let Some(idx) = destination_path.rfind('/') {
|
||||
&destination_path[..idx]
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user