Search code examples
phpauthenticationfilterlaravel-5middleware

Laravel 5 - Only Owner (creator) can edit/delete/view Entry


I'm new to Laravel and have a little Question.

I want to accomplish that just the Creator/Owner of a post can edit/view/delete it.

Each Post belongs to a User and each User can have multiple Posts (1-to-Many relationship). That part works like a charm.

To be more specific, if one of these routes is called:

GET mydomain.com/posts/{id} (show)

GET mydomain.com/posts/{id}/edit (edit)

PUT mydomain.com/posts/{id} (update)

DELETE mydomain.com/posts/{id} (destroy)

the application should check if the currently authenticated user's id matches the posts user_id field.

As far as I know this is not possible with a middleware because the middleware does not have access to the current Post-Object and I can't pass a paramenter to it.

Currently I was able to accomplish my goal with a filter (I use Route-Model binding).

Route::filter('isOwnerOfPost', function() {
 if(Route::input('posts')->user_id !==  \Auth::id()) {
    abort(403);
 };
});

Route::get('posts', 'PostController@index');
Route::group(['before' => 'isOwnerOfPost'], function(){
 Route::resource('posts', 'PostController', ['except' => ['index', 'create', 'store']]);
});

But this solution seems a bit messy to me. I would have to create a new filter for every Model and I can't use resourceful routing (at least not completely).

Is there a better way to accomplish such a behavior?


Solution

  • I was able to solve it with a middleware. The following code only works if route model binding for the parameter is 'active'.

    I don't really know if this is the right way to do this, but it seems to work...

    public function handle($request, Closure $next)
    {
        $requestParameters = $request->route()->parameters();
    
        foreach ($requestParameters as $requestParameter) {
            // Loop through route parameters
            if (gettype($requestParameter) === "object") {
                // Route Model Binding is active for this parameter
                if (isset($requestParameter->user_id)) {
                    // Model has an owner (column user_id is set)
                    $owner = $requestParameter->user_id;
    
                    if ($owner !== Auth::id()) {
                        // Authenticated user is the not owner
                        abort(403);
                    }
                }
            }
        }
    
        return $next($request);
    }