Backend: How to associate each Firebase user with their own data

Hi all,

I’m new to backend dev and want to learn how to associate each user in the DB with their own set of data (currently each user can see the data globally). I feel as though I am 90% there [ GITHUB REPO ], as the data is posting to the DB with the User ID and nested data (see screenshot). There are some issues with logging in and out, mainly cause I know it’s not setup 100% correct,

However I currently get an error in the console saying
"permission_denied at /campaigns: Client doesn't have permission to access the desired data."

I have set permissions in my Firebase console like this (following along from some Stack Overflow posts):

{
  "rules": {
    "campaigns": {
      "$userId": {
            ".read": "$userId === auth.uid",
            ".write": "$userId === auth.uid"   
      }
    }
  }
}

And the posted data looks like this:

I have a setDataToTable method like this:

addDataToTable () {
        this.updateCampaignData('camp/updateLoadingState', true)
        // TODO: Set specific data for each user
        const USER_KEY = this.$store.getters['auth/getUserId']
        db.ref().child('campaigns').child(USER_KEY).set({
          campaign_name: this.campaignName,
          campaign_created: new Date().toLocaleDateString(),
          campaign_link: this.returnGeneratedUrl,
          copy: 'COPY LINK'
        })
        this.resetForm()
        this.dialog = false
        this.$store.dispatch('camp/updateDataTable')
        this.updateCampaignData('camp/updateLoadingState', false)
        console.log('data pushed to db successfully')
      }
    },

Thank you in advance and if you need any more information, please just let me know :slight_smile:

1 Like

Haiiiyo! I haven’t looked at it too closely but I suggest trying to debug by logging in to get your userId and then writing to the database with firebase.database().ref('campaigns/' + userId).set() (or update()—by the way, you can update multiple locations at the same time by providing a list, and I think it’s really neat).

In fact, try doing without the child() method and provide the absolute path to the location you want to update inside the ref method first and see if it works—I don’t remember having need to use child() to do that at all (unless you have your Firebase database set up to facilitate multiple apps to save project space on the free plan and the rules you posted is only a snapshot—in that case it could just be a matter of incorrect path reference). Make sure that the higher-order path (in your path campaigns) exists before you attempt to write to it, too—if I’m not mistaken it would fail because a user does not have the permission to create campaigns if it doesn’t exist.

The simplest way to test this is to make dummy data in the structure that you intend to have and write to it. If it doesn’t work it could be that you have a misunderstanding of the hierarchy inside the rules or when specifying the path to write to on the client side. If all fails and you haven’t actually been able to write to anything successfully on the client side even once, then you are ignoring the documentation and you should seriously try to get a basic example working first. I hope that helps. :slight_smile:

Example:

firebase.database().ref(`/voting-app/users/${userID}/newPoll`).set(newPoll)
  .then(() => {
    console.log("New poll data sent!")
  })
  .catch(error => console.log("Error when creating new poll.", error));

should write to the realtime database that has the following rules:

{
  "rules": {
    "voting-app": {
      "users": {
        "$uid": {
          "newPoll": {
            ".read": "auth != null && auth.uid == $uid",
            ".write": "auth != null && auth.uid == $uid"
          }
        }
      }  
    }
  }
}

EDIT: added example.

3 Likes

Thank you so much for your detailed response, this is amazing. I reallllllly appreciate the help. :slight_smile:

1 Like