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:
15
app/controllers/dmcas_controller.rb
Normal file
15
app/controllers/dmcas_controller.rb
Normal 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
|
||||||
@@ -12,7 +12,7 @@ class ApplicationMailer < ActionMailer::Base
|
|||||||
default from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.contact_email}>", content_type: "text/html"
|
default from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.contact_email}>", content_type: "text/html"
|
||||||
default "Message-ID": -> { "<#{SecureRandom.uuid}@#{Danbooru.config.hostname}>" }
|
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
|
# 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
|
# 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)
|
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.perform_deliveries = user.can_receive_email?(require_verified_email: require_verified_email)
|
||||||
message
|
message
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.with_request(request)
|
def self.with_request(request, **params)
|
||||||
with(
|
with(
|
||||||
request: {
|
request: {
|
||||||
url: "#{request.method} #{request.url}",
|
url: "#{request.method} #{request.url}",
|
||||||
remote_ip: request.remote_ip.to_s,
|
remote_ip: request.remote_ip.to_s,
|
||||||
request_id: request.request_id.to_s,
|
request_id: request.request_id.to_s,
|
||||||
session_id: request.session.id.to_s,
|
session_id: request.session.id.to_s,
|
||||||
}
|
},
|
||||||
|
**params
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class UserMailer < ApplicationMailer
|
|||||||
def dmail_notice(dmail)
|
def dmail_notice(dmail)
|
||||||
@dmail = dmail
|
@dmail = dmail
|
||||||
@user = dmail.to
|
@user = dmail.to
|
||||||
mail(
|
mail_user(
|
||||||
@user,
|
@user,
|
||||||
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.notification_email}>",
|
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.notification_email}>",
|
||||||
subject: "#{Danbooru.config.canonical_app_name}: #{dmail.from.name} sent you a message",
|
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.
|
# The email sent when a user requests a password reset.
|
||||||
def password_reset(user)
|
def password_reset(user)
|
||||||
@user = user
|
@user = user
|
||||||
mail(
|
mail_user(
|
||||||
@user,
|
@user,
|
||||||
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.account_security_email}>",
|
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.account_security_email}>",
|
||||||
subject: "#{Danbooru.config.app_name} password reset request",
|
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.
|
# The email sent when a user changes their email address.
|
||||||
def email_change_confirmation(user)
|
def email_change_confirmation(user)
|
||||||
@user = user
|
@user = user
|
||||||
mail(
|
mail_user(
|
||||||
@user,
|
@user,
|
||||||
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.account_security_email}>",
|
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.account_security_email}>",
|
||||||
subject: "Confirm your email address",
|
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.
|
# The email sent when a new user signs up with an email address.
|
||||||
def welcome_user(user)
|
def welcome_user(user)
|
||||||
@user = user
|
@user = user
|
||||||
mail(
|
mail_user(
|
||||||
@user,
|
@user,
|
||||||
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.welcome_user_email}>",
|
from: "#{Danbooru.config.canonical_app_name} <#{Danbooru.config.welcome_user_email}>",
|
||||||
subject: "Welcome to #{Danbooru.config.app_name}! Confirm your email address",
|
subject: "Welcome to #{Danbooru.config.app_name}! Confirm your email address",
|
||||||
require_verified_email: false,
|
require_verified_email: false,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dmca_complaint(to:)
|
||||||
|
@dmca = params[:dmca]
|
||||||
|
mail(
|
||||||
|
from: Danbooru.config.dmca_email,
|
||||||
|
to: to,
|
||||||
|
subject: "DMCA complaint",
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
30
app/views/dmcas/create.html.erb
Normal file
30
app/views/dmcas/create.html.erb
Normal 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>
|
||||||
83
app/views/dmcas/show.html.erb
Normal file
83
app/views/dmcas/show.html.erb
Normal 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>
|
||||||
38
app/views/dmcas/template.html.erb
Normal file
38
app/views/dmcas/template.html.erb
Normal 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>
|
||||||
22
app/views/user_mailer/dmca_complaint.html.erb
Normal file
22
app/views/user_mailer/dmca_complaint.html.erb
Normal 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>
|
||||||
@@ -91,6 +91,11 @@ module Danbooru
|
|||||||
"webmaster@#{Danbooru.config.hostname}"
|
"webmaster@#{Danbooru.config.hostname}"
|
||||||
end
|
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.
|
# The email address to use for Dmail notifications.
|
||||||
def notification_email
|
def notification_email
|
||||||
"notifications@#{Danbooru.config.hostname}"
|
"notifications@#{Danbooru.config.hostname}"
|
||||||
|
|||||||
@@ -296,6 +296,9 @@ Rails.application.routes.draw do
|
|||||||
get :diff
|
get :diff
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
resource :dmca, only: [:create, :show] do
|
||||||
|
get :template
|
||||||
|
end
|
||||||
|
|
||||||
# Legacy Danbooru 1 API endpoints
|
# Legacy Danbooru 1 API endpoints
|
||||||
get "/tag/index.xml", :controller => "legacy", :action => "tags", :format => "xml"
|
get "/tag/index.xml", :controller => "legacy", :action => "tags", :format => "xml"
|
||||||
|
|||||||
28
test/functional/dmcas_controller.rb
Normal file
28
test/functional/dmcas_controller.rb
Normal 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
|
||||||
@@ -1,21 +1,36 @@
|
|||||||
class UserMailerPreview < ActionMailer::Preview
|
class UserMailerPreview < ActionMailer::Preview
|
||||||
def dmail_notice
|
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)
|
UserMailer.dmail_notice(dmail)
|
||||||
end
|
end
|
||||||
|
|
||||||
def password_reset
|
def password_reset
|
||||||
user = User.find(params[:id])
|
user = params[:id].present? ? User.find(params[:id]) : User.owner
|
||||||
UserMailer.password_reset(user)
|
UserMailer.password_reset(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_change_confirmation
|
def email_change_confirmation
|
||||||
user = User.find(params[:id])
|
user = params[:id].present? ? User.find(params[:id]) : User.owner
|
||||||
UserMailer.email_change_confirmation(user)
|
UserMailer.email_change_confirmation(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def welcome_user
|
def welcome_user
|
||||||
user = User.find(params[:id])
|
user = params[:id].present? ? User.find(params[:id]) : User.owner
|
||||||
UserMailer.welcome_user(user)
|
UserMailer.welcome_user(user)
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@@ -68,5 +68,22 @@ class UserMailerTest < ActionMailer::TestCase
|
|||||||
assert_emails(0) { mail.deliver_now }
|
assert_emails(0) { mail.deliver_now }
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user