In my laravel app I have multiple user accounts who have resources that are assigned to them. Say, for example, a "payment". To edit or view a payment a user would visit the /payment/edit/{payment}
route (where payment
is the payment ID).
Although I have an auth filter to stop un-logged in users from accessing this page there is nothing to stop, for example, user 1 from editing user 2's payment.
Is there a filter I can user that checks which user a payment (or any other resource) belongs to prevent this kind of issue?
[I am using Laravel's model bindings which automatically fetches the model specified by the route rather than me get it in the controller using eloquent.]
No such filter exists by default, however you can easily create one (depending on how your database is set up). Within app/filters.php, you may do something like this:
Route::filter('restrictPermission', function($route)
{
$payment_id = $route->parameter('payment');
if (!Auth::user()->payments()->find($payment_id)) return Redirect::to('/');
});
This compares the currently logged in user's payment_id (in your database) to the {payment} argument passed into the route. Obviously, depending on how your database is set up (for instance if the payment_id is in a separate table) you need to change the conditional.
Then, apply the filter to your route:
Route::get('/payment/edit/{payment}', array('before' => 'restrictPermission'));
One way is to place a where statement in every relevant query. Although not very pretty, it works.
$payment = Payment::where('user_id', '=', Auth::user()->id)->find($id);
It's also possible to use url filters like seeARMS is suggesting, however I think it's not very elegant. The most logical place to nest such logic is in the model itself. One possibility is to use model events, but this gives you only the option to intercept update, insert or delete statements, not selects. This might change in the future. Maybe you could use boot()
event, but I'm not sure if this is gonna work.
Last but not least you could use query scopes.
class Payment extends Eloquent {
public function scopeAuthuser($query)
{
return $query->where('user_id', '=', Auth::user()->id);
}
}
and in the queries you attach the scope
Payment::authuser()->find($id);
You could do this on a base Model and extend from it, so you have that method in all your relevant models.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With