[RUBY] (Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 12]

Premise

・ Rails tutorial is the 4th edition ・ This study is the 3rd lap (2nd lap after Chapter 9) ・ The author is a beginner who has done all of Progate.

Basic policy

・ If you read it, you will not understand it. ・ Search and summarize terms that you do not understand (at the bottom of the article, glossary). ・ Dive into what you do not understand. ・ Work on all exercises. ・ Do not copy chords as much as possible.

Authentication system development-The 6th and final chapter 12! The world has four consecutive holidays, but there are no holidays for studying. Let's do it all. Make constant efforts.   Click here for today's song. SUPERCAR "PLANET short ver." Good songs won't fade over the years.

[12.1.1 Password Resets controller exercise]

  1. At this point, make sure the test suite is green. → It is GREEN.

2. The named route in Table 12.1 states that _url should be used instead of _path. Why? Think about it. Tip: For the same reason as the account activation exercise (11.1.1.1). → Because you need the complete URL (absolute path).

[12.1.2 Exercise for setting a new password]

  1. Why is the form_for method in Listing 12.4 using: password_reset instead of @password_reset? Think about it. → Because there is no password_reset model. If you have a model, you can use that variable (@user, etc.), but this time there is no such variable.

[12.1.3 Exercise for resetting password with create action]

  1. Let's send a valid email address from the form (Fig. 12.6). What error message did you get? → ArgumentError in PasswordResetsController#create wrong number of arguments (given 1, expected 0)

2. Move to the console and check that the corresponding user object has reset_digest and reset_sent_at (although it is displayed as an error) as a result of sending in the previous exercise. Also, what are the respective values? → There was. following.

>> user = User.find_by(email: "[email protected]")
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "[email protected]"], ["LIMIT", 1]]
=> #<User id: 102, name: "kawa", email: "[email protected]", created_at: "2020-09-17 22:39:47",
 updated_at: "2020-09-20 04:23:52", password_digest: "$2a$10$kgv1Loz8fVDaaZvtUMtkZOUBnbCcHZNIBQBrgb18QMj...", remember_digest: nil, admin: false, activation_digest: "$2a$10$bmgQ2XztK7kgePhH8pVDiuKenXFDEl51XktqmfPUwHv...", activated: true, activated_at: "2020-09-17 22:40:33", 
reset_digest: "$2a$10$iuW.1GDheym2P5Nkuo7QUu7YjCs1DyooYonE0RY2lck...", reset_sent_at: "2020-09-20 04:23:52">

[12.2.1 Password reset email and template exercise]

  1. Let's preview the sent mail from the browser. What kind of information is displayed in the "Date" column? → Date: Sun, 20 Sep 2020 04:49:13 +0000

  2. Let's send a valid email address from the password reset form. Also, look at the Rails server logs to see what the outgoing emails are. → Below

----==_mimepart_5f66df073210_17841d9a2dc334fd
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

To reset your password click the link below:

https://545f54b8b0d74dfd8bcc26b33cb0f3fe.vfs.cloud9.us-east-2.amazonaws.com/password_resets/TaQ06fMRyqZk-wHJp8fnyw/edit?email=kawa%40kawa.com

This link will expire in two hours.

if you did not request your password to be reset, 
please ignore this email and your password will stay as it is.

3. Move to the console and search for the User object whose password was reset in the previous exercise. Once you find the object, let's check the reset_digest and reset_sent_at values that the object has. → Below

reset_digest: "$2a$10$JUgxhUTG.XKFk7BnZqfLHeU8fdUIU/cnMvBGaAs.RCX...", 
reset_sent_at: "2020-09-20 04:48:06">

[12.2.2 Test of sent mail] Exercise

  1. Try running only the mailer test. Is this test green? → GREEN at $ rails test test /mailers/user_mailer_test.rb

2. Let's confirm that the test turns red when the second CGI.escape in Listing 12.12 is deleted. → It was RED.

[12.3.1 Exercise to reset with edit action]

  1. Follow the procedure shown in 12.2.1.1 to find the outgoing mail from the Rails server log and find the link written there. Try viewing that link from your browser and see if it looks like Figure 12.11. → The Reset password screen is displayed.

2. Let's actually send the new password from the page displayed earlier. What are the results? → Unknown action The action 'update' could not be found for PasswordResetsController

[12.3.2 Exercise to update password]

  1. Display the link (obtained from the Rails server log) obtained in 12.2.1.1 on your browser, and intentionally send the password and confirmation strings by mistake. What error message do you get? → Password confirmation doesn't match Password

2. Go to the console and find the user object that sent the password reset. Once found, try getting the value of password_digest for that object. Next, enter a valid password from the password reset form and submit it (Fig. 12.13). If the password reset is successful, get the password_digest value again and make sure it is different from the value you got earlier. Tip: You need to get the new value through user.reload. → And when I try to reset the password, "SQLite3 :: BusyException: database is locked: commit transaction" appears. Refer to this article, it worked when I hit ActiveRecord :: Base.connection.execute ("BEGIN TRANSACTION; END;") in the Rails console. .. The result is below. It's different. Before change: \ $ 2a $ 10 $ kgv1Loz8fVDaaZvtUMtkZOUBnbCcHZNIBQBrgb18QMjyvnK.U3vlW After change: \ $ 2a $ 10 $ / lAIMLbkR84Zg0rBkVmcIeWn6u / UBEOaHGrU34rLR8ZMnmcIEomiu

[12.3.3 Exercise to test password reset]

  1. The create_reset_digest method in Listing 12.6 calls update_attribute twice, which means that it queries the database once for each row. Let's combine the update_attribute calls into a single update_columns call using the template shown in Listing 12.20 (this will allow us to query the database once). Also, run the test after the change and make sure it turns green. By the way, the code in Listing 12.20 also contains the answers to the exercises in the previous chapter (Listing 11.39). → Below

user.rb


  def create_reset_digest
    self.reset_token = User.new_token
    update_columns(reset_digest: User.digest(reset_token), reset_sent_at: Time.zone.now)
  end

2. Fill in the template in Listing 12.21 and cover the branching (Listing 12.16) that occurs when you reset the expired password with an integration test (response.body in the code in 12.21 is the HTML body of the page. A method that returns everything). There are several ways to test for expiration, but you can use the technique recommended in Listing 12.21 to check for the word "expired" in the body of the response (note that it's not case sensitive). .. → Below (What is / ~ / i? I don't know even if I look it up)

password_resets_test.rb


test "expired token" do
    get new_password_reset_path
    post password_resets_path,
        params: { password_reset: { email: @user.email } }
    
    @user = assigns(:user)
    @user.update_attribute(:reset_sent_at, 3.hours.ago)
    patch password_reset_path(@user.reset_token),
        params: { email: @user.email,
            user: { password:        "foobar",
              password_confirmation: "foobar" } }
    assert_response :redirect
    follow_redirect!
    assert_match /expired/i, response.body
  end

3. The policy of not being able to reset the password after 2 hours is a good security method. But there are still ways to make it better. For example, consider a password reset on a public (or shared) computer. Even if you log out and leave your desk, within 2 hours, you can display the password reset form from the computer history and update the password (and the login mechanism is broken through as it is). I will!). To solve this problem, let's add the code in Listing 12.22 and change the digest to nil after successfully resetting the password. → Just enter @ user.update_attribute (: reset_digest, nil).

4. Add a line to List 12.18 and write a test for the previous exercise. Tip: Let's combine the assert_nil method in Listing 9.25 with the user.reload method in Listing 11.33 to directly test the reset_digest attribute. → Only the relevant part is below

password_resets_test.rb


    #Valid password and password confirmation
    patch password_reset_path(user.reset_token),
        params: { email: user.email,
            user: { password:        "foobaz",
              password_confirmation: "foobaz" } }
    assert is_logged_in?
    assert_nil user.reload.reset_digest
    assert_not flash.empty?
    assert_redirected_to user

[12.4 Exercise of sending emails in a production environment]

Cut here! !! The reason is the same as the previous chapter! !!

Chapter 12 Summary

-Modeled with resources as in the previous chapter. -Reset_sent_at is also added to the User model to set an expiration date for the reset link (to use this as the reference time) -Hidden_field_tag retains the email address even after sending once (edit action). -Play an empty string with @ user.errors.add (: password,: blank).

Finally, the development of the authentication system is over. Even if you do so far, you will be familiar with terms such as tokens and digests. Even if you don't understand a little, if you eat and eat all the time, it will be digested and become bloody. Let's do our best. In the next chapter, we will implement the posting function!

Go to Chapter 13! Click here for Chapter 11 Click here for premise and author status for learning

A glossary that somehow captures the image

Not this time.

Recommended Posts

(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 1]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 14]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 12]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 5]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 3]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 4]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 8]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 6]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 13]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 9]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 10]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 7]
(Giri) A local government employee in his twenties works on a Rails tutorial [Chapter 2]
(Giri) A local government employee in his twenties works on a Rails tutorial [Introduction]
[Ruby on Rails Tutorial] Error in the test in Chapter 3
[Rails Tutorial Chapter 5] Create a layout
[Rails Struggle/Rails Tutorial] What you learned in Rails Tutorial Chapter 6
[Rails Struggle/Rails Tutorial] What you learned in Rails Tutorial Chapter 3
(Ruby on Rails6) Creating data in a table
[Rails tutorial] A memorandum of "Chapter 11 Account Activation"
rails tutorial Chapter 6
rails tutorial Chapter 1
rails tutorial Chapter 7
rails tutorial Chapter 5
rails tutorial Chapter 10
rails tutorial Chapter 9
rails tutorial Chapter 8
[Rails Tutorial Chapter 2] What to do when you make a mistake in the column name
Rails Tutorial Chapter 5 Notes
Rails Tutorial Chapter 10 Notes
Rails Tutorial Chapter 3 Notes
Rails Tutorial Chapter 3 Learning
Rails Tutorial Memorandum (Chapter 3, 3.1)
Rails Tutorial Chapter 4 Notes
Rails Tutorial Chapter 4 Learning
Rails Tutorial Chapter 1 Learning
Rails Tutorial Chapter 2 Learning
Rails Tutorial Chapter 8 Notes
Rails Tutorial Memorandum (Chapter 3, 3.3.2)
Difficulties in building a Ruby on Rails environment (Windows 10) (SQLite3)
How to display a graph in Ruby on Rails (LazyHighChart)
Apply CSS to a specific View in Ruby on Rails