From 3c033c4352f8b156887cd7157b4a89c23a545838 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 22 Dec 2018 20:02:09 +0100 Subject: Add moderation warnings (#9519) * Add moderation warnings Replace individual routes for disabling, silencing, and suspending a user, as well as the report update route, with a unified account action controller that allows you to select an action (none, disable, silence, suspend) as well as whether it should generate an e-mail notification with optional custom text. That notification, with the optional custom text, is saved as a warning. Additionally, there are warning presets you can configure to save time when performing the above. * Use Account#local_username_and_domain --- .../admin/account_actions_controller.rb | 36 ++++++ .../admin/account_moderation_notes_controller.rb | 1 + app/controllers/admin/accounts_controller.rb | 23 ++-- app/controllers/admin/reports_controller.rb | 79 ++++-------- app/controllers/admin/silences_controller.rb | 27 ----- app/controllers/admin/suspensions_controller.rb | 60 --------- .../admin/warning_presets_controller.rb | 58 +++++++++ app/helpers/admin/action_logs_helper.rb | 7 +- app/javascript/images/icon_flag.svg | 4 + app/javascript/images/mailer/icon_warning.png | Bin 0 -> 371 bytes app/javascript/styles/mailer.scss | 4 + app/javascript/styles/mastodon/admin.scss | 4 + app/mailers/user_mailer.rb | 12 ++ app/models/account.rb | 8 ++ app/models/account_warning.rb | 23 ++++ app/models/account_warning_preset.rb | 15 +++ app/models/admin/account_action.rb | 134 +++++++++++++++++++++ app/models/concerns/account_associations.rb | 2 + app/models/form/admin_suspension_confirmation.rb | 7 -- app/policies/account_policy.rb | 4 + app/policies/account_warning_preset_policy.rb | 19 +++ app/views/admin/account_actions/new.html.haml | 26 ++++ .../account_warnings/_account_warning.html.haml | 6 + app/views/admin/accounts/show.html.haml | 14 ++- app/views/admin/reports/show.html.haml | 17 +-- app/views/admin/suspensions/new.html.haml | 25 ---- app/views/admin/warning_presets/edit.html.haml | 11 ++ app/views/admin/warning_presets/index.html.haml | 30 +++++ app/views/user_mailer/warning.html.haml | 63 ++++++++++ app/views/user_mailer/warning.text.erb | 9 ++ app/views/user_mailer/welcome.text.erb | 2 +- 31 files changed, 533 insertions(+), 197 deletions(-) create mode 100644 app/controllers/admin/account_actions_controller.rb delete mode 100644 app/controllers/admin/silences_controller.rb delete mode 100644 app/controllers/admin/suspensions_controller.rb create mode 100644 app/controllers/admin/warning_presets_controller.rb create mode 100644 app/javascript/images/icon_flag.svg create mode 100644 app/javascript/images/mailer/icon_warning.png create mode 100644 app/models/account_warning.rb create mode 100644 app/models/account_warning_preset.rb create mode 100644 app/models/admin/account_action.rb delete mode 100644 app/models/form/admin_suspension_confirmation.rb create mode 100644 app/policies/account_warning_preset_policy.rb create mode 100644 app/views/admin/account_actions/new.html.haml create mode 100644 app/views/admin/account_warnings/_account_warning.html.haml delete mode 100644 app/views/admin/suspensions/new.html.haml create mode 100644 app/views/admin/warning_presets/edit.html.haml create mode 100644 app/views/admin/warning_presets/index.html.haml create mode 100644 app/views/user_mailer/warning.html.haml create mode 100644 app/views/user_mailer/warning.text.erb (limited to 'app') diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb new file mode 100644 index 000000000..e847495f1 --- /dev/null +++ b/app/controllers/admin/account_actions_controller.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Admin + class AccountActionsController < BaseController + before_action :set_account + + def new + @account_action = Admin::AccountAction.new(type: params[:type], report_id: params[:report_id], send_email_notification: true) + @warning_presets = AccountWarningPreset.all + end + + def create + account_action = Admin::AccountAction.new(resource_params) + account_action.target_account = @account + account_action.current_account = current_account + + account_action.save! + + if account_action.with_report? + redirect_to admin_report_path(account_action.report) + else + redirect_to admin_account_path(@account.id) + end + end + + private + + def set_account + @account = Account.find(params[:account_id]) + end + + def resource_params + params.require(:admin_account_action).permit(:type, :report_id, :warning_preset_id, :text, :send_email_notification) + end + end +end diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb index 7d5b9bf52..44f6e34f8 100644 --- a/app/controllers/admin/account_moderation_notes_controller.rb +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -14,6 +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 render template: 'admin/accounts/show' end diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index 771302db8..10abd1e6a 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -2,9 +2,9 @@ module Admin class AccountsController < BaseController - before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :remove_avatar, :remove_header, :enable, :disable, :memorialize] + before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :remove_avatar, :remove_header, :enable, :memorialize] before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload] - before_action :require_local_account!, only: [:enable, :disable, :memorialize] + before_action :require_local_account!, only: [:enable, :memorialize] def index authorize :account, :index? @@ -13,8 +13,10 @@ module Admin def show authorize @account, :show? + @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account) - @moderation_notes = @account.targeted_moderation_notes.latest + @moderation_notes = @account.targeted_moderation_notes.latest + @warnings = @account.targeted_account_warnings.latest.custom end def subscribe @@ -43,10 +45,17 @@ module Admin redirect_to admin_account_path(@account.id) end - def disable - authorize @account.user, :disable? - @account.user.disable! - log_action :disable, @account.user + def unsilence + authorize @account, :unsilence? + @account.unsilence! + log_action :unsilence, @account + redirect_to admin_account_path(@account.id) + end + + def unsuspend + authorize @account, :unsuspend? + @account.unsuspend! + log_action :unsuspend, @account redirect_to admin_account_path(@account.id) end diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index e97ddb9b6..f138376b2 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -13,75 +13,42 @@ module Admin authorize @report, :show? @report_note = @report.notes.new - @report_notes = (@report.notes.latest + @report.history).sort_by(&:created_at) + @report_notes = (@report.notes.latest + @report.history + @report.target_account.targeted_account_warnings.latest.custom).sort_by(&:created_at) @form = Form::StatusBatch.new end - def update + def assign_to_self authorize @report, :update? - process_report - - if @report.action_taken? - redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg') - else - redirect_to admin_report_path(@report) - end + @report.update!(assigned_account_id: current_account.id) + log_action :assigned_to_self, @report + redirect_to admin_report_path(@report) end - private - - def process_report - case params[:outcome].to_s - when 'assign_to_self' - @report.update!(assigned_account_id: current_account.id) - log_action :assigned_to_self, @report - when 'unassign' - @report.update!(assigned_account_id: nil) - log_action :unassigned, @report - when 'reopen' - @report.unresolve! - log_action :reopen, @report - when 'resolve' - @report.resolve!(current_account) - log_action :resolve, @report - when 'disable' - @report.resolve!(current_account) - @report.target_account.user.disable! - - log_action :resolve, @report - log_action :disable, @report.target_account.user - - resolve_all_target_account_reports - when 'silence' - @report.resolve!(current_account) - @report.target_account.update!(silenced: true) - - log_action :resolve, @report - log_action :silence, @report.target_account - - resolve_all_target_account_reports - else - raise ActiveRecord::RecordNotFound - end - - @report.reload + def unassign + authorize @report, :update? + @report.update!(assigned_account_id: nil) + log_action :unassigned, @report + redirect_to admin_report_path(@report) end - def resolve_all_target_account_reports - unresolved_reports_for_target_account.update_all(action_taken: true, action_taken_by_account_id: current_account.id) + def reopen + authorize @report, :update? + @report.unresolve! + log_action :reopen, @report + redirect_to admin_report_path(@report) end - def unresolved_reports_for_target_account - Report.where( - target_account: @report.target_account - ).unresolved + def resolve + authorize @report, :update? + @report.resolve!(current_account) + log_action :resolve, @report + redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg') end + private + def filtered_reports - ReportFilter.new(filter_params).results.order(id: :desc).includes( - :account, - :target_account - ) + ReportFilter.new(filter_params).results.order(id: :desc).includes(:account, :target_account) end def filter_params diff --git a/app/controllers/admin/silences_controller.rb b/app/controllers/admin/silences_controller.rb deleted file mode 100644 index 4c06a9c0c..000000000 --- a/app/controllers/admin/silences_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module Admin - class SilencesController < BaseController - before_action :set_account - - def create - authorize @account, :silence? - @account.update!(silenced: true) - log_action :silence, @account - redirect_to admin_accounts_path - end - - def destroy - authorize @account, :unsilence? - @account.update!(silenced: false) - log_action :unsilence, @account - redirect_to admin_accounts_path - end - - private - - def set_account - @account = Account.find(params[:account_id]) - end - end -end diff --git a/app/controllers/admin/suspensions_controller.rb b/app/controllers/admin/suspensions_controller.rb deleted file mode 100644 index f9bbf36fb..000000000 --- a/app/controllers/admin/suspensions_controller.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: true - -module Admin - class SuspensionsController < BaseController - before_action :set_account - - def new - @suspension = Form::AdminSuspensionConfirmation.new(report_id: params[:report_id]) - end - - def create - authorize @account, :suspend? - - @suspension = Form::AdminSuspensionConfirmation.new(suspension_params) - - if suspension_params[:acct] == @account.acct - resolve_report! if suspension_params[:report_id].present? - perform_suspend! - mark_reports_resolved! - redirect_to admin_accounts_path - else - flash.now[:alert] = I18n.t('admin.suspensions.bad_acct_msg') - render :new - end - end - - def destroy - authorize @account, :unsuspend? - @account.unsuspend! - log_action :unsuspend, @account - redirect_to admin_accounts_path - end - - private - - def set_account - @account = Account.find(params[:account_id]) - end - - def suspension_params - params.require(:form_admin_suspension_confirmation).permit(:acct, :report_id) - end - - def resolve_report! - report = Report.find(suspension_params[:report_id]) - report.resolve!(current_account) - log_action :resolve, report - end - - def perform_suspend! - @account.suspend! - Admin::SuspensionWorker.perform_async(@account.id) - log_action :suspend, @account - end - - def mark_reports_resolved! - Report.where(target_account: @account).unresolved.update_all(action_taken: true, action_taken_by_account_id: current_account.id) - end - end -end diff --git a/app/controllers/admin/warning_presets_controller.rb b/app/controllers/admin/warning_presets_controller.rb new file mode 100644 index 000000000..37be842c5 --- /dev/null +++ b/app/controllers/admin/warning_presets_controller.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Admin + class WarningPresetsController < BaseController + before_action :set_warning_preset, except: [:index, :create] + + def index + authorize :account_warning_preset, :index? + + @warning_presets = AccountWarningPreset.all + @warning_preset = AccountWarningPreset.new + end + + def create + authorize :account_warning_preset, :create? + + @warning_preset = AccountWarningPreset.new(warning_preset_params) + + if @warning_preset.save + redirect_to admin_warning_presets_path + else + @warning_presets = AccountWarningPreset.all + render :index + end + end + + def edit + authorize @warning_preset, :update? + end + + def update + authorize @warning_preset, :update? + + if @warning_preset.update(warning_preset_params) + redirect_to admin_warning_presets_path + else + render :edit + end + end + + def destroy + authorize @warning_preset, :destroy? + + @warning_preset.destroy! + redirect_to admin_warning_presets_path + end + + private + + def set_warning_preset + @warning_preset = AccountWarningPreset.find(params[:id]) + end + + def warning_preset_params + params.require(:account_warning_preset).permit(:text) + end + end +end diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index 68cf8c75d..359d60b60 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -23,6 +23,8 @@ module Admin::ActionLogsHelper link_to record.domain, "https://#{record.domain}" when 'Status' link_to record.account.acct, TagManager.instance.url_for(record) + when 'AccountWarning' + link_to record.target_account.acct, admin_account_path(record.target_account_id) end end @@ -34,6 +36,7 @@ module Admin::ActionLogsHelper link_to attributes['domain'], "https://#{attributes['domain']}" when 'Status' tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count')) + if tmp_status.account link_to tmp_status.account&.acct || "##{tmp_status.account_id}", admin_account_path(tmp_status.account_id) else @@ -81,6 +84,8 @@ module Admin::ActionLogsHelper 'envelope' when 'Status' 'pencil' + when 'AccountWarning' + 'warning' end end @@ -104,6 +109,6 @@ module Admin::ActionLogsHelper private def opposite_verbs?(log) - %w(DomainBlock EmailDomainBlock).include?(log.target_type) + %w(DomainBlock EmailDomainBlock AccountWarning).include?(log.target_type) end end diff --git a/app/javascript/images/icon_flag.svg b/app/javascript/images/icon_flag.svg new file mode 100644 index 000000000..3939c9d2b --- /dev/null +++ b/app/javascript/images/icon_flag.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/javascript/images/mailer/icon_warning.png b/app/javascript/images/mailer/icon_warning.png new file mode 100644 index 000000000..7baaac61c Binary files /dev/null and b/app/javascript/images/mailer/icon_warning.png differ diff --git a/app/javascript/styles/mailer.scss b/app/javascript/styles/mailer.scss index d83bd4d96..74d1df8ed 100644 --- a/app/javascript/styles/mailer.scss +++ b/app/javascript/styles/mailer.scss @@ -426,6 +426,10 @@ h5 { background: $success-green; } + &.alert-icon td { + background: $error-red; + } + img { max-width: 32px; width: 32px; diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index b6c771abf..e8f331932 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -542,6 +542,10 @@ a.name-tag, border-left-color: lighten($error-red, 12%); } + &.warning { + border-left-color: $gold-star; + } + &__bubble { padding: 16px; padding-left: 14px; diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index aa76b4dfe..8f3a4ab3a 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -78,4 +78,16 @@ class UserMailer < Devise::Mailer mail to: @resource.email, subject: I18n.t('user_mailer.backup_ready.subject') end end + + def warning(user, warning) + @resource = user + @warning = warning + @instance = Rails.configuration.x.local_domain + + I18n.with_locale(@resource.locale || I18n.default_locale) do + mail to: @resource.email, + subject: I18n.t("user_mailer.warning.subject.#{@warning.action}", acct: "@#{user.account.local_username_and_domain}"), + reply_to: Setting.site_contact_email + end + end end diff --git a/app/models/account.rb b/app/models/account.rb index 5a7a9c580..16ef6c187 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -155,6 +155,14 @@ class Account < ApplicationRecord ResolveAccountService.new.call(acct) end + def silence! + update!(silenced: true) + end + + def unsilence! + update!(silenced: false) + end + def suspend! transaction do user&.disable! if local? diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb new file mode 100644 index 000000000..157e6c04d --- /dev/null +++ b/app/models/account_warning.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: account_warnings +# +# id :bigint(8) not null, primary key +# account_id :bigint(8) +# target_account_id :bigint(8) +# action :integer default("none"), not null +# text :text default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# + +class AccountWarning < ApplicationRecord + enum action: %i(none disable silence suspend), _suffix: :action + + belongs_to :account, inverse_of: :account_warnings + belongs_to :target_account, class_name: 'Account', inverse_of: :targeted_account_warnings + + scope :latest, -> { order(created_at: :desc) } + scope :custom, -> { where.not(text: '') } +end diff --git a/app/models/account_warning_preset.rb b/app/models/account_warning_preset.rb new file mode 100644 index 000000000..ba8ceabb3 --- /dev/null +++ b/app/models/account_warning_preset.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: account_warning_presets +# +# id :bigint(8) not null, primary key +# text :text default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# + +class AccountWarningPreset < ApplicationRecord + validates :text, presence: true +end diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb new file mode 100644 index 000000000..84c3f880d --- /dev/null +++ b/app/models/admin/account_action.rb @@ -0,0 +1,134 @@ +# frozen_string_literal: true + +class Admin::AccountAction + include ActiveModel::Model + include AccountableConcern + include Authorization + + TYPES = %w( + none + disable + silence + suspend + ).freeze + + attr_accessor :target_account, + :current_account, + :type, + :text, + :report_id, + :warning_preset_id, + :send_email_notification + + attr_reader :warning + + def save! + ApplicationRecord.transaction do + process_action! + process_warning! + end + + queue_email! + process_reports! + end + + def report + @report ||= Report.find(report_id) if report_id.present? + end + + def with_report? + !report.nil? + end + + class << self + def types_for_account(account) + if account.local? + TYPES + else + TYPES - %w(none disable) + end + end + end + + private + + def process_action! + case type + when 'disable' + handle_disable! + when 'silence' + handle_silence! + when 'suspend' + handle_suspend! + end + end + + def process_warning! + return unless warnable? + + authorize(target_account, :warn?) + + @warning = AccountWarning.create!(target_account: target_account, + account: current_account, + action: type, + text: text_for_warning) + + # A log entry is only interesting if the warning contains + # custom text from someone. Otherwise it's just noise. + log_action(:create, warning) if warning.text.present? + end + + def process_reports! + return if report_id.blank? + + authorize(report, :update?) + + if type == 'none' + log_action(:resolve, report) + report.resolve!(current_account) + else + Report.where(target_account: target_account).unresolved.update_all(action_taken: true, action_taken_by_account_id: current_account.id) + end + end + + def handle_disable! + authorize(target_account.user, :disable?) + log_action(:disable, target_account.user) + target_account.user&.disable! + end + + def handle_silence! + authorize(target_account, :silence?) + log_action(:silence, target_account) + target_account.silence! + end + + def handle_suspend! + authorize(target_account, :suspend?) + log_action(:suspend, target_account) + target_account.suspend! + queue_suspension_worker! + end + + def text_for_warning + [warning_preset&.text, text].compact.join("\n\n") + end + + def queue_suspension_worker! + Admin::SuspensionWorker.perform_async(target_account.id) + end + + def queue_email! + return unless warnable? + + UserMailer.warning(target_account.user, warning).deliver_later! + end + + def warnable? + send_email_notification && target_account.local? + end + + def warning_preset + @warning_preset ||= AccountWarningPreset.find(warning_preset_id) if warning_preset_id.present? + end +end diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account_associations.rb index ae50860ed..a894b5eed 100644 --- a/app/models/concerns/account_associations.rb +++ b/app/models/concerns/account_associations.rb @@ -39,6 +39,8 @@ module AccountAssociations # Moderation notes has_many :account_moderation_notes, dependent: :destroy, inverse_of: :account has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account + has_many :account_warnings, dependent: :destroy, inverse_of: :account + has_many :targeted_account_warnings, class_name: 'AccountWarning', foreign_key: :target_account_id, dependent: :destroy, inverse_of: :target_account # Lists (that the account is on, not owned by the account) has_many :list_accounts, inverse_of: :account, dependent: :destroy diff --git a/app/models/form/admin_suspension_confirmation.rb b/app/models/form/admin_suspension_confirmation.rb deleted file mode 100644 index c34b5b30e..000000000 --- a/app/models/form/admin_suspension_confirmation.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class Form::AdminSuspensionConfirmation - include ActiveModel::Model - - attr_accessor :acct, :report_id -end diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb index 07bae68ef..9c145979d 100644 --- a/app/policies/account_policy.rb +++ b/app/policies/account_policy.rb @@ -9,6 +9,10 @@ class AccountPolicy < ApplicationPolicy staff? end + def warn? + staff? && !record.user&.staff? + end + def suspend? staff? && !record.user&.staff? end diff --git a/app/policies/account_warning_preset_policy.rb b/app/policies/account_warning_preset_policy.rb new file mode 100644 index 000000000..bccbd33ef --- /dev/null +++ b/app/policies/account_warning_preset_policy.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AccountWarningPresetPolicy < ApplicationPolicy + def index? + staff? + end + + def create? + staff? + end + + def update? + staff? + end + + def destroy? + staff? + end +end diff --git a/app/views/admin/account_actions/new.html.haml b/app/views/admin/account_actions/new.html.haml new file mode 100644 index 000000000..97286c8e5 --- /dev/null +++ b/app/views/admin/account_actions/new.html.haml @@ -0,0 +1,26 @@ +- content_for :page_title do + = t('admin.account_actions.title', acct: @account.acct) + += simple_form_for @account_action, url: admin_account_action_path(@account.id) do |f| + = f.input :report_id, as: :hidden + + .fields-group + = f.input :type, collection: Admin::AccountAction.types_for_account(@account), include_blank: false, wrapper: :with_block_label, label_method: ->(type) { I18n.t("simple_form.labels.admin_account_action.types.#{type}")}, hint: t('simple_form.hints.admin_account_action.type_html', acct: @account.acct) + + - if @account.local? + %hr.spacer/ + + .fields-group + = f.input :send_email_notification, as: :boolean, wrapper: :with_label + + %hr.spacer/ + + - unless @warning_presets.empty? + .fields-group + = f.input :warning_preset_id, collection: @warning_presets, label_method: :text, wrapper: :with_block_label + + .fields-group + = f.input :text, as: :text, wrapper: :with_block_label, hint: t('simple_form.hints.admin_account_action.text_html', path: admin_warning_presets_path) + + .actions + = f.button :button, t('admin.account_actions.action'), type: :submit diff --git a/app/views/admin/account_warnings/_account_warning.html.haml b/app/views/admin/account_warnings/_account_warning.html.haml new file mode 100644 index 000000000..8c9c9679c --- /dev/null +++ b/app/views/admin/account_warnings/_account_warning.html.haml @@ -0,0 +1,6 @@ +.speech-bubble.warning + .speech-bubble__bubble + = Formatter.instance.linkify(account_warning.text) + .speech-bubble__owner + = admin_account_link_to account_warning.account + %time.formatted{ datetime: account_warning.created_at.iso8601 }= l account_warning.created_at diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index e9f765107..226aef732 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -64,7 +64,7 @@ = table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post if can?(:enable, @account.user) - else = t('admin.accounts.enabled') - = table_link_to 'lock', t('admin.accounts.disable'), disable_admin_account_path(@account.id), method: :post if can?(:disable, @account.user) + = table_link_to 'lock', t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable') if can?(:disable, @account.user) %tr %th= t('admin.accounts.most_recent_ip') %td= @account.user_current_sign_in_ip @@ -119,18 +119,18 @@ %div{ style: 'float: left' } - if @account.silenced? - = link_to t('admin.accounts.undo_silenced'), admin_account_silence_path(@account.id), method: :delete, class: 'button' if can?(:unsilence, @account) + = link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account) - else - = link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button button--destructive' if can?(:silence, @account) + = link_to t('admin.accounts.silence'), new_admin_account_action_path(@account.id, type: 'silence'), class: 'button button--destructive' if can?(:silence, @account) - if @account.local? - unless @account.user_confirmed? = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user) - if @account.suspended? - = link_to t('admin.accounts.undo_suspension'), admin_account_suspension_path(@account.id), method: :delete, class: 'button' if can?(:unsuspend, @account) + = link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsuspend, @account) - else - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_suspension_path(@account.id), class: 'button button--destructive' if can?(:suspend, @account) + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@account.id, type: 'suspend'), class: 'button button--destructive' if can?(:suspend, @account) - if !@account.local? && @account.hub_url.present? %hr.spacer/ @@ -184,6 +184,10 @@ %hr.spacer/ += render @warnings + +%hr.spacer/ + = render @moderation_notes = simple_form_for @account_moderation_note, url: admin_account_moderation_notes_path do |f| diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index 3588d151d..863dada9e 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -8,13 +8,14 @@ - if @report.unresolved? %div{ style: 'float: right' } - if @report.target_account.local? - = link_to t('admin.accounts.disable'), admin_report_path(@report, outcome: 'disable'), method: :put, class: 'button button--destructive' - = link_to t('admin.accounts.silence'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button button--destructive' - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_suspension_path(@report.target_account_id, report_id: @report.id), class: 'button button--destructive' + = link_to t('admin.accounts.warn'), new_admin_account_action_path(@report.target_account_id, type: 'none', report_id: @report.id), class: 'button' + = link_to t('admin.accounts.disable'), new_admin_account_action_path(@report.target_account_id, type: 'disable', report_id: @report.id), class: 'button button--destructive' + = link_to t('admin.accounts.silence'), new_admin_account_action_path(@report.target_account_id, type: 'silence', report_id: @report.id), class: 'button button--destructive' + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@report.target_account_id, type: 'suspend', report_id: @report.id), class: 'button button--destructive' %div{ style: 'float: left' } - = link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button' + = link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(@report), method: :post, class: 'button' - else - = link_to t('admin.reports.mark_as_unresolved'), admin_report_path(@report, outcome: 'reopen'), method: :put, class: 'button' + = link_to t('admin.reports.mark_as_unresolved'), reopen_admin_report_path(@report), method: :post, class: 'button' %hr.spacer @@ -67,10 +68,10 @@ = admin_account_link_to @report.assigned_account %td - if @report.assigned_account != current_user.account - = table_link_to 'user', t('admin.reports.assign_to_self'), admin_report_path(@report, outcome: 'assign_to_self'), method: :put + = table_link_to 'user', t('admin.reports.assign_to_self'), assign_to_self_admin_report_path(@report), method: :post %td - if !@report.assigned_account.nil? - = table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put + = table_link_to 'trash', t('admin.reports.unassign'), unassign_admin_report_path(@report), method: :post %hr.spacer @@ -104,7 +105,7 @@ - @report_notes.each do |item| - if item.is_a?(Admin::ActionLog) = render partial: 'action_log', locals: { action_log: item } - - elsif item.is_a?(ReportNote) + - else = render item = simple_form_for @report_note, url: admin_report_notes_path do |f| diff --git a/app/views/admin/suspensions/new.html.haml b/app/views/admin/suspensions/new.html.haml deleted file mode 100644 index f03ecacc3..000000000 --- a/app/views/admin/suspensions/new.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -- content_for :page_title do - = t('admin.suspensions.title', acct: @account.acct) - -= simple_form_for @suspension, url: admin_account_suspension_path(@account.id), method: :post do |f| - %p.hint= t('admin.suspensions.warning_html') - - .fields-group - %ul - %li.negative-hint - = number_to_human @account.statuses_count, strip_insignificant_zeros: true - = t('accounts.posts', count: @account.statuses_count) - %li.negative-hint - = number_to_human @account.following_count, strip_insignificant_zeros: true - = t('accounts.following', count: @account.following_count) - %li.negative-hint - = number_to_human @account.followers_count, strip_insignificant_zeros: true - = t('accounts.followers', count: @account.followers_count) - - %p.hint= t('admin.suspensions.hint_html', value: content_tag(:code, @account.acct)) - - = f.input :acct - = f.input_field :report_id, as: :hidden - - .actions - = f.button :button, t('admin.suspensions.proceed'), type: :submit, class: 'negative' diff --git a/app/views/admin/warning_presets/edit.html.haml b/app/views/admin/warning_presets/edit.html.haml new file mode 100644 index 000000000..9522746cd --- /dev/null +++ b/app/views/admin/warning_presets/edit.html.haml @@ -0,0 +1,11 @@ +- content_for :page_title do + = t('admin.warning_presets.edit_preset') + += simple_form_for @warning_preset, url: admin_warning_preset_path(@warning_preset) do |f| + = render 'shared/error_messages', object: @warning_preset + + .fields-group + = f.input :text, wrapper: :with_block_label + + .actions + = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/admin/warning_presets/index.html.haml b/app/views/admin/warning_presets/index.html.haml new file mode 100644 index 000000000..45913ef73 --- /dev/null +++ b/app/views/admin/warning_presets/index.html.haml @@ -0,0 +1,30 @@ +- content_for :page_title do + = t('admin.warning_presets.title') + +- if can? :create, :account_warning_preset + = simple_form_for @warning_preset, url: admin_warning_presets_path do |f| + = render 'shared/error_messages', object: @warning_preset + + .fields-group + = f.input :text, wrapper: :with_block_label + + .actions + = f.button :button, t('admin.warning_presets.add_new'), type: :submit + + %hr.spacer/ + +- unless @warning_presets.empty? + .table-wrapper + %table.table + %thead + %tr + %th= t('simple_form.labels.account_warning_preset.text') + %th + %tbody + - @warning_presets.each do |preset| + %tr + %td + = Formatter.instance.linkify(preset.text) + %td + = table_link_to 'pencil', t('admin.warning_presets.edit'), edit_admin_warning_preset_path(preset) + = table_link_to 'trash', t('admin.warning_presets.delete'), admin_warning_preset_path(preset), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } diff --git a/app/views/user_mailer/warning.html.haml b/app/views/user_mailer/warning.html.haml new file mode 100644 index 000000000..c5e1f5a28 --- /dev/null +++ b/app/views/user_mailer/warning.html.haml @@ -0,0 +1,63 @@ +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.hero + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center.padded + %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td + = image_tag full_pack_url('icon_warning.png'), alt: '' + + %h1= t "user_mailer.warning.title.#{@warning.action}" + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.content-start + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center + - unless @warning.none_action? + %p= t "user_mailer.warning.explanation.#{@warning.action}" + + - unless @warning.text.blank? + = Formatter.instance.linkify(@warning.text) + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.button-cell + %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.button-primary + = link_to about_more_url do + %span= t 'user_mailer.warning.review_server_policies' diff --git a/app/views/user_mailer/warning.text.erb b/app/views/user_mailer/warning.text.erb new file mode 100644 index 000000000..b4f2402cb --- /dev/null +++ b/app/views/user_mailer/warning.text.erb @@ -0,0 +1,9 @@ +<%= t "user_mailer.warning.title.#{@warning.action}" %> + +=== + +<% unless @warning.none_action? %> +<%= t "user_mailer.warning.explanation.#{@warning.action}" %> + +<% end %> +<%= @warning.text %> diff --git a/app/views/user_mailer/welcome.text.erb b/app/views/user_mailer/welcome.text.erb index 5bd0cab2a..845458c32 100644 --- a/app/views/user_mailer/welcome.text.erb +++ b/app/views/user_mailer/welcome.text.erb @@ -2,7 +2,7 @@ === -<%= t 'user_mailer.welcome.full_handle' %> (<%= "@#{@resource.account.username}@#{@instance}" %>) +<%= t 'user_mailer.welcome.full_handle' %> (<%= "@#{@resource.account.local_username_and_domain}" %>) <%= t 'user_mailer.welcome.full_handle_hint', instance: @instance %> --- -- cgit