ユーザー認証の仕上げに、アクティベーションコードの再送機能を追加します。アクティベーションコードには有効期限があるので、一定時間がすぎると利用できなくなります。また、ユーザーがメールを削除してしまう可能性もあるので、コードの再発行が必要となります。
(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対応のものは、後日作成します。