Add DMCA complaint form.

Add a form for submitting DMCA complaints. The complaint is emailed to
the site owner, and a confirmation email is sent to the submitter.
This commit is contained in:
evazion
2022-10-11 15:45:03 -05:00
parent 8fbc6d1d3a
commit 24bc6aa949
12 changed files with 278 additions and 12 deletions

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
class DmcasController < ApplicationController
def create
@dmca = params[:dmca].slice(:name, :email, :address, :infringing_urls, :original_urls, :proof, :perjury_agree, :good_faith_agree, :signature)
UserMailer.with_request(request, dmca: @dmca).dmca_complaint(to: Danbooru.config.dmca_email).deliver_now
UserMailer.with_request(request, dmca: @dmca).dmca_complaint(to: @dmca[:email]).deliver_now
end
def show
end
def template
end
end

View File

@@ -12,7 +12,7 @@ class ApplicationMailer < ActionMailer::Base
default from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.contact_email}>", content_type: "text/html"
default "Message-ID": -> { "<#{SecureRandom.uuid}@#{Danbooru.config.hostname}>" }
def mail(user, require_verified_email:, **options)
def mail_user(user, require_verified_email:, **options)
# https://www.rfc-editor.org/rfc/rfc8058#section-3.1
#
# A mail receiver can do a one-click unsubscription by performing an HTTPS POST to the HTTPS URI in the
@@ -31,19 +31,20 @@ class ApplicationMailer < ActionMailer::Base
headers(params.to_h[:headers].to_h)
message = super(to: user.email_address&.address, **options)
message = mail(to: user.email_address&.address, **options)
message.perform_deliveries = user.can_receive_email?(require_verified_email: require_verified_email)
message
end
def self.with_request(request)
def self.with_request(request, **params)
with(
request: {
url: "#{request.method} #{request.url}",
remote_ip: request.remote_ip.to_s,
request_id: request.request_id.to_s,
session_id: request.session.id.to_s,
}
},
**params
)
end
end

View File

@@ -5,7 +5,7 @@ class UserMailer < ApplicationMailer
def dmail_notice(dmail)
@dmail = dmail
@user = dmail.to
mail(
mail_user(
@user,
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.notification_email}>",
subject: "#{Danbooru.config.canonical_app_name}: #{dmail.from.name} sent you a message",
@@ -16,7 +16,7 @@ class UserMailer < ApplicationMailer
# The email sent when a user requests a password reset.
def password_reset(user)
@user = user
mail(
mail_user(
@user,
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.account_security_email}>",
subject: "#{Danbooru.config.app_name} password reset request",
@@ -27,7 +27,7 @@ class UserMailer < ApplicationMailer
# The email sent when a user changes their email address.
def email_change_confirmation(user)
@user = user
mail(
mail_user(
@user,
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.account_security_email}>",
subject: "Confirm your email address",
@@ -38,11 +38,20 @@ class UserMailer < ApplicationMailer
# The email sent when a new user signs up with an email address.
def welcome_user(user)
@user = user
mail(
mail_user(
@user,
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.welcome_user_email}>",
subject: "Welcome to #{Danbooru.config.app_name}! Confirm your email address",
require_verified_email: false,
)
end
def dmca_complaint(to:)
@dmca = params[:dmca]
mail(
from: Danbooru.config.dmca_email,
to: to,
subject: "DMCA complaint",
)
end
end

View File

@@ -0,0 +1,30 @@
<% page_title "DMCA Notice" %>
<div id="c-static">
<div id="a-dmca" class="prose fixed-width-container">
<h1>DMCA Notice</h1>
<p>Your DMCA notice has been submitted. Please allow up to 48 hours for it to be processed. A confirmation email will be sent to <%= @dmca[:email] %>. You may not receive a response unless further information is needed from you. You may contact <%= link_to Danbooru.config.dmca_email, "mailto:#{Danbooru.config.dmca_email}" %> if you have any further questions.</p>
<p>Your name: <%= @dmca[:name] %></p>
<p>Your email: <%= @dmca[:email] %></p>
<p>Your address: <%= @dmca[:address] %></p>
<p>Infringing URLs:</p>
<ul>
<% @dmca[:infringing_urls].to_s.split.each do |url| %>
<li><%= url %></li>
<% end %>
</ul>
<p>Original URLs:</p>
<ul>
<% @dmca[:original_urls].to_s.split.each do |url| %>
<li><%= url %></li>
<% end %>
</ul>
<p>Proof that you are the artist: <%= @dmca[:proof] %></p>
<p>Your signature: <%= @dmca[:signature] %></p>
</div>
</div>

View File

@@ -0,0 +1,83 @@
<% page_title "DMCA Complaint" %>
<% @danbooru = Danbooru.config.canonical_app_name %>
<div id="c-static">
<div id="a-dmca" class="prose fixed-width-container mx-auto">
<h1>DMCA Complaint</h1>
<p>Fill out the form below to submit a DMCA complaint.</p>
<p>Please allow up to 48 hours for your complaint to be processed. You may not receive a response unless further information is needed from you.</p>
<p>The information below is legally required by the DMCA process. If any required information is falsified or omitted, your notice may be not be processed. Please submit your information in English. If you're not sure about anything, seek legal advice.</p>
<hr class="border">
<%= form_tag(dmca_path) do %>
<p>
<label>Your name</label><br>
<input name="dmca[name]" class="w-1/2" required></input>
</p>
<p>
<label>Your email address</label><br>
<input name="dmca[email]" class="w-1/2" type="email" required></input>
</p>
<p>
<label>Your contact information (mailing address or phone number)</label><br>
<input name="dmca[address]" class="w-1/2"></input>
</p>
<p>
<label>A list of links to the <%= @danbooru %> posts you would like to have removed (one per line).</label><br>
<textarea name="dmca[infringing_urls]" class="w-full h-150px" required></textarea>
</p>
<p>
<label>A list of links to the original location of each of these works on your Twitter, Pixiv, or other accounts or personal websites (one per line).</label><br>
<textarea name="dmca[original_urls]" class="w-full h-150px" required></textarea>
</p>
<p>
<label>Proof that you are the artist or copyright holder. Proof can include either an email address or message listed on one of your social media profiles (provide a link or describe it below), or a screenshot or .psd file of one of your original works (provide a link below)</label><br>
<textarea name="dmca[proof]" class="w-full h-16"></textarea>
</p>
<p>
<input type="checkbox" name="perjury_agree" required>
<label for="dmca[perjury_agree]">I swear, under penalty of perjury, that the information in this notification is accurate and that I am the copyright owner or am authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.</label>
</p>
<p>
<input type="checkbox" name="good_faith_agree" required>
<label for="dmca[good_faith_agree]">I have a good faith belief that the use of the copyrighted materials described above and contained on the service is not authorized by the copyright owner, its agent, or by protection of law.</label>
</p>
<p>
<label>Signature (type your full legal name)</label><br>
<input name="dmca[signature]" class="w-1/2" required></input>
</p>
<p>
<input type="submit" value="Submit">
</p>
<% end %>
<hr class="border">
<p>If you'd prefer not to use our automated form, you can <%= link_to "email us here", "mailto:#{Danbooru.config.dmca_email}" %>. Your email must include the following:</p>
<ul>
<li>Your contact information, including your name, mailing address, phone number, and email address.</li>
<li>A description of the material that you claim upon infringes your copyright, in enough detail to permit us to locate that material. For example, a list of links to each post on <%= Danbooru.config.canonical_app_name %> you wish to have removed. Screenshots or simply listing your name or social media accounts are not sufficient to locate the works you wish to have removed.</li>
<li>An identification of the copyrighted work you claim to have been infringed. For example, for each <%= Danbooru.config.canonical_app_name %> post you claim infringes on your copyright, a link to where the work was originally posted on your Pixiv, Twitter, or other social media accounts or personal websites.</li>
<li>A statement that you have a good faith belief that use of the material in the manner complained of is not authorized by the copyright owner, its agent, or the law.</li>
<li>A statement that the information in the notification is accurate, and under penalty of perjury, that you are authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.</li>
<li>A physical or electronic signature of the copyright owner or a person authorized to act on their behalf. Typing your full name will suffice. This must be your full legal name, not a pseudonym or artist handle.</li>
</ul>
<p><%= link_to "Here is a template you can follow", template_dmca_path %>. All of the above information is legally required by the DMCA process. Your notice may not be processed if any required information is omitted or falsified.</p>
</div>
</div>

View File

@@ -0,0 +1,38 @@
<% page_title "DMCA Template" %>
<div id="c-static">
<div id="a-dmca-template" class="prose fixed-width-container">
<h1>DMCA Template</h1>
<p>Pursuant to 17 USC 512(c)(3)(A), this communication serves as a statement that:</p>
<p>I hereby request that you remove or disable access to the following material as it appears on your service:</p>
<p>
<ul>
<li><b>List of links to the <%= Danbooru.config.canonical_app_name %> posts would you like to have removed.</b></li>
</ul>
</p>
<p>I am the exclusive rights holder or the duly authorized representative of the exclusive rights holder for the works listed above. These works infringe upon my original copyrighted works located at:</p>
<p>
<ul>
<li><b>List of links where the above works were originally posted on your social media accounts or personal websites.</b></li>
</ul>
</p>
<p>I have a good faith belief that the use of this material in such a fashion is not authorized by the copyright holder, the copyright holder's agent, or the law.</p>
<p>Under penalty of perjury in a United States court of law, I state that the information contained in this notification is accurate, and that I am authorized to act on the behalf of the exclusive rights holder for the material in question.</p>
<p>I may be contacted by the following methods: <b>[Full name, physical address, phone number, and email address]</b></p>
<p>Signed,</p>
<p><b>[Your full legal name]</b></p>
<hr class="border">
<p>Send the above notice <%= link_to "here", "mailto:#{Danbooru.config.dmca_email}" %>.</p>
</div>
</div>

View File

@@ -0,0 +1,22 @@
<p>Your DMCA notice has been submitted. Please allow up to 48 hours for it to be processed. You may not receive a response unless further information is needed from you. You may contact <%= Danbooru.config.dmca_email %> if you have any further questions.</p>
<p>Name: <%= @dmca[:name] %></p>
<p>Email: <%= @dmca[:email] %></p>
<p>Address: <%= @dmca[:address] %></p>
<p>Infringing URLs:</p>
<ul>
<% @dmca[:infringing_urls].to_s.split.each do |url| %>
<li><%= url %></li>
<% end %>
</ul>
<p>Original URLs:</p>
<ul>
<% @dmca[:original_urls].to_s.split.each do |url| %>
<li><%= url %></li>
<% end %>
</ul>
<p>Proof that you are the artist: <%= @dmca[:proof] %></p>
<p>Signature: <%= @dmca[:signature] %></p>

View File

@@ -91,6 +91,11 @@ module Danbooru
"webmaster@#{Danbooru.config.hostname}"
end
# The email address where DMCA complaints should be sent.
def dmca_email
"dmca@#{Danbooru.config.hostname}"
end
# The email address to use for Dmail notifications.
def notification_email
"notifications@#{Danbooru.config.hostname}"

View File

@@ -296,6 +296,9 @@ Rails.application.routes.draw do
get :diff
end
end
resource :dmca, only: [:create, :show] do
get :template
end
# Legacy Danbooru 1 API endpoints
get "/tag/index.xml", :controller => "legacy", :action => "tags", :format => "xml"

View File

@@ -0,0 +1,28 @@
require "test_helper"
class DmcasControllerTest < ActionDispatch::IntegrationTest
context "show action" do
should "work for anonymous users" do
get dmca_path
assert_response :success
end
end
context "create action" do
should "work" do
dmca = {
name: "John Doe",
email: "test@example.com",
address: "123 Fake Street",
infringing_urls: "https://example.com/1.html\nhttps://example.com/2.html",
original_urls: "https://google.com/1.html\nhttps://google.com/2.html",
proof: "source: me",
signature: "John Doe",
}
post dmca_path, params: { dmca: dmca }
assert_response :success
assert_emails 2
end
end
end

View File

@@ -1,21 +1,36 @@
class UserMailerPreview < ActionMailer::Preview
def dmail_notice
dmail = User.system.dmails.first
user = params[:id].present? ? User.find(params[:id]) : User.owner
dmail = Dmail.received.order(id: :desc).offset(279).first
UserMailer.dmail_notice(dmail)
end
def password_reset
user = User.find(params[:id])
user = params[:id].present? ? User.find(params[:id]) : User.owner
UserMailer.password_reset(user)
end
def email_change_confirmation
user = User.find(params[:id])
user = params[:id].present? ? User.find(params[:id]) : User.owner
UserMailer.email_change_confirmation(user)
end
def welcome_user
user = User.find(params[:id])
user = params[:id].present? ? User.find(params[:id]) : User.owner
UserMailer.welcome_user(user)
end
def dmca_complaint
dmca = {
name: "John Doe",
email: "test@example.com",
address: "123 Fake Street",
infringing_urls: "https://example.com/1.html\nhttps://example.com/2.html",
original_urls: "https://google.com/1.html\nhttps://google.com/2.html",
proof: "source: me",
signature: "John Doe",
}
UserMailer.with(dmca: dmca).dmca_complaint(to: dmca[:email])
end
end

View File

@@ -68,5 +68,22 @@ class UserMailerTest < ActionMailer::TestCase
assert_emails(0) { mail.deliver_now }
end
end
context "dmail_complaint method" do
should "work" do
dmca = {
name: "John Doe",
email: "test@example.com",
address: "123 Fake Street",
infringing_urls: "https://example.com/1.html\nhttps://example.com/2.html",
original_urls: "https://google.com/1.html\nhttps://google.com/2.html",
proof: "source: me",
signature: "John Doe",
}
mail = UserMailer.with(dmca: dmca).dmca_complaint(to: dmca[:email])
assert_emails(1) { mail.deliver_now }
end
end
end
end