Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AO3-6830 Add creator IDs to abuse reports #5088

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions app/models/abuse_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,17 @@ def email_and_send
end

def send_report
return unless %w(staging production).include?(Rails.env)
return unless zoho_enabled?

reporter = AbuseReporter.new(
title: summary,
description: comment,
language: language,
email: email,
username: username,
ip_address: ip_address,
url: url
url: url,
creator_ids: creator_ids
)
response = reporter.send_report!
ticket_id = response["id"]
Expand All @@ -123,10 +125,27 @@ def send_report
attach_work_download(ticket_id)
end

def creator_ids
work_id = reported_work_id
return unless work_id

work = Work.find_by(id: work_id)
return "deletedwork" unless work

ids = work.pseuds.pluck(:user_id).push(*work.original_creators.pluck(:user_id)).uniq.sort!
ids.prepend("orphanedwork") if ids.delete(User.orphan_account.id)
ids.join(", ")
end

# ID of the reported work, unless the report is about comment(s) on the work
def reported_work_id
comments = url[%r{/comments/}, 0]
url[%r{/works/(\d+)}, 1] if comments.nil?
end

def attach_work_download(ticket_id)
is_not_comments = url[%r{/comments/}, 0].nil?
work_id = url[%r{/works/(\d+)}, 1]
return unless work_id && is_not_comments
work_id = reported_work_id
return unless work_id

work = Work.find_by(id: work_id)
ReportAttachmentJob.perform_later(ticket_id, work) if work
Expand Down Expand Up @@ -174,4 +193,10 @@ def email_is_not_over_reporting
out violations to report, but only report violations you
encounter during your normal browsing."))
end

private

def zoho_enabled?
%w[staging production].include?(Rails.env)
end
end
5 changes: 4 additions & 1 deletion app/models/feedback_reporters/abuse_reporter.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class AbuseReporter < FeedbackReporter
attr_accessor :creator_ids

def report_attributes
super.deep_merge(
"departmentId" => department_id,
Expand All @@ -13,7 +15,8 @@ def report_attributes
def custom_zoho_fields
{
"cf_ip" => ip_address.presence || "Unknown IP",
"cf_url" => url.presence || "Unknown URL"
"cf_url" => url.presence || "Unknown URL",
"cf_user_id" => creator_ids.presence || ""
}
end

Expand Down
150 changes: 146 additions & 4 deletions spec/models/abuse_report_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'spec_helper'
require "spec_helper"

describe AbuseReport do
context "when report is not spam" do
Expand All @@ -9,7 +9,7 @@
end

context "comment missing" do
let(:report_without_comment) {build(:abuse_report, comment: nil)}
let(:report_without_comment) { build(:abuse_report, comment: nil) }
it "is invalid" do
expect(report_without_comment.save).to be_falsey
expect(report_without_comment.errors[:comment]).not_to be_empty
Expand Down Expand Up @@ -328,8 +328,8 @@

context "when report is spam" do
let(:legit_user) { create(:user) }
let(:spam_report) { build(:abuse_report, username: 'viagra-test-123') }
let!(:safe_report) { build(:abuse_report, username: 'viagra-test-123', email: legit_user.email) }
let(:spam_report) { build(:abuse_report, username: "viagra-test-123") }
let!(:safe_report) { build(:abuse_report, username: "viagra-test-123", email: legit_user.email) }

before do
allow(Akismetor).to receive(:spam?).and_return(true)
Expand Down Expand Up @@ -380,4 +380,146 @@
.to have_enqueued_job
end
end

describe "#creator_ids" do
it "returns no creator ids for non-work URLs" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/users/someone/")

expect(subject.creator_ids).to be_nil
end

it "returns no creator ids for comment sub-URLs" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/123/comments/")

expect(subject.creator_ids).to be_nil
end

context "for work URLs" do
it "returns deletedwork for a work that doesn't exist" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/000/")

expect(subject.creator_ids).to eq("deletedwork")
end

context "for a single creator" do
let(:work) { create(:work) }

it "returns a single creator id" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq(work.users.first.id.to_s)
end
end

context "for an anonymous work" do
let(:anonymous_collection) { create(:anonymous_collection) }
let(:work) { create(:work, collections: [anonymous_collection]) }

it "returns a single creator id" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq(work.users.first.id.to_s)
end
end

context "for an unrevealed work" do
let(:unrevealed_collection) { create(:unrevealed_collection) }
let(:work) { create(:work, collections: [unrevealed_collection]) }

it "returns a single creator id" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq(work.users.first.id.to_s)
end
end

context "for multiple pseuds of one creator" do
let(:user) { create(:user) }
let(:pseud) { create(:pseud, user: user) }
let(:work) { create(:work, authors: [pseud, user.default_pseud]) }

it "returns a single creator id" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq(user.id.to_s)
end
end

context "for multiple creators" do
let(:user1) { create(:user, id: 10) }
let(:user2) { create(:user, id: 11) }
let(:work) { create(:work, authors: [user2.default_pseud, user1.default_pseud]) }

it "returns a sorted list of creator ids" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq("#{user1.id}, #{user2.id}")
end
end

context "for an invited co-creator that hasn't accepted yet" do
let(:user) { create(:user) }
let(:invited) { create(:user) }
let(:work) { create(:work, authors: [user.default_pseud, invited.default_pseud]) }
let(:creatorship) { work.creatorships.last }

before do
creatorship.approved = false
creatorship.save!(validate: false)
end

it "returns only the creator" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq(user.id.to_s)
end
end
end

context "for an orphaned work" do
let!(:orphan_account) { create(:user, login: "orphan_account") }
let(:orphaneer) { create(:user, id: 20) }
let(:work) { create(:work, authors: [orphaneer.default_pseud]) }

context "recently orphaned" do
before do
Creatorship.orphan([orphaneer.default_pseud], [work], false)
end

it "returns orphanedwork and the original creator" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq("orphanedwork, #{orphaneer.id}")
end
end

context "orphaned a long time ago" do
before do
Creatorship.orphan([orphaneer.default_pseud], [work], false)
work.original_creators.destroy_all
end

it "returns orphanedwork" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq("orphanedwork")
end
end

context "partially orphaned" do
let(:cocreator) { create(:user, id: 21) }
let(:work) { create(:work, authors: [cocreator.default_pseud, orphaneer.default_pseud]) }

before do
Creatorship.orphan([orphaneer.default_pseud], [work], false)
end

it "returns a sorted list of orphanedwork, the co-creator and the original creator" do
allow(subject).to receive(:url).and_return("http://archiveofourown.org/works/#{work.id}/")

expect(subject.creator_ids).to eq("orphanedwork, #{orphaneer.id}, #{cocreator.id}")
end
end
end
end
end
14 changes: 12 additions & 2 deletions spec/models/feedback_reporters/abuse_reporter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
email: "[email protected]",
username: "Walrus",
ip_address: "127.0.0.1",
url: "http://localhost"
url: "http://localhost",
creator_ids: "3, 4"
}
end

Expand All @@ -28,7 +29,8 @@
"cf_language" => "English",
"cf_name" => "Walrus",
"cf_ip" => "127.0.0.1",
"cf_url" => "http://localhost"
"cf_url" => "http://localhost",
"cf_user_id" => "3, 4"
}
}
end
Expand Down Expand Up @@ -87,5 +89,13 @@
expect(subject.report_attributes.fetch("description")).to eq("Hi!http://example.com/Camera-icon.svgBye!")
end
end

context "if the report does not have creator_ids" do
it "returns a hash containing a blank string for the user id" do
allow(subject).to receive(:creator_ids).and_return(nil)

expect(subject.report_attributes.fetch("cf").fetch("cf_user_id")).to eq("")
end
end
end
end
Loading