1

I am using Firebase database to store student/teacher database. Right now my rules allow teachers to read their student's data by calling a callable function which provide the data related with the student. (Firebase admin sdk)

What I am trying to do -

  1. Allow teachers to invite students to add them under his student list. Teachers can send an invite by calling a http firebase function to send invitation via email.
  2. Once students clicks on the invite link to accept, they get added under the teacher who sent them invitation.
  3. After acceptance, teacher can read the data of all the student registered under him by calling a callable function. This is where I have problem. I can read properly with no problem but calling a function everytime page refresh, are gonna be expensive hence I decided to play with the firebase rules.

Below is my structure of firebase database. How can I design the database rule such a way that a teacher can read their student data without calling the callable function.

I have found something similar on this stackoverflow post -

DATABASE

{
    "teachers":
    {
        "teacher-unique-id":
        {
            "invited":
            {
                "auto-gen-key-id": "student-email-id-1",
                "auto-gen-key-id": "student-email-id-2",
                "auto-gen-key-id": "student-email-id-3",
                "auto-gen-key-id": "student-email-id-4",
                "auto-gen-key-id": "student-email-id-5",
            },
            "accepted":
            {
                "auto-gen-key-id": "unique-student-id-1",
                "auto-gen-key-id": "unique-student-id-2",
                "auto-gen-key-id": "unique-student-id-3",
            }
        }
    },
    "students":
    {
        "unique-student-id-1":
        {
            "session-id-1":
            {
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
            },
            "session-id-2":
            {
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
            }
        },
        "unique-student-id-2":
        {
            "session-id-1":
            {
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
            },
            "session-id-2":
            {
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
                "auto-gen-key-id": "data",
            }
        }
    }
}

Firebase rules - This is basically default one I am using. How can I modify them to do what I want to achieve?

 {
  /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
  "rules": {
    "teachers":{
      "$uid":{
        "studentsId":{
          ".read": "$uid===auth.uid", 
        }
      }
    },
    "students":{
      "$uid":{
        ".read": "$uid===auth.uid",
            ".write": "$uid===auth.uid"
      } 
    }
  }
}
Greyfrog
  • 926
  • 1
  • 8
  • 19

1 Answers1

1

You store the accepted students for a teacher as:

"teachers": {
  "teacher-unique-id": {
    "accepted": {
      "auto-gen-key-id": "unique-student-id-1",
      "auto-gen-key-id": "unique-student-id-2",
      "auto-gen-key-id": "unique-student-id-3",
    }
  }
},

The problem is that with this structure you need to search across all values under accepted to know if the teacher knows a student, and you can't search in security rules. So I recommend storing the data as:

"teachers": {
  "teacher-unique-id": {
    "accepted": {
      "unique-student-id-1": true, 
      "unique-student-id-2": true, 
      "unique-student-id-3": true, 
    }
  }
},

With that structure, you can allow the teacher to read the data for students that have accepted them with:

{
  "rules": {
    ...
    "students":{
      "$uid":{
        ".read": "$uid===auth.uid || 
               root.child('teachers').child(auth.uid).child('accepted').child($uid).exists()",
        ".write": "$uid===auth.uid"
      } 
    }
  }
}

Note that this grants the teacher access to /student/$studentid, not as /students. Since rules are not filters they'll need to access each student's data individually.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • van Pufflelen - I know I should ask this question separately but I want to try your suggestion first before even going to stackoverflow. My Question is - How can I split my cloud functions into separate files and pass functions and firebase object to make accessible from other files? I don't want to do require in each and every file i split. Also initializing firebase.initializeApp() in every file, conflicts with each other and throw error. Do you have best practice recommendation. I have looked into some stackoverflow questions already but they are so confusing. – Greyfrog May 04 '20 at 21:46
  • If I need to scale things out, I typically write my separate files almost like node modules, without any dependency on Cloud Functions. Then in my main `index.js` I include/require all of those "modules" and just have their Cloud Functions wrappers. – Frank van Puffelen May 04 '20 at 22:52
  • I did split my code. I thought it would be different than creating separate module like I used to in in nodejs. Anyway, I have a small query, "should" I used firebase to create realtime chat app? I have read several blogs and stackoverflow question and I am now confused. can you please advice me? – Greyfrog May 08 '20 at 20:52
  • Technology recommendations are off-topic on Stack Overflow. But as your searches probably showed, there are hundreds of tutorials on how to build a chat app with Firebase Realtime Database. – Frank van Puffelen May 08 '20 at 20:56
  • I am sorry and I know but I was just asking for your opinion since you are an engineer at Firebase technology so I guess who would be a better person to give straight answer on this topic. I just wanted to know if it is a good tech stack to go forward and develop chat application. Thank you. – Greyfrog May 08 '20 at 22:16