2 回答
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);
}
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中定义的那样
- 2 回答
- 0 关注
- 120 浏览
添加回答
举报