@@ -72,19 +72,14 @@ pub async fn put_object(
7272 }
7373 }
7474
75- // Store in bucket
76- tracing:: debug!( bucket = %bucket_name, "Opening bucket" ) ;
77- let mut bucket = state. bucket_manager . open_bucket ( & bucket_name) . await
75+ // Store in bucket (user-scoped)
76+ tracing:: debug!( bucket = %bucket_name, "Opening user-scoped bucket" ) ;
77+ let mut bucket = state. bucket_manager . open_bucket_for_user ( & session . hashed_user_id , & bucket_name) . await
7878 . map_err ( |e| {
7979 tracing:: error!( error = %e, bucket = %bucket_name, "Failed to open bucket" ) ;
8080 e
8181 } ) ?;
82-
83- // Verify bucket ownership (security audit fix #1)
84- if !session. can_access_bucket ( & bucket. metadata ( ) . owner_id ) {
85- return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "You do not have access to this bucket" ) ) ;
86- }
87-
82+
8883 tracing:: debug!( key = %key, "Storing object metadata" ) ;
8984 bucket. put_object ( key. clone ( ) , metadata) . await
9085 . map_err ( |e| {
@@ -142,13 +137,9 @@ pub async fn get_object(
142137 return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "Read access required" ) ) ;
143138 }
144139
145- let bucket = state. bucket_manager . open_bucket ( & bucket_name) . await ?;
146-
147- // Verify bucket ownership (security audit fix #1)
148- if !session. can_access_bucket ( & bucket. metadata ( ) . owner_id ) {
149- return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "You do not have access to this bucket" ) ) ;
150- }
151-
140+ // User-scoped bucket access
141+ let bucket = state. bucket_manager . open_bucket_for_user ( & session. hashed_user_id , & bucket_name) . await ?;
142+
152143 let metadata = bucket. get_object ( & key) . await ?
153144 . ok_or_else ( || ApiError :: s3_with_resource (
154145 S3ErrorCode :: NoSuchKey ,
@@ -301,13 +292,9 @@ pub async fn head_object(
301292 return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "Read access required" ) ) ;
302293 }
303294
304- let bucket = state. bucket_manager . open_bucket ( & bucket_name) . await ?;
305-
306- // Verify bucket ownership (security audit fix #1)
307- if !session. can_access_bucket ( & bucket. metadata ( ) . owner_id ) {
308- return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "You do not have access to this bucket" ) ) ;
309- }
310-
295+ // User-scoped bucket access
296+ let bucket = state. bucket_manager . open_bucket_for_user ( & session. hashed_user_id , & bucket_name) . await ?;
297+
311298 let metadata = bucket. get_object ( & key) . await ?
312299 . ok_or_else ( || ApiError :: s3_with_resource (
313300 S3ErrorCode :: NoSuchKey ,
@@ -343,13 +330,9 @@ pub async fn delete_object(
343330 return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "Write access required" ) ) ;
344331 }
345332
346- let mut bucket = state. bucket_manager . open_bucket ( & bucket_name) . await ?;
347-
348- // Verify bucket ownership (security audit fix #1)
349- if !session. can_access_bucket ( & bucket. metadata ( ) . owner_id ) {
350- return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "You do not have access to this bucket" ) ) ;
351- }
352-
333+ // User-scoped bucket access
334+ let mut bucket = state. bucket_manager . open_bucket_for_user ( & session. hashed_user_id , & bucket_name) . await ?;
335+
353336 bucket. delete_object ( & key) . await ?;
354337 bucket. flush ( ) . await ?;
355338
@@ -390,33 +373,23 @@ pub async fn copy_object(
390373 . split_once ( '/' )
391374 . ok_or_else ( || ApiError :: s3 ( S3ErrorCode :: InvalidArgument , "Invalid copy source format" ) ) ?;
392375
393- // Get source object
394- let source_bucket_handle = state. bucket_manager . open_bucket ( source_bucket) . await ?;
395-
396- // Verify source bucket ownership (security audit fix #1)
397- if !session. can_access_bucket ( & source_bucket_handle. metadata ( ) . owner_id ) {
398- return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "You do not have access to the source bucket" ) ) ;
399- }
400-
376+ // Get source object (user-scoped)
377+ let source_bucket_handle = state. bucket_manager . open_bucket_for_user ( & session. hashed_user_id , source_bucket) . await ?;
378+
401379 let source_metadata = source_bucket_handle. get_object ( source_key) . await ?
402380 . ok_or_else ( || ApiError :: s3_with_resource (
403381 S3ErrorCode :: NoSuchKey ,
404382 "Source object not found" ,
405383 copy_source,
406384 ) ) ?;
407385
408- // Copy to destination
409- // Security audit fix A3: Use hashed user ID
386+ // Copy to destination (user-scoped)
410387 let mut dest_metadata = source_metadata. clone ( ) ;
411388 dest_metadata. last_modified = chrono:: Utc :: now ( ) ;
412389 dest_metadata. owner_id = Some ( session. hashed_user_id . clone ( ) ) ;
413390
414- let mut dest_bucket_handle = state. bucket_manager . open_bucket ( & dest_bucket) . await ?;
415-
416- // Verify destination bucket ownership (security audit fix #1)
417- if !session. can_access_bucket ( & dest_bucket_handle. metadata ( ) . owner_id ) {
418- return Err ( ApiError :: s3 ( S3ErrorCode :: AccessDenied , "You do not have access to the destination bucket" ) ) ;
419- }
391+ let mut dest_bucket_handle = state. bucket_manager . open_bucket_for_user ( & session. hashed_user_id , & dest_bucket) . await ?;
392+
420393 dest_bucket_handle. put_object ( dest_key, dest_metadata. clone ( ) ) . await ?;
421394 dest_bucket_handle. flush ( ) . await ?;
422395
0 commit comments