Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to increment a count in Firebase without exposing current count to the client?

I would like to increment a count in Firebase, but without exposing the the current count to client.

I have read numerous helpful answers about using transactions to increment counters in Firebase, but all of these assume that the client has "read" access to the counter element. What if the client shouldn't have read access to the count, but I want to increment the value based on the user's actions?

Example:

Suppose I want to track views or impressions (or some other user action) on a specific piece of content. The counts are for internal eyes only, and perhaps to be shared privately with advertisers and partners -- but not shown to the users themselves, and we don't want to share that data with competitors by exposing it to the browser.

For cases like this, I could route things through a server process, in which the server process fetches the count and increments it, but that kinda defeats the purpose of using Firebase in the first place. Are there any other options to increment a "private" counter from the browser?

like image 573
Mark Carey Avatar asked Aug 23 '16 13:08

Mark Carey


1 Answers

I'm not sure why you're getting downvoted, as it seems like a valid question to me.

There is no server-side way to increment a counter in Firebase. With that knowledge, the only way to currently increment a counter is to have the client perform the increment. While you can secure that with rules to ensure that each user can only increment once, that each increment is a single step and many other things, the client-app will have to be able to read the current value.

The common solution to your problem would be to introduce a tally server. Each client can write it's "I've viewed this content" record into the database and then you have a server that listens to this queue and updates the count.

viewQueue
    $pushId
      uid: <uid>
      itemId: <itemId>
viewCounts
    $itemId: <totalViewCount>

You could secure this so that users can only write to the view queue and only the server (which likely will run under a service account can access the view counts:

{
  "rules": {
    "viewQueue": {
      ".read": false, // only the server can read this
      "$pushid": {
        ".write": "newData.exists() && !data.exists()"
      }
    },
    "viewCounts": {
      // only the server can access this
      ".read": false,
      ".write": false
    }
  }
}
like image 177
Frank van Puffelen Avatar answered Oct 21 '22 12:10

Frank van Puffelen