refactor(server): file_management_service: move all method without owner check into private, add folder_ports

This commit is contained in:
Edouard Vanbelle
2026-05-20 15:39:53 +02:00
parent ac42a6d3cc
commit dfb082fdf4
17 changed files with 318 additions and 328 deletions
+12 -6
View File
@@ -117,10 +117,10 @@ impl FileHandler {
// ── SECURITY: Verify folder ownership before upload (IDOR V-03 fix) ──
if let Some(ref fid) = folder_id {
use crate::application::ports::inbound::FolderUseCase;
use crate::application::ports::folder_ports::FolderUseCase;
let folder_service = &state.applications.folder_service;
if folder_service
.get_folder_owned(fid, auth_user.id)
.get_folder_with_perms(fid, auth_user.id)
.await
.is_err()
{
@@ -875,7 +875,7 @@ impl FileHandler {
// Auth required: trash-first with dedup cleanup + ownership verification
let result = mgmt
.delete_with_cleanup(&id, auth_user.id)
.delete_and_cleanup_with_perms(&id, auth_user.id)
.await
.map(|was_trashed| {
if was_trashed {
@@ -917,7 +917,10 @@ impl FileHandler {
tracing::info!("Renaming file {} to \"{}\"", id, new_name);
let mgmt = &state.applications.file_management_service;
match mgmt.rename_file_owned(&id, auth_user.id, &new_name).await {
match mgmt
.rename_file_with_perms(&id, auth_user.id, &new_name)
.await
{
Ok(file_dto) => (StatusCode::OK, Json(file_dto)).into_response(),
Err(err) => AppError::from(err).into_response(),
}
@@ -935,7 +938,7 @@ impl FileHandler {
let mgmt = &state.applications.file_management_service;
match mgmt
.move_file_owned(&id, auth_user.id, payload.folder_id)
.move_file_with_perms(&id, auth_user.id, payload.folder_id)
.await
{
Ok(file) => (StatusCode::OK, Json(file)).into_response(),
@@ -956,7 +959,10 @@ impl FileHandler {
.map(|s| s.to_string());
let mgmt = &state.applications.file_management_service;
match mgmt.move_file_owned(&id, auth_user.id, folder_id).await {
match mgmt
.move_file_with_perms(&id, auth_user.id, folder_id)
.await
{
Ok(file_dto) => (StatusCode::OK, Json(file_dto)).into_response(),
Err(err) => AppError::from(err).into_response(),
}
@@ -16,7 +16,7 @@ use crate::application::dtos::folder_dto::{
use crate::application::dtos::folder_listing_dto::FolderListingDto;
use crate::application::dtos::pagination::PaginationRequestDto;
use crate::application::ports::file_ports::FileRetrievalUseCase;
use crate::application::ports::inbound::FolderUseCase;
use crate::application::ports::folder_ports::FolderUseCase;
use crate::application::ports::trash_ports::TrashUseCase;
use crate::application::services::folder_service::FolderService;
use crate::common::di::AppState as GlobalAppState;
@@ -76,7 +76,7 @@ impl FolderHandler {
}
}
match service.create_folder(dto, auth_user.id).await {
match service.create_folder_with_perms(dto, auth_user.id).await {
Ok(folder) => (StatusCode::CREATED, Json(folder)).into_response(),
Err(err) => AppError::from(err).into_response(),
}
@@ -244,7 +244,10 @@ impl FolderHandler {
Path(id): Path<String>,
Json(dto): Json<RenameFolderDto>,
) -> impl IntoResponse {
match service.rename_folder(&id, dto, auth_user.id).await {
match service
.rename_folder_with_perms(&id, dto, auth_user.id)
.await
{
Ok(folder) => (StatusCode::OK, Json(folder)).into_response(),
Err(err) => AppError::from(err).into_response(),
}
@@ -257,7 +260,7 @@ impl FolderHandler {
Path(id): Path<String>,
Json(dto): Json<MoveFolderDto>,
) -> impl IntoResponse {
match service.move_folder(&id, dto, auth_user.id).await {
match service.move_folder_with_perms(&id, dto, auth_user.id).await {
Ok(folder) => (StatusCode::OK, Json(folder)).into_response(),
Err(err) => AppError::from(err).into_response(),
}
@@ -269,7 +272,7 @@ impl FolderHandler {
auth_user: AuthUser,
Path(id): Path<String>,
) -> impl IntoResponse {
match service.delete_folder(&id, auth_user.id).await {
match service.delete_folder_with_perms(&id, auth_user.id).await {
Ok(_) => StatusCode::NO_CONTENT.into_response(),
Err(err) => AppError::from(err).into_response(),
}
@@ -304,7 +307,7 @@ impl FolderHandler {
// Fallback to permanent delete if trash is unavailable or failed
let folder_service = &state.applications.folder_service;
match folder_service.delete_folder(&id, user_id).await {
match folder_service.delete_folder_with_perms(&id, user_id).await {
Ok(_) => {
tracing::info!("Folder permanently deleted: {}", id);
StatusCode::NO_CONTENT.into_response()
+22 -20
View File
@@ -22,7 +22,7 @@ use crate::application::dtos::file_dto::FileDto;
use crate::application::dtos::folder_dto::FolderDto;
use crate::application::ports::file_ports::FileRetrievalUseCase;
use crate::application::ports::file_ports::{FileManagementUseCase, FileUploadUseCase};
use crate::application::ports::inbound::FolderUseCase;
use crate::application::ports::folder_ports::FolderUseCase;
use crate::application::ports::storage_ports::StorageUsagePort;
use crate::application::services::file_retrieval_service::FileRetrievalService;
use crate::application::services::folder_service::FolderService;
@@ -1046,7 +1046,7 @@ async fn handle_mkcol(
// their proper HTTP status codes (was: blanket 500 swallowed
// ownership-rejection NotFound from verify_owner).
let created = folder_service
.create_folder(create_dto, user.id)
.create_folder_with_perms(create_dto, user.id)
.await
.map_err(AppError::from)?;
parent_id = Some(created.id);
@@ -1092,7 +1092,7 @@ async fn handle_delete(
match resolver.resolve_path_for_user(&path, user.id).await {
Ok(ResolvedResource::Folder(folder)) => {
folder_service
.delete_folder(&folder.id, user.id)
.delete_folder_with_perms(&folder.id, user.id)
.await
.map_err(|e| {
AppError::internal_error(format!("Failed to delete folder: {}", e))
@@ -1100,7 +1100,7 @@ async fn handle_delete(
}
Ok(ResolvedResource::File(file)) => {
file_management_service
.delete_file(&file.id)
.delete_file_with_perms(&file.id, user.id)
.await
.map_err(|e| {
AppError::internal_error(format!("Failed to delete file: {}", e))
@@ -1115,7 +1115,7 @@ async fn handle_delete(
if let Ok(folder) = folder_result {
assert_owner(folder.owner_id.as_deref(), &user.id.to_string(), &path)?;
folder_service
.delete_folder(&folder.id, user.id)
.delete_folder_with_perms(&folder.id, user.id)
.await
.map_err(|e| AppError::internal_error(format!("Failed to delete folder: {}", e)))?;
} else {
@@ -1126,7 +1126,7 @@ async fn handle_delete(
assert_owner(file.owner_id.as_deref(), &user.id.to_string(), &path)?;
file_management_service
.delete_file(&file.id)
.delete_file_with_perms(&file.id, user.id)
.await
.map_err(|e| AppError::internal_error(format!("Failed to delete file: {}", e)))?;
}
@@ -1248,7 +1248,7 @@ async fn handle_move(
};
folder_service
.move_folder(&folder.id, move_dto, user.id)
.move_folder_with_perms(&folder.id, move_dto, user.id)
.await
.map_err(AppError::from)?;
@@ -1257,7 +1257,7 @@ async fn handle_move(
name: dest_folder_name.to_string(),
};
folder_service
.rename_folder(&folder.id, rename_dto, user.id)
.rename_folder_with_perms(&folder.id, rename_dto, user.id)
.await
.map_err(AppError::from)?;
}
@@ -1291,13 +1291,13 @@ async fn handle_move(
)?;
}
file_management_service
.move_file(&file.id, Some(dest_parent_path.to_string()))
.move_file_with_perms(&file.id, user.id, Some(dest_parent_path.to_string()))
.await
.map_err(AppError::from)?;
}
if file.name != dest_filename {
file_management_service
.rename_file(&file.id, dest_filename)
.rename_file_with_perms(&file.id, user.id, dest_filename)
.await
.map_err(AppError::from)?;
}
@@ -1349,7 +1349,7 @@ async fn handle_move(
};
folder_service
.move_folder(&folder.id, move_dto, user.id)
.move_folder_with_perms(&folder.id, move_dto, user.id)
.await
.map_err(|e| AppError::internal_error(format!("Failed to move folder: {}", e)))?;
@@ -1358,7 +1358,7 @@ async fn handle_move(
name: dest_folder_name.to_string(),
};
folder_service
.rename_folder(&folder.id, rename_dto, user.id)
.rename_folder_with_perms(&folder.id, rename_dto, user.id)
.await
.map_err(AppError::from)?;
}
@@ -1398,13 +1398,13 @@ async fn handle_move(
)?;
}
file_management_service
.move_file(&file.id, Some(dest_parent_path.to_string()))
.move_file_with_perms(&file.id, user.id, Some(dest_parent_path.to_string()))
.await
.map_err(AppError::from)?;
}
if file.name != dest_filename {
file_management_service
.rename_file(&file.id, dest_filename)
.rename_file_with_perms(&file.id, user.id, dest_filename)
.await
.map_err(AppError::from)?;
}
@@ -1535,8 +1535,9 @@ async fn handle_copy(
if recursive {
let file_management_service = &state.applications.file_management_service;
file_management_service
.copy_folder_tree(
.copy_folder_tree_with_perms(
&folder.id,
user.id,
target_parent_id,
Some(dest_folder_name.to_string()),
)
@@ -1550,7 +1551,7 @@ async fn handle_copy(
parent_id: target_parent_id,
};
folder_service
.create_folder(create_dto, user.id)
.create_folder_with_perms(create_dto, user.id)
.await
.map_err(|e| {
AppError::internal_error(format!(
@@ -1586,7 +1587,7 @@ async fn handle_copy(
let file_management_service = &state.applications.file_management_service;
file_management_service
.copy_file(&file.id, target_folder_id)
.copy_file_with_perms(&file.id, user.id, target_folder_id)
.await
.map_err(|e| AppError::internal_error(format!("Failed to copy file: {}", e)))?;
}
@@ -1639,8 +1640,9 @@ async fn handle_copy(
if recursive {
let file_management_service = &state.applications.file_management_service;
file_management_service
.copy_folder_tree(
.copy_folder_tree_with_perms(
&folder.id,
user.id,
target_parent_id,
Some(dest_folder_name.to_string()),
)
@@ -1654,7 +1656,7 @@ async fn handle_copy(
parent_id: target_parent_id,
};
folder_service
.create_folder(create_dto, user.id)
.create_folder_with_perms(create_dto, user.id)
.await
.map_err(|e| {
AppError::internal_error(format!(
@@ -1697,7 +1699,7 @@ async fn handle_copy(
let file_management_service = &state.applications.file_management_service;
file_management_service
.copy_file(&file.id, target_folder_id)
.copy_file_with_perms(&file.id, user.id, target_folder_id)
.await
.map_err(|e| AppError::internal_error(format!("Failed to copy file: {}", e)))?;
}