I know that there are a lot of threads available about creating a role system on firestore using security rules, but I still am unable to do it. I want to be able to have three different roles, with three different access levels.
- Administrator: Can read and write anything within the organisation
- Manager: Can read anything within the organisation, but not write unless it is their own document
- Employee: Can read and update their own data
I have found the documentation by google on this topic(https://firebase.google.com/docs/firestore/solutions/role-based-access), but I don't want every manager or administrator at every user and estabishment, because that is way too much duplicated data. Also, the roles should apply to anywhere within the organisation, it should not be different per subcollection.
My database:
organisations{
organisation1{
<data about organisation>
establishments{
establishment1{
<data about establishment>
}
establishment2{
<data about establishment>
}
}
people{
user1{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
}
user2{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
}
}
}
organisation2{
<data about organisation>
establishments{
establishment1{
<data about establishment>
}
establishment2{
<data about establishment>
}
}
people{
user1{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
documents{
some documents
}
}
user2{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
}
}
}
}
I know it is quite a lot, but it might help someone understand my problem a bit better. An administrator(someone with an accountType of Administrator) should be able to read and write anywhere within the organisation(organisation1 or organisation2). A manager should only be able to read everything, but not write unless it is their own data(So they can read anything but have the same write permissions as an employee, they can only write documents and anywhere in subcollections of those documents that have their request.auth.uid as the userId field, like user1 in organisation2 should be able to write the document of user1, as well as every document in any subcollection)
I currently have the following, and I think I need to get something like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
//Access levels:
//Medewerker: Can only see their own user document and all subcollections
//Beheerder: Can see any document within the organisation
//Administrator: Can see and do everything
function getAccountType(orgId, userId) {
return get(/databases/$(database)/documents/organisations/$(orgId)/people/$(userId)).data.accountType;
}
function isAdmin(orgID){
return getAccountType(orgID, request.auth.uid) == "Administrator";
}
function isBeheerder(orgID){
return getAccountType(orgID, request.auth.uid) == "Beheerder";
}
function isOwnData(userId){
return request.auth.uid == userId;
}
function authenticated(){
return request.auth != null;
}
match /organisations/{orgID} {
//Administrator rule goes here
allow write: if authenticated() && (isAdmin(resource.data.organisationId));
//Beheerder rule goes here
allow read: if authenticated() && (isAdmin(resource.data.organisationId) || isBeheerder(resource.data.organisationId));
match /people/{userID} {
//Medewerker rule goes here
allow read: if authenticated() && (isAdmin(resource.data.organisationId) || isBeheerder(resource.data.organisationId) || isOwnData(resource.data.userId));
allow update: if authenticated() && (isAdmin(resource.data.organisationId) || isOwnData(resource.data.userId));
allow create, delete: if authenticated() && (isAdmin(resource.data.organisationId));
}
}
}
}
The code that I have now doesn't give errors, but it doesn't behave the way I had expected. When I log in with an Administrator account, I first see only my own user record. If I log in with a Beheerder or Medewerker account, I don't get any records at all, not even my own. Also, if I change my account back to Administrator, I don't get my own record back. Is there any way to fix this/what is wrong with my code? Also, do I need an organisation ID in every document, or is there a workaround for it? My current code did have that. Thanks for your help!