読者です 読者をやめる 読者になる 読者になる

tanaka's Programming Memo

プログラミングについてのメモ。

Laravel5.3でSentinelを利用する(7)アクティベーションコードの再送

前へ

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

(2016/12/21 テストにwantToを追加)


方針

アクティベーションコードを再送信する方針は以下の通りです。



テストを準備

先に作成していた 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'));
    }

ビューの調整

アクティベーションが済んでいない時に、アクティベーションコードを再送信するためのリンクを表示するようにします。

  • resources/views/auth/login.blade.php をエディターで開く
  • パスワード欄と Remember Me のチェックボックスの間(53行目付近)に、以下のコードを追加
                        @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対応のものは、後日作成します。



前へ