I want to create an increment field for article likes.
I am referring to this link: https://firebase.google.com/docs/database/android/save-data#save_data_as_transactions
In the example there is code for increment field:
if (p.stars.containsKey(getUid())) {
// Unstar the post and remove self from stars
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
} else {
// Star the post and add self to stars
p.starCount = p.starCount + 1;
p.stars.put(getUid(), true);
}
But how can I be sure if the user already liked/unliked the article?
In the example, user (hacker) might as well clear whole stars Map like this and it will save anyway:
p.stars = new HashMap<>();
and it will ruin the logic for other users who were already liked it.
I do not even think you can make rules for this, especially for "decrease count" action.
Any help, suggestions?
The security rules can do a few things:
ensure that a user can only add/remove their own
uid
to thestars
nodeensure that a user can only change the
starCount
when they are adding their ownuid
to thestars
node or removing it from therestarCount
by 1Even with these, it might indeed still be tricky to have a security rule that ensures that the
starCount
is equal to the number of uids in thestars
node. I encourage you to try it though, and share your result.The way I've seen most developers deal with this though is:
stars
node is not too large, this is reasonable).stars
intostarCount
. It could use child_added/child_removed events for incrementing/decrementing.Update: with working example
I wrote up a working example of a voting system. The data structure is:
When a user votes, the app sends a multi-location update:
And then to remove their vote:
This means the app needs to explicitly read the current value for
voteCount
, with:It's essentially a multi-location transaction, but then built in app code and security rules instead of the Firebase SDK and server itself.
The security rules do a few things:
Note that the rules don't:
.write
rule)The rules:
jsbin with some code to test this: http://jsbin.com/yaxexe/edit?js,console