From 762bf6f55d809f9bccbac847c92074a2b8c41150 Mon Sep 17 00:00:00 2001 From: Thomas P Date: Fri, 18 Dec 2020 16:26:46 +0100 Subject: [PATCH] fix(storage, ios): resolve listAll promise once and only once on error (#4688) * FIX: [Storage] Don't try resolving the promise twice if an error occurs in listAll() See https://github.com/firebase/firebase-ios-sdk/blob/14764b8d60a6ad023d8fa5b7f81d42378d92e6fe/FirebaseStorage/Sources/FIRStorageReference.m#L417 * TST: Make sure listAll behaves as expected when the user is not authorized * Apply suggestions from code review Co-authored-by: Mike Hardy --- packages/storage/e2e/StorageReference.e2e.js | 14 ++++++++++++++ .../storage/ios/RNFBStorage/RNFBStorageModule.m | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/storage/e2e/StorageReference.e2e.js b/packages/storage/e2e/StorageReference.e2e.js index 76edcc68fb..2d356ff79d 100644 --- a/packages/storage/e2e/StorageReference.e2e.js +++ b/packages/storage/e2e/StorageReference.e2e.js @@ -346,6 +346,20 @@ describe('storage() -> StorageReference', function() { result.prefixes.length.should.be.greaterThan(0); result.prefixes[0].constructor.name.should.eql('StorageReference'); }); + + it('should not crash if the user is not allowed to list the directory', async function() { + const storageReference = firebase.storage().ref('/forbidden'); + try { + await storageReference.listAll(); + return Promise.reject(new Error('listAll on a forbidden directory succeeded')); + } catch (error) { + error.code.should.equal('storage/unauthorized'); + error.message.should.equal( + '[storage/unauthorized] User is not authorized to perform the desired action.', + ); + return Promise.resolve(); + } + }); }); describe('updateMetadata', function() { diff --git a/packages/storage/ios/RNFBStorage/RNFBStorageModule.m b/packages/storage/ios/RNFBStorage/RNFBStorageModule.m index a3a92a87dd..012367193e 100644 --- a/packages/storage/ios/RNFBStorage/RNFBStorageModule.m +++ b/packages/storage/ios/RNFBStorage/RNFBStorageModule.m @@ -194,7 +194,16 @@ - (void)invalidate { ) { FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp]; + __block bool alreadyCompleted = false; + id completionBlock = ^(FIRStorageListResult *result, NSError *error) { + // This may be called multiple times if an error occurs + // Make sure we won't try to resolve the promise twice in this case + // TODO - remove pending resolution of https://github.com/firebase/firebase-ios-sdk/issues/7197 + if (alreadyCompleted) { + return; + } + alreadyCompleted = true; if (error != nil) { [self promiseRejectStorageException:reject error:error]; } else {