當訪問 Nova 的用戶只有你和你或者公司內部的開發(fā)團隊時,Nova 接收請求之前你是不需要添加額外的授權的。然而,如果你想要提供給客戶或者大型開發(fā)團隊去訪問你的客戶端時,你可能希望對某些請求加上權限。例如,只希望管理員可以刪除記錄。值得高興的是,Nova 提供了一種簡單的授權方法,這種方法正如你所了解的 Laravel 中的許多功能一樣。
為了限制用戶的哪些用戶可以查看、創(chuàng)建、更新、或者刪除資源,Nova 利用了 Laravel 授權策略,策略是一個用于管理特定模型或者資源授權邏輯的簡單類。例如,如果你的程序是一個博客,你可能有一個 Post
模型和相應的
PostPolicy
在你的程序中。
在 Nova 中操作資源時, Nova 會自動的嘗試為模型找相應的策略。通常,這些策略會在你應用程序的 AuthServiceProvider
中注冊。如果 Nova 監(jiān)測到你已經為模型注冊了策略,他將在執(zhí)行各自的操作前,自動檢查該策略的相關授權方法,例如:
viewAny
view
create
update
delete
restore
forceDelete
不需要額外的配置!例如,要確定允許哪些用戶能夠更新 Post
模型,你只需在相應的策略類上定義一個 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';
}
}
未定義策略方法
如果策略存在但缺少特定的操作方法的策略,所有用戶將不會被允許執(zhí)行相應的操作的,所以,當你已經定義策略后,請定義其所有的相關授權方法。
如果你希望對你的用戶隱藏一個 Nove 的實體資源,你可以定義一個 viewAny
方法在對應模型的策略類上。如果在該模型的策略類上沒有 viewAny
方法,Nova 認為所有用戶都能查看該資源:
<?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);
}
}
我們已經學會了怎樣授權簡單的視圖、創(chuàng)建、更新和刪除動作,但是模型關系的交互呢?例如,如果你希望建立一個播客程序,你希望某些特定的 Nova 用戶可以給播客評論。同樣的,Nova 使用了 Laravel 的策略簡單的實現(xiàn)。
使用模型關系時,Nova 使用了簡單的命名規(guī)則。為了簡單的說明這個規(guī)則,讓我們假設你的程序具有 Podcast
資源和 Comment
資源。如果你希望某個授權的用戶能夠給一篇播客添加評論,你應該在播客模型的策略類里定一個 addComment
方法:
<?php
namespace App\Policies;
use App\User;
use App\Podcast;
use Illuminate\Auth\Access\HandlesAuthorization;
class PodcastPolicy
{
use HandlesAuthorization;
/**
* 確定用戶是否可以在播客中添加評論。
*
* @param \App\User $user
* @param \App\Podcast $podcast
* @return mixed
*/
public function addComment(User $user, Podcast $podcast)
{
return true;
}
}
正如您所看到的,Nova 使用了一個簡單的 add{Model}
策略方法命名約定來授權關系行為。
對于多對多的關系,Nova 使用了 ige 簡單的命名規(guī)則。 然而,代替 add{Model}
,你可以使用 attach{Model}
/ detach{Model}
naming 規(guī)則。例如,假設 Postcast
模型
和 Tag
模型之間有多對多的關系。如果你希望授權用戶能夠給播客附加 "Tags",你可能需要在播客的策略類上定義一個 attachTag
方法。另外,你也需要在在 tag 的策略上定義 attachPodcast
來反轉定義:
<?php
namespace App\Policies;
use App\Tag;
use App\User;
use App\Podcast;
use Illuminate\Auth\Access\HandlesAuthorization;
class PodcastPolicy
{
use HandlesAuthorization;
/**
* 確定用戶是否可以將標簽附加到播客上。
*
* @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;
}
/**
* 確定用戶是否可以從播客中分離標簽。
*
* @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;
}
}
在前面的示例中,我們能夠判斷用戶是否有權限附加到另外一個模型。如果永遠不允許某些類型的用戶附加給特定的模型,你可以在你的策略類上定義 attachAny{Model}
方法。這樣將導致 "Attach" 按鈕的不會在 Nova UI 實體上的顯示 :
<?php
namespace App\Policies;
use App\User;
use App\Podcast;
use Illuminate\Auth\Access\HandlesAuthorization;
class PodcastPolicy
{
use HandlesAuthorization;
/**
* 確定用戶是否可以在播客中附加任何標簽
*
* @param \App\User $user
* @param \App\Podcast $podcast
* @return mixed
*/
public function attachAnyTag(User $user, Podcast $podcast)
{
return false;
}
}
多對多的授權
在處理多對多的關系時,請確保在每個涉及的資源的策略類上定義適當?shù)氖跈嗖呗苑椒ā?
如果你的某個 Nova 的資源模型已經有相應的策略,但是你希望禁用該資源的 Nova 授權,我們可以覆蓋 authorizable
Nova 資源策略類的方法:
/**
* 定義該資源策略是否啟用
*
* @return bool
*/
public static function authorizable()
{
return false;
}
有時候,你可能希望對某些用戶組隱藏某些字段。你可以通過 canSee
方法鏈接到字段的定義,輕松完成這個操作。canSee
該方法接收一個返回 true
或 false
的一個閉包函數(shù)。然而這個閉包函數(shù)接收
HTTP 的請求對象作為參數(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
方法,來確定授權用戶是否被授權 viewProfile
動作。然而,由于代理授權策略方法是 canSee
的常見用例,你可以使用
canSeeWhen
方法實現(xiàn)相同的行為。canSeeWhen
方法與 Illuminate\Foundation\Auth\Access\Authorizable
trait 的 can
方法有相同的方法簽名:
Text::make('Name')
->sortable()
->canSeeWhen('viewProfile', $this),
授權 > 「can」方法
想了解更多關于 Laravel 授權和
can
方法的信息,請查看完整的 Laravel 授權文檔 。
如果你希望過濾數(shù)據(jù)在關聯(lián)數(shù)據(jù)中的展示,你可以在 Nova 資源中覆蓋 relatableQuery
方法。
例如,如果你的項目中有一個 Comment
資源屬于一個 Podcast
資源。在創(chuàng)建一個 Comment
資源時,Nova 將允許你選擇他歸屬的 Podcast
資源。為了在選項中限制用戶能選擇的 Podcast
,你應該在 Podcast
資源中覆蓋 relatableQuery
方法:
/**
* 為資源構建可關聯(lián)過濾。
*
* 這個查詢條件決定了哪些實例可以在關聯(lián)選項中被選擇。
*
* @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);
}
如果你的應用程序使用了強大的 Laravel Scout 搜索擴展,你可以自定義 Laravel\Scout\Builder
查詢實例,然后將其提供個查詢服務提供者。如果你要完成這個操作,請復寫你資源上的 scoutQuery
方法
/**
* 為給定的資源構建一個 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);
}
更多建議: