FIX: Category topics should not be deletable via review queue

FIX: Category topics should not be deletable via review queue

diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index fc699c8..3d4d0c2 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -550,9 +550,9 @@ class Admin::UsersController < Admin::AdminController
     if post = Post.where(id: params[:post_id]).first
       case params[:post_action]
       when 'delete'
-        PostDestroyer.new(current_user, post).destroy
+        PostDestroyer.new(current_user, post).destroy if guardian.can_delete_post_or_topic?(post)
       when "delete_replies"
-        PostDestroyer.delete_with_replies(current_user, post)
+        PostDestroyer.delete_with_replies(current_user, post) if guardian.can_delete_post_or_topic?(post)
       when 'edit'
         revisor = PostRevisor.new(post)
 
diff --git a/app/models/reviewable_flagged_post.rb b/app/models/reviewable_flagged_post.rb
index cd65edc..cc67cac 100644
--- a/app/models/reviewable_flagged_post.rb
+++ b/app/models/reviewable_flagged_post.rb
@@ -66,7 +66,7 @@ class ReviewableFlaggedPost < Reviewable
 
     build_action(actions, :ignore, icon: 'external-link-alt')
 
-    if guardian.is_staff?
+    if guardian.can_delete_post_or_topic?(post)
       delete = actions.add_bundle("#{id}-delete", icon: "far-trash-alt", label: "reviewables.actions.delete.title")
       build_action(actions, :delete_and_ignore, icon: 'external-link-alt', bundle: delete)
       if post.reply_count > 0
diff --git a/lib/guardian/post_guardian.rb b/lib/guardian/post_guardian.rb
index baf2b77..a8344e9 100644
--- a/lib/guardian/post_guardian.rb
+++ b/lib/guardian/post_guardian.rb
@@ -164,6 +164,10 @@ module PostGuardian
     false
   end
 
+  def can_delete_post_or_topic?(post)
+    post.is_first_post? ? post.topic && can_delete_topic?(post.topic) : can_delete_post?(post)
+  end
+
   # Deleting Methods
   def can_delete_post?(post)
     return false if !can_see_post?(post)
diff --git a/spec/models/reviewable_flagged_post_spec.rb b/spec/models/reviewable_flagged_post_spec.rb
index 59f4479..52413d1 100644
--- a/spec/models/reviewable_flagged_post_spec.rb
+++ b/spec/models/reviewable_flagged_post_spec.rb
@@ -44,6 +44,16 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
         expect(actions.has?(:disagree_and_restore)).to eq(false)
       end
 
+      it "doesn't include deletes for category topics" do
+        c = Fabricate(:category)
+        flag = PostActionCreator.spam(user, c.topic.posts.first).reviewable
+        actions = flag.actions_for(guardian)
+        expect(actions.has?(:delete_and_ignore)).to eq(false)
+        expect(actions.has?(:delete_and_ignore_replies)).to eq(false)
+        expect(actions.has?(:delete_and_agree)).to eq(false)
+        expect(actions.has?(:delete_and_replies)).to eq(false)
+      end
+
       it "returns `agree_and_restore` if the post is user deleted" do
         post.update(user_deleted: true)
         expect(reviewable.actions_for(guardian).has?(:agree_and_restore)).to eq(true)
diff --git a/spec/requests/admin/users_controller_spec.rb b/spec/requests/admin/users_controller_spec.rb
index 718b735..93af224 100644
--- a/spec/requests/admin/users_controller_spec.rb
+++ b/spec/requests/admin/users_controller_spec.rb
@@ -185,6 +185,36 @@ RSpec.describe Admin::UsersController do
         expect(response.status).to eq(200)
       end
 
+      it "won't delete a category topic" do
+        c = Fabricate(:category)
+        cat_post = c.topic.posts.first
+        put(
+          "/admin/users/#{user.id}/suspend.json",
+          params: suspend_params.merge(
+            post_action: 'delete',
+            post_id: cat_post.id
+          )
+        )
+        cat_post.reload
+        expect(cat_post.deleted_at).to be_blank
+        expect(response.status).to eq(200)
+      end
+
+      it "won't delete a category topic by replies" do
+        c = Fabricate(:category)
+        cat_post = c.topic.posts.first
+        put(
+          "/admin/users/#{user.id}/suspend.json",
+          params: suspend_params.merge(
+            post_action: 'delete_replies',
+            post_id: cat_post.id
+          )
+        )
+        cat_post.reload
+        expect(cat_post.deleted_at).to be_blank
+        expect(response.status).to eq(200)
+      end
+
       it "can delete an associated post and its replies" do
         reply = PostCreator.create(
           Fabricate(:user),

GitHub sha: 2e0a4000

1 Like

This commit has been mentioned on Discourse Meta. There might be relevant details there: