为了账号安全,请及时绑定邮箱和手机立即绑定

允许根据设置的权限以及 Laravel 中模型的属性值编辑模型

允许根据设置的权限以及 Laravel 中模型的属性值编辑模型

PHP
陪伴而非守候 2023-06-30 16:05:03
我有一个位置模型,其中包含两个属性:ID 和名称。为了编辑这个模型,我设置了这条路线:Route::get('administration/location/{location}/edit', 'LocationController@edit')->name('location.edit');我设置了非常简单的权限:在AuthServiceProvider我正在检查boot以下方法中Gate::before(function ($user, $permission) {    if ($user->permissions->pluck('name')->contains($permission)) {        return true;    }});其中permission是包含 ID 和名称的模型,通过permission_user表映射。我设置了这些权限:编辑洛杉矶编辑纽约编辑波士顿与位置无关的大量其他权限经过所有这些漫无目的的讨论,我真正的问题是:如何将这些权限与编辑位置联系起来?我面临的问题是,不允许给定用户编辑所有位置,而只能允许编辑一个位置。只有具有权限的用户edit_los_angeles才可以编辑Location名称为 的文件Los Angeles。因此,我无法将其分组为一个权限,例如edit_location并将其添加到我的路线中->middleware('can:edit_location')。相反,我想我需要这样的东西:Route::get('administration/location/{location}/edit', 'LocationController@edit')->name('location.edit')->middleware('can:edit_los_angeles');Route::get('administration/location/{location}/edit', 'LocationController@edit')->name('location.edit')->middleware('can:edit_new_york');Route::get('administration/location/{location}/edit', 'LocationController@edit')->name('location.edit')->middleware('can:edit_boston');...显然这是行不通的。你会采取什么方法来解决这个困境?:-)也许我做的事情完全错误,并且有更好的 Laravel-Way 来做到这一点?非常感谢您提前提供的帮助!我正在使用 Laravel 6.0 :-)
查看完整描述

2 回答

?
FFIVE

TA贡献1797条经验 获得超6个赞

我的工作方法有两个假设,在控制器中使用模型绑定(无论如何你都应该这样做)。其次,位置与其所需的权限之间需要存在某种关系,类似于您建议的slug。


你的控制器功能看起来像这样。添加 FormRequest 是执行此逻辑的好方法。


class LocationController {

     public function edit(EditLocationRequest $request, Location $location) { // implicit model binding

         ...

     }

}

为了方便使用,我也会制定一个政策。


class LocationPolicy

{

    public function edit(User $user, Location $location) {

        return $user->permissions->pluck('name')

            ->contains($location->permission_slug); // assuming we have a binding

    }

}

请记住在 中注册策略AuthServiceProvider.php。


protected $policies = [

    Location::class => LocationPolicy::class,

];

现在,在您的表单请求中使用授权方法中的策略。从这里,您处于请求上下文中,您可以访问用户,$this->user()并且可以访问在其名称上绑定模型的所有模型,例如$this->location。


class EditLocationRequest

{

    public function authorize(): bool

    {

        return $this->user()->can('edit', $this->location);

    }

}

现在您应该只能有一个路由定义。


Route::get('administration/location/{location}/edit', 'LocationController@edit')->name('location.edit');

编辑


如果您使用 AuthorizesRequests 特征,则无需表单请求即可执行以下操作。这将抛出一个 AuthorizationException 失败。


use AuthorizesRequests;


public function edit() {

    $this->authorize('edit', $location);

}


查看完整回答
反对 回复 2023-06-30
?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

如果您有基于位置关系的要求,那么您将需要在数据中捕获该关系。一个好的起点是添加特定于这些编辑权限的数据透视表。考虑一个表,location_permissions,带有 auser_id和 a location_id。然后,一旦您拥有特定的用户和位置,您就可以修改或添加权限中间件来检查此表中的记录。


编辑:回答有关中间件实现的问题,


通过这个新的数据透视表定义用户模型与位置的关系可能会解决实现的关键问题。


我建议添加一个额外的方法,该方法locations按照以下方式消耗与模型的新关系


public function canEditLocation(Location $location): bool { 


   return $this->locations

               ->where('location_id', '=', $location->id)

               ->count() > 0; 

    }

实际的中间件是这样的:


public function handle($request, Closure $next, $location)

    {

        if (! $request->user()->canEditLocation($location)) {

            \\handle failed permission as appropriate here.

        }


        return $next($request);

    }

我的中间件参数知识很生疏,但我相信这是正确的,如https://laravel.com/docs/master/middleware#middleware-parameters中定义的那样


查看完整回答
反对 回复 2023-06-30
  • 2 回答
  • 0 关注
  • 120 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信