Search code examples
javascriptfirebasefirebase-realtime-databasegoogle-cloud-functionsfirebase-security

Firebase preventing data fetch even though read rules are assigned


I'm trying to fetch data in the front-end using firebase. Here's how my rules are applied to the realtime database:

{
    "rules": {
        "users": {
            ".indexOn": "username",
            "$userId": {
                ".indexOn": "username",
                ".read": "$userId==auth.uid",
                ".write": "$userId==auth.uid",
                "favorites": {
                    ".indexOn": "thumb"
                }
            }
        },
        "files": {
            ".indexOn": ["uploadId", "uploadedBy", "fileURL"],
            "$fileId": {
                ".write": "newData.child('uploadedBy').val() == auth.uid",
                ".read": "data.child('uploadedBy').val() == auth.uid",
                ".indexOn": "fileURL"
            }
        },
        "uploads": {
            "$id": {
                ".write": "newData.child('createdBy').val() == auth.uid || data.child('assignedModeratorId').val() == auth.uid",
                ".read": "data.child('createdBy').val() == auth.uid || data.child('assignedModeratorId').val() == auth.uid"
            },
            ".indexOn": ["createdBy", "status", "assignedModeratorId"]
        }
    }
}

And here's what one uploads document looks like:

enter image description here

I'm using this function:

const snapshot = await firebase.database().ref('uploads').orderByChild('createdBy').equalTo(uid).limitToLast(1000).once('value');

But I keep getting Error: permission_denied at /uploads: Client doesn't have permission to access the desired data. error in the front-end. It's working fine when I use admin in the cloud functions. What's wrong with my set rules?


Solution

  • Your code tries to read data from /uploads, but your rules don't grant anyone permission to read from that node - so it rejects the read.

    If you want to allow the user to read the uploads they created, your rules should validate that query with something like:

    "uploads": {
      ".read": "auth.uid !== null &&
                query.orderByChild === 'createdBy' &&
                query.equalTo === auth.uid"}