0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

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

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

 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

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

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

エラーになった。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?