This is actually not too difficult, but it does require a bit of setup for the middleware to be able to detect which resource is being loaded. This is accomplished by using Route-Model Binding
Example resource routes:
Route::group(['middleware' => 'BelongsToAccount'], function() {
Route::resource('asset', 'AssetController');
Route::resource('liability', 'LiabilityController');
});
Now, we need to bind the resources in RouteServiceProvider
so our routes will load the resources:
/**
* Define your route model bindings, pattern filters, etc.
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function boot(Router $router)
{
parent::boot($router);
// bound models
$router->model('asset', 'App\Asset');
$router->model('liability', 'App\Liability');
}
Now go to the middleware's handle
method and dump $request->route()->parameters();
. You should see the resource listed in the parameter list. With the instance of the resource available in the request, the last step is to check for and validate against it in the middleware:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Routing\Middleware;
class BelongsToAccount implements Middleware {
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* @param Guard $auth
* @return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// get the resource from the route
$resource = $this->getResource($request);
if (!empty($resource))
{
if ($this->auth->user()->accountId == $resource->accountId)
{
return $next($request);
}
}
}
/**
* Get resource from route if it exists
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function getResource($request)
{
foreach ($request->route()->parameters() as $param)
{
if ($param instanceof Model) return $param;
}
return null;
}
}
This code above won't be plug and play, you may need to change exactly how you get the accountId
value from your currently logged in user, etc. But the gist of what's going on here is an additional method was added to look for an instance of an Eloquent\Model
. Once it's found, it returns this resource to be used by the middleware and assumes that the resource has an accountId already bound to it.
If you want a more fine control, I'd suggest moving the middleware to the controller's __construct
to more specifically tune which controller actions it works on. You can accomplish this in the routes file as well, though.
Hope this helps!