Laravel 嵌套浅层资源的策略

oli*_*rbj 5 php laravel

我定义了以下路线:

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

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

上面生成了以下 url:

| 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                                     |
Run Code Online (Sandbox Code Playgroud)

关系如下:

Properties hasMany Leases.
Leases hasMany Invoices.
Run Code Online (Sandbox Code Playgroud)

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

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

在我的文章中,AuthServiceProvider我定义了以下政策:

| 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                                     |
Run Code Online (Sandbox Code Playgroud)

在我的文件中LeaseController,我定义了授权检查:

Properties hasMany Leases.
Leases hasMany Invoices.
Run Code Online (Sandbox Code Playgroud)

看起来LeasePolicy像这样:

protected $policies = [
    Lease::class => LeasePolicy::class,
    Invoice::class => InvoicePolicy::class,
];
Run Code Online (Sandbox Code Playgroud)

在我的文章中InvoiceController我已经定义了这一点:

public function __construct()
{
    $this->authorizeResource(Lease::class, 'lease');
}
Run Code Online (Sandbox Code Playgroud)

看起来InvoicePolicy像这样:

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);
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我有很多位于/lease/{lease}/{model}路线“下方”的路线,例如:

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

对于这些,我如何定义Policies只有有权查看这些资源的用户才能访问?

Yus*_* T. 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);

        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果你想变得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);
    }
}
Run Code Online (Sandbox Code Playgroud)