Laravel Nova 授權(quán)

2023-02-16 17:09 更新

當(dāng)訪問 Nova 的用戶只有你和你或者公司內(nèi)部的開發(fā)團(tuán)隊(duì)時(shí),Nova 接收請求之前你是不需要添加額外的授權(quán)的。然而,如果你想要提供給客戶或者大型開發(fā)團(tuán)隊(duì)去訪問你的客戶端時(shí),你可能希望對(duì)某些請求加上權(quán)限。例如,只希望管理員可以刪除記錄。值得高興的是,Nova 提供了一種簡單的授權(quán)方法,這種方法正如你所了解的 Laravel 中的許多功能一樣。

策略

為了限制用戶的哪些用戶可以查看、創(chuàng)建、更新、或者刪除資源,Nova 利用了 Laravel 授權(quán)策略,策略是一個(gè)用于管理特定模型或者資源授權(quán)邏輯的簡單類。例如,如果你的程序是一個(gè)博客,你可能有一個(gè) Post 模型和相應(yīng)的  PostPolicy 在你的程序中。

在 Nova 中操作資源時(shí), Nova 會(huì)自動(dòng)的嘗試為模型找相應(yīng)的策略。通常,這些策略會(huì)在你應(yīng)用程序的 AuthServiceProvider 中注冊。如果 Nova 監(jiān)測到你已經(jīng)為模型注冊了策略,他將在執(zhí)行各自的操作前,自動(dòng)檢查該策略的相關(guān)授權(quán)方法,例如:

  • viewAny
  • view
  • create
  • update
  • delete
  • restore
  • forceDelete

不需要額外的配置!例如,要確定允許哪些用戶能夠更新 Post 模型,你只需在相應(yīng)的策略類上定義一個(gè) update 方法:

<?php

namespace App\Policies;

use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    /**
     * 檢查用戶是否能夠更新帖子模型
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return mixed
     */
    public function update(User $user, Post $post)
    {
        return $user->type == 'editor';
    }
}

未定義策略方法

如果策略存在但缺少特定的操作方法的策略,所有用戶將不會(huì)被允許執(zhí)行相應(yīng)的操作的,所以,當(dāng)你已經(jīng)定義策略后,請定義其所有的相關(guān)授權(quán)方法。

隱藏實(shí)體資源

如果你希望對(duì)你的用戶隱藏一個(gè) Nove 的實(shí)體資源,你可以定義一個(gè) viewAny 方法在對(duì)應(yīng)模型的策略類上。如果在該模型的策略類上沒有 viewAny 方法,Nova 認(rèn)為所有用戶都能查看該資源:

<?php

namespace App\Policies;

use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
    use HandlesAuthorization;

    /**
     *  確定用戶是否可以查看任何帖子
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function viewAny(User $user)
    {
        return in_array('view-posts', $user->permissions);
    }
}

模型關(guān)系

我們已經(jīng)學(xué)會(huì)了怎樣授權(quán)簡單的視圖、創(chuàng)建、更新和刪除動(dòng)作,但是模型關(guān)系的交互呢?例如,如果你希望建立一個(gè)播客程序,你希望某些特定的 Nova 用戶可以給播客評(píng)論。同樣的,Nova 使用了 Laravel 的策略簡單的實(shí)現(xiàn)。

使用模型關(guān)系時(shí),Nova 使用了簡單的命名規(guī)則。為了簡單的說明這個(gè)規(guī)則,讓我們假設(shè)你的程序具有 Podcast 資源和 Comment 資源。如果你希望某個(gè)授權(quán)的用戶能夠給一篇播客添加評(píng)論,你應(yīng)該在播客模型的策略類里定一個(gè) addComment 方法:

<?php

namespace App\Policies;

use App\User;
use App\Podcast;
use Illuminate\Auth\Access\HandlesAuthorization;

class PodcastPolicy
{
    use HandlesAuthorization;

    /**
     * 確定用戶是否可以在播客中添加評(píng)論。
     *
     * @param  \App\User  $user
     * @param  \App\Podcast  $podcast
     * @return mixed
     */
    public function addComment(User $user, Podcast $podcast)
    {
        return true;
    }
}

正如您所看到的,Nova 使用了一個(gè)簡單的 add{Model} 策略方法命名約定來授權(quán)關(guān)系行為。

附加 / 分離授權(quán)

對(duì)于多對(duì)多的關(guān)系,Nova 使用了 ige 簡單的命名規(guī)則。 然而,代替 add{Model},你可以使用 attach{Model} / detach{Model} naming 規(guī)則。例如,假設(shè) Postcast 模型 和 Tag 模型之間有多對(duì)多的關(guān)系。如果你希望授權(quán)用戶能夠給播客附加 "Tags",你可能需要在播客的策略類上定義一個(gè) attachTag 方法。另外,你也需要在在 tag 的策略上定義 attachPodcast 來反轉(zhuǎn)定義:

<?php

namespace App\Policies;

use App\Tag;
use App\User;
use App\Podcast;
use Illuminate\Auth\Access\HandlesAuthorization;

class PodcastPolicy
{
    use HandlesAuthorization;

    /**
     * 確定用戶是否可以將標(biāo)簽附加到播客上。
     *
     * @param  \App\User  $user
     * @param  \App\Podcast  $podcast
     * @param  \App\Tag  $tag
     * @return mixed
     */
    public function attachTag(User $user, Podcast $podcast, Tag $tag)
    {
        return true;
    }

    /**
     * 確定用戶是否可以從播客中分離標(biāo)簽。
     *
     * @param  \App\User  $user
     * @param  \App\Podcast  $podcast
     * @param  \App\Tag  $tag
     * @return mixed
     */
    public function detachTag(User $user, Podcast $podcast, Tag $tag)
    {
        return true;
    }
}

在前面的示例中,我們能夠判斷用戶是否有權(quán)限附加到另外一個(gè)模型。如果永遠(yuǎn)不允許某些類型的用戶附加給特定的模型,你可以在你的策略類上定義 attachAny{Model} 方法。這樣將導(dǎo)致 "Attach" 按鈕的不會(huì)在 Nova UI 實(shí)體上的顯示 :

<?php

namespace App\Policies;

use App\User;
use App\Podcast;
use Illuminate\Auth\Access\HandlesAuthorization;

class PodcastPolicy
{
    use HandlesAuthorization;

    /**
     * 確定用戶是否可以在播客中附加任何標(biāo)簽
     *
     * @param  \App\User  $user
     * @param  \App\Podcast  $podcast
     * @return mixed
     */
    public function attachAnyTag(User $user, Podcast $podcast)
    {
        return false;
    }
}

多對(duì)多的授權(quán)

在處理多對(duì)多的關(guān)系時(shí),請確保在每個(gè)涉及的資源的策略類上定義適當(dāng)?shù)氖跈?quán)策略方法。

禁用授權(quán)

如果你的某個(gè) Nova 的資源模型已經(jīng)有相應(yīng)的策略,但是你希望禁用該資源的 Nova 授權(quán),我們可以覆蓋 authorizable Nova 資源策略類的方法:

/**
 *  定義該資源策略是否啟用
 *
 * @return bool
 */
public static function authorizable()
{
    return false;
}

字段

有時(shí)候,你可能希望對(duì)某些用戶組隱藏某些字段。你可以通過 canSee 方法鏈接到字段的定義,輕松完成這個(gè)操作。canSee 該方法接收一個(gè)返回 true 或 false 的一個(gè)閉包函數(shù)。然而這個(gè)閉包函數(shù)接收 HTTP 的請求對(duì)象作為參數(shù):

use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;

/**
 * 獲取資源顯示的字段。
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
public function fields(Request $request)
{
    return [
        ID::make()->sortable(),

        Text::make('Name')
                ->sortable()
                ->canSee(function ($request) {
                    return $request->user()->can('viewProfile', $this);
                }),
    ];
}

上面的例子中,我們在 User 模型里使用 Laravel 的 Authorizable trait 的 can 方法,來確定授權(quán)用戶是否被授權(quán) viewProfile 動(dòng)作。然而,由于代理授權(quán)策略方法是 canSee 的常見用例,你可以使用  canSeeWhen 方法實(shí)現(xiàn)相同的行為。canSeeWhen 方法與 Illuminate\Foundation\Auth\Access\Authorizabletrait 的 can 方法有相同的方法簽名:

Text::make('Name')
        ->sortable()
        ->canSeeWhen('viewProfile', $this),

授權(quán) > 「can」方法

想了解更多關(guān)于 Laravel 授權(quán)和 can 方法的信息,請查看完整的 Laravel 授權(quán)文檔 。

可關(guān)聯(lián)過濾

如果你希望過濾數(shù)據(jù)在關(guān)聯(lián)數(shù)據(jù)中的展示,你可以在 Nova 資源中覆蓋 relatableQuery 方法。

例如,如果你的項(xiàng)目中有一個(gè) Comment 資源屬于一個(gè) Podcast 資源。在創(chuàng)建一個(gè) Comment 資源時(shí),Nova 將允許你選擇他歸屬的 Podcast 資源。為了在選項(xiàng)中限制用戶能選擇的 Podcast,你應(yīng)該在 Podcast 資源中覆蓋 relatableQuery 方法:

/**
 * 為資源構(gòu)建可關(guān)聯(lián)過濾。
 *
 * 這個(gè)查詢條件決定了哪些實(shí)例可以在關(guān)聯(lián)選項(xiàng)中被選擇。
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @param  \Illuminate\Database\Eloquent\Builder  $query
 * @return \Illuminate\Database\Eloquent\Builder
 */
public static function relatableQuery(NovaRequest $request, $query)
{
    return $query->where('user_id', $request->user()->id);
}

Scout 過濾

如果你的應(yīng)用程序使用了強(qiáng)大的 Laravel Scout 搜索擴(kuò)展,你可以自定義 Laravel\Scout\Builder 查詢實(shí)例,然后將其提供個(gè)查詢服務(wù)提供者。如果你要完成這個(gè)操作,請復(fù)寫你資源上的 scoutQuery 方法

/**
 * 為給定的資源構(gòu)建一個(gè) Scout 搜索查詢。
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @param  \Laravel\Scout\Builder  $query
 * @return \Laravel\Scout\Builder
 */
public static function scoutQuery(NovaRequest $request, $query)
{
    return $query->where('user_id', $request->user()->id);
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)