Search code examples
firebasegoogle-cloud-firestorefirebase-security

Firebase / Firestore how to store user data


I have a project where users can create "companies" and invite other users to join this company.

My firestore database looks like this:

firestore companies

In each company the name of the company and the owner (Google uid) is stored.

In addition, in each company there are subcollections with further data about the company. e.g. tasks, which can then be viewed and edited by users who are invited to the company.

enter image description here

Currently there is a "users" collection where all users are stored. If a user is invited to a company it is stored in the "users" subcollection "companies":

enter image description here

match /companies/{compId} {
  function hasUserJoinedTheCompany() {
    return exists(/databases/$(database)/documents/users/$(request.auth.uid)/companies/$(compId));
  }
    
  allow read: if hasUserJoinedTheCompany();

  ...
}

With this structure and rules, the user can only access the data from the companies to which he is invited.

In my frontend it looks like this:

The user can switch between the companies (to which he is invited) in the upper left corner. And in blue highlighted he sees the "tasks" of the currently selected company.

enter image description here

My problem: I want to create a page where all users in a company are listed.

With my current structure I don't know how to make it work.

I was thinking of putting the users in a subcollection in "companies" (/companies/{companyId}/users/). So that it is easy to list all users in a company. But then I don't know how to list all the companies a user is invited to (as marked in red in the last screen shot).

Is there a solution for this, without firebase functions?


Solution

  • This is a Problem a lot of devs have when starting to use nonSQL databases. You can/should store the same data twice. In SQL databases we are all forced to link the data and not to store anything twice or more. In a nonSQL database you can and sometimes your realy should do that. In your case it is absolutely OK for you to store the data in 3 places:

    • all users in the users collection
    • users of a company in the companies/{id}/users collection
    • companies that a user belogs to to the users/{id}/companies collection

    That way you can very easy query all data you need and write very simple database rule to make everything secure. It would even make the automated sync trogh cloud functions more easy because you know when a company changes for what users to update the data and if a users changes for what companies to update the user data.

    I would recommend to just save there the basic data like name and if shown in a list some extra ones. But awoid to save the full user data and full company data on all places. All that is just the link for you to know exactly and easy where what belogs to and to get the main data very easy.