about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorEmelia Smith <ThisIsMissEm@users.noreply.github.com>2018-04-02 22:04:14 +0200
committerEugen Rochko <eugen@zeonfederated.com>2018-04-02 22:04:14 +0200
commite85cffb2362f914c0f2f7ced4112430b30bc7997 (patch)
tree416a0b35e690ca8b52dd34901f142845f1e12048 /app
parent36eac8ba9011f225f7f949bbf1ca173832561f10 (diff)
Feature: Report improvements (#6967) (#7000)
* Implement Assignment of Reports (#6967)

* Change translation of admin.report.comment.label to "Report Comment" for clarity

As we'll soon add the ability for reports to have comments on them, this clarification makes sense.

* Implement notes for Reports

This enables moderators to leave comments about a report whilst they work on it

* Fix display of report moderation notes

* Allow reports to be reopened / marked as unresolved

* Redirect to reports listing upon resolution of report

* Implement "resolve with note" functionality

* Add inverse relationship for report notes

* Remove additional database querying when loading report notes

* Fix tests for reports

* Fix localisations for report notes / reports
Diffstat (limited to 'app')
-rw-r--r--app/controllers/admin/report_notes_controller.rb49
-rw-r--r--app/controllers/admin/reports_controller.rb20
-rw-r--r--app/helpers/admin/action_logs_helper.rb2
-rw-r--r--app/models/account.rb2
-rw-r--r--app/models/report.rb4
-rw-r--r--app/models/report_note.rb21
-rw-r--r--app/policies/report_note_policy.rb17
-rw-r--r--app/views/admin/report_notes/_report_note.html.haml11
-rw-r--r--app/views/admin/reports/_report.html.haml5
-rw-r--r--app/views/admin/reports/index.html.haml1
-rw-r--r--app/views/admin/reports/show.html.haml84
11 files changed, 197 insertions, 19 deletions
diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb
new file mode 100644
index 000000000..ef8c0f469
--- /dev/null
+++ b/app/controllers/admin/report_notes_controller.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Admin
+  class ReportNotesController < BaseController
+    before_action :set_report_note, only: [:destroy]
+
+    def create
+      authorize ReportNote, :create?
+
+      @report_note = current_account.report_notes.new(resource_params)
+
+      if @report_note.save
+        if params[:create_and_resolve]
+          @report_note.report.update!(action_taken: true, action_taken_by_account_id: current_account.id)
+          log_action :resolve, @report_note.report
+
+          redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
+        else
+          redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.created_msg')
+        end
+      else
+        @report       = @report_note.report
+        @report_notes = @report.notes.latest
+        @form = Form::StatusBatch.new
+
+        render template: 'admin/reports/show'
+      end
+    end
+
+    def destroy
+      authorize @report_note, :destroy?
+      @report_note.destroy!
+      redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.destroyed_msg')
+    end
+
+    private
+
+    def resource_params
+      params.require(:report_note).permit(
+        :content,
+        :report_id
+      )
+    end
+
+    def set_report_note
+      @report_note = ReportNote.find(params[:id])
+    end
+  end
+end
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index 75db6b78a..fc3785e3b 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -11,19 +11,35 @@ module Admin
 
     def show
       authorize @report, :show?
+      @report_note = @report.notes.new
+      @report_notes = @report.notes.latest
       @form = Form::StatusBatch.new
     end
 
     def update
       authorize @report, :update?
       process_report
-      redirect_to admin_report_path(@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
     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.update!(action_taken: false, action_taken_by_account_id: nil)
+        log_action :reopen, @report
       when 'resolve'
         @report.update!(action_taken_by_current_attributes)
         log_action :resolve, @report
@@ -32,11 +48,13 @@ module Admin
         log_action :resolve, @report
         log_action :suspend, @report.target_account
         resolve_all_target_account_reports
+        @report.reload
       when 'silence'
         @report.target_account.update!(silenced: true)
         log_action :resolve, @report
         log_action :silence, @report.target_account
         resolve_all_target_account_reports
+        @report.reload
       else
         raise ActiveRecord::RecordNotFound
       end
diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb
index 78278c700..7c26c0b05 100644
--- a/app/helpers/admin/action_logs_helper.rb
+++ b/app/helpers/admin/action_logs_helper.rb
@@ -86,7 +86,7 @@ module Admin::ActionLogsHelper
       opposite_verbs?(log) ? 'negative' : 'positive'
     when :update, :reset_password, :disable_2fa, :memorialize
       'neutral'
-    when :demote, :silence, :disable, :suspend, :remove_avatar
+    when :demote, :silence, :disable, :suspend, :remove_avatar, :reopen
       'negative'
     when :destroy
       opposite_verbs?(log) ? 'positive' : 'negative'
diff --git a/app/models/account.rb b/app/models/account.rb
index a34b6a2d3..446144a3e 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -95,6 +95,8 @@ class Account < ApplicationRecord
   has_many :reports
   has_many :targeted_reports, class_name: 'Report', foreign_key: :target_account_id
 
+  has_many :report_notes, dependent: :destroy
+
   # Moderation notes
   has_many :account_moderation_notes, dependent: :destroy
   has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy
diff --git a/app/models/report.rb b/app/models/report.rb
index dd123fc15..f5b37cb6d 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -12,12 +12,16 @@
 #  account_id                 :integer          not null
 #  action_taken_by_account_id :integer
 #  target_account_id          :integer          not null
+#  assigned_account_id        :integer
 #
 
 class Report < ApplicationRecord
   belongs_to :account
   belongs_to :target_account, class_name: 'Account'
   belongs_to :action_taken_by_account, class_name: 'Account', optional: true
+  belongs_to :assigned_account, class_name: 'Account', optional: true
+
+  has_many :notes, class_name: 'ReportNote', foreign_key: :report_id, inverse_of: :report, dependent: :destroy
 
   scope :unresolved, -> { where(action_taken: false) }
   scope :resolved,   -> { where(action_taken: true) }
diff --git a/app/models/report_note.rb b/app/models/report_note.rb
new file mode 100644
index 000000000..3d12cf7b6
--- /dev/null
+++ b/app/models/report_note.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+# == Schema Information
+#
+# Table name: report_notes
+#
+#  id         :integer          not null, primary key
+#  content    :text             not null
+#  report_id  :integer          not null
+#  account_id :integer          not null
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+class ReportNote < ApplicationRecord
+  belongs_to :account
+  belongs_to :report, inverse_of: :notes
+
+  scope :latest, -> { reorder('created_at ASC') }
+
+  validates :content, presence: true, length: { maximum: 500 }
+end
diff --git a/app/policies/report_note_policy.rb b/app/policies/report_note_policy.rb
new file mode 100644
index 000000000..694bc096b
--- /dev/null
+++ b/app/policies/report_note_policy.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ReportNotePolicy < ApplicationPolicy
+  def create?
+    staff?
+  end
+
+  def destroy?
+    admin? || owner?
+  end
+
+  private
+
+  def owner?
+    record.account_id == current_account&.id
+  end
+end
diff --git a/app/views/admin/report_notes/_report_note.html.haml b/app/views/admin/report_notes/_report_note.html.haml
new file mode 100644
index 000000000..60ac5d0d5
--- /dev/null
+++ b/app/views/admin/report_notes/_report_note.html.haml
@@ -0,0 +1,11 @@
+%tr
+  %td
+    %p
+      %strong= report_note.account.acct
+      on
+      %time.formatted{ datetime: report_note.created_at.iso8601, title: l(report_note.created_at) }
+        = l report_note.created_at
+      = table_link_to 'trash', t('admin.reports.notes.delete'), admin_report_note_path(report_note), method: :delete if can?(:destroy, report_note)
+      %br/
+      %br/
+    = simple_format(h(report_note.content))
diff --git a/app/views/admin/reports/_report.html.haml b/app/views/admin/reports/_report.html.haml
index d5eb161b9..d266f4840 100644
--- a/app/views/admin/reports/_report.html.haml
+++ b/app/views/admin/reports/_report.html.haml
@@ -18,4 +18,9 @@
         = fa_icon('camera')
         = report.media_attachments.count
   %td
+    - if report.assigned_account.nil?
+      \-
+    - else
+      = link_to report.assigned_account.acct, admin_account_path(report.assigned_account.id)
+  %td
     = table_link_to 'circle', t('admin.reports.view'), admin_report_path(report)
diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml
index 577c68a86..3b127c4fc 100644
--- a/app/views/admin/reports/index.html.haml
+++ b/app/views/admin/reports/index.html.haml
@@ -20,6 +20,7 @@
           %th= t('admin.reports.reported_by')
           %th= t('admin.reports.comment.label')
           %th= t('admin.reports.report_contents')
+          %th= t('admin.reports.assigned')
           %th
       %tbody
         = render @reports
diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml
index 5747cc274..e7634a034 100644
--- a/app/views/admin/reports/show.html.haml
+++ b/app/views/admin/reports/show.html.haml
@@ -4,24 +4,68 @@
 - content_for :page_title do
   = t('admin.reports.report', id: @report.id)
 
+%div{ style: 'overflow: hidden; margin-bottom: 20px' }
+  - if !@report.action_taken?
+    %div{ style: 'float: right' }
+      = link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
+      = link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
+    %div{ style: 'float: left' }
+      = link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button'
+  - else
+    = link_to t('admin.reports.mark_as_unresolved'), admin_report_path(@report, outcome: 'reopen'), method: :put, class: 'button'
+
+.table-wrapper
+  %table.table.inline-table
+    %tbody
+      %tr
+        %th= t('admin.reports.updated_at')
+        %td{colspan: 2}
+          %time.formatted{ datetime: @report.updated_at.iso8601 }
+      %tr
+        %th= t('admin.reports.status')
+        %td{colspan: 2}
+          - if @report.action_taken?
+            = t('admin.reports.resolved')
+            = table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
+          - else
+            = t('admin.reports.unresolved')
+      - if !@report.action_taken_by_account.nil?
+        %tr
+          %th= t('admin.reports.action_taken_by')
+          %td= @report.action_taken_by_account.acct
+      - else
+        %tr
+          %th= t('admin.reports.assigned')
+          %td
+            - if @report.assigned_account.nil?
+              \-
+            - else
+              = link_to @report.assigned_account.acct, admin_account_path(@report.assigned_account.id)
+          %td{style: "text-align: right"}
+            - 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
+            - if !@report.assigned_account.nil?
+              = table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put
+
 .report-accounts
   .report-accounts__item
-    %strong= t('admin.reports.reported_account')
+    %h3= t('admin.reports.reported_account')
     = render 'authorize_follows/card', account: @report.target_account, admin: true
     = render 'admin/accounts/card', account: @report.target_account
   .report-accounts__item
-    %strong= t('admin.reports.reported_by')
+    %h3= t('admin.reports.reported_by')
     = render 'authorize_follows/card', account: @report.account, admin: true
     = render 'admin/accounts/card', account: @report.account
 
-%p
-  %strong= t('admin.reports.comment.label')
-  \:
-  = simple_format(@report.comment.presence || t('admin.reports.comment.none'))
+%h3= t('admin.reports.comment.label')
+
+= simple_format(@report.comment.presence || t('admin.reports.comment.none'))
 
 - unless @report.statuses.empty?
   %hr/
 
+  %h3= t('admin.reports.statuses')
+
   = form_for(@form, url: admin_report_reported_statuses_path(@report.id)) do |f|
     .batch-form-box
       .batch-checkbox-all
@@ -46,14 +90,20 @@
 
 %hr/
 
-- if !@report.action_taken?
-  %div{ style: 'overflow: hidden' }
-    %div{ style: 'float: right' }
-      = link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
-      = link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
-    %div{ style: 'float: left' }
-      = link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button'
-- elsif !@report.action_taken_by_account.nil?
-  %p
-    %strong #{t('admin.reports.action_taken_by')}:
-    = @report.action_taken_by_account.acct
+%h3= t('admin.reports.notes.label')
+
+- if @report_notes.length > 0
+  .table-wrapper
+    %table.table
+      %thead
+        %tr
+          %th
+      %tbody
+        = render @report_notes
+
+= simple_form_for @report_note, url: admin_report_notes_path do |f|
+  = render 'shared/error_messages', object: @report_note
+  = f.input :content
+  = f.hidden_field :report_id
+  = f.button :button, t('admin.reports.notes.create'), type: :submit
+  = f.button :button, t('admin.reports.notes.create_and_resolve'), type: :submit, name: :create_and_resolve