FEATURE: Staff can suspend users when reviewing Akismet flagged posts (#60)

FEATURE: Staff can suspend users when reviewing Akismet flagged posts (#60)

diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 28673bd..4507f1f 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -21,6 +21,7 @@ en:
       confirm_spam: "Confirm Spam"
       not_spam: "Not Spam"
       confirm_delete: "Confirm Spam & Delete User"
+      confirm_suspend: "Confirm Spam & Suspend User"
       reject_spam_user_delete: "Delete User"
       dismiss: "Dismiss"
       ignore: "Ignore"
diff --git a/models/reviewable_akismet_post.rb b/models/reviewable_akismet_post.rb
index a5e6bdc..556b6d9 100644
--- a/models/reviewable_akismet_post.rb
+++ b/models/reviewable_akismet_post.rb
@@ -3,13 +3,27 @@
 require_dependency 'reviewable'
 
 class ReviewableAkismetPost < Reviewable
+  def self.action_aliases
+    { confirm_suspend: :confirm_spam }
+  end
+
   def build_actions(actions, guardian, _args)
     return [] unless pending?
 
-    build_action(actions, :confirm_spam, icon: 'check')
-    build_action(actions, :not_spam, icon: 'thumbs-up')
-    build_action(actions, :ignore, icon: 'times')
-    build_action(actions, :confirm_delete, icon: 'trash-alt', confirm: true, button_class: "btn-danger") if guardian.is_staff?
+    agree = actions.add_bundle("#{id}-agree", icon: 'thumbs-up', label: 'reviewables.actions.agree.title')
+
+    build_action(actions, :confirm_spam, icon: 'check', bundle: agree)
+
+    if guardian.can_suspend?(target_created_by)
+      build_action(actions, :confirm_suspend, icon: 'ban', bundle: agree, client_action: 'suspend')
+    end
+
+    if guardian.can_delete_user?(target_created_by)
+      build_action(actions, :confirm_delete, icon: 'trash-alt', bundle: agree, confirm: true)
+    end
+
+    build_action(actions, :not_spam, icon: 'thumbs-down')
+    build_action(actions, :ignore, icon: 'external-link-alt')
   end
 
   def post
@@ -45,10 +59,12 @@ class ReviewableAkismetPost < Reviewable
   end
 
   def perform_confirm_delete(performed_by, _args)
-    if Guardian.new(performed_by).can_delete_user?(post.user)
+    if Guardian.new(performed_by).can_delete_user?(target_created_by)
       bouncer.submit_feedback(post, 'spam')
       log_confirmation(performed_by, 'confirmed_spam_deleted')
-      UserDestroyer.new(performed_by).destroy(post.user, user_deletion_opts(performed_by))
+
+      PostDestroyer.new(performed_by, post).destroy unless post.deleted_at?
+      UserDestroyer.new(performed_by).destroy(target_created_by, user_deletion_opts(performed_by))
     end
 
     successful_transition :deleted, :agreed, recalculate_score: false
@@ -67,11 +83,12 @@ class ReviewableAkismetPost < Reviewable
     end
   end
 
-  def build_action(actions, id, icon:, bundle: nil, confirm: false, button_class: nil)
+  def build_action(actions, id, icon:, bundle: nil, confirm: false, button_class: nil, client_action: nil)
     actions.add(id, bundle: bundle) do |action|
       action.icon = icon
       action.label = "js.akismet.#{id}"
       action.confirm_message = 'js.akismet.reviewable_delete_prompt' if confirm
+      action.client_action = client_action
       action.button_class = button_class
     end
   end
diff --git a/spec/models/reviewable_akismet_post_spec.rb b/spec/models/reviewable_akismet_post_spec.rb
index dafaea7..bbe5b20 100644
--- a/spec/models/reviewable_akismet_post_spec.rb
+++ b/spec/models/reviewable_akismet_post_spec.rb
@@ -8,7 +8,9 @@ describe 'ReviewableAkismetPost' do
   before { SiteSetting.akismet_enabled = true }
 
   describe '#build_actions' do
-    let(:reviewable) { ReviewableAkismetPost.new }
+    let(:reviewable) { ReviewableAkismetPost.new(target: Fabricate(:post)) }
+
+    before { reviewable.created_new! }
 
     it 'Does not return available actions when the reviewable is no longer pending' do
       available_actions = (Reviewable.statuses.keys - [:pending]).reduce([]) do |actions, status|
@@ -46,10 +48,6 @@ describe 'ReviewableAkismetPost' do
       actions = reviewable_actions(guardian)
 
       expect(actions.has?(:confirm_delete)).to be true
-
-      expect(actions.to_a.
-        find { |a| a.id == :confirm_delete }.button_class).
-        to eq("btn-danger")
     end
 
     it 'Excludes the confirm delete action when the user is not an staff member' do
@@ -69,7 +67,7 @@ describe 'ReviewableAkismetPost' do
   describe 'Performing actions on reviewable' do
     let(:admin) { Fabricate(:admin) }
     let(:post) { Fabricate(:post_with_long_raw_content) }
-    let(:reviewable) { ReviewableAkismetPost.needs_review!(target: post, created_by: admin).reload }
+    let(:reviewable) { ReviewableAkismetPost.needs_review!(target: post, created_by: admin) }
 
     before do
       PostDestroyer.new(admin, post).destroy
@@ -196,14 +194,6 @@ describe 'ReviewableAkismetPost' do
 
         expect(post.reload.user).to be_nil
       end
-
-      it 'Does not delete the user when it cannot be deleted' do
-        post.update(user: admin)
-
-        reviewable.perform admin, action
-
-        expect(post.reload.user).to be_present
-      end
     end
   end
 

GitHub sha: 98ef2a18

This commit appears in #60 which was approved by eviltrout. It was merged by romanrizzi.