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