Refactor email verification links and Dmail share links to use the new Rails signed_id mechanism, rather than our own handrolled mechanism. For Dmail share links, we have to override some Rails internal methods so that our old links still work. For email verification links, this will invalidate existing links, but this isn't a huge deal since these links are short-lived anyway. https://api.rubyonrails.org/classes/ActiveRecord/SignedId.html https://api.rubyonrails.org/classes/ActiveRecord/SignedId/ClassMethods.html
76 lines
1.9 KiB
Ruby
76 lines
1.9 KiB
Ruby
class EmailAddress < ApplicationRecord
|
|
belongs_to :user, inverse_of: :email_address
|
|
|
|
validates :address, presence: true, confirmation: true, format: { with: EmailValidator::EMAIL_REGEX }
|
|
validates :normalized_address, uniqueness: true
|
|
validates :user_id, uniqueness: true
|
|
validate :validate_deliverable, on: :deliverable
|
|
|
|
def self.visible(user)
|
|
if user.is_moderator?
|
|
where(user: User.where("level < ?", user.level).or(User.where(id: user.id)))
|
|
else
|
|
none
|
|
end
|
|
end
|
|
|
|
def address=(value)
|
|
self.normalized_address = EmailValidator.normalize(value) || address
|
|
super
|
|
end
|
|
|
|
def is_restricted?
|
|
EmailValidator.is_restricted?(normalized_address)
|
|
end
|
|
|
|
def is_normalized?
|
|
address == normalized_address
|
|
end
|
|
|
|
def is_valid?
|
|
EmailValidator.is_valid?(address)
|
|
end
|
|
|
|
def self.restricted(restricted = true)
|
|
domains = Danbooru.config.email_domain_verification_list
|
|
domain_regex = domains.map { |domain| Regexp.escape(domain) }.join("|")
|
|
|
|
if restricted.to_s.truthy?
|
|
where_not_regex(:normalized_address, "@(#{domain_regex})$")
|
|
elsif restricted.to_s.falsy?
|
|
where_regex(:normalized_address, "@(#{domain_regex})$")
|
|
else
|
|
all
|
|
end
|
|
end
|
|
|
|
def self.search(params)
|
|
q = search_attributes(params, :id, :created_at, :updated_at, :user, :address, :normalized_address, :is_verified, :is_deliverable)
|
|
|
|
q = q.restricted(params[:is_restricted])
|
|
q = q.apply_default_order(params)
|
|
|
|
q
|
|
end
|
|
|
|
def validate_deliverable
|
|
if EmailValidator.undeliverable?(address)
|
|
errors.add(:address, "is invalid or does not exist")
|
|
end
|
|
end
|
|
|
|
def verify!
|
|
transaction do
|
|
update!(is_verified: true)
|
|
|
|
if user.is_restricted? && !is_restricted?
|
|
user.update!(level: User::Levels::MEMBER, is_verified: is_verified?)
|
|
end
|
|
end
|
|
end
|
|
|
|
def verification_key
|
|
signed_id(purpose: "verify")
|
|
end
|
|
end
|