disable multiple voting on user comments - php

Description:
I am creating comment/reply functionality to a web app that I built. I have a post that I want to link these comments too. To decrease spam and encourage community involvement I want to implement a voting system on each comment/reply.
Problem:
I know how to set up the database and I know how to show upvotes/downvotes. The only thing I don't know what to do is to keep the vote... voted even if the user refreshes the page. I don't want a user to be able to vote up more than once on a single post. Something like the voting on this site, it tracks that you have already voted with a yellow upvote.
What I have thought of:
Place post id in cookie with the user_id appended to it. A simple check of the cookie can stop the user from voting again
Place a unique constraint in table post id... but this is where I get confused. Should I have a separate table just for voted posts? Database schema idea ( I think ) here: https://stackoverflow.com/a/12350981/185672
Keep all the ids in a session array and check against all voted on ids... but that would get huge.
Combination of cookie and database to reduce number of db calls.
In the future there may be 1000s of votes cast by a single user.
edit:
I figured out that storing the results in a database is a must. How can I check for every reply/comment if the user has valid voting privileges without making 1000s of calls?
Resources:
Helped with some further spamming problems, but didn't answer initial question:
https://stackoverflow.com/a/2333085/185672
Old solution that explains how to count votes but not keep the "upvote" checked.
http://www.9lessons.info/2009/08/vote-with-jquery-ajax-and-php.html
Bonus question:
If you guys know of a great script that can allow me to sync up a commenting system ( with votes ) into my already built app?
Also, I tried to find duplicates, but I just can't.

Yeah, just keep a separate table to track user votes. Since you know which user is requesting the page, you can easily join the votes table to determine the current user's eligibility to vote on each post on the page. For each post, if they're eligible, output one version of html, if they're not then output another.
Once the ajax request asks for the php file that does the vote, you can then check once more that that user is eligible to vote - I.e they're changing their vote, or they haven't voted before.
Take yahoo's news stories for example - when you request a page that you've made a comment on, your own comment has disabled voting buttons. With some hacking of the page inside the browser's dev tools, you can enable the buttons. You can even click on them and vote for your own post - though only once.
So, you can see that they got 2/3rds of it right, and output html based on the user's eligibility to vote. They also prevent multiple voting (server-side), they just don't do a server-side check to ensure you're not voting for your own comment.
Stack Overflow on the other hand, always shows the same html - but when you click to vote for your own comment, the server-side code baulks at the idea and the response is basically 'bugger-off! you can't do that' having received a negative result from the server, the javascript on the page pops up the message, rather than updating the vote count.

I suggest you create a "hidden field" in your page that stores information about the upvote/downvote by the user. This is how you would use it:
If the user upvotes/downvotes, the javsvscript on the on the shows the upvote, sets the field to maybe true to indicate the vote status and would also send an AJAX request to the server where the server would record the vote status in the user profile database.
Then whenever the post is re-loaded for a particular user, the server sets the hidden field server-side to true or false, depending on the vote record that is stored in the database. The JS would, on load, check the hidden field and set the vote on the page accordingly (you might need an extra hidden field to indicate whether it is an up or down vote).

Related

PHP / MYSQL Voting system for user blog/forum

I have a blog/forum system which has upvotes/downvote and each comment can also have an upvote/downvote like the reddit/stackoverflow system.
Which is the best way to ensure that a user who has already upvoted can't upvote it again?
I did consider the possibility of making a new row with an seperate upvote table.But if a post has 30 comments then the script would end up doing 30 database queries which can also put a tremendous load on my server. Another possibility would be to make a row for each upvote of user,query them together and check with post_id which is again infeasible.
So which is the best way for upvote/downvote system and what do sites like stumbleupon/reddit do? As in the moment he log's in, the he can see a red color maybe to the posts he has already upvoted
I believe that the best way to do it is to make a separate table for up/down votes, where you save user's id and is it up or down vote, and include reputation to comments/posts/whatever table.
If a user tries to do up/down vote you only need to check one comment (why 30?). Then you simply check in the separate table if the user has already voted for that comment/post. If so, you can remove vote (for example like in SO – if you press up vote twice, your upvote will be removed), or if person pressed a different button (f.e. downvote after upvote) you can just change his vote. The reason why I offered you to add reputation column to your posts/comments table and update it after all up,down votes is that then you will not need to get count(*) of reputation from that separate table and your comment/post reputation will be easy and fast to recieve, especially, if your database has many rows.

Allowing only one vote per person on a voting system

I'm working on a little posting system so I can post posts on my site and people can like and dislike it.
It looks like this:
At the moment you can upvote and downvote as many times as you would like. I know how to make the images not clickable with JavaScript but I also need a way to do this in PHP because someone could just make the buttons clickable again with fireBug or the Chrome Console.
This is probable the first thing i'm actually making in PHP so i'm still a beginner. Thanks for any suggestions.
I am not going to just write code for you, and there are probably dozens of workable examples on script sites. Here are a few tips to get you pointed in the right direction:
Session variables - $_SESSION[] - Check if it is set, and then set them after a vote. As long as they don't close the browser, they won't be able to vote again.
Cookies - $_COOKIE[] - Same as session, but can remain even if they close and open their browser again.
IP Address - $_SERVER['REMOTE_ADDR'] - Keep a record in a MySQL table of IPs and votes.
Login system - Only allow authenticated users to vote, and then keep track of the votes in the database.
Any combination of the above is acceptable. Hope that gets you pointed in the right direction.
Since you're going to learn this, I'm not going to post any complete code. I can give an overview, though.
The best way to do this is to store votes in a database table (probably MySQL):
| vote_id | user_id | post_id | vote |
Where:
vote_id is an auto-increment column that creates a unique ID for each vote
user_id is an identifier of who the user is that submitted this vote
post_id is an identifier for the post the user is voting on
vote determines whether this vote was up or down.
Now, you can form queries to determine whether or not somebody has already voted on the post, and act accordingly.
You need to validate it on the server-side i.e. in PHP code. You can do that either by IP address (if non-logged in user / guest) or by username (for logged in user)
There is no way you can stop users by client-side validation.

PHP vote system, how to stop spamming?

I want to set up a voting system which doesn't require people to log in, but they can vote as they want.
How do i stop people from spamming on voting (sending request to add the vote)? i know using client site scripting can easily stop it (from proper user), but what about server side (PHP). i don't want people to have that url and constantly hit it to increase the number.
Cheers
Implement reCAPTCHA - it's super easy to implement (takes maybe 10 minutes), is a good anti-spam measure, and serves a greater purpose (digitising books).
If you really want to go with cookies, have a look into evercookies. They're super-invasive, and very unethical, but hey, it's your site :)
You'll have to log their IP and/or set a cookie. The problem with cookies is the client can erase them and the problem with IP tracking is it can block more than one user if a NAT firewall is in the mix, but it will do well for the most part.
You can add a vote_tracking table:
vote_tracking
id
poll_id
session_id
When a user votes in a specific poll, you can update the row with their session id.
You will then need to implement some code to ensure you don't keep issuing queries to determine if user already voted in a poll. If you have an 'active' poll, you can do one lookup, then register a session var indicating that they have already voted, so no matter how many times the poll is rendered, you won't keep hitting the database. Obviously this will only work as long as the current session_id matches, when it differs you will have to issue the first query then reset the session var.
And I'd recommend a reaping mechanism so your table doesn't end up with a million+ rows. If you create a new 'active' poll, truncate the vote_tracking table, or archive it by renaming the table.
Also, the problem with IP tracking is that you will bork users who are behind a proxy, after the first person votes none of the others will be able to vote.

how to restrict user not to vote an article more than once?

in my application a user can post his/her article that other users can response upon ans vote up and down also like stackoverflow has for posted question ans answers.
How can I restrict user so that he/she can't vote twice ?
Just store user id in the voting table.
So, you can always check if particular user already voted.
article-id, user-id, vote time and vote value columns is enough
Two methods:
Client Side: Set into cookie (article IDs for last 5 or 10 votes ) and do not allow to vote again. This is easily hackable but allows you to implement without any database changes!
Server side: track each and every vote up and vote down in a table like <{userID}, {vote UP/DOWN}, {articleID}>
StackOverflow uses database to store all this data. They also lock your vote after some period so you cannot undo your action.
I think the best way to do that is to store all votes and user ids in database, and if it gets bigger you can remove old records from the database after one week/month/etc and restrict voting on items that are older than a week/month/etc, so no one will be able to vote twice on the same item.
You will need to use some kind of server side scripting to remember users by IP or some other unique data. You'll have to store the IP or other data and remember it. When the user tries to up/down vote again, you'll have to check against that to see if you should let them do so. You should let them do the opposite though, in case they want to change their vote. You can do this with PHP and MySQL (and lots of other things).

What's the safest way to remove data from mysql? (PHP/Mysql)

I want to allow users as well as me(the admin) to delete data in mysql.
I used to have remove.php that would get $_GETs from whatever that needed to be deleted such as... remove.php?action=post&posting_id=2. But I learned that anyone can simply abuse it and delete all my data.
So what's the safest way for users and me to delete information without getting all crazy and hard? I am only a beginner :)
I'm not sure if I can use POSTs because there is no forms and the data isn't changing.
Is sessions good? Or would there be too many with postings, user information, comments, etc.
Ex: James wants to delete one of his postings(it is posting_id=5). So he clicks the remove link and that takes him to remove.php?action=post&posting_id=5.
EDIT: Alright, so now I am a little confused. While I can't be 100% secure, how do I do this with $_POSTs?
SOO I should use GETs to get all the data to remove.php, THEN have a confirmation submit button and when users click on it, it put all the data into POSTs and delete from the dbc?
Deleting records is a kind of a scary practice. If you or someone makes a mistake there's no real recourse to resolve the issue. Expunged records are very hard to resurrect.
Instead of deleting records, you could add an "active" bit (e.g. Boolean) column that is toggled off when users "delete" records. Essentially your users would be suspending records by toggling them off and the records would be saved in case mistakes or abuse but appear "deleted" to the user. To make this work with your other queries, just add a where clause of active = 1.
You could then have a utility script that's run at some specific date interval that would clean out deprecated, past dated records. You'd also need some type of timestamp for this type of maintenance.
Just a thought. Take if for what it's worth.
I'll echo gurun8 in preferring to 'mark' records as deleted, instead of actually removing data. And then obviously, you'll need to check that the authenticated user has permission to delete the post.
However, it seems very important to mention that $_GET is not safe even with authentication because of cross-site request forgery.
Imagine if Amazon adding things to your cart based on a GET request. All I'd have to do is put an image on my page with that URL, and everyone who visited that page and logged into Amazon will have products added automatically.
To match your example, I don't like Jame's post, so i put an image on my site like this:
<img src='http://example.com/remove.php?action=post&posting_id=5'>
And I send him a link to my page, and ask him to check it out, hoping that at the time he's logged in to your site. Because, of course, he clicked that little 'keep me logged in' button.
So you are right to be concerned about using GET. If you don't want to litter pages with forms, then confirm the action by POST.
Well you have to start by authenticating the users with a login script.
If you want the simplest solution possible, then I'd suggest protecting the directory in which you have remove.php with a simple .htaccess username and password.
If different users have different rights for deleting database entries, then you probably should create a PHP login script and use PHP session.
Bonk me if I'm stupid, but I searched for quite some time for a simple PHP login tutorial that could be placed on a real site (doesn't use session_register(), uses mysql_real_escape_string(), htmlspecialchars() etc) and I simply couldn't find one!
Probably this one comes the closest, you just have to replace session_register() variables with $_SESSION ones for it to work without register_globals (default in PHP5).

Categories