Laravel6 Userモデルに紐づくPolicyを作成（マイページ用）

こんにちは、JeffTechです。

# 説明
マイページの実装時に、ログインユーザー以外のユーザー情報を変更できないようにする処理を実装したので、メモ程度に残しておきます。
URLのID番号変えると編集できちゃうとかのあれですね！

# この記事で実現できること
- ユーザーモデルに紐づくPolicyの作成
- アクセス制限

# 開発環境
- OS:MacOS
- PHP:7.3
- Laravel6

# 実装
下記コマンドで`UserPolicy`を作成

```bash
$ php artisan make:policy UserPolicy
```
Policyの中身を整えて行きます。
ログインユーザーのIDと編集しようとしているマイページの所有ユーザーIDを見比べるようにしています。

```php:app/Policies/UserPolicy.php
namespace App\Policies;

use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Auth\Access\HandlesAuthorization;

class UserPolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * マイページアクセス制限
     */
    public function ctrlMyPage(User $user, User $model)
    {
        return $user->id === $model->id ? Response::allow() : Response::deny();
    }
}
```

今回私は、`app/Models`配下にユーザーモデルを配置しているので、AuthServiceProvider.phpへPolicyの登録を行います。
※ポリシーの自動検出機能がありますが、今回の場合は該当しないため

```php:app/Providers/AuthServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use App\Models\User; // ここを追加
use App\Policies\UserPolicy; // ここを追加

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        User::class => UserPolicy::class, // ここを追加
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}
```

最後にコントローラを少し変えていきます。
今回は下記の3つのメソッドの中に必要な処理を追記していきます。
Show（マイページ表示）
Edit（ユーザー情報編集ページ）
Update（ユーザー情報編集処理）
の全てのメソッドにアクセス制限を実装していきます。

```php:app/Http/Controllers/MyPageController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\UpdateMyPageRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;

class MyPageController extends Controller
{
    public function __construct()
    {
        // $this->middleware('can:ctrlMyPage,user')->only('show');
    }

    /**
     * ユーザー情報表示
     * 
     * @return view
     */
    public function show()
    {
        // ログインユーザー情報取得
        $user = Auth::user();

        // ポリシー設定
        $this->authorize('ctrlMyPage', $user);

        // ユーザー情報表示
        return view('my_pages.show', compact('user'));
    }

    /**
     * ユーザー情報編集画面表示
     * 
     * @param Int $id
     * 
     * @return view
     */
    public function edit(Int $id)
    {
        // ユーザー情報
        $user = User::find($id);

        // ポリシー設定
        $this->authorize('ctrlMyPage', $user);

        // ユーザー情報編集ページへ
        return view('my_pages.edit', compact('user'));
    }

    /**
     * ユーザー情報編集処理
     * 
     * @param UpdateMyPageRequest $request
     * @param Int $id
     * 
     * @return redirect
     */
    public function update(UpdateMyPageRequest $request, Int $id)
    {
        // ユーザー情報取得
        $user = User::find($id);
        
        // ポリシー設定
        $this->authorize('ctrlMyPage', $user);

        // 編集処理実行
        $user->fill($request->all())->save();

        // ユーザー情報表示
        return redirect()->route('mypage.show')->with('flash_message', '変更が完了しました。');
    }
}
```

```php
// ポリシー設定
$this->authorize('ctrlMyPage', $user);
```
ここで編集しようとしているユーザーの情報を渡しています。
Showメソッドの場合、ログインユーザーの情報を渡しているので、おそらくPolicyの設定は不要なのですが、一応実装しています。
いらないと思えば、外しても問題なさそうです。

これで実装自体は終わりなので、他の人のマイページに飛べるかどうか試してみてください！
Forbiddenが出ていればOKです！


# 最後に
少しでも役に立った！という時は、いいねをポチッとして
フォローしてくださると嬉しいです、、、笑

役に立たなかった時は、怒らないでコメント頂けますと幸いです笑

Twitterもやってますので、よかったら見てみてくださいね！
https://twitter.com/jefftechsaku