about summary refs log tree commit diff
path: root/app/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/admin/account_actions_controller.rb4
-rw-r--r--app/controllers/admin/accounts_controller.rb2
-rw-r--r--app/controllers/admin/action_logs_controller.rb5
-rw-r--r--app/controllers/admin/base_controller.rb2
-rw-r--r--app/controllers/admin/custom_emojis_controller.rb2
-rw-r--r--app/controllers/admin/dashboard_controller.rb4
-rw-r--r--app/controllers/admin/domain_blocks_controller.rb1
-rw-r--r--app/controllers/admin/email_domain_blocks_controller.rb2
-rw-r--r--app/controllers/admin/follow_recommendations_controller.rb2
-rw-r--r--app/controllers/admin/ip_blocks_controller.rb2
-rw-r--r--app/controllers/admin/relationships_controller.rb2
-rw-r--r--app/controllers/admin/roles_controller.rb65
-rw-r--r--app/controllers/admin/statuses_controller.rb2
-rw-r--r--app/controllers/admin/subscriptions_controller.rb20
-rw-r--r--app/controllers/admin/tags_controller.rb4
-rw-r--r--app/controllers/admin/trends/links/preview_card_providers_controller.rb4
-rw-r--r--app/controllers/admin/trends/links_controller.rb4
-rw-r--r--app/controllers/admin/trends/statuses_controller.rb4
-rw-r--r--app/controllers/admin/trends/tags_controller.rb4
-rw-r--r--app/controllers/admin/users/roles_controller.rb33
-rw-r--r--app/controllers/admin/users/two_factor_authentications_controller.rb (renamed from app/controllers/admin/two_factor_authentications_controller.rb)2
-rw-r--r--app/controllers/api/v1/admin/account_actions_controller.rb7
-rw-r--r--app/controllers/api/v1/admin/accounts_controller.rb6
-rw-r--r--app/controllers/api/v1/admin/dimensions_controller.rb6
-rw-r--r--app/controllers/api/v1/admin/domain_allows_controller.rb95
-rw-r--r--app/controllers/api/v1/admin/domain_blocks_controller.rb2
-rw-r--r--app/controllers/api/v1/admin/measures_controller.rb6
-rw-r--r--app/controllers/api/v1/admin/reports_controller.rb2
-rw-r--r--app/controllers/api/v1/admin/retention_controller.rb6
-rw-r--r--app/controllers/api/v1/admin/trends/links_controller.rb20
-rw-r--r--app/controllers/api/v1/admin/trends/statuses_controller.rb20
-rw-r--r--app/controllers/api/v1/admin/trends/tags_controller.rb20
-rw-r--r--app/controllers/api/v1/featured_tags/suggestions_controller.rb2
-rw-r--r--app/controllers/api/v1/featured_tags_controller.rb4
-rw-r--r--app/controllers/api/v1/filters/keywords_controller.rb50
-rw-r--r--app/controllers/api/v1/filters_controller.rb35
-rw-r--r--app/controllers/api/v1/followed_tags_controller.rb52
-rw-r--r--app/controllers/api/v1/push/subscriptions_controller.rb2
-rw-r--r--app/controllers/api/v1/tags_controller.rb30
-rw-r--r--app/controllers/api/v1/trends/links_controller.rb10
-rw-r--r--app/controllers/api/v1/trends/statuses_controller.rb10
-rw-r--r--app/controllers/api/v1/trends/tags_controller.rb14
-rw-r--r--app/controllers/api/v2/admin/accounts_controller.rb13
-rw-r--r--app/controllers/api/v2/filters_controller.rb48
-rw-r--r--app/controllers/application_controller.rb8
-rw-r--r--app/controllers/auth/sessions_controller.rb8
-rw-r--r--app/controllers/custom_css_controller.rb2
-rw-r--r--app/controllers/filters_controller.rb12
-rw-r--r--app/controllers/settings/featured_tags_controller.rb1
49 files changed, 543 insertions, 118 deletions
diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb
index ea56fa0ac..3f2e28b6a 100644
--- a/app/controllers/admin/account_actions_controller.rb
+++ b/app/controllers/admin/account_actions_controller.rb
@@ -5,11 +5,15 @@ module Admin
     before_action :set_account
 
     def new
+      authorize @account, :show?
+
       @account_action  = Admin::AccountAction.new(type: params[:type], report_id: params[:report_id], send_email_notification: true, include_statuses: true)
       @warning_presets = AccountWarningPreset.all
     end
 
     def create
+      authorize @account, :show?
+
       account_action                 = Admin::AccountAction.new(resource_params)
       account_action.target_account  = @account
       account_action.current_account = current_account
diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb
index e0ae71b9f..46c9aba91 100644
--- a/app/controllers/admin/accounts_controller.rb
+++ b/app/controllers/admin/accounts_controller.rb
@@ -14,6 +14,8 @@ module Admin
     end
 
     def batch
+      authorize :account, :index?
+
       @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/action_logs_controller.rb b/app/controllers/admin/action_logs_controller.rb
index 2d77620df..42edec15a 100644
--- a/app/controllers/admin/action_logs_controller.rb
+++ b/app/controllers/admin/action_logs_controller.rb
@@ -4,7 +4,10 @@ module Admin
   class ActionLogsController < BaseController
     before_action :set_action_logs
 
-    def index; end
+    def index
+      authorize :audit_log, :index?
+      @auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username)
+    end
 
     private
 
diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb
index cc6cd51f0..c645ce12b 100644
--- a/app/controllers/admin/base_controller.rb
+++ b/app/controllers/admin/base_controller.rb
@@ -7,9 +7,9 @@ module Admin
 
     layout 'admin'
 
-    before_action :require_staff!
     before_action :set_pack
     before_action :set_body_classes
+    after_action :verify_authorized
 
     private
 
diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb
index 47138bf6c..1fae60f5b 100644
--- a/app/controllers/admin/custom_emojis_controller.rb
+++ b/app/controllers/admin/custom_emojis_controller.rb
@@ -29,6 +29,8 @@ module Admin
     end
 
     def batch
+      authorize :custom_emoji, :index?
+
       @form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index da9c6dd16..924b623ad 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -5,7 +5,9 @@ module Admin
     include Redisable
 
     def index
-      @system_checks         = Admin::SystemCheck.perform
+      authorize :dashboard, :index?
+
+      @system_checks         = Admin::SystemCheck.perform(current_user)
       @time_period           = (29.days.ago.to_date...Time.now.utc.to_date)
       @pending_users_count   = User.pending.count
       @pending_reports_count = Report.unresolved.count
diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb
index 48e9781d6..32f1f9a5d 100644
--- a/app/controllers/admin/domain_blocks_controller.rb
+++ b/app/controllers/admin/domain_blocks_controller.rb
@@ -5,6 +5,7 @@ module Admin
     before_action :set_domain_block, only: [:show, :destroy, :edit, :update]
 
     def batch
+      authorize :domain_block, :create?
       @form = Form::DomainBlockBatch.new(form_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb
index a4bbbba5b..593457b94 100644
--- a/app/controllers/admin/email_domain_blocks_controller.rb
+++ b/app/controllers/admin/email_domain_blocks_controller.rb
@@ -12,6 +12,8 @@ module Admin
     end
 
     def batch
+      authorize :email_domain_block, :index?
+
       @form = Form::EmailDomainBlockBatch.new(form_email_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/follow_recommendations_controller.rb b/app/controllers/admin/follow_recommendations_controller.rb
index e3eac62b3..841e3cc7f 100644
--- a/app/controllers/admin/follow_recommendations_controller.rb
+++ b/app/controllers/admin/follow_recommendations_controller.rb
@@ -12,6 +12,8 @@ module Admin
     end
 
     def update
+      authorize :follow_recommendation, :show?
+
       @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/ip_blocks_controller.rb b/app/controllers/admin/ip_blocks_controller.rb
index 92b8b0d2b..a87520f4e 100644
--- a/app/controllers/admin/ip_blocks_controller.rb
+++ b/app/controllers/admin/ip_blocks_controller.rb
@@ -29,6 +29,8 @@ module Admin
     end
 
     def batch
+      authorize :ip_block, :index?
+
       @form = Form::IpBlockBatch.new(form_ip_block_batch_params.merge(current_account: current_account, action: action_from_button))
       @form.save
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/relationships_controller.rb b/app/controllers/admin/relationships_controller.rb
index 085ded21c..67645f054 100644
--- a/app/controllers/admin/relationships_controller.rb
+++ b/app/controllers/admin/relationships_controller.rb
@@ -7,7 +7,7 @@ module Admin
     PER_PAGE = 40
 
     def index
-      authorize :account, :index?
+      authorize @account, :show?
 
       @accounts = RelationshipFilter.new(@account, filter_params).results.includes(:account_stat, user: [:ips, :invite_request]).page(params[:page]).per(PER_PAGE)
       @form     = Form::AccountBatch.new
diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb
index 13f56e9be..3e502ccc4 100644
--- a/app/controllers/admin/roles_controller.rb
+++ b/app/controllers/admin/roles_controller.rb
@@ -2,20 +2,63 @@
 
 module Admin
   class RolesController < BaseController
-    before_action :set_user
+    before_action :set_role, except: [:index, :new, :create]
 
-    def promote
-      authorize @user, :promote?
-      @user.promote!
-      log_action :promote, @user
-      redirect_to admin_account_path(@user.account_id)
+    def index
+      authorize :user_role, :index?
+
+      @roles = UserRole.order(position: :desc).page(params[:page])
+    end
+
+    def new
+      authorize :user_role, :create?
+
+      @role = UserRole.new
+    end
+
+    def create
+      authorize :user_role, :create?
+
+      @role = UserRole.new(resource_params)
+      @role.current_account = current_account
+
+      if @role.save
+        redirect_to admin_roles_path
+      else
+        render :new
+      end
+    end
+
+    def edit
+      authorize @role, :update?
+    end
+
+    def update
+      authorize @role, :update?
+
+      @role.current_account = current_account
+
+      if @role.update(resource_params)
+        redirect_to admin_roles_path
+      else
+        render :edit
+      end
+    end
+
+    def destroy
+      authorize @role, :destroy?
+      @role.destroy!
+      redirect_to admin_roles_path
+    end
+
+    private
+
+    def set_role
+      @role = UserRole.find(params[:id])
     end
 
-    def demote
-      authorize @user, :demote?
-      @user.demote!
-      log_action :demote, @user
-      redirect_to admin_account_path(@user.account_id)
+    def resource_params
+      params.require(:user_role).permit(:name, :color, :highlighted, :position, permissions_as_keys: [])
     end
   end
 end
diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb
index 817c0caa9..084921ceb 100644
--- a/app/controllers/admin/statuses_controller.rb
+++ b/app/controllers/admin/statuses_controller.rb
@@ -14,6 +14,8 @@ module Admin
     end
 
     def batch
+      authorize :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!
     rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/subscriptions_controller.rb b/app/controllers/admin/subscriptions_controller.rb
deleted file mode 100644
index 40500ef43..000000000
--- a/app/controllers/admin/subscriptions_controller.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
-  class SubscriptionsController < BaseController
-    def index
-      authorize :subscription, :index?
-      @subscriptions = ordered_subscriptions.page(requested_page)
-    end
-
-    private
-
-    def ordered_subscriptions
-      Subscription.order(id: :desc).includes(:account)
-    end
-
-    def requested_page
-      params[:page].to_i
-    end
-  end
-end
diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb
index 749e2f144..4f727c398 100644
--- a/app/controllers/admin/tags_controller.rb
+++ b/app/controllers/admin/tags_controller.rb
@@ -16,6 +16,8 @@ module Admin
       if @tag.update(tag_params.merge(reviewed_at: Time.now.utc))
         redirect_to admin_tag_path(@tag.id), notice: I18n.t('admin.tags.updated_msg')
       else
+        @time_period = (6.days.ago.to_date...Time.now.utc.to_date)
+
         render :show
       end
     end
@@ -27,7 +29,7 @@ module Admin
     end
 
     def tag_params
-      params.require(:tag).permit(:name, :trendable, :usable, :listable)
+      params.require(:tag).permit(:name, :display_name, :trendable, :usable, :listable)
     end
   end
 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 40a466cd6..97dee8eca 100644
--- a/app/controllers/admin/trends/links/preview_card_providers_controller.rb
+++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb
@@ -2,13 +2,15 @@
 
 class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController
   def index
-    authorize :preview_card_provider, :index?
+    authorize :preview_card_provider, :review?
 
     @preview_card_providers = filtered_preview_card_providers.page(params[:page])
     @form = Trends::PreviewCardProviderBatch.new
   end
 
   def batch
+    authorize :preview_card_provider, :review?
+
     @form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb
index 434eec5fe..a497eae41 100644
--- a/app/controllers/admin/trends/links_controller.rb
+++ b/app/controllers/admin/trends/links_controller.rb
@@ -2,13 +2,15 @@
 
 class Admin::Trends::LinksController < Admin::BaseController
   def index
-    authorize :preview_card, :index?
+    authorize :preview_card, :review?
 
     @preview_cards = filtered_preview_cards.page(params[:page])
     @form          = Trends::PreviewCardBatch.new
   end
 
   def batch
+    authorize :preview_card, :review?
+
     @form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/trends/statuses_controller.rb b/app/controllers/admin/trends/statuses_controller.rb
index 766242738..c538962f9 100644
--- a/app/controllers/admin/trends/statuses_controller.rb
+++ b/app/controllers/admin/trends/statuses_controller.rb
@@ -2,13 +2,15 @@
 
 class Admin::Trends::StatusesController < Admin::BaseController
   def index
-    authorize :status, :index?
+    authorize :status, :review?
 
     @statuses = filtered_statuses.page(params[:page])
     @form     = Trends::StatusBatch.new
   end
 
   def batch
+    authorize :status, :review?
+
     @form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb
index f4d1ec0d1..98dd6c8ec 100644
--- a/app/controllers/admin/trends/tags_controller.rb
+++ b/app/controllers/admin/trends/tags_controller.rb
@@ -2,13 +2,15 @@
 
 class Admin::Trends::TagsController < Admin::BaseController
   def index
-    authorize :tag, :index?
+    authorize :tag, :review?
 
     @tags = filtered_tags.page(params[:page])
     @form = Trends::TagBatch.new
   end
 
   def batch
+    authorize :tag, :review?
+
     @form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button))
     @form.save
   rescue ActionController::ParameterMissing
diff --git a/app/controllers/admin/users/roles_controller.rb b/app/controllers/admin/users/roles_controller.rb
new file mode 100644
index 000000000..0db50cee9
--- /dev/null
+++ b/app/controllers/admin/users/roles_controller.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Admin
+  class Users::RolesController < BaseController
+    before_action :set_user
+
+    def show
+      authorize @user, :change_role?
+    end
+
+    def update
+      authorize @user, :change_role?
+
+      @user.current_account = current_account
+
+      if @user.update(resource_params)
+        redirect_to admin_account_path(@user.account_id), notice: I18n.t('admin.accounts.change_role.changed_msg')
+      else
+        render :show
+      end
+    end
+
+    private
+
+    def set_user
+      @user = User.find(params[:user_id])
+    end
+
+    def resource_params
+      params.require(:user).permit(:role_id)
+    end
+  end
+end
diff --git a/app/controllers/admin/two_factor_authentications_controller.rb b/app/controllers/admin/users/two_factor_authentications_controller.rb
index f7fb7eb8f..5e3fb2b3c 100644
--- a/app/controllers/admin/two_factor_authentications_controller.rb
+++ b/app/controllers/admin/users/two_factor_authentications_controller.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 module Admin
-  class TwoFactorAuthenticationsController < BaseController
+  class Users::TwoFactorAuthenticationsController < BaseController
     before_action :set_target_user
 
     def destroy
diff --git a/app/controllers/api/v1/admin/account_actions_controller.rb b/app/controllers/api/v1/admin/account_actions_controller.rb
index 6c9e04402..7249797a4 100644
--- a/app/controllers/api/v1/admin/account_actions_controller.rb
+++ b/app/controllers/api/v1/admin/account_actions_controller.rb
@@ -1,11 +1,16 @@
 # frozen_string_literal: true
 
 class Api::V1::Admin::AccountActionsController < Api::BaseController
+  include Authorization
+
   before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }
-  before_action :require_staff!
   before_action :set_account
 
+  after_action :verify_authorized
+
   def create
+    authorize @account, :show?
+
     account_action                 = Admin::AccountAction.new(resource_params)
     account_action.target_account  = @account
     account_action.current_account = current_account
diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb
index 65ed69f7b..0dee02e94 100644
--- a/app/controllers/api/v1/admin/accounts_controller.rb
+++ b/app/controllers/api/v1/admin/accounts_controller.rb
@@ -8,11 +8,11 @@ class Api::V1::Admin::AccountsController < Api::BaseController
 
   before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:accounts' }, only: [:index, :show]
   before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }, except: [:index, :show]
-  before_action :require_staff!
   before_action :set_accounts, only: :index
   before_action :set_account, except: :index
   before_action :require_local_account!, only: [:enable, :approve, :reject]
 
+  after_action :verify_authorized
   after_action :insert_pagination_headers, only: :index
 
   FILTER_PARAMS = %i(
@@ -119,7 +119,9 @@ class Api::V1::Admin::AccountsController < Api::BaseController
       translated_params[:status] = status.to_s if params[status].present?
     end
 
-    translated_params[:permissions] = 'staff' if params[:staff].present?
+    if params[:staff].present?
+      translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id)
+    end
 
     translated_params
   end
diff --git a/app/controllers/api/v1/admin/dimensions_controller.rb b/app/controllers/api/v1/admin/dimensions_controller.rb
index 49a5be1c3..4a72ad08b 100644
--- a/app/controllers/api/v1/admin/dimensions_controller.rb
+++ b/app/controllers/api/v1/admin/dimensions_controller.rb
@@ -1,11 +1,15 @@
 # frozen_string_literal: true
 
 class Api::V1::Admin::DimensionsController < Api::BaseController
+  include Authorization
+
   before_action -> { authorize_if_got_token! :'admin:read' }
-  before_action :require_staff!
   before_action :set_dimensions
 
+  after_action :verify_authorized
+
   def create
+    authorize :dashboard, :index?
     render json: @dimensions, each_serializer: REST::Admin::DimensionSerializer
   end
 
diff --git a/app/controllers/api/v1/admin/domain_allows_controller.rb b/app/controllers/api/v1/admin/domain_allows_controller.rb
new file mode 100644
index 000000000..59aa807d6
--- /dev/null
+++ b/app/controllers/api/v1/admin/domain_allows_controller.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+class Api::V1::Admin::DomainAllowsController < Api::BaseController
+  include Authorization
+  include AccountableConcern
+
+  LIMIT = 100
+
+  before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_allows' }, only: [:index, :show]
+  before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_allows' }, except: [:index, :show]
+  before_action :set_domain_allows, only: :index
+  before_action :set_domain_allow, only: [:show, :destroy]
+
+  after_action :verify_authorized
+  after_action :insert_pagination_headers, only: :index
+
+  PAGINATION_PARAMS = %i(limit).freeze
+
+  def create
+    authorize :domain_allow, :create?
+
+    @domain_allow = DomainAllow.find_by(resource_params)
+
+    if @domain_allow.nil?
+      @domain_allow = DomainAllow.create!(resource_params)
+      log_action :create, @domain_allow
+    end
+
+    render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer
+  end
+
+  def index
+    authorize :domain_allow, :index?
+    render json: @domain_allows, each_serializer: REST::Admin::DomainAllowSerializer
+  end
+
+  def show
+    authorize @domain_allow, :show?
+    render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer
+  end
+
+  def destroy
+    authorize @domain_allow, :destroy?
+    UnallowDomainService.new.call(@domain_allow)
+    log_action :destroy, @domain_allow
+    render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer
+  end
+
+  private
+
+  def set_domain_allows
+    @domain_allows = filtered_domain_allows.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+  end
+
+  def set_domain_allow
+    @domain_allow = DomainAllow.find(params[:id])
+  end
+
+  def filtered_domain_allows
+    # TODO: no filtering yet
+    DomainAllow.all
+  end
+
+  def insert_pagination_headers
+    set_pagination_headers(next_path, prev_path)
+  end
+
+  def next_path
+    api_v1_admin_domain_allows_url(pagination_params(max_id: pagination_max_id)) if records_continue?
+  end
+
+  def prev_path
+    api_v1_admin_domain_allows_url(pagination_params(min_id: pagination_since_id)) unless @domain_allows.empty?
+  end
+
+  def pagination_max_id
+    @domain_allows.last.id
+  end
+
+  def pagination_since_id
+    @domain_allows.first.id
+  end
+
+  def records_continue?
+    @domain_allows.size == limit_param(LIMIT)
+  end
+
+  def pagination_params(core_params)
+    params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
+  end
+
+  def resource_params
+    params.permit(:domain)
+  end
+end
diff --git a/app/controllers/api/v1/admin/domain_blocks_controller.rb b/app/controllers/api/v1/admin/domain_blocks_controller.rb
index 229870eee..de8fd9d08 100644
--- a/app/controllers/api/v1/admin/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/admin/domain_blocks_controller.rb
@@ -8,10 +8,10 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
 
   before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_blocks' }, only: [:index, :show]
   before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_blocks' }, except: [:index, :show]
-  before_action :require_staff!
   before_action :set_domain_blocks, only: :index
   before_action :set_domain_block, only: [:show, :update, :destroy]
 
+  after_action :verify_authorized
   after_action :insert_pagination_headers, only: :index
 
   PAGINATION_PARAMS = %i(limit).freeze
diff --git a/app/controllers/api/v1/admin/measures_controller.rb b/app/controllers/api/v1/admin/measures_controller.rb
index da95d3422..d78d7e10b 100644
--- a/app/controllers/api/v1/admin/measures_controller.rb
+++ b/app/controllers/api/v1/admin/measures_controller.rb
@@ -1,11 +1,15 @@
 # frozen_string_literal: true
 
 class Api::V1::Admin::MeasuresController < Api::BaseController
+  include Authorization
+
   before_action -> { authorize_if_got_token! :'admin:read' }
-  before_action :require_staff!
   before_action :set_measures
 
+  after_action :verify_authorized
+
   def create
+    authorize :dashboard, :index?
     render json: @measures, each_serializer: REST::Admin::MeasureSerializer
   end
 
diff --git a/app/controllers/api/v1/admin/reports_controller.rb b/app/controllers/api/v1/admin/reports_controller.rb
index 865ba3d23..9dfb181a2 100644
--- a/app/controllers/api/v1/admin/reports_controller.rb
+++ b/app/controllers/api/v1/admin/reports_controller.rb
@@ -8,10 +8,10 @@ class Api::V1::Admin::ReportsController < Api::BaseController
 
   before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:reports' }, only: [:index, :show]
   before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:reports' }, except: [:index, :show]
-  before_action :require_staff!
   before_action :set_reports, only: :index
   before_action :set_report, except: :index
 
+  after_action :verify_authorized
   after_action :insert_pagination_headers, only: :index
 
   FILTER_PARAMS = %i(
diff --git a/app/controllers/api/v1/admin/retention_controller.rb b/app/controllers/api/v1/admin/retention_controller.rb
index 98d1a3d81..59d6b8388 100644
--- a/app/controllers/api/v1/admin/retention_controller.rb
+++ b/app/controllers/api/v1/admin/retention_controller.rb
@@ -1,11 +1,15 @@
 # frozen_string_literal: true
 
 class Api::V1::Admin::RetentionController < Api::BaseController
+  include Authorization
+
   before_action -> { authorize_if_got_token! :'admin:read' }
-  before_action :require_staff!
   before_action :set_cohorts
 
+  after_action :verify_authorized
+
   def create
+    authorize :dashboard, :index?
     render json: @cohorts, each_serializer: REST::Admin::CohortSerializer
   end
 
diff --git a/app/controllers/api/v1/admin/trends/links_controller.rb b/app/controllers/api/v1/admin/trends/links_controller.rb
index 0a191fe4b..cc6388980 100644
--- a/app/controllers/api/v1/admin/trends/links_controller.rb
+++ b/app/controllers/api/v1/admin/trends/links_controller.rb
@@ -1,17 +1,19 @@
 # frozen_string_literal: true
 
-class Api::V1::Admin::Trends::LinksController < Api::BaseController
+class Api::V1::Admin::Trends::LinksController < Api::V1::Trends::LinksController
   before_action -> { authorize_if_got_token! :'admin:read' }
-  before_action :require_staff!
-  before_action :set_links
-
-  def index
-    render json: @links, each_serializer: REST::Trends::LinkSerializer
-  end
 
   private
 
-  def set_links
-    @links = Trends.links.query.limit(limit_param(10))
+  def enabled?
+    super || current_user&.can?(:manage_taxonomies)
+  end
+
+  def links_from_trends
+    if current_user&.can?(:manage_taxonomies)
+      Trends.links.query
+    else
+      super
+    end
   end
 end
diff --git a/app/controllers/api/v1/admin/trends/statuses_controller.rb b/app/controllers/api/v1/admin/trends/statuses_controller.rb
index cb145f165..c39f77363 100644
--- a/app/controllers/api/v1/admin/trends/statuses_controller.rb
+++ b/app/controllers/api/v1/admin/trends/statuses_controller.rb
@@ -1,17 +1,19 @@
 # frozen_string_literal: true
 
-class Api::V1::Admin::Trends::StatusesController < Api::BaseController
+class Api::V1::Admin::Trends::StatusesController < Api::V1::Trends::StatusesController
   before_action -> { authorize_if_got_token! :'admin:read' }
-  before_action :require_staff!
-  before_action :set_statuses
-
-  def index
-    render json: @statuses, each_serializer: REST::StatusSerializer
-  end
 
   private
 
-  def set_statuses
-    @statuses = cache_collection(Trends.statuses.query.limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
+  def enabled?
+    super || current_user&.can?(:manage_taxonomies)
+  end
+
+  def statuses_from_trends
+    if current_user&.can?(:manage_taxonomies)
+      Trends.statuses.query
+    else
+      super
+    end
   end
 end
diff --git a/app/controllers/api/v1/admin/trends/tags_controller.rb b/app/controllers/api/v1/admin/trends/tags_controller.rb
index 9c28b0412..f3c0c4b6b 100644
--- a/app/controllers/api/v1/admin/trends/tags_controller.rb
+++ b/app/controllers/api/v1/admin/trends/tags_controller.rb
@@ -1,17 +1,19 @@
 # frozen_string_literal: true
 
-class Api::V1::Admin::Trends::TagsController < Api::BaseController
+class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
   before_action -> { authorize_if_got_token! :'admin:read' }
-  before_action :require_staff!
-  before_action :set_tags
-
-  def index
-    render json: @tags, each_serializer: REST::Admin::TagSerializer
-  end
 
   private
 
-  def set_tags
-    @tags = Trends.tags.query.limit(limit_param(10))
+  def enabled?
+    super || current_user&.can?(:manage_taxonomies)
+  end
+
+  def tags_from_trends
+    if current_user&.can?(:manage_taxonomies)
+      Trends.tags.query
+    else
+      super
+    end
   end
 end
diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
index 75545d3c7..76633210a 100644
--- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb
+++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
@@ -6,7 +6,7 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController
   before_action :set_recently_used_tags, only: :index
 
   def index
-    render json: @recently_used_tags, each_serializer: REST::TagSerializer
+    render json: @recently_used_tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@recently_used_tags, current_user&.account_id)
   end
 
   private
diff --git a/app/controllers/api/v1/featured_tags_controller.rb b/app/controllers/api/v1/featured_tags_controller.rb
index e4e836c97..c1ead4f54 100644
--- a/app/controllers/api/v1/featured_tags_controller.rb
+++ b/app/controllers/api/v1/featured_tags_controller.rb
@@ -13,9 +13,7 @@ class Api::V1::FeaturedTagsController < Api::BaseController
   end
 
   def create
-    @featured_tag = current_account.featured_tags.new(featured_tag_params)
-    @featured_tag.reset_data
-    @featured_tag.save!
+    @featured_tag = current_account.featured_tags.create!(featured_tag_params)
     render json: @featured_tag, serializer: REST::FeaturedTagSerializer
   end
 
diff --git a/app/controllers/api/v1/filters/keywords_controller.rb b/app/controllers/api/v1/filters/keywords_controller.rb
new file mode 100644
index 000000000..d3718a137
--- /dev/null
+++ b/app/controllers/api/v1/filters/keywords_controller.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+class Api::V1::Filters::KeywordsController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show]
+  before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show]
+  before_action :require_user!
+
+  before_action :set_keywords, only: :index
+  before_action :set_keyword, only: [:show, :update, :destroy]
+
+  def index
+    render json: @keywords, each_serializer: REST::FilterKeywordSerializer
+  end
+
+  def create
+    @keyword = current_account.custom_filters.find(params[:filter_id]).keywords.create!(resource_params)
+
+    render json: @keyword, serializer: REST::FilterKeywordSerializer
+  end
+
+  def show
+    render json: @keyword, serializer: REST::FilterKeywordSerializer
+  end
+
+  def update
+    @keyword.update!(resource_params)
+
+    render json: @keyword, serializer: REST::FilterKeywordSerializer
+  end
+
+  def destroy
+    @keyword.destroy!
+    render_empty
+  end
+
+  private
+
+  def set_keywords
+    filter = current_account.custom_filters.includes(:keywords).find(params[:filter_id])
+    @keywords = filter.keywords
+  end
+
+  def set_keyword
+    @keyword = CustomFilterKeyword.includes(:custom_filter).where(custom_filter: { account: current_account }).find(params[:id])
+  end
+
+  def resource_params
+    params.permit(:keyword, :whole_word)
+  end
+end
diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb
index b0ace3af0..07cd14147 100644
--- a/app/controllers/api/v1/filters_controller.rb
+++ b/app/controllers/api/v1/filters_controller.rb
@@ -8,21 +8,32 @@ class Api::V1::FiltersController < Api::BaseController
   before_action :set_filter, only: [:show, :update, :destroy]
 
   def index
-    render json: @filters, each_serializer: REST::FilterSerializer
+    render json: @filters, each_serializer: REST::V1::FilterSerializer
   end
 
   def create
-    @filter = current_account.custom_filters.create!(resource_params)
-    render json: @filter, serializer: REST::FilterSerializer
+    ApplicationRecord.transaction do
+      filter_category = current_account.custom_filters.create!(resource_params)
+      @filter = filter_category.keywords.create!(keyword_params)
+    end
+
+    render json: @filter, serializer: REST::V1::FilterSerializer
   end
 
   def show
-    render json: @filter, serializer: REST::FilterSerializer
+    render json: @filter, serializer: REST::V1::FilterSerializer
   end
 
   def update
-    @filter.update!(resource_params)
-    render json: @filter, serializer: REST::FilterSerializer
+    ApplicationRecord.transaction do
+      @filter.update!(keyword_params)
+      @filter.custom_filter.assign_attributes(filter_params)
+      raise Mastodon::ValidationError, I18n.t('filters.errors.deprecated_api_multiple_keywords') if @filter.custom_filter.changed? && @filter.custom_filter.keywords.count > 1
+
+      @filter.custom_filter.save!
+    end
+
+    render json: @filter, serializer: REST::V1::FilterSerializer
   end
 
   def destroy
@@ -33,14 +44,22 @@ class Api::V1::FiltersController < Api::BaseController
   private
 
   def set_filters
-    @filters = current_account.custom_filters
+    @filters = CustomFilterKeyword.includes(:custom_filter).where(custom_filter: { account: current_account })
   end
 
   def set_filter
-    @filter = current_account.custom_filters.find(params[:id])
+    @filter = CustomFilterKeyword.includes(:custom_filter).where(custom_filter: { account: current_account }).find(params[:id])
   end
 
   def resource_params
     params.permit(:phrase, :expires_in, :irreversible, :whole_word, context: [])
   end
+
+  def filter_params
+    resource_params.slice(:expires_in, :irreversible, :context)
+  end
+
+  def keyword_params
+    resource_params.slice(:phrase, :whole_word)
+  end
 end
diff --git a/app/controllers/api/v1/followed_tags_controller.rb b/app/controllers/api/v1/followed_tags_controller.rb
new file mode 100644
index 000000000..f0dfd044c
--- /dev/null
+++ b/app/controllers/api/v1/followed_tags_controller.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+class Api::V1::FollowedTagsController < Api::BaseController
+  TAGS_LIMIT = 100
+
+  before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' }, except: :show
+  before_action :require_user!
+  before_action :set_results
+
+  after_action :insert_pagination_headers, only: :show
+
+  def index
+    render json: @results.map(&:tag), each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@results.map(&:tag), current_user&.account_id)
+  end
+
+  private
+
+  def set_results
+    @results = TagFollow.where(account: current_account).joins(:tag).eager_load(:tag).to_a_paginated_by_id(
+      limit_param(TAGS_LIMIT),
+      params_slice(:max_id, :since_id, :min_id)
+    )
+  end
+
+  def insert_pagination_headers
+    set_pagination_headers(next_path, prev_path)
+  end
+
+  def next_path
+    api_v1_followed_tags_url pagination_params(max_id: pagination_max_id) if records_continue?
+  end
+
+  def prev_path
+    api_v1_followed_tags_url pagination_params(since_id: pagination_since_id) unless @results.empty?
+  end
+
+  def pagination_max_id
+    @results.last.id
+  end
+
+  def pagination_since_id
+    @results.first.id
+  end
+
+  def records_continue?
+    @results.size == limit_param(TAG_LIMIT)
+  end
+
+  def pagination_params(core_params)
+    params.slice(:limit).permit(:limit).merge(core_params)
+  end
+end
diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb
index 47f2e6440..7148d63a4 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(:policy, alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status])
+    params.require(:data).permit(:policy, alerts: Notification::TYPES)
   end
 end
diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb
new file mode 100644
index 000000000..9e5c53330
--- /dev/null
+++ b/app/controllers/api/v1/tags_controller.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class Api::V1::TagsController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, except: :show
+  before_action :require_user!, except: :show
+  before_action :set_or_create_tag
+
+  override_rate_limit_headers :follow, family: :follows
+
+  def show
+    render json: @tag, serializer: REST::TagSerializer
+  end
+
+  def follow
+    TagFollow.create!(tag: @tag, account: current_account, rate_limit: true)
+    render json: @tag, serializer: REST::TagSerializer
+  end
+
+  def unfollow
+    TagFollow.find_by(account: current_account, tag: @tag)&.destroy!
+    render json: @tag, serializer: REST::TagSerializer
+  end
+
+  private
+
+  def set_or_create_tag
+    return not_found unless /\A(#{Tag::HASHTAG_NAME_RE})\z/.match?(params[:id])
+    @tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id])
+  end
+end
diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb
index 2385fe438..1a9f918f2 100644
--- a/app/controllers/api/v1/trends/links_controller.rb
+++ b/app/controllers/api/v1/trends/links_controller.rb
@@ -13,10 +13,14 @@ class Api::V1::Trends::LinksController < Api::BaseController
 
   private
 
+  def enabled?
+    Setting.trends
+  end
+
   def set_links
     @links = begin
-      if Setting.trends
-        links_from_trends
+      if enabled?
+        links_from_trends.offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT))
       else
         []
       end
@@ -24,7 +28,7 @@ class Api::V1::Trends::LinksController < Api::BaseController
   end
 
   def links_from_trends
-    Trends.links.query.allowed.in_locale(content_locale).offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT))
+    Trends.links.query.allowed.in_locale(content_locale)
   end
 
   def insert_pagination_headers
diff --git a/app/controllers/api/v1/trends/statuses_controller.rb b/app/controllers/api/v1/trends/statuses_controller.rb
index 1f2fff582..c275d5fc8 100644
--- a/app/controllers/api/v1/trends/statuses_controller.rb
+++ b/app/controllers/api/v1/trends/statuses_controller.rb
@@ -11,10 +11,14 @@ class Api::V1::Trends::StatusesController < Api::BaseController
 
   private
 
+  def enabled?
+    Setting.trends
+  end
+
   def set_statuses
     @statuses = begin
-      if Setting.trends
-        cache_collection(statuses_from_trends, Status)
+      if enabled?
+        cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
       else
         []
       end
@@ -24,7 +28,7 @@ class Api::V1::Trends::StatusesController < Api::BaseController
   def statuses_from_trends
     scope = Trends.statuses.query.allowed.in_locale(content_locale)
     scope = scope.filtered_for(current_account) if user_signed_in?
-    scope.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT))
+    scope
   end
 
   def insert_pagination_headers
diff --git a/app/controllers/api/v1/trends/tags_controller.rb b/app/controllers/api/v1/trends/tags_controller.rb
index 38003f599..21adfa2a1 100644
--- a/app/controllers/api/v1/trends/tags_controller.rb
+++ b/app/controllers/api/v1/trends/tags_controller.rb
@@ -8,21 +8,29 @@ class Api::V1::Trends::TagsController < Api::BaseController
   DEFAULT_TAGS_LIMIT = 10
 
   def index
-    render json: @tags, each_serializer: REST::TagSerializer
+    render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id)
   end
 
   private
 
+  def enabled?
+    Setting.trends
+  end
+
   def set_tags
     @tags = begin
-      if Setting.trends
-        Trends.tags.query.allowed.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT))
+      if enabled?
+        tags_from_trends.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT))
       else
         []
       end
     end
   end
 
+  def tags_from_trends
+    Trends.tags.query.allowed
+  end
+
   def insert_pagination_headers
     set_pagination_headers(next_path, prev_path)
   end
diff --git a/app/controllers/api/v2/admin/accounts_controller.rb b/app/controllers/api/v2/admin/accounts_controller.rb
index a89e6835e..bcc1a0733 100644
--- a/app/controllers/api/v2/admin/accounts_controller.rb
+++ b/app/controllers/api/v2/admin/accounts_controller.rb
@@ -11,6 +11,7 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
     email
     ip
     invited_by
+    role_ids
   ).freeze
 
   PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze
@@ -18,7 +19,17 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
   private
 
   def filtered_accounts
-    AccountFilter.new(filter_params).results
+    AccountFilter.new(translated_filter_params).results
+  end
+
+  def translated_filter_params
+    translated_params = filter_params.slice(*AccountFilter::KEYS)
+
+    if params[:permissions] == 'staff'
+      translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id)
+    end
+
+    translated_params
   end
 
   def filter_params
diff --git a/app/controllers/api/v2/filters_controller.rb b/app/controllers/api/v2/filters_controller.rb
new file mode 100644
index 000000000..8ff3076cf
--- /dev/null
+++ b/app/controllers/api/v2/filters_controller.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+class Api::V2::FiltersController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show]
+  before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show]
+  before_action :require_user!
+  before_action :set_filters, only: :index
+  before_action :set_filter, only: [:show, :update, :destroy]
+
+  def index
+    render json: @filters, each_serializer: REST::FilterSerializer, rules_requested: true
+  end
+
+  def create
+    @filter = current_account.custom_filters.create!(resource_params)
+
+    render json: @filter, serializer: REST::FilterSerializer, rules_requested: true
+  end
+
+  def show
+    render json: @filter, serializer: REST::FilterSerializer, rules_requested: true
+  end
+
+  def update
+    @filter.update!(resource_params)
+
+    render json: @filter, serializer: REST::FilterSerializer, rules_requested: true
+  end
+
+  def destroy
+    @filter.destroy!
+    render_empty
+  end
+
+  private
+
+  def set_filters
+    @filters = current_account.custom_filters.includes(:keywords)
+  end
+
+  def set_filter
+    @filter = current_account.custom_filters.find(params[:id])
+  end
+
+  def resource_params
+    params.permit(:title, :expires_in, :filter_action, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
+  end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0f948ff5f..ee3c5204d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -58,14 +58,6 @@ class ApplicationController < ActionController::Base
     store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym)
   end
 
-  def require_admin!
-    forbidden unless current_user&.admin?
-  end
-
-  def require_staff!
-    forbidden unless current_user&.staff?
-  end
-
   def require_functional!
     redirect_to edit_user_registration_path unless current_user.functional?
   end
diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb
index 056f8a9f1..13dfebcdd 100644
--- a/app/controllers/auth/sessions_controller.rb
+++ b/app/controllers/auth/sessions_controller.rb
@@ -8,12 +8,18 @@ class Auth::SessionsController < Devise::SessionsController
   skip_before_action :update_user_sign_in
 
   prepend_before_action :set_pack
+  prepend_before_action :check_suspicious!, only: [:create]
 
   include TwoFactorAuthenticationConcern
 
   before_action :set_instance_presenter, only: [:new]
   before_action :set_body_classes
 
+  def check_suspicious!
+    user = find_user
+    @login_is_suspicious = suspicious_sign_in?(user) unless user.nil?
+  end
+
   def create
     super do |resource|
       # We only need to call this if this hasn't already been
@@ -148,7 +154,7 @@ class Auth::SessionsController < Devise::SessionsController
       user_agent: request.user_agent
     )
 
-    UserMailer.suspicious_sign_in(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later! if suspicious_sign_in?(user)
+    UserMailer.suspicious_sign_in(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later! if @login_is_suspicious
   end
 
   def suspicious_sign_in?(user)
diff --git a/app/controllers/custom_css_controller.rb b/app/controllers/custom_css_controller.rb
index e1dc5eaf6..9270c467d 100644
--- a/app/controllers/custom_css_controller.rb
+++ b/app/controllers/custom_css_controller.rb
@@ -13,6 +13,6 @@ class CustomCssController < ApplicationController
   def show
     expires_in 3.minutes, public: true
     request.session_options[:skip] = true
-    render plain: Setting.custom_css || '', content_type: 'text/css'
+    render content_type: 'text/css'
   end
 end
diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb
index 0d4c1b97c..6d778312e 100644
--- a/app/controllers/filters_controller.rb
+++ b/app/controllers/filters_controller.rb
@@ -4,17 +4,17 @@ class FiltersController < ApplicationController
   layout 'admin'
 
   before_action :authenticate_user!
-  before_action :set_filters, only: :index
   before_action :set_filter, only: [:edit, :update, :destroy]
   before_action :set_pack
   before_action :set_body_classes
 
   def index
-    @filters = current_account.custom_filters.order(:phrase)
+    @filters = current_account.custom_filters.includes(:keywords).order(:phrase)
   end
 
   def new
-    @filter = current_account.custom_filters.build
+    @filter = current_account.custom_filters.build(action: :warn)
+    @filter.keywords.build
   end
 
   def create
@@ -48,16 +48,12 @@ class FiltersController < ApplicationController
     use_pack 'settings'
   end
 
-  def set_filters
-    @filters = current_account.custom_filters
-  end
-
   def set_filter
     @filter = current_account.custom_filters.find(params[:id])
   end
 
   def resource_params
-    params.require(:custom_filter).permit(:phrase, :expires_in, :irreversible, :whole_word, context: [])
+    params.require(:custom_filter).permit(:title, :expires_in, :filter_action, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
   end
 
   def set_body_classes
diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb
index e805527d0..aadff7c83 100644
--- a/app/controllers/settings/featured_tags_controller.rb
+++ b/app/controllers/settings/featured_tags_controller.rb
@@ -11,7 +11,6 @@ class Settings::FeaturedTagsController < Settings::BaseController
 
   def create
     @featured_tag = current_account.featured_tags.new(featured_tag_params)
-    @featured_tag.reset_data
 
     if @featured_tag.save
       redirect_to settings_featured_tags_path