about summary refs log tree commit diff
path: root/app/controllers
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-10-28 11:36:25 +0200
committerClaire <claire.github-309c@sitedethib.com>2022-10-28 19:23:58 +0200
commitcb19be67d1b47dd04cb5bb88e09f0101a614bd1c (patch)
tree6c85ccc6ac0279ae7b1ed4dff56c8e83f71a0c95 /app/controllers
parent371563b0e249b6369e04709fb974a8e57413529f (diff)
parent8dfe5179ee7186e549dbe1186a151ffa848fe8ab (diff)
Merge branch 'main' into glitch-soc/merge-upstream
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/about_controller.rb61
-rw-r--r--app/controllers/account_follow_controller.rb12
-rw-r--r--app/controllers/account_unfollow_controller.rb12
-rw-r--r--app/controllers/accounts_controller.rb59
-rw-r--r--app/controllers/admin/custom_emojis_controller.rb2
-rw-r--r--app/controllers/admin/ip_blocks_controller.rb2
-rw-r--r--app/controllers/admin/settings/about_controller.rb9
-rw-r--r--app/controllers/admin/settings/appearance_controller.rb9
-rw-r--r--app/controllers/admin/settings/branding_controller.rb9
-rw-r--r--app/controllers/admin/settings/content_retention_controller.rb9
-rw-r--r--app/controllers/admin/settings/discovery_controller.rb9
-rw-r--r--app/controllers/admin/settings/registrations_controller.rb9
-rw-r--r--app/controllers/admin/settings_controller.rb10
-rw-r--r--app/controllers/admin/site_uploads_controller.rb2
-rw-r--r--app/controllers/admin/statuses_controller.rb16
-rw-r--r--app/controllers/admin/trends/links/preview_card_providers_controller.rb2
-rw-r--r--app/controllers/admin/trends/links_controller.rb3
-rw-r--r--app/controllers/admin/trends/statuses_controller.rb7
-rw-r--r--app/controllers/admin/trends/tags_controller.rb2
-rw-r--r--app/controllers/api/base_controller.rb4
-rw-r--r--app/controllers/api/v1/featured_tags_controller.rb6
-rw-r--r--app/controllers/api/v1/instances/domain_blocks_controller.rb23
-rw-r--r--app/controllers/api/v1/instances/extended_descriptions_controller.rb18
-rw-r--r--app/controllers/api/v1/instances/privacy_policies_controller.rb18
-rw-r--r--app/controllers/api/v1/statuses_controller.rb1
-rw-r--r--app/controllers/api/v1/timelines/public_controller.rb1
-rw-r--r--app/controllers/api/v1/timelines/tag_controller.rb1
-rw-r--r--app/controllers/api/v1/trends/links_controller.rb4
-rw-r--r--app/controllers/api/v2/search_controller.rb14
-rw-r--r--app/controllers/auth/registrations_controller.rb16
-rw-r--r--app/controllers/concerns/account_controller_concern.rb3
-rw-r--r--app/controllers/concerns/web_app_controller_concern.rb32
-rw-r--r--app/controllers/directories_controller.rb37
-rw-r--r--app/controllers/follower_accounts_controller.rb6
-rw-r--r--app/controllers/following_accounts_controller.rb6
-rw-r--r--app/controllers/home_controller.rb35
-rw-r--r--app/controllers/privacy_controller.rb19
-rw-r--r--app/controllers/public_timelines_controller.rb31
-rw-r--r--app/controllers/remote_follow_controller.rb46
-rw-r--r--app/controllers/remote_interaction_controller.rb60
-rw-r--r--app/controllers/settings/deletes_controller.rb5
-rw-r--r--app/controllers/settings/featured_tags_controller.rb6
-rw-r--r--app/controllers/statuses_controller.rb14
-rw-r--r--app/controllers/tags_controller.rb11
44 files changed, 237 insertions, 424 deletions
diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb
index d3f03374f..104348614 100644
--- a/app/controllers/about_controller.rb
+++ b/app/controllers/about_controller.rb
@@ -1,72 +1,19 @@
 # frozen_string_literal: true
 
 class AboutController < ApplicationController
-  include RegistrationSpamConcern
+  include WebAppControllerConcern
 
-  before_action :set_pack
+  skip_before_action :require_functional!
 
-  layout 'public'
-
-  before_action :require_open_federation!, only: [:show, :more]
-  before_action :set_body_classes, only: :show
   before_action :set_instance_presenter
-  before_action :set_expires_in, only: [:more]
-  before_action :set_registration_form_time, only: :show
-
-  skip_before_action :require_functional!, only: [:more]
-
-  def show; end
-
-  def more
-    flash.now[:notice] = I18n.t('about.instance_actor_flash') if params[:instance_actor]
-
-    toc_generator = TOCGenerator.new(@instance_presenter.extended_description)
 
-    @rules             = Rule.ordered
-    @contents          = toc_generator.html
-    @table_of_contents = toc_generator.toc
-    @blocks            = DomainBlock.with_user_facing_limitations.by_severity if display_blocks?
+  def show
+    expires_in 0, public: true unless user_signed_in?
   end
 
-  helper_method :display_blocks?
-  helper_method :display_blocks_rationale?
-  helper_method :public_fetch_mode?
-  helper_method :new_user
-
   private
 
-  def require_open_federation!
-    not_found if whitelist_mode?
-  end
-
-  def display_blocks?
-    Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?)
-  end
-
-  def display_blocks_rationale?
-    Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?)
-  end
-
-  def new_user
-    User.new.tap do |user|
-      user.build_account
-      user.build_invite_request
-    end
-  end
-
-  def set_pack
-    use_pack 'public'
-  end
-
   def set_instance_presenter
     @instance_presenter = InstancePresenter.new
   end
-
-  def set_body_classes
-    @hide_navbar = true
-  end
-
-  def set_expires_in
-    expires_in 0, public: true
-  end
 end
diff --git a/app/controllers/account_follow_controller.rb b/app/controllers/account_follow_controller.rb
deleted file mode 100644
index 33394074d..000000000
--- a/app/controllers/account_follow_controller.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AccountFollowController < ApplicationController
-  include AccountControllerConcern
-
-  before_action :authenticate_user!
-
-  def create
-    FollowService.new.call(current_user.account, @account, with_rate_limit: true)
-    redirect_to account_path(@account)
-  end
-end
diff --git a/app/controllers/account_unfollow_controller.rb b/app/controllers/account_unfollow_controller.rb
deleted file mode 100644
index 378ec86dc..000000000
--- a/app/controllers/account_unfollow_controller.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AccountUnfollowController < ApplicationController
-  include AccountControllerConcern
-
-  before_action :authenticate_user!
-
-  def create
-    UnfollowService.new.call(current_user.account, @account)
-    redirect_to account_path(@account)
-  end
-end
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 02f3c3dd7..f36a0c859 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -9,7 +9,6 @@ class AccountsController < ApplicationController
 
   before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
-  before_action :set_body_classes
 
   skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
   skip_before_action :require_functional!, unless: :whitelist_mode?
@@ -17,26 +16,7 @@ class AccountsController < ApplicationController
   def show
     respond_to do |format|
       format.html do
-        use_pack 'public'
         expires_in 0, public: true unless user_signed_in?
-
-        @pinned_statuses   = []
-        @endorsed_accounts = @account.endorsed_accounts.to_a.sample(4)
-        @featured_hashtags = @account.featured_tags.order(statuses_count: :desc)
-
-        if current_account && @account.blocking?(current_account)
-          @statuses = []
-          return
-        end
-
-        @pinned_statuses = cached_filtered_status_pins if show_pinned_statuses?
-        @statuses        = cached_filtered_status_page
-        @rss_url         = rss_url
-
-        unless @statuses.empty?
-          @older_url = older_url if @statuses.last.id > filtered_statuses.last.id
-          @newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
-        end
       end
 
       format.rss do
@@ -56,18 +36,6 @@ class AccountsController < ApplicationController
 
   private
 
-  def set_body_classes
-    @body_classes = 'with-modals'
-  end
-
-  def show_pinned_statuses?
-    [replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
-  end
-
-  def filtered_pinned_statuses
-    @account.pinned_statuses.not_local_only.where(visibility: [:public, :unlisted])
-  end
-
   def filtered_statuses
     default_statuses.tap do |statuses|
       statuses.merge!(hashtag_scope)    if tag_requested?
@@ -114,26 +82,6 @@ class AccountsController < ApplicationController
     end
   end
 
-  def older_url
-    pagination_url(max_id: @statuses.last.id)
-  end
-
-  def newer_url
-    pagination_url(min_id: @statuses.first.id)
-  end
-
-  def pagination_url(max_id: nil, min_id: nil)
-    if tag_requested?
-      short_account_tag_url(@account, params[:tag], max_id: max_id, min_id: min_id)
-    elsif media_requested?
-      short_account_media_url(@account, max_id: max_id, min_id: min_id)
-    elsif replies_requested?
-      short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
-    else
-      short_account_url(@account, max_id: max_id, min_id: min_id)
-    end
-  end
-
   def media_requested?
     request.path.split('.').first.end_with?('/media') && !tag_requested?
   end
@@ -146,13 +94,6 @@ class AccountsController < ApplicationController
     request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
   end
 
-  def cached_filtered_status_pins
-    cache_collection(
-      filtered_pinned_statuses,
-      Status
-    )
-  end
-
   def cached_filtered_status_page
     cache_collection_paginated_by_id(
       filtered_statuses,
diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb
index 1fae60f5b..431dc1524 100644
--- a/app/controllers/admin/custom_emojis_controller.rb
+++ b/app/controllers/admin/custom_emojis_controller.rb
@@ -34,7 +34,7 @@ module Admin
       @form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
-      flash[:alert] = I18n.t('admin.accounts.no_account_selected')
+      flash[:alert] = I18n.t('admin.custom_emojis.no_emoji_selected')
     rescue Mastodon::NotPermittedError
       flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
     rescue ActiveRecord::RecordInvalid => e
diff --git a/app/controllers/admin/ip_blocks_controller.rb b/app/controllers/admin/ip_blocks_controller.rb
index a87520f4e..1bd7ec805 100644
--- a/app/controllers/admin/ip_blocks_controller.rb
+++ b/app/controllers/admin/ip_blocks_controller.rb
@@ -5,7 +5,7 @@ module Admin
     def index
       authorize :ip_block, :index?
 
-      @ip_blocks = IpBlock.page(params[:page])
+      @ip_blocks = IpBlock.order(ip: :asc).page(params[:page])
       @form      = Form::IpBlockBatch.new
     end
 
diff --git a/app/controllers/admin/settings/about_controller.rb b/app/controllers/admin/settings/about_controller.rb
new file mode 100644
index 000000000..86327fe39
--- /dev/null
+++ b/app/controllers/admin/settings/about_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Admin::Settings::AboutController < Admin::SettingsController
+  private
+
+  def after_update_redirect_path
+    admin_settings_about_path
+  end
+end
diff --git a/app/controllers/admin/settings/appearance_controller.rb b/app/controllers/admin/settings/appearance_controller.rb
new file mode 100644
index 000000000..39b2448d8
--- /dev/null
+++ b/app/controllers/admin/settings/appearance_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Admin::Settings::AppearanceController < Admin::SettingsController
+  private
+
+  def after_update_redirect_path
+    admin_settings_appearance_path
+  end
+end
diff --git a/app/controllers/admin/settings/branding_controller.rb b/app/controllers/admin/settings/branding_controller.rb
new file mode 100644
index 000000000..4a4d76f49
--- /dev/null
+++ b/app/controllers/admin/settings/branding_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Admin::Settings::BrandingController < Admin::SettingsController
+  private
+
+  def after_update_redirect_path
+    admin_settings_branding_path
+  end
+end
diff --git a/app/controllers/admin/settings/content_retention_controller.rb b/app/controllers/admin/settings/content_retention_controller.rb
new file mode 100644
index 000000000..b88336a2c
--- /dev/null
+++ b/app/controllers/admin/settings/content_retention_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Admin::Settings::ContentRetentionController < Admin::SettingsController
+  private
+
+  def after_update_redirect_path
+    admin_settings_content_retention_path
+  end
+end
diff --git a/app/controllers/admin/settings/discovery_controller.rb b/app/controllers/admin/settings/discovery_controller.rb
new file mode 100644
index 000000000..be4b57f79
--- /dev/null
+++ b/app/controllers/admin/settings/discovery_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Admin::Settings::DiscoveryController < Admin::SettingsController
+  private
+
+  def after_update_redirect_path
+    admin_settings_discovery_path
+  end
+end
diff --git a/app/controllers/admin/settings/registrations_controller.rb b/app/controllers/admin/settings/registrations_controller.rb
new file mode 100644
index 000000000..b4a74349c
--- /dev/null
+++ b/app/controllers/admin/settings/registrations_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Admin::Settings::RegistrationsController < Admin::SettingsController
+  private
+
+  def after_update_redirect_path
+    admin_settings_registrations_path
+  end
+end
diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb
index dc1c79b7f..338a3638c 100644
--- a/app/controllers/admin/settings_controller.rb
+++ b/app/controllers/admin/settings_controller.rb
@@ -2,7 +2,7 @@
 
 module Admin
   class SettingsController < BaseController
-    def edit
+    def show
       authorize :settings, :show?
 
       @admin_settings = Form::AdminSettings.new
@@ -15,14 +15,18 @@ module Admin
 
       if @admin_settings.save
         flash[:notice] = I18n.t('generic.changes_saved_msg')
-        redirect_to edit_admin_settings_path
+        redirect_to after_update_redirect_path
       else
-        render :edit
+        render :show
       end
     end
 
     private
 
+    def after_update_redirect_path
+      raise NotImplementedError
+    end
+
     def settings_params
       params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
     end
diff --git a/app/controllers/admin/site_uploads_controller.rb b/app/controllers/admin/site_uploads_controller.rb
index cacecedb0..a5d2cf41c 100644
--- a/app/controllers/admin/site_uploads_controller.rb
+++ b/app/controllers/admin/site_uploads_controller.rb
@@ -9,7 +9,7 @@ module Admin
 
       @site_upload.destroy!
 
-      redirect_to edit_admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
+      redirect_to admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
     end
 
     private
diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb
index 084921ceb..b80cd20f5 100644
--- a/app/controllers/admin/statuses_controller.rb
+++ b/app/controllers/admin/statuses_controller.rb
@@ -3,18 +3,23 @@
 module Admin
   class StatusesController < BaseController
     before_action :set_account
-    before_action :set_statuses
+    before_action :set_statuses, except: :show
+    before_action :set_status, only: :show
 
     PER_PAGE = 20
 
     def index
-      authorize :status, :index?
+      authorize [:admin, :status], :index?
 
       @status_batch_action = Admin::StatusBatchAction.new
     end
 
+    def show
+      authorize [:admin, @status], :show?
+    end
+
     def batch
-      authorize :status, :index?
+      authorize [:admin, :status], :index?
 
       @status_batch_action = Admin::StatusBatchAction.new(admin_status_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button))
       @status_batch_action.save!
@@ -32,6 +37,7 @@ module Admin
 
     def after_create_redirect_path
       report_id = @status_batch_action&.report_id || params[:report_id]
+
       if report_id.present?
         admin_report_path(report_id)
       else
@@ -43,6 +49,10 @@ module Admin
       @account = Account.find(params[:account_id])
     end
 
+    def set_status
+      @status = @account.statuses.find(params[:id])
+    end
+
     def set_statuses
       @statuses = Admin::StatusFilter.new(@account, filter_params).results.preload(:application, :preloadable_poll, :media_attachments, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, active_mentions: :account]).page(params[:page]).per(PER_PAGE)
     end
diff --git a/app/controllers/admin/trends/links/preview_card_providers_controller.rb b/app/controllers/admin/trends/links/preview_card_providers_controller.rb
index 97dee8eca..768b79f8d 100644
--- a/app/controllers/admin/trends/links/preview_card_providers_controller.rb
+++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb
@@ -14,7 +14,7 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll
     @form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
-    flash[:alert] = I18n.t('admin.accounts.no_account_selected')
+    flash[:alert] = I18n.t('admin.trends.links.publishers.no_publisher_selected')
   ensure
     redirect_to admin_trends_links_preview_card_providers_path(filter_params)
   end
diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb
index a497eae41..83d68eba6 100644
--- a/app/controllers/admin/trends/links_controller.rb
+++ b/app/controllers/admin/trends/links_controller.rb
@@ -4,6 +4,7 @@ class Admin::Trends::LinksController < Admin::BaseController
   def index
     authorize :preview_card, :review?
 
+    @locales       = PreviewCardTrend.pluck('distinct language')
     @preview_cards = filtered_preview_cards.page(params[:page])
     @form          = Trends::PreviewCardBatch.new
   end
@@ -14,7 +15,7 @@ class Admin::Trends::LinksController < Admin::BaseController
     @form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
-    flash[:alert] = I18n.t('admin.accounts.no_account_selected')
+    flash[:alert] = I18n.t('admin.trends.links.no_link_selected')
   ensure
     redirect_to admin_trends_links_path(filter_params)
   end
diff --git a/app/controllers/admin/trends/statuses_controller.rb b/app/controllers/admin/trends/statuses_controller.rb
index c538962f9..3d8b53ea8 100644
--- a/app/controllers/admin/trends/statuses_controller.rb
+++ b/app/controllers/admin/trends/statuses_controller.rb
@@ -2,19 +2,20 @@
 
 class Admin::Trends::StatusesController < Admin::BaseController
   def index
-    authorize :status, :review?
+    authorize [:admin, :status], :review?
 
+    @locales  = StatusTrend.pluck('distinct language')
     @statuses = filtered_statuses.page(params[:page])
     @form     = Trends::StatusBatch.new
   end
 
   def batch
-    authorize :status, :review?
+    authorize [:admin, :status], :review?
 
     @form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
-    flash[:alert] = I18n.t('admin.accounts.no_account_selected')
+    flash[:alert] = I18n.t('admin.trends.statuses.no_status_selected')
   ensure
     redirect_to admin_trends_statuses_path(filter_params)
   end
diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb
index 98dd6c8ec..f5946448a 100644
--- a/app/controllers/admin/trends/tags_controller.rb
+++ b/app/controllers/admin/trends/tags_controller.rb
@@ -14,7 +14,7 @@ class Admin::Trends::TagsController < Admin::BaseController
     @form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
-    flash[:alert] = I18n.t('admin.accounts.no_account_selected')
+    flash[:alert] = I18n.t('admin.trends.tags.no_tag_selected')
   ensure
     redirect_to admin_trends_tags_path(filter_params)
   end
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 7ce6599c5..c46fde65b 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -24,6 +24,10 @@ class Api::BaseController < ApplicationController
     render json: { error: 'Duplicate record' }, status: 422
   end
 
+  rescue_from Date::Error do
+    render json: { error: 'Invalid date supplied' }, status: 422
+  end
+
   rescue_from ActiveRecord::RecordNotFound do
     render json: { error: 'Record not found' }, status: 404
   end
diff --git a/app/controllers/api/v1/featured_tags_controller.rb b/app/controllers/api/v1/featured_tags_controller.rb
index c1ead4f54..edb42a94e 100644
--- a/app/controllers/api/v1/featured_tags_controller.rb
+++ b/app/controllers/api/v1/featured_tags_controller.rb
@@ -13,12 +13,12 @@ class Api::V1::FeaturedTagsController < Api::BaseController
   end
 
   def create
-    @featured_tag = current_account.featured_tags.create!(featured_tag_params)
-    render json: @featured_tag, serializer: REST::FeaturedTagSerializer
+    featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name])
+    render json: featured_tag, serializer: REST::FeaturedTagSerializer
   end
 
   def destroy
-    @featured_tag.destroy!
+    RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
     render_empty
   end
 
diff --git a/app/controllers/api/v1/instances/domain_blocks_controller.rb b/app/controllers/api/v1/instances/domain_blocks_controller.rb
new file mode 100644
index 000000000..37a6906fb
--- /dev/null
+++ b/app/controllers/api/v1/instances/domain_blocks_controller.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class Api::V1::Instances::DomainBlocksController < Api::BaseController
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+
+  before_action :require_enabled_api!
+  before_action :set_domain_blocks
+
+  def index
+    expires_in 3.minutes, public: true
+    render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?))
+  end
+
+  private
+
+  def require_enabled_api!
+    head 404 unless Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?)
+  end
+
+  def set_domain_blocks
+    @domain_blocks = DomainBlock.with_user_facing_limitations.by_severity
+  end
+end
diff --git a/app/controllers/api/v1/instances/extended_descriptions_controller.rb b/app/controllers/api/v1/instances/extended_descriptions_controller.rb
new file mode 100644
index 000000000..c72e16cff
--- /dev/null
+++ b/app/controllers/api/v1/instances/extended_descriptions_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+
+  before_action :set_extended_description
+
+  def show
+    expires_in 3.minutes, public: true
+    render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer
+  end
+
+  private
+
+  def set_extended_description
+    @extended_description = ExtendedDescription.current
+  end
+end
diff --git a/app/controllers/api/v1/instances/privacy_policies_controller.rb b/app/controllers/api/v1/instances/privacy_policies_controller.rb
new file mode 100644
index 000000000..dbd69f54d
--- /dev/null
+++ b/app/controllers/api/v1/instances/privacy_policies_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController
+  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
+
+  before_action :set_privacy_policy
+
+  def show
+    expires_in 1.day, public: true
+    render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer
+  end
+
+  private
+
+  def set_privacy_policy
+    @privacy_policy = PrivacyPolicy.current
+  end
+end
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index b2cee3e92..bb9d794a5 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -79,6 +79,7 @@ class Api::V1::StatusesController < Api::BaseController
     authorize @status, :destroy?
 
     @status.discard
+    StatusPin.find_by(status: @status)&.destroy
     @status.account.statuses_count = @status.account.statuses_count - 1
     json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true
 
diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
index 493fe4776..2ee5aaf18 100644
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ b/app/controllers/api/v1/timelines/public_controller.rb
@@ -35,6 +35,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController
   def public_feed
     PublicFeed.new(
       current_account,
+      locale: content_locale,
       local: truthy_param?(:local),
       remote: truthy_param?(:remote),
       only_media: truthy_param?(:only_media),
diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb
index 64a1db58d..9f3a5b3f1 100644
--- a/app/controllers/api/v1/timelines/tag_controller.rb
+++ b/app/controllers/api/v1/timelines/tag_controller.rb
@@ -36,6 +36,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
     TagFeed.new(
       @tag,
       current_account,
+      locale: content_locale,
       any: params[:any],
       all: params[:all],
       none: params[:none],
diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb
index 1a9f918f2..8ff3b364e 100644
--- a/app/controllers/api/v1/trends/links_controller.rb
+++ b/app/controllers/api/v1/trends/links_controller.rb
@@ -28,7 +28,9 @@ class Api::V1::Trends::LinksController < Api::BaseController
   end
 
   def links_from_trends
-    Trends.links.query.allowed.in_locale(content_locale)
+    scope = Trends.links.query.allowed.in_locale(content_locale)
+    scope = scope.filtered_for(current_account) if user_signed_in?
+    scope
   end
 
   def insert_pagination_headers
diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb
index 77eeab5b0..b084eae42 100644
--- a/app/controllers/api/v2/search_controller.rb
+++ b/app/controllers/api/v2/search_controller.rb
@@ -5,8 +5,8 @@ class Api::V2::SearchController < Api::BaseController
 
   RESULTS_LIMIT = (ENV['MAX_SEARCH_RESULTS'] || 20).to_i
 
-  before_action -> { doorkeeper_authorize! :read, :'read:search' }
-  before_action :require_user!
+  before_action -> { authorize_if_got_token! :read, :'read:search' }
+  before_action :validate_search_params!
 
   def index
     @search = Search.new(search_results)
@@ -19,6 +19,16 @@ class Api::V2::SearchController < Api::BaseController
 
   private
 
+  def validate_search_params!
+    params.require(:q)
+
+    return if user_signed_in?
+
+    return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present?
+
+    render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve)
+  end
+
   def search_results
     SearchService.new.call(
       params[:q],
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 486edcdcb..f31677f64 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -15,6 +15,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
   before_action :set_body_classes, only: [:new, :create, :edit, :update]
   before_action :require_not_suspended!, only: [:update]
   before_action :set_cache_headers, only: [:edit, :update]
+  before_action :set_rules, only: :new
+  before_action :require_rules_acceptance!, only: :new
   before_action :set_registration_form_time, only: :new
 
   skip_before_action :require_functional!, only: [:edit, :update]
@@ -56,7 +58,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 
   def configure_sign_up_params
     devise_parameter_sanitizer.permit(:sign_up) do |u|
-      u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
+      u.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
     end
   end
 
@@ -143,6 +145,18 @@ class Auth::RegistrationsController < Devise::RegistrationsController
     forbidden if current_account.suspended?
   end
 
+  def set_rules
+    @rules = Rule.ordered
+  end
+
+  def require_rules_acceptance!
+    return if @rules.empty? || (session[:accept_token].present? && params[:accept] == session[:accept_token])
+
+    @accept_token = session[:accept_token] = SecureRandom.hex
+
+    set_locale { render :rules }
+  end
+
   def set_cache_headers
     response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
   end
diff --git a/app/controllers/concerns/account_controller_concern.rb b/app/controllers/concerns/account_controller_concern.rb
index 11eac0eb6..2f7d84df0 100644
--- a/app/controllers/concerns/account_controller_concern.rb
+++ b/app/controllers/concerns/account_controller_concern.rb
@@ -3,13 +3,12 @@
 module AccountControllerConcern
   extend ActiveSupport::Concern
 
+  include WebAppControllerConcern
   include AccountOwnedConcern
 
   FOLLOW_PER_PAGE = 12
 
   included do
-    layout 'public'
-
     before_action :set_instance_presenter
     before_action :set_link_headers, if: -> { request.format.nil? || request.format == :html }
   end
diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb
new file mode 100644
index 000000000..b6050c913
--- /dev/null
+++ b/app/controllers/concerns/web_app_controller_concern.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module WebAppControllerConcern
+  extend ActiveSupport::Concern
+
+  included do
+    before_action :set_pack
+    before_action :redirect_unauthenticated_to_permalinks!
+    before_action :set_app_body_class
+    before_action :set_referrer_policy_header
+  end
+
+  def set_app_body_class
+    @body_classes = 'app-body'
+  end
+
+  def set_referrer_policy_header
+    response.headers['Referrer-Policy'] = 'origin'
+  end
+
+  def redirect_unauthenticated_to_permalinks!
+    return if user_signed_in?
+
+    redirect_path = PermalinkRedirector.new(request.path).redirect_path
+
+    redirect_to(redirect_path) if redirect_path.present?
+  end
+
+  def set_pack
+    use_pack 'home'
+  end
+end
diff --git a/app/controllers/directories_controller.rb b/app/controllers/directories_controller.rb
deleted file mode 100644
index 2263f286b..000000000
--- a/app/controllers/directories_controller.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class DirectoriesController < ApplicationController
-  layout 'public'
-
-  before_action :authenticate_user!, if: :whitelist_mode?
-  before_action :require_enabled!
-  before_action :set_instance_presenter
-  before_action :set_accounts
-  before_action :set_pack
-
-  skip_before_action :require_functional!, unless: :whitelist_mode?
-
-  def index
-    render :index
-  end
-
-  private
-
-  def set_pack
-    use_pack 'share'
-  end
-
-  def require_enabled!
-    return not_found unless Setting.profile_directory
-  end
-
-  def set_accounts
-    @accounts = Account.local.discoverable.by_recent_status.page(params[:page]).per(20).tap do |query|
-      query.merge!(Account.not_excluded_by_account(current_account)) if current_account
-    end
-  end
-
-  def set_instance_presenter
-    @instance_presenter = InstancePresenter.new
-  end
-end
diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb
index 0d9e624ef..35ce31f80 100644
--- a/app/controllers/follower_accounts_controller.rb
+++ b/app/controllers/follower_accounts_controller.rb
@@ -3,6 +3,7 @@
 class FollowerAccountsController < ApplicationController
   include AccountControllerConcern
   include SignatureVerification
+  include WebAppControllerConcern
 
   before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
@@ -13,12 +14,7 @@ class FollowerAccountsController < ApplicationController
   def index
     respond_to do |format|
       format.html do
-        use_pack 'public'
         expires_in 0, public: true unless user_signed_in?
-
-        next if @account.hide_collections?
-
-        follows
       end
 
       format.json do
diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb
index 68e1a79be..f84dca1e5 100644
--- a/app/controllers/following_accounts_controller.rb
+++ b/app/controllers/following_accounts_controller.rb
@@ -3,6 +3,7 @@
 class FollowingAccountsController < ApplicationController
   include AccountControllerConcern
   include SignatureVerification
+  include WebAppControllerConcern
 
   before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
@@ -13,12 +14,7 @@ class FollowingAccountsController < ApplicationController
   def index
     respond_to do |format|
       format.html do
-        use_pack 'public'
         expires_in 0, public: true unless user_signed_in?
-
-        next if @account.hide_collections?
-
-        follows
       end
 
       format.json do
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index 61b1690fa..d8ee82a7a 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -1,47 +1,16 @@
 # frozen_string_literal: true
 
 class HomeController < ApplicationController
-  before_action :redirect_unauthenticated_to_permalinks!
+  include WebAppControllerConcern
 
-  before_action :set_pack
-  before_action :set_referrer_policy_header
   before_action :set_instance_presenter
 
   def index
-    @body_classes = 'app-body'
+    expires_in 0, public: true unless user_signed_in?
   end
 
   private
 
-  def redirect_unauthenticated_to_permalinks!
-    return if user_signed_in?
-
-    redirect_path = PermalinkRedirector.new(request.path).redirect_path
-    redirect_path ||= default_redirect_path
-
-    redirect_to(redirect_path) if redirect_path.present?
-  end
-
-  def set_pack
-    use_pack 'home'
-  end
-
-  def default_redirect_path
-    if whitelist_mode?
-      new_user_session_path
-    elsif request.path.start_with?('/web')
-      nil
-    elsif single_user_mode?
-      short_account_path(Account.local.without_suspended.where('id > 0').first)
-    else
-      about_path
-    end
-  end
-
-  def set_referrer_policy_header
-    response.headers['Referrer-Policy'] = 'origin'
-  end
-
   def set_instance_presenter
     @instance_presenter = InstancePresenter.new
   end
diff --git a/app/controllers/privacy_controller.rb b/app/controllers/privacy_controller.rb
index 126bb0128..2c98bf3bf 100644
--- a/app/controllers/privacy_controller.rb
+++ b/app/controllers/privacy_controller.rb
@@ -1,28 +1,19 @@
 # frozen_string_literal: true
 
 class PrivacyController < ApplicationController
-  layout 'public'
+  include WebAppControllerConcern
 
-  before_action :set_pack
+  skip_before_action :require_functional!
 
   before_action :set_instance_presenter
-  before_action :set_expires_in
-
-  skip_before_action :require_functional!
 
-  def show; end
+  def show
+    expires_in 0, public: true if current_account.nil?
+  end
 
   private
 
-  def set_pack
-    use_pack 'public'
-  end
-
   def set_instance_presenter
     @instance_presenter = InstancePresenter.new
   end
-
-  def set_expires_in
-    expires_in 0, public: true
-  end
 end
diff --git a/app/controllers/public_timelines_controller.rb b/app/controllers/public_timelines_controller.rb
deleted file mode 100644
index eb5bb191b..000000000
--- a/app/controllers/public_timelines_controller.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class PublicTimelinesController < ApplicationController
-  before_action :set_pack
-  layout 'public'
-
-  before_action :authenticate_user!, if: :whitelist_mode?
-  before_action :require_enabled!
-  before_action :set_body_classes
-  before_action :set_instance_presenter
-
-  def show; end
-
-  private
-
-  def require_enabled!
-    not_found unless Setting.timeline_preview
-  end
-
-  def set_body_classes
-    @body_classes = 'with-modals'
-  end
-
-  def set_instance_presenter
-    @instance_presenter = InstancePresenter.new
-  end
-
-  def set_pack
-    use_pack 'about'
-  end
-end
diff --git a/app/controllers/remote_follow_controller.rb b/app/controllers/remote_follow_controller.rb
deleted file mode 100644
index 93a0a7476..000000000
--- a/app/controllers/remote_follow_controller.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteFollowController < ApplicationController
-  include AccountOwnedConcern
-
-  layout 'modal'
-
-  before_action :set_pack
-  before_action :set_body_classes
-
-  skip_before_action :require_functional!
-
-  def new
-    @remote_follow = RemoteFollow.new(session_params)
-  end
-
-  def create
-    @remote_follow = RemoteFollow.new(resource_params)
-
-    if @remote_follow.valid?
-      session[:remote_follow] = @remote_follow.acct
-      redirect_to @remote_follow.subscribe_address_for(@account)
-    else
-      render :new
-    end
-  end
-
-  private
-
-  def resource_params
-    params.require(:remote_follow).permit(:acct)
-  end
-
-  def session_params
-    { acct: session[:remote_follow] || current_account&.username }
-  end
-
-  def set_pack
-    use_pack 'modal'
-  end
-
-  def set_body_classes
-    @body_classes = 'modal-layout'
-    @hide_header  = true
-  end
-end
diff --git a/app/controllers/remote_interaction_controller.rb b/app/controllers/remote_interaction_controller.rb
deleted file mode 100644
index a277bfa10..000000000
--- a/app/controllers/remote_interaction_controller.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteInteractionController < ApplicationController
-  include Authorization
-
-  layout 'modal'
-
-  before_action :authenticate_user!, if: :whitelist_mode?
-  before_action :set_interaction_type
-  before_action :set_status
-  before_action :set_body_classes
-  before_action :set_pack
-
-  skip_before_action :require_functional!, unless: :whitelist_mode?
-
-  def new
-    @remote_follow = RemoteFollow.new(session_params)
-  end
-
-  def create
-    @remote_follow = RemoteFollow.new(resource_params)
-
-    if @remote_follow.valid?
-      session[:remote_follow] = @remote_follow.acct
-      redirect_to @remote_follow.interact_address_for(@status)
-    else
-      render :new
-    end
-  end
-
-  private
-
-  def resource_params
-    params.require(:remote_follow).permit(:acct)
-  end
-
-  def session_params
-    { acct: session[:remote_follow] || current_account&.username }
-  end
-
-  def set_status
-    @status = Status.find(params[:id])
-    authorize @status, :show?
-  rescue Mastodon::NotPermittedError
-    not_found
-  end
-
-  def set_body_classes
-    @body_classes = 'modal-layout'
-    @hide_header  = true
-  end
-
-  def set_pack
-    use_pack 'modal'
-  end
-
-  def set_interaction_type
-    @interaction_type = %w(reply reblog favourite).include?(params[:type]) ? params[:type] : 'reply'
-  end
-end
diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb
index e0dd5edcb..bb096567a 100644
--- a/app/controllers/settings/deletes_controller.rb
+++ b/app/controllers/settings/deletes_controller.rb
@@ -4,7 +4,6 @@ class Settings::DeletesController < Settings::BaseController
   skip_before_action :require_functional!
 
   before_action :require_not_suspended!
-  before_action :check_enabled_deletion
 
   def show
     @confirmation = Form::DeleteConfirmation.new
@@ -21,10 +20,6 @@ class Settings::DeletesController < Settings::BaseController
 
   private
 
-  def check_enabled_deletion
-    redirect_to root_path unless Setting.open_deletion
-  end
-
   def resource_params
     params.require(:form_delete_confirmation).permit(:password, :username)
   end
diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb
index aadff7c83..b3db04a42 100644
--- a/app/controllers/settings/featured_tags_controller.rb
+++ b/app/controllers/settings/featured_tags_controller.rb
@@ -10,9 +10,9 @@ class Settings::FeaturedTagsController < Settings::BaseController
   end
 
   def create
-    @featured_tag = current_account.featured_tags.new(featured_tag_params)
+    @featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], force: false)
 
-    if @featured_tag.save
+    if @featured_tag.valid?
       redirect_to settings_featured_tags_path
     else
       set_featured_tags
@@ -23,7 +23,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
   end
 
   def destroy
-    @featured_tag.destroy!
+    RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
     redirect_to settings_featured_tags_path
   end
 
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index 55cc3790f..6986176ea 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -1,21 +1,19 @@
 # frozen_string_literal: true
 
 class StatusesController < ApplicationController
+  include WebAppControllerConcern
   include StatusControllerConcern
   include SignatureAuthentication
   include Authorization
   include AccountOwnedConcern
 
-  layout 'public'
-
   before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_status
   before_action :set_instance_presenter
   before_action :set_link_headers
   before_action :redirect_to_original, only: :show
-  before_action :set_referrer_policy_header, only: :show
   before_action :set_cache_headers
-  before_action :set_body_classes
+  before_action :set_body_classes, only: :embed
 
   skip_around_action :set_locale, if: -> { request.format == :json }
   skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode?
@@ -27,11 +25,7 @@ class StatusesController < ApplicationController
   def show
     respond_to do |format|
       format.html do
-        use_pack 'public'
-
         expires_in 10.seconds, public: true if current_account.nil?
-        set_ancestors
-        set_descendants
       end
 
       format.json do
@@ -80,8 +74,4 @@ class StatusesController < ApplicationController
   def redirect_to_original
     redirect_to ActivityPub::TagManager.instance.url_for(@status.reblog) if @status.reblog?
   end
-
-  def set_referrer_policy_header
-    response.headers['Referrer-Policy'] = 'origin' unless @status.distributable?
-  end
 end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 315eabb3d..f0a099350 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -2,18 +2,16 @@
 
 class TagsController < ApplicationController
   include SignatureVerification
+  include WebAppControllerConcern
 
   PAGE_SIZE     = 20
   PAGE_SIZE_MAX = 200
 
-  layout 'public'
-
   before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :authenticate_user!, if: :whitelist_mode?
   before_action :set_local
   before_action :set_tag
   before_action :set_statuses
-  before_action :set_body_classes
   before_action :set_instance_presenter
 
   skip_before_action :require_functional!, unless: :whitelist_mode?
@@ -21,8 +19,7 @@ class TagsController < ApplicationController
   def show
     respond_to do |format|
       format.html do
-        use_pack 'about'
-        expires_in 0, public: true
+        expires_in 0, public: true unless user_signed_in?
       end
 
       format.rss do
@@ -55,10 +52,6 @@ class TagsController < ApplicationController
     end
   end
 
-  def set_body_classes
-    @body_classes = 'with-modals'
-  end
-
   def set_instance_presenter
     @instance_presenter = InstancePresenter.new
   end