From 83579695593c941ab39ab545c10a7f711bf715fc Mon Sep 17 00:00:00 2001
From: ThibG <thib@sitedethib.com>
Date: Tue, 15 Dec 2020 17:23:58 +0100
Subject: [PATCH] Fix admins being able to suspend their instance actor
 (#14567)

* Fix admin being able to suspend their own instance account

* Add text about the instance's own actor in admin view

* Change instance actor notice from flash message to template

* Do not list local instance actor in account moderation list
---
 app/models/account.rb                   | 3 ++-
 app/models/account_filter.rb            | 2 +-
 app/policies/account_policy.rb          | 4 ++--
 app/views/admin/accounts/show.html.haml | 4 ++++
 config/locales/en.yml                   | 1 +
 spec/models/account_filter_spec.rb      | 2 +-
 6 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/app/models/account.rb b/app/models/account.rb
index e21b353e9..80eb92a71 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -100,6 +100,7 @@ class Account < ApplicationRecord
   scope :sensitized, -> { where.not(sensitized_at: nil) }
   scope :without_suspended, -> { where(suspended_at: nil) }
   scope :without_silenced, -> { where(silenced_at: nil) }
+  scope :without_instance_actor, -> { where.not(id: -99) }
   scope :recent, -> { reorder(id: :desc) }
   scope :bots, -> { where(actor_type: %w(Application Service)) }
   scope :groups, -> { where(actor_type: 'Group') }
@@ -222,7 +223,7 @@ class Account < ApplicationRecord
   end
 
   def suspended?
-    suspended_at.present?
+    suspended_at.present? && !instance_actor?
   end
 
   def suspended_permanently?
diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb
index 7b6012e0f..2b001385f 100644
--- a/app/models/account_filter.rb
+++ b/app/models/account_filter.rb
@@ -45,7 +45,7 @@ class AccountFilter
   def scope_for(key, value)
     case key.to_s
     when 'local'
-      Account.local
+      Account.local.without_instance_actor
     when 'remote'
       Account.remote
     when 'by_domain'
diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb
index 262ada42e..672e1786b 100644
--- a/app/policies/account_policy.rb
+++ b/app/policies/account_policy.rb
@@ -14,7 +14,7 @@ class AccountPolicy < ApplicationPolicy
   end
 
   def suspend?
-    staff? && !record.user&.staff?
+    staff? && !record.user&.staff? && !record.instance_actor?
   end
 
   def destroy?
@@ -62,6 +62,6 @@ class AccountPolicy < ApplicationPolicy
   end
 
   def memorialize?
-    admin? && !record.user&.admin?
+    admin? && !record.user&.admin? && !record.instance_actor?
   end
 end
diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml
index ae527cc23..27e1f80a7 100644
--- a/app/views/admin/accounts/show.html.haml
+++ b/app/views/admin/accounts/show.html.haml
@@ -1,6 +1,10 @@
 - content_for :page_title do
   = @account.acct
 
+- if @account.instance_actor?
+  .flash-message.notice
+    %strong= t('accounts.instance_actor_flash')
+
 = render 'application/card', account: @account
 
 - account = @account
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 1f5798fcc..83f75b28f 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -60,6 +60,7 @@ en:
       one: Follower
       other: Followers
     following: Following
+    instance_actor_flash: This account is a virtual actor used to represent the server itself and not any individual user. It is used for federation purposes and should not be suspended.
     joined: Joined %{date}
     last_active: last active
     link_verified_on: Ownership of this link was checked on %{date}
diff --git a/spec/models/account_filter_spec.rb b/spec/models/account_filter_spec.rb
index 176a0eeac..0cdb373f6 100644
--- a/spec/models/account_filter_spec.rb
+++ b/spec/models/account_filter_spec.rb
@@ -5,7 +5,7 @@ describe AccountFilter do
     it 'defaults to recent local not-suspended account list' do
       filter = described_class.new({})
 
-      expect(filter.results).to eq Account.local.recent.without_suspended
+      expect(filter.results).to eq Account.local.without_instance_actor.recent.without_suspended
     end
   end