到目前为止,我能够允许用户编辑自己的帖子,但每当我通过if he's owner of the subreddit/category
条件时,它都会完全停止工作。
我有这3个表
Users: id, name, email...
Subreddits: id, name, user_id...
Posts: id, link, title, user_id, subreddit_id...
这是edit()
PostsController.php
方法
public function edit(Post $post, Subreddit $subreddit)
{
if(Auth::id() !== $post->user_id) {
return view('home')->withErrors('You cannot do that');
} else {
return view('post/edit')->with('post', $post)->with('subreddit', $subreddit);
}
}
这是视图
@if(Auth::id() == $post->user_id)
<a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
@endif
这样可以正常工作,它只检查登录的user_id是否与帖子的user_id相同,并且更新是否通过。
但如果我添加if(Auth::id() == $subreddit->user_id)
它就会停止工作。它在所有帖子的视图上显示“编辑”链接,但点击其中任何一个都会给我验证错误You cannot do that
,即使对于我拥有的帖子也是如此。
那么如何检查用户是文章的所有者还是要显示的类别的所有者并允许编辑?
使用$subreddit->user_id
public function edit(Post $post, Subreddit $subreddit)
{
if(Auth::id() == $post->user_id || Auth::id() == $subreddit->user_id) {
return view('post/edit')->with('post', $post)->with('subreddit', $subreddit);
} else {
return view('home')->withErrors('You cannot do that');
}
}
查看
@if(Auth::id() == $post->user_id || Auth::id() == $subreddit->user_id)
<a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
@endif
这将允许我编辑自己的帖子,但仍会在我自己的论坛类别/ subreddit中的帖子上给我验证错误You cannot do that
。
这是我尝试的Gate
政策,但它也无效
class AuthServiceProvider extends ServiceProvider
{
// Authorizations and Permissions
public function boot(GateContract $gate)
{
parent::registerPolicies($gate);
$gate->define('update-post', function ($user, $post) {
return $user->id === $post->user_id;
});
$gate->define('mod-update-post', function ($user, $subreddit) {
return $user->id === $subreddit->user_id;
});
}
PostsController.php
public function edit(Post $post, Subreddit $subreddit, User $user)
{
if(Gate::denies('update-post', $post) && Gate::denies('mod-update-post', $subreddit)) {
return view('home')->withErrors('You cannot do that');
} else {
return view('post/edit')->with('post', $post)->with('subreddit', $subreddit);
}
}
查看
@can('update-post', $post)
<a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
@endcan
使用上面的代码,如果'update-post'为true,我终于能够编辑帖子但是我无法检查mod-update-post
是否也是如此,我一直收到验证错误You cannot do this
dd($subreddit)
里面的edit()方法显示一个空数组。 https://cryptbin.com/x6V6wX#26810f755a62f6c8837c0c0fe0371dcf
$post->subreddit->user->id
而不是$subreddit->user_id
,因为它返回null。现在,如果帖子属于用户或用户是论坛所有者,那么这一切似乎都有效。
但视图上的编辑链接仍然显示我是否有权访问。我无法同时仔细检查update-post
和mod-update-post
。使用@can('update-post', $post)
只能使用一次,我不能仔细检查。
答案 0 :(得分:6)
那么如何检查用户是文章的所有者还是要显示的类别的所有者并允许编辑?
使用Laravel的新authorization component。
编辑:我认为您误解了应该如何使用授权。它应该用于检查当前用户是否可以执行操作(或不执行)。因此,您不希望为不同的用户类型定义多个方法。
以编辑帖子为例。您的授权检查名称为@can('edit', $post)
。您不需要为常规用户定义不同的用户,也不需要为管理员定义另一个用户。只需将逻辑添加到编辑帖子方法:
class PostPolicy
{
public function edit(User $user, Post $post)
{
// If user is administrator, then can edit any post
if ($user->isModerator()) {
return true;
}
// Check if user is the post author
if ($user->id === $post->author_id) {
return true;
}
return false;
}
}
正如您所看到的,我正在使用相同的方法进行不同的检查,因此在您的Blade模板中,您可以执行此操作:
@can('edit', $post)
<a href="{{ route('post.edit', $post->getRouteKey()) }}">Edit post</a>
@endcan
希望这可以解决问题。
答案 1 :(得分:0)
替代技术(也许会更简单一些)在这里描述:
https://laracasts.com/discuss/channels/laravel/dont-allow-user-to-change-others-posts
因此,这个想法是实现Request的子类,您可以在其中实现验证规则,还可以在其中实现“授权”方法。
答案 2 :(得分:0)
您还可以按照规则在App \ Http中创建新文件夹:
并添加一个新的Rule文件:
<?php
namespace App\Http\Rules;
use Illuminate\Contracts\Validation\Rule;
use App\Models\Post;
class IsOwner implements Rule
{
public function passes($attribute, $value)
{
return auth()->user()->id == Post::find($value)->user_id;
}
public function message()
{
return 'You are forbidden from taking this action!';
}
}
然后,我仅导入此类并用作验证规则:'post' => ['required', new IsOwner()]