From be1bed847ce4122a7b8ebf1c7f9ba6f2d6460a4c Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 16 May 2021 22:18:50 -0500 Subject: [PATCH] feat(storage, md5hash): allow md5hash to be set on upload metadata property md5hash is allowed for upload, just not for updateMetadata allow it to go through in the putNNN scenarios but screen for it on update --- packages/storage/e2e/StorageReference.e2e.js | 47 ++++++++++++++++++++ packages/storage/lib/StorageReference.js | 12 ++--- packages/storage/lib/index.d.ts | 5 +++ packages/storage/lib/utils.js | 10 ++++- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/packages/storage/e2e/StorageReference.e2e.js b/packages/storage/e2e/StorageReference.e2e.js index bed7fc493f..eba8b4c97f 100644 --- a/packages/storage/e2e/StorageReference.e2e.js +++ b/packages/storage/e2e/StorageReference.e2e.js @@ -351,6 +351,10 @@ describe('storage() -> StorageReference', function () { const storageReference = firebase.storage().ref(WRITE_ONLY_NAME); const metadata = await storageReference.updateMetadata({ contentType: 'image/jpeg', + cacheControl: 'true', + contentDisposition: 'disposed', + contentEncoding: 'encoded', + contentLanguage: 'martian', customMetadata: { hello: 'world', }, @@ -406,6 +410,19 @@ describe('storage() -> StorageReference', function () { // FIXME this is failing the part that fails should.equal(metadataAfterRemove.customMetadata.removeMe, undefined); }); + + it('should error if updateMetadata includes md5hash', async function () { + const storageReference = firebase.storage().ref(WRITE_ONLY_NAME); + try { + await storageReference.updateMetadata({ + md5hash: '0xDEADBEEF', + }); + return Promise.reject(new Error('Did not throw on invalid updateMetadata')); + } catch (e) { + e.message.should.containEql('md5hash may only be set on upload, not on updateMetadata'); + return Promise.resolve(); + } + }); }); describe('putFile', function () { @@ -515,6 +532,21 @@ describe('storage() -> StorageReference', function () { return Promise.resolve(); } }); + + it('allows valid metadata properties for upload', async function () { + const storageReference = firebase.storage().ref(`${PATH}/metadataTest.txt`); + await storageReference.putString('foo', 'raw', { + contentType: 'text/plain', + md5hash: '123412341234', + cacheControl: 'true', + contentDisposition: 'disposed', + contentEncoding: 'encoded', + contentLanguage: 'martian', + customMetadata: { + customMetadata1: 'metadata1value', + }, + }); + }); }); describe('put', function () { @@ -563,5 +595,20 @@ describe('storage() -> StorageReference', function () { return Promise.resolve(); } }); + + it('allows valid metadata properties for upload', async function () { + const storageReference = firebase.storage().ref(`${PATH}/metadataTest.jpeg`); + await storageReference.put(new jet.context.window.ArrayBuffer(), { + contentType: 'image/jpg', + md5hash: '123412341234', + cacheControl: 'true', + contentDisposition: 'disposed', + contentEncoding: 'encoded', + contentLanguage: 'martian', + customMetadata: { + customMetadata1: 'metadata1value', + }, + }); + }); }); }); diff --git a/packages/storage/lib/StorageReference.js b/packages/storage/lib/StorageReference.js index 7787200e58..ce784a2aa9 100644 --- a/packages/storage/lib/StorageReference.js +++ b/packages/storage/lib/StorageReference.js @@ -179,12 +179,12 @@ export default class StorageReference extends ReferenceBase { */ put(data, metadata) { if (!isUndefined(metadata)) { - validateMetadata(metadata); + validateMetadata(metadata, false); } return new StorageUploadTask(this, task => Base64.fromData(data).then(({ string, format }) => { - const { _string, _format, _metadata } = this._updateString(string, format, metadata); + const { _string, _format, _metadata } = this._updateString(string, format, metadata, false); return this._storage.native.putString( this.toString(), _string, @@ -200,7 +200,7 @@ export default class StorageReference extends ReferenceBase { * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#putString */ putString(string, format = StorageStatics.StringFormat.RAW, metadata) { - const { _string, _format, _metadata } = this._updateString(string, format, metadata); + const { _string, _format, _metadata } = this._updateString(string, format, metadata, false); return new StorageUploadTask(this, task => this._storage.native.putString(this.toString(), _string, _format, _metadata, task._id), @@ -250,7 +250,7 @@ export default class StorageReference extends ReferenceBase { */ putFile(filePath, metadata) { if (!isUndefined(metadata)) { - validateMetadata(metadata); + validateMetadata(metadata, false); } if (!isString(filePath)) { @@ -264,7 +264,7 @@ export default class StorageReference extends ReferenceBase { ); } - _updateString(string, format, metadata) { + _updateString(string, format, metadata, update = false) { if (!isString(string)) { throw new Error( "firebase.storage.StorageReference.putString(*, _, _) 'string' expects a string value.", @@ -280,7 +280,7 @@ export default class StorageReference extends ReferenceBase { } if (!isUndefined(metadata)) { - validateMetadata(metadata); + validateMetadata(metadata, update); } let _string = string; diff --git a/packages/storage/lib/index.d.ts b/packages/storage/lib/index.d.ts index 8265b2ee4a..41dcd83775 100644 --- a/packages/storage/lib/index.d.ts +++ b/packages/storage/lib/index.d.ts @@ -315,6 +315,11 @@ export namespace FirebaseStorageTypes { */ contentType?: string | null; + /** + * You may specify the md5hash of the file in metadata on upload only. It may not be updated via updateMetadata + */ + md5hash?: string | null; + /** * Additional user-defined custom metadata for this storage object. * diff --git a/packages/storage/lib/utils.js b/packages/storage/lib/utils.js index 84fe1c3846..b8acc75a0f 100644 --- a/packages/storage/lib/utils.js +++ b/packages/storage/lib/utils.js @@ -25,6 +25,7 @@ const SETTABLE_FIELDS = [ 'contentLanguage', 'contentType', 'customMetadata', + 'md5hash', ]; export async function handleStorageEvent(storageInstance, event) { @@ -57,7 +58,7 @@ export function getGsUrlParts(url) { return { bucket, path }; } -export function validateMetadata(metadata) { +export function validateMetadata(metadata, update = true) { if (!isObject(metadata)) { throw new Error('firebase.storage.SettableMetadata must be an object value if provided.'); } @@ -73,6 +74,13 @@ export function validateMetadata(metadata) { ); } + // md5 is only allowed on put, not on update + if (key === 'md5hash' && update === true) { + throw new Error( + `firebase.storage.SettableMetadata md5hash may only be set on upload, not on updateMetadata`, + ); + } + // validate values if (key !== 'customMetadata') { if (!isString(value) && !isNull(value)) {