Reputation: 857
I have a situation in Firebase where users have roles. According some profile already defined in another "schema" users can delete, update, create, delete and update, etc, etc... Many combinations are made.
Ex.:
Users/:
user_1:
create: "ok"
delete: "no"
update: "ok"
user_2:
create: "no"
... etc ...
How manage this in firebase once ".write' permission do not accept dynamic condition? I found Bolt that have some alias (create(), update(), delete()) to that however, you have only create OR update OR delete. Once one is defined you cannot change.
Thanks
Upvotes: 3
Views: 6136
Reputation: 1215
Okay, so I'm going to assume that your data is structured something like below. This answer is my own subjective approach to how I would dynamically manage users accessing different parts of the DB.
NOTE::the chmod that I use stands for READ-WRITE-DELETE, instead of READ-WRITE-EXECUTE (i.e. 6=read+write but not delete, 7=full CRUD privileges). This sample DB is structured in 3 parts, and models a social media app. Also, the default for the "world" (3rd digit would most likely be only authenticated users. This is a very simple example:
root/
|
|-- user/ <-main node that contains profile info
| \uid <-node name - one for each user with sub-nodes containing profile info
| \user
| |-<UID> <-shows who has "user" privileges (1st digit)
| \group
| |-<UID> <-shows who has "group" privileges (1st digit)
| \permissions = 744 <-universal "user" entry rule
|
|-- trending/ <-node that contains global, read only info
| \user <-No one will be here for "trending"
| \group
| \feed-data
| \<POST_UUIDS> <-Data here
| \permissions = 444 <-Everyone can read the global feed
|
|-- messaging/
| \<chat-uuid-number-1>
| \user
| |-<User1>
| |-<User2>
| \group
| \messages node
| \<chat-uuid-number-2>
| \user
| |-<User8>
| |-<User5>
| \messages-node
|
| \permissions = 600 <-Only 2 users can read&send messages in their node
|
|-- chatrooms/ <-each node contains a list of UID, and list of messages
| \<room-uuid-number>
| \user
| |-<Admin1>
| |-<Admin2...>
| \group
| |-<uid1>
| |-<uid2>
| |-<uid3...infinity>
| \permissions = 760 <-Only admins have user privilege, users in chat can send and receive in the chat though
So this is a somewhat denormalized
database structure, like JSON databases are apparently supposed to be. Read about this here: https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html Each branch does not hold very much information except exactly what it is concerned with. Now, if you have a unified "inheritance" type structure, then you can use relative directory paths to check relative to the directory that a user is trying to access and isolate the validation rules in one spot- at your root - and then all the children nodes will be covered as long as they all have uniform structure for basic permissions!
So as long as your new data is NEVER going into the root directory or any of the main nodes/directories below it (you can write rules to ensure this also), you use data.parent() to get to the parent of your entry, then call parent() again to get to the main directory (e.g. chatroom), then you check the permissions value for each consecutive number, and match against the list of users/group/world:
".write": "data.parent().parent().child('permissions').val().beginsWith('6') && data.parent().child('users').child($uid).exists"
This (pseudocode?) checks the first digit of the permissions code, and then checks the node's "users" subdir to see if the current user has user privileges for that particular sub-node. Add a conditional OR after this to check and see if there's group
writing privileges and the user exists in the group. And so on... all from the root directory! Just make sure you guard against writing under '/' or '//' (write those conditionals first using '&&' so it fails the check before trying to get parent of the root, etc.) and it should work well.
This isn't an absolute structure, but I set mine up to be 'shallow' database all while restricting each entry under a major directory like "messages" to have a permissions code and check for that UID of the user making the DB read/write, and it saved me a ton of pain down the line. Although the last time I used it was about 5 months ago, I'm not sure if things have gotten simpler or simple tools/libraries exist now. Hope this helped!
Upvotes: 4
Reputation: 857
I found a solution... no ideia if is the best one... however, solve my problem. In any case, is a little painful to write the conditions.
and then in your firebase rules:
CUD means Create Update Delete. You can use chmod numbers as well (777, 765, etc).
Now, I need to discover how to write the conditions for -ud, --d, etc. :)
Upvotes: 3