ログイン処理を、Sentinelに変更します。ルートは前の手順ですでに作成済みなので、postに対するコントローラーの作成を行います。
(2016/11/8 エラーを withErrors で渡すように修正)
(2016/12/15 HTMLのID 'loginForm'がキャメルケースだったので、ケバブケースに修正)
(2016/12/21 テストにwantToを追加)
(2016/12/31 ログアウト後表示するページを home から login に変更)
ログイン
ログインのテストコードの作成
ログインに関する処理のテストコードを用意します。
まずは、ボタンを押すフォームを指定するためのIDをformタグに追加します。
- resources/views/auth/login.blade.php をエディターで開く
- 「<form」から始まる行を探して、以下のようにID属性を追加する
<form id="login-form" class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
続けて、Cestファイルを作成します。
- ターミナルから以下を実行して、ログイン用のCestファイルを作成
composer exec codecept g:cest functional Login
- tests/functional/LoginCest.php をエディターで開いて、以下のコードにする(2016/12/21 テストにwantToを追加)
<?php use Activation; use Sentinel; class LoginCest { // ユーザー情報 private $cre = [ 'name' => 'ログイン', 'email' => 'login@test.com', 'password' => 'password' ]; public function _before(FunctionalTester $I) { // ユーザーを登録 Sentinel::registerAndActivate($this->cre); } public function _after(FunctionalTester $I) { } // tests public function tryToTest(FunctionalTester $I) { // 無効なログインテスト $I->wantTo(' 未登録ユーザーのログイン失敗'); $I->amOnPage('/login'); $I->submitForm('#login-form', [ 'email' => 'nobody@test.com', 'password' => 'notentry' ]); $I->see(trans('sentinel.login_failed')); // ログインの成功テスト $I->wantTo(' ログイン動作の確認.'); $I->amOnPage('/login'); $I->submitForm('#login-form', $this->cre); $I->seeInCurrentUrl('/home'); } }
npm test でテストを走らせると、まずはエラーになります。機能を実装してテストが通るようにします。
必要なメッセージの追加
ログインに関連するメッセージを追加します。
- resources/lang/ja/sentinel.php をエディターで開く
- 以下のメッセージを追加
// ログイン関連 'not_activation' => 'ユーザー登録が完了していません。登録したメールアドレスに、登録確認用のメールを送信してあります。メールを開いて、リンクをクリックしてください。メールを紛失した場合は、下のリンクからメールを再送できます。', 'login_failed' => 'ログインに失敗しました。正しいメールアドレスとパスワードでログインしてください。', 'login_throttling' => 'ログイン失敗が規定回数を越えました。一定時間、IPを凍結します。',
ログイン処理の実装
既存のログイン処理のコードを、Sentinelに合わせて書き換えます。
アクティベーションされていない時や、ログイン失敗時の処理もまとめて作成します。アクティベーションされていない時には、アクティベーションコードの再送信をする指示をビューに投げていますが、この辺りの実装は後ほど行います。
- app/Http/Controllers/Auth/LoginController.php をエディターで開く
- ファイルの中身を、以下のように書き換える(エラーをwithErrorsで渡すように修正)
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; use Cartalyst\Sentinel\Checkpoints\NotActivatedException; use Cartalyst\Sentinel\Checkpoints\ThrottlingException; use Sentinel; class LoginController extends Controller { /** * Where to redirect users after login. * * @var string */ protected $redirectTo = '/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest', ['except' => 'logout']); } /** * ログイン処理 */ public function login(Request $request) { // バリデーション $this->validate($request, [ 'email' => 'required|email|max:255', 'password' => 'required|between:6,255', 'remember' => 'boolean', ]); // 認証処理 try { $this->userInterface = Sentinel::authenticate([ 'email' => $request['email'], 'password' => $request['password'] ], $request['remember']); } catch (NotActivatedException $notactivated) { return view('auth.login', [ 'resend_code' => $request['email'] ])->withErrors([trans('sentinel.not_activation')]); } catch (ThrottlingException $throttling) { return view('auth.login')->withErrors([trans('sentinel.login_throttling')."[あと".$throttling->getDelay()."秒]"]); } if (!$this->userInterface) { // エラー return view('auth.login')->withErrors([trans('sentinel.login_failed')]); } return redirect($this->redirectTo); } }
以上で、ログイン、未アクティベーション、IP凍結に対応しました。 npm test で実行したテストが成功します。また、 http://localhost:8000 を開いて、先に登録したユーザーでログインを試すと、今度は home ページに移動して、ログインが成功します。
ログアウト
ログアウトに対応させます。
テストの作成
テストはシンプルなので、Loginのものに実装します。
- tests/functional/LoginCest.php をエディターで開く
- tryToTest メソッドのログイン用のテストコードの下に、以下のコードを追加する(2016/12/21 テストにwantToを追加)
// POSTでログアウトテスト $I->wantTo(' ログアウトの動作確認.'); $I->amOnPage('/login'); $I->submitForm('#login-form', $this->cre); $I->submitForm('#logout-form', []); $I->seeInCurrentUrl('/login'); // GETでログアウトテスト $I->wantTo(' GETでのログアウトの動作確認.'); $I->amOnPage('/logout'); $I->seeInCurrentUrl('/login');
ルートの追加
ログアウトのルートを設定します。フォームからのリクエストは、postで送信されるので、getとpostの双方にルートを設定します。
- routes/web.php をエディターで開く
- 以下のルートをログイン関連の下あたりに追加する
// ログアウト用のルート
Route::match(['get', 'post'], 'logout', 'Auth\LoginController@logout')->name('logout');
コントローラーを追加する
コントローラーはシンプルなので、Loginのものに追加します。
- app/Http/Auth/LoginController.php
- 以下の変数をクラス内に追加する
/** * ログアウト後に表示するページ */ protected $logoutTo = '/login';
- 以下のlogoutメソッドをクラスに追加する(2016/12/31 ログアウト後のリダイレクト先を logoutTo に変更)
/**
* ログアウト処理
*/
protected function logout(Request $request) {
Sentinel::logout();
return redirect($this->logoutTo);
}
ログアウトの実装完了です。 npm test を実行して、成功することを確認して下さい。
以上で、ログインとログアウトが実装できました。 http://localhost:8000/ を開いて、ログインとログアウトを試してください。テストが通っているので、問題なく成功します。
これで最低限の流れは実装できました。残りは、アクティベーションコードの再送や、パスワードの対応などです。