22
33use std:: { collections:: HashSet , sync:: Arc } ;
44
5- use alloy_core:: primitives:: Address ;
5+ use alloy_core:: { hex :: ToHexExt , primitives:: Address } ;
66use axum_extra:: extract:: multipart:: Field ;
77use bigdecimal:: { BigDecimal , RoundingMode } ;
88use codec:: { Decode , Encode } ;
@@ -214,9 +214,9 @@ impl MspService {
214214 } ) )
215215 }
216216
217- /// Get a specific bucket by ID
217+ /// Get a specific bucket by its ID
218218 ///
219- /// Verifies ownership of bucket is `user` (or that the bucket is public if `user` is `None`)
219+ /// Verifies that the owner of the bucket is `user`. If the bucket is public, this check always passes.
220220 pub async fn get_bucket (
221221 & self ,
222222 bucket_id : & str ,
@@ -514,18 +514,7 @@ impl MspService {
514514 "Starting file upload"
515515 ) ;
516516
517- // Retrieve the onchain file info and verify user has permission to access the file
518- let info = self . get_file_info ( user, & file_key) . await ?;
519-
520- // Validate bucket id and file key against metadata
521- let expected_bucket_id = hex:: encode ( file_metadata. bucket_id ( ) ) ;
522- let bucket_id_without_prefix = info. bucket_id . trim_start_matches ( "0x" ) ;
523- if bucket_id_without_prefix != expected_bucket_id {
524- return Err ( Error :: BadRequest (
525- format ! ( "Bucket ID in URL does not match file metadata: {expected_bucket_id} != {bucket_id_without_prefix}" ) ,
526- ) ) ;
527- }
528-
517+ // Validate the received file key against the one corresponding to the file metadata.
529518 let expected_file_key = hex:: encode ( file_metadata. file_key :: < Blake2Hasher > ( ) ) ;
530519 let file_key_without_prefix = file_key. trim_start_matches ( "0x" ) ;
531520 if file_key_without_prefix != expected_file_key {
@@ -534,6 +523,15 @@ impl MspService {
534523 ) ) ) ;
535524 }
536525
526+ // Get the bucket ID from the metadata and verify that the user is its owner.
527+ // We check the bucket ownership instead of the file ownership as the file might not be in
528+ // the indexer at this point (since the storage request would have to have been finalised).
529+ // TODO: This could still fail as the bucket creation extrinsic might not have been finalised yet,
530+ // ideally we should have a way to directly check on-chain (like an RPC).
531+ let bucket_id = hex:: encode ( file_metadata. bucket_id ( ) ) ;
532+ let bucket = self . get_db_bucket ( & bucket_id) . await ?;
533+ self . can_user_view_bucket ( bucket, user) ?;
534+
537535 // Initialize the trie that will hold the chunked file data.
538536 let mut trie = InMemoryFileDataTrie :: < StorageProofsMerkleTrieLayout > :: new ( ) ;
539537
@@ -674,20 +672,20 @@ impl MspService {
674672 // If the complete file was uploaded to the MSP successfully, we can return the response.
675673 let bytes_location = file_metadata. location ( ) ;
676674 let location = str:: from_utf8 ( & bytes_location)
677- . unwrap_or ( & info . file_key )
675+ . unwrap_or ( & file_key)
678676 . to_string ( ) ;
679677
680678 debug ! (
681- file_key = %info . file_key,
679+ file_key = %file_key,
682680 chunks = total_chunks,
683681 "File upload completed"
684682 ) ;
685683
686684 Ok ( FileUploadResponse {
687685 status : "upload_successful" . to_string ( ) ,
688- fingerprint : info . fingerprint_hexstr ( ) ,
689- file_key : info . file_key ,
690- bucket_id : info . bucket_id ,
686+ fingerprint : file_metadata . fingerprint ( ) . encode_hex_with_prefix ( ) ,
687+ file_key : file_key. to_string ( ) ,
688+ bucket_id : bucket_id,
691689 location,
692690 } )
693691 }
@@ -867,11 +865,11 @@ impl MspService {
867865}
868866
869867impl MspService {
870- /// Verifies user can access the given bucket
868+ /// Verifies that a user can access the given bucket.
871869 ///
872- /// If the bucket is public, the `user` may be `None`
870+ /// If the bucket is public, this check always passes.
873871 ///
874- /// Will return the bucket if the user has the required permissions
872+ /// Will return the bucket metadata if the user has the required permissions, or an error otherwise.
875873 fn can_user_view_bucket (
876874 & self ,
877875 bucket : DBBucket ,
@@ -880,15 +878,20 @@ impl MspService {
880878 // TODO: NFT ownership
881879 if bucket. private {
882880 let Some ( user) = user else {
883- return Err ( Error :: Unauthorized ( "This bucket is private" . to_string ( ) ) ) ;
881+ return Err ( Error :: Unauthorized ( format ! (
882+ "Bucket with ID {} is private and no user received." ,
883+ bucket. onchain_bucket_id. encode_hex_with_prefix( )
884+ ) ) ) ;
884885 } ;
885886
886887 if bucket. account . as_str ( ) == user. to_string ( ) {
887888 Ok ( bucket)
888889 } else {
889- Err ( Error :: Unauthorized (
890- "Specified user is not authorized to view this bucket" . to_string ( ) ,
891- ) )
890+ Err ( Error :: Unauthorized ( format ! (
891+ "User {} is not authorized to view bucket with ID {}" ,
892+ user,
893+ bucket. onchain_bucket_id. encode_hex_with_prefix( )
894+ ) ) )
892895 }
893896 } else {
894897 Ok ( bucket)
0 commit comments