2

I want to let users find a record by value, but I don't want them to be able to list all records.

For example I want to create a wiki, and I want some pages to only be accessible by direct urls.

I know I can give read access on the record level, and a user wouldn't be able to read all keys, but then I'm limited to only characters allowed for a key, while I might want to use / and other characters.

So I would store a thing's path in it's path property and then look for the thing by path;

// database structure
things
    -KNi4OQXGXsHKYHVuTln
        path: "should/not/be/listed/anywhere"

I want to let the user to find the thing only if they know the path.

The problem is I can only find the thing by searching /things with orderByChild and equalTo:

// request with javascript
firebase.database()
    .ref('/things').orderByChild('path')
    .equalTo("should/not/be/listed/anywhere")
    .once('value', s=>{  });

Which means I would have to give read access to /things:

// database security rules
{
    "rules": {
        "things": {
            ".read": true,
            ".indexOn": ["path"],
            "$thingId": {
                ".validate": "newData.hasChildren(['path']) && newData.child('path').isString()"
            }
        }
    }
}

and that effectively lets anyone see all the things that I have. Is there a way to avoid that?

And if not, does that mean Firebase forces me to make all my things public as soon as I want to find by a property value?

Yura
  • 2,690
  • 26
  • 32

2 Answers2

2

To be able to find something in the Firebase Database, you must have read access to it. There is no way to avoid that.

We commonly refer to this as "rules are not filters" and you can find more about it in the documentation, in this answer and by searching for "rules are not filters" on Stack Overflow.

If you want to offer search-without-access, you'll have to set up your own search service, which runs the trusted code and then exposes the matching items' paths back to the client.

Common ways of setting up such a search service in front of Firebase are with the Firebase Flashlight library for ElasticSearch or with a cloud search service such as Algolia.

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you Frank. I was hoping to avoid creating and maintaining a server for a simpler project. – Yura Dec 27 '16 at 16:05
1

I knew I should be able to avoid maintaining a server for a simple thing like that, so I'm answering my own question.

My actual problem was that I wanted to give users access to things when they know the key, but didn't want them to see all the things. I could do that by giving thing-level access and using path as the key, but then the keys wouldn't allow me to use /, and of course I also wanted my things structure to be flat.

After looking at that once again I found the limitations on keys in firebase, which are

  • Max 768 characters
  • Forbidden characters: . $ # [ ] /
  • Some allowed characters: \ ! @ % & ? : ; , * = + < > ( ) | " ' ^ ~ - _

So I can simply create a simple map to translate forbidden characters to allowed characters and use the path as a key, which solves my problem: users will be able to access things only when they know the path, while the path can look as a URL.

Yura
  • 2,690
  • 26
  • 32