Ad Rienks
Ad Rienks

Reputation: 410

Michael Hartl's Rails Tutorial: Figure 12.11: The password reset form

In the tutorial (4th edition, for Rails 5) I've come to chapter 12. If the password is forgotten, the password can be reset. I checked and double-checked my code, also compared it to the files in Bitbucket by Michael: https://bitbucket.org/railstutorial/sample_app_4th_ed/src/6c255b27f7c7935dd9b04f28d3a249af8618242f/?at=password-reset

What happens? After the password reset email is send (no problems there, afaik), the text says" following the link from Listing 12.11 should render a password reset form. The result appears in Figure 12.11."

However, the reset form does not show up; instead I am immediately redirected to the root, with no message or error.

I found a similar question asked before, but could not figure out what the solution was; where to look for mistakes?

I still can be considered to be a newby, unfortunately, I have no real clue how to solve this....

Thank you for any help, Ad

The answer is helpful, however, does not yet help me enough; I will edit with more information: (in $ rails console) I entered:

>> User.find_by(email: "[email protected]") User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]] => #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2016-07-28 22:52:07", updated_at: "2016-08-03 16:51:52", password_digest: "$2a$10$IFxi0SPvA/I4rY53g.PrF.Ihxgb9.KtZpC2jcjWLgqk...", remember_digest: nil, admin: true, activation_digest: "$2a$10$J49AUluY8tSVExQBeDeCoO3U8bCHgNEgNjMyVtFmzT6...", activated: true, activated_at: "2016-07-28 22:52:06", reset_digest: "$2a$10$GGExFYbJIqhqSZq.Nc7hUeJhnbTRmtPjsAd89K99X8L...", reset_sent_at: "2016-08-03 16:51:52">

You see that this "Example User" is activated, and that a reset is sent. The 'problem' (or challenge) thus lies in the authenticated?(attribute, token) method; isn't that obvious?

How can I look into the 'inner workings' of this method? For me as a newbie, I am breaking my head how this could be done.

pry is new for me; Hartl's tutorial does not mention this, till now. The only possible option I have seen, is debugger. Could that be used?

Another question, about :reset What exactly is this? A symbol? But what is the symbol representing? Does it refer to a method, a variable, inbuilt?

I was thinking, maybe more debug information could be put on the screen? For instance, in app/views/layouts/application.html.erb if have this line:

<%= debug(params) if Rails.env.development? %>

Could that be enhanced?

Update: I found out that the screen from figure 12.11 does show up, when I comment out the last line: redirect_to root_url

Upvotes: 4

Views: 323

Answers (3)

Goku San
Goku San

Reputation: 91

The thing is that -- @user.authenticated?(:reset, params[:id]) -- is evaluated as false, because of a typo that I had in my code in user.rb create_reset_digest method. The part where you update the attribute User.digest(:reset_token) --> was, should be --> User.digest(reset_token) --, without " : ", so for anyone that stumbles on this look for typo in the code, because the code works...

Upvotes: 0

Maurus Vitor
Maurus Vitor

Reputation: 31

I got this same scenario too as I follow the hartl's tutorial(rails 5 version). In my case, I found out that I was being redirected to the root_url because the email I was using was for a user that wasn't activated yet (making @user.activated? == false)

I guess, this kind of unexpected behavior happens because sometimes we test using data from a database that we seed ourselves in development mode, that we do not notice that we have left out some processes an account goes through in production mode.

the first answer was informative to me, which prompt me to use the rails console to type each condition and know its value. again in my case, @user was true, but @user.activated? was false.

What I did next was restructure the valid_user method with flash messages:

def valid_user
    if @user
      if @user.activated?
        unless @user.authenticated?(:reset, params[:id])
          flash[:danger] = "Reset token do not match."
          redirect_to root_url
        end
      else
        flash[:danger] = "User is not yet activated."
        redirect_to root_url
      end
    else
      flash[:danger] = "User does not exist."
      redirect_to root_url
    end
end

Now I know what invalidates the user. And so that, in the future, if ever every else cases will still happen in production mode, I have an idea where the issues starts.

In my case, I was unknowingly at first trying to reset the password of a user account that didn't go through activation yet. I would want to make the system not send an email if the account is not activated yet, and I might like to send an email for a notice for an activation first to inform the user to activate their account first before even changing their password.

But that's for another production cycle, which the Rails tutorial had left out because this is the initial cycle of password reset functionality and some other secondary scenarios is for you, the developer, to decide.

Upvotes: 1

SteveTurczyn
SteveTurczyn

Reputation: 36860

In the app/controllers/passwords_resets_controller.rb notice that there's a few before_action calls for the edit action. One of them is...

  before_action :valid_user,       only: [:edit, :update]

   def valid_user
      unless (@user && @user.activated? &&
              @user.authenticated?(:reset, params[:id]))
        redirect_to root_url
      end
    end

the redirect_to root_url is exactly the problem you're encountering, so it must be that (a) there's no @user found, or (b) @user.activated? is not true or (c) @user.authenticated?(:reset, params[:id]) is not true.

So to solve this, you'll need to find out which of those conditions are failing and then find out why. You can do this with pry (I don't know if the Hartl tutorial covers pry) or you may want to set up some Rails.logger.info lines to inspect the variables.

Upvotes: 1

Related Questions