diff --git a/src/application/dtos/file_dto.rs b/src/application/dtos/file_dto.rs index 6676ea34..bc6af74c 100644 --- a/src/application/dtos/file_dto.rs +++ b/src/application/dtos/file_dto.rs @@ -119,6 +119,21 @@ impl From for File { } impl FileDto { + /// Returns a copy of this DTO with the `path` field cleared. + /// + /// Used when a file is returned to a share recipient: `path` reveals the + /// full folder hierarchy above the file which the recipient may not have + /// access to. `folder_id` and `owner_id` are intentionally kept — the + /// former is needed for sub-folder navigation (covered by the cascade + /// grant), and the latter is harmless metadata. + #[must_use] + pub fn without_hierarchy_info(self) -> Self { + Self { + path: String::new(), + ..self + } + } + /// Creates an empty file DTO for stub implementations pub fn empty() -> Self { Self { diff --git a/src/application/dtos/folder_dto.rs b/src/application/dtos/folder_dto.rs index cedf2289..098f1739 100644 --- a/src/application/dtos/folder_dto.rs +++ b/src/application/dtos/folder_dto.rs @@ -107,6 +107,21 @@ impl From for Folder { } impl FolderDto { + /// Returns a copy of this DTO with the `path` field cleared. + /// + /// Used when a folder is returned to a share recipient: `path` reveals the + /// full folder hierarchy above the shared folder which the recipient may + /// not have access to. `parent_id` and `owner_id` are intentionally kept + /// — the former is needed for sub-folder navigation (covered by the + /// cascade grant), and the latter is harmless metadata. + #[must_use] + pub fn without_hierarchy_info(self) -> Self { + Self { + path: String::new(), + ..self + } + } + /// Creates an empty folder DTO for stub implementations pub fn empty() -> Self { Self { diff --git a/src/interfaces/api/handlers/grant_handler.rs b/src/interfaces/api/handlers/grant_handler.rs index d379136f..eb813ccb 100644 --- a/src/interfaces/api/handlers/grant_handler.rs +++ b/src/interfaces/api/handlers/grant_handler.rs @@ -384,7 +384,7 @@ pub async fn list_shared_with_me( permissions: summary.permissions.iter().map(|p| (*p).into()).collect(), granted_at: summary.granted_at, granted_by: summary.granted_by, - file: Some(file_dto.clone()), + file: Some(file_dto.clone().without_hierarchy_info()), folder: None, }); } @@ -415,7 +415,7 @@ pub async fn list_shared_with_me( granted_at: summary.granted_at, granted_by: summary.granted_by, file: None, - folder: Some(folder_dto.clone()), + folder: Some(folder_dto.clone().without_hierarchy_info()), }); } Err(e) if e.kind == ErrorKind::NotFound => {