From e84fecb7e97851ed56f4d954e2d68128bb87da37 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 24 Nov 2017 02:05:53 +0100 Subject: Add logging of admin actions (#5757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add logging of admin actions * Update brakeman whitelist * Log creates, updates and destroys with history of changes * i18n: Update Polish translation (#5782) Signed-off-by: Marcin Mikołajczak * Split admin navigation into moderation and administration * Redesign audit log page * 🇵🇱 (#5795) * Add color coding to audit log * Change dismiss->resolve, log all outcomes of report as resolve * Update terminology (e-mail blacklist) (#5796) * Update terminology (e-mail blacklist) imho looks better * Update en.yml * Fix code style issues * i18n-tasks normalize --- app/helpers/admin/action_logs_helper.rb | 103 ++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 app/helpers/admin/action_logs_helper.rb (limited to 'app/helpers/admin') diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb new file mode 100644 index 000000000..e85243e57 --- /dev/null +++ b/app/helpers/admin/action_logs_helper.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +module Admin::ActionLogsHelper + def log_target(log) + if log.target + linkable_log_target(log.target) + else + log_target_from_history(log.target_type, log.recorded_changes) + end + end + + def linkable_log_target(record) + case record.class.name + when 'Account' + link_to record.acct, admin_account_path(record.id) + when 'User' + link_to record.account.acct, admin_account_path(record.account_id) + when 'CustomEmoji' + record.shortcode + when 'Report' + link_to "##{record.id}", admin_report_path(record) + when 'DomainBlock', 'EmailDomainBlock' + link_to record.domain, "https://#{record.domain}" + when 'Status' + link_to record.account.acct, TagManager.instance.url_for(record) + end + end + + def log_target_from_history(type, attributes) + case type + when 'CustomEmoji' + attributes['shortcode'] + when 'DomainBlock', 'EmailDomainBlock' + link_to attributes['domain'], "https://#{attributes['domain']}" + when 'Status' + tmp_status = Status.new(attributes) + link_to tmp_status.account.acct, TagManager.instance.url_for(tmp_status) + end + end + + def relevant_log_changes(log) + if log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action) + log.recorded_changes.slice('domain') + elsif log.target_type == 'CustomEmoji' && log.action == :update + log.recorded_changes.slice('domain', 'visible_in_picker') + elsif log.target_type == 'User' && [:promote, :demote].include?(log.action) + log.recorded_changes.slice('moderator', 'admin') + elsif log.target_type == 'DomainBlock' + log.recorded_changes.slice('severity', 'reject_media') + elsif log.target_type == 'Status' && log.action == :update + log.recorded_changes.slice('sensitive') + end + end + + def log_extra_attributes(hash) + safe_join(hash.to_a.map { |key, value| safe_join([content_tag(:span, key, class: 'diff-key'), '=', log_change(value)]) }, ' ') + end + + def log_change(val) + return content_tag(:span, val, class: 'diff-neutral') unless val.is_a?(Array) + safe_join([content_tag(:span, val.first, class: 'diff-old'), content_tag(:span, val.last, class: 'diff-new')], '→') + end + + def icon_for_log(log) + case log.target_type + when 'Account', 'User' + 'user' + when 'CustomEmoji' + 'file' + when 'Report' + 'flag' + when 'DomainBlock' + 'lock' + when 'EmailDomainBlock' + 'envelope' + when 'Status' + 'pencil' + end + end + + def class_for_log_icon(log) + case log.action + when :enable, :unsuspend, :unsilence, :confirm, :promote, :resolve + 'positive' + when :create + opposite_verbs?(log) ? 'negative' : 'positive' + when :update, :reset_password, :disable_2fa, :memorialize + 'neutral' + when :demote, :silence, :disable, :suspend + 'negative' + when :destroy + opposite_verbs?(log) ? 'positive' : 'negative' + else + '' + end + end + + private + + def opposite_verbs?(log) + %w(DomainBlock EmailDomainBlock).include?(log.target_type) + end +end -- cgit From 74320971e2cc9f605dbcc23c52ac36e18b80716f Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Sat, 2 Dec 2017 00:40:02 +0900 Subject: Add invite filter (#5862) --- app/controllers/admin/invites_controller.rb | 10 ++++++++- app/helpers/admin/filter_helper.rb | 3 ++- app/models/invite.rb | 3 +++ app/models/invite_filter.rb | 32 +++++++++++++++++++++++++++++ app/views/admin/invites/index.html.haml | 8 ++++++++ config/locales/en.yml | 5 +++++ 6 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 app/models/invite_filter.rb (limited to 'app/helpers/admin') diff --git a/app/controllers/admin/invites_controller.rb b/app/controllers/admin/invites_controller.rb index 607588d90..faccaa7c8 100644 --- a/app/controllers/admin/invites_controller.rb +++ b/app/controllers/admin/invites_controller.rb @@ -5,7 +5,7 @@ module Admin def index authorize :invite, :index? - @invites = Invite.includes(user: :account).page(params[:page]) + @invites = filtered_invites.includes(user: :account).page(params[:page]) @invite = Invite.new end @@ -35,5 +35,13 @@ module Admin def resource_params params.require(:invite).permit(:max_uses, :expires_in) end + + def filtered_invites + InviteFilter.new(filter_params).results + end + + def filter_params + params.permit(:available, :expired) + end end end diff --git a/app/helpers/admin/filter_helper.rb b/app/helpers/admin/filter_helper.rb index e0fae9d9a..73250cbf5 100644 --- a/app/helpers/admin/filter_helper.rb +++ b/app/helpers/admin/filter_helper.rb @@ -3,8 +3,9 @@ module Admin::FilterHelper ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip).freeze REPORT_FILTERS = %i(resolved account_id target_account_id).freeze + INVITE_FILTER = %i(available expired).freeze - FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER def filter_link_to(text, link_to_params, link_class_params = link_to_params) new_url = filtered_url_for(link_to_params) diff --git a/app/models/invite.rb b/app/models/invite.rb index 7626f4cfa..6907c1f1d 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -17,6 +17,9 @@ class Invite < ApplicationRecord belongs_to :user, required: true has_many :users, inverse_of: :invite + scope :available, -> { where(expires_at: nil).or(where('expires_at >= ?', Time.now.utc)) } + scope :expired, -> { where.not(expires_at: nil).where('expires_at < ?', Time.now.utc) } + before_validation :set_code attr_reader :expires_in diff --git a/app/models/invite_filter.rb b/app/models/invite_filter.rb new file mode 100644 index 000000000..7d89bad4a --- /dev/null +++ b/app/models/invite_filter.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class InviteFilter + attr_reader :params + + def initialize(params) + @params = params + end + + def results + scope = Invite.order(created_at: :desc) + + params.each do |key, value| + scope.merge!(scope_for(key, value)) if value.present? + end + + scope + end + + private + + def scope_for(key, _value) + case key.to_s + when 'available' + Invite.available + when 'expired' + Invite.expired + else + raise "Unknown filter: #{key}" + end + end +end diff --git a/app/views/admin/invites/index.html.haml b/app/views/admin/invites/index.html.haml index 52a748fe0..944a60471 100644 --- a/app/views/admin/invites/index.html.haml +++ b/app/views/admin/invites/index.html.haml @@ -1,6 +1,14 @@ - content_for :page_title do = t('admin.invites.title') +.filters + .filter-subset + %strong= t('admin.invites.filter.title') + %ul + %li= filter_link_to t('admin.invites.filter.all'), available: nil, expired: nil + %li= filter_link_to t('admin.invites.filter.available'), available: 1, expired: nil + %li= filter_link_to t('admin.invites.filter.expired'), available: nil, expired: 1 + - if policy(:invite).create? %p= t('invites.prompt') diff --git a/config/locales/en.yml b/config/locales/en.yml index 2719a4f8c..5b9d43b9f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -232,6 +232,11 @@ en: search: Search title: Known instances invites: + filter: + all: All + available: Available + expired: Expired + title: Filter title: Invites reports: action_taken_by: Action taken by -- cgit