From 03a798b202777b9966598b57c3fa6c186d35ba88 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 8 Feb 2013 19:04:14 -0500 Subject: [PATCH] Can clear flags on deleted posts if you're a moderator --- app/controllers/post_actions_controller.rb | 9 +++- app/controllers/posts_controller.rb | 12 ++--- app/models/post_action.rb | 2 +- lib/guardian.rb | 6 +++ spec/components/guardian_spec.rb | 23 +++++++++ .../post_actions_controller_spec.rb | 49 +++++++++++++++++++ 6 files changed, 90 insertions(+), 11 deletions(-) diff --git a/app/controllers/post_actions_controller.rb b/app/controllers/post_actions_controller.rb index 1edc1e313ae..7015b9cf90c 100644 --- a/app/controllers/post_actions_controller.rb +++ b/app/controllers/post_actions_controller.rb @@ -52,7 +52,7 @@ class PostActionsController < ApplicationController def clear_flags requires_parameter(:post_action_type_id) - raise Discourse::InvalidAccess unless guardian.is_admin? + guardian.ensure_can_clear_flags!(@post) PostAction.clear_flags!(@post, current_user.id, params[:post_action_type_id].to_i) @post.reload @@ -69,7 +69,12 @@ class PostActionsController < ApplicationController def fetch_post_from_params requires_parameter(:id) - @post = Post.where(id: params[:id]).first + finder = Post.where(id: params[:id]) + + # Include deleted posts if the user is a moderator + finder = finder.with_deleted if current_user.try(:has_trust_level?, :moderator) + + @post = finder.first guardian.ensure_can_see!(@post) end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 6af0c180d84..5f7b7a0efda 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -65,8 +65,6 @@ class PostsController < ApplicationController def show @post = find_post_from_params - guardian.ensure_can_see!(@post) - @post.revert_to(params[:version].to_i) if params[:version].present? post_serializer = PostSerializer.new(@post, scope: guardian, root: false) post_serializer.add_raw = true @@ -109,22 +107,18 @@ class PostsController < ApplicationController # Retrieves a list of versions and who made them for a post def versions post = find_post_from_params - guardian.ensure_can_see!(post) - render_serialized(post.all_versions, VersionSerializer) end # Direct replies to this post def replies post = find_post_from_params - guardian.ensure_can_see!(post) render_serialized(post.replies, PostSerializer) end def bookmark post = find_post_from_params - guardian.ensure_can_see!(post) if current_user if params[:bookmarked] == "true" PostAction.act(current_user, post, PostActionType.Types[:bookmark]) @@ -143,7 +137,9 @@ class PostsController < ApplicationController # Include deleted posts if the user is a moderator finder = finder.with_deleted if current_user.try(:has_trust_level?, :moderator) - - finder.first + + post = finder.first + guardian.ensure_can_see!(post) + post end end diff --git a/app/models/post_action.rb b/app/models/post_action.rb index 2036d9ff933..657b2674cce 100644 --- a/app/models/post_action.rb +++ b/app/models/post_action.rb @@ -66,7 +66,7 @@ class PostAction < ActiveRecord::Base r = PostActionType.Types.invert f = actions.map{|t| ["#{r[t]}_count", 0]} - Post.update_all(Hash[*f.flatten], id: post.id) + Post.with_deleted.update_all(Hash[*f.flatten], id: post.id) update_flagged_posts_count end diff --git a/lib/guardian.rb b/lib/guardian.rb index 7654a62fa19..d8df070ffac 100644 --- a/lib/guardian.rb +++ b/lib/guardian.rb @@ -109,6 +109,12 @@ class Guardian true end + def can_clear_flags?(post) + return false if @user.blank? + return false if post.blank? + @user.has_trust_level?(:moderator) + end + def can_revoke_admin?(admin) return false unless @user.try(:admin?) return false if admin.blank? diff --git a/spec/components/guardian_spec.rb b/spec/components/guardian_spec.rb index 355c2324ce9..4c12e0e8de8 100644 --- a/spec/components/guardian_spec.rb +++ b/spec/components/guardian_spec.rb @@ -68,6 +68,29 @@ describe Guardian do end + describe "can_clear_flags" do + let(:post) { Fabricate(:post) } + let(:user) { post.user } + let(:moderator) { Fabricate(:moderator) } + + it "returns false when the user is nil" do + Guardian.new(nil).can_clear_flags?(post).should be_false + end + + it "returns false when the post is nil" do + Guardian.new(moderator).can_clear_flags?(nil).should be_false + end + + it "returns false when the user is not a moderator" do + Guardian.new(user).can_clear_flags?(post).should be_false + end + + it "returns true when the user is a moderator" do + Guardian.new(moderator).can_clear_flags?(post).should be_true + end + + end + describe 'can_send_private_message' do let(:user) { Fabricate(:user) } let(:another_user) { Fabricate(:user) } diff --git a/spec/controllers/post_actions_controller_spec.rb b/spec/controllers/post_actions_controller_spec.rb index e9f93f86630..642ceb60c6d 100644 --- a/spec/controllers/post_actions_controller_spec.rb +++ b/spec/controllers/post_actions_controller_spec.rb @@ -85,6 +85,55 @@ describe PostActionsController do end + context 'clear_flags' do + + let(:flagged_post) { Fabricate(:post, user: Fabricate(:coding_horror)) } + + context "not logged in" do + it "should not allow them to clear flags" do + lambda { xhr :post, :clear_flags }.should raise_error(Discourse::NotLoggedIn) + end + end + + context 'logged in' do + let!(:user) { log_in(:moderator) } + + it "raises an error without a post_action_type_id" do + -> { xhr :post, :clear_flags, id: flagged_post.id }.should raise_error(Discourse::InvalidParameters) + end + + it "raises an error when the user doesn't have access" do + Guardian.any_instance.expects(:can_clear_flags?).returns(false) + xhr :post, :clear_flags, id: flagged_post.id, post_action_type_id: PostActionType.Types[:spam] + response.should be_forbidden + end + + context "success" do + before do + Guardian.any_instance.expects(:can_clear_flags?).returns(true) + PostAction.expects(:clear_flags!).with(flagged_post, user.id, PostActionType.Types[:spam]) + end + + it "delegates to clear_flags" do + xhr :post, :clear_flags, id: flagged_post.id, post_action_type_id: PostActionType.Types[:spam] + response.should be_success + end + + it "works with a deleted post" do + flagged_post.destroy + xhr :post, :clear_flags, id: flagged_post.id, post_action_type_id: PostActionType.Types[:spam] + response.should be_success + end + + + end + + end + + + + end + describe 'users' do