about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
authorThibG <thib@sitedethib.com>2019-05-14 19:05:02 +0200
committerEugen Rochko <eugen@zeonfederated.com>2019-05-14 19:05:02 +0200
commit14f6ce2885f7999f2fcbbdda6241a035271076d4 (patch)
treee0db9d9bf95e61cf4c96cd6b94fcc6f2c07daaa1 /app/models
parent564106c5d6ddd781064bdaeba1994328d7aceeae (diff)
Record account suspend/silence time and keep track of domain blocks (#10660)
* Record account suspend/silence time and keep track of domain blocks

* Also unblock users who were suspended/silenced before dates were recorded

* Add tests

* Keep track of suspending date for users suspended through the CLI

* Show accurate number of accounts that would be affected by unsuspending an instance

* Change migration to set silenced_at and suspended_at

* Revert "Also unblock users who were suspended/silenced before dates were recorded"

This reverts commit a015c65d2d1e28c7b7cfab8b3f8cd5fb48b8b71c.

* Switch from using suspended and silenced to suspended_at and silenced_at

* Add post-deployment migration script to remove `suspended` and `silenced` columns

* Use Account#silence! and Account#suspend! instead of updating the underlying property

* Add silenced_at and suspended_at migration to post-migration

* Change account fabricator to translate suspended and silenced attributes

* Minor fixes

* Make unblocking domains always retroactive
Diffstat (limited to 'app/models')
-rw-r--r--app/models/account.rb40
-rw-r--r--app/models/concerns/account_finder_concern.rb2
-rw-r--r--app/models/domain_block.rb7
-rw-r--r--app/models/status.rb4
-rw-r--r--app/models/user.rb2
5 files changed, 34 insertions, 21 deletions
diff --git a/app/models/account.rb b/app/models/account.rb
index 51e01246e..a894d5be5 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -28,8 +28,6 @@
 #  header_updated_at       :datetime
 #  avatar_remote_url       :string
 #  subscription_expires_at :datetime
-#  silenced                :boolean          default(FALSE), not null
-#  suspended               :boolean          default(FALSE), not null
 #  locked                  :boolean          default(FALSE), not null
 #  header_remote_url       :string           default(""), not null
 #  last_webfingered_at     :datetime
@@ -45,6 +43,8 @@
 #  actor_type              :string
 #  discoverable            :boolean
 #  also_known_as           :string           is an Array
+#  silenced_at             :datetime
+#  suspended_at            :datetime
 #
 
 class Account < ApplicationRecord
@@ -82,10 +82,10 @@ class Account < ApplicationRecord
   scope :local, -> { where(domain: nil) }
   scope :expiring, ->(time) { remote.where.not(subscription_expires_at: nil).where('subscription_expires_at < ?', time) }
   scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
-  scope :silenced, -> { where(silenced: true) }
-  scope :suspended, -> { where(suspended: true) }
-  scope :without_suspended, -> { where(suspended: false) }
-  scope :without_silenced, -> { where(silenced: false) }
+  scope :silenced, -> { where.not(silenced_at: nil) }
+  scope :suspended, -> { where.not(suspended_at: nil) }
+  scope :without_suspended, -> { where(suspended_at: nil) }
+  scope :without_silenced, -> { where(silenced_at: nil) }
   scope :recent, -> { reorder(id: :desc) }
   scope :bots, -> { where(actor_type: %w(Application Service)) }
   scope :alphabetic, -> { order(domain: :asc, username: :asc) }
@@ -165,25 +165,35 @@ class Account < ApplicationRecord
     ResolveAccountService.new.call(acct)
   end
 
-  def silence!
-    update!(silenced: true)
+  def silenced?
+    silenced_at.present?
+  end
+
+  def silence!(date = nil)
+    date ||= Time.now.utc
+    update!(silenced_at: date)
   end
 
   def unsilence!
-    update!(silenced: false)
+    update!(silenced_at: nil)
+  end
+
+  def suspended?
+    suspended_at.present?
   end
 
-  def suspend!
+  def suspend!(date = nil)
+    date ||= Time.now.utc
     transaction do
       user&.disable! if local?
-      update!(suspended: true)
+      update!(suspended_at: date)
     end
   end
 
   def unsuspend!
     transaction do
       user&.enable! if local?
-      update!(suspended: false)
+      update!(suspended_at: nil)
     end
   end
 
@@ -399,7 +409,7 @@ class Account < ApplicationRecord
           ts_rank_cd(#{textsearch}, #{query}, 32) AS rank
         FROM accounts
         WHERE #{query} @@ #{textsearch}
-          AND accounts.suspended = false
+          AND accounts.suspended_at IS NULL
           AND accounts.moved_to_account_id IS NULL
         ORDER BY rank DESC
         LIMIT ? OFFSET ?
@@ -427,7 +437,7 @@ class Account < ApplicationRecord
           LEFT OUTER JOIN follows AS f ON (accounts.id = f.account_id AND f.target_account_id = ?) OR (accounts.id = f.target_account_id AND f.account_id = ?)
           WHERE accounts.id IN (SELECT * FROM first_degree)
             AND #{query} @@ #{textsearch}
-            AND accounts.suspended = false
+            AND accounts.suspended_at IS NULL
             AND accounts.moved_to_account_id IS NULL
           GROUP BY accounts.id
           ORDER BY rank DESC
@@ -443,7 +453,7 @@ class Account < ApplicationRecord
           FROM accounts
           LEFT OUTER JOIN follows AS f ON (accounts.id = f.account_id AND f.target_account_id = ?) OR (accounts.id = f.target_account_id AND f.account_id = ?)
           WHERE #{query} @@ #{textsearch}
-            AND accounts.suspended = false
+            AND accounts.suspended_at IS NULL
             AND accounts.moved_to_account_id IS NULL
           GROUP BY accounts.id
           ORDER BY rank DESC
diff --git a/app/models/concerns/account_finder_concern.rb b/app/models/concerns/account_finder_concern.rb
index 0ac49cc12..ccd7bfa12 100644
--- a/app/models/concerns/account_finder_concern.rb
+++ b/app/models/concerns/account_finder_concern.rb
@@ -13,7 +13,7 @@ module AccountFinderConcern
     end
 
     def representative
-      find_local(Setting.site_contact_username.strip.gsub(/\A@/, '')) || Account.local.find_by(suspended: false)
+      find_local(Setting.site_contact_username.strip.gsub(/\A@/, '')) || Account.local.without_suspended.first
     end
 
     def find_local(username)
diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb
index 0b12617c6..84c08c158 100644
--- a/app/models/domain_block.rb
+++ b/app/models/domain_block.rb
@@ -17,8 +17,6 @@ class DomainBlock < ApplicationRecord
 
   enum severity: [:silence, :suspend, :noop]
 
-  attr_accessor :retroactive
-
   validates :domain, presence: true, uniqueness: true
 
   has_many :accounts, foreign_key: :domain, primary_key: :domain
@@ -36,4 +34,9 @@ class DomainBlock < ApplicationRecord
     return false if other_block.silence? && noop?
     (reject_media || !other_block.reject_media) && (reject_reports || !other_block.reject_reports)
   end
+
+  def affected_accounts_count
+    scope = suspend? ? accounts.where(suspended_at: created_at) : accounts.where(silenced_at: created_at)
+    scope.count
+  end
 end
diff --git a/app/models/status.rb b/app/models/status.rb
index 8d31fd382..2f6101b90 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -84,8 +84,8 @@ class Status < ApplicationRecord
   scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') }
   scope :with_public_visibility, -> { where(visibility: :public) }
   scope :tagged_with, ->(tag) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag }) }
-  scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced: false }) }
-  scope :including_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced: true }) }
+  scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced_at: nil }) }
+  scope :including_silenced_accounts, -> { left_outer_joins(:account).where.not(accounts: { silenced_at: nil }) }
   scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) }
   scope :not_domain_blocked_by_account, ->(account) { account.excluded_from_timeline_domains.blank? ? left_outer_joins(:account) : left_outer_joins(:account).where('accounts.domain IS NULL OR accounts.domain NOT IN (?)', account.excluded_from_timeline_domains) }
   scope :tagged_with_all, ->(tags) {
diff --git a/app/models/user.rb b/app/models/user.rb
index bce28aa5f..6941b040d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -88,7 +88,7 @@ class User < ApplicationRecord
   scope :confirmed, -> { where.not(confirmed_at: nil) }
   scope :enabled, -> { where(disabled: false) }
   scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
-  scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended: false }) }
+  scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where.not(accounts: { suspended_at: nil }) }
   scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) }
   scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) }