railsチュートリアル第10章 ユーザーにログインを要求する

##認可
ウェブアプリケーションの文脈では、
認証（authentication）はサイトのユーザーを識別することであり、
認可（authorization）はそのユーザーが実行可能な操作を管理することです。

updateアクションには大きな穴がある。
ユーザーにログインを要求し、かつ自分以外のユーザー情報を変更できないように制御してみましょう。
###ユーザーにログインを要求する
####beforeフィルターにlogged_in_userを追加する
app/controllers/users_controller.rb

```rb
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  # before_actionメソッドを使って何らかの処理が実行される直前に
  # 特定のメソッドを実行する仕組み
  # :editと:updateアクションだけ
.
.
.
    # ログイン済みユーザーかどうか確認
    def logged_in_user
      unless logged_in?
      # もしも、評価が偽(false)であれば○○する
        flash[:danger] = "Please log in."
        # ログインされていなければメッセージを表示する
        redirect_to login_url
        # ログインページを表示させる
      end
    end
end
```

#####テスト
```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 17649
Started with run options --seed 49225

 FAIL["test_unsuccessful_edit", #<Minitest::Reporters::Suite:0x00007f5338811400 @name="UsersEditTest">, 0.08051444600096147]
 test_unsuccessful_edit#UsersEditTest (0.08s)
        expecting <"users/edit"> but rendering with <[]>
        test/integration/users_edit_test.rb:13:in `block in <class:UsersEditTest>'

 FAIL["test_successful_edit", #<Minitest::Reporters::Suite:0x0000557d37110f08 @name="UsersEditTest">, 0.0888614100003906]
 test_successful_edit#UsersEditTest (0.09s)
        expecting <"users/edit"> but rendering with <[]>
        test/integration/users_edit_test.rb:32:in `block in <class:UsersEditTest>'

  31/31: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.12748s
31 tests, 70 assertions, 2 failures, 0 errors, 0 skips
```
13行目```assert_template 'users/edit'```

32行目```assert_template 'users/edit'```

表示されないらしい。

editアクションやupdateアクションでログインを要求するようになったため、ログインしていないユーザーだとこれらのテストが失敗するようになったため

####テストユーザーでログインする
test/integration/users_edit_test.rb

```rb
 require 'test_helper'
 # test_helper.rbのパラメータ群を指定

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "unsuccessful edit" do
    log_in_as(@user)
.
.
.
  end
  
  test "successful edit" do
    log_in_as(@user)
    # ログインさせる
    get edit_user_path(@user)
    assert_template 'users/edit'
    name  = "Foo Bar"
    email = "foo@bar.com"
.
.
.
  end
end
```

#####テスト
```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 18369
Started with run options --seed 35897

  31/31: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.13056s
31 tests, 77 assertions, 0 failures, 0 errors, 0 skips
```
getリクエストを送ってもログインしていなければページが表示されない。

####セキュリティモデルを確認するためにbeforeフィルターをコメントアウトする
app/controllers/users_controller.rb

```rb
class UsersController < ApplicationController
  #before_action :logged_in_user, only: [:edit, :update]
  # before_actionメソッドを使って何らかの処理が実行される直前に
  # 特定のメソッドを実行する仕組み
  # ログインをさせる
  # :editと:updateアクションだけ
.
.
.
end
```

#####テスト
```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 18729
Started with run options --seed 19344

  31/31: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.80145s
31 tests, 77 assertions, 0 failures, 0 errors, 0 skips
```

####editとupdateアクションの保護に対するテストする
test/controllers/users_controller_test.rb

```rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest
  def setup
    @user = users(:michael)
    # テストユーザー
  end
  
  test "should get new" do
    get signup_path
    assert_response :success
  end
  
  test "should redirect edit when not logged in" do
    get edit_user_path(@user)
    assert_not flash.empty?
    # flashメッセージが空ではないかどうか？
    assert_redirected_to login_url
    # login_urlにリダイレクトできるか？
  end

  test "should redirect update when not logged in" do
    patch user_path(@user), params: { user: { name: @user.name,
                                              email: @user.email } }
    # ユーザー情報を上書き                                          
    assert_not flash.empty?
    assert_redirected_to login_url
  end

end
```
#####テスト
```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 19211
Started with run options --seed 27208

 FAIL["test_should_redirect_edit_when_not_logged_in", #<Minitest::Reporters::Suite:0x0000557d39d96730 @name="UsersControllerTest">, 1.666765893000047]
 test_should_redirect_edit_when_not_logged_in#UsersControllerTest (1.67s)
        Expected true to be nil or false
        test/controllers/users_controller_test.rb:16:in `block in <class:UsersControllerTest>'

 FAIL["test_should_redirect_update_when_not_logged_in", #<Minitest::Reporters::Suite:0x0000557d39dd59d0 @name="UsersControllerTest">, 1.6791209879993403]
 test_should_redirect_update_when_not_logged_in#UsersControllerTest (1.68s)
        Expected response to be a redirect to <http://www.example.com/login> but was a redirect to <http://www.example.com/users/762146111>.
        Expected "http://www.example.com/login" to be === "http://www.example.com/users/762146111".
        test/controllers/users_controller_test.rb:27:in `block in <class:UsersControllerTest>'

  33/33: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.78848s
33 tests, 81 assertions, 2 failures, 0 errors, 0 skips
```
#####わからない
``` Expected true to be nil or false ```
16行目assert_not flash.empty?
27行目assert_redirected_to login_url


修正後
#####テスト
```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 19244
Started with run options --seed 1774

  33/33: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.70367s
33 tests, 81 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.
デフォルトのbeforeフィルターは、すべてのアクションに対して制限を加えます。今回のケースだと、ログインページやユーザー登録ページにも制限の範囲が及んでしまうはずです（結果としてテストも失敗するはずです）。リスト 10.15のonly:オプションをコメントアウトしてみて、テストスイートがそのエラーを検知できるかどうか（テストが失敗するかどうか）確かめてみましょう。

```
ubuntu:~/environment/sample_app (updating-users) $ rails t
Running via Spring preloader in process 20218
Started with run options --seed 60077

 FAIL["test_should_get_new", #<Minitest::Reporters::Suite:0x00007f5338f52188 @name="UsersControllerTest">, 0.09008692899988091]
 test_should_get_new#UsersControllerTest (0.09s)
        Expected response to be a <2XX: success>, but was a <302: Found> redirect to <http://www.example.com/login>
        Response body: <html><body>You are being <a href="http://www.example.com/login">redirected</a>.</body></html>
        test/controllers/users_controller_test.rb:11:in `block in <class:UsersControllerTest>'

 FAIL["test_layout_links", #<Minitest::Reporters::Suite:0x0000557d39aac218 @name="SiteLayoutTest">, 1.471755246999237]
 test_layout_links#SiteLayoutTest (1.47s)
        Expected at least 1 element matching "title", found 0..
        Expected 0 to be >= 1.
        test/integration/site_layout_test.rb:18:in `block in <class:SiteLayoutTest>'

 FAIL["test_invalid_signup_information", #<Minitest::Reporters::Suite:0x0000557d39af55f8 @name="UsersSignupTest">, 1.4869099379993713]
 test_invalid_signup_information#UsersSignupTest (1.49s)
        expecting <"users/new"> but rendering with <[]>
        test/integration/users_signup_test.rb:17:in `block in <class:UsersSignupTest>'

 FAIL["test_valid_signup_information", #<Minitest::Reporters::Suite:0x0000557d39b3f568 @name="UsersSignupTest">, 1.4974412970004778]
 test_valid_signup_information#UsersSignupTest (1.50s)
        "User.count" didn't change by 1.
        Expected: 2
          Actual: 1
        test/integration/users_signup_test.rb:22:in `block in <class:UsersSignupTest>'

  33/33: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.56975s
33 tests, 79 assertions, 4 failures, 0 errors, 0 skips
```
エラーになった。