Created
March 4, 2022 11:27
-
-
Save mdmunir/d264a64fafef63d771c295d897a7fa10 to your computer and use it in GitHub Desktop.
Laravel access control
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Middleware; | |
use App\Models\Auth; | |
use Closure; | |
use Illuminate\Http\Request; | |
use yii\db\Query; | |
use function abort; | |
use function auth; | |
use function config; | |
use function env; | |
/** | |
* Description of AccessControl | |
* | |
* @author Misbahul D Munir <[email protected]> | |
* @since 1.0 | |
*/ | |
class AccessControl | |
{ | |
/** | |
* Handle an incoming request. | |
* | |
* @param Request $request | |
* @param Closure $next | |
* @return mixed | |
*/ | |
public function handle($request, Closure $next) | |
{ | |
if (!env('ACCESS_CONTROL_ENABLE', false)) { | |
return $next($request); | |
} | |
$allowed = config('auth.allowed_route', []); | |
$route = $request->route(); | |
if ($route && ($name = $route->getName())) { | |
if (in_array($name, $allowed)) { | |
return $next($request); | |
} elseif ($user = auth()->user()) { | |
/* @var $user Auth */ | |
$roles = \yii\helpers\ArrayHelper::getColumn($user->roles, 'role_id'); | |
$query = (new Query()) | |
->from('role_action ra') | |
->where([ | |
'ra.role_id' => $roles, | |
'ra.action' => $name | |
]); | |
if ($query->exists()) { | |
return $next($request); | |
} | |
abort(403, 'Forbiden'); | |
} | |
abort(401, 'Unauthorized'); | |
} | |
return $next($request); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models; | |
use App\Classes\ActiveRecord; | |
use App\Models\RoleAction; | |
use App\Models\RoleMenu; | |
use Dee; | |
use Illuminate\Support\Facades\Route; | |
use yii\behaviors\BlameableBehavior; | |
use yii\behaviors\TimestampBehavior; | |
use yii\db\ActiveQuery; | |
use yii\helpers\Inflector; | |
use function auth; | |
/** | |
* This is the model class for table "roles". | |
* | |
* @property int $id | |
* @property string $name | |
* @property string|null $description | |
* @property int $level | |
* @property bool $active | |
* @property int|null $created_by | |
* @property int|null $updated_by | |
* @property string|null $created_at | |
* @property string|null $updated_at | |
* | |
* @property RoleAction[] $roleActions | |
* @property array $actions | |
*/ | |
class Role extends ActiveRecord | |
{ | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function tableName() | |
{ | |
return 'role'; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function rules() | |
{ | |
return [ | |
[['name'], 'required'], | |
[['level',], 'integer'], | |
[['active'], 'boolean'], | |
[['name', 'description'], 'string', 'max' => 255], | |
]; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function attributeLabels() | |
{ | |
return [ | |
'id' => 'ID', | |
'name' => 'Name', | |
'description' => 'Description', | |
'level' => 'Level', | |
'created_by' => 'Created By', | |
'updated_by' => 'Updated By', | |
'created_at' => 'Created At', | |
'updated_at' => 'Updated At', | |
]; | |
} | |
public function getActions() | |
{ | |
$actions = $this->getSystemRoutes(); | |
foreach ($this->roleActions as $row) { | |
$actions[$row->action] = true; | |
} | |
$result = []; | |
foreach ($actions as $name => $value) { | |
list($group, $action) = explode('.', $name, 2); | |
if(!isset($result[$group])){ | |
$result[$group] = [ | |
'name' => $group, | |
'label' => Inflector::titleize($group), | |
'actions' => [] | |
]; | |
} | |
$result[$group]['actions'][] = [ | |
'name' => $name, | |
'label' => Inflector::titleize($action), | |
'assigned' => $value | |
]; | |
} | |
return array_values($result); | |
} | |
public function getMenus() | |
{ | |
$assigned = RoleMenu::find() | |
->where(['role_id' => $this->id]) | |
->asArray() | |
->indexBy(['menu_id']) | |
->all(); | |
return Menu::resolve($assigned); | |
} | |
public function assignAction(array $actions) | |
{ | |
return Dee::db()->transaction(function()use($actions) { | |
$roleId = $this->id; | |
$userId = auth()->id(); | |
$now = Dee::now(); | |
$deleted = RoleAction::deleteAll(['role_id' => $this->id]); | |
$values = []; | |
foreach ($actions as $row) { | |
if (!empty($row['assigned'])) { | |
$values[] = [$roleId, $row['name'], $now, $now, $userId, $userId]; | |
} | |
} | |
$insert = 0; | |
if (count($values)) { | |
$command = Dee::db()->createCommand(); | |
$columns = ['role_id', 'action', 'created_at', 'updated_at', 'created_by', 'updated_by']; | |
$insert = $command->batchInsert(RoleAction::tableName(), $columns, $values)->execute(); | |
} | |
return [ | |
'deleted' => $deleted, | |
'insert' => $insert, | |
]; | |
}); | |
} | |
public function assignMenu(array $menus) | |
{ | |
return Dee::db()->transaction(function()use($menus) { | |
$roleId = $this->id; | |
$userId = auth()->id(); | |
$now = Dee::now(); | |
$deleted = RoleMenu::deleteAll(['role_id' => $this->id]); | |
$values = []; | |
foreach ($menus as $row) { | |
if (!empty($row['assigned'])) { | |
$values[] = [$roleId, $row['id'], $now, $now, $userId, $userId]; | |
} | |
} | |
$insert = 0; | |
if (count($values)) { | |
$command = Dee::db()->createCommand(); | |
$columns = ['role_id', 'menu_id', 'created_at', 'updated_at', 'created_by', 'updated_by']; | |
$insert = $command->batchInsert(RoleMenu::tableName(), $columns, $values)->execute(); | |
} | |
return[ | |
'deleted' => $deleted, | |
'insert' => $insert, | |
]; | |
}); | |
} | |
/** | |
* Gets query for [[RoleAction]]. | |
* | |
* @return ActiveQuery | |
*/ | |
public function getRoleActions() | |
{ | |
return $this->hasMany(RoleAction::class, ['role_id' => 'id']); | |
} | |
public function behaviors(): array | |
{ | |
return[ | |
TimestampBehavior::class, | |
BlameableBehavior::class, | |
]; | |
} | |
public function extraFields() | |
{ | |
return[ | |
'roleActions', | |
'actions', | |
'menus', | |
]; | |
} | |
private static $_routes; | |
/** | |
* | |
* @return array | |
*/ | |
public function getSystemRoutes() | |
{ | |
if (self::$_routes === null) { | |
// list routes | |
foreach (Route::getRoutes()->getRoutes() as $route) { | |
$name = $route->getName(); | |
if ($name && strncmp($name, 'ignition.', 9) != 0 && strpos($name, '.') > 0) { | |
self::$_routes[$name] = false; | |
} | |
} | |
ksort(self::$_routes); | |
} | |
return self::$_routes; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment