fix(drive): fix drive_id on copy to other drive

- fix alsot drive_id exposition
This commit is contained in:
Edouard Vanbelle
2026-06-29 21:55:47 +02:00
parent e81b297f68
commit 583af517c2
15 changed files with 593 additions and 27 deletions
+5
View File
@@ -125,6 +125,11 @@ pub struct FavoriteResourceRow {
pub resource_created_at: DateTime<Utc>,
pub modified_at: DateTime<Utc>,
pub owner_id: Uuid,
/// Drive that owns this row. Surfaced on the favorites listing
/// so a UI can tell when a favorited item lives in a different
/// drive than the user's home (post-D6 cross-drive moves +
/// copies make this reachable).
pub drive_id: Uuid,
/// Raw BLAKE3 content hash. `Some(_)` for file rows, `None` for
/// folder rows. Routes into `FileDto::content_hash` and feeds
/// `File::compute_etag` to populate `FileDto::etag`.
+6
View File
@@ -206,6 +206,12 @@ pub struct FolderResourceRow {
pub created_at: DateTime<Utc>,
pub modified_at: DateTime<Utc>,
pub owner_id: Uuid,
/// Drive that owns this row. Same column as
/// `storage.folders.drive_id` / `storage.files.drive_id`. Surfaced
/// on the listing so a UI can tell when a child lives in a
/// different drive than its parent (post-D6 cross-drive moves +
/// copies make this reachable).
pub drive_id: Uuid,
/// Raw BLAKE3 content hash. `Some(_)` for file rows, `None` for
/// folder rows. Populates `FileDto::content_hash` + `FileDto::etag`
/// on the REST `/api/folders/{id}/resources` listing so API
+5
View File
@@ -105,6 +105,11 @@ pub struct RecentResourceRow {
pub resource_created_at: DateTime<Utc>,
pub modified_at: DateTime<Utc>,
pub owner_id: Uuid,
/// Drive that owns this row. Surfaced on the recent listing
/// so a UI can tell when a recently-accessed item lives in a
/// different drive than the user's home (post-D6 cross-drive
/// moves + copies make this reachable).
pub drive_id: Uuid,
/// Raw BLAKE3 content hash. `Some(_)` for file rows, `None` for
/// folder rows. Feeds `File::compute_etag` so this listing's
/// `etag` matches GET/HEAD/PROPFIND for the same file.
+4
View File
@@ -155,6 +155,10 @@ pub struct SearchFolderResultDto {
pub path: String,
/// Parent folder ID
pub parent_id: Option<String>,
/// Drive that owns this folder. Same column as `storage.folders.drive_id`,
/// carried through so downstream callers (e.g. the NC search REPORT
/// handler) can populate `FolderDto::drive_id` without a fallback sentinel.
pub drive_id: uuid::Uuid,
/// Creation timestamp
pub created_at: u64,
/// Last modification timestamp
@@ -241,6 +241,7 @@ impl SearchService {
name: folder.name.clone(),
path: folder.path.clone(),
parent_id: folder.parent_id.clone(),
drive_id: folder.drive_id,
created_at: folder.created_at,
modified_at: folder.modified_at,
is_root: folder.is_root,
@@ -310,6 +310,7 @@ impl FavoritesRepositoryPort for FavoritesPgRepository {
fld.created_at AS resource_created_at,
fld.updated_at AS modified_at,
fld.user_id AS owner_id,
fld.drive_id AS drive_id,
NULL::text AS blob_hash,
(fld.user_id = $1::uuid) AS is_owner,
uf.created_at AS favorited_at,
@@ -333,6 +334,7 @@ impl FavoritesRepositoryPort for FavoritesPgRepository {
f.created_at AS resource_created_at,
f.updated_at AS modified_at,
f.user_id AS owner_id,
f.drive_id AS drive_id,
f.blob_hash,
(f.user_id = $1::uuid) AS is_owner,
uf.created_at AS favorited_at,
@@ -504,7 +506,7 @@ impl FavoritesRepositoryPort for FavoritesPgRepository {
SELECT
r.resource_type, r.resource_id, r.name, r.parent_id,
r.mime_type, r.size, r.resource_created_at, r.modified_at,
r.owner_id, r.is_owner, r.favorited_at, r.resource_path,
r.owner_id, r.drive_id, r.is_owner, r.favorited_at, r.resource_path,
r.sort_str, r.type_order, r.folder_first{username_col}
FROM resources r
{user_join}
@@ -576,6 +578,7 @@ LIMIT $6"
resource_created_at: row.get("resource_created_at"),
modified_at: row.get("modified_at"),
owner_id: row.get("owner_id"),
drive_id: row.get("drive_id"),
blob_hash: row.try_get("blob_hash").ok(),
is_owner: row.try_get("is_owner").unwrap_or(false),
favorited_at: row.get("favorited_at"),
@@ -1435,6 +1435,7 @@ impl FolderDbRepository {
f.created_at,
f.updated_at AS modified_at,
f.user_id,
f.drive_id,
NULL::text AS blob_hash,
LOWER(f.name) AS sort_str,
0::bigint AS type_order,
@@ -1454,6 +1455,7 @@ impl FolderDbRepository {
fm.created_at,
fm.updated_at AS modified_at,
fm.user_id,
fm.drive_id,
fm.blob_hash,
LOWER(fm.name) AS sort_str,
fm.category_order::bigint AS type_order,
@@ -1578,7 +1580,8 @@ impl FolderDbRepository {
let sql = format!(
"WITH resources AS ({cte_inner}) \
SELECT resource_type, id, name, folder_id, mime_type, size, \
created_at, modified_at, user_id, blob_hash, sort_str, type_order, folder_first \
created_at, modified_at, user_id, drive_id, blob_hash, \
sort_str, type_order, folder_first \
FROM resources \
{where_clause} \
{order_clause} \
@@ -1586,7 +1589,7 @@ impl FolderDbRepository {
);
// Row: (resource_type, id, name, folder_id, mime_type, size,
// created_at, modified_at, user_id, blob_hash,
// created_at, modified_at, user_id, drive_id, blob_hash,
// sort_str, type_order, folder_first)
type Row = (
String,
@@ -1598,6 +1601,7 @@ impl FolderDbRepository {
chrono::DateTime<chrono::Utc>,
chrono::DateTime<chrono::Utc>,
Uuid,
Uuid,
Option<String>,
String,
i64,
@@ -1629,10 +1633,11 @@ impl FolderDbRepository {
created_at: r.6,
modified_at: r.7,
owner_id: r.8,
blob_hash: r.9,
sort_str: r.10,
type_order: r.11,
folder_first: r.12,
drive_id: r.9,
blob_hash: r.10,
sort_str: r.11,
type_order: r.12,
folder_first: r.13,
})
.collect())
}
@@ -217,6 +217,7 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
fld.created_at AS resource_created_at,
fld.updated_at AS modified_at,
fld.user_id AS owner_id,
fld.drive_id AS drive_id,
NULL::text AS blob_hash,
(fld.user_id = $1::uuid) AS is_owner,
ur.accessed_at AS accessed_at,
@@ -240,6 +241,7 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
f.created_at AS resource_created_at,
f.updated_at AS modified_at,
f.user_id AS owner_id,
f.drive_id AS drive_id,
f.blob_hash,
(f.user_id = $1::uuid) AS is_owner,
ur.accessed_at AS accessed_at,
@@ -409,7 +411,7 @@ impl RecentItemsRepositoryPort for RecentItemsPgRepository {
SELECT
r.resource_type, r.resource_id, r.name, r.parent_id,
r.mime_type, r.size, r.resource_created_at, r.modified_at,
r.owner_id, r.is_owner, r.accessed_at, r.resource_path,
r.owner_id, r.drive_id, r.is_owner, r.accessed_at, r.resource_path,
r.sort_str, r.type_order, r.folder_first{username_col}
FROM resources r
{user_join}
@@ -485,6 +487,7 @@ LIMIT $6"
resource_created_at: row.get("resource_created_at"),
modified_at: row.get("modified_at"),
owner_id: row.get("owner_id"),
drive_id: row.get("drive_id"),
blob_hash: row.try_get("blob_hash").ok(),
is_owner: row.try_get("is_owner").unwrap_or(false),
accessed_at: row.get("accessed_at"),
@@ -216,11 +216,7 @@ pub async fn list_favorites_resources(
path,
parent_id: row.parent_id.map(|u| u.to_string()),
owner_id: Some(row.owner_id.to_string()),
// Listing handler — drive_id is informational
// and the favorites row doesn't currently
// SELECT it. Path-based lookups never enter
// this code path.
drive_id: uuid::Uuid::nil(),
drive_id: row.drive_id,
created_at: row.resource_created_at.timestamp() as u64,
modified_at: row.modified_at.timestamp() as u64,
is_root: false,
@@ -502,10 +502,7 @@ pub async fn list_folder_resources(
path: String::new(), // cleared — share recipients must not see hierarchy
parent_id: row.parent_id.map(|u| u.to_string()),
owner_id: Some(row.owner_id.to_string()),
// Resources listing — drive_id is informational
// here; not selected by the underlying query.
// Path-based lookups never enter this code path.
drive_id: uuid::Uuid::nil(),
drive_id: row.drive_id,
created_at: row.created_at.timestamp() as u64,
modified_at: row.modified_at.timestamp() as u64,
is_root: false,
@@ -247,11 +247,7 @@ pub async fn list_recent_resources(
path,
parent_id: row.parent_id.map(|u| u.to_string()),
owner_id: Some(row.owner_id.to_string()),
// Listing handler — drive_id is informational
// and the recents row doesn't currently SELECT
// it. Path-based lookups never enter this code
// path.
drive_id: uuid::Uuid::nil(),
drive_id: row.drive_id,
created_at: row.resource_created_at.timestamp() as u64,
modified_at: row.modified_at.timestamp() as u64,
is_root: false,
+1 -4
View File
@@ -361,10 +361,7 @@ fn folder_dto_from_search(
path: sr.path.clone(),
parent_id: sr.parent_id.clone(),
owner_id: None,
// Search result — drive_id is informational. The search row
// doesn't currently SELECT it, and path-based lookups never
// enter this code path.
drive_id: uuid::Uuid::nil(),
drive_id: sr.drive_id,
created_at: sr.created_at,
modified_at: sr.modified_at,
is_root: sr.is_root,