fix: resolve clippy warnings and rustfmt issues for CI compliance

Fix all clippy lints (collapsible if, clone on Copy, needless borrow,
redundant bindings, unused params) and apply rustfmt across the codebase.
Update test mocks to match Uuid-based trait signatures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zjean
2026-03-09 14:34:07 +01:00
parent cf9fe82b5f
commit 18518bedaf
34 changed files with 370 additions and 336 deletions
@@ -17,11 +17,11 @@ use crate::infrastructure::services::jwt_service::JwtTokenService;
use crate::infrastructure::services::oidc_service::OidcService;
use crate::infrastructure::services::password_hasher::Argon2PasswordHasher;
use moka::sync::Cache;
use uuid::Uuid;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::RwLock;
use std::time::Duration;
use uuid::Uuid;
/// Result of a successful OIDC callback. The handler layer inspects this to
/// decide whether to redirect to the regular frontend or complete a Nextcloud
+2 -6
View File
@@ -448,11 +448,9 @@ impl BatchOperationService {
},
};
let uid = user_id;
let mut operation_stream = stream::iter(file_ids.into_iter().map(|file_id| {
let trash = trash_service.clone();
let uid = uid;
let uid = user_id;
async move {
let trash_result = trash.move_to_trash(&file_id, "file", uid).await;
@@ -513,11 +511,9 @@ impl BatchOperationService {
},
};
let uid = user_id;
let mut operation_stream = stream::iter(folder_ids.into_iter().map(|folder_id| {
let trash = trash_service.clone();
let uid = uid;
let uid = user_id;
async move {
let trash_result = trash.move_to_trash(&folder_id, "folder", uid).await;
+30 -15
View File
@@ -1,6 +1,6 @@
use chrono::Utc;
use uuid::Uuid;
use std::sync::Arc;
use uuid::Uuid;
use crate::application::dtos::address_book_dto::{
AddressBookDto, CreateAddressBookDto, ShareAddressBookDto, UnshareAddressBookDto,
@@ -296,8 +296,11 @@ impl AddressBookUseCase for ContactService {
// Check if user has write access to the address book
let address_book = self
.check_address_book_write_access(&id, &Uuid::parse_str(&update.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?)
.check_address_book_write_access(
&id,
&Uuid::parse_str(&update.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?,
)
.await?;
// Apply updates
@@ -526,9 +529,12 @@ impl ContactUseCase for ContactService {
.map_err(|_| DomainError::validation_error("Invalid address book ID format"))?;
// Check if user has write access to the address book
self.check_address_book_write_access(&address_book_id, &Uuid::parse_str(&dto.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?)
.await?;
self.check_address_book_write_access(
&address_book_id,
&Uuid::parse_str(&dto.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?,
)
.await?;
// Convert DTOs to domain entities
let email: Vec<Email> = dto
@@ -604,9 +610,12 @@ impl ContactUseCase for ContactService {
.map_err(|_| DomainError::validation_error("Invalid address book ID format"))?;
// Check if user has write access to the address book
self.check_address_book_write_access(&address_book_id, &Uuid::parse_str(&dto.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?)
.await?;
self.check_address_book_write_access(
&address_book_id,
&Uuid::parse_str(&dto.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?,
)
.await?;
// Parse vCard data
let mut contact = self.parse_vcard(&dto.vcard)?;
@@ -819,9 +828,12 @@ impl ContactUseCase for ContactService {
.map_err(|_| DomainError::validation_error("Invalid address book ID format"))?;
// Check if user has write access to the address book
self.check_address_book_write_access(&address_book_id, &Uuid::parse_str(&dto.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?)
.await?;
self.check_address_book_write_access(
&address_book_id,
&Uuid::parse_str(&dto.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?,
)
.await?;
let group = ContactGroup::new(address_book_id, dto.name);
@@ -845,9 +857,12 @@ impl ContactUseCase for ContactService {
.ok_or_else(|| DomainError::not_found("Contact group", "not found"))?;
// Check if user has write access to the address book
self.check_address_book_write_access(group.address_book_id(), &Uuid::parse_str(&update.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?)
.await?;
self.check_address_book_write_access(
group.address_book_id(),
&Uuid::parse_str(&update.user_id)
.map_err(|_| DomainError::validation_error("Invalid user ID format"))?,
)
.await?;
// Update the group
let updated_group = ContactGroup::from_raw(
@@ -178,10 +178,10 @@ impl FileManagementUseCase for FileManagementService {
async fn delete_file(&self, id: &str) -> Result<(), DomainError> {
self.file_repository.delete_file(id).await?;
// Best-effort thumbnail cleanup
if let Some(thumb) = &self.thumbnail_service {
if let Err(e) = thumb.delete_thumbnails(id).await {
warn!("Failed to delete thumbnails for file {}: {}", id, e);
}
if let Some(thumb) = &self.thumbnail_service
&& let Err(e) = thumb.delete_thumbnails(id).await
{
warn!("Failed to delete thumbnails for file {}: {}", id, e);
}
Ok(())
}
@@ -223,10 +223,10 @@ impl FileManagementUseCase for FileManagementService {
warn!("Permanently deleting file: {}", id);
self.file_repository.delete_file(id).await?;
// Best-effort thumbnail cleanup
if let Some(thumb) = &self.thumbnail_service {
if let Err(e) = thumb.delete_thumbnails(id).await {
warn!("Failed to delete thumbnails for file {}: {}", id, e);
}
if let Some(thumb) = &self.thumbnail_service
&& let Err(e) = thumb.delete_thumbnails(id).await
{
warn!("Failed to delete thumbnails for file {}: {}", id, e);
}
info!("File permanently deleted: {}", id);
@@ -9,6 +9,7 @@ use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::sync::Mutex;
use uuid::Uuid;
use crate::application::ports::storage_ports::{FileReadPort, FileWritePort};
use crate::common::errors::DomainError;
@@ -22,7 +23,7 @@ use crate::domain::services::path_service::StoragePath;
/// A simple in-memory mock that maps (file_id → (File, owner_id)).
struct MockFileReadPort {
/// file_id → (File, owner_id)
files: Mutex<HashMap<String, (File, String)>>,
files: Mutex<HashMap<String, (File, Uuid)>>,
}
impl MockFileReadPort {
@@ -33,7 +34,7 @@ impl MockFileReadPort {
}
/// Insert a test file owned by `owner_id`.
fn insert(&self, id: &str, name: &str, owner_id: &str) {
fn insert(&self, id: &str, name: &str, owner_id: Uuid) {
let file = File::new(
id.to_string(),
name.to_string(),
@@ -46,7 +47,7 @@ impl MockFileReadPort {
self.files
.lock()
.unwrap()
.insert(id.to_string(), (file, owner_id.to_string()));
.insert(id.to_string(), (file, owner_id));
}
}
@@ -59,10 +60,10 @@ impl FileReadPort for MockFileReadPort {
.ok_or_else(|| DomainError::not_found("File", id.to_string()))
}
async fn get_file_for_owner(&self, id: &str, owner_id: &str) -> Result<File, DomainError> {
async fn get_file_for_owner(&self, id: &str, owner_id: Uuid) -> Result<File, DomainError> {
let files = self.files.lock().unwrap();
match files.get(id) {
Some((file, actual_owner)) if actual_owner == owner_id => Ok(file.clone()),
Some((file, actual_owner)) if *actual_owner == owner_id => Ok(file.clone()),
// Return NotFound regardless — do not leak existence
_ => Err(DomainError::not_found("File", id.to_string())),
}
@@ -104,7 +105,7 @@ impl FileReadPort for MockFileReadPort {
&self,
_folder_id: Option<&str>,
_criteria: &crate::application::dtos::search_dto::SearchCriteriaDto,
_user_id: &str,
_user_id: Uuid,
) -> Result<(Vec<File>, usize), DomainError> {
Ok((Vec::new(), 0))
}
@@ -113,7 +114,7 @@ impl FileReadPort for MockFileReadPort {
&self,
_folder_id: Option<&str>,
_criteria: &crate::application::dtos::search_dto::SearchCriteriaDto,
_user_id: &str,
_user_id: Uuid,
) -> Result<usize, DomainError> {
Ok(0)
}
@@ -248,20 +249,23 @@ impl FileWritePort for MockFileWritePort {
#[tokio::test]
async fn get_file_for_owner_returns_file_for_correct_owner() {
let alice_id = Uuid::new_v4();
let repo = MockFileReadPort::new();
repo.insert("file-1", "secret.txt", "alice");
repo.insert("file-1", "secret.txt", alice_id);
let result = repo.get_file_for_owner("file-1", "alice").await;
let result = repo.get_file_for_owner("file-1", alice_id).await;
assert!(result.is_ok(), "owner should be able to read own file");
assert_eq!(result.unwrap().id(), "file-1");
}
#[tokio::test]
async fn get_file_for_owner_rejects_wrong_owner() {
let alice_id = Uuid::new_v4();
let bob_id = Uuid::new_v4();
let repo = MockFileReadPort::new();
repo.insert("file-1", "secret.txt", "alice");
repo.insert("file-1", "secret.txt", alice_id);
let result = repo.get_file_for_owner("file-1", "bob").await;
let result = repo.get_file_for_owner("file-1", bob_id).await;
assert!(result.is_err(), "non-owner should be rejected");
// Must be NotFound, NOT Forbidden — avoids leaking existence
@@ -276,20 +280,23 @@ async fn get_file_for_owner_rejects_wrong_owner() {
#[tokio::test]
async fn get_file_for_owner_returns_not_found_for_missing_file() {
let alice_id = Uuid::new_v4();
let repo = MockFileReadPort::new();
let result = repo.get_file_for_owner("nonexistent", "alice").await;
let result = repo.get_file_for_owner("nonexistent", alice_id).await;
assert!(result.is_err());
}
#[tokio::test]
async fn verify_file_owner_uses_default_impl() {
let alice_id = Uuid::new_v4();
let bob_id = Uuid::new_v4();
let repo = MockFileReadPort::new();
repo.insert("file-1", "secret.txt", "alice");
repo.insert("file-1", "secret.txt", alice_id);
// Default impl delegates to get_file_for_owner and maps to ()
assert!(repo.verify_file_owner("file-1", "alice").await.is_ok());
assert!(repo.verify_file_owner("file-1", "bob").await.is_err());
assert!(repo.verify_file_owner("file-1", alice_id).await.is_ok());
assert!(repo.verify_file_owner("file-1", bob_id).await.is_err());
}
// ═══════════════════════════════════════════════════════════════════════════
@@ -310,15 +317,17 @@ async fn verify_file_owner_uses_default_impl() {
async fn verify_file_owner_delegates_to_read_port() {
// This test verifies the FileReadPort contract that verify_file_owner
// returns Ok for the correct owner and Err for others.
let user_id = Uuid::new_v4();
let attacker_id = Uuid::new_v4();
let read = MockFileReadPort::new();
read.insert("abc-123", "report.pdf", "user-42");
read.insert("abc-123", "report.pdf", user_id);
// Same user → Ok
let ok = read.verify_file_owner("abc-123", "user-42").await;
let ok = read.verify_file_owner("abc-123", user_id).await;
assert!(ok.is_ok(), "correct owner should pass verify_file_owner");
// Different user → Err
let err = read.verify_file_owner("abc-123", "attacker-99").await;
let err = read.verify_file_owner("abc-123", attacker_id).await;
assert!(err.is_err(), "wrong owner should fail verify_file_owner");
}
@@ -326,15 +335,17 @@ async fn verify_file_owner_delegates_to_read_port() {
async fn owned_methods_require_ownership_check_first() {
// Simulate what the _owned methods do: verify_owner then delegate.
// We test with the mock read port to prove the sequence.
let owner_id = Uuid::new_v4();
let attacker_id = Uuid::new_v4();
let read = MockFileReadPort::new();
read.insert("file-1", "data.csv", "owner-a");
read.insert("file-1", "data.csv", owner_id);
// Step 1: verify_owner for correct owner → Ok
let step1 = read.verify_file_owner("file-1", "owner-a").await;
let step1 = read.verify_file_owner("file-1", owner_id).await;
assert!(step1.is_ok());
// Step 2: verify_owner for attacker → Err, so the move/rename never executes
let step2 = read.verify_file_owner("file-1", "attacker").await;
let step2 = read.verify_file_owner("file-1", attacker_id).await;
assert!(step2.is_err());
}
@@ -347,18 +358,20 @@ use crate::common::stubs::StubFileManagementUseCase;
#[tokio::test]
async fn stub_move_file_owned_returns_ok() {
let user_id = Uuid::new_v4();
let stub = StubFileManagementUseCase;
let result = stub
.move_file_owned("file-1", "user-1", Some("folder-2".to_string()))
.move_file_owned("file-1", user_id, Some("folder-2".to_string()))
.await;
assert!(result.is_ok(), "stub should return Ok for move_file_owned");
}
#[tokio::test]
async fn stub_rename_file_owned_returns_ok() {
let user_id = Uuid::new_v4();
let stub = StubFileManagementUseCase;
let result = stub
.rename_file_owned("file-1", "user-1", "new-name.txt")
.rename_file_owned("file-1", user_id, "new-name.txt")
.await;
assert!(
result.is_ok(),
@@ -371,16 +384,18 @@ use crate::common::stubs::StubFileRetrievalUseCase;
#[tokio::test]
async fn stub_get_file_owned_returns_ok() {
let user_id = Uuid::new_v4();
let stub = StubFileRetrievalUseCase;
let result = stub.get_file_owned("file-1", "user-1").await;
let result = stub.get_file_owned("file-1", user_id).await;
assert!(result.is_ok(), "stub should return Ok for get_file_owned");
}
#[tokio::test]
async fn stub_get_file_optimized_owned_returns_ok() {
let user_id = Uuid::new_v4();
let stub = StubFileRetrievalUseCase;
let result = stub
.get_file_optimized_owned("file-1", "user-1", true, false)
.get_file_optimized_owned("file-1", user_id, true, false)
.await;
assert!(
result.is_ok(),
+6 -6
View File
@@ -806,7 +806,7 @@ mod tests {
&self,
_folder_id: Option<&str>,
_criteria: &crate::application::dtos::search_dto::SearchCriteriaDto,
_user_id: &str,
_user_id: Uuid,
) -> Result<(Vec<crate::domain::entities::file::File>, usize), DomainError> {
Ok((Vec::new(), 0))
}
@@ -815,7 +815,7 @@ mod tests {
&self,
_folder_id: Option<&str>,
_criteria: &crate::application::dtos::search_dto::SearchCriteriaDto,
_user_id: &str,
_user_id: Uuid,
) -> Result<usize, DomainError> {
Ok(0)
}
@@ -839,7 +839,7 @@ mod tests {
async fn get_file_for_owner(
&self,
id: &str,
_owner_id: &str,
_owner_id: Uuid,
) -> Result<crate::domain::entities::file::File, DomainError> {
self.get_file(id).await
}
@@ -891,7 +891,7 @@ mod tests {
async fn list_folders_by_owner(
&self,
_parent_id: Option<&str>,
_owner_id: &str,
_owner_id: Uuid,
) -> Result<Vec<crate::domain::entities::folder::Folder>, DomainError> {
unimplemented!()
}
@@ -910,7 +910,7 @@ mod tests {
async fn list_folders_by_owner_paginated(
&self,
_parent_id: Option<&str>,
_owner_id: &str,
_owner_id: Uuid,
_offset: usize,
_limit: usize,
_include_total: bool,
@@ -971,7 +971,7 @@ mod tests {
async fn create_home_folder(
&self,
_user_id: &str,
_user_id: Uuid,
_name: String,
) -> Result<crate::domain::entities::folder::Folder, DomainError> {
unimplemented!()
+4 -4
View File
@@ -566,10 +566,10 @@ impl TrashUseCase for TrashService {
// Best-effort thumbnail cleanup — thumbnails are cache
// artifacts, so failure must not block file deletion.
if let Some(thumb) = &self.thumbnail_service {
if let Err(e) = thumb.delete_thumbnails(&file_id).await {
warn!("Failed to delete thumbnails for file {}: {}", file_id, e);
}
if let Some(thumb) = &self.thumbnail_service
&& let Err(e) = thumb.delete_thumbnails(&file_id).await
{
warn!("Failed to delete thumbnails for file {}: {}", file_id, e);
}
}
TrashedItemType::Folder => {
+33 -43
View File
@@ -61,10 +61,8 @@ where
FW: FileWritePort,
FoR: FolderRepository,
{
async fn get_trash_items(&self, user_id: &str) -> Result<Vec<TrashedItemDto>> {
let user_uuid = Uuid::parse_str(user_id)
.map_err(|e| DomainError::validation_error(format!("Invalid user ID: {}", e)))?;
let items = self.trash_repository.get_trash_items(&user_uuid).await?;
async fn get_trash_items(&self, user_id: Uuid) -> Result<Vec<TrashedItemDto>> {
let items = self.trash_repository.get_trash_items(&user_id).await?;
Ok(items
.into_iter()
.map(|item| {
@@ -85,11 +83,9 @@ where
.collect())
}
async fn move_to_trash(&self, item_id: &str, item_type: &str, user_id: &str) -> Result<()> {
async fn move_to_trash(&self, item_id: &str, item_type: &str, user_id: Uuid) -> Result<()> {
let item_uuid = Uuid::parse_str(item_id)
.map_err(|e| DomainError::validation_error(format!("Invalid item ID: {}", e)))?;
let user_uuid = Uuid::parse_str(user_id)
.map_err(|e| DomainError::validation_error(format!("Invalid user ID: {}", e)))?;
match item_type {
"file" => {
@@ -103,7 +99,7 @@ where
let original_path = file.storage_path().to_string();
let trashed_item = TrashedItem::new(
item_uuid,
user_uuid,
user_id,
TrashedItemType::File,
file.name().to_string(),
original_path,
@@ -145,7 +141,7 @@ where
let original_path = folder.storage_path().to_string();
let trashed_item = TrashedItem::new(
item_uuid,
user_uuid,
user_id,
TrashedItemType::Folder,
folder.name().to_string(),
original_path,
@@ -179,15 +175,13 @@ where
}
}
async fn restore_item(&self, trash_id: &str, user_id: &str) -> Result<()> {
async fn restore_item(&self, trash_id: &str, user_id: Uuid) -> Result<()> {
let trash_uuid = Uuid::parse_str(trash_id)
.map_err(|e| DomainError::validation_error(format!("Invalid trash ID: {}", e)))?;
let user_uuid = Uuid::parse_str(user_id)
.map_err(|e| DomainError::validation_error(format!("Invalid user ID: {}", e)))?;
let item = self
.trash_repository
.get_trash_item(&trash_uuid, &user_uuid)
.get_trash_item(&trash_uuid, &user_id)
.await?;
match item {
Some(item) => {
@@ -228,7 +222,7 @@ where
}
}
self.trash_repository
.restore_from_trash(&trash_uuid, &user_uuid)
.restore_from_trash(&trash_uuid, &user_id)
.await
.map_err(|e| {
DomainError::new(
@@ -243,15 +237,13 @@ where
}
}
async fn delete_permanently(&self, trash_id: &str, user_id: &str) -> Result<()> {
async fn delete_permanently(&self, trash_id: &str, user_id: Uuid) -> Result<()> {
let trash_uuid = Uuid::parse_str(trash_id)
.map_err(|e| DomainError::validation_error(format!("Invalid trash ID: {}", e)))?;
let user_uuid = Uuid::parse_str(user_id)
.map_err(|e| DomainError::validation_error(format!("Invalid user ID: {}", e)))?;
let item = self
.trash_repository
.get_trash_item(&trash_uuid, &user_uuid)
.get_trash_item(&trash_uuid, &user_id)
.await?;
match item {
Some(item) => {
@@ -287,7 +279,7 @@ where
}
}
self.trash_repository
.delete_permanently(&trash_uuid, &user_uuid)
.delete_permanently(&trash_uuid, &user_id)
.await
.map_err(|e| {
DomainError::new(
@@ -302,10 +294,8 @@ where
}
}
async fn empty_trash(&self, user_id: &str) -> Result<()> {
let user_uuid = Uuid::parse_str(user_id)
.map_err(|e| DomainError::validation_error(format!("Invalid user ID: {}", e)))?;
self.trash_repository.clear_trash(&user_uuid).await
async fn empty_trash(&self, user_id: Uuid) -> Result<()> {
self.trash_repository.clear_trash(&user_id).await
}
}
@@ -492,7 +482,7 @@ impl FileReadPort for MockFileRepository {
&self,
_folder_id: Option<&str>,
_criteria: &crate::application::dtos::search_dto::SearchCriteriaDto,
_user_id: &str,
_user_id: Uuid,
) -> std::result::Result<(Vec<File>, usize), DomainError> {
Ok((Vec::new(), 0))
}
@@ -501,7 +491,7 @@ impl FileReadPort for MockFileRepository {
&self,
_folder_id: Option<&str>,
_criteria: &crate::application::dtos::search_dto::SearchCriteriaDto,
_user_id: &str,
_user_id: Uuid,
) -> std::result::Result<usize, DomainError> {
Ok(0)
}
@@ -519,7 +509,7 @@ impl FileReadPort for MockFileRepository {
async fn get_file_for_owner(
&self,
id: &str,
_owner_id: &str,
_owner_id: Uuid,
) -> std::result::Result<File, DomainError> {
// In this mock, ignore ownership — trash tests don't focus on ownership
self.get_file(id).await
@@ -697,7 +687,7 @@ impl FolderRepository for MockFolderRepository {
async fn list_folders_by_owner(
&self,
_parent_id: Option<&str>,
_owner_id: &str,
_owner_id: Uuid,
) -> std::result::Result<Vec<Folder>, DomainError> {
Ok(vec![])
}
@@ -715,7 +705,7 @@ impl FolderRepository for MockFolderRepository {
async fn list_folders_by_owner_paginated(
&self,
_parent_id: Option<&str>,
_owner_id: &str,
_owner_id: Uuid,
_offset: usize,
_limit: usize,
_include_total: bool,
@@ -799,7 +789,7 @@ impl FolderRepository for MockFolderRepository {
async fn create_home_folder(
&self,
_user_id: &str,
_user_id: Uuid,
_name: String,
) -> std::result::Result<Folder, DomainError> {
Ok(Folder::default())
@@ -839,18 +829,18 @@ mod tests {
let file_id = "550e8400-e29b-41d4-a716-446655440000";
let user_id = "550e8400-e29b-41d4-a716-446655440001";
let user_uuid = Uuid::parse_str(user_id).unwrap();
// Add a test file to the repository
file_repo.add_test_file(file_id, "test.txt", "/test/path/test.txt");
// Act
let result = service.move_to_trash(file_id, "file", user_id).await;
let result = service.move_to_trash(file_id, "file", user_uuid).await;
// Assert
assert!(result.is_ok(), "Moving file to trash failed: {:?}", result);
// Verify the file is in trash
let user_uuid = Uuid::parse_str(user_id).unwrap();
let trash_items = trash_repo.get_trash_items(&user_uuid).await.unwrap();
assert_eq!(
@@ -913,12 +903,13 @@ mod tests {
let folder_id = "550e8400-e29b-41d4-a716-446655440002";
let user_id = "550e8400-e29b-41d4-a716-446655440001";
let user_uuid = Uuid::parse_str(user_id).unwrap();
// Add a test folder to the repository
folder_repo.add_test_folder(folder_id, "test_folder", "/test/path/test_folder");
// Act
let result = service.move_to_trash(folder_id, "folder", user_id).await;
let result = service.move_to_trash(folder_id, "folder", user_uuid).await;
// Assert
assert!(
@@ -928,7 +919,6 @@ mod tests {
);
// Verify the folder is in trash
let user_uuid = Uuid::parse_str(user_id).unwrap();
let trash_items = trash_repo.get_trash_items(&user_uuid).await.unwrap();
assert_eq!(
@@ -978,22 +968,22 @@ mod tests {
let file_id = "550e8400-e29b-41d4-a716-446655440000";
let user_id = "550e8400-e29b-41d4-a716-446655440001";
let user_uuid = Uuid::parse_str(user_id).unwrap();
let file_path = "/test/path/test.txt";
// Add a test file and move it to trash
file_repo.add_test_file(file_id, "test.txt", file_path);
service
.move_to_trash(file_id, "file", user_id)
.move_to_trash(file_id, "file", user_uuid)
.await
.unwrap();
// Get the trash item ID
let user_uuid = Uuid::parse_str(user_id).unwrap();
let trash_items = trash_repo.get_trash_items(&user_uuid).await.unwrap();
let trash_id = trash_items[0].id().to_string();
// Act
let result = service.restore_item(&trash_id, user_id).await;
let result = service.restore_item(&trash_id, user_uuid).await;
// Assert
assert!(
@@ -1048,21 +1038,21 @@ mod tests {
let file_id = "550e8400-e29b-41d4-a716-446655440000";
let user_id = "550e8400-e29b-41d4-a716-446655440001";
let user_uuid = Uuid::parse_str(user_id).unwrap();
// Add a test file and move it to trash
file_repo.add_test_file(file_id, "test.txt", "/test/path/test.txt");
service
.move_to_trash(file_id, "file", user_id)
.move_to_trash(file_id, "file", user_uuid)
.await
.unwrap();
// Get the trash item ID
let user_uuid = Uuid::parse_str(user_id).unwrap();
let trash_items = trash_repo.get_trash_items(&user_uuid).await.unwrap();
let trash_id = trash_items[0].id().to_string();
// Act
let result = service.delete_permanently(&trash_id, user_id).await;
let result = service.delete_permanently(&trash_id, user_uuid).await;
// Assert
assert!(
@@ -1116,6 +1106,7 @@ mod tests {
);
let user_id = "550e8400-e29b-41d4-a716-446655440001";
let user_uuid = Uuid::parse_str(user_id).unwrap();
// Add multiple files and folders to trash
let file_ids = [
@@ -1136,7 +1127,7 @@ mod tests {
&format!("/test/path/test{}.txt", i),
);
service
.move_to_trash(file_id, "file", user_id)
.move_to_trash(file_id, "file", user_uuid)
.await
.unwrap();
}
@@ -1148,18 +1139,17 @@ mod tests {
&format!("/test/path/folder{}", i),
);
service
.move_to_trash(folder_id, "folder", user_id)
.move_to_trash(folder_id, "folder", user_uuid)
.await
.unwrap();
}
// Verify items are in trash
let user_uuid = Uuid::parse_str(user_id).unwrap();
let trash_items = trash_repo.get_trash_items(&user_uuid).await.unwrap();
assert_eq!(trash_items.len(), 4, "Should have 4 items in trash");
// Act
let result = service.empty_trash(user_id).await;
let result = service.empty_trash(user_uuid).await;
// Assert
assert!(result.is_ok(), "Emptying trash failed: {:?}", result);