diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 340cfbc7fa4..7b26f70d08c 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -4650,6 +4650,7 @@ en: restored: Restored reviewables: + already_handled: "Thanks, but we've already reviewed that post and determined it does not need to be flagged again." priorities: low: "Low" medium: "Medium" diff --git a/lib/post_action_creator.rb b/lib/post_action_creator.rb index b4bb11f086a..0f78ab6fb6d 100644 --- a/lib/post_action_creator.rb +++ b/lib/post_action_creator.rb @@ -66,6 +66,13 @@ class PostActionCreator PostAction.limit_action!(@created_by, @post, @post_action_type_id) + reviewable = Reviewable.includes(:reviewable_scores).find_by(target: @post) + + if reviewable && flagging_post? && cannot_flag_again?(reviewable) + result.add_error(I18n.t("reviewables.already_handled")) + return result + end + # create meta topic / post if needed if @message.present? && [:notify_moderators, :notify_user, :spam].include?(@post_action_name) creator = create_message_creator @@ -115,6 +122,19 @@ class PostActionCreator private + def flagging_post? + PostActionType.notify_flag_type_ids.include?(@post_action_type_id) + end + + def cannot_flag_again?(reviewable) + return false if @post_action_type_id == PostActionType.types[:notify_moderators] + flag_type_already_used = reviewable.reviewable_scores.any? { |rs| rs.reviewable_score_type == @post_action_type_id } + not_edited_since_last_review = @post.last_version_at.blank? || reviewable.updated_at > @post.last_version_at + handled_recently = reviewable.updated_at > 24.hours.ago + + !reviewable.pending? && flag_type_already_used && not_edited_since_last_review && handled_recently + end + def notify_subscribers if self.class.notify_types.include?(@post_action_name) @post.publish_change_to_clients! :acted @@ -261,7 +281,7 @@ private end def create_reviewable(result) - return unless PostActionType.notify_flag_type_ids.include?(@post_action_type_id) + return unless flagging_post? return if @post.user_id.to_i < 0 result.reviewable = ReviewableFlaggedPost.needs_review!( diff --git a/spec/components/post_action_creator_spec.rb b/spec/components/post_action_creator_spec.rb index 74031a639a4..dd5c97f560d 100644 --- a/spec/components/post_action_creator_spec.rb +++ b/spec/components/post_action_creator_spec.rb @@ -115,6 +115,38 @@ describe PostActionCreator do expect(score.reviewed_by).to be_blank expect(score.reviewed_at).to be_blank end + + describe "When the post was already reviewed by staff" do + fab!(:admin) { Fabricate(:admin) } + + before { reviewable.perform(admin, :ignore) } + + it "fails because the post was recently reviewed" do + result = PostActionCreator.create(user, post, :inappropriate) + + expect(result.success?).to eq(false) + end + + it "succesfully flags the post if it was edited after being reviewed" do + reviewable.update!(updated_at: 25.hours.ago) + post.last_version_at = 30.hours.ago + + result = PostActionCreator.create(user, post, :inappropriate) + + expect(result.success?).to eq(true) + expect(result.reviewable).to be_present + end + + it 'succesfully flags the post if it was reviewed more than 24 hours ago' do + reviewable.update!(updated_at: 10.minutes.ago) + post.last_version_at = 1.minute.ago + + result = PostActionCreator.create(user, post, :inappropriate) + + expect(result.success?).to eq(true) + expect(result.reviewable).to be_present + end + end end end diff --git a/spec/models/reviewable_spec.rb b/spec/models/reviewable_spec.rb index ff2e31fd108..9b46eb7c529 100644 --- a/spec/models/reviewable_spec.rb +++ b/spec/models/reviewable_spec.rb @@ -266,7 +266,7 @@ RSpec.describe Reviewable, type: :model do end it "triggers a notification on update" do - reviewable = PostActionCreator.spam(moderator, post).reviewable + reviewable = PostActionCreator.create(moderator, post, :inappropriate).reviewable reviewable.perform(moderator, :disagree) expect { PostActionCreator.spam(Fabricate(:user), post) }