Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5: allow user to edit post if he's the owner of the post or the owner of the forum category

So far I was able to allow the user to edit his own posts but whenever I through the if he's owner of the subreddit/category condition, it stops working altogether.

I have these 3 table

Users: id, name, email...
Subreddits: id, name, user_id...
Posts: id, link, title, user_id, subreddit_id...

This is the edit() method in 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);
        }
    }

And this is the view

@if(Auth::id() == $post->user_id)
      <a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
@endif

This works fine, it only checks if the logged in user_id is the same as the posts's user_id and updating goes through.

But if I added if(Auth::id() == $subreddit->user_id) it stops working. It displays the "Edit" link on the view on all the posts but clicking on any of them gives me the validation error You cannot do that even for posts that I own.

So how can I check if the users is the owner of the article OR the owner of the category to display and allow EDIT?

Updated method with $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');
        }
    }

View

@if(Auth::id() == $post->user_id || Auth::id() == $subreddit->user_id)
      <a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
@endif

This will allow me to edit my own posts but will still give me the validation error You cannot do that on posts in my own forum category/subreddit.

This is the Gate policies that I've tried but it also didn't work

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);
    }
    }

View

@can('update-post', $post)
     <a href="{{ action('PostsController@edit', [$post->id]) }}">Edit</a>
@endcan

With the above code, I am finally able to edit posts if 'update-post' is true but I cannot check if mod-update-post is also true, I keep receiving the validation error You cannot do this

dd($subreddit) inside edit() method shows an empty array. https://cryptbin.com/x6V6wX#26810f755a62f6c8837c0c0fe0371dcf

EDIT: I think I've solved it. I used $post->subreddit->user->id instead of $subreddit->user_id because that was returning null. And now it all seems to work based on if posts belongs to user or user is forum owner.

But the edit link on the view still shows whether or not I have access. I am unable to double check for update-post and mod-update-post simultaneously. and using @can('update-post', $post) only works once, I cannot double check that.

like image 765
Halnex Avatar asked Oct 05 '15 14:10

Halnex


1 Answers

So how can I check if the users is the owner of the article OR the owner of the category to display and allow EDIT?

Use Laravel’s new authorization component.

EDIT: I think you’re misunderstanding how authorization should be used. It should be used to check if the current user can perform an action (or not). Therefore, you don’t want to be defining multiple methods for different users types.

Take editing a post for example. There’s the name of your authorization check: @can('edit', $post). You don’t need to define a different one for regular users, and another for moderators. Just add the logic to your edit post method:

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;
    }
}

As you can see, I’m doing the different checks in the same method, so in your Blade template you can just do this:

@can('edit', $post)
    <a href="{{ route('post.edit', $post->getRouteKey()) }}">Edit post</a>
@endcan

Hope this clears things up.

like image 157
Martin Bean Avatar answered Oct 03 '22 01:10

Martin Bean