ユーザー認証の仕上げに、アクティベーションコードの再送機能を追加します。アクティベーションコードには有効期限があるので、一定時間がすぎると利用できなくなります。また、ユーザーがメールを削除してしまう可能性もあるので、コードの再発行が必要となります。
(2016/12/21 テストにwantToを追加)
方針
アクティベーションコードを再送信する方針は以下の通りです。
- ルートはgetメソッドの register/{email}
- 古くなったアクティベーションを削除
- ユーザーが登録済みで、かつ、未アクティベーションの場合のみ機能させる
- 有効なアクティベーションコードがない場合は、再度生成
- メールを送信
- ログインページにリダイレクトする
テストを準備
先に作成していた ActivationUserCest に追加します。
- tests/functional/ActivationUserCest.php をエディターで開く
- tryToTest メソッドの最初に、以下のコードを追加(アクティベーション済みの場所ではテストにならないので)(2016/12/21 expectをwantToに変更)
// アクティベーションの再送チェック $I->wantTo(' アクティベーションコードの再送.'); $url = url('register', [base64_encode($this->cre['email'])]); $I->amOnPage($url); $I->seeInCurrentUrl('/login'); $I->see(trans('sentinel.after_register')); // アクティベーションで無効なemail $I->wantTo(' 無効なメールアドレスでの要求に対してエラーを確認.'); $url = url('register', [base64_encode('nobody@test.com')]); $I->amOnPage($url); $I->seeInCurrentUrl('/login'); $I->see(trans('sentinel.invalid_activation_params'));
- 登録済みのテストもしたいので、tryToTestメソッドの最後に以下のコードを追加
// アクティベーションの再送チェック $I->wantTo(' アクティベーション済みに対する再送を確認.'); $url = url('register', [base64_encode($this->cre['email'])]); $I->amOnPage($url); $I->seeInCurrentUrl('/login'); $I->see(trans('sentinel.activation_done'));
上書きして、 npm test をターミイナルで実行してください。まだルートや処理がないので、エラーが発生します。実装を進めて、エラーをなくします。
ルートの作成
ルートを追加します。
- routes/web.php をエディターで開く
- Route::get('register', ・・・);の上に、以下のコードを追加する
Route::get('register/{email}', 'Auth\RegisterController@resendActivationCode');
コントローラーの作成
コントローラーを作成します。メールは、先に作成済みの RegisterNotify をそのまま利用します。
- app/Http/Controller/Auth/RegisterController.php をエディターで開く
- 以下の関数を、クラスに追加する
/** * 指定のメールアドレスのアクティベーションコードを再送する */ protected function resendActivationCode(Request $request) { // 古いアクティベーションコードを削除 Activation::removeExpired(); // ユーザーを確認 $user = Sentinel::findByCredentials(['email' => base64_decode($request->email)]); if (is_null($user)) { return redirect('login')->with(['myerror' => trans('sentinel.invalid_activation_params')]); } // すでにアクティベート済みの時は、何もせずにログインへ if (Activation::completed($user)) { return redirect('login')->with(['info' => trans('sentinel.activation_done')]); } // アクティベーションの状況を確認 $exists = Activation::exists($user); if (!$exists) { // 存在しない場合は、再生成して、そのコードを送信する $activation = Activation::create($user); } else { // 現在のコードを $activation = $exists; } // メールで送信する $usermodel = User::where('email', $user->email)->get()[0]; $usermodel->notify(new RegisterNotify($activation->code)); // メールを確認して、承認してからログインすることを表示するページへ return redirect('login')->with('info', trans('sentinel.after_register')); }
ビューの調整
アクティベーションが済んでいない時に、アクティベーションコードを再送信するためのリンクを表示するようにします。
@if(isset($resend_code)) <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <a class="btn btn-link" href="{{ url('register', base64_encode($resend_code))}}"> ユーザー登録を完了させるメールを再送 </a> </div> </div> @endif
以上で完了です。 npm test でテストを実行すると成功するようになります。
手動で動きを確認する場合は、 http://localhost:8000 に接続して、ユーザー登録をした後、アクティベーションをメールで行う前に、ログインを試してみてください。アクティベートが未完了である旨、メッセージが表示されて、アクティベートコードの再送信のリンクが表示されます。リンクをクリックすると、アクティベートコードが再送信されます。その時点で、アクティベートコードが古くなっていたら、新しいアクティベートコードを生成して、そのコードをメールします。
-
-
- -
-
以上で、Laravelの認証の機能を全て置き換えることができました。ユーザー登録にメールによる確認が必要になるのはメリットが大きいです。
編集可能なロールやパーミッションを使った認可機能がつけば、さらにSentinelに変更した効果が高まります。
Laravel5.3対応のものは、後日作成します。