#
# Indexes
#
-# users_auth_idx (auth_provider,auth_uid) UNIQUE
-# users_display_name_idx (display_name) UNIQUE
-# users_display_name_lower_idx (lower((display_name)::text))
-# users_email_idx (email) UNIQUE
-# users_email_lower_idx (lower((email)::text))
-# users_home_idx (home_tile)
+# users_auth_idx (auth_provider,auth_uid) UNIQUE
+# users_display_name_canonical_idx (lower(NORMALIZE(display_name, NFKC)))
+# users_display_name_idx (display_name) UNIQUE
+# users_email_idx (email) UNIQUE
+# users_email_lower_idx (lower((email)::text))
+# users_home_idx (home_tile)
#
class User < ApplicationRecord
validates :display_name, :presence => true, :length => 3..255,
:exclusion => %w[new terms save confirm confirm-email go_public reset-password forgot-password suspended]
validates :display_name, :if => proc { |u| u.display_name_changed? },
- :uniqueness => { :case_sensitive => false }
+ :normalized_uniqueness => { :case_sensitive => false }
validates :display_name, :if => proc { |u| u.display_name_changed? },
:characters => { :url_safe => true },
:whitespace => { :leading => false, :trailing => false }
+ validate :display_name_cannot_be_user_id_with_other_id, :if => proc { |u| u.display_name_changed? }
validates :email, :presence => true, :confirmation => true, :characters => true
validates :email, :if => proc { |u| u.email_changed? },
:uniqueness => { :case_sensitive => false }
before_save :update_tile
after_save :spam_check
+ generates_token_for :new_email, :expires_in => 1.week do
+ fingerprint
+ end
+
+ generates_token_for :password_reset, :expires_in => 1.week do
+ fingerprint
+ end
+
+ def display_name_cannot_be_user_id_with_other_id
+ display_name&.match(/^user_(\d+)$/i) do |m|
+ errors.add :display_name, I18n.t("activerecord.errors.messages.display_name_is_user_n") unless m[1].to_i == id
+ end
+ end
+
def to_param
display_name
end
user = find_by("email = ? OR display_name = ?", options[:username].strip, options[:username])
if user.nil?
- users = where("LOWER(email) = LOWER(?) OR LOWER(display_name) = LOWER(?)", options[:username].strip, options[:username])
+ users = where("LOWER(email) = LOWER(?) OR LOWER(NORMALIZE(display_name, NFKC)) = LOWER(NORMALIZE(?, NFKC))", options[:username].strip, options[:username])
user = users.first if users.count == 1
end