Reputation: 6007
I'm using this structure of user levels:
Company Owner
- Group Manager
-- Unit Manager
---Employee
I need to control users to access the datas in the database. Employee can access only that datas what he stored. The unit manager can access his own datas and datas of his emplyee too. Group manager can access to entire group's datas. And the company owner can acceess to everything.
I have some controllers like this:
class ClientController extends Controller
{
public function index()
{
return Client::all();
}
// ...
}
What is the best practice in Laravel to control access to datas (not the controller) in some controllers, but not everywhere? Is here a good implementation for this issue?
Upvotes: 1
Views: 2854
Reputation: 6007
Maybe the question wansn't clear enough, but I found a solution:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Auth;
use App\User;
class DataAccessScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
// find the actual user
$user_id = Auth::user()->id;
$user = User::find( $user_id );
// get all employees
$employees = $user->allEmployeeFlatten();
// get only the employee's ids
$user_ids = $employees->pluck('id');
// add current user's id too
$user_ids->push( $user_id );
// add the condition to every sql query
$builder->whereIn('user_id', $user_ids);
}
}
Here is the User
model's allEmployeeFaletten()
function:
public function allEmployeeFlatten() {
$employees = new Collection();
foreach ( $this->employee()->get() as $employee ) {
$employees->push( $employee );
// run only if the user is on a leader level
if ( $employee->user_role_id != 5 ) {
$employees = $employees->merge( $employee->allEmployeeFlatten() );
}
}
return $employees;
}
This scope add a condition to all SQL queries every time I use the scope.
Upvotes: 0
Reputation: 1340
middleware is the right place for access control. For group middleware you can use by this format
Route::group(['middleware' => ['role:Company Owner']], function() {
Route::get('/', 'AdminController@welcome');
Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController@manageAdmins']);
});
Route::group(['middleware' => ['role:Employee']], function() {
Route::get('/', 'AdminController@welcome');
Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController@manageAdmins']);
});
For single route
Route::put('post/{id}', function ($id) {
//
})->middleware('role:Employee');
You can use a package for user role base access control
Upvotes: 0
Reputation: 1029
In Route. One good place for all middleware.
Route::get('/', function () { ... })->middleware('web');
Upvotes: 0
Reputation: 654
You can create a middleware for each role, then in your web.php file, use route groups to assign access to the routes that the users can access. So for a route that both employee and unit manager can access, you pass the two middleware, for those that only group manager can access, you just pass group manager.
Route::group(['middleware' => ['auth', 'group-manager','unit-manager']],
function() {
Route::get('client','ClientController@index');
});
Upvotes: 1