From e5b08c71c45f412fa55ea73e11f9de6d85f0c2a5 Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Sun, 23 Feb 2020 19:16:31 +1100 Subject: [PATCH] FIX: do not allow whispers to be accepted as answers This also cleans up the guardian so it is easier to reason about --- plugin.rb | 25 ++++++++++++++----------- spec/integration/solved_spec.rb | 8 ++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/plugin.rb b/plugin.rb index 83e214f..77d9601 100644 --- a/plugin.rb +++ b/plugin.rb @@ -188,7 +188,7 @@ SQL topic = post.topic topic ||= Topic.with_deleted.find(post.topic_id) if guardian.is_staff? - guardian.ensure_can_accept_answer!(topic) + guardian.ensure_can_accept_answer!(topic, post) DiscourseSolved.accept_answer!(post, current_user, topic: topic) @@ -204,7 +204,7 @@ SQL topic = post.topic topic ||= Topic.with_deleted.find(post.topic_id) if guardian.is_staff? - guardian.ensure_can_accept_answer!(topic) + guardian.ensure_can_accept_answer!(topic, post) DiscourseSolved.unaccept_answer!(post, topic: topic) render json: success_json @@ -422,13 +422,16 @@ SQL @@allowed_accepted_cache["allowed"].include?(category_id) end - def can_accept_answer?(topic) - topic && allow_accepted_answers_on_category?(topic.category_id) && ( - is_staff? || ( - authenticated? && ((!topic.closed? && topic.user_id == current_user.id) || - (current_user.trust_level >= SiteSetting.accept_all_solutions_trust_level)) - ) - ) + def can_accept_answer?(topic, post) + return false if !authenticated? + return false if !topic || !post || post.whisper? + return false if !allow_accepted_answers_on_category?(topic.category_id) + + return true if is_staff? + return true if current_user.trust_level >= SiteSetting.accept_all_solutions_trust_level + + topic.user_id == current_user.id && !topic.closed + end end @@ -440,7 +443,7 @@ SQL topic = (topic_view && topic_view.topic) || object.topic if topic - return scope.can_accept_answer?(topic) && object.post_number > 1 && !accepted_answer + return scope.can_accept_answer?(topic, object) && object.post_number > 1 && !accepted_answer end false @@ -449,7 +452,7 @@ SQL def can_unaccept_answer topic = (topic_view && topic_view.topic) || object.topic if topic - scope.can_accept_answer?(topic) && (post_custom_fields["is_accepted_answer"] == 'true') + scope.can_accept_answer?(topic, object) && (post_custom_fields["is_accepted_answer"] == 'true') end end diff --git a/spec/integration/solved_spec.rb b/spec/integration/solved_spec.rb index a3451eb..fda575a 100644 --- a/spec/integration/solved_spec.rb +++ b/spec/integration/solved_spec.rb @@ -90,6 +90,14 @@ RSpec.describe "Managing Posts solved status" do p1.reload expect(p1.custom_fields["is_accepted_answer"]).to eq("true") end + + it 'does not allow you to accept a whisper' do + whisper = Fabricate(:post, topic: topic, post_type: Post.types[:whisper]) + sign_in(Fabricate(:admin)) + + post "/solution/accept.json", params: { id: whisper.id } + expect(response.status).to eq(403) + end end describe '#unaccept' do