about summary refs log tree commit diff
path: root/app/controllers
diff options
context:
space:
mode:
authorThibaut Girka <thib@sitedethib.com>2020-09-28 14:13:30 +0200
committerThibaut Girka <thib@sitedethib.com>2020-09-28 14:13:30 +0200
commita7aedebc310ad7d387c508f7b0198a567a408fe6 (patch)
tree53fe5fd79302e796ced8000904e46edd84dc1319 /app/controllers
parent787d5d728923393f12421a480b3c7aee789a11fe (diff)
parentd88a79b4566869ede24958fbff946e357bbb3cb9 (diff)
Merge branch 'master' into glitch-soc/merge-upstream
Conflicts:
- `Gemfile.lock`:
  Not a real conflict, upstream updated dependencies that were too close to
  glitch-soc-only ones in the file.
- `app/controllers/oauth/authorized_applications_controller.rb`:
  Upstream changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc's theming system.
  Ported upstream changes.
- `app/controllers/settings/base_controller.rb`:
  Upstream refactored and changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc's theming system.
  Ported upstream changes.
- `app/controllers/settings/sessions_controller.rb`:
  Upstream refactored and changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc's theming system.
  Ported upstream changes.
- `app/models/user.rb`:
  Upstream refactored and changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc not preventing moved accounts from logging
  in.
  Ported upstream changes while keeping the ability for moved accounts to log
  in.
- `app/policies/status_policy.rb`:
  Upstream refactored and changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc's local-only toots.
  Ported upstream changes.
- `app/serializers/rest/account_serializer.rb`:
  Upstream refactored and changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc's ability  to hide followers count.
  Ported upstream changes.
- `app/services/process_mentions_service.rb`:
  Upstream refactored and changed the logic surrounding suspended accounts.
  Minor conflict due to glitch-soc's local-only toots.
  Ported upstream changes.
- `package.json`:
  Not a real conflict, upstream updated dependencies that were too close to
  glitch-soc-only ones in the file.
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/accounts_controller.rb11
-rw-r--r--app/controllers/activitypub/outboxes_controller.rb3
-rw-r--r--app/controllers/admin/accounts_controller.rb31
-rw-r--r--app/controllers/api/base_controller.rb4
-rw-r--r--app/controllers/api/v1/accounts/featured_tags_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/follower_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/following_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/identity_proofs_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/lists_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/relationships_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/statuses_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts_controller.rb10
-rw-r--r--app/controllers/api/v1/admin/accounts_controller.rb9
-rw-r--r--app/controllers/api/v1/blocks_controller.rb2
-rw-r--r--app/controllers/api/v1/endorsements_controller.rb2
-rw-r--r--app/controllers/api/v1/follow_requests_controller.rb4
-rw-r--r--app/controllers/api/v1/lists/accounts_controller.rb4
-rw-r--r--app/controllers/api/v1/mutes_controller.rb2
-rw-r--r--app/controllers/api/v1/notifications_controller.rb4
-rw-r--r--app/controllers/api/v1/push/subscriptions_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb1
-rw-r--r--app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb2
-rw-r--r--app/controllers/api/web/push_subscriptions_controller.rb3
-rw-r--r--app/controllers/concerns/export_controller_concern.rb5
-rw-r--r--app/controllers/oauth/authorized_applications_controller.rb5
-rw-r--r--app/controllers/settings/aliases_controller.rb4
-rw-r--r--app/controllers/settings/applications_controller.rb3
-rw-r--r--app/controllers/settings/base_controller.rb7
-rw-r--r--app/controllers/settings/deletes_controller.rb9
-rw-r--r--app/controllers/settings/exports/blocked_accounts_controller.rb2
-rw-r--r--app/controllers/settings/exports/blocked_domains_controller.rb2
-rw-r--r--app/controllers/settings/exports/following_accounts_controller.rb2
-rw-r--r--app/controllers/settings/exports/lists_controller.rb2
-rw-r--r--app/controllers/settings/exports/muted_accounts_controller.rb2
-rw-r--r--app/controllers/settings/exports_controller.rb11
-rw-r--r--app/controllers/settings/featured_tags_controller.rb3
-rw-r--r--app/controllers/settings/identity_proofs_controller.rb3
-rw-r--r--app/controllers/settings/imports_controller.rb3
-rw-r--r--app/controllers/settings/migration/redirects_controller.rb9
-rw-r--r--app/controllers/settings/migrations_controller.rb9
-rw-r--r--app/controllers/settings/pictures_controller.rb1
-rw-r--r--app/controllers/settings/preferences_controller.rb4
-rw-r--r--app/controllers/settings/profiles_controller.rb3
-rw-r--r--app/controllers/settings/sessions_controller.rb9
-rw-r--r--app/controllers/settings/two_factor_authentication/confirmations_controller.rb5
-rw-r--r--app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb5
-rw-r--r--app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb5
-rw-r--r--app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb3
-rw-r--r--app/controllers/settings/two_factor_authentication_methods_controller.rb5
49 files changed, 91 insertions, 138 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 54106933c..356542767 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -7,6 +7,7 @@ class AccountsController < ApplicationController
   include AccountControllerConcern
   include SignatureAuthentication
 
+  before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
   before_action :set_body_classes
 
@@ -49,7 +50,7 @@ class AccountsController < ApplicationController
 
       format.json do
         expires_in 3.minutes, public: !(authorized_fetch_mode? && signed_request_account.present?)
-        render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter, fields: restrict_fields_to
+        render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter
       end
     end
   end
@@ -154,12 +155,4 @@ class AccountsController < ApplicationController
   def params_slice(*keys)
     params.slice(*keys).permit(*keys)
   end
-
-  def restrict_fields_to
-    if signed_request_account.present? || public_fetch_mode?
-      # Return all fields
-    else
-      %i(id type preferred_username inbox public_key endpoints)
-    end
-  end
 end
diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb
index e066860bf..5fd735ad6 100644
--- a/app/controllers/activitypub/outboxes_controller.rb
+++ b/app/controllers/activitypub/outboxes_controller.rb
@@ -57,9 +57,8 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
   def set_statuses
     return unless page_requested?
 
-    @statuses = @account.statuses.permitted_for(@account, signed_request_account)
     @statuses = cache_collection_paginated_by_id(
-      @statuses,
+      @account.statuses.permitted_for(@account, signed_request_account),
       Status,
       LIMIT,
       params_slice(:max_id, :min_id, :since_id)
diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb
index 7b1783542..b9b75727d 100644
--- a/app/controllers/admin/accounts_controller.rb
+++ b/app/controllers/admin/accounts_controller.rb
@@ -2,7 +2,7 @@
 
 module Admin
   class AccountsController < BaseController
-    before_action :set_account, only: [:show, :redownload, :remove_avatar, :remove_header, :enable, :unsilence, :unsuspend, :memorialize, :approve, :reject]
+    before_action :set_account, except: [:index]
     before_action :require_remote_account!, only: [:redownload]
     before_action :require_local_account!, only: [:enable, :memorialize, :approve, :reject]
 
@@ -14,49 +14,58 @@ module Admin
     def show
       authorize @account, :show?
 
+      @deletion_request        = @account.deletion_request
       @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
       @moderation_notes        = @account.targeted_moderation_notes.latest
       @warnings                = @account.targeted_account_warnings.latest.custom
+      @domain_block            = DomainBlock.rule_for(@account.domain)
     end
 
     def memorialize
       authorize @account, :memorialize?
       @account.memorialize!
       log_action :memorialize, @account
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.memorialized_msg', username: @account.acct)
     end
 
     def enable
       authorize @account.user, :enable?
       @account.user.enable!
       log_action :enable, @account.user
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.enabled_msg', username: @account.acct)
     end
 
     def approve
       authorize @account.user, :approve?
       @account.user.approve!
-      redirect_to admin_pending_accounts_path
+      redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
     end
 
     def reject
       authorize @account.user, :reject?
-      SuspendAccountService.new.call(@account, reserve_email: false, reserve_username: false)
-      redirect_to admin_pending_accounts_path
+      DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
+      redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
+    end
+
+    def destroy
+      authorize @account, :destroy?
+      Admin::AccountDeletionWorker.perform_async(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.destroyed_msg', username: @account.acct)
     end
 
     def unsilence
       authorize @account, :unsilence?
       @account.unsilence!
       log_action :unsilence, @account
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unsilenced_msg', username: @account.acct)
     end
 
     def unsuspend
       authorize @account, :unsuspend?
       @account.unsuspend!
+      Admin::UnsuspensionWorker.perform_async(@account.id)
       log_action :unsuspend, @account
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unsuspended_msg', username: @account.acct)
     end
 
     def redownload
@@ -65,7 +74,7 @@ module Admin
       @account.update!(last_webfingered_at: nil)
       ResolveAccountService.new.call(@account)
 
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.redownloaded_msg', username: @account.acct)
     end
 
     def remove_avatar
@@ -76,7 +85,7 @@ module Admin
 
       log_action :remove_avatar, @account.user
 
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_avatar_msg', username: @account.acct)
     end
 
     def remove_header
@@ -87,7 +96,7 @@ module Admin
 
       log_action :remove_header, @account.user
 
-      redirect_to admin_account_path(@account.id)
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_header_msg', username: @account.acct)
     end
 
     private
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 467225547..e962c4e97 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -96,12 +96,12 @@ class Api::BaseController < ApplicationController
   def require_user!
     if !current_user
       render json: { error: 'This method requires an authenticated user' }, status: 422
-    elsif current_user.disabled?
-      render json: { error: 'Your login is currently disabled' }, status: 403
     elsif !current_user.confirmed?
       render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
     elsif !current_user.approved?
       render json: { error: 'Your login is currently pending approval' }, status: 403
+    elsif !current_user.functional?
+      render json: { error: 'Your login is currently disabled' }, status: 403
     else
       set_user_activity
     end
diff --git a/app/controllers/api/v1/accounts/featured_tags_controller.rb b/app/controllers/api/v1/accounts/featured_tags_controller.rb
index d6277261d..014d71956 100644
--- a/app/controllers/api/v1/accounts/featured_tags_controller.rb
+++ b/app/controllers/api/v1/accounts/featured_tags_controller.rb
@@ -17,6 +17,6 @@ class Api::V1::Accounts::FeaturedTagsController < Api::BaseController
   end
 
   def set_featured_tags
-    @featured_tags = @account.featured_tags
+    @featured_tags = @account.suspended? ? @account.featured_tags : []
   end
 end
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index 2277067c9..a665863eb 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
   end
 
   def hide_results?
-    (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
+    @account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
   end
 
   def default_accounts
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index 93d4bd3a4..7d885a212 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
   end
 
   def hide_results?
-    (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
+    @account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
   end
 
   def default_accounts
diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
index 8dad6fee9..4b5f6902c 100644
--- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb
+++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
@@ -5,7 +5,7 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController
   before_action :set_account
 
   def index
-    @proofs = @account.identity_proofs.active
+    @proofs = @account.suspended? ? [] : @account.identity_proofs.active
     render json: @proofs, each_serializer: REST::IdentityProofSerializer
   end
 
diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb
index ccb751f8f..c92f1f8a0 100644
--- a/app/controllers/api/v1/accounts/lists_controller.rb
+++ b/app/controllers/api/v1/accounts/lists_controller.rb
@@ -6,7 +6,7 @@ class Api::V1::Accounts::ListsController < Api::BaseController
   before_action :set_account
 
   def index
-    @lists = @account.lists.where(account: current_account)
+    @lists = @account.suspended? ? [] : @account.lists.where(account: current_account)
     render json: @lists, each_serializer: REST::ListSerializer
   end
 
diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb
index 1d3992a28..503f85c97 100644
--- a/app/controllers/api/v1/accounts/relationships_controller.rb
+++ b/app/controllers/api/v1/accounts/relationships_controller.rb
@@ -5,7 +5,7 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
   before_action :require_user!
 
   def index
-    accounts = Account.where(id: account_ids).select('id')
+    accounts = Account.without_suspended.where(id: account_ids).select('id')
     # .where doesn't guarantee that our results are in the same order
     # we requested them, so return the "right" order to the requestor.
     @accounts = accounts.index_by(&:id).values_at(*account_ids).compact
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 85a9133e3..92ccb8061 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -18,7 +18,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
   end
 
   def load_statuses
-    cached_account_statuses
+    @account.suspended? ? [] : cached_account_statuses
   end
 
   def cached_account_statuses
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index 0080faf33..aef51a647 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -9,7 +9,6 @@ class Api::V1::AccountsController < Api::BaseController
 
   before_action :require_user!, except: [:show, :create]
   before_action :set_account, except: [:create]
-  before_action :check_account_suspension, only: [:show]
   before_action :check_enabled_registrations, only: [:create]
 
   skip_before_action :require_authenticated_user!, only: :create
@@ -31,9 +30,8 @@ class Api::V1::AccountsController < Api::BaseController
   end
 
   def follow
-    FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), with_rate_limit: true)
-
-    options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } }
+    follow  = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, with_rate_limit: true)
+    options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify? } }, requested_map: { @account.id => false } }
 
     render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options)
   end
@@ -73,10 +71,6 @@ class Api::V1::AccountsController < Api::BaseController
     AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options)
   end
 
-  def check_account_suspension
-    gone if @account.suspended?
-  end
-
   def account_params
     params.permit(:username, :email, :password, :agreement, :locale, :reason)
   end
diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb
index 24c7fbef1..3af572f25 100644
--- a/app/controllers/api/v1/admin/accounts_controller.rb
+++ b/app/controllers/api/v1/admin/accounts_controller.rb
@@ -58,7 +58,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController
 
   def reject
     authorize @account.user, :reject?
-    SuspendAccountService.new.call(@account, reserve_email: false, reserve_username: false)
+    DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
+    render json: @account, serializer: REST::Admin::AccountSerializer
+  end
+
+  def destroy
+    authorize @account, :destroy?
+    Admin::AccountDeletionWorker.perform_async(@account.id)
     render json: @account, serializer: REST::Admin::AccountSerializer
   end
 
@@ -72,6 +78,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController
   def unsuspend
     authorize @account, :unsuspend?
     @account.unsuspend!
+    Admin::UnsuspensionWorker.perform_async(@account.id)
     log_action :unsuspend, @account
     render json: @account, serializer: REST::Admin::AccountSerializer
   end
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index a2baeef90..586cdfca9 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -18,6 +18,8 @@ class Api::V1::BlocksController < Api::BaseController
 
   def paginated_blocks
     @paginated_blocks ||= Block.eager_load(target_account: :account_stat)
+                               .joins(:target_account)
+                               .merge(Account.without_suspended)
                                .where(account: current_account)
                                .paginate_by_max_id(
                                  limit_param(DEFAULT_ACCOUNTS_LIMIT),
diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb
index c87dbc4ce..9e80f468a 100644
--- a/app/controllers/api/v1/endorsements_controller.rb
+++ b/app/controllers/api/v1/endorsements_controller.rb
@@ -25,7 +25,7 @@ class Api::V1::EndorsementsController < Api::BaseController
   end
 
   def endorsed_accounts
-    current_account.endorsed_accounts.includes(:account_stat)
+    current_account.endorsed_accounts.includes(:account_stat).without_suspended
   end
 
   def insert_pagination_headers
diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb
index 0ee6e531f..b34c76f29 100644
--- a/app/controllers/api/v1/follow_requests_controller.rb
+++ b/app/controllers/api/v1/follow_requests_controller.rb
@@ -13,7 +13,7 @@ class Api::V1::FollowRequestsController < Api::BaseController
 
   def authorize
     AuthorizeFollowService.new.call(account, current_account)
-    NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account))
+    NotifyService.new.call(current_account, :follow, Follow.find_by(account: account, target_account: current_account))
     render json: account, serializer: REST::RelationshipSerializer, relationships: relationships
   end
 
@@ -37,7 +37,7 @@ class Api::V1::FollowRequestsController < Api::BaseController
   end
 
   def default_accounts
-    Account.includes(:follow_requests, :account_stat).references(:follow_requests)
+    Account.without_suspended.includes(:follow_requests, :account_stat).references(:follow_requests)
   end
 
   def paginated_follow_requests
diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb
index 23078263e..b66ea9bfe 100644
--- a/app/controllers/api/v1/lists/accounts_controller.rb
+++ b/app/controllers/api/v1/lists/accounts_controller.rb
@@ -37,9 +37,9 @@ class Api::V1::Lists::AccountsController < Api::BaseController
 
   def load_accounts
     if unlimited?
-      @list.accounts.includes(:account_stat).all
+      @list.accounts.without_suspended.includes(:account_stat).all
     else
-      @list.accounts.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
+      @list.accounts.without_suspended.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
     end
   end
 
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index 5dc047b43..a89f3d700 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -27,6 +27,8 @@ class Api::V1::MutesController < Api::BaseController
 
   def paginated_mutes
     @paginated_mutes ||= Mute.eager_load(:target_account)
+                             .joins(:target_account)
+                             .merge(Account.without_suspended)
                              .where(account: current_account)
                              .paginate_by_max_id(
                                limit_param(DEFAULT_ACCOUNTS_LIMIT),
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index 9ff168367..fda348265 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -14,7 +14,7 @@ class Api::V1::NotificationsController < Api::BaseController
   end
 
   def show
-    @notification = current_account.notifications.find(params[:id])
+    @notification = current_account.notifications.without_suspended.find(params[:id])
     render json: @notification, serializer: REST::NotificationSerializer
   end
 
@@ -49,7 +49,7 @@ class Api::V1::NotificationsController < Api::BaseController
   end
 
   def browserable_account_notifications
-    current_account.notifications.browserable(exclude_types, from_account)
+    current_account.notifications.without_suspended.browserable(exclude_types, from_account)
   end
 
   def target_statuses_from_notifications
diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb
index d34b333eb..0918c61e9 100644
--- a/app/controllers/api/v1/push/subscriptions_controller.rb
+++ b/app/controllers/api/v1/push/subscriptions_controller.rb
@@ -52,6 +52,6 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController
   def data_params
     return {} if params[:data].blank?
 
-    params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll])
+    params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status])
   end
 end
diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
index 8229786d6..2b614a837 100644
--- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
@@ -22,6 +22,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
 
   def default_accounts
     Account
+      .without_suspended
       .includes(:favourites, :account_stat)
       .references(:favourites)
       .where(favourites: { status_id: @status.id })
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index 6c9e49d90..24db30fcc 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -21,7 +21,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
   end
 
   def default_accounts
-    Account.includes(:statuses, :account_stat).references(:statuses)
+    Account.without_suspended.includes(:statuses, :account_stat).references(:statuses)
   end
 
   def paginated_statuses
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb
index 7916b82fa..1dce3e70f 100644
--- a/app/controllers/api/web/push_subscriptions_controller.rb
+++ b/app/controllers/api/web/push_subscriptions_controller.rb
@@ -22,6 +22,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
         reblog: alerts_enabled,
         mention: alerts_enabled,
         poll: alerts_enabled,
+        status: alerts_enabled,
       },
     }
 
@@ -57,6 +58,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
   end
 
   def data_params
-    @data_params ||= params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll])
+    @data_params ||= params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status])
   end
 end
diff --git a/app/controllers/concerns/export_controller_concern.rb b/app/controllers/concerns/export_controller_concern.rb
index bfe990c82..24cfc7a01 100644
--- a/app/controllers/concerns/export_controller_concern.rb
+++ b/app/controllers/concerns/export_controller_concern.rb
@@ -5,7 +5,6 @@ module ExportControllerConcern
 
   included do
     before_action :authenticate_user!
-    before_action :require_not_suspended!
     before_action :load_export
 
     skip_before_action :require_functional!
@@ -30,8 +29,4 @@ module ExportControllerConcern
   def export_filename
     "#{controller_name}.csv"
   end
-
-  def require_not_suspended!
-    forbidden if current_account.suspended?
-  end
 end
diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb
index c5ccece13..b2564a791 100644
--- a/app/controllers/oauth/authorized_applications_controller.rb
+++ b/app/controllers/oauth/authorized_applications_controller.rb
@@ -6,6 +6,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
   before_action :store_current_location
   before_action :authenticate_resource_owner!
   before_action :set_pack
+  before_action :require_not_suspended!, only: :destroy
   before_action :set_body_classes
 
   skip_before_action :require_functional!
@@ -30,4 +31,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
   def set_pack
     use_pack 'settings'
   end
+
+  def require_not_suspended!
+    forbidden if current_account.suspended?
+  end
 end
diff --git a/app/controllers/settings/aliases_controller.rb b/app/controllers/settings/aliases_controller.rb
index b7c9a409d..a421b8ede 100644
--- a/app/controllers/settings/aliases_controller.rb
+++ b/app/controllers/settings/aliases_controller.rb
@@ -1,9 +1,9 @@
 # frozen_string_literal: true
 
 class Settings::AliasesController < Settings::BaseController
-  layout 'admin'
+  skip_before_action :require_functional!
 
-  before_action :authenticate_user!
+  before_action :require_not_suspended!
   before_action :set_aliases, except: :destroy
   before_action :set_alias, only: :destroy
 
diff --git a/app/controllers/settings/applications_controller.rb b/app/controllers/settings/applications_controller.rb
index ed3f82a8e..d3ac268d8 100644
--- a/app/controllers/settings/applications_controller.rb
+++ b/app/controllers/settings/applications_controller.rb
@@ -1,9 +1,6 @@
 # frozen_string_literal: true
 
 class Settings::ApplicationsController < Settings::BaseController
-  layout 'admin'
-
-  before_action :authenticate_user!
   before_action :set_application, only: [:show, :update, :destroy, :regenerate]
   before_action :prepare_scopes, only: [:create, :update]
 
diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb
index b97603af6..dee3922d8 100644
--- a/app/controllers/settings/base_controller.rb
+++ b/app/controllers/settings/base_controller.rb
@@ -2,6 +2,9 @@
 
 class Settings::BaseController < ApplicationController
   before_action :set_pack
+  layout 'admin'
+
+  before_action :authenticate_user!
   before_action :set_body_classes
   before_action :set_cache_headers
 
@@ -18,4 +21,8 @@ class Settings::BaseController < ApplicationController
   def set_cache_headers
     response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
   end
+
+  def require_not_suspended!
+    forbidden if current_account.suspended?
+  end
 end
diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb
index 15a59c999..f96c83b80 100644
--- a/app/controllers/settings/deletes_controller.rb
+++ b/app/controllers/settings/deletes_controller.rb
@@ -1,13 +1,10 @@
 # frozen_string_literal: true
 
 class Settings::DeletesController < Settings::BaseController
-  layout 'admin'
+  skip_before_action :require_functional!
 
-  before_action :check_enabled_deletion
-  before_action :authenticate_user!
   before_action :require_not_suspended!
-
-  skip_before_action :require_functional!
+  before_action :check_enabled_deletion
 
   def show
     @confirmation = Form::DeleteConfirmation.new
@@ -46,7 +43,7 @@ class Settings::DeletesController < Settings::BaseController
 
   def destroy_account!
     current_account.suspend!
-    Admin::SuspensionWorker.perform_async(current_user.account_id, true)
+    AccountDeletionWorker.perform_async(current_user.account_id)
     sign_out
   end
 end
diff --git a/app/controllers/settings/exports/blocked_accounts_controller.rb b/app/controllers/settings/exports/blocked_accounts_controller.rb
index 2092104e0..2190caa36 100644
--- a/app/controllers/settings/exports/blocked_accounts_controller.rb
+++ b/app/controllers/settings/exports/blocked_accounts_controller.rb
@@ -2,7 +2,7 @@
 
 module Settings
   module Exports
-    class BlockedAccountsController < ApplicationController
+    class BlockedAccountsController < BaseController
       include ExportControllerConcern
 
       def index
diff --git a/app/controllers/settings/exports/blocked_domains_controller.rb b/app/controllers/settings/exports/blocked_domains_controller.rb
index 6676ce340..bee4b2431 100644
--- a/app/controllers/settings/exports/blocked_domains_controller.rb
+++ b/app/controllers/settings/exports/blocked_domains_controller.rb
@@ -2,7 +2,7 @@
 
 module Settings
   module Exports
-    class BlockedDomainsController < ApplicationController
+    class BlockedDomainsController < BaseController
       include ExportControllerConcern
 
       def index
diff --git a/app/controllers/settings/exports/following_accounts_controller.rb b/app/controllers/settings/exports/following_accounts_controller.rb
index 74281ddca..acefcb15d 100644
--- a/app/controllers/settings/exports/following_accounts_controller.rb
+++ b/app/controllers/settings/exports/following_accounts_controller.rb
@@ -2,7 +2,7 @@
 
 module Settings
   module Exports
-    class FollowingAccountsController < ApplicationController
+    class FollowingAccountsController < BaseController
       include ExportControllerConcern
 
       def index
diff --git a/app/controllers/settings/exports/lists_controller.rb b/app/controllers/settings/exports/lists_controller.rb
index cf5a9de44..bc65f56a0 100644
--- a/app/controllers/settings/exports/lists_controller.rb
+++ b/app/controllers/settings/exports/lists_controller.rb
@@ -2,7 +2,7 @@
 
 module Settings
   module Exports
-    class ListsController < ApplicationController
+    class ListsController < BaseController
       include ExportControllerConcern
 
       def index
diff --git a/app/controllers/settings/exports/muted_accounts_controller.rb b/app/controllers/settings/exports/muted_accounts_controller.rb
index e511619ca..50b7bf1f7 100644
--- a/app/controllers/settings/exports/muted_accounts_controller.rb
+++ b/app/controllers/settings/exports/muted_accounts_controller.rb
@@ -2,7 +2,7 @@
 
 module Settings
   module Exports
-    class MutedAccountsController < ApplicationController
+    class MutedAccountsController < BaseController
       include ExportControllerConcern
 
       def index
diff --git a/app/controllers/settings/exports_controller.rb b/app/controllers/settings/exports_controller.rb
index 0e93d07a9..30138d29e 100644
--- a/app/controllers/settings/exports_controller.rb
+++ b/app/controllers/settings/exports_controller.rb
@@ -3,11 +3,6 @@
 class Settings::ExportsController < Settings::BaseController
   include Authorization
 
-  layout 'admin'
-
-  before_action :authenticate_user!
-  before_action :require_not_suspended!
-
   skip_before_action :require_functional!
 
   def show
@@ -16,8 +11,6 @@ class Settings::ExportsController < Settings::BaseController
   end
 
   def create
-    raise Mastodon::NotPermittedError unless user_signed_in?
-
     backup = nil
 
     RedisLock.acquire(lock_options) do |lock|
@@ -37,8 +30,4 @@ class Settings::ExportsController < Settings::BaseController
   def lock_options
     { redis: Redis.current, key: "backup:#{current_user.id}" }
   end
-
-  def require_not_suspended!
-    forbidden if current_account.suspended?
-  end
 end
diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb
index e9861da56..e805527d0 100644
--- a/app/controllers/settings/featured_tags_controller.rb
+++ b/app/controllers/settings/featured_tags_controller.rb
@@ -1,9 +1,6 @@
 # frozen_string_literal: true
 
 class Settings::FeaturedTagsController < Settings::BaseController
-  layout 'admin'
-
-  before_action :authenticate_user!
   before_action :set_featured_tags, only: :index
   before_action :set_featured_tag, except: [:index, :create]
   before_action :set_recently_used_tags, only: :index
diff --git a/app/controllers/settings/identity_proofs_controller.rb b/app/controllers/settings/identity_proofs_controller.rb
index b217b3c3b..4618c7883 100644
--- a/app/controllers/settings/identity_proofs_controller.rb
+++ b/app/controllers/settings/identity_proofs_controller.rb
@@ -1,9 +1,6 @@
 # frozen_string_literal: true
 
 class Settings::IdentityProofsController < Settings::BaseController
-  layout 'admin'
-
-  before_action :authenticate_user!
   before_action :check_required_params, only: :new
   before_action :check_enabled, only: :new
 
diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb
index 7b8c4ae23..d4516526e 100644
--- a/app/controllers/settings/imports_controller.rb
+++ b/app/controllers/settings/imports_controller.rb
@@ -1,9 +1,6 @@
 # frozen_string_literal: true
 
 class Settings::ImportsController < Settings::BaseController
-  layout 'admin'
-
-  before_action :authenticate_user!
   before_action :set_account
 
   def show
diff --git a/app/controllers/settings/migration/redirects_controller.rb b/app/controllers/settings/migration/redirects_controller.rb
index 97193ade0..6d469f384 100644
--- a/app/controllers/settings/migration/redirects_controller.rb
+++ b/app/controllers/settings/migration/redirects_controller.rb
@@ -1,13 +1,10 @@
 # frozen_string_literal: true
 
 class Settings::Migration::RedirectsController < Settings::BaseController
-  layout 'admin'
+  skip_before_action :require_functional!
 
-  before_action :authenticate_user!
   before_action :require_not_suspended!
 
-  skip_before_action :require_functional!
-
   def new
     @redirect = Form::Redirect.new
   end
@@ -38,8 +35,4 @@ class Settings::Migration::RedirectsController < Settings::BaseController
   def resource_params
     params.require(:form_redirect).permit(:acct, :current_password, :current_username)
   end
-
-  def require_not_suspended!
-    forbidden if current_account.suspended?
-  end
 end
diff --git a/app/controllers/settings/migrations_controller.rb b/app/controllers/settings/migrations_controller.rb
index 68304bb51..62603aba8 100644
--- a/app/controllers/settings/migrations_controller.rb
+++ b/app/controllers/settings/migrations_controller.rb
@@ -1,15 +1,12 @@
 # frozen_string_literal: true
 
 class Settings::MigrationsController < Settings::BaseController
-  layout 'admin'
+  skip_before_action :require_functional!
 
-  before_action :authenticate_user!
   before_action :require_not_suspended!
   before_action :set_migrations
   before_action :set_cooldown
 
-  skip_before_action :require_functional!
-
   def show
     @migration = current_account.migrations.build
   end
@@ -44,8 +41,4 @@ class Settings::MigrationsController < Settings::BaseController
   def on_cooldown?
     @cooldown.present?
   end
-
-  def require_not_suspended!
-    forbidden if current_account.suspended?
-  end
 end
diff --git a/app/controllers/settings/pictures_controller.rb b/app/controllers/settings/pictures_controller.rb
index df2a6eed3..28df65f8f 100644
--- a/app/controllers/settings/pictures_controller.rb
+++ b/app/controllers/settings/pictures_controller.rb
@@ -2,7 +2,6 @@
 
 module Settings
   class PicturesController < BaseController
-    before_action :authenticate_user!
     before_action :set_account
     before_action :set_picture
 
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index 75c3e2495..87431f8cf 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -1,10 +1,6 @@
 # frozen_string_literal: true
 
 class Settings::PreferencesController < Settings::BaseController
-  layout 'admin'
-
-  before_action :authenticate_user!
-
   def show; end
 
   def update
diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb
index 19a7ce157..0c15447a6 100644
--- a/app/controllers/settings/profiles_controller.rb
+++ b/app/controllers/settings/profiles_controller.rb
@@ -1,9 +1,6 @@
 # frozen_string_literal: true
 
 class Settings::ProfilesController < Settings::BaseController
-  layout 'admin'
-
-  before_action :authenticate_user!
   before_action :set_account
 
   def show
diff --git a/app/controllers/settings/sessions_controller.rb b/app/controllers/settings/sessions_controller.rb
index f8fb4036e..ee2fc5dc8 100644
--- a/app/controllers/settings/sessions_controller.rb
+++ b/app/controllers/settings/sessions_controller.rb
@@ -1,12 +1,11 @@
 # frozen_string_literal: true
 
-#  Intentionally does not inherit from BaseController
-class Settings::SessionsController < ApplicationController
-  before_action :authenticate_user!
-  before_action :set_session, only: :destroy
-
+class Settings::SessionsController < Settings::BaseController
   skip_before_action :require_functional!
 
+  before_action :require_not_suspended!
+  before_action :set_session, only: :destroy
+
   def destroy
     @session.destroy!
     flash[:notice] = I18n.t('sessions.revoke_success')
diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb
index 9f23011a7..1a0afe58b 100644
--- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb
+++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb
@@ -5,14 +5,11 @@ module Settings
     class ConfirmationsController < BaseController
       include ChallengableConcern
 
-      layout 'admin'
+      skip_before_action :require_functional!
 
-      before_action :authenticate_user!
       before_action :require_challenge!
       before_action :ensure_otp_secret
 
-      skip_before_action :require_functional!
-
       def new
         prepare_two_factor_form
       end
diff --git a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb
index 6836f7ef6..cbba842a9 100644
--- a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb
+++ b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb
@@ -5,14 +5,11 @@ module Settings
     class OtpAuthenticationController < BaseController
       include ChallengableConcern
 
-      layout 'admin'
+      skip_before_action :require_functional!
 
-      before_action :authenticate_user!
       before_action :verify_otp_not_enabled, only: [:show]
       before_action :require_challenge!, only: [:create]
 
-      skip_before_action :require_functional!
-
       def show
         @confirmation = Form::TwoFactorConfirmation.new
       end
diff --git a/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb b/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb
index 0c4f5bff7..6ec53224d 100644
--- a/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb
+++ b/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb
@@ -5,13 +5,10 @@ module Settings
     class RecoveryCodesController < BaseController
       include ChallengableConcern
 
-      layout 'admin'
+      skip_before_action :require_functional!
 
-      before_action :authenticate_user!
       before_action :require_challenge!, on: :create
 
-      skip_before_action :require_functional!
-
       def create
         @recovery_codes = current_user.generate_otp_backup_codes!
         current_user.save!
diff --git a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb
index ee5392785..bd6f83134 100644
--- a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb
+++ b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb
@@ -3,9 +3,8 @@
 module Settings
   module TwoFactorAuthentication
     class WebauthnCredentialsController < BaseController
-      layout 'admin'
+      skip_before_action :require_functional!
 
-      before_action :authenticate_user!
       before_action :require_otp_enabled
       before_action :require_webauthn_enabled, only: [:index, :destroy]
 
diff --git a/app/controllers/settings/two_factor_authentication_methods_controller.rb b/app/controllers/settings/two_factor_authentication_methods_controller.rb
index 224d3a45c..205933ea8 100644
--- a/app/controllers/settings/two_factor_authentication_methods_controller.rb
+++ b/app/controllers/settings/two_factor_authentication_methods_controller.rb
@@ -4,14 +4,11 @@ module Settings
   class TwoFactorAuthenticationMethodsController < BaseController
     include ChallengableConcern
 
-    layout 'admin'
+    skip_before_action :require_functional!
 
-    before_action :authenticate_user!
     before_action :require_challenge!, only: :disable
     before_action :require_otp_enabled
 
-    skip_before_action :require_functional!
-
     def index; end
 
     def disable