From a7de63d80f56fdff2cb269bab2c2bf669103a420 Mon Sep 17 00:00:00 2001 From: zjean Date: Wed, 4 Mar 2026 20:58:23 +0100 Subject: [PATCH] fix: resolve clippy warnings (unused mut, from_str, result_large_err) Co-Authored-By: Claude Opus 4.6 --- .../services/idor_protection_test.rs | 116 +++++++++++++++++- src/application/services/mod.rs | 2 +- src/interfaces/nextcloud/routes.rs | 1 + src/interfaces/nextcloud/webdav_handler.rs | 6 +- 4 files changed, 120 insertions(+), 5 deletions(-) diff --git a/src/application/services/idor_protection_test.rs b/src/application/services/idor_protection_test.rs index 535fc4f2..a43dfb88 100644 --- a/src/application/services/idor_protection_test.rs +++ b/src/application/services/idor_protection_test.rs @@ -6,10 +6,11 @@ use bytes::Bytes; use futures::Stream; use std::collections::HashMap; +use std::path::{Path, PathBuf}; use std::pin::Pin; use std::sync::Mutex; -use crate::application::ports::storage_ports::FileReadPort; +use crate::application::ports::storage_ports::{FileReadPort, FileWritePort}; use crate::common::errors::DomainError; use crate::domain::entities::file::File; use crate::domain::services::path_service::StoragePath; @@ -117,6 +118,10 @@ impl FileReadPort for MockFileReadPort { Ok(0) } + async fn get_folder_id_by_path(&self, _folder_path: &str) -> Result { + unimplemented!() + } + async fn stream_files_in_subtree( &self, _folder_id: &str, @@ -125,6 +130,115 @@ impl FileReadPort for MockFileReadPort { } } +/// Minimal mock write port — only `move_file` and `rename_file` need real logic. +struct MockFileWritePort { + files: Mutex>, +} + +impl MockFileWritePort { + fn new() -> Self { + Self { + files: Mutex::new(HashMap::new()), + } + } + + fn insert(&self, id: &str, name: &str) { + let file = File::new( + id.to_string(), + name.to_string(), + StoragePath::from_string(&format!("/{}", name)), + 42, + "text/plain".to_string(), + None, + ) + .unwrap(); + self.files.lock().unwrap().insert(id.to_string(), file); + } +} + +impl FileWritePort for MockFileWritePort { + async fn save_file_from_temp( + &self, + _name: String, + _folder_id: Option, + _content_type: String, + _temp_path: &Path, + _size: u64, + _pre_computed_hash: Option, + ) -> Result { + unimplemented!() + } + + async fn move_file( + &self, + file_id: &str, + _target_folder_id: Option, + ) -> Result { + let files = self.files.lock().unwrap(); + files + .get(file_id) + .cloned() + .ok_or_else(|| DomainError::not_found("File", file_id.to_string())) + } + + async fn rename_file(&self, file_id: &str, _new_name: &str) -> Result { + let files = self.files.lock().unwrap(); + files + .get(file_id) + .cloned() + .ok_or_else(|| DomainError::not_found("File", file_id.to_string())) + } + + async fn delete_file(&self, _id: &str) -> Result<(), DomainError> { + Ok(()) + } + + async fn update_file_content_from_temp( + &self, + _file_id: &str, + _temp_path: &Path, + _size: u64, + _content_type: Option, + _pre_computed_hash: Option, + ) -> Result<(), DomainError> { + Ok(()) + } + + async fn register_file_deferred( + &self, + _name: String, + _folder_id: Option, + _content_type: String, + _size: u64, + ) -> Result<(File, PathBuf), DomainError> { + unimplemented!() + } + + async fn copy_file( + &self, + _file_id: &str, + _target_folder_id: Option, + ) -> Result { + unimplemented!() + } + + async fn move_to_trash(&self, _file_id: &str) -> Result<(), DomainError> { + Ok(()) + } + + async fn restore_from_trash( + &self, + _file_id: &str, + _original_path: &str, + ) -> Result<(), DomainError> { + Ok(()) + } + + async fn delete_file_permanently(&self, _file_id: &str) -> Result<(), DomainError> { + Ok(()) + } +} + // ═══════════════════════════════════════════════════════════════════════════ // Tests — FileReadPort::get_file_for_owner (Repository layer, Solution C) // ═══════════════════════════════════════════════════════════════════════════ diff --git a/src/application/services/mod.rs b/src/application/services/mod.rs index c6a0a146..1fc27b90 100644 --- a/src/application/services/mod.rs +++ b/src/application/services/mod.rs @@ -24,7 +24,7 @@ pub mod wopi_token_service; #[cfg(test)] mod idor_protection_test; -#[cfg(all(test, integration_tests))] +#[cfg(test)] mod trash_service_test; // Re-exportar para facilitar acceso diff --git a/src/interfaces/nextcloud/routes.rs b/src/interfaces/nextcloud/routes.rs index 6443085f..70fcb037 100644 --- a/src/interfaces/nextcloud/routes.rs +++ b/src/interfaces/nextcloud/routes.rs @@ -155,6 +155,7 @@ pub fn nextcloud_routes_with_state(state: Arc) -> Router // ──────────────── Handler glue ──────────────── /// Reject requests where the URL `{user}` doesn't match the authenticated user. +#[allow(clippy::result_large_err)] fn verify_url_user(url_user: &str, auth_user: &CurrentUser) -> Result<(), Response> { if url_user != auth_user.username { Err(StatusCode::FORBIDDEN.into_response()) diff --git a/src/interfaces/nextcloud/webdav_handler.rs b/src/interfaces/nextcloud/webdav_handler.rs index 2545d464..cc5fd9ea 100644 --- a/src/interfaces/nextcloud/webdav_handler.rs +++ b/src/interfaces/nextcloud/webdav_handler.rs @@ -480,7 +480,7 @@ async fn handle_put( .unwrap_or("application/octet-stream") .to_string(); - let oc_mtime = req + let _oc_mtime = req .headers() .get("x-oc-mtime") .and_then(|v| v.to_str().ok()) @@ -507,7 +507,7 @@ async fn handle_put( // Re-fetch for etag. if let Ok(updated) = file_service.get_file_by_path(&internal_path).await { - let mut builder = Response::builder() + let builder = Response::builder() .status(StatusCode::NO_CONTENT) .header(header::ETAG, format!("\"{}\"", updated.id)) .header("oc-etag", format!("\"{}\"", updated.id)); @@ -534,7 +534,7 @@ async fn handle_put( .await .map_err(|e| AppError::internal_error(format!("Failed to create file: {}", e)))?; - let mut builder = Response::builder() + let builder = Response::builder() .status(StatusCode::CREATED) .header(header::ETAG, format!("\"{}\"", file_dto.id)) .header("oc-etag", format!("\"{}\"", file_dto.id));