Skip to content

Commit 76d37fc

Browse files
Improved verification of user access to controllers and actions
1 parent c65491b commit 76d37fc

File tree

6 files changed

+140
-22
lines changed

6 files changed

+140
-22
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
use yii\db\Migration;
4+
5+
/**
6+
* Initializing roles
7+
*/
8+
class m240112_225911_add_column_to_roles_table extends Migration
9+
{
10+
public function up()
11+
{
12+
$this->addColumn('roles', 'parameters', 'text');
13+
}
14+
15+
public function down()
16+
{
17+
$this->dropColumn('roles', 'parameters');
18+
}
19+
}

src/controllers/UserController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*/
1515
class UserController extends ParentController
1616
{
17-
public $controller_id = 1;
17+
public $controller_id = 1001;
1818

1919
public $full_access_actions = ['login', 'logout'];
2020

src/models/Menu.php

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace ZakharovAndrew\user\models;
4+
5+
use Yii;
6+
use ZakharovAndrew\user\models\User;
7+
8+
/**
9+
* Menu
10+
*/
11+
class Menu extends \yii\base\Model
12+
{
13+
/**
14+
* Get menu for NavBar
15+
* @return array
16+
*/
17+
public static function getNavBar()
18+
{
19+
$controllersAccessList = Yii::$app->getModule('user')->controllersAccessList;
20+
21+
$list = User::getAccessList(Yii::$app->user->id);
22+
23+
// menu items
24+
$items = [];
25+
26+
foreach ($controllersAccessList as $controller_id => $params) {
27+
if (isset($list[$controller_id])) {
28+
$actions = explode(',', $list[$controller_id]);
29+
30+
//перебираем
31+
foreach ($params as $link => $title) {
32+
33+
34+
$arr = explode('/', $link);
35+
if ($list[$controller_id] == '*' || in_array(end($arr), $actions)) {
36+
$items[] = ['label' => $title, 'url' => [$link]];
37+
}
38+
}
39+
}
40+
}
41+
42+
return $items;
43+
}
44+
}

src/models/Roles.php

+25-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* @property string $title
1414
* @property string|null $description
1515
* @property string|null $created_at
16+
* @property string|null $parameters
1617
*/
1718
class Roles extends \yii\db\ActiveRecord
1819
{
@@ -32,7 +33,7 @@ public function rules()
3233
return [
3334
[['title'], 'required'],
3435
[['description'], 'string'],
35-
[['created_at'], 'safe'],
36+
[['parameters', 'created_at'], 'safe'],
3637
[['title', 'code'], 'string', 'max' => 255],
3738
];
3839
}
@@ -47,6 +48,7 @@ public function attributeLabels()
4748
'title' => Module::t('Title'),
4849
'description' => Module::t('Description'),
4950
'code' => Module::t('Code'),
51+
'parameters' => Module::t('Parameters'),
5052
'created_at' => 'Created At',
5153
];
5254
}
@@ -60,4 +62,26 @@ public static function getRolesList()
6062

6163
return ArrayHelper::map($arr, 'id', 'title');
6264
}
65+
66+
/**
67+
* Get all user roles with available controller actions
68+
*
69+
* @param integer $user_id User ID
70+
* @return mixed
71+
*/
72+
public static function getRolesByUserId($user_id)
73+
{
74+
return Yii::$app->cache->getOrSet('get_roles_by_user_'.$user_id, function () use ($user_id) {
75+
return static::find()
76+
->select('roles.*')
77+
->leftJoin('user_roles', 'user_roles.role_id = roles.id')
78+
->where(['user_roles.user_id' => $user_id])
79+
->all();
80+
}, 10);
81+
}
82+
83+
public function getParametersList()
84+
{
85+
return json_decode($this->parameters) ?? [];
86+
}
6387
}

src/models/User.php

+45-16
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,40 @@ public static function getSexList()
113113
2 => Module::t('Female'),
114114
];
115115
}
116+
117+
public static function getAccessList($user_id)
118+
{
119+
$controllersAccessList = Yii::$app->getModule('user')->controllersAccessList;
120+
121+
$roles = Roles::getRolesByUserId($user_id);
122+
123+
$list = [];
124+
foreach ($roles as $role) {
125+
if ($role->code == 'admin') {
126+
$list = array_combine(array_keys($controllersAccessList), ['*']);
127+
break;
128+
}
129+
130+
foreach ($role->getParametersList() as $controller_id => $actions) {
131+
if ($actions == '*') {
132+
$list[$controller_id] = '*';
133+
break;
134+
}
135+
136+
$arrAction = explode(',', $actions);
137+
138+
if (isset($list[$controller_id]) && $list[$controller_id] != '*') {
139+
$arr = explode(',', $list[$controller_id]);
140+
141+
$list[$controller_id] = array_merge($arr, $arrAction);
142+
} else if (!isset($list[$controller_id])) {
143+
$list[$controller_id] = $actions;
144+
}
145+
}
146+
}
147+
148+
return $list;
149+
}
116150

117151
/**
118152
* Checking the ability to perform the action of the selected controller
@@ -123,27 +157,22 @@ public static function getSexList()
123157
*/
124158
public static function isActionAllowed($user_id, $controller_id, $action)
125159
{
126-
$roles_id = \yii\helpers\ArrayHelper::getColumn(
127-
UserRoles::find()->select('role_id')->where(['user_id' => $user_id])->asArray()->all(),
128-
'role_id'
129-
);
130-
131-
$roles = \yii\helpers\ArrayHelper::getColumn(
132-
Roles::find()
133-
->select('code')
134-
->where(['IN', 'id', $roles_id])
135-
->asArray()
136-
->all(),
137-
'code'
138-
);
139-
160+
// check god mode
161+
$roles = \yii\helpers\ArrayHelper::getColumn(UserRoles::getUserRoles($user_id), 'code');
140162
if (in_array('admin', $roles)) {
141163
return true;
142164
}
143165

144-
//other checking
166+
// check access
167+
$accessList = static::getAccessList($user_id);
168+
169+
if (!isset($accessList[$controller_id])) {
170+
return false;
171+
}
172+
173+
$arr = explode(',', $accessList[$controller_id]);
145174

146-
return false;
175+
return ($accessList[$controller_id] == '*' || in_array($action, $arr));
147176
}
148177

149178
/**

src/models/UserRoles.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ public function attributeLabels()
6060
*/
6161
public static function getUserRoles($user_id)
6262
{
63-
return Yii::$app->cache->getOrSet('get_users_roles'.$user_id, function () use ($user_id) {
63+
return Yii::$app->cache->getOrSet('get_users_roles_'.$user_id, function () use ($user_id) {
6464
return static::find()
65-
->select('user_roles.*, roles.title')
65+
->select('user_roles.*, roles.title, roles.code')
6666
->leftJoin('roles', 'user_roles.role_id = roles.id')
6767
->where(['user_roles.user_id' => $user_id])
68+
->asArray()
6869
->all();
69-
}, 3600);
70+
}, 10);
7071
}
7172

7273
/**
@@ -75,6 +76,7 @@ public static function getUserRoles($user_id)
7576
public function afterSave($insert, $changedAttributes)
7677
{
7778
parent::afterSave($insert, $changedAttributes);
78-
Yii::$app->cache->delete('get_users_roles'.$this->user_id);
79+
Yii::$app->cache->delete('get_users_roles_'.$this->user_id);
80+
Yii::$app->cache->delete('get_roles_by_user_'.$this->user_id);
7981
}
8082
}

0 commit comments

Comments
 (0)