2
votes

What would be the best practice approach to implement security groups in Firestore for mobile apps (in this case react-native which effectively uses the "Web" interfaces). To give a more specific example:

  • Users using a mobile app with ability to "share" data (e.g. todo list) that is stored in Firestore [built using "Web" interface]
  • Aim for very low friction approach. Ideally starts with primary user have used the app using "Anonymous" authentication approach
  • Then user wants to "share" the data (e.g. todo list) with others securely

My question is really how do you implement the above in general, but covering aspects such as

  • Q1 - In terms of user experience approach what do you ask / get the user to do here? Build this into the app code?
  • Q2 - How do you structure the Firestore database to handle this? i.e. what would the structure look like - perhaps all data is just under Primary user UID
  • Q3 - How do you construct the Firestore rules to protect it? e.g. how do you do a "user-in-group" type check here? example?
  • Q4 - What would the application code look like for:
    • creating the user security group when the primary user hits "share"
    • adding users to the group?
    • accessing the data?

Overall keen to understand the lowest friction approach to having a user securely (on mobile app with firestore "web" sdk, i.e. react-native wrapper) share his data (e.g. todo list) to other people he/she specifically selects/approves somehow.

1

1 Answers

4
votes

For posterity, this has been answered on the google-cloud-firestore-discuss group: https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/google-cloud-firestore-discuss/KEs4is11LXc/xs2zIvQmCQAJ

TL;DR:

service cloud.firestore {
  match /databases/{database}/documents {
    match /lists/{listId} {
      // step 1
      allow create: if request.resource.data.owner == request.auth.uid;
      // step 3
      allow get: if exists(/databases/$(database)/documents/lists/$(listId)/users/$(request.auth.uid));
      match /users/{userId} {
        // step 2
        allow create: if request.auth.uid == get(/databases/$(database)/documents/lists/$(listId)).data.owner;
      }
    }
  }
}