Skip to content

Instantly share code, notes, and snippets.

@aelfannir
Last active December 22, 2020 08:10
Show Gist options
  • Save aelfannir/f53c25fc7fb58ebe9faeeedd3036fae2 to your computer and use it in GitHub Desktop.
Save aelfannir/f53c25fc7fb58ebe9faeeedd3036fae2 to your computer and use it in GitHub Desktop.
User Role managment
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
/**
* Class User
* @package App
*/
class User extends Authenticatable
{
//...
public const ROLE_VISITOR = "ROLE_VISITOR";
public const ROLE_PROVIDER = "ROLE_PROVIDER";
public const ROLE_CLIENT = "ROLE_CLIENT";
public const ROLE_SUPER_ADMIN = "ROLE_SUPER_ADMIN";
protected static $roleHierarchy = [
self::ROLE_SUPER_ADMIN => ['*'],
self::ROLE_PROVIDER => [self::ROLE_VISITOR],
self::ROLE_CLIENT => [self::ROLE_VISITOR],
self::ROLE_VISITOR => []
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'roles'=>'array'
];
/***
* @param $role
* @return mixed
*/
public function hasRole($role)
{
return in_array($role, $this->getRoles());
}
/**
* @return array
*/
public function getRoles()
{
$roles = $this->getAttribute('roles');
if (is_null($roles)) {
$roles = [];
}
return $roles;
}
/**
* @param string $role
* @return array
*/
public static function getAllowedRoles(string $role)
{
if (isset(self::$roleHierarchy[$role])) {
return self::$roleHierarchy[$role];
}
return [];
}
public function check(User $user, string $role)
{
//todo use current model
// Admin has everything
if ($user->hasRole(self::ROLE_SUPER_ADMIN)) {
return true;
}
else if($user->hasRole(self::ROLE_CLIENT)) {
$managementRoles = $this->getAllowedRoles(self::ROLE_CLIENT);
if (in_array($role, $managementRoles)) {
return true;
}
}
return $user->hasRole($role);
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
//...
$table->json('roles')->nullable()->default(new Expression('(JSON_ARRAY("ROLE_VISITOR"))'));
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use App\User;
use App\RoleChecker;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
/**
* Class CheckUserRole
* @package App\Http\Middleware
*/
class CheckUserRole
{
/**
* @var RoleChecker
*/
protected $roleChecker;
/**
* CheckUserRole constructor.
* @param RoleChecker $roleChecker
*/
public function __construct(RoleChecker $roleChecker)
{
$this->roleChecker = $roleChecker;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$roles
* @return mixed
*/
public function handle($request, Closure $next, ...$roles)
{
if(!in_array(User::ROLE_VISITOR,$roles) && !Auth::check()) {
return response($roles,Response::HTTP_UNAUTHORIZED);
}
if ( ! $this->roleChecker->check(Auth::guard()->user(), $roles)) {
return response(null,Response::HTTP_FORBIDDEN);
}
return $next($request);
}
}
<?php
declare(strict_types=1);
namespace App\Providers;
use App\Http\Middleware\CheckUserRole;
use App\RoleChecker;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
/**
* Class AppServiceProvider
* @package App\Providers
*/
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//...
$this->app->singleton(CheckUserRole::class, function(Application $app) {
return new CheckUserRole(
$app->make(RoleChecker::class)
);
});
}
//...
}
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
//...
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
//...
'check_user_role' => \App\Http\Middleware\CheckUserRole::class,
];
}
<?php
//...
public function __construct()
{
$this->middleware('auth:api', ['except' => ['index']]);
$this->middleware('check_user_role:' .implode(',',[User::ROLE_CLIENT]))->only(['show','store']);
}
public function index()
{
//...
}
public function show()
{
//...
}
public function store()
{
//...
}
public function update()
{
//...
}
public function destroy()
{
//...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment