0

Hello so I have a role in my user collection and I wanted to write the rules depending on the role so if the role is the teacher you can have access to a little more stuff than the parent role. Now my question is there a possibility that I can access the role and use it for every collection, not only the user collection. Like a function that just checks every time what your role is? I'm doing this for the first time and I'm not pretty sure if I understand everything right, so far.

This is what I have in my rules so far:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  
  function isSignedIn() {
      return request.auth != null;
    }

   function isOneOfRoles(rsc, array) {
      return isSignedIn() && ((getRole() in array) || rsc.data.openWorld == true);
}
    function getRole() {
    return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'pädagoge';
}
   
      
    match /posts/{userPosts} {
      allow read: if isSignedIn();
      allow create: if isOneOfRoles(resource, ['pädagoge']);
    }
     match /messages/{messages} {
      allow read, write: if isSignedIn();
      
    }
  }
}

UPDATE

enter image description here

enter image description here

enter image description here

enter image description here

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
chin14
  • 175
  • 1
  • 4
  • 16
  • "is there a possibility that I can access the role and use it for every collection" => Yes, it is to define functions like you did or like [explained in the doc](https://firebase.google.com/docs/firestore/security/rules-conditions#custom_functions). I didn't check your rules but what is the problem you are currently encountering with these rules? – Renaud Tarnec Oct 11 '21 at 12:26
  • Looking at your rules a little bit more thoroughly it seems that you should probably use `request.resource` instead of `resource` in `if isOneOfRoles(resource, ['pädagoge']);` but this is depending on your exact queries. (Excerpts from the doc: "When writing data, you may want to compare incoming data to existing data. In this case, if your ruleset allows the pending write, the `request.resource` variable contains the future state of the document.") – Renaud Tarnec Oct 11 '21 at 12:34
  • I tried to test to create in userPost I'm getting this error: Function [get] called with incorrect path: /databases/(default)/documents/users/ – chin14 Oct 11 '21 at 12:35
  • How do you test? Via the simulator in the console OR via your app that is deployed? – Renaud Tarnec Oct 11 '21 at 12:43
  • Via the Simulator. – chin14 Oct 11 '21 at 12:44
  • Also, is there any change if you put the `getRole()` function above the `isOneOfRoles()`one? (the second one uses the first one) – Renaud Tarnec Oct 11 '21 at 12:45
  • "Via the Simulator" => do you assign a value to Firebase UID in the simulator? – Renaud Tarnec Oct 11 '21 at 12:45
  • I don't think I understand why to do this ? And no as you can see in the code – chin14 Oct 11 '21 at 12:55
  • "I don't think I understand why to do this?" Which part are you taking about? "And no as you can see in the code" Same question :-) Have a look at the following [answer](https://stackoverflow.com/a/57910883/3371862) for the emulator and user ID. – Renaud Tarnec Oct 11 '21 at 13:31
  • I'm still getting the same error – chin14 Oct 11 '21 at 13:39

1 Answers1

2

I've tried your security rules in the Firestore "Rules playground". You can see below that you need to do isOneOfRoles(request.resource, ['pädagoge']);: with only resource, the rule engine cannot check the value of the field openWorld beacause the future state of the document is contained in the request.resource variable, not in the resource one. See the doc for more details.

You also need to have a corresponding user in the users collection with a role field with the value pädagoge: in my example the user's UID is A1 (i.e. the ID of the Firestore doc in the users collection). See on the second and third screenshots below how we use this value in the Firebase UID field in the "Rules playground" simulator.

enter image description here

enter image description here (same screenshot as above, only the left pane was scrolled down to show the Firebase UID field)


enter image description here

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • I don't get it I did it just how you explain it and I'm still getting an error this time it's this : Error: simulator.rules line [19], column [37]. Property resource is undefined on object. – chin14 Oct 12 '21 at 10:10
  • Can you add in your question: 1/ The screenshots of the simulator like I did in the anwser. Don't forget that you need to have an `openWorld` field set to `true` in the new doc => See my first screenshot: under the button "Build Document" you can see the `openWorld` field. 2/ A screenshot of your users collection. – Renaud Tarnec Oct 12 '21 at 10:21
  • I updated the post and I have the field set to true – chin14 Oct 12 '21 at 10:29
  • Can you also show the top of the left pane of the simulator, pls – Renaud Tarnec Oct 12 '21 at 10:51
  • Yeah, did it :) – chin14 Oct 12 '21 at 11:04
  • Thanks, but I meant the top of the simulator configuration on the far left. The part above "password", like my first screenshot. – Renaud Tarnec Oct 12 '21 at 11:12
  • Oh sorry haha I updated the screenshots again – chin14 Oct 12 '21 at 11:16
  • You need to simulate the doc content by clicking the "Document Erstellen" button and add the `openWorld` field, see my first screenshot. – Renaud Tarnec Oct 12 '21 at 11:17
  • You are welcome ;-)BTW sometimes it may be interesting to directly test with a real query, to avoid some of the simulator "complexities" – Renaud Tarnec Oct 12 '21 at 11:23