netdjw
netdjw

Reputation: 6007

Laravel middleware for control user access to datas

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

Answers (4)

netdjw
netdjw

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

Zahid Hassan Shaikot
Zahid Hassan Shaikot

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

https://github.com/Zizaco/entrust

Upvotes: 0

FAEWZX
FAEWZX

Reputation: 1029

In Route. One good place for all middleware.

Route::get('/', function () {  ...  })->middleware('web');

Upvotes: 0

Toby Okeke
Toby Okeke

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

Related Questions