mirror of https://github.com/mastodon/mastodon
				
				
				
			Add ability to filter audit log in admin UI (#13381)
							parent
							
								
									69558d2fe5
								
							
						
					
					
						commit
						f65568f1d4
					
				@ -0,0 +1,81 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Admin::ActionLogFilter
 | 
			
		||||
  KEYS = %i(
 | 
			
		||||
    action_type
 | 
			
		||||
    account_id
 | 
			
		||||
    target_account_id
 | 
			
		||||
  ).freeze
 | 
			
		||||
 | 
			
		||||
  ACTION_TYPE_MAP = {
 | 
			
		||||
    assigned_to_self_report: { target_type: 'Report', action: 'assigned_to_self' }.freeze,
 | 
			
		||||
    change_email_user: { target_type: 'User', action: 'change_email' }.freeze,
 | 
			
		||||
    confirm_user: { target_type: 'User', action: 'confirm' }.freeze,
 | 
			
		||||
    create_account_warning: { target_type: 'AccountWarning', action: 'create' }.freeze,
 | 
			
		||||
    create_announcement: { target_type: 'Announcement', action: 'create' }.freeze,
 | 
			
		||||
    create_custom_emoji: { target_type: 'CustomEmoji', action: 'create' }.freeze,
 | 
			
		||||
    create_domain_allow: { target_type: 'DomainAllow', action: 'create' }.freeze,
 | 
			
		||||
    create_domain_block: { target_type: 'DomainBlock', action: 'create' }.freeze,
 | 
			
		||||
    create_email_domain_block: { target_type: 'EmailDomainBlock', action: 'create' }.freeze,
 | 
			
		||||
    demote_user: { target_type: 'User', action: 'demote' }.freeze,
 | 
			
		||||
    destroy_announcement: { target_type: 'Announcement', action: 'destroy' }.freeze,
 | 
			
		||||
    destroy_custom_emoji: { target_type: 'CustomEmoji', action: 'destroy' }.freeze,
 | 
			
		||||
    destroy_domain_allow: { target_type: 'DomainAllow', action: 'destroy' }.freeze,
 | 
			
		||||
    destroy_domain_block: { target_type: 'DomainBlock', action: 'destroy' }.freeze,
 | 
			
		||||
    destroy_email_domain_block: { target_type: 'EmailDomainBlock', action: 'destroy' }.freeze,
 | 
			
		||||
    destroy_status: { target_type: 'Status', action: 'destroy' }.freeze,
 | 
			
		||||
    disable_2fa_user: { target_type: 'User', action: 'disable' }.freeze,
 | 
			
		||||
    disable_custom_emoji: { target_type: 'CustomEmoji', action: 'disable' }.freeze,
 | 
			
		||||
    disable_user: { target_type: 'User', action: 'disable' }.freeze,
 | 
			
		||||
    enable_custom_emoji: { target_type: 'CustomEmoji', action: 'enable' }.freeze,
 | 
			
		||||
    enable_user: { target_type: 'User', action: 'enable' }.freeze,
 | 
			
		||||
    memorialize_account: { target_type: 'Account', action: 'memorialize' }.freeze,
 | 
			
		||||
    promote_user: { target_type: 'User', action: 'promote' }.freeze,
 | 
			
		||||
    remove_avatar_user: { target_type: 'User', action: 'remove_avatar' }.freeze,
 | 
			
		||||
    reopen_report: { target_type: 'Report', action: 'reopen' }.freeze,
 | 
			
		||||
    reset_password_user: { target_type: 'User', action: 'reset_password' }.freeze,
 | 
			
		||||
    resolve_report: { target_type: 'Report', action: 'resolve' }.freeze,
 | 
			
		||||
    silence_account: { target_type: 'Account', action: 'silence' }.freeze,
 | 
			
		||||
    suspend_account: { target_type: 'Account', action: 'suspend' }.freeze,
 | 
			
		||||
    unassigned_report: { target_type: 'Report', action: 'unassigned' }.freeze,
 | 
			
		||||
    unsilence_account: { target_type: 'Account', action: 'unsilence' }.freeze,
 | 
			
		||||
    unsuspend_account: { target_type: 'Account', action: 'unsuspend' }.freeze,
 | 
			
		||||
    update_announcement: { target_type: 'Announcement', action: 'update' }.freeze,
 | 
			
		||||
    update_custom_emoji: { target_type: 'CustomEmoji', action: 'update' }.freeze,
 | 
			
		||||
    update_status: { target_type: 'Status', action: 'update' }.freeze,
 | 
			
		||||
  }.freeze
 | 
			
		||||
 | 
			
		||||
  attr_reader :params
 | 
			
		||||
 | 
			
		||||
  def initialize(params)
 | 
			
		||||
    @params = params
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def results
 | 
			
		||||
    scope = Admin::ActionLog.includes(:target)
 | 
			
		||||
 | 
			
		||||
    params.each do |key, value|
 | 
			
		||||
      next if key.to_s == 'page'
 | 
			
		||||
 | 
			
		||||
      scope.merge!(scope_for(key.to_s, value.to_s.strip)) if value.present?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    scope
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def scope_for(key, value)
 | 
			
		||||
    case key
 | 
			
		||||
    when 'action_type'
 | 
			
		||||
      Admin::ActionLog.where(ACTION_TYPE_MAP[value.to_sym])
 | 
			
		||||
    when 'account_id'
 | 
			
		||||
      Admin::ActionLog.where(account_id: value)
 | 
			
		||||
    when 'target_account_id'
 | 
			
		||||
      account = Account.find(value)
 | 
			
		||||
      Admin::ActionLog.where(target: [account, account.user].compact)
 | 
			
		||||
    else
 | 
			
		||||
      raise "Unknown filter: #{key}"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,6 +1,28 @@
 | 
			
		||||
- content_for :page_title do
 | 
			
		||||
  = t('admin.action_logs.title')
 | 
			
		||||
 | 
			
		||||
= render @action_logs
 | 
			
		||||
- content_for :header_tags do
 | 
			
		||||
  = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
 | 
			
		||||
 | 
			
		||||
= form_tag admin_action_logs_url, method: 'GET', class: 'simple_form' do
 | 
			
		||||
  = hidden_field_tag :target_account_id, params[:target_account_id] if params[:target_account_id].present?
 | 
			
		||||
 | 
			
		||||
  .filters
 | 
			
		||||
    .filter-subset.filter-subset--with-select
 | 
			
		||||
      %strong= t('admin.action_logs.filter_by_user')
 | 
			
		||||
      .input.select.optional
 | 
			
		||||
        = select_tag :account_id, options_from_collection_for_select(Account.joins(:user).merge(User.staff), :id, :username, params[:account_id]), prompt: I18n.t('admin.accounts.moderation.all')
 | 
			
		||||
 | 
			
		||||
    .filter-subset.filter-subset--with-select
 | 
			
		||||
      %strong= t('admin.action_logs.filter_by_action')
 | 
			
		||||
      .input.select.optional
 | 
			
		||||
        = select_tag :action_type, options_for_select(Admin::ActionLogFilter::ACTION_TYPE_MAP.keys.map { |key| [I18n.t("admin.action_logs.action_types.#{key}"), key]}, params[:action_type]), prompt: I18n.t('admin.accounts.moderation.all')
 | 
			
		||||
 | 
			
		||||
- if @action_logs.empty?
 | 
			
		||||
  %div.muted-hint.center-text
 | 
			
		||||
    = t 'admin.action_logs.empty'
 | 
			
		||||
- else
 | 
			
		||||
  .announcements-list
 | 
			
		||||
    = render @action_logs
 | 
			
		||||
 | 
			
		||||
= paginate @action_logs
 | 
			
		||||
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue