0

I would like to store data under a $user where some data is readable by the public, and some data is readable only by the user. The security rules would look something like this:

{
  "rules": {      
    "users": {
      "$uid": {
        "public":{
          ".read": "auth != null",
        },
        "private": {
          ".read": "$uid === auth.uid"
        }
      }
    }
  }
}

However, since security rules are not filters, if I were the $user trying to read at users/$user, the read would fail, correct? Is there a way to accomplish this or will I always need to perform a read at both users/$user/public and users/$user/private when trying to obtain all $user info for the actual user?

Note that I want to avoid duplicating data in order to reduce the need to keep duplicate data current with the source node, as well as reduce db sanitation when source nodes are deleted. My schema is such that unique keys are the only duplicate data, which always point to a source node as the place to query from.

skwny
  • 2,930
  • 4
  • 25
  • 45
  • 2
    You seem to have read the relevant documentation that indicates the problems with the scenario. I also recommend reading some of the many [questions about using rules for filtering data](https://stackoverflow.com/search?tab=votes&q=%5bfirebase%5d%20rules%20are%20not%20filters). If those don't address your question, share the code that you intend to use to read data - as that is key to helping in this case. – Frank van Puffelen Sep 16 '17 at 20:09

1 Answers1

1

The structure you have proposed will work fine if you only ever read one user's information at a time -- you can simply always add /public when reading the public information, or read the $uid node directly when accessing as the user and wanting to read both public and private.

If, however, you plan to do any kind of querying, this data structure simply won't work as there will be no way to query while reading the public data without reading the private data. Instead, you would need to hoist the public and private up above the $uid level:

users
  - public
    - $uid
  - private
    - $uid

Once you get to this point, yes, you'll have to do two reads to access both bits of information. Remember a few things though:

  1. The private information can only be read by the user who authored it according to your rules, so you could easily just set up a listener on this single node as soon as a user logs in and then you'll always have it.
  2. Firebase connects via an ongoing realtime connection, which means that doing multiple reads is not likely as expensive as you think.

Another thing to consider regarding duplicate data is that Cloud Functions for Firebase can make denormalization pretty painless by handling the sync-on-update without having to code around it in the client.

Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • Thanks for the tip on the data structure! I didn't consider the impact on querying with what I was considering. I'm going use the structure you provided. For duplicate data I thought about using cloud functions, but stuck with the plan of not duplicating (as much as possible) in an effort to reduce complexity. – skwny Sep 17 '17 at 21:44