Reputation: 291
just a simple question: whats wrong with this and why this is not working?
Trying to get access with user who has role 'admin' in users section to the /titles/{anyTitle} but still get
Missing or insufficient permissions.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow write: if false;
allow read: if false;
}
function userCanWrite () {
return get(/databases/{database}/documents/users/$(request.auth.uid)).data.role == "admin";
}
match /titles/{anyTitle=**} {
allow read: if request.auth != null;
allow write: if userCanWrite();
}
}
}
I tried another rule from official documents
get(/databases/{database}/documents/users/$(request.auth.uid)).data.isAdmin == true;
and this is not working too
Support helped me find the solution this is how you should do:
db structure:
users -> {{ userid }} -> { role: "admin" }
database rule settings:
get(usersPath/$(request.auth.uid)).role == "admin" || get(usersPath/$(request.auth.uid)).data.role == "admin";
Upvotes: 18
Views: 12377
Reputation: 1275
This is the Firestore rule I use to check if the user is admin.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if true;
allow write: if userIsAdmin();
}
function userIsAdmin() {
return getUserData().userRole == 'Admin';
}
function getUserData() {
return get(/databases/$(database)/documents/User/$(request.auth.uid)).data;
}
}
}
Upvotes: 0
Reputation: 1951
What worked for me was moving the userCanWrite
function above my rules. It appears that the function has to be defined before any of the match
rules that call it. Maddening :-)
Upvotes: 1
Reputation: 1237
You should use $(database)
instead of {database}
in your code:
get(/databases/{database}/documents/users/$(request.auth.uid)).data.role == "admin";
Upvotes: 5
Reputation: 424
I contacted to the Firebase support to report that bug and they gave me a temporary solution on this. It seems that they are having a bug in their systems on the security rules side. They say that the documentation is ok, but for now we should workaround this way:
get(path).data.field == true || get(path).field == true;
Because the bug is that data object isn't populated, you should check both properties. There's no ETA for launching a solution on this bug, so I asked they if they could give me an advice when they solved this issue, so I'll keep this answer up-to-date with their information.
Upvotes: 20
Reputation: 20011
So the way I've solved it is I've created another Collection
Called admins
Then I've just added the uid
of the user I needed there as such -
Here is my database structure - https://i.sstatic.net/U2YnN.png
And here is the rules
service cloud.firestore {
match /databases/{database}/documents {
function isAdmin() {
return exists(/databases/$(database)/documents/admins/$(request.auth.uid));
}
match /tasks/{anyTask} {
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if request.auth != null && isAdmin();
allow delete: if request.auth != null && isAdmin();
}
}
}
You can view my full Open Source project here: https://github.com/metaburn/doocrate
Upvotes: 5