Oto działające rozwiązanie końcowe.
A więc kolejny dzień, więcej refaktoryzacji.
Moje ostateczne rozwiązanie wykorzystuje funkcję checkAccess w plikach źródłowych DbManager/ManagerInterface, ale dodałem parametr $assignments do przekazania. Główny problem polega na tym, że musiałem zbudować własną listę zadań do sprawdzenia. Upewnij się, że skomentowałeś wiersze, w których ustawiono zmienną $assignments.
Oto mój nowy model dostępu:
<?php
namespace app\models;
use Yii;
class Access
{
public function canUser($type, $permissionName, $params = [])
{
$auth = Yii::$app->authManager;
switch ($type) {
case 'group':
$userID = Yii::$app->user->identity->id;
$groupID = Yii::$app->options->getOption('user', 'active_group_id');
$queryAll = GroupAccess::find()
->where('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID])
->asArray()
->all();
$assignments = [];
foreach ($queryAll as $queryItem) {
$assignments[$queryItem['item_name']] = [
'userId' => $queryItem['user_id'],
'roleName' => $queryItem['item_name'],
'createdAt' => $queryItem['created_date'],
];
}
$result = $auth->checkAccess($userID, $permissionName, $assignments, $params);
return $result;
break;
case 'user':
$userID = Yii::$app->user->identity->id;
$queryAll = UserAccess::find()
->where('user_id = :user_id', [':user_id' => $userID])
->asArray()
->all();
$assignments = [];
foreach ($queryAll as $queryItem) {
$assignments[$queryItem['item_name']] = [
'userId' => $queryItem['user_id'],
'roleName' => $queryItem['item_name'],
'createdAt' => $queryItem['created_date'],
];
}
$result = $auth->checkAccess($userID, $permissionName, $assignments, $params);
return $result;
break;
}
}
public function assign($type, $role, $userID = null, $groupID = null)
{
switch ($type) {
case 'group':
// clear existing assigments
self::revoke('group', $userID, $groupID);
$groupAccess = new GroupAccess();
$groupAccess->group_id = $groupID;
$groupAccess->user_id = $userID;
$groupAccess->item_name = $role;
$groupAccess->created_date = time();
return $groupAccess->save();
break;
case 'user':
// clear existing assignments
self::revoke('user', $userID);
$userAccess = new UserAccess();
$userAccess->user_id = $userID;
$userAccess->item_name = $role;
$userAccess->created_date = time();
return $userAccess->save();
break;
}
}
public function revoke($type, $userID, $groupID = null)
{
switch ($type) {
case 'group':
GroupAccess::deleteAll('user_id = :user_id and group_id = :group_id', [':user_id' => $userID, ':group_id' => $groupID]);
break;
case 'user':
UserAccess::deleteAll('user_id = :user_id', [':user_id' => $userID]);
break;
}
}
}
A oto zmodyfikowana funkcja checkAccess w DbManager:
public function checkAccess($userId, $permissionName, $assignments, $params = [])
{
//$assignments = $this->getAssignments($userId);
$this->loadFromCache();
if ($this->items !== null) {
return $this->checkAccessFromCache($userId, $permissionName, $params, $assignments);
} else {
return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments);
}
}
A oto zmodyfikowana funkcja checkAccess w ManagerInterface.php:
public function checkAccess($userId, $permissionName, $assignments, $params = []);
Nie zmieniłem funkcji $items, checkAccessFromCache i checkAccessRecursive na public z chronionych.
A oto mój model UserAccess:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
/**
* This is the model class for table "app_user_access".
*
* @property integer $id
* @property integer $user_id
* @property string $item_name
* @property integer $created_date
*
* @property AppAuthItem $itemName
* @property AppUsers $user
*/
class UserAccess extends ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'app_user_access';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['user_id', 'item_name', 'created_date'], 'required'],
[['user_id', 'created_date'], 'integer'],
[['item_name'], 'string', 'max' => 64]
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'user_id' => 'User ID',
'item_name' => 'Item Name',
'created_date' => 'Created Date',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getItemName()
{
return $this->hasOne(AppAuthItem::className(), ['name' => 'item_name']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(AppUsers::className(), ['id' => 'user_id']);
}
}
A oto model GroupAccess:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
/**
* This is the model class for table "app_group_access".
*
* @property integer $id
* @property integer $group_id
* @property integer $user_id
* @property string $item_name
* @property integer $created_date
*
* @property AppUsers $user
* @property AppAuthItem $itemName
* @property AppGroups $group
*/
class GroupAccess extends ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'app_group_access';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['group_id', 'user_id', 'item_name', 'created_date'], 'required'],
[['group_id', 'user_id', 'created_date'], 'integer'],
[['item_name'], 'string', 'max' => 64]
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'group_id' => 'Group ID',
'user_id' => 'User ID',
'item_name' => 'Item Name',
'created_date' => 'Created Date',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(AppUsers::className(), ['id' => 'user_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getItemName()
{
return $this->hasOne(AppAuthItem::className(), ['name' => 'item_name']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getGroup()
{
return $this->hasOne(AppGroups::className(), ['id' => 'group_id']);
}
}
I jeszcze raz kilka przydatnych przykładów:
// assign group role
Yii::$app->access->assign('group', 'group_creator', 24, 20);
// assign user role
Yii::$app->access->assign('user', 'app_user', 24);
// revoke group
Yii::$app->access->revoke('group', 22, 18);
// revoke user
Yii::$app->access->revoke('user', 22);
// test user permission
var_dump(Yii::$app->access->canUser('user', 'manage_app_settings'));
// test the group permission
var_dump(Yii::$app->access->canUser('group', 'manage_group_settings'));