Skip to content
Open
9 changes: 8 additions & 1 deletion app/controllers/votes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ def create
post = Post.find(params[:post_id])

if post.user == current_user && !SiteSetting['AllowSelfVotes']
render(json: { status: 'failed', message: 'You may not vote on your own posts.' }, status: :forbidden)
render(json: { status: 'failed', message: I18n.t('votes.limits.own_post') },
status: :forbidden)
return
end

unless current_user.can_vote_on?(post)
render(json: { status: 'failed', message: I18n.t('votes.limits.restricted_ability') },
status: :forbidden)
return
end

Expand Down
9 changes: 9 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ def post_privilege?(name, post)
post.user == self || privilege?(name)
end

# Can the user vote on this post?
# This post does not check for the 'AllowSelfVotes' site setting, only
# whether this user has the ability to vote on this post.
# @param post [Post] to check
# @return [Boolean] check result
def can_vote_on?(post)
privilege?('unrestricted') || owns_post_or_parent?(post)
end

# Can the user rename a given comment thread?
# @param thread [CommentThread] thread to rename
# @return [Boolean] check result
Expand Down
5 changes: 4 additions & 1 deletion config/locales/strings/en.votes.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
en:
votes:
summary:
post_missing: 'Post not found'
post_missing: 'Post not found'
limits:
own_post: 'You may not vote on your own posts.'
restricted_ability: 'You must have the Participate Everywhere ability to vote on this post.'
39 changes: 28 additions & 11 deletions test/controllers/votes_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,45 @@ class VotesControllerTest < ActionController::TestCase
test 'should cast upvote' do
sign_in users(:standard_user)

post :create, params: { post_id: posts(:question_without_votes).id, vote_type: 1 }
try_create_vote posts(:question_without_votes), 1

assert_json_success
end

test 'should cast downvote' do
sign_in users(:standard_user)

post :create, params: { post_id: posts(:question_without_votes).id, vote_type: -1 }
try_create_vote posts(:question_without_votes), -1

assert_json_success
end

test 'should return correct modified status' do
post_id = posts(:question_without_votes).id
post = posts(:question_without_votes)

sign_in users(:standard_user)

post :create, params: { post_id: post_id, vote_type: 1 }
post :create, params: { post_id: post_id, vote_type: -1 }
try_create_vote post, 1
try_create_vote post, 1

assert_json_success(status: 'modified')
end

test 'should silently accept duplicate votes' do
post_id = posts(:question_without_votes).id
post = posts(:question_without_votes)

sign_in users(:standard_user)

post :create, params: { post_id: post_id, vote_type: 1 }
post :create, params: { post_id: post_id, vote_type: 1 }
try_create_vote post, 1
try_create_vote post, 1

assert_json_success(status: 'modified')
end

test 'should prevent self voting' do
sign_in users(:editor)

post :create, params: { post_id: posts(:question_without_votes).id, vote_type: 1 }
try_create_vote posts(:question_without_votes), 1

assert_response(:forbidden)
assert_valid_json_response
Expand Down Expand Up @@ -92,7 +92,7 @@ class VotesControllerTest < ActionController::TestCase
test 'should prevent deleted account casting votes' do
sign_in users(:deleted_account)

post :create, params: { post_id: posts(:question_without_votes).id, vote_type: 1 }
try_create_vote posts(:question_without_votes), 1

assert_response(:forbidden)
assert_valid_json_response
Expand All @@ -102,10 +102,27 @@ class VotesControllerTest < ActionController::TestCase
test 'should prevent deleted profile casting votes' do
sign_in users(:deleted_profile)

post :create, params: { post_id: posts(:question_without_votes).id, vote_type: 1 }
try_create_vote posts(:question_without_votes), 1

assert_response(:forbidden)
assert_valid_json_response
assert_json_response_message('You must be logged in to vote.')
end

test 'should not allow restricted users to vote' do
sign_in users(:basic_user)

try_create_vote posts(:question_without_votes), 1

assert_response(:forbidden)
assert_valid_json_response
assert_json_response_message(I18n.t('votes.limits.restricted_ability'))
end

private

def try_create_vote(target_post, vote_type)
post :create, params: { post_id: target_post.id,
vote_type: vote_type }
end
end
Loading