From ba81e4e0192371e1fc07ad6d7cf58e86766d0e77 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Fri, 13 Sep 2024 11:11:10 +0200
Subject: [PATCH] Fix inability to locally suspend remotely-suspended accounts
 in moderation interface (#31899)

---
 app/models/account.rb                         |  4 +++
 app/models/admin/account_action.rb            |  2 +-
 app/views/admin/account_actions/new.html.haml |  2 +-
 app/views/admin/reports/_actions.html.haml    |  6 ++--
 spec/models/account_spec.rb                   | 29 +++++++++++++++++++
 5 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/app/models/account.rb b/app/models/account.rb
index 0a2cff2fe..a4cab99f7 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -259,6 +259,10 @@ class Account < ApplicationRecord
     suspended_at.present? && !instance_actor?
   end
 
+  def suspended_locally?
+    suspended? && suspension_origin_local?
+  end
+
   def suspended_permanently?
     suspended? && deletion_request.nil?
   end
diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb
index 4be58ba85..7c66b6e64 100644
--- a/app/models/admin/account_action.rb
+++ b/app/models/admin/account_action.rb
@@ -74,7 +74,7 @@ class Admin::AccountAction
     end
 
     def disabled_types_for_account(account)
-      if account.suspended?
+      if account.suspended_locally?
         %w(silence suspend)
       elsif account.silenced?
         %w(silence)
diff --git a/app/views/admin/account_actions/new.html.haml b/app/views/admin/account_actions/new.html.haml
index 5b98582d8..c4311eba9 100644
--- a/app/views/admin/account_actions/new.html.haml
+++ b/app/views/admin/account_actions/new.html.haml
@@ -1,7 +1,7 @@
 - content_for :page_title do
   = t('admin.account_actions.title', acct: @account.pretty_acct)
 
-- if @account.suspended?
+- if @account.suspended_locally?
   .flash-message.alert
     = t('admin.account_actions.already_suspended')
 - elsif @account.silenced?
diff --git a/app/views/admin/reports/_actions.html.haml b/app/views/admin/reports/_actions.html.haml
index 7317d401e..ef016e949 100644
--- a/app/views/admin/reports/_actions.html.haml
+++ b/app/views/admin/reports/_actions.html.haml
@@ -27,7 +27,7 @@
         = form.button t('admin.accounts.silence'),
                       name: :silence,
                       class: 'button button--destructive',
-                      disabled: report.target_account.silenced? || report.target_account.suspended?,
+                      disabled: report.target_account.silenced? || report.target_account.suspended_locally?,
                       title: report.target_account.silenced? ? t('admin.account_actions.already_silenced') : ''
       .report-actions__item__description
         = t('admin.reports.actions.silence_description_html')
@@ -36,8 +36,8 @@
         = form.button t('admin.accounts.suspend'),
                       name: :suspend,
                       class: 'button button--destructive',
-                      disabled: report.target_account.suspended?,
-                      title: report.target_account.suspended? ? t('admin.account_actions.already_suspended') : ''
+                      disabled: report.target_account.suspended_locally?,
+                      title: report.target_account.suspended_locally? ? t('admin.account_actions.already_suspended') : ''
       .report-actions__item__description
         = t('admin.reports.actions.suspend_description_html')
     .report-actions__item
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 2ec7aafc5..e8d761f38 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -10,10 +10,39 @@ RSpec.describe Account do
 
     let(:bob) { Fabricate(:account, username: 'bob') }
 
+    describe '#suspended_locally?' do
+      context 'when the account is not suspended' do
+        it 'returns false' do
+          expect(subject.suspended_locally?).to be false
+        end
+      end
+
+      context 'when the account is suspended locally' do
+        before do
+          subject.update!(suspended_at: 1.day.ago, suspension_origin: :local)
+        end
+
+        it 'returns true' do
+          expect(subject.suspended_locally?).to be true
+        end
+      end
+
+      context 'when the account is suspended remotely' do
+        before do
+          subject.update!(suspended_at: 1.day.ago, suspension_origin: :remote)
+        end
+
+        it 'returns false' do
+          expect(subject.suspended_locally?).to be false
+        end
+      end
+    end
+
     describe '#suspend!' do
       it 'marks the account as suspended and creates a deletion request' do
         expect { subject.suspend! }
           .to change(subject, :suspended?).from(false).to(true)
+          .and change(subject, :suspended_locally?).from(false).to(true)
           .and(change { AccountDeletionRequest.exists?(account: subject) }.from(false).to(true))
       end