Skip to content

コントローラー側の$this can() の調査

Mitsuru Mutaguchi edited this page Feb 8, 2022 · 8 revisions

2020/08/28時点の調査記事です。

結論:ちょっとわかりにくい動きだけど、正常に動くコントローラー側の$this->can()を使う。

https://github.com/opensource-workshop/connect-cms/wiki/Policies(権限)

// Role Check(役割チェック)
if ($this->can('role_reporter')) {
    return $this->view_error(403);
}
  • 正常に動く。けど、ちょっとわかりにくい動きだった。
    • role_reporter権限がないと、$this->can()メソッドは、$this->view_error()となり、エラー画面のHTML文字列が戻ってくる。
    • role_reporter権限があると、$this->can()メソッドは、returnがないので nullになる。
    • 権限エラーでエラー画面のHTML文字列が戻ってくると、if文は文字列あり=trueと判定して、return $this->view_error(403);する。
  • コントローラー側の$this->can()はConnect-CMS自作メソッド。
  • Bladeの @can は、Laravel Gate(ゲート)機能の一部みたい
    • Bladeの@canAuth::user()->can()は同一のものでした。
    • コントローラー側の$this->can()メソッド内で、Auth::user()->can()を使ってるため、Bladeの@canと同一のチェックができてます。
    • コントローラー側の$this->isCan()メソッド内で、Auth::user()->can()を使っていますが、セットする引数がBladeの@canと違うため、現状(2020/08/28時点)で同一チェックできてなかったです。
      • 結論:ちょっとわかりにくい動きだけど、正常に動くコントローラー側の$this->can()を使う。

can()メソッド・isCan()メソッド

https://github.com/opensource-workshop/connect-cms/blob/master/app/Traits/ConnectCommonTrait.php#L37-L76

    /**
     * 権限チェック & エラー時
     * roll_or_auth : 権限 or 役割
     *
     * @return view|null 権限チェックの結果、エラーがあればエラー表示用HTML が返ってくる。
     *
     * @see \App\Providers\AppServiceProvider AppServiceProvider::boot()
     */
    public function can($roll_or_auth, $post = null, $plugin_name = null, $buckets = null, $frame = null)
    {
        $args = null;
        if ($post != null || $plugin_name != null || $buckets != null || $frame != null) {
            $args = [[$post, $plugin_name, $buckets, $frame]];
        }

        if (!Auth::check() || !Auth::user()->can($roll_or_auth, $args)) {
            return $this->view_error("403_inframe", null, "canメソッドチェック:{$roll_or_auth}");
        }
    }

    /**
     * 権限チェック
     * roll_or_auth : 権限 or 役割
     *
     * @return bool
     *
     * @see \App\Providers\AppServiceProvider AppServiceProvider::boot()
     */
    public function isCan($roll_or_auth, $post = null, $plugin_name = null, $buckets = null, $frame = null): bool
    {
        $args = null;
        if ($post != null || $plugin_name != null || $buckets != null || $frame != null) {
            $args = [[$post, $plugin_name, $buckets, $frame]];
        }

        if (!Auth::check() || !Auth::user()->can($roll_or_auth, $args)) {
            return false;
        }
        return true;
    }

Bledeの@can

@can('posts.update', [[$inputs, $frame->plugin_name, $buckets]])
<div class="row mt-2">
    <div class="col-12 text-right mb-1">
        <button type="button" class="btn btn-success btn-sm" onclick="location.href='{{url('/')}}/plugin/databases/input/{{$page->id}}/{{$frame_id}}/{{$inputs->id}}'">
            <i class="far fa-edit"></i> 編集
        </button>
    </div>
</div>
@endcan

Gate, @can で使える権限

https://github.com/opensource-workshop/connect-cms/blob/master/app/Providers/AppServiceProvider.php

bladeの @can は、Laravel Gate(ゲート)機能の一部みたい。

https://reffect.co.jp/laravel/laravel-gate-policy-understand#Blade

// Gate(ゲート)とPolicy(ポリシー)、要はアクセス制限です。
// Policy(ポリシー)は、Connect-CMSで App\Policies はフォルダ自体なく使ってない。

Bladeの@canAuth::user()->can()は同一のものでした。

Bladeの@canは便利な短縮形

@can('update', $post)
    <!-- 現在のユーザーはポストを更新できる -->
@elsecan('create', App\Post::class)
    <!-- 現在のユーザーはポストを作成できる -->
@endcan

上記の@canに対応するコード

@if (Auth::user()->can('update', $post))
    <!-- 現在のユーザーはポストを更新できる -->
@endif

コントローラー側の$this->can() で使っているため、$this->can()はBladeの@canと同一のチェックができてます。

参考

Bladeテンプレートによる認可 を参照 - 認可 5.5 Laravel
https://readouble.com/laravel/5.5/ja/authorization.html

Clone this wiki locally