10
votes

I'm developing a messaging iOS app, where a user can send the same message to multiple people. The message is saved in firebase storage. I want to only enable the users who have been sent the message to be able to read it from storage. I am already implementing this rule structure in my firebase database.

In order to implement this for storage I add a list of uids to the message file customMetadata, including a fromUid key for the person who composed the message. I do the following in my iOS app:

    var metadataValues = [String:String]()

    for friendUid in friendsSelected.keys {
        metadataValues.updateValue(friendUid, forKey: friendUid) // how do I access these values in my security rules
    }
    metadataValues.updateValue(senderUid, forKey: "fromUid") // how do I access this in security rules 
    let messageMetadata = FIRStorageMetadata()
    messageMetadata.customMetadata = metadataValues

This was my attempt for my read and write security rules for the messages node in Firebase Storage but it doesn't work and the documentation is of no help.

    match /messages/{messageId} {

        allow read: if request.auth.uid == resource.metadata.request.auth.uid; // I want all friend uids to be able to read file
        allow write: if request.auth.uid == resource.metadata.fromUid; // only the person who create the message can access it

}

My attempt doesn't work. How do I access the customMetadata variable with the keys 'fromUid' and the friends uids 'request.auth.uid' in my security rules??

As a sidenote, I assume there is no limit on how many keys I add to customMetadata?

1
would really appreciate help on this. For some reason everything I have tried hasn't worked.Edward

1 Answers

15
votes

So I have managed to solve it. The problem I had was that I wasn't familiar with Javascript and so I was getting the syntax wrong. After looking into Javascript I was soon able to work it out.

Hope my answer helps anyone else but would recommend learning the basics of Javascript if you are in a similar position to me.

It's also worth noting that to access the file metadata you use request.resource.metadata before the write is executed and resource.metadata to access once uploaded.

    match /messages/{messageId} {
    
        allow write: if request.resource.metadata['fromUid'] == request.auth.uid; 
        allow read: if resource.metadata[request.auth.uid] == request.auth.uid; 
    }