RoR Devise: Войдите в систему с именем пользователя или по электронной почте
Какой лучший способ разрешить пользователям регистрироваться с их адресом электронной почты или их именем? Я использую warden + devise для аутентификации. Я думаю, что, вероятно, это будет не слишком сложно сделать, но я думаю, мне нужен совет, где можно разместить все необходимое. Возможно, разработка уже предоставляет эту функцию? Как и в config/initializers/devise.rb, вы должны написать:
config.authentication_keys = [ :email, :username ]
Требовать как имя пользователя, так и адрес электронной почты для входа. Но я действительно хочу иметь только одно поле для имени пользователя и электронной почты и для этого требуется только один из них. Я просто визуализирую, что с некоторым искусством ASCII в представлении должно выглядеть примерно так:
Username or Email:
[____________________]
Password:
[____________________]
[Sign In]
Ответы
Ответ 1
Я нашел решение проблемы. Я не совсем доволен этим (я бы предпочел бы указать это в инициализаторе), но теперь он работает. В пользовательской модели я добавил следующий метод:
def self.find_for_database_authentication(conditions={})
find_by(username: conditions[:email]) || find_by(email: conditions[:email])
end
Как отмечали @sguha и @Chetan, еще один отличный ресурс доступен в официальной вики-разработке.
Ответ 2
Из их Wiki - Как разрешить пользователям войти в систему, используя свое имя пользователя или адрес электронной почты.
Ответ 3
def self.find_for_authentication(conditions)
conditions = ["username = ? or email = ?", conditions[authentication_keys.first], conditions[authentication_keys.first]]
# raise StandardError, conditions.inspect
super
end
Используйте свой пример!
Ответ 4
Убедитесь, что вы уже добавили имя пользователя и добавили имя пользователя в attr_accessible.
Создайте виртуальный атрибут входа в "Пользователи"
1) Добавить логин как attr_accessor
# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login
2) Добавить логин в attr_accessible
attr_accessible :login
Скажите, что использовать: login в файлах authentication_keys
Измените config/initializers/devise.rb, чтобы иметь:
config.authentication_keys = [ :login ]
Перезаписать метод find_for_database_authentication в Users
# Overrides the devise method find_for_authentication
# Allow users to Sign In using their username or email address
def self.find_for_authentication(conditions)
login = conditions.delete(:login)
where(conditions).where(["username = :value OR email = :value", { :value => login }]).first
end
Обновить список просмотров
Удостоверьтесь, что у вас есть представления в вашем проекте, чтобы вы могли их настроить.
remove <%= f.label :email %>
remove <%= f.email_field :email %>
add <%= f.label :login %>
add <%= f.text_field :login %>
Ответ 5
https://gist.github.com/867932: одно решение для всего. Войдите, забыли пароль, подтверждение, инструкции по разблокировке.
Ответ 6
Platforma Tec (разработчик автор) опубликовал решение своей вики-библиотеки github, которая использует базовую стратегию аутентификации Warden, а не подключается к контроллеру:
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
(Более ранний ответ имел сломанную ссылку, которая, как мне кажется, была предназначена для ссылки на этот ресурс.)
Ответ 7
Если вы используете MongoDB (с MongoId), вам нужно запросить по-другому:
def self.find_for_database_authentication(conditions={})
self.any_of({name: conditions[:email]},{email: conditions[:email]}).limit(1).first
end
просто так будет где-то в сети.
Ответ 8
С помощью squeel gem вы можете сделать:
def self.find_for_authentication(conditions={})
self.where{(email == conditions[:email]) | (username == conditions[:email])}.first
end
Ответ 9
Здесь находится решение Rails, которое рефакторирует @padde. Он использует ActiveRecord find_by для упрощения вызовов, обеспечивает только один вызов на основе регулярного выражения, а также поддерживает числовые идентификаторы, если вы хотите разрешить это (полезно для скриптов /API ). Регулярное выражение для электронной почты так же просто, как и должно быть в этом контексте; просто проверяя наличие @, поскольку я предполагаю, что ваш идентификатор имени пользователя не позволяет @символов.
def self.find_for_database_authentication(conditions={})
email = conditions[:email]
if email =~ /@/
self.find_by_email(email)
elsif email.to_s =~ /\A[0-9]+\z/
self.find(Integer(email))
else
self.find_by_username(email])
end
end
Как и wiki и @aku, я также рекомендую создать новый параметр login с использованием attr_accessible и authentication_keys вместо использования: здесь. (Я сохранил его как: email в этом примере, чтобы показать быстрое исправление.)
Ответ 10
Я написал вот так, и это сработает. Не знаю, будет ли это "уродливое исправление", но если я придумаю лучшее решение, я дам вам знать...
def self.authenticate(email, password)
user = find_by_email(email) ||
username = find_by_username(email)
if user && user.password_hash = BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
Ответ 11
Я использую быстрый взлом для этого, чтобы избежать изменения какого-либо кода определенного кода и использовать его для моего конкретного сценария (я особенно использую его для API, где мобильные приложения могут создавать пользователей на сервере).
Я добавил файл before_filter для всех контроллеров разработки, где, если имя пользователя передается, я генерирую электронное письмо от имени пользователя ( "# {params [: user] [: username]} @mycustomdomain.com" ) и сохраняю пользователь. Для всех других вызовов я генерирую электронное письмо на основе той же логики. Мой before_filter выглядит следующим образом:
def generate_email_for_username
return if(!params[:user][:email].blank? || params[:user][:username].blank?)
params[:user][:email] = "#{params[:user][:username]}@mycustomdomain.com"
end
Я также сохраняю имя пользователя в таблице users, поэтому я знаю, что пользователи с электронной почтой, заканчивающиеся на @mycustomdomain.com, были созданы с использованием имени пользователя.