在我的网络应用程序上使用 Rails 4 和 Devise 3.1.0。我写了一个 Cucumber 测试来测试用户注册;当从电子邮件中单击“确认我的帐户”链接时,它会失败。
Scenario: User signs up with valid data # features/users/sign_up.feature:9
When I sign up with valid user data # features/step_definitions/user_steps.rb:87
Then I should receive an email # features/step_definitions/email_steps.rb:51
When I open the email # features/step_definitions/email_steps.rb:76
Then I should see the email delivered from "no-reply@mysite.com" # features/step_definitions/email_steps.rb:116
And I should see "You can confirm your account email through the link below:" in the email body # features/step_definitions/email_steps.rb:108
When I follow "Confirm my account" in the email # features/step_definitions/email_steps.rb:178
Then I should be signed in # features/step_definitions/user_steps.rb:142
expected to find text "Logout" in "...Confirmation token is invalid..." (RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/user_steps.rb:143:in `/^I should be signed in$
当我也通过 Web 服务器手动注册时,此错误是可重现的,因此它似乎不是 Cucumber 问题。
我想:
- 用户能够通过此电子邮件的链接一键确认他们的帐户
- 让用户在确认其帐户后保持登录状态
我有设置:
- 最新的设计代码,来自 GitHub (3.1.0, ref 041fcf90807df5efded5fdcd53ced80544e7430f)
- 一个
User
实现的类confirmable
- 使用“默认”确认控制器(我还没有定义自己的自定义控制器。)
我读过这些帖子:
并尝试过:
- 在我的 Devise 初始化程序中设置
config.allow_insecure_tokens_lookup = true
,它在启动时会引发“未知方法”错误。另外,这听起来应该只是一个临时修复,所以我想避免使用它。 - 清除我的数据库并从头开始(因此不存在旧令牌)
更新:
检查User
注册后存储的确认令牌。emails 令牌与 DBs 令牌匹配。根据上面的帖子,新的设计行为说不应该,而是应该根据电子邮件的令牌生成第二个令牌。这是可疑的。运行User.confirm_by_token('[EMAIL_CONFIRMATION_TOKEN]')
返回的用户设置了错误“@messages={:confirmation_token=>["is invalid"]}”,这似乎是问题的根源。
不匹配的代币似乎是问题的核心;在控制台中运行以下代码以手动更改用户的确认令牌会导致确认成功:
new_token = Devise.token_generator.digest(User, :confirmation_token, '[EMAIL_TOKEN]')
u = User.first
u.confirmation_token = new_token
u.save
User.confirm_by_token('[EMAIL_TOKEN]') # Succeeds
那么为什么它首先将错误的确认令牌保存到数据库中呢?我正在使用自定义注册控制器......也许其中有一些东西导致它设置不正确?
路线.rb
devise_for :users,
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
},
:controllers => {
:registrations => "users/registrations",
:sessions => "users/sessions"
}
用户/registrations_controller.rb:
class Users::RegistrationsController < Devise::RegistrationsController
def create
# Custom code to fix DateTime issue
Utils::convert_params_date_select params[:user][:profile_attributes], :birthday, nil, true
super
end
def sign_up_params
# TODO: Still need to fix this. Strong parameters with nested attributes not working.
# Permitting all is a security hazard.
params.require(:user).permit!
#params.require(:user).permit(:email, :password, :password_confirmation, :profile_attributes)
end
private :sign_up_params
end