web-dev-qa-db-ja.com

Laravelのゲートの使用/ VueJsでの承認

これが以前にどのように処理されたかはわかりませんが、VueJを使用してVueテンプレートでアクションを承認するにはどうすればよいですか?

Laravelのブレードを使用している場合、これは簡単です(@canディレクティブを使用)が、Googleで時間を検索した後、Vue)でこれを実行するためのドキュメントや方法はありません。

これで、ユーザーのアクセス許可をビュー内の配列/ JSONオブジェクトに簡単にロードできることがわかりましたが、Laravelのゲートメソッドを使用してVueテンプレートでアクションを表示/非表示にする方法はないようです。ユーザーが特定のレコードに対してアクションを実行できるかどうかを判別します。

たとえば、コメントのリストがありますが、[編集]ボタンを表示するには、ユーザーがコメントを所有している必要があります。

問題は、Vueでロジックを実装すると、このためにバックエンドとフロントエンド全体に承認ロジックを複製することになります。

Laravelのポリシーを使用して、特定のアクションの複雑な承認を実行できます。しかし、Vueでポリシーをどのように実装するかについては困惑しています。

adminロールを持つユーザーがコメントを閲覧している場合、コメントを所有していなくても編集できるようにするなど、より複雑なシナリオもあります。

このタイプのシナリオについて誰か提案がありますか?

編集:

これで、モデルに属性アクセサーを追加できます。次に例を示します。

モデル:

class Comment extends Model
{
    protected $appends = ['can_update'];

    public function getCanUpdateAttribute()
    {
        return Gate::allows('update', $this);
    }
}

Vue:

<button v-if="comment.can_update">Edit</button>

しかし、これは、ポリシー内にすでに存在するロジックを再び複製しているようです。

10
Steve Bauman

私はこれを達成するためにLaravel resources を使用することになりました。

次に例を示します(can配列キーに注意してください)。

class Ticket extends Resource
{
    /**
     * The "data" wrapper that should be applied.
     *
     * @var string
     */
    public static $wrap = 'ticket';

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'answer_id' => $this->answer_id,
            'summary' => $this->summary,
            'description' => $this->description,
            'creator' => $this->creator,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'reported_at' => $this->reported_at,
            'closed_at' => $this->closed_at,
            'closed' => $this->closed,
            'answered' => $this->answered,
            'can' => $this->permissions(),
        ];
    }

    /**
     * Returns the permissions of the resource.
     *
     * @return array
     */
    protected function permissions()
    {
        return [
            'update' => Gate::allows('update', $this->resource),
            'delete' => Gate::allows('delete', $this->resource),
            'open' => Gate::allows('open', $this->resource),
        ];
    }
}

これにより、フロントエンドで実際のアクセス許可ロジックを複製するのではなく、Vueテンプレートで単純なブールロジックを使用して、フロントエンドでのアクセスを制御できるようになりました。

<router-link v-if="ticket.can.update" :to="{name:'tickets.edit', params: {ticketId: ticket.id}}" class="btn btn-sm btn-secondary">
    <i class="fa fa-edit"></i> Edit
</router-link>

また、Laravel resourcecollectionsを使用して、ユーザーが許可を適用できる場合に許可を適用できるようにしましたリソースの作成

class TicketCollection extends ResourceCollection
{
    /**
     * The "data" wrapper that should be applied.
     *
     * @var string
     */
    public static $wrap = 'tickets';

    /**
     * Get any additional data that should be returned with the resource array.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function with($request)
    {
        return [
            'can' => [
                'create' => Gate::allows('create', Ticket::class),
            ],
        ];
    }
}

次に、私のAPIコントローラーで:

public function index()
{
    $tickets = Ticket::paginate(25);

    return new TicketCollection($tickets);
}

public function show(Ticket $ticket)
{
    $ticket->load('media');

    return new TicketResource($ticket);
}

これにより、現在認証されているユーザーが、リストされているリソースを作成できるアクセス権を持っているかどうかを検証できました。検証する実際のリソースがないため、返されたコレクションに関連しているため、これを行うことができます。完全に。

このパターンを実装することは、私のVueアプリ全体で実際の承認ロジックを複製せず、ブレードを使用してコンポーネントに個別にアクセス許可を挿入することなく、承認を管理する最も簡単な方法のように思えました。

コンポーネントにパーミッションを挿入すると、パーミッションも必要とするネストされたコンポーネントがある場合に問題が発生します。これは、子コンポーネントのパーミッションを親に渡して検証できるようにする必要があるためです。

ネストされたアクセス許可の場合、canアクセス許可配列も含む関係の親リソースからサブリソースを返すことができるため、Vueそして、それらへのユーザーアクセスを決定するための単純なロジックも使用します。

このアプローチも有益だったので、頻繁に変更されないリソースのサーバー側を介して各ユーザーのアクセス許可をキャッシュできました。

18
Steve Bauman

現在、バックエンドのコードをフロントエンドに複製せずにこれを実現する方法はありません。

Fullstack Radio (17:15)のこのエピソードでは、JeffreyWayとAdamWathanがその点について正確に話しました。彼らは私の意見と同じ意見を持っており、現在、彼らはあなたがしたのと同じことをしています。

彼らはまた、次のような小道具の使用について話しました。

<post-component :can-update="{{ $user->can('update', $post) }}"></post-component>

この回答がお役に立てば幸いです。

8
Ian Rodrigues