Declaring a function in Firestore rules

六月ゝ 毕业季﹏ 提交于 2020-04-11 18:10:31

问题


Here is a problem I am facing now with the Firestore security rules.

First of all here is an example of data structure I have in my firestore database:

userProfiles/userId/userData

companies/companyId/companyData

Looks pretty simple. Each userData includes and array named companies which includes all companyIds which this user has access to.

Now I need to write rules to allow read companyData only if companyId is in particular user info companies list.

Here are the rules which work for me:

service cloud.firestore {
  match /databases/{database}/documents {
    match /companies/{companyId} {
      allow read: if companyId in get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
    }
  }
}

Taking the fact that I am going to have much more rules, I would like to make them more readable and comfortable to reuse. According to this official guide I can create custom functions and according to this article they can be common and declared outside of the main rules bock.

I refactored my rules to look like this and it also worked for me:

service cloud.firestore {
  match /databases/{database}/documents {
    match /companies/{companyId} {
      allow read: if companyId in getUserCompanies()
    }
    function getUserCompanies() {
        return get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
    } 
  }
}

But now I would like to move function outside of the rules block to amke it even more clear:

service cloud.firestore {
  match /databases/{database}/documents {
    match /companies/{companyId} {
      allow read: if companyId in getUserCompanies()
    } 
  }
}

function getUserCompanies() {
    return get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
}

And that doesn't work. There is no any errors, I just receive the regular Read denied message from the simulator.

So the questions are: is it possible to move function outside as I did it in my example? Are there any obvious mistakes I've done here? is there better way to make my rules set even more clear?

P.S. I also tried to pass some parameters to that function, including user and company ids - no luck.


回答1:


Functions can be defined on any level in your rules file. But they only have access to variables that are defined in the scope where you define them. Anything else you have to pass in as a variable.

So this (useless) function works when defined globally:

function isTrue() {
  return true;
}

But this one won't, because it doesn't have access to request:

function isAdmin() {
  return (request.auth.token.email_verified && 
    request.auth.token.email.matches(".*@google.com"));
}

What I sometimes do is add a parameter to the function definition:

function isAdmin(request) {
  return (request.auth.token.email_verified && 
    request.auth.token.email.matches(".*@google.com"));
}

and then pass the variable in to the call:

  allow update: if isAdmin(request) || 
    (request.auth.uid == uid && isUnmodified(request, resource, 'name'));



回答2:


It’s not possible, rules only work on the scope they are defined, they mentioned very subtly here



来源:https://stackoverflow.com/questions/56442795/declaring-a-function-in-firestore-rules

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!