about summary refs log tree commit diff
path: root/app/controllers/admin
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/admin')
-rw-r--r--app/controllers/admin/account_moderation_notes_controller.rb2
-rw-r--r--app/controllers/admin/accounts_controller.rb45
-rw-r--r--app/controllers/admin/dashboard_controller.rb37
-rw-r--r--app/controllers/admin/instances_controller.rb9
-rw-r--r--app/controllers/admin/pending_accounts_controller.rb52
-rw-r--r--app/controllers/admin/report_notes_controller.rb23
-rw-r--r--app/controllers/admin/reported_statuses_controller.rb44
-rw-r--r--app/controllers/admin/reports_controller.rb6
-rw-r--r--app/controllers/admin/resets_controller.rb4
-rw-r--r--app/controllers/admin/sign_in_token_authentications_controller.rb27
-rw-r--r--app/controllers/admin/statuses_controller.rb66
-rw-r--r--app/controllers/admin/tags_controller.rb76
-rw-r--r--app/controllers/admin/trends/links/preview_card_providers_controller.rb41
-rw-r--r--app/controllers/admin/trends/links_controller.rb45
-rw-r--r--app/controllers/admin/trends/tags_controller.rb41
-rw-r--r--app/controllers/admin/two_factor_authentications_controller.rb2
16 files changed, 256 insertions, 264 deletions
diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb
index 44f6e34f8..4f36f33f4 100644
--- a/app/controllers/admin/account_moderation_notes_controller.rb
+++ b/app/controllers/admin/account_moderation_notes_controller.rb
@@ -14,7 +14,7 @@ module Admin
       else
         @account          = @account_moderation_note.target_account
         @moderation_notes = @account.targeted_moderation_notes.latest
-        @warnings         = @account.targeted_account_warnings.latest.custom
+        @warnings         = @account.strikes.custom.latest
 
         render template: 'admin/accounts/show'
       end
diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb
index 1dd7430e0..e7f56e243 100644
--- a/app/controllers/admin/accounts_controller.rb
+++ b/app/controllers/admin/accounts_controller.rb
@@ -2,13 +2,24 @@
 
 module Admin
   class AccountsController < BaseController
-    before_action :set_account, except: [:index]
+    before_action :set_account, except: [:index, :batch]
     before_action :require_remote_account!, only: [:redownload]
     before_action :require_local_account!, only: [:enable, :memorialize, :approve, :reject]
 
     def index
       authorize :account, :index?
+
       @accounts = filtered_accounts.page(params[:page])
+      @form     = Form::AccountBatch.new
+    end
+
+    def batch
+      @form = Form::AccountBatch.new(form_account_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')
+    ensure
+      redirect_to admin_accounts_path(filter_params)
     end
 
     def show
@@ -17,7 +28,7 @@ module Admin
       @deletion_request        = @account.deletion_request
       @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
       @moderation_notes        = @account.targeted_moderation_notes.latest
-      @warnings                = @account.targeted_account_warnings.latest.custom
+      @warnings                = @account.strikes.custom.latest
       @domain_block            = DomainBlock.rule_for(@account.domain)
     end
 
@@ -38,13 +49,13 @@ module Admin
     def approve
       authorize @account.user, :approve?
       @account.user.approve!
-      redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
+      redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
     end
 
     def reject
       authorize @account.user, :reject?
       DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
-      redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
+      redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
     end
 
     def destroy
@@ -106,6 +117,16 @@ module Admin
       redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_header_msg', username: @account.acct)
     end
 
+    def unblock_email
+      authorize @account, :unblock_email?
+
+      CanonicalEmailBlock.where(reference_account: @account).delete_all
+
+      log_action :unblock_email, @account
+
+      redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unblocked_email_msg', username: @account.acct)
+    end
+
     private
 
     def set_account
@@ -121,11 +142,25 @@ module Admin
     end
 
     def filtered_accounts
-      AccountFilter.new(filter_params).results
+      AccountFilter.new(filter_params.with_defaults(order: 'recent')).results
     end
 
     def filter_params
       params.slice(*AccountFilter::KEYS).permit(*AccountFilter::KEYS)
     end
+
+    def form_account_batch_params
+      params.require(:form_account_batch).permit(:action, account_ids: [])
+    end
+
+    def action_from_button
+      if params[:suspend]
+        'suspend'
+      elsif params[:approve]
+        'approve'
+      elsif params[:reject]
+        'reject'
+      end
+    end
   end
 end
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index a00d7ed96..f0a935411 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -1,50 +1,17 @@
 # frozen_string_literal: true
-require 'sidekiq/api'
 
 module Admin
   class DashboardController < BaseController
     def index
       @system_checks         = Admin::SystemCheck.perform
-      @users_count           = User.count
+      @time_period           = (29.days.ago.to_date...Time.now.utc.to_date)
       @pending_users_count   = User.pending.count
-      @registrations_week    = Redis.current.get("activity:accounts:local:#{current_week}") || 0
-      @logins_week           = Redis.current.pfcount("activity:logins:#{current_week}")
-      @interactions_week     = Redis.current.get("activity:interactions:#{current_week}") || 0
-      @relay_enabled         = Relay.enabled.exists?
-      @single_user_mode      = Rails.configuration.x.single_user_mode
-      @registrations_enabled = Setting.registrations_mode != 'none'
-      @deletions_enabled     = Setting.open_deletion
-      @invites_enabled       = Setting.min_invite_role == 'user'
-      @search_enabled        = Chewy.enabled?
-      @version               = Mastodon::Version.to_s
-      @database_version      = ActiveRecord::Base.connection.execute('SELECT VERSION()').first['version'].match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
-      @redis_version         = redis_info['redis_version']
-      @reports_count         = Report.unresolved.count
-      @queue_backlog         = Sidekiq::Stats.new.enqueued
-      @recent_users          = User.confirmed.recent.includes(:account).limit(8)
-      @database_size         = ActiveRecord::Base.connection.execute('SELECT pg_database_size(current_database())').first['pg_database_size']
-      @redis_size            = redis_info['used_memory']
-      @ldap_enabled          = ENV['LDAP_ENABLED'] == 'true'
-      @cas_enabled           = ENV['CAS_ENABLED'] == 'true'
-      @saml_enabled          = ENV['SAML_ENABLED'] == 'true'
-      @pam_enabled           = ENV['PAM_ENABLED'] == 'true'
-      @hidden_service        = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
-      @trending_hashtags     = TrendingTags.get(10, filtered: false)
+      @pending_reports_count = Report.unresolved.count
       @pending_tags_count    = Tag.pending_review.count
-      @authorized_fetch      = authorized_fetch_mode?
-      @whitelist_enabled     = whitelist_mode?
-      @profile_directory     = Setting.profile_directory
-      @timeline_preview      = Setting.timeline_preview
-      @keybase_integration   = Setting.enable_keybase
-      @trends_enabled        = Setting.trends
     end
 
     private
 
-    def current_week
-      @current_week ||= Time.now.utc.to_date.cweek
-    end
-
     def redis_info
       @redis_info ||= begin
         if Redis.current.is_a?(Redis::Namespace)
diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb
index 748c5de5a..306ec1f53 100644
--- a/app/controllers/admin/instances_controller.rb
+++ b/app/controllers/admin/instances_controller.rb
@@ -14,6 +14,15 @@ module Admin
       authorize :instance, :show?
     end
 
+    def destroy
+      authorize :instance, :destroy?
+
+      Admin::DomainPurgeWorker.perform_async(@instance.domain)
+
+      log_action :destroy, @instance
+      redirect_to admin_instances_path, notice: I18n.t('admin.instances.destroyed_msg', domain: @instance.domain)
+    end
+
     def clear_delivery_errors
       authorize :delivery, :clear_delivery_errors?
 
diff --git a/app/controllers/admin/pending_accounts_controller.rb b/app/controllers/admin/pending_accounts_controller.rb
deleted file mode 100644
index b62a9bc84..000000000
--- a/app/controllers/admin/pending_accounts_controller.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
-  class PendingAccountsController < BaseController
-    before_action :set_accounts, only: :index
-
-    def index
-      @form = Form::AccountBatch.new
-    end
-
-    def batch
-      @form = Form::AccountBatch.new(form_account_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')
-    ensure
-      redirect_to admin_pending_accounts_path(current_params)
-    end
-
-    def approve_all
-      Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'approve').save
-      redirect_to admin_pending_accounts_path(current_params)
-    end
-
-    def reject_all
-      Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'reject').save
-      redirect_to admin_pending_accounts_path(current_params)
-    end
-
-    private
-
-    def set_accounts
-      @accounts = Account.joins(:user).merge(User.pending.recent).includes(user: :invite_request).page(params[:page])
-    end
-
-    def form_account_batch_params
-      params.require(:form_account_batch).permit(:action, account_ids: [])
-    end
-
-    def action_from_button
-      if params[:approve]
-        'approve'
-      elsif params[:reject]
-        'reject'
-      end
-    end
-
-    def current_params
-      params.slice(:page).permit(:page)
-    end
-  end
-end
diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb
index b816c5b5d..3fd815b60 100644
--- a/app/controllers/admin/report_notes_controller.rb
+++ b/app/controllers/admin/report_notes_controller.rb
@@ -14,20 +14,17 @@ module Admin
         if params[:create_and_resolve]
           @report.resolve!(current_account)
           log_action :resolve, @report
-
-          redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
-          return
-        end
-
-        if params[:create_and_unresolve]
+        elsif params[:create_and_unresolve]
           @report.unresolve!
           log_action :reopen, @report
         end
 
-        redirect_to admin_report_path(@report), notice: I18n.t('admin.report_notes.created_msg')
+        redirect_to after_create_redirect_path, notice: I18n.t('admin.report_notes.created_msg')
       else
-        @report_notes = (@report.notes.latest + @report.history + @report.target_account.targeted_account_warnings.latest.custom).sort_by(&:created_at)
-        @form         = Form::StatusBatch.new
+        @report_notes = @report.notes.includes(:account).order(id: :desc)
+        @action_logs  = @report.history.includes(:target)
+        @form         = Admin::StatusBatchAction.new
+        @statuses     = @report.statuses.with_includes
 
         render template: 'admin/reports/show'
       end
@@ -41,6 +38,14 @@ module Admin
 
     private
 
+    def after_create_redirect_path
+      if params[:create_and_resolve]
+        admin_reports_path
+      else
+        admin_report_path(@report)
+      end
+    end
+
     def resource_params
       params.require(:report_note).permit(
         :content,
diff --git a/app/controllers/admin/reported_statuses_controller.rb b/app/controllers/admin/reported_statuses_controller.rb
deleted file mode 100644
index 3ba9f5df2..000000000
--- a/app/controllers/admin/reported_statuses_controller.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
-  class ReportedStatusesController < BaseController
-    before_action :set_report
-
-    def create
-      authorize :status, :update?
-
-      @form         = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button))
-      flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
-
-      redirect_to admin_report_path(@report)
-    rescue ActionController::ParameterMissing
-      flash[:alert] = I18n.t('admin.statuses.no_status_selected')
-
-      redirect_to admin_report_path(@report)
-    end
-
-    private
-
-    def status_params
-      params.require(:status).permit(:sensitive)
-    end
-
-    def form_status_batch_params
-      params.require(:form_status_batch).permit(status_ids: [])
-    end
-
-    def action_from_button
-      if params[:nsfw_on]
-        'nsfw_on'
-      elsif params[:nsfw_off]
-        'nsfw_off'
-      elsif params[:delete]
-        'delete'
-      end
-    end
-
-    def set_report
-      @report = Report.find(params[:report_id])
-    end
-  end
-end
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index 7c831b3d4..00d200d7c 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -13,8 +13,10 @@ module Admin
       authorize @report, :show?
 
       @report_note  = @report.notes.new
-      @report_notes = (@report.notes.latest + @report.history + @report.target_account.targeted_account_warnings.latest.custom).sort_by(&:created_at)
-      @form         = Form::StatusBatch.new
+      @report_notes = @report.notes.includes(:account).order(id: :desc)
+      @action_logs  = @report.history.includes(:target)
+      @form         = Admin::StatusBatchAction.new
+      @statuses     = @report.statuses.with_includes
     end
 
     def assign_to_self
diff --git a/app/controllers/admin/resets_controller.rb b/app/controllers/admin/resets_controller.rb
index db8f61d64..7962b7a58 100644
--- a/app/controllers/admin/resets_controller.rb
+++ b/app/controllers/admin/resets_controller.rb
@@ -6,9 +6,9 @@ module Admin
 
     def create
       authorize @user, :reset_password?
-      @user.send_reset_password_instructions
+      @user.reset_password!
       log_action :reset_password, @user
-      redirect_to admin_accounts_path
+      redirect_to admin_account_path(@user.account_id)
     end
   end
 end
diff --git a/app/controllers/admin/sign_in_token_authentications_controller.rb b/app/controllers/admin/sign_in_token_authentications_controller.rb
new file mode 100644
index 000000000..e620ab292
--- /dev/null
+++ b/app/controllers/admin/sign_in_token_authentications_controller.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Admin
+  class SignInTokenAuthenticationsController < BaseController
+    before_action :set_target_user
+
+    def create
+      authorize @user, :enable_sign_in_token_auth?
+      @user.update(skip_sign_in_token: false)
+      log_action :enable_sign_in_token_auth, @user
+      redirect_to admin_account_path(@user.account_id)
+    end
+
+    def destroy
+      authorize @user, :disable_sign_in_token_auth?
+      @user.update(skip_sign_in_token: true)
+      log_action :disable_sign_in_token_auth, @user
+      redirect_to admin_account_path(@user.account_id)
+    end
+
+    private
+
+    def set_target_user
+      @user = User.find(params[:user_id])
+    end
+  end
+end
diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb
index ef279509d..8d039b281 100644
--- a/app/controllers/admin/statuses_controller.rb
+++ b/app/controllers/admin/statuses_controller.rb
@@ -2,71 +2,57 @@
 
 module Admin
   class StatusesController < BaseController
-    helper_method :current_params
-
     before_action :set_account
+    before_action :set_statuses
 
     PER_PAGE = 20
 
     def index
       authorize :status, :index?
 
-      @statuses = @account.statuses.where(visibility: [:public, :unlisted])
-
-      if params[:media]
-        @statuses.merge!(Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id))
-      end
-
-      @statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE)
-      @form     = Form::StatusBatch.new
-    end
-
-    def show
-      authorize :status, :index?
-
-      @statuses = @account.statuses.where(id: params[:id])
-      authorize @statuses.first, :show?
-
-      @form = Form::StatusBatch.new
+      @status_batch_action = Admin::StatusBatchAction.new
     end
 
-    def create
-      authorize :status, :update?
-
-      @form         = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button))
-      flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
-
-      redirect_to admin_account_statuses_path(@account.id, current_params)
+    def batch
+      @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
       flash[:alert] = I18n.t('admin.statuses.no_status_selected')
-
-      redirect_to admin_account_statuses_path(@account.id, current_params)
+    ensure
+      redirect_to after_create_redirect_path
     end
 
     private
 
-    def form_status_batch_params
-      params.require(:form_status_batch).permit(:action, status_ids: [])
+    def admin_status_batch_action_params
+      params.require(:admin_status_batch_action).permit(status_ids: [])
+    end
+
+    def after_create_redirect_path
+      if @status_batch_action.report_id.present?
+        admin_report_path(@status_batch_action.report_id)
+      else
+        admin_account_statuses_path(params[:account_id], current_params)
+      end
     end
 
     def set_account
       @account = Account.find(params[:account_id])
     end
 
-    def current_params
-      page = (params[:page] || 1).to_i
+    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
 
-      {
-        media: params[:media],
-        page: page > 1 && page,
-      }.select { |_, value| value.present? }
+    def filter_params
+      params.slice(*Admin::StatusFilter::KEYS).permit(*Admin::StatusFilter::KEYS)
     end
 
     def action_from_button
-      if params[:nsfw_on]
-        'nsfw_on'
-      elsif params[:nsfw_off]
-        'nsfw_off'
+      if params[:report]
+        'report'
+      elsif params[:remove_from_report]
+        'remove_from_report'
       elsif params[:delete]
         'delete'
       end
diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb
index eed4feea2..749e2f144 100644
--- a/app/controllers/admin/tags_controller.rb
+++ b/app/controllers/admin/tags_controller.rb
@@ -2,38 +2,12 @@
 
 module Admin
   class TagsController < BaseController
-    before_action :set_tag, except: [:index, :batch, :approve_all, :reject_all]
-    before_action :set_usage_by_domain, except: [:index, :batch, :approve_all, :reject_all]
-    before_action :set_counters, except: [:index, :batch, :approve_all, :reject_all]
-
-    def index
-      authorize :tag, :index?
-
-      @tags = filtered_tags.page(params[:page])
-      @form = Form::TagBatch.new
-    end
-
-    def batch
-      @form = Form::TagBatch.new(form_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')
-    ensure
-      redirect_to admin_tags_path(filter_params)
-    end
-
-    def approve_all
-      Form::TagBatch.new(current_account: current_account, tag_ids: Tag.pending_review.pluck(:id), action: 'approve').save
-      redirect_to admin_tags_path(filter_params)
-    end
-
-    def reject_all
-      Form::TagBatch.new(current_account: current_account, tag_ids: Tag.pending_review.pluck(:id), action: 'reject').save
-      redirect_to admin_tags_path(filter_params)
-    end
+    before_action :set_tag
 
     def show
       authorize @tag, :show?
+
+      @time_period = (6.days.ago.to_date...Time.now.utc.to_date)
     end
 
     def update
@@ -52,52 +26,8 @@ module Admin
       @tag = Tag.find(params[:id])
     end
 
-    def set_usage_by_domain
-      @usage_by_domain = @tag.statuses
-                             .with_public_visibility
-                             .excluding_silenced_accounts
-                             .where(Status.arel_table[:id].gteq(Mastodon::Snowflake.id_at(Time.now.utc.beginning_of_day)))
-                             .joins(:account)
-                             .group('accounts.domain')
-                             .reorder(statuses_count: :desc)
-                             .pluck(Arel.sql('accounts.domain, count(*) AS statuses_count'))
-    end
-
-    def set_counters
-      @accounts_today = @tag.history.first[:accounts]
-      @accounts_week  = Redis.current.pfcount(*current_week_days.map { |day| "activity:tags:#{@tag.id}:#{day}:accounts" })
-    end
-
-    def filtered_tags
-      TagFilter.new(filter_params).results
-    end
-
-    def filter_params
-      params.slice(:page, *TagFilter::KEYS).permit(:page, *TagFilter::KEYS)
-    end
-
     def tag_params
       params.require(:tag).permit(:name, :trendable, :usable, :listable)
     end
-
-    def current_week_days
-      now = Time.now.utc.beginning_of_day.to_date
-
-      (Date.commercial(now.cwyear, now.cweek)..now).map do |date|
-        date.to_time(:utc).beginning_of_day.to_i
-      end
-    end
-
-    def form_tag_batch_params
-      params.require(:form_tag_batch).permit(:action, tag_ids: [])
-    end
-
-    def action_from_button
-      if params[:approve]
-        'approve'
-      elsif params[:reject]
-        'reject'
-      end
-    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
new file mode 100644
index 000000000..2c26e03f3
--- /dev/null
+++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController
+  def index
+    authorize :preview_card_provider, :index?
+
+    @preview_card_providers = filtered_preview_card_providers.page(params[:page])
+    @form = Form::PreviewCardProviderBatch.new
+  end
+
+  def batch
+    @form = Form::PreviewCardProviderBatch.new(form_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')
+  ensure
+    redirect_to admin_trends_links_preview_card_providers_path(filter_params)
+  end
+
+  private
+
+  def filtered_preview_card_providers
+    PreviewCardProviderFilter.new(filter_params).results
+  end
+
+  def filter_params
+    params.slice(:page, *PreviewCardProviderFilter::KEYS).permit(:page, *PreviewCardProviderFilter::KEYS)
+  end
+
+  def form_preview_card_provider_batch_params
+    params.require(:form_preview_card_provider_batch).permit(:action, preview_card_provider_ids: [])
+  end
+
+  def action_from_button
+    if params[:approve]
+      'approve'
+    elsif params[:reject]
+      'reject'
+    end
+  end
+end
diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb
new file mode 100644
index 000000000..619b37deb
--- /dev/null
+++ b/app/controllers/admin/trends/links_controller.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+class Admin::Trends::LinksController < Admin::BaseController
+  def index
+    authorize :preview_card, :index?
+
+    @preview_cards = filtered_preview_cards.page(params[:page])
+    @form          = Form::PreviewCardBatch.new
+  end
+
+  def batch
+    @form = Form::PreviewCardBatch.new(form_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')
+  ensure
+    redirect_to admin_trends_links_path(filter_params)
+  end
+
+  private
+
+  def filtered_preview_cards
+    PreviewCardFilter.new(filter_params.with_defaults(trending: 'all')).results
+  end
+
+  def filter_params
+    params.slice(:page, *PreviewCardFilter::KEYS).permit(:page, *PreviewCardFilter::KEYS)
+  end
+
+  def form_preview_card_batch_params
+    params.require(:form_preview_card_batch).permit(:action, preview_card_ids: [])
+  end
+
+  def action_from_button
+    if params[:approve]
+      'approve'
+    elsif params[:approve_all]
+      'approve_all'
+    elsif params[:reject]
+      'reject'
+    elsif params[:reject_all]
+      'reject_all'
+    end
+  end
+end
diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb
new file mode 100644
index 000000000..91ff33d40
--- /dev/null
+++ b/app/controllers/admin/trends/tags_controller.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class Admin::Trends::TagsController < Admin::BaseController
+  def index
+    authorize :tag, :index?
+
+    @tags = filtered_tags.page(params[:page])
+    @form = Form::TagBatch.new
+  end
+
+  def batch
+    @form = Form::TagBatch.new(form_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')
+  ensure
+    redirect_to admin_trends_tags_path(filter_params)
+  end
+
+  private
+
+  def filtered_tags
+    TagFilter.new(filter_params).results
+  end
+
+  def filter_params
+    params.slice(:page, *TagFilter::KEYS).permit(:page, *TagFilter::KEYS)
+  end
+
+  def form_tag_batch_params
+    params.require(:form_tag_batch).permit(:action, tag_ids: [])
+  end
+
+  def action_from_button
+    if params[:approve]
+      'approve'
+    elsif params[:reject]
+      'reject'
+    end
+  end
+end
diff --git a/app/controllers/admin/two_factor_authentications_controller.rb b/app/controllers/admin/two_factor_authentications_controller.rb
index 0652c3a7a..f7fb7eb8f 100644
--- a/app/controllers/admin/two_factor_authentications_controller.rb
+++ b/app/controllers/admin/two_factor_authentications_controller.rb
@@ -9,7 +9,7 @@ module Admin
       @user.disable_two_factor!
       log_action :disable_2fa, @user
       UserMailer.two_factor_disabled(@user).deliver_later!
-      redirect_to admin_accounts_path
+      redirect_to admin_account_path(@user.account_id)
     end
 
     private