概要
Laravel5.2のAuth機能の上にLaravelが公式でソーシャル連携する実装で利用しているSocialiteというパッケージをを動かして、Twitter経由でログインとかユーザー登録をさせます。
5.3のバージョンも書きました。| Laravel5.3でソーシャル連携ウェブサービスの土台を作る(Socialite/Twitter)
構築用の環境設定
プロジェクトの作成
PhpStormでの例を書いています。composerで作ったりするのは誰か他の人のドキュメントを参考に。
PhpStormの起動画面はこんなで「Create New Project」します。
プロジェクトの初期設定を入力
プロジェクトの初期設定を入力して、LaravelのVersionも指定。
プロジェクト作成が完了。
動作環境の設定
HomesteadというLaravelの公式のVMの設定で実装します。
Homesteadのライブラリをインストール
composer require laravel/homestead --dev
Homesteadの設定をこのプロジェクト用に生成
php vendor/bin/homestead make
host名を登録しておく
/etc/hostsファイルの最終行に以下を足しておけばいいはず。
192.168.10.10   homestead.app
上記のIPの設定は、homestead makeによって、プロジェクト直下/Homestead.yamlに自動生成されてる。
仮想環境を起動して動作確認
vagrant up
動作確認
ここにアクセスできたらOK。
ユーザー認証を実装
laravel5はフルスタックをうたっているので、5.2ではとうとうRailsでのDevise gemのような、ログイン認証機能がコマンド一発で生成できる。すごい。
ユーザーのモデルをmigrate
なんか最初からユーザーモデルとパスワード変更のテーブルのmigrationも先に用意されているので実行する。
php artisan migrate
ユーザー認証のプログラムを自動生成
以下のコマンドで、ユーザー認証のプログラムを自動生成。
php artisan make:auth
結果の確認
以下ができる。すごひ…。
Created View: /home/vagrant/rankings/resources/views/auth/login.blade.php
Created View: /home/vagrant/rankings/resources/views/auth/register.blade.php
Created View: /home/vagrant/rankings/resources/views/auth/passwords/email.blade.php
Created View: /home/vagrant/rankings/resources/views/auth/passwords/reset.blade.php
Created View: /home/vagrant/rankings/resources/views/auth/emails/password.blade.php
Created View: /home/vagrant/rankings/resources/views/layouts/app.blade.php
Created View: /home/vagrant/rankings/resources/views/home.blade.php
Created View: /home/vagrant/rankings/resources/views/welcome.blade.php
Installed HomeController.
Updated Routes File.
Authentication scaffolding generated successfully!
homeのルーティング設定
そのままだと/へのアクセスは、routes.phpの一番上に書かれている。これでは、ログインされているかどうかわからないので、routeを書き直す。
最初は一番上に/へのルートが書かれているのをmiddleware web の中に書くいて、
HomeControllerのindexに送るようにする。
// これが一番上に書かれている。
Route::get('/', function () {
    return view('welcome');
});
// 省略
Route::group(['middleware' => 'web'], function () {
    Route::auth();
    Route::get('/', 'HomeController@index');
}
// 省略
実装されたルーティングの一覧をみる
以下のコマンドでルートの一覧が見れる。
php artisan route:list
ログインとか全部実装されてるすげえw
+--------+----------+-------------------------+------+-----------------------------------------------------------------+------------+
| Domain | Method   | URI                     | Name | Action                                                          | Middleware |
+--------+----------+-------------------------+------+-----------------------------------------------------------------+------------+
|        | GET|HEAD | /                       |      | Closure                                                         |            |
|        | GET|HEAD | auth/twitter            |      | App\Http\Controllers\Auth\AuthController@redirectToProvider     | web,guest  |
|        | GET|HEAD | auth/twitter/callback   |      | App\Http\Controllers\Auth\AuthController@handleProviderCallback | web,guest  |
|        | GET|HEAD | home                    |      | App\Http\Controllers\HomeController@index                       | web,auth   |
|        | GET|HEAD | login                   |      | App\Http\Controllers\Auth\AuthController@showLoginForm          | web,guest  |
|        | POST     | login                   |      | App\Http\Controllers\Auth\AuthController@login                  | web,guest  |
|        | GET|HEAD | logout                  |      | App\Http\Controllers\Auth\AuthController@logout                 | web        |
|        | POST     | password/email          |      | App\Http\Controllers\Auth\PasswordController@sendResetLinkEmail | web,guest  |
|        | POST     | password/reset          |      | App\Http\Controllers\Auth\PasswordController@reset              | web,guest  |
|        | GET|HEAD | password/reset/{token?} |      | App\Http\Controllers\Auth\PasswordController@showResetForm      | web,guest  |
|        | GET|HEAD | register                |      | App\Http\Controllers\Auth\AuthController@showRegistrationForm   | web,guest  |
|        | POST     | register                |      | App\Http\Controllers\Auth\AuthController@register               | web,guest  |
+--------+----------+-------------------------+------+-----------------------------------------------------------------+------------+
少し動かしてみると、登録画面はこんな。
少し動かしてみると、ログイン画面はこんな。
少し動かしてみると、ログイン状態のホーム画面はこんな。
logoutの実装も用意されているので、http://homestead.app/logoutにアクセスするとログアウトされる。
Twitter経由のログインとユーザー登録
ユーザー登録はメアドで登録ってのも全然ありだが、最初はtwitter経由で登録してあとからTwitter連携外すとか、よくやると思うので、そのようにする。
このサイトの言うこと聞いとけば大体できそう。
Using Twitter Authentication For Login in Laravel 5
socialiteのインストール
composer require laravel/socialite
ライブラリの読み込み
'providers' => [
    // Other service providers...
    Laravel\Socialite\SocialiteServiceProvider::class,
],
'aliases' => [
	snip...
    // Other service providers...
    'Socialite' => Laravel\Socialite\Facades\Socialite::class,
],
oauth APIのキーを.envに書く。
oauth APIのキーとかはここからとる。
https://apps.twitter.com/
TWITTER_CLIENT_ID=XXXXXXX
TWITTER_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXX
CALLBACK_URL=http://homestead.app/auth/twitter/callback
configのservice.phpに設定を追加
    'twitter' => [
        'client_id' => env('TWITTER_CLIENT_ID'),
        'client_secret' => env('TWITTER_CLIENT_SECRET'),
        'redirect' => env('CALLBACK_URL'),
    ],
routes.phpにパスとコントローラーの対応を追加
Route::get('auth/twitter', 'Auth\AuthController@redirectToProvider');
Route::get('auth/twitter/callback', 'Auth\AuthController@handleProviderCallback');
モデルのUsersにtwitter_idとかが保存できるよう、filleableにフィールドを追加。
User.php
    protected $fillable = [
        'name', 'email', 'password','handle','twitter_id','avatar'
    ];
filleableに追加するのと同じく、migrationを追加
migrationファイルを作成
php artisan make:migration add_twitter_columns_to_user  --table=users
オプションに--table=テーブル名ってすると、指定したテーブル名の変更のクロージャを用意してくれるので、マニュアル見なくてすんで便利。
make:migrationで出来上がるファイルはこんな感じ。
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddTwitterColumnsToUser extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
}
database/migrations/{日付とか}_add_twitter_columns_to_user.phpにmigrationファイルの中身を書く
upの中身はこう書く。
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('handle');
            $table->bigInteger('twitter_id')->unique();
            $table->string('avatar');
        });
    }
downの中身はこう書く。
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('handle');
            $table->dropColumn('twitter_id');
            $table->dropColumn('avatar');
        });
    }
php artisan migrateした。
controllerの中身を書く。
用意するのは、3つのmethod。すでにあるAuthControllerに、追加する。
twitter経由でログインするのにTwitterにリダイレクトするところ
    /**
     * Redirect the user to the Twitter authentication page.
     *
     * @return Response
     */
    public function redirectToProvider()
    {
        return Socialite::driver('twitter')->redirect();
    }
twitterでログインしたあとに帰ってくるところ。
    /**
     * Obtain the user information from Twitter.
     *
     * @return Response
     */
    public function handleProviderCallback()
    {
        try {
            /** @var \Laravel\Socialite\Contracts\User $user */
            $user = Socialite::driver('twitter')->user();
        } catch (Exception $e) {
            return redirect('auth/twitter');
        }
        $authUser = $this->findOrCreateUser($user);
        Auth::login($authUser, true);
        return redirect('home');
    }
Twitterから帰ってくるところの中で、ユーザーの情報がDBに入ってればそれを返して入って無ければユーザー作成するmethod。
    /**
     * Return user if exists; create and return if doesn't
     *
     * @param $twitterUser
     * @return User
     */
    private function findOrCreateUser($twitterUser)
    {
        $authUser = User::where('twitter_id', $twitterUser->id)->first();
        if ($authUser){
            return $authUser;
        }
        return User::create([
            'name' => $twitterUser->name,
            'email' => str_random(16)."@example.com",
            'password' => bcrypt(str_random(16)),
            'handle' => $twitterUser->nickname,
            'twitter_id' => $twitterUser->id,
            'avatar' => $twitterUser->avatar_original
        ]);
    }
viewファイルにリンクを用意する。
このファイル(ユーザー登録画面)の
</div>
@endsection
の直前に、以下を入れる。
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Register with Social</div>
                <div class="panel-body">
                    <a href="{{ url('auth/twitter') }}" class="btn btn-primary">
                        <i class="fa fa-btn fa-user"></i>Register with Twitter
                    </a>
                </div>
            </div>
        </div>
    </div>
このファイル(ログイン画面)の
</div>
@endsection
の直前に、以下を入れる。
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Register with Social</div>
                <div class="panel-body">
                    <a href="{{ url('auth/twitter') }}" class="btn btn-primary">
                        <i class="fa fa-btn fa-user"></i>Register with Twitter
                    </a>
                </div>
            </div>
        </div>
    </div>
とりあえずこの時点で、Twitter経由でログインできます。
パスワードとメールアドレスが未設定の表示とかフラグとか付ける
パスワードとメールアドレスが初期状態では設定されていないので、設定されていないっていうフラグフィールドを儲ける。ユーザーが設定したパスワードなのか、システムがダミーで入れたものなのかが区別できるようにする。
このフラグは、usersテーブルに持たせる。
フィールドの名前はvalud_passwordとvalid_emailで、種類はbooleanで、defaultの値はfalseにする。
マイグレーションの作成
usersテーブルのマイグレーションファイル作る。
php artisan make:migration add_no_email_no_password_column_to_user --table=users
Created Migration: 2016_01_11_200214_add_no_email_no_password_column_to_user
マイグレーションファイルにフィールドを書く。
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddNoEmailNoPasswordColumnToUser extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            //
            $table->boolean('valid_password')->default(false);
            $table->boolean('valid_email')->default(false);
        });
    }
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            //
            $table->dropColumn('valid_password');
            $table->dropColumn('valid_email');
        });
    }
}
HOME画面をちょっと書き換えて未設定である旨表示する。
絶対設定しろよなって感じに見えるのなんとかしたいけど、まあとりあえず、いいか。
@extends('layouts.app')
@section('content')
<div class="container spark-screen">
    <div class="row">
        @if (session('message'))
            <div class="alert alert-info">
                {{ session('message') }}
            </div>
        @endif
    </div>
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">Dashboard</div>
                <div class="panel-body">
                    {{ $user->name }}さん ログイン中
                </div>
                <div class="panel-body">
                    @unless ( $user->valid_password )
                    <div class="alert alert-warning">
                        <a class="close" data-dismiss="alert">×</a>
                        <h4 class="alert-heading">Warning!</h4>
                        パスワードが一度も設定されていません。メールアドレスでログインするにはパスワードの設定が必要です。
                    </div>
                    @endunless
                    @if ( $user->valid_email )
                        {{ $user->email }}
                    @else
                        <div class="alert alert-warning">
                            <a class="close" data-dismiss="alert">×</a>
                            <h4 class="alert-heading">Warning!</h4>
                            メールアドレスが一度も設定されていません。ツイッター連携などを解除する場合はメールアドレスを設定してください。
                        </div>
                    @endunless
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
スクショ
スクショは切り貼り捏造だ。
捏造した事がわかる区切り線が見えますね…。
メールアドレスの変更の実装
つづいて、ユーザー設定画面でのメールアドレス変更をできるようにする。twitterからログインするだけだったので、メールアドレスはダミーデータが入っていた。これを設定するところを作る。
実は、emailのフォームってphp artisan make:authですでに実装されていて、resources/views/auth/passwords/email.blade.phpとかあるんだけど、実はこれは、パスワードをわすれた時のパスワードリマインダとしての実装なので、実際のメールアドレスの変更はない。自分は機能がよくわかってなくて混乱してしまいました。
コントローラーの最初の実装
ユーザー設定が諸々出てくるはずなので、ユーザー情報の設定変更用のコントローラーを app/Http/Controllers/Auth/UserController.php として作ることにする。
コントローラー最初はこんな状態。__constructでauthのmiddlewareを必ず通るようにしておくの味噌。
<?php
namespace App\Http\Controllers\Auth;
use Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
    use ResetsPasswords;
    public function __construct()
    {
        $this->middleware('auth');
    }
}
素晴らしお味噌です。これで、このユーザーコントローラーはいつでもログインしてないと操作できないようになってる。(たぶん)
ルートの設定
メールアドレスの変更の入力画面表示は:
Controler:UserController @showEmailChangeForm
route:getでauth/user/email
FormのPOSTして登録の処理は:
Controler:UserController @postEmailChange(Request $request)
route:postでauth/user/email
route.phpに書くのはこんな感じ。
Route::group(['middleware' => 'web'], function () {
	// 省略
    Route::get('auth/user/email', 'Auth\UserController@showEmailChangeForm');
    Route::post('auth/user/email', 'Auth\UserController@postEmailChange');
	// 省略
});
コントローラーの処理を内容を書く
変更フォームを表示するところ。
ユーザー情報を取ってきてメールアドレスを変数にセットしてるだけ。
User情報をそのまま引っ張ってきたい時が画面で有りそうなので、userもView変数として送り込む。
    public function showEmailChangeForm()
    {
        $user = Auth::user();
        $email = $user->email;
        return view('auth.users.email')->with('email', $email)->with('user', $user);
    }
ちょっと->with('user', $user)のところは、user渡さなくてもいいんじゃないかって疑問が残るけど、おいておく…。
メールアドレスを変更をpostするところ。
    public function postEmailChange(Request $request)
    {
        $this->validate($request, ['email' => 'required|email|confirmed']);
        $user = Auth::user();
        $user->email = $request->email;
        $user->valid_email = true;
        $user->save();
        return redirect('home')->with('message', ['Email changed']);
    }
ここですごいのは、validateのconfirmedってとこ。実は、emailとemail_confirmationって入力の値を送ると、その2つのフィールドの値が一緒かどうかチェックしてくれるってわけ。マジ最高。
viewを書く
resources/views/auth/users/email.blade.phpにファイルを作る。
中身は、resources/views/auth/passwords/email.blade.phpをコピーして、formのactionを/password/emailから/auth/user/emailに変える。
メールの入力のところを、コピペで2つに増やした後、新しく増やした方のフィールド名をemail_confirmationにかえる。
まあできあがりは、こう。
@extends('layouts.app')
<!-- Main Content -->
@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Change E-mail Address</div>
                <div class="panel-body">
                    @if (session('status'))
                        <div class="alert alert-success">
                            {{ session('status') }}
                        </div>
                    @endif
                    <form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/user/email') }}">
                        {!! csrf_field() !!}
                        <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
                            <label class="col-md-4 control-label">New E-Mail Address</label>
                            <div class="col-md-6">
                                <input type="email" class="form-control" name="email" value="{{ old('email') }}">
                                @if ($errors->has('email'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group{{ $errors->has('email_confirmation') ? ' has-error' : '' }}">
                            <label class="col-md-4 control-label">Retype New E-Mail Address</label>
                            <div class="col-md-6">
                                <input type="email" class="form-control" name="email_confirmation" value="{{ old('email_confirmation') }}">
                                @if ($errors->has('email'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('email_confirmation') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    <i class="fa fa-btn fa-save"></i>Change
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
動作確認
パスワードの変更の実装
メールアドレスとほぼ同じ。Laravel5.2で用意されているものではログインできなかった時のパスワードリセットはできるけど、ログインしてる時にパスワード変更ができないので、それを実装する。
ルートの設定
パスワードの変更の入力は
Controler:UserController@showPasswordChangeForm
route:getでauth/user/password
FormのPOSTして登録は
Controler:UserController @postPasswordChange(Request $request)
route:postでauth/user/password
route.phpに書くのはこんな感じ。
Route::group(['middleware' => 'web'], function () {
	// 省略
    Route::get('auth/user/password', 'Auth\UserController@showPasswordChangeForm');
    Route::post('auth/user/password', 'Auth\UserController@postPasswordChange');
	// 省略
});
コントローラーの処理を内容を書く
変更フォームを表示するところ。
ユーザー情報を取ってきてパスワードを変数にセットしてる。
User情報を画面で利用したさがあるので、userもView変数として送り込む。(消したさもある)
    public function showPasswordChangeForm()
    {
        $user = Auth::user();
        $password = $user->password;
        return view('auth.users.password')->with('password', $password)->with('user', $user);
    }
パスワード変更をpostするところ。
    public function postPasswordChange(Request $request)
    {
        $this->validate($request, ['password' => 'required|confirmed|min:6']);
        $user = Auth::user();
        $this->resetPassword($user, $request->password);
        $user->valid_password = true;
        $user->save();
        return redirect('home')->with('message', 'パスワードが変更されました。');
    }
resetPasswordって謎の関数使ってるけど、これはすでに用意されているパスワードを暗号化してくれるtraitなので利用する。
利用するには、useしてuseね。
// 省略
use Illuminate\Foundation\Auth\ResetsPasswords;
class UserController extends Controller
{
    use ResetsPasswords;
// 省略
validatesのconfirmedはまた出てきた。
パスワードの長さ6文字にしてるけど8文字くらいにした方がいいかも知んないしもっとランダム文字列とか強要した方がいいと思う。
viewを書く
このようにした。このままコピペしてもいいけど、捏造の仕方を後ろに書く。
@extends('layouts.app')
@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Reset Password</div>
                <div class="panel-body">
                    <form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/user/password') }}">
                        {!! csrf_field() !!}
                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                            <label class="col-md-4 control-label">Password</label>
                            <div class="col-md-6">
                                <input type="password" class="form-control" name="password">
                                @if ($errors->has('password'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
                            <label class="col-md-4 control-label">Confirm Password</label>
                            <div class="col-md-6">
                                <input type="password" class="form-control" name="password_confirmation">
                                @if ($errors->has('password_confirmation'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('password_confirmation') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    <i class="fa fa-btn fa-refresh"></i>Reset Password
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
viewの捏造方法
viewのコピペで作る方法を書きます。上で書いたのが間違ってたら試してみてください。
ファイルは、resources/views/auth/passwords/reset.blade.phpをresources/views/auth/users/password.blade.phpにコピーして、formのactionのurlを変えたあとに...
<form class="form-horizontal" role="form" method="POST" action="{{ url('/password/reset') }}">
<form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/user/password') }}">
reset tokenのフィールドとemailのフィールドを消す。
<input type="hidden" name="token" value="{{ $token }}">
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
    <label class="col-md-4 control-label">E-Mail Address</label>
    <div class="col-md-6">
        <input type="email" class="form-control" name="email" value="{{ $email or old('email') }}">
        @if ($errors->has('email'))
            <span class="help-block">
                <strong>{{ $errors->first('email') }}</strong>
            </span>
        @endif
    </div>
</div>
というふうに捏造した。
動作確認
画面はこんな感じ。ちょっと手抜きで入力画面だけ。
最後にHOME画面をそれっぽく整えてみた。
HTMLとFORMのヘルパーインストールする。
リンクとかhtmlとか自分で書き始めるので、htmlとformのヘルパーを入れる。ヘルパーは、LaravelCollectiveで作られてるものが標準に変わったっぽい。あー。なんかformとmodelの連結みたいなのがLaravel4では本家ドキュメントにくっついてたのに、5では書いていないのはそういうことなのかー。わかんないよー。いっぱいかわったなー。
それはともかくインストール
composer require laravelcollective/html
ライブラリのロード設定変更
providersでロードするように変更
    'providers' => [
        // 省略…
        Collective\Html\HtmlServiceProvider::class, // 追加する
    ],
 
設定変更Aliasで呼び出せるように名前を登録
 
    'aliases' => [
        // 省略…
        'Form' => Collective\Html\FormFacade::class,  // 追加する
        'Html' => Collective\Html\HtmlFacade::class,  // 追加する
    ],
viewを書く
やったことは…
- メールアドレスの表示のpanelの追加
- メールアドレス変更へのリンクをおいた
- パスワードの表示のpalelの追加
- パスワード変更へのリンクをおいた
- メアドとパスワードが設定されてないってメッセージをそれぞれのdivのpanelのところに移動した。
- 一番上に、sessionでmessageが送られてきた時の表示場所実装。
@extends('layouts.app')
@section('content')
<div class="container spark-screen">
    <div class="row">
        @if (session('message'))
            <div class="alert alert-info">
                {{ session('message') }}
            </div>
        @endif
    </div>
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">Dashboard</div>
                <div class="panel-body">
                    {{ $user->name }}さん ログイン中
                </div>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">メールアドレス</div>
                <div class="panel-body">
                    @if ( $user->valid_email )
                        {{ $user->email }}
                    @else
                        <div class="alert alert-warning">
                            <a class="close" data-dismiss="alert">×</a>
                            <h4 class="alert-heading">Warning!</h4>
                            メールアドレスが一度も設定されていません。ツイッター連携などを解除する場合はメールアドレスを設定してください。
                        </div>
                    @endunless
                    {!! link_to('auth/user/email', '設定する', ['class' => 'btn btn-info']) !!}
                </div>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">パスワード変更</div>
                <div class="panel-body">
                    @unless ( $user->valid_password )
                    <div class="alert alert-warning">
                        <a class="close" data-dismiss="alert">×</a>
                        <h4 class="alert-heading">Warning!</h4>
                        パスワードが一度も設定されていません。メールアドレスでログインするにはパスワードの設定が必要です。
                    </div>
                    @endunless
                    {!! link_to('auth/user/password', '設定する', ['class' => 'btn btn-info'] ) !!}
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
書き足したいこと
- oauthの設定の方法とかへのリンク。
- Twitterからの情報の上書き。
- adminなどのrole関連。









