feat: check thumbnail cleanup on files deletion + correct ref counter
This commit is contained in:
@@ -26,7 +26,9 @@ pub struct HashCheckResponse {
|
||||
/// If exists, the size of the existing blob
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub existing_size: Option<u64>,
|
||||
/// If exists, the number of references to this blob
|
||||
/// Global reference count for this blob across all users.
|
||||
/// Only populated when the authenticated user has the `admin` role;
|
||||
/// omitted for regular users to prevent cross-user content inference.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ref_count: Option<u32>,
|
||||
}
|
||||
@@ -85,7 +87,8 @@ impl DedupHandler {
|
||||
/// Check if the authenticated user already has a file with the given hash.
|
||||
///
|
||||
/// User-scoped: only reveals whether **this user** owns a file that
|
||||
/// references the blob — never exposes global existence or ref_count.
|
||||
/// references the blob — never exposes global existence to non-admins.
|
||||
/// Admins additionally receive the global `ref_count` in the response.
|
||||
///
|
||||
/// GET /api/dedup/check/{hash}
|
||||
pub(super) async fn check_hash_impl(
|
||||
@@ -113,13 +116,20 @@ impl DedupHandler {
|
||||
.await;
|
||||
|
||||
if user_has_it {
|
||||
// Fetch size from metadata (safe — user owns a reference)
|
||||
let size = dedup.get_blob_metadata(&hash).await.map(|m| m.size);
|
||||
// Fetch size from metadata (safe — user owns a reference).
|
||||
// Admins also get the global ref_count for dedup accounting tests.
|
||||
let metadata = dedup.get_blob_metadata(&hash).await;
|
||||
let size = metadata.as_ref().map(|m| m.size);
|
||||
let ref_count = if auth_user.role == "admin" {
|
||||
metadata.map(|m| m.ref_count)
|
||||
} else {
|
||||
None // Never expose global ref_count to regular users
|
||||
};
|
||||
let response = HashCheckResponse {
|
||||
exists: true,
|
||||
hash,
|
||||
existing_size: size,
|
||||
ref_count: None, // Never expose global ref_count
|
||||
ref_count,
|
||||
};
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
@@ -492,6 +502,7 @@ impl DedupHandler {
|
||||
.unwrap()
|
||||
.into_response()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ── Route handlers (free functions) ──────────────────────────────────────────
|
||||
@@ -511,7 +522,7 @@ impl DedupHandler {
|
||||
("hash" = String, Path, description = "BLAKE3 hash (64 hex characters)"),
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Hash check result (user-scoped)", body = HashCheckResponse),
|
||||
(status = 200, description = "Hash check result. `ref_count` is only present for admin users.", body = HashCheckResponse),
|
||||
(status = 400, description = "Invalid hash format"),
|
||||
),
|
||||
tag = "dedup",
|
||||
|
||||
@@ -783,6 +783,7 @@ impl FileHandler {
|
||||
file_id,
|
||||
blob_hash_owned,
|
||||
original_bytes,
|
||||
dedup_service.clone(),
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
Reference in New Issue
Block a user