Skip to content

Commit 10bd7f9

Browse files
committed
Start building up a report page
1 parent 381152f commit 10bd7f9

8 files changed

Lines changed: 170 additions & 4 deletions

File tree

app/controllers/complaints_controller.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def create
2828
if @complaint.save
2929
@comment = ComplaintComment.new(comment_params.merge(complaint: @complaint, internal: false))
3030
if @comment.save
31-
redirect_to safety_center_path # report path
31+
redirect_to complaint_path(@complaint.access_token)
3232
else
3333
@errors = @comment.errors.full_messages
3434
render :report, status: :bad_request, layout: 'without_sidebar'
@@ -38,4 +38,33 @@ def create
3838
render :report, status: :bad_request, layout: 'without_sidebar'
3939
end
4040
end
41+
42+
def show
43+
@complaint = Complaint.includes(:comments, :assignee, comments: :user).where(access_token: params[:token]).first
44+
45+
if @complaint.nil?
46+
raise ActiveRecord::RecordNotFound, "Complaint not found with token=#{params[:token]}"
47+
end
48+
49+
return unless access_check(@complaint)
50+
51+
@report_type = AppConfig.safety_center['report_types'][@complaint.report_type]
52+
@content_type = AppConfig.safety_center['content_types'][@complaint.content_type]
53+
@status = AppConfig.safety_center['statuses'][@complaint.status]
54+
render layout: 'without_sidebar'
55+
end
56+
57+
private
58+
59+
def access_check(complaint)
60+
if user_signed_in? && (current_user.staff? || current_user == complaint.user)
61+
# only allow complainants to access their own complaints regardless of access token
62+
true
63+
elsif !user_signed_in?
64+
# if not signed in then we're just relying on the access token as proof of access
65+
true
66+
else
67+
raise ActiveRecord::RecordNotFound
68+
end
69+
end
4170
end

app/models/complaint.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
class Complaint < ApplicationRecord
22
belongs_to :user, required: false
33
belongs_to :assignee, required: false, class_name: 'User'
4+
has_many :comments, class_name: 'ComplaintComment', dependent: :destroy
45

56
after_create :generate_access_token
7+
after_create :assign_status
68

79
validates :email, presence: -> { !user.present? }
810
validates :report_type, presence: true
911
validates :reported_url, presence: true
1012

13+
##
14+
# Update the complaint's status, create a comment to record the change, and send emails to the right people.
15+
# @param new_status [String] The new status to set, from safety_center.yml.
16+
# @param attribute_to [String] Who should the status change be attributed to? Username only.
17+
def update_status(new_status, attribute_to = nil)
18+
dt = DateTime.now
19+
update(status: new_status, status_updated_at: dt)
20+
attribution = attribute_to.nil? ? 'automatically' : "by #{attribute_to}"
21+
comments.create(content: "Status updated to #{new_status} at #{dt.iso8601} #{attribution}.", internal: true,
22+
user_id: -1)
23+
# TODO send email
24+
end
25+
1126
private
1227

1328
def generate_access_token
1429
update(access_token: SecureRandom.uuid)
1530
end
31+
32+
def assign_status
33+
update_status 'new'
34+
end
1635
end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<%#
2+
Complaint comment partial rendered in a widget.
3+
4+
Variables:
5+
comment: [ComplaintComment] The comment to render.
6+
%>
7+
8+
<div class="widget <%= 'is-yellow' if comment.internal? %>">
9+
<div class="widget--header">
10+
<span class="has-font-size-caption">
11+
<strong>
12+
<% if comment.user.nil? || comment.user == @complaint.user %>
13+
Reporter
14+
<% elsif current_user&.staff? %>
15+
<%= comment.user.rtl_safe_username %>
16+
<% else %>
17+
Staff
18+
<% end %>
19+
</strong>
20+
<%= time_ago_in_words(comment.created_at) %> ago
21+
</span>
22+
</div>
23+
<div class="widget--body has-font-size-caption">
24+
<%= comment.content %>
25+
</div>
26+
</div>

app/views/complaints/show.html.erb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<%= link_to safety_center_path do %>
2+
&laquo; Back to Safety Center
3+
<% end %>
4+
5+
<h1><%= @report_type['name'] %></h1>
6+
<div class="grid">
7+
<div class="grid--cell is-12 is-6-md is-6-lg">
8+
<div class="widget">
9+
<div class="widget--body">
10+
<h2 class="has-font-size-base h-m-t-0">Report</h2>
11+
<div class="grid has-font-size-caption">
12+
<div class="grid--cell is-3">Reported URL</div>
13+
<div class="grid--cell is-9 has-color-yellow-700">
14+
<i class="fas fa-exclamation-triangle"></i>
15+
<%= link_to @complaint.reported_url, @complaint.reported_url, class: 'is-yellow' %>
16+
</div>
17+
18+
<% if @content_type.present? %>
19+
<div class="grid--cell is-3">Content type</div>
20+
<div class="grid--cell is-9"><%= @content_type['name'] %></div>
21+
<% end %>
22+
23+
<div class="grid--cell is-3">Reported by</div>
24+
<div class="grid--cell is-9">
25+
<% if @complaint.user.present? %>
26+
<%= user_link @complaint.user %>
27+
<% else %>
28+
<%= @complaint.email %>
29+
<% end %>
30+
</div>
31+
</div>
32+
</div>
33+
</div>
34+
</div>
35+
<div class="grid--cell is-12 is-6-md is-6-lg">
36+
<div class="widget">
37+
<div class="widget--body">
38+
<h2 class="has-font-size-base h-m-t-0">Investigation</h2>
39+
<div class="grid has-font-size-caption">
40+
<div class="grid--cell is-3">Status</div>
41+
<div class="grid--cell is-9">
42+
<%= @status['name'] %>
43+
(last updated <%= time_ago_in_words(@complaint.status_updated_at) %> ago)
44+
</div>
45+
46+
<div class="grid--cell is-3">Assignee</div>
47+
<div class="grid--cell is-9">
48+
<% if @complaint.assignee.nil? %>
49+
(unassigned)
50+
<% elsif user_signed_in? && current_user.staff? %>
51+
<%= user_link @complaint.assignee %>
52+
<% else %>
53+
Yes - Assigned to Investigator
54+
<% end %>
55+
</div>
56+
</div>
57+
</div>
58+
</div>
59+
</div>
60+
</div>
61+
62+
<% @complaint.comments.sort_by(&:created_at).each do |comment| %>
63+
<% next if comment.internal? && !current_user&.staff? %>
64+
<%= render 'comment', comment: comment %>
65+
<% end %>

config/config/safety_center.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
1+
statuses:
2+
new:
3+
name: New
4+
description: This is a new report, waiting to be assigned an investigator.
5+
assigned:
6+
name: Assigned
7+
description: This report has been assigned to a member of staff and is being investigated.
8+
reviewed:
9+
name: Reviewed
10+
description: This report has been investigated and appropriate action taken.
11+
responded:
12+
name: Responded
13+
description: This report has had a response from the reporter.
14+
closed:
15+
name: Closed
16+
description: This report has been closed. No further action may be taken.
17+
118
report_types:
219
illegal:
320
enabled: true
21+
name: Report of illegal content
422
description: illegal harmful content
523
abusive:
624
enabled: true
25+
name: Report of abusive content
726
description: abusive or otherwise harmful content
827
copyright:
928
enabled: true
29+
name: Report of copyright infringement
1030
description: copyright infringement
1131
appeal:
1232
enabled: true
33+
name: Classification Appeal
1334
description: an appeal regarding how we've handled your content
1435

1536
content_types:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddStatusUpdatedAtToComplaints < ActiveRecord::Migration[7.2]
2+
def change
3+
add_column :complaints, :status_updated_at, :datetime
4+
end
5+
end

db/schema.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[7.2].define(version: 2025_10_08_162510) do
13+
ActiveRecord::Schema[7.2].define(version: 2025_10_10_005424) do
1414
create_table "abilities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
1515
t.bigint "community_id"
1616
t.string "name"
@@ -256,6 +256,7 @@
256256
t.string "content_type"
257257
t.string "email"
258258
t.string "reported_url"
259+
t.datetime "status_updated_at"
259260
t.index ["access_token"], name: "index_complaints_on_access_token", unique: true
260261
t.index ["assignee_id"], name: "index_complaints_on_assignee_id"
261262
t.index ["report_type"], name: "index_complaints_on_report_type"

test/controllers/complaints_controller_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class ComplaintsControllerTest < ActionDispatch::IntegrationTest
4343
content: 'test', email: 'something@else.com', user_wants_updates: true
4444
assert_response(:found)
4545
assert_not_nil assigns(:complaint)
46-
# assert_redirected_to complaint_path(@complaint.access_token)
46+
assert_redirected_to complaint_path(@complaint.access_token)
4747
assert_equal users(:basic_user).email, assigns(:complaint).email
4848
end
4949

@@ -52,7 +52,7 @@ class ComplaintsControllerTest < ActionDispatch::IntegrationTest
5252
content: 'test', email: 'something@else.com', user_wants_updates: true
5353
assert_response(:found)
5454
assert_not_nil assigns(:complaint)
55-
# assert_redirected_to complaint_path(@complaint.access_token)
55+
assert_redirected_to complaint_path(@complaint.access_token)
5656
assert_equal 'something@else.com', assigns(:complaint).email
5757
end
5858

0 commit comments

Comments
 (0)