users: require email verification for signups from proxies.

Require users who signup using proxies to verify their email addresses
before they can perform any edits. For verification purposes, the email
must be a nondisposable address from a whitelist of trusted email
providers.
This commit is contained in:
evazion
2020-03-24 02:18:37 -05:00
parent 5faa323729
commit b7bd6c8fdd
10 changed files with 83 additions and 2 deletions

View File

@@ -61,6 +61,7 @@ class UsersController < ApplicationController
def create
@user = authorize User.new(
last_ip_addr: CurrentUser.ip_addr,
requires_verification: IpLookup.new(CurrentUser.ip_addr).is_proxy?,
name: params[:user][:name],
password: params[:user][:password],
password_confirmation: params[:user][:password_confirmation]

View File

@@ -76,6 +76,11 @@ module EmailValidator
"#{name}@#{domain}"
end
def nondisposable?(address)
domain = Mail::Address.new(address).domain
domain.in?(Danbooru.config.email_domain_verification_list)
end
def undeliverable?(to_address, from_address: Danbooru.config.contact_email, timeout: 3)
mail_server = mx_domain(to_address, timeout: timeout)
mail_server.nil? || rcpt_to_failed?(to_address, from_address, mail_server, timeout: timeout)

View File

@@ -5,6 +5,10 @@ class IpLookup
attr_reader :ip_addr, :api_key, :cache_duration
def self.enabled?
Danbooru.config.ip_registry_api_key.present?
end
def initialize(ip_addr, api_key: Danbooru.config.ip_registry_api_key, cache_duration: 1.day)
@ip_addr = ip_addr
@api_key = api_key

View File

@@ -2,24 +2,33 @@ class EmailAddress < ApplicationRecord
# https://www.regular-expressions.info/email.html
EMAIL_REGEX = /\A[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\z/
belongs_to :user
belongs_to :user, inverse_of: :email_address
validates :address, presence: true, confirmation: true, format: { with: EMAIL_REGEX }
validates :normalized_address, uniqueness: true
validates :user_id, uniqueness: true
validate :validate_deliverable, on: :deliverable
after_save :update_user
def address=(value)
self.normalized_address = EmailValidator.normalize(value) || address
super
end
def nondisposable?
EmailValidator.nondisposable?(address)
end
def validate_deliverable
if EmailValidator.undeliverable?(address)
errors[:address] << "is invalid or does not exist"
end
end
def update_user
user.update!(is_verified: is_verified? && nondisposable?)
end
concerning :VerificationMethods do
def verifier
@verifier ||= Danbooru::MessageVerifier.new(:email_verification_key)

View File

@@ -63,6 +63,8 @@ class User < ApplicationRecord
opt_out_tracking
no_flagging
no_feedback
requires_verification
is_verified
)
has_bit_flags BOOLEAN_ATTRIBUTES, :field => "bit_prefs"

View File

@@ -39,7 +39,11 @@ class ApplicationPolicy
end
def unbanned?
user.is_member? && !user.is_banned?
user.is_member? && !user.is_banned? && verified?
end
def verified?
user.is_verified? || user.is_gold? || !user.requires_verification?
end
def policy(object)