Laravel 5:如果用户是帖子的所有者或论坛类别的所有者,则允许用户编辑帖子

时间:2015-10-05 14:26:58

标签: php mysql laravel laravel-5 eloquent

到目前为止,我能够允许用户编辑自己的帖子,但每当我通过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-postmod-update-post。使用@can('update-post', $post)只能使用一次,我不能仔细检查。

3 个答案:

答案 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()]