Rails 5、设计、Omniauth、推特
Rails 5, Devise, Omniauth, Twitter
我知道这个问题已经被问过很多次了,但我从来没有完全接受答案。
所以我正在关注 Ryan Bates' Railscast about this topic, and mixing that with the official Devise Omniauth guide(基于 FB),但我只是没有让它像我期望的那样工作,所以我希望得到一些帮助。
我有一个 Users::OmniauthCallbacksController
看起来像这样:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
@user = User.from_omniauth(request.env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect root_path, :event => :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
else
session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages
redirect_to new_user_registration_url
end
end
alias_method :twitter, :all
def failure
redirect_to root_path
end
end
那我的User.rb
也有两个方法
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.update(
email: auth.info.email,
password: Devise.friendly_token[0,20],
username: auth.info.nickname,
remote_avatar_url: auth.info.image,
token: auth.credentials.token,
secret: auth.credentials.secret
)
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.twitter_data"]
# user.attributes = params
user.update(
email: params[:email],
password: Devise.friendly_token[0,20],
username: data["info"]["nickname"],
remote_avatar_url: data["info"]["image"],
token: data["credentials"]["token"],
secret: data["credentials"]["secret"]
)
end
end
end
我运行陷入各种问题。最直接的是因为我正在设置密码,用户在尝试登录时不知道密码(而且我不会在确认后自动登录)。
但是如果我不设置密码,它不会要求他们设置密码...所以这也有点奇怪。
这些是我在 User
型号上的设计设置:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable, :omniauth_providers => [:twitter]
validates :username,
presence: true,
uniqueness: {
case_sensitive: false
}
validate :validate_username
def validate_username
if User.where(email: username).exists?
errors.add(:username, :invalid)
end
end
所以我的问题是,当有人通过 Twitter 注册时,他们需要输入密码吗?无论如何,我都会自动将它们发送到 registration/new.html.erb
,因为 Twitter 没有 return 电子邮件值。但在优化之前,我试图先让流程正常工作。
如何处理密码问题?
编辑 1
为了更清楚起见,无论 OAuth 提供商如何,我都必须处理这个 password_required
问题。
那么如何覆盖所有 OAuth 提供商的要求?
您应该将 the following method 添加到 User
class:
def password_required?
(provider.blank? || uid.blank?) && super
end
由于 Twitter 没有 return 用户的电子邮件,您可能还想 tweak that email validation,但是像您已经在做的那样将用户重定向到 registration/new.html.erb
似乎是正确的方法对我来说。
我知道这个问题已经被问过很多次了,但我从来没有完全接受答案。
所以我正在关注 Ryan Bates' Railscast about this topic, and mixing that with the official Devise Omniauth guide(基于 FB),但我只是没有让它像我期望的那样工作,所以我希望得到一些帮助。
我有一个 Users::OmniauthCallbacksController
看起来像这样:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
@user = User.from_omniauth(request.env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect root_path, :event => :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
else
session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages
redirect_to new_user_registration_url
end
end
alias_method :twitter, :all
def failure
redirect_to root_path
end
end
那我的User.rb
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.update(
email: auth.info.email,
password: Devise.friendly_token[0,20],
username: auth.info.nickname,
remote_avatar_url: auth.info.image,
token: auth.credentials.token,
secret: auth.credentials.secret
)
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.twitter_data"]
# user.attributes = params
user.update(
email: params[:email],
password: Devise.friendly_token[0,20],
username: data["info"]["nickname"],
remote_avatar_url: data["info"]["image"],
token: data["credentials"]["token"],
secret: data["credentials"]["secret"]
)
end
end
end
我运行陷入各种问题。最直接的是因为我正在设置密码,用户在尝试登录时不知道密码(而且我不会在确认后自动登录)。
但是如果我不设置密码,它不会要求他们设置密码...所以这也有点奇怪。
这些是我在 User
型号上的设计设置:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable, :omniauth_providers => [:twitter]
validates :username,
presence: true,
uniqueness: {
case_sensitive: false
}
validate :validate_username
def validate_username
if User.where(email: username).exists?
errors.add(:username, :invalid)
end
end
所以我的问题是,当有人通过 Twitter 注册时,他们需要输入密码吗?无论如何,我都会自动将它们发送到 registration/new.html.erb
,因为 Twitter 没有 return 电子邮件值。但在优化之前,我试图先让流程正常工作。
如何处理密码问题?
编辑 1
为了更清楚起见,无论 OAuth 提供商如何,我都必须处理这个 password_required
问题。
那么如何覆盖所有 OAuth 提供商的要求?
您应该将 the following method 添加到 User
class:
def password_required?
(provider.blank? || uid.blank?) && super
end
由于 Twitter 没有 return 用户的电子邮件,您可能还想 tweak that email validation,但是像您已经在做的那样将用户重定向到 registration/new.html.erb
似乎是正确的方法对我来说。