比方说,我们有政策,我们的模型,可以在一堆不同的场景返回false
在行动:
class PostPolicy
{
public function publish(User $user, Post $post)
{
if ($post->user_id !== $user->id) {
return false;
}
return $post->show_at->lessThan(now());
}
}
正如你所看到的,我们拒绝这个用户他的发布权在两种情况下:如果不是他的职位,或者该职位是提前准备将来的某一天即尚未到期。
我怎么能提供一些背景,为什么授权失败?是不是因为我们不是业主或者是它,因为它不是时间却为要发布这个帖子?
$user->can('publish', $post); // if this returns false we don't know
// what caused authorization to fail.
它看起来是由设计Laravel政策并没有这样做的任何方式。不过我很好奇,什么解决办法在那里都不可能使我们可以有授权逻辑(无论多么复杂)在一个地方(模型的政策),也得到一些上下文(即,自定义错误代码)时,授权失败。
有任何想法吗?
如果控制器使用的是一样的政策:
<?php
$this->authorize('publish', Post::class)
然后laravel都将有403类HTTPResponse错误。
你应该做的是,一个策略方法应该只检查一个验证的情况下。
例如更新你的政策:
<?php
// Check if post he is trying to publish is his own
public function publishOwnPost(){...}
// Check if post is for future purpose
public function publicFuturePost(){...}
然后,在控制器做:
<?php
if(!$user->can('publishOwnPost', $post)){
// Return custom error view for case 1
return response()->view('errors.publishOwnPostError', $data, 403);
}
if(!$user->can('publishFuturePost', $post)){
// Return custom error view for case 2
return response()->view('errors.publishFuturePostError', $data, 403);
}
// Do further processing
我落得这样做是分裂的一些模型之间的责任和它的政策。
政策最终负责确保用户做了具体的行动的权利。没有更多或更少:
class PostPolicy
{
public function publish(User $user, Post $post)
{
return $post->user_id !== $user->id;
}
}
在另一方面型号必须具有逻辑来检查是否某些动作可以用它来进行:
class Post extends Model
{
...
public function isPublishable()
{
return $this->show_at->lessThan(now());
}
...
}
因此现在每个岗位的实例可以告诉我们它是否可以发布。最后我Post::publishBy(User $user)
行动将包括第一授权用户的这一行动,并检查,如果这个职位可以单独发布,以便我们能够确定具体原因为何发布失败。
我觉得像这样的设计适合更好,更让他们应该做的(授权用户操作),并要求模型负责的事情,只关心他们有什么Laravel政策,只能做。