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
+ @report.update!(assigned_account_id: current_account.id)
+ log_action :assigned_to_self, @report
+ redirect_to admin_report_path(@report)
+ end
- if @report.action_taken?
- redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
- else
- redirect_to admin_report_path(@report)
- end
+ def unassign
+ authorize @report, :update?
+ @report.update!(assigned_account_id: nil)
+ log_action :unassigned, @report
+ redirect_to admin_report_path(@report)
+ end
+
+ def reopen
+ authorize @report, :update?
+ @report.unresolve!
+ log_action :reopen, @report
+ redirect_to admin_report_path(@report)
+ end
+
+ 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 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
- 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)
- end
-
- def unresolved_reports_for_target_account
- Report.where(
- target_account: @report.target_account
- ).unresolved
- end
-
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 %>
---
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 2fa075273..0652089d4 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -455,11 +455,6 @@ ar:
last_delivery: آخر إيداع
title: WebSub
topic: الموضوع
- suspensions:
- bad_acct_msg: قيمة التأكيد غير متطابقة. متأكد مِن أنك بصدد تعليق الحساب الصحيح؟
- hint_html: 'لتأكيد إجراء تعليق الحساب، يُرجى إدخال %{value} في الحقل التالي:'
- proceed: مواصلة
- title: تعليق الحساب %{acct}
tags:
accounts: الحسابات
hidden: المخفية
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index e6c51b10e..c18c398eb 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -121,8 +121,6 @@ ast:
failed_to_execute: Fallu al executar
subscriptions:
title: WebSub
- suspensions:
- warning_html: 'El suspender esta cuenta va desaniciar de mou irreversible los sos datos qu''inclúin:'
title: Alministración
admin_mailer:
new_report:
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 1575b32ea..b7e3cb7f6 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -439,12 +439,6 @@ ca:
last_delivery: Últim lliurament
title: WebSub
topic: Tema
- suspensions:
- bad_acct_msg: El valor de confirmació no s'ha trobat. Estàs suspenen el compte correcte?
- hint_html: 'Per confirmar la suspensió del compte, introdueix %{value} al camp següent:'
- proceed: Procedeix
- title: Suspèn %{acct}
- warning_html: 'Suspenen aquest compte esborrarà irreversiblement les dades del compte, incloent:'
tags:
accounts: Comptes
hidden: Amagat
diff --git a/config/locales/co.yml b/config/locales/co.yml
index c15f241c6..3df78f007 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -439,12 +439,6 @@ co:
last_delivery: Ultima arricata
title: WebSub
topic: Sughjettu
- suspensions:
- bad_acct_msg: U valore di cunfirmazione ùn era micca curretta. Site sicuru·a di suspende u bonu contu?
- hint_html: 'Per cunfirmà a suspensione di u contu, entrate %{value} quì sottu:'
- proceed: Cuntinuà
- title: Suspende %{acct}
- warning_html: 'A suspensione di u contu sguasserà di manera irreversibile i so dati, cum''è:'
tags:
accounts: Conti
hidden: Piattatu
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index d25ca6c2c..0042d5641 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -444,12 +444,6 @@ cs:
last_delivery: Poslední doručení
title: WebSub
topic: Téma
- suspensions:
- bad_acct_msg: Hodnota pro potvrzení neodpovídá. Suspendujete správný účet?
- hint_html: 'Pro potvrzení suspenzace účtu prosím zadejte do pole níže %{value}:'
- proceed: Pokračovat
- title: Suspendovat účet %{acct}
- warning_html: 'Suspenzace tohoto účtu nenávratně smaže z tohoto účtu data, včetně:'
tags:
accounts: Účty
hidden: Skryté
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index 24ae6fa10..2467d3e78 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -423,12 +423,6 @@ cy:
last_delivery: Danfoniad diwethaf
title: WebSub
topic: Pwnc
- suspensions:
- bad_acct_msg: Nid yw'r gwerthoedd cadarnhau yn cyfateb. Ydych chi'n atal y cyfrif cywir?
- hint_html: 'I gadarnhau atal y cyfrif, mewnbynwch %{value} yn y maes isod:'
- proceed: Parhau
- title: Atal %{acct}
- warning_html: 'Mi fydd atal y cyfrif hwn yn dileu data am byth o''r cyfrif hwn, gan gynnwys:'
title: Gweinyddiaeth
admin_mailer:
new_report:
diff --git a/config/locales/da.yml b/config/locales/da.yml
index c6bdc753a..202f6bfb3 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -427,12 +427,6 @@ da:
last_delivery: Sidste levering
title: Websub
topic: Emne
- suspensions:
- bad_acct_msg: Bekræftelsværdien stemte ikke overens. Er du ved at udelukke den rigtige konto?
- hint_html: 'For at bekræfte udelukkelsen af kontoen, indtast venligst %{value} i nedenstående felt:'
- proceed: Fortsæt
- title: Udeluk %{acct}
- warning_html: 'Udelukkelse af denne konto vil uigenkaldeligt slette al data fra denne konto, hvilket indebærer:'
title: Administration
admin_mailer:
new_report:
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 945d5a0ff..647897171 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -439,12 +439,6 @@ de:
last_delivery: Letzte Zustellung
title: WebSub
topic: Thema
- suspensions:
- bad_acct_msg: Der Bestätigungswert stimmt nicht überein. Sperrst du das richtige Benutzerkonto?
- hint_html: 'Um die Sperrung des Benutzerkontos zu genehmigen tippe %{value} in das Feld unten ein:'
- proceed: Fortfahren
- title: "%{acct} sperren"
- warning_html: 'Die Sperrung des Benutzerkontos wird unwiederrufliche Schäden hervorrufen und alle Daten löschen, die folgendes beinhalten:'
tags:
accounts: Konten
hidden: Versteckt
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 66393f213..e03a116d0 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -439,12 +439,6 @@ el:
last_delivery: Τελευταία παράδοση
title: WebSub
topic: Θέμα
- suspensions:
- bad_acct_msg: Η τιμή επιβεβαίωσης δεν ταιριάζει. Σίγουρα αναστέλλεις το σωστό λογαριασμό;
- hint_html: 'Για να επιβεβαιώσεις την αναστολή του λογαριασμού, γράψε %{value} στο ακόλουθο πεδίο:'
- proceed: Συνέχεια
- title: Αναστολή %{acct}
- warning_html: 'Αναστέλλοντας αυτό το λογαριασμό θα διαγραφούν αμετάκλητα δεδομένα του, μεταξύ των οποίων:'
tags:
accounts: Λογαριασμοί
hidden: Κρυμμένες
diff --git a/config/locales/en.yml b/config/locales/en.yml
index bd0b0c3d5..bea182f0b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -70,6 +70,9 @@ en:
moderator: Mod
unfollow: Unfollow
admin:
+ account_actions:
+ action: Perform action
+ title: Perform moderation action on %{acct}
account_moderation_notes:
create: Leave note
created_msg: Moderation note successfully created!
@@ -173,6 +176,7 @@ en:
assigned_to_self_report: "%{name} assigned report %{target} to themselves"
change_email_user: "%{name} changed the e-mail address of user %{target}"
confirm_user: "%{name} confirmed e-mail address of user %{target}"
+ create_account_warning: "%{name} sent a warning to %{target}"
create_custom_emoji: "%{name} uploaded new emoji %{target}"
create_domain_block: "%{name} blocked domain %{target}"
create_email_domain_block: "%{name} blacklisted e-mail domain %{target}"
@@ -441,12 +445,6 @@ en:
last_delivery: Last delivery
title: WebSub
topic: Topic
- suspensions:
- bad_acct_msg: The confirmation value didn't match up. Are you suspending the right account?
- hint_html: 'To confirm the suspension of the account, please enter %{value} into the field below:'
- proceed: Proceed
- title: Suspend %{acct}
- warning_html: 'Suspending this account will irreversibly delete data from this account, which includes:'
tags:
accounts: Accounts
hidden: Hidden
@@ -456,6 +454,12 @@ en:
unhide: Show in directory
visible: Visible
title: Administration
+ warning_presets:
+ add_new: Add new
+ delete: Delete
+ edit: Edit
+ edit_preset: Edit warning preset
+ title: Manage warning presets
admin_mailer:
new_report:
body: "%{reporter} has reported %{target}"
@@ -922,6 +926,22 @@ en:
explanation: You requested a full backup of your Mastodon account. It's now ready for download!
subject: Your archive is ready for download
title: Archive takeout
+ warning:
+ explanation:
+ disable: While your account is frozen, your account data remains intact, but you cannot perform any actions until it is unlocked.
+ silence: While your account is limited, only people who are already following you will see your toots on this server, and you may be excluded from various public listings. However, others may still manually follow you.
+ suspend: Your account has been suspended, and all of your toots and your uploaded media files have been irreversibly removed from this server, and servers where you had followers.
+ review_server_policies: Review server policies
+ subject:
+ disable: Your account %{acct} has been frozen
+ none: Warning for %{acct}
+ silence: Your account %{acct} has been limited
+ suspend: Your account %{acct} has been suspended
+ title:
+ disable: Account frozen
+ none: Warning
+ silence: Account limited
+ suspend: Account suspended
welcome:
edit_profile_action: Setup profile
edit_profile_step: You can customize your profile by uploading an avatar, header, changing your display name and more. If you’d like to review new followers before they’re allowed to follow you, you can lock your account.
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index f944b2a19..6a62f7021 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -427,11 +427,6 @@ eo:
last_delivery: Lasta livero
title: WebSub
topic: Temo
- suspensions:
- hint_html: 'Por konformi la haltigo de la konto, bonvolu enigi %{value} en la kampo sube:'
- proceed: Daŭrigita
- title: Haltigi %{acct}
- warning_html: 'Haltigi ĉi tiu konton forigos senrevene datumojn de ĉi tiu konto, inklusive de:'
title: Administrado
admin_mailer:
new_report:
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 4cd1e2a38..8927c3b38 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -433,12 +433,6 @@ es:
last_delivery: Última entrega
title: WebSub
topic: Tópico
- suspensions:
- bad_acct_msg: El valor de confirmación no cuadra. ¿Estás suspendiendo la cuenta correcta?
- hint_html: 'Para confirmar las suspensión de la cuenta, por favor introduce %{value} en el campo de abajo:'
- proceed: Proceder
- title: Suspender %{acct}
- warning_html: 'Suspender esta cuenta borrará irreversiblemente los datos de stra cuenta que incluyen:'
title: Administración
admin_mailer:
new_report:
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index c96438bc3..eb148c6a2 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -435,12 +435,6 @@ eu:
last_delivery: Azken bidalketa
title: WebSub
topic: Mintzagaia
- suspensions:
- bad_acct_msg: Berrespen balioa ez dator bat. Dagokion kontua kanporatzen ari zara?
- hint_html: 'Kontuaren kanporatzea berresteko, sartu %{value} beheko eremuan:'
- proceed: Jarraitu
- title: Kanporatu %{acct}
- warning_html: 'Kontu hau kanporatzeak behin betiko ezabatuko ditu kontu honetako datuak, hauek barne:'
tags:
accounts: Kontuak
hidden: Ezkutatuta
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 7802ca98d..a87949183 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -433,12 +433,6 @@ fa:
last_delivery: آخرین ارسال
title: WebSub
topic: موضوع
- suspensions:
- bad_acct_msg: محتوایی که برای تأیید وارد کردید منطبق نبود. آیا دارید حساب درستی را معلق میکنید؟
- hint_html: 'برای تأیید معلقکردن حساب، لطفاً در کادر زیر %{value} را وارد کنید:'
- proceed: ادامه
- title: معلقکردن %{acct}
- warning_html: 'معلقکردن این حساب برای همیشه دادههایش را پاک میکند. دادههایی شامل:'
title: مدیریت سرور
admin_mailer:
new_report:
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 3d33cd40c..167c942ee 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -439,12 +439,6 @@ fr:
last_delivery: Dernière livraison
title: WebSub
topic: Sujet
- suspensions:
- bad_acct_msg: La valeur de confirmation n'a pas correspondu. Êtes-vous certain de suspendre le bon compte ?
- hint_html: 'Pour confirmer la suspension du compte, veuillez entrer %{value} dans le champ ci-dessous :'
- proceed: Confirmer
- title: Suspension de %{acct}
- warning_html: 'Suspendre ce compte effacera irréversiblement les données de ce compte, ce qui inclut :'
tags:
accounts: Comptes
hidden: Masqué
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index de1557fb9..b6830fb72 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -439,12 +439,6 @@ gl:
last_delivery: Última entrega
title: WebSub
topic: Asunto
- suspensions:
- bad_acct_msg: O valor de confirmación non é coincidente. Está a suspender a conta correcta?
- hint_html: 'Para confirmar a suspensión da conta introduza %{value} no campo inferior:'
- proceed: Proceder
- title: Suspender %{acct}
- warning_html: 'Ao suspender esta conta eliminará de xeito irreversible os datos de esta conta, que inclúe:'
tags:
accounts: Contas
hidden: Ocultas
diff --git a/config/locales/it.yml b/config/locales/it.yml
index dc62b1bea..e9bf78cdf 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -429,12 +429,6 @@ it:
confirmed: Confermato
expires_in: Scade in
topic: Argomento
- suspensions:
- bad_acct_msg: Il valore di conferma non corrisponde. Stai sospendendo l'account giusto?
- hint_html: 'Per confermare la sospensione dell''account, inserisci %{value} nel campo qui sotto:'
- proceed: Continua
- title: Sospendi %{acct}
- warning_html: 'La sospensione dell''account comporta la cancellazione irreversibile dei suoi dati, che comprendono:'
title: Amministrazione
application_mailer:
notification_preferences: Cambia preferenze email
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 038131a61..292acf52f 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -441,12 +441,6 @@ ja:
last_delivery: 最終配送
title: WebSub
topic: トピック
- suspensions:
- bad_acct_msg: 値が一致しませんでした。停止しようとしているアカウントに間違いはありませんか?
- hint_html: 'アカウントの停止を確認するには、以下のフィールドに %{value} と入力してください:'
- proceed: 完全に活動停止させる
- title: "%{acct} を停止"
- warning_html: 'このアカウントを停止すると、このアカウントから次のようなデータが不可逆的に削除されます:'
tags:
accounts: アカウント
hidden: 非表示
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 40dab2d79..6bbc71e0b 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -441,12 +441,6 @@ ko:
last_delivery: 최종 발송
title: WebSub
topic: 토픽
- suspensions:
- bad_acct_msg: 확인값이 일치하지 않습니다. 정지하려는 계정이 맞습니까?
- hint_html: '이 계정을 정지하려면 %{value}를 아래 입력칸에 입력하세요:'
- proceed: 완전히 정지시키기
- title: "%{acct} 정지하기"
- warning_html: '이 계정을 정지하면 계정의 데이터를 모두 삭제하며 되돌릴 수 없습니다. 이것은 다음을 포함합니다:'
tags:
accounts: 계정들
hidden: 숨겨짐
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index d0578bc74..700217830 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -439,12 +439,6 @@ nl:
last_delivery: Laatste bezorging
title: WebSub
topic: Account
- suspensions:
- bad_acct_msg: De bevestigingswaarde kwam niet overeen. Schort je wel het juiste account op?
- hint_html: Vul in het veld hieronder %{value} in, om het opschorten van dit account te bevestigen.
- proceed: Ga verder
- title: "%{acct} opschorten"
- warning_html: 'Door het opschorten van dit account worden gegevens van dit account permanent verwijderd, waaronder:'
tags:
accounts: Accounts
hidden: Verborgen
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 0468fac86..e647e400c 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -439,12 +439,6 @@ oc:
last_delivery: Darrièra distribucion
title: WebSub
topic: Subjècte
- suspensions:
- bad_acct_msg: La valor de confirmacion a pas coïncidit. Sètz a suspendre lo bon compte ?
- hint_html: 'Per confirmar la suspension del compte, picatz %{value} al camp çai-jos :'
- proceed: Tractat
- title: Suspension de %{acct}
- warning_html: 'Suspendre aqueste compte suprimirà irreversiblament las donadas del compte, aquò compren :'
tags:
accounts: Comptes
hidden: Amagat
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 79ba6f9fb..7fd5df038 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -445,12 +445,6 @@ pl:
last_delivery: Ostatnio doręczono
title: WebSub
topic: Temat
- suspensions:
- bad_acct_msg: Zawartość potwierdzenia nie zgadza się. Czy próbujesz zawiesić właściwe konto?
- hint_html: 'Aby potwierdzić zawieszenie konta, wprowadź %{value} w poniższe pole:'
- proceed: Przejdź
- title: Zawieś %{acct}
- warning_html: 'Zawieszenie konta będzie skutkowało nieodwracalnym usunięciem danych z tego konta, wliczając:'
tags:
accounts: Konta
hidden: Ukryte
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 27f3b820c..e9625628b 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -439,12 +439,6 @@ pt-BR:
last_delivery: Última entrega
title: WebSub
topic: Tópico
- suspensions:
- bad_acct_msg: Os valores de confirmação não correspondem. Você está suspendendo a conta certa?
- hint_html: 'Para confirmar a suspensão da conta, por favor digite %{value} no campo abaixo:'
- proceed: Prosseguir
- title: Suspender %{acct}
- warning_html: 'Suspender essa conta vai remover irreversivelmente dados dessa conta, o que inclui:'
tags:
accounts: Contas
hidden: Escondido
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 9fa85b7c2..dceb41376 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -427,12 +427,6 @@ ru:
last_delivery: Последняя доставка
title: WebSub
topic: Тема
- suspensions:
- bad_acct_msg: Не удалось найти такое число подтверждения. Вы уверены, что замораживаете нужный аккаунт?
- hint_html: 'Чтобы подтвердить заморозку аккаунта, пожалуйста, введите %{value} в поле ниже:'
- proceed: Продолжить
- title: Заморозить %{acct}
- warning_html: 'Заморозка этого аккаунта приведёт к необратимому удалению данных с этого аккаунта, включая:'
title: Администрирование
admin_mailer:
new_report:
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index ce6a62e87..4363c59e4 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -2,6 +2,13 @@
en:
simple_form:
hints:
+ account_warning_preset:
+ text: You can use toot syntax, such as URLs, hashtags and mentions
+ admin_account_action:
+ send_email_notification: The user will receive an explanation of what happened with their account
+ text_html: Optional. You can use toot syntax. You can add warning presets to save time
+ type_html: Choose what to do with %{acct}
+ warning_preset_id: Optional. You can still add custom text to end of the preset
defaults:
autofollow: People who sign up through the invite will automatically follow you
avatar: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px
@@ -40,6 +47,18 @@ en:
fields:
name: Label
value: Content
+ account_warning_preset:
+ text: Preset text
+ admin_account_action:
+ send_email_notification: Notify the user per e-mail
+ text: Custom warning
+ type: Action
+ types:
+ disable: Disable
+ none: Do nothing
+ silence: Silence
+ suspend: Suspend and irreversibly delete account data
+ warning_preset_id: Use a warning preset
defaults:
autofollow: Invite to follow your account
avatar: Avatar
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 3458c699c..f44d971a4 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -444,12 +444,6 @@ sk:
last_delivery: Posledné doručenie
title: WebSub
topic: Téma
- suspensions:
- bad_acct_msg: Hodnota pre potvrdenie sa nezhoduje. Si si istý/á že zamrazuješ ten správny účet?
- hint_html: 'Pre potvrdenie zamrazenia účtu, prosím napíš %{value} do následujúceho políčka:'
- proceed: Pokračuj
- title: Zamraziť %{acct}
- warning_html: 'Zamrazením tohto účtu budú dáta na tomto účte nenávratne zmazané, zahŕňajúc:'
tags:
accounts: Účty
hidden: Skryté
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index da621a910..8dee9fdac 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -443,12 +443,6 @@ sr:
last_delivery: Последња достава
title: WebSub
topic: Topic
- suspensions:
- bad_acct_msg: Вредност потврде се не поклапа. Да ли суспендујете прави рачун?
- hint_html: 'Да бисте потврдили суспензију налога, унесите %{value} у поље испод:'
- proceed: Настави
- title: Суспендуј %{acct}
- warning_html: 'Суспендовање овог налога ће неповратноизбрисати све податке са овог налога, који укључују:'
title: Администрација
admin_mailer:
new_report:
diff --git a/config/routes.rb b/config/routes.rb
index 0aba433e2..7723a08af 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -139,6 +139,7 @@ Rails.application.routes.draw do
resources :domain_blocks, only: [:index, :new, :create, :show, :destroy]
resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
resources :action_logs, only: [:index]
+ resources :warning_presets, except: [:new]
resource :settings, only: [:edit, :update]
resources :invites, only: [:index, :create, :destroy] do
@@ -160,7 +161,14 @@ Rails.application.routes.draw do
end
end
- resources :reports, only: [:index, :show, :update] do
+ resources :reports, only: [:index, :show] do
+ member do
+ post :assign_to_self
+ post :unassign
+ post :reopen
+ post :resolve
+ end
+
resources :reported_statuses, only: [:create]
end
@@ -171,7 +179,8 @@ Rails.application.routes.draw do
post :subscribe
post :unsubscribe
post :enable
- post :disable
+ post :unsilence
+ post :unsuspend
post :redownload
post :remove_avatar
post :remove_header
@@ -180,8 +189,7 @@ Rails.application.routes.draw do
resource :change_email, only: [:show, :update]
resource :reset, only: [:create]
- resource :silence, only: [:create, :destroy]
- resource :suspension, only: [:new, :create, :destroy]
+ resource :action, only: [:new, :create], controller: 'account_actions'
resources :statuses, only: [:index, :create, :update, :destroy]
resource :confirmation, only: [:create] do
diff --git a/db/migrate/20181213184704_create_account_warnings.rb b/db/migrate/20181213184704_create_account_warnings.rb
new file mode 100644
index 000000000..e768be277
--- /dev/null
+++ b/db/migrate/20181213184704_create_account_warnings.rb
@@ -0,0 +1,12 @@
+class CreateAccountWarnings < ActiveRecord::Migration[5.2]
+ def change
+ create_table :account_warnings do |t|
+ t.belongs_to :account, foreign_key: { on_delete: :nullify }
+ t.belongs_to :target_account, foreign_key: { to_table: 'accounts', on_delete: :cascade }
+ t.integer :action, null: false, default: 0
+ t.text :text, null: false, default: ''
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20181213185533_create_account_warning_presets.rb b/db/migrate/20181213185533_create_account_warning_presets.rb
new file mode 100644
index 000000000..9c81f1b5e
--- /dev/null
+++ b/db/migrate/20181213185533_create_account_warning_presets.rb
@@ -0,0 +1,9 @@
+class CreateAccountWarningPresets < ActiveRecord::Migration[5.2]
+ def change
+ create_table :account_warning_presets do |t|
+ t.text :text, null: false, default: ''
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 51ac43e1d..51a7b5e74 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2018_12_07_011115) do
+ActiveRecord::Schema.define(version: 2018_12_13_185533) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -76,6 +76,23 @@ ActiveRecord::Schema.define(version: 2018_12_07_011115) do
t.index ["tag_id"], name: "index_account_tag_stats_on_tag_id", unique: true
end
+ create_table "account_warning_presets", force: :cascade do |t|
+ t.text "text", default: "", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ create_table "account_warnings", force: :cascade do |t|
+ t.bigint "account_id"
+ t.bigint "target_account_id"
+ t.integer "action", default: 0, null: false
+ t.text "text", default: "", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["account_id"], name: "index_account_warnings_on_account_id"
+ t.index ["target_account_id"], name: "index_account_warnings_on_target_account_id"
+ end
+
create_table "accounts", force: :cascade do |t|
t.string "username", default: "", null: false
t.string "domain"
@@ -656,6 +673,8 @@ ActiveRecord::Schema.define(version: 2018_12_07_011115) do
add_foreign_key "account_pins", "accounts", on_delete: :cascade
add_foreign_key "account_stats", "accounts", on_delete: :cascade
add_foreign_key "account_tag_stats", "tags", on_delete: :cascade
+ add_foreign_key "account_warnings", "accounts", column: "target_account_id", on_delete: :cascade
+ add_foreign_key "account_warnings", "accounts", on_delete: :nullify
add_foreign_key "accounts", "accounts", column: "moved_to_account_id", on_delete: :nullify
add_foreign_key "admin_action_logs", "accounts", on_delete: :cascade
add_foreign_key "backups", "users", on_delete: :nullify
diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb
index dbcad3c2d..a348ab3d7 100644
--- a/spec/controllers/admin/accounts_controller_spec.rb
+++ b/spec/controllers/admin/accounts_controller_spec.rb
@@ -191,58 +191,6 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
end
- describe 'POST #disable' do
- subject { post :disable, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: current_user_admin) }
- let(:account) { Fabricate(:account, user: user) }
- let(:user) { Fabricate(:user, disabled: false, admin: target_user_admin) }
-
- context 'when user is admin' do
- let(:current_user_admin) { true }
-
- context 'when target user is admin' do
- let(:target_user_admin) { true }
-
- it 'fails to disable account' do
- is_expected.to have_http_status :forbidden
- expect(user.reload).not_to be_disabled
- end
- end
-
- context 'when target user is not admin' do
- let(:target_user_admin) { false }
-
- it 'succeeds in disabling account' do
- is_expected.to redirect_to admin_account_path(account.id)
- expect(user.reload).to be_disabled
- end
- end
- end
-
- context 'when user is not admin' do
- let(:current_user_admin) { false }
-
- context 'when target user is admin' do
- let(:target_user_admin) { true }
-
- it 'fails to disable account' do
- is_expected.to have_http_status :forbidden
- expect(user.reload).not_to be_disabled
- end
- end
-
- context 'when target user is not admin' do
- let(:target_user_admin) { false }
-
- it 'fails to disable account' do
- is_expected.to have_http_status :forbidden
- expect(user.reload).not_to be_disabled
- end
- end
- end
- end
-
describe 'POST #redownload' do
subject { post :redownload, params: { id: account.id } }
diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb
index bcc789c57..b428299ee 100644
--- a/spec/controllers/admin/reports_controller_spec.rb
+++ b/spec/controllers/admin/reports_controller_spec.rb
@@ -46,73 +46,37 @@ describe Admin::ReportsController do
end
end
- describe 'PUT #update' do
- describe 'with an unknown outcome' do
- it 'rejects the change' do
- report = Fabricate(:report)
- put :update, params: { id: report, outcome: 'unknown' }
+ describe 'POST #reopen' do
+ it 'reopens the report' do
+ report = Fabricate(:report)
- expect(response).to have_http_status(404)
- end
+ put :reopen, params: { id: report }
+ expect(response).to redirect_to(admin_report_path(report))
+ report.reload
+ expect(report.action_taken_by_account).to eq nil
+ expect(report.action_taken).to eq false
end
+ end
- describe 'with an outcome of `resolve`' do
- it 'resolves the report' do
- report = Fabricate(:report)
+ describe 'POST #assign_to_self' do
+ it 'reopens the report' do
+ report = Fabricate(:report)
- put :update, params: { id: report, outcome: 'resolve' }
- expect(response).to redirect_to(admin_reports_path)
- report.reload
- expect(report.action_taken_by_account).to eq user.account
- expect(report.action_taken).to eq true
- end
+ put :assign_to_self, params: { id: report }
+ expect(response).to redirect_to(admin_report_path(report))
+ report.reload
+ expect(report.assigned_account).to eq user.account
end
+ end
- describe 'with an outsome of `silence`' do
- it 'silences the reported account' do
- report = Fabricate(:report)
+ describe 'POST #unassign' do
+ it 'reopens the report' do
+ report = Fabricate(:report)
- put :update, params: { id: report, outcome: 'silence' }
- expect(response).to redirect_to(admin_reports_path)
- report.reload
- expect(report.action_taken_by_account).to eq user.account
- expect(report.action_taken).to eq true
- expect(report.target_account).to be_silenced
- end
- end
-
- describe 'with an outsome of `reopen`' do
- it 'reopens the report' do
- report = Fabricate(:report)
-
- put :update, params: { id: report, outcome: 'reopen' }
- expect(response).to redirect_to(admin_report_path(report))
- report.reload
- expect(report.action_taken_by_account).to eq nil
- expect(report.action_taken).to eq false
- end
- end
-
- describe 'with an outsome of `assign_to_self`' do
- it 'reopens the report' do
- report = Fabricate(:report)
-
- put :update, params: { id: report, outcome: 'assign_to_self' }
- expect(response).to redirect_to(admin_report_path(report))
- report.reload
- expect(report.assigned_account).to eq user.account
- end
- end
-
- describe 'with an outsome of `unassign`' do
- it 'reopens the report' do
- report = Fabricate(:report)
-
- put :update, params: { id: report, outcome: 'unassign' }
- expect(response).to redirect_to(admin_report_path(report))
- report.reload
- expect(report.assigned_account).to eq nil
- end
+ put :unassign, params: { id: report }
+ expect(response).to redirect_to(admin_report_path(report))
+ report.reload
+ expect(report.assigned_account).to eq nil
end
end
end
diff --git a/spec/controllers/admin/silences_controller_spec.rb b/spec/controllers/admin/silences_controller_spec.rb
deleted file mode 100644
index 78560eb39..000000000
--- a/spec/controllers/admin/silences_controller_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require 'rails_helper'
-
-describe Admin::SilencesController do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'POST #create' do
- it 'redirects to admin accounts page' do
- account = Fabricate(:account, silenced: false)
-
- post :create, params: { account_id: account.id }
-
- account.reload
- expect(account.silenced?).to eq true
- expect(response).to redirect_to(admin_accounts_path)
- end
- end
-
- describe 'DELETE #destroy' do
- it 'redirects to admin accounts page' do
- account = Fabricate(:account, silenced: true)
-
- delete :destroy, params: { account_id: account.id }
-
- account.reload
- expect(account.silenced?).to eq false
- expect(response).to redirect_to(admin_accounts_path)
- end
- end
-end
diff --git a/spec/controllers/admin/suspensions_controller_spec.rb b/spec/controllers/admin/suspensions_controller_spec.rb
deleted file mode 100644
index 1bc33e490..000000000
--- a/spec/controllers/admin/suspensions_controller_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'rails_helper'
-
-describe Admin::SuspensionsController do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'GET #new' do
- it 'returns 200' do
- get :new, params: { account_id: Fabricate(:account).id, report_id: Fabricate(:report).id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- it 'redirects to admin accounts page' do
- account = Fabricate(:account, suspended: false)
- expect(Admin::SuspensionWorker).to receive(:perform_async).with(account.id)
-
- post :create, params: { account_id: account.id, form_admin_suspension_confirmation: { acct: account.acct } }
-
- expect(response).to redirect_to(admin_accounts_path)
- end
- end
-
- describe 'DELETE #destroy' do
- it 'redirects to admin accounts page' do
- account = Fabricate(:account, suspended: true)
-
- delete :destroy, params: { account_id: account.id }
-
- account.reload
- expect(account.suspended?).to eq false
- expect(response).to redirect_to(admin_accounts_path)
- end
- end
-end
diff --git a/spec/fabricators/account_warning_fabricator.rb b/spec/fabricators/account_warning_fabricator.rb
new file mode 100644
index 000000000..db161d446
--- /dev/null
+++ b/spec/fabricators/account_warning_fabricator.rb
@@ -0,0 +1,5 @@
+Fabricator(:account_warning) do
+ account nil
+ target_account nil
+ text "MyText"
+end
diff --git a/spec/fabricators/account_warning_preset_fabricator.rb b/spec/fabricators/account_warning_preset_fabricator.rb
new file mode 100644
index 000000000..6c0b87e7c
--- /dev/null
+++ b/spec/fabricators/account_warning_preset_fabricator.rb
@@ -0,0 +1,3 @@
+Fabricator(:account_warning_preset) do
+ text "MyText"
+end
diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb
index d9cdb9264..53c836494 100644
--- a/spec/mailers/previews/user_mailer_preview.rb
+++ b/spec/mailers/previews/user_mailer_preview.rb
@@ -39,4 +39,9 @@ class UserMailerPreview < ActionMailer::Preview
def backup_ready
UserMailer.backup_ready(User.first, Backup.first)
end
+
+ # Preview this email at http://localhost:3000/rails/mailers/user_mailer/warning
+ def warning
+ UserMailer.warning(User.first, AccountWarning.new(text: '', action: :silence))
+ end
end
diff --git a/spec/models/account_warning_preset_spec.rb b/spec/models/account_warning_preset_spec.rb
new file mode 100644
index 000000000..a859a305f
--- /dev/null
+++ b/spec/models/account_warning_preset_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe AccountWarningPreset, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/account_warning_spec.rb b/spec/models/account_warning_spec.rb
new file mode 100644
index 000000000..5286f9177
--- /dev/null
+++ b/spec/models/account_warning_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe AccountWarning, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb
new file mode 100644
index 000000000..8c55cf4dd
--- /dev/null
+++ b/spec/models/admin/account_action_spec.rb
@@ -0,0 +1,4 @@
+require 'rails_helper'
+
+RSpec.describe Admin::AccountAction, type: :model do
+end