Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Like/Dislike function for Firebase

The system itself is pretty easy to understand but tricky to implement. Moreover, security reasons made me think how to do that.

I was thinking to make the function work in frontend firebase scripts simply doing everything there as checking if there is already like/dislike posted by this user and remove/add/switch if user clicked. The problem lies in security of this method: can't user create a new function which won't check if the like was posted?

And if that's possible, how should this system work? Right now my logic:

Clicked like:
    locally activate/deactivate like button and remove dislike active class if on
    check docs for this user/doc like
        `1`? -> remove this doc from collection
        `0`? -> switch to `1`, because `0` is dislike
        `undefined`? -> create doc with `vote: 1`
            change (+1/-1 or +2/-2) the value of post votes fields

Same for dislike. But this sounds really complicated as for such a small feature. Maybe it is possible to wave additional collection with user/votes without losing that level of security? Or using http-triggers may help with this somehow? This feature would be much easier on some PHP-like languages, so I am freaking out right now.

like image 656
Telion Avatar asked Dec 08 '22 15:12

Telion


1 Answers

Here are my assumptions.

  1. You have a post with a unique id, let's call it post_id
  2. You have a user with a unique id, let's call it user_id
  3. There are 3 valid states: (Undefined), (Like), (Dislike)

Basic process follows

To store the likes/dislikes, you create a collection called feelings which uses post_id+':'+user_id as it's document id (this makes it easy to look up).

Documents in feelings have a single field called state that stores -1 for dislike, 1 for like.

As you mention, you can simply set or overwrite this value to whatever the user desires. If they decide to remove their 'feeling' and neither like or dislike, issue a delete command (this is cheaper than doing a write to set state to 0).

Use Cloud Functions to listen to the feelings collection and update the post documents like/dislike count based on how this state changes (or gets created/deleted).

Security Rules can enforce only allow states of -1 and 1, and if you're using Firebase Auth, you can trivially enforce only allowing the user matching user_id from being able to change state.

What have you got now?

You now have a system with the following properties:

  • Users can like and dislike posts
  • Users can remove and/or change their like/dislikes
  • Users can only like or dislike a post once - they cannot do it multiple times
  • Only valid states (like, dislike) can be written to the database
  • Only the user can update their likes/dislikes
  • Scalable: Whether it's 10 posts, or millions of posts, this system will work

Bonus credit

Using the same Cloud Functions event you register to update counts, you can also use this to add or remove from a list of user ids in both a like and dislike array. This would allow you to list out users who liked or disliked a post without have to query for each individual document in the feelings collection

Also remember that Cloud Functions has is a small chance it gets triggered more than once for a single event. If you want the counts to be guaranteed to be accurate, either make the code idempotent, or just have a manually triggered 'recount' process you can trigger if you or a user detects the counts seem off by one.

like image 92
Dan McGrath Avatar answered Dec 11 '22 11:12

Dan McGrath