Reputation: 2678
I found this nice answer to my question, here.
match /leagues/{league}/{document=**} {
allow read, write: if request.auth.uid ==
get(/databases/$(database)/documents/leagues/$(league)).data.creator
}
However, I do not get it to work. My implementation looks like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{user} {
allow read, write: if false;
}
match /employees/{user} {
allow read, write: if false;
}
// match /companies/{document=**} {
// allow read, write: if false;
// }
function isSignedIn() {
return request.auth != null;
}
function getEmployeeData() {
return get(/databases/$(database)/documents/employees/$(request.auth.uid)).data
}
// check if the current user has access to specific company
function accessCompany(companyId) {
return isSignedIn() && getEmployeeData()['companyId'] == companyId;
}
}
match /users/{user} {
allow get: if true;
allow list, create: if false;
allow update, delete: if request.auth.uid == user;
}
match /employees/{user} {
allow get: if request.auth.uid == user || hasRole('admin');
allow list: if hasRole('admin');
allow update: if hasRole('admin');
allow create, delete: if false;
}
match /companies/{company}/{document=**} { // <<<<<<<<<<<<<< IMPLEMENTATION HERE
allow read, write: if getEmployeeData()['companyId'] ==
get(/databases/$(database)/documents/companies/$(company)).data.id;
}
}
So with request.auth.uid
I lookup the document id of the company document in the employees collection. Then I compare this with the id of the requested company (sub) document companies/$(company)).data.id
.
I also tried
match /companies/{company}/{document=**} {
allow read, write: if getEmployeeData()['companyId'] == company;
Does anyone see my mistake or misunderstanding?
Upvotes: 0
Views: 226
Reputation: 3499
The function needs to be "anywhere upchain" from the match statement. I use a very deep database structure, with convenience functions at many levels. In your case, you could put the function like so:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function getEmployeeData() {
return get(/databases/$(database)/documents/employees/$(request.auth.uid)).data;
}
and it would be available to all of your other match statements.
Upvotes: 1
Reputation: 2678
My blueprint for this was quite misleading. The functions need to be located within the calling match statement. Now it works
match /companies/{company}/{document=**} {
function getEmployeeData() {
return get(/databases/$(database)/documents/employees/$(request.auth.uid)).data;
}
allow read, write: if getEmployeeData()['companyId'] == company;
}
Upvotes: 0