Laravel 嵌套浅层资源的策略

问题描述 投票:0回答:2

我定义了以下路线:

//Leases
Route::resource('properties.leases', LeaseController::class)
        ->only(['show'])
        ->shallow();

//Invoices
Route::resource('leases.invoices', InvoiceController::class)
        ->only(['index', 'show'])
        ->shallow();

上面生成了以下网址:

| GET|HEAD  | leases/{lease}                                             | App\Http\Controllers\LeaseController@show                                       |
| GET|HEAD  | leases/{lease}/invoices                                    | App\Http\Controllers\InvoiceController@index                                    |
| GET|HEAD  | invoices/{invoice}                                         | App\Http\Controllers\InvoiceController@show                                     |

关系如下:

Properties hasMany Leases.
Leases hasMany Invoices.

我正在尝试授权这些路线,因此只有以下用户:

  1. “租赁”和“发票”也属于同一个团队。
  2. 当前已登录该团队。

在我的

AuthServiceProvider
中,我定义了以下政策:

protected $policies = [
    Lease::class => LeasePolicy::class,
    Invoice::class => InvoicePolicy::class,
];

在我的

LeaseController
中我定义了授权检查:

public function __construct()
{
    $this->authorizeResource(Lease::class, 'lease');
}

LeasePolicy
看起来像这样:

public function view(User $user, Lease $lease)
{
    //Does the current user belong to the team that the lease is associated with
    //and is the user's current team the same one?
    $team = $lease->property->team;
    return $user->belongsToTeam($team) && $user->isCurrentTeam($team);
}

在我的

InvoiceController
中我定义了这一点:

public function __construct()
{
    $this->authorizeResource(Invoice::class, 'invoice');
}

InvoicePolicy
看起来像这样:

/**
 * Path: leases/{lease}/{$invoice}
 */
public function viewAny(User $user)
{

    //When users go to this path I can only access $user here. 
    //How to check if the user can even access the $lease.

}

/**
 * Path: invoices/{$invoice}
 */
public function view(User $user, Invoice $invoice)
{
    //Does the current user belong to the team that the lease is associated with
    //and is the user's current team the same one?
    $team = $invoice->lease->property->team;
    return $user->belongsToTeam($team) && $user->isCurrentTeam($team);
}

在我的应用程序中,我有很多位于

/lease/{lease}/{model}
路线“下方”的路线,例如:

//Files
Route::resource('leases.files', FileController::class)
        ->only(['index'])
        ->shallow();

对于这些,我如何定义我的

Policies
,以便只有有权查看这些资源的用户才能访问?

php laravel
2个回答
3
投票

据我在撰写此答案时所知,

authorizeResource
不能用于某些浅层嵌套方法(例如
index
create
store
)。因此,您可以通过控制器助手在每个方法上调用
authorize
函数

或者如果你仍然想使用

authorizeResource

,你只能在一些浅层嵌套方法上手动调用
authorize
,如下例所示:

class InvoiceController extends Controller { public function __construct() { $this->authorizeResource(Invoice::class, 'invoice'); } /** * Get the map of resource methods to ability names. * * @return array */ protected function resourceAbilityMap() { return collect(parent::resourceAbilityMap()) ->except(['index', 'create', 'store']) ->all(); } /** * Display a listing of the resource. * * @param \App\Models\Lease $lease * @return \Illuminate\Http\Response */ public function index(Lease $lease): Response { $this->authorize('view', $lease); ... } }
顺便说一句,如果你想让

InvoicePolicy

更简单,你也可以重用
LeasePolicy
,就像下面的代码:

class InvoicePolicy { use HandlesAuthorization; public function __construct( protected LeasePolicy $leasePolicy, ) { } /** * Determine whether the user can view the model. * * @param \App\Models\User $user * @param \App\Models\Invoice $invoice * @return \Illuminate\Auth\Access\Response|bool */ public function view(User $user, Invoice $invoice): bool { return $this->leasePolicy->view($user, $invoice->lease); } }
    

0
投票
不再需要手动注册策略,

InvoicePolicy

将被注册为
Invoice
策略(请参阅
策略发现)。

namespace App\Policies; use App\Models\Invoice; use App\Models\Lease; use App\Models\User; class InvoicePolicy { public function viewAny(User $user, Lease $lease): bool { // } public function view(User $user, Invoice $invoice, Lease $lease): bool { // } }
传递给 

authorize

 方法的数组的第一个元素决定将使用哪个模型。它可以是实例
类名(请参阅没有模型的方法不需要模型的操作)。

namespace App\Http\Controllers; use App\Models\Invoice; use App\Models\Lease; use App\Models\User; class InvoiceController extends Controller { // leases/{lease}/invoices public function index(Lease $lease) { $this->authorize('viewAny', [ Invoice::class, $lease ]); // } // leases/{lease}/invoices/{invoice} public function show(Lease $lease, Invoice $invoice) { $this->authorize('view', [ $invoice, $lease ]); // } }
    
© www.soinside.com 2019 - 2024. All rights reserved.