2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-04-27 02:47:36 +08:00
|
|
|
class UserEmail < ActiveRecord::Base
|
|
|
|
belongs_to :user
|
|
|
|
|
2017-10-25 13:02:18 +08:00
|
|
|
attr_accessor :skip_validate_email
|
2017-08-09 10:56:08 +08:00
|
|
|
|
2017-04-27 02:47:36 +08:00
|
|
|
before_validation :strip_downcase_email
|
|
|
|
|
2018-03-20 10:22:06 +08:00
|
|
|
validates :email, presence: true
|
2017-04-27 02:47:36 +08:00
|
|
|
validates :email, email: true, format: { with: EmailValidator.email_regex },
|
2017-08-09 10:56:08 +08:00
|
|
|
if: :validate_email?
|
2017-04-27 02:47:36 +08:00
|
|
|
|
2017-12-21 20:30:26 +08:00
|
|
|
validates :primary, uniqueness: { scope: [:user_id] }, if: [:user_id, :primary]
|
2018-01-04 15:37:26 +08:00
|
|
|
validate :user_id_not_changed, if: :primary
|
2018-03-20 10:22:06 +08:00
|
|
|
validate :unique_email
|
2017-04-27 02:47:36 +08:00
|
|
|
|
2020-04-14 12:16:30 +08:00
|
|
|
before_save :save_canonical
|
|
|
|
|
2018-07-03 19:51:22 +08:00
|
|
|
scope :secondary, -> { where(primary: false) }
|
|
|
|
|
2020-04-14 12:16:30 +08:00
|
|
|
def self.canonical(email)
|
|
|
|
name, domain = email.split('@', 2)
|
|
|
|
name = name.gsub(/\+.*/, '')
|
|
|
|
if ['gmail.com', 'googlemail.com'].include?(domain.downcase)
|
|
|
|
name = name.gsub('.', '')
|
|
|
|
end
|
|
|
|
"#{name}@#{domain}".downcase
|
|
|
|
end
|
|
|
|
|
2017-04-27 02:47:36 +08:00
|
|
|
private
|
|
|
|
|
2020-04-14 12:16:30 +08:00
|
|
|
def save_canonical
|
|
|
|
if SiteSetting.enforce_canonical_emails && self.will_save_change_to_email?
|
|
|
|
self.canonical_email = UserEmail.canonical(self.email)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-27 02:47:36 +08:00
|
|
|
def strip_downcase_email
|
|
|
|
if self.email
|
|
|
|
self.email = self.email.strip
|
|
|
|
self.email = self.email.downcase
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-08-09 10:56:08 +08:00
|
|
|
def validate_email?
|
2017-10-25 13:02:18 +08:00
|
|
|
return false if self.skip_validate_email
|
2017-04-27 02:47:36 +08:00
|
|
|
email_changed?
|
|
|
|
end
|
2018-01-04 15:37:26 +08:00
|
|
|
|
2018-03-20 10:22:06 +08:00
|
|
|
def unique_email
|
2020-04-14 12:16:30 +08:00
|
|
|
if self.will_save_change_to_email?
|
|
|
|
exists = self.class.where("lower(email) = ?", email).exists?
|
|
|
|
exists ||= SiteSetting.enforce_canonical_emails &&
|
|
|
|
self.class.where("canonical_email = ?", UserEmail.canonical(email)).exists?
|
|
|
|
|
|
|
|
if exists
|
|
|
|
self.errors.add(:email, :taken)
|
|
|
|
end
|
2018-03-20 10:22:06 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-01-04 15:37:26 +08:00
|
|
|
def user_id_not_changed
|
|
|
|
if self.will_save_change_to_user_id? && self.persisted?
|
|
|
|
self.errors.add(:user_id, I18n.t(
|
|
|
|
'active_record.errors.model.user_email.attributes.user_id.reassigning_primary_email')
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
2017-04-27 02:47:36 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: user_emails
|
|
|
|
#
|
2020-04-14 12:16:30 +08:00
|
|
|
# id :integer not null, primary key
|
|
|
|
# user_id :integer not null
|
|
|
|
# email :string(513) not null
|
|
|
|
# primary :boolean default(FALSE), not null
|
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
|
|
|
# canonical_email :string
|
2017-04-27 02:47:36 +08:00
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
2020-04-14 12:16:30 +08:00
|
|
|
# index_user_emails_on_canonical_email (canonical_email) WHERE (canonical_email IS NOT NULL)
|
2017-10-06 11:13:01 +08:00
|
|
|
# index_user_emails_on_email (lower((email)::text)) UNIQUE
|
2017-04-27 02:47:36 +08:00
|
|
|
# index_user_emails_on_user_id (user_id)
|
2018-07-16 14:18:07 +08:00
|
|
|
# index_user_emails_on_user_id_and_primary (user_id,primary) UNIQUE WHERE "primary"
|
2017-04-27 02:47:36 +08:00
|
|
|
#
|