0

I am trying to create a Reddit/Hacker News-like voting system on "posts" that users submit. I don't want to allow a user to vote for the same post more than once. What's the best way to prevent users from doing this using Firebase's security API?

Jake
  • 809
  • 1
  • 8
  • 18
  • possible duplicate of [A simple voting system: how to prevent duplicate votes](http://stackoverflow.com/questions/16863272/a-simple-voting-system-how-to-prevent-duplicate-votes) – Kato Apr 17 '14 at 06:21
  • Thanks for pointing that out, Kato -- I somehow missed that one. I think it would still be interesting to see how to count the "likes" users have added to a particular post (see comments in Alex Ghisculescu answer below). Any thoughts/ideas? It may be that numChildren() is the way to go for now, and we can deal with a situation where there are thousands of votes later. – Jake Apr 17 '14 at 16:06
  • In a situation where there are thousands of votes, just increment a counter every time a vote is recorded. I covered that as part of this example: http://stackoverflow.com/questions/22971571/how-do-i-prevent-duplicate-voting-while-incrementing-the-vote-count-on-firebase – Kato Apr 17 '14 at 20:40

1 Answers1

2

One way to do it would be to have a location for each post, and then children for user IDs that have liked the post. eg. https://<you>.firebaseio.com/posts/<post_id> and https://<you>.firebaseio.com/posts/<post_id>/likes/<user_id>.

Then, you could have a .validate rule that, when attempting to add push a new like to the list, first checks if https://<you>.firebaseio.com/posts/<post_id>/likes has that child already. So the rule would look like: (note: not tested)

"likes": {
  ".validate": "!data.hasChildren([newData.val()])",
},

(Happy to hear if there is a better way of doing this out there!)

Alex Ghiculescu
  • 7,522
  • 3
  • 25
  • 41
  • 1
    Maybe a dumb question, but how would you then get the overall count of the "likes" in this sort of system? – Jake Apr 16 '14 at 23:53
  • Also, you might be able to write the rule like this (also untested): "likes": { "$user": { ".write": "auth.uid == $user", ".validate": "!data.exists()" } } – Jake Apr 16 '14 at 23:58
  • I suppose to answer my first question/comment, you could pull into the client the list of all the users who "liked" the post and do a count on it client-side. I worry that if the list got very long (i.e., if the site was like Reddit big) it would impact performance... but until then, the answer is "good enough." I would still be curious to see if there's a smart way to do it with a likes number stored somewhere so you don't have to do all this counting client-side. – Jake Apr 17 '14 at 00:22
  • See http://stackoverflow.com/questions/15148803/in-firebase-is-there-a-way-to-get-the-of-children-of-a-node-w-out-loading-all - not looking too promising at the moment. – Alex Ghiculescu Apr 17 '14 at 05:25