问题
I'm building an Rails 4 app with the authentication gem 'clearance'. I'm kind of stuck with the following problem:
When an user forgets his/her password and would like to set a new password, the user is not found. (but exist in DB), this is the server log:
Started PUT "/passwords/1?token=[FILTERED]" for 127.0.0.1 at 2013-08-10 21:00:58 +0200
Processing by PasswordsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "password_reset"=>"[FILTERED]", "token"=>"[FILTERED]", "id"=>"1"}
User Load (1.1ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL AND "users"."confirmation_token" = 'bcc6a5b49bc64628eff15bf92761fe1775ef252c' LIMIT 1
Rendered passwords/new.html.slim within layouts/application (0.9ms)
Rendered partials/_favicon_styles.html.slim (0.4ms)
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
Rendered partials/_navigation.html.slim (11.2ms)
Rendered partials/_notification.html.slim (0.1ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
Rendered partials/_footer.html.slim (1.0ms)
Filter chain halted as :forbid_non_existent_user rendered or redirected
Completed 200 OK in 38ms (Views: 33.0ms | ActiveRecord: 2.3ms)
But when a user is logged in, he or she can change password and also login works normally ..
I think the problem is in the query, I am sending the id with the form, but when the id reaches the query it says IS NULL. But I've struggled with it for hours, but can't find the solution.
Also is the 7 times request for cache a problem?
Thanks in advance!
Update
Changed the strong parameters and the 'find_user_by_id_and_confimatrion_token' method as followed:
def find_user_by_id_and_confirmation_token
Clearance.configuration.user_model.
find_by_id_and_confirmation_token params[:**id**], params[:token].to_s
end
This was :user_id, this is not the name of the params.
def password_reset_params
# if params.has_key? :user
# ActiveSupport::Deprecation.warn %{Since locales functionality was added, accessing params[:user] is no longer supported.}
# params[:user][:password]
# else
# params[:password_reset][:password]
# end
params.require(:password_reset).permit(:password_reset, :password, :token, :id)
end
But this throws in another error:
Started PUT "/passwords/1?token=[FILTERED]" for 127.0.0.1 at 2013-08-11 16:31:20 +0200
Processing by PasswordsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "password_reset"=>" [FILTERED]", "token"=>"[FILTERED]", "id"=>"1"}
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."confirmation_token" = 'd892a4698f5eff29e34378716ebd46414ad6e8cf' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."confirmation_token" = 'd892a4698f5eff29e34378716ebd46414ad6e8cf' LIMIT 1
(0.4ms) BEGIN
User Exists (1.0ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'user@test.nl' AND "users"."id" != 1) LIMIT 1
(0.4ms) ROLLBACK
Rendered passwords/edit.html.slim within layouts/application (1.2ms)
Rendered partials/_favicon_styles.html.slim (0.3ms)
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
Rendered partials/_navigation.html.slim (4.7ms)
Rendered partials/_notification.html.slim (0.1ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
Rendered partials/_footer.html.slim (0.4ms)
Completed 200 OK in 112ms (Views: 12.5ms | ActiveRecord: 4.1ms)
It says that the user already exists, and rollback the changes. Because this is an update, the user must exist.
Update 2
I'm still trying to fix this issue, here the difference between a logged in user who's editing their password, and via password forget method (not logged in)
Logged in user changing password
Started PATCH "/admin/users/1" for 127.0.0.1 at 2013-08-13 16:12:07 +0200
Processing by Admin::UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "user"=>{"password"=>" [FILTERED]", "password_confirmation"=>"[FILTERED]"}, "id"=>"1"}
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'f1078c2b74f6b3b3c9950b87a5b927db3f2bffcd' LIMIT 1
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1(0.4ms)
BEGIN
User Exists (1.0ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'info@netventief.nl' AND "users"."id" != 1) LIMIT 1
SQL (1.6ms) UPDATE "users" SET "encrypted_password" = $1, "updated_at" = $2 WHERE "users"."id" = 1 [["encrypted_password", "$2a$10$F4p6N0va/TY2nKOiXOSQ7e23NnHPyDytQZ6EvhtGd7FJ2oTMVFbSS"], ["updated_at", Tue, 13 Aug 2013 16:12:07 CEST +02:00]](12.6ms)
COMMIT
Rendered admin/users/edit.html.slim within layouts/application (8.7ms)
Rendered partials/_favicon_styles.html.slim (0.3ms)
Rendered partials/_olderbrowser.html (0.0ms)
Rendered partials/_navigation.html.slim (2.6ms)
Rendered partials/_notification.html.slim (0.1ms)
Rendered partials/_footer.html.slim (0.1ms)
Completed 200 OK in 167ms (Views: 23.0ms | ActiveRecord: 17.3ms)
User who is forgotten the password and would enter a new password
Started PUT "/passwords/1?token=[FILTERED]" for 127.0.0.1 at 2013-08-13 16:58:45 +0200
Processing by PasswordsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "user"=>{"password"=>"[FILTERED]"}, "token"=>"[FILTERED]", "id"=>"1"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."confirmation_token" = 'b198361b098c1bf110a2171dd7f00258d9ca9240' LIMIT 1
CACHE
(0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."confirmation_token" = 'b198361b098c1bf110a2171dd7f00258d9ca9240' LIMIT 1
(0.3ms)BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'info@netventief.nl' AND "users"."id" != 1) LIMIT 1
(0.2ms) ROLLBACK
Rendered passwords/edit.html.slim within layouts/application (1.4ms)
Rendered partials/_favicon_styles.html.slim (0.3ms)
Rendered partials/_olderbrowser.html (0.0ms)
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
Rendered partials/_navigation.html.slim (5.0ms)
Rendered partials/_notification.html.slim (0.1ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '' LIMIT 1
Rendered partials/_footer.html.slim (0.5ms)
Completed 200 OK in 102ms (Views: 14.7ms | ActiveRecord: 2.0ms)
Still expect the Put/Patch method and all the cache alerts. This seems pretty the same to me .. I have tried to use the patch http method, but it didn't help.
Update 3
Also my controller code, its pretty much the same as Clearance::PasswordsController. Removed methods that are not called by my problem.
require 'active_support/deprecation'
class PasswordsController < ApplicationController
skip_before_filter :authorize, :only => [:create, :edit, :new, :update]
before_filter :forbid_missing_token, :only => [:edit, :update]
before_filter :forbid_non_existent_user, :only => [:edit, :update]
def edit
@user = find_user_for_edit
render :template => 'passwords/edit'
end
def update
@user = find_user_for_update
if @user.update_attributes( password: password_reset_params )
sign_in @user
redirect_to url_after_update
else
flash_failure_after_update
render :template => 'passwords/edit'
end
end
private
def password_reset_params
if params.has_key? :user
ActiveSupport::Deprecation.warn %{Since locales functionality was added, accessing params[:user] is no longer supported.}
params[:user][:password]
else
params[:password_reset][:password]
end
end
def find_user_by_id_and_confirmation_token
Clearance.configuration.user_model.
find_by_id_and_confirmation_token params[:id], params[:token].to_s
end
def find_user_for_edit
find_user_by_id_and_confirmation_token
end
def find_user_for_update
find_user_by_id_and_confirmation_token
end
def forbid_missing_token
if params[:token].to_s.blank?
flash_failure_when_forbidden
render :template => 'passwords/new'
end
end
def forbid_non_existent_user
unless find_user_by_id_and_confirmation_token
flash_failure_when_forbidden
render :template => 'passwords/new'
end
end
end
回答1:
You should track down where the following SQL query is being triggered from:
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'info@netventief.nl' AND "users"."id" != 1) LIMIT 1
This is the line that is causing your save to fail. My guess is that you have a validation or some other callback on your User model that is firing when you are calling @user.update_attributes
. The validation/callback is failing, which is causing the save to fail.
回答2:
This is the line that is causing your save to fail. My guess is that you have a validation or some other callback on your User model that is firing when you are calling @user.update_attributes. The validation/callback is failing, which is causing the save to fail.
来源:https://stackoverflow.com/questions/18165559/rails-4-with-clearance-password-reset-issue