Hello, I’ve used rights and implements the caching for rights like this:
1/ Edit the AuthItemController.php to support generate Permission Cache File
Add new functions
/**
* Generate Permission into File
*/
public function actionGenerateFile(){
// Delete old cache
Yii::app()->cache->delete('permission-cache');
// Generate new cache
$rdb_auth_manager=new RDbAuthManager;
//Get all roles
$sql = "SELECT name,t1.type,description,t1.bizrule,t1.data
FROM {$rdb_auth_manager->itemTable} t1
WHERE t1.type=2
ORDER BY t1.type DESC";
$command=Yii::app()->db->createCommand($sql);
$roles=$command->queryAll();
//Get all items
$sql = "SELECT name,t1.type,description,t1.bizrule,t1.data
FROM {$rdb_auth_manager->itemTable} t1
WHERE t1.type<>2
ORDER BY t1.type DESC";
$command=Yii::app()->db->createCommand($sql);
$items=$command->queryAll();
$permissions=array();
//Create permission item array
foreach($items as $item){
$permissions[$item['name']]['bizrule']=$item['bizrule'];
$permissions[$item['name']]['data']=$item['data'];
if(!isset($permissions[$item['name']]['roles']))
$permissions[$item['name']]['roles']=array();
if(!isset($permissions[$item['name']]['users']))
$permissions[$item['name']]['users']=array();
// Check if there is any user assigned with this item
$sql = "SELECT userid,bizrule,data
FROM {$rdb_auth_manager->assignmentTable}
WHERE itemname=:name";
$command=Yii::app()->db->createCommand($sql);
$command->bindParam(":name",$item['name'],PDO::PARAM_STR);
$a_users=$command->queryAll();
if($a_users && count($a_users)>0){
foreach($a_users as $a_user){
$permissions[$item['name']]['users'][$a_user['userid']]['bizrule']=$a_user['bizrule'];
$permissions[$item['name']]['users'][$a_user['userid']]['data']=$a_user['data'];
// Get child Items of current items
// to make sure if the user is assigned to parent item,
// it must be assigned to all children items of this parent
$child_items=$this->getChildItemsRecursive($item['name']);
if($child_items and count($child_items)>0){
foreach($child_items as $key=>$value){
$permissions[$key]['bizrule']=$value['bizrule'];
$permissions[$key]['data']=$value['data'];
if(!isset($permissions[$key]['roles']))
$permissions[$key]['roles']=array();
if(!isset($permissions[$key]['users']))
$permissions[$key]['users']=array();
// Assign user to Item,
$permissions[$key]['users'][$a_user['userid']]['bizrule']=null;
$permissions[$key]['users'][$a_user['userid']]['data']="N;";
}
}
}
}
// Check roles that are allowed with this item
$permissions[$item['name']]['roles']=$this->getAllowedRolesRecursive($item['name']);
//$permissions[$item['name']]['users']=array_unique($permissions[$item['name']]['users']);
$permissions[$item['name']]['roles']=array_unique($permissions[$item['name']]['roles']);
}
Yii::app()->cache->set('permission-cache',$permissions,0); // No expire
Yii::app()->user->setFlash($this->module->flashSuccessKey,
Rights::t('core', 'Updated Permission Cache')
);
Yii::app()->controller->redirect(array('authItem/permissions'));
}
public function getChildItemsRecursive($itemname){
$items=array();
$rdb_auth_manager=new RDbAuthManager;
$sql = "SELECT t2.type,t2.name,t2.bizrule,t2.data
FROM {$rdb_auth_manager->itemChildTable} t1
INNER JOIN {$rdb_auth_manager->itemTable} t2 ON t1.child=t2.name
WHERE t2.type<>2 AND parent=:name";
$command=Yii::app()->db->createCommand($sql);
$command->bindParam(":name",$itemname,PDO::PARAM_STR);
$childrens=$command->queryAll();
if(!($childrens && count($childrens)>0)){
return $items;
} else {
foreach($childrens as $child){
$items[$child['name']]['bizrule']=$child['bizrule'];
$items[$child['name']]['data']=$child['data'];
$temp_items=$this->getChildItemsRecursive($child['name']);
$items=array_merge($items,$temp_items);
}
return $items;
}
}
public function getAllowedRolesRecursive($itemname){
$rdb_auth_manager=new RDbAuthManager;
// Check roles that are allowed with this item
// Get parent of the item
$roles=array();
$sql = "SELECT t2.type,t2.name
FROM {$rdb_auth_manager->itemChildTable} t1
INNER JOIN {$rdb_auth_manager->itemTable} t2 ON t1.parent=t2.name
WHERE child=:name";
$command=Yii::app()->db->createCommand($sql);
$command->bindParam(":name",$itemname,PDO::PARAM_STR);
$parents=$command->queryAll();
if(!($parents && count($parents)>0)){
return $roles;
} else{
foreach($parents as $p){
if($p['type']==2){
$roles[]=$p['name'];
}
$temp_roles=$this->getAllowedRolesRecursive($p['name']);
$roles=array_merge($roles,$temp_roles);
}
return array_merge($roles,$temp_roles);
}
}
Add generateFile to accessRules
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules()
{
return array(
array('allow', // Allow superusers to access Rights
'actions'=>array(
'permissions',
'operations',
'tasks',
'roles',
'generate',
'create',
'update',
'delete',
'removeChild',
'assign',
'revoke',
'sortable',
'generateFile'
),
'users'=>$this->_authorizer->getSuperusers(),
),
array('deny', // Deny all users
'users'=>array('*'),
),
);
}
2/ Add getArrayRoles in Rights.php
/**
* Static Function retrun Array Roles of the User
* @param bigint $uid
* @return string
*/
public static function getArrayRoles($uid=0)
{
$res=array();
if($uid){
$roles=Rights::getAssignedRoles($uid,true);
$res=array();
foreach($roles as $r){
$res[]=$r->name;
}
}
return $res;
}
3/ Edit RWebUser.php file
Add user roles state after user logged in
/**
* Actions to be taken after logging in.
* Overloads the parent method in order to mark superusers.
* @param boolean $fromCookie whether the login is based on cookie.
*/
public function afterLogin($fromCookie)
{
parent::afterLogin($fromCookie);
// Set User Roles here
$this->setState('current_roles', Rights::getArrayRoles($this->getId()));
// Mark the user as a superuser if necessary.
if( Rights::getAuthorizer()->isSuperuser($this->getId())===true )
$this->isSuperuser = true;
}
Add new functioncs
public function checkAccessWithCache($operation, $params=array(), $allowCaching=true){
$permissions=Yii::app()->cache->get('permission-cache');
if($permissions!==false){
if(!array_key_exists($operation,$permissions)){
return false;
}
if($this->executeBizRule($permissions[$operation]['bizrule'],$params,$permissions[$operation]['data']))
{
//Check with default Roles
if(in_array(app()->authManager->defaultRoles, $permissions[$operation]['roles'])){
return true;
}
//Check if allow user id for current operation
if(array_key_exists($this->getId(), $permissions[$operation]['users'])){
$uid=$this->getId();
if($this->executeBizRule($permissions[$operation]['users'][$uid]['bizrule'],$params,$permissions[$operation]['users'][$uid]['data']))
return true;
}
//Check if allow user id for current operation
$check_roles = array_intersect($this->getState('current_roles'),$permissions[$operation]['roles']);
return count($check_roles)>0;
}
} else {
parent::checkAccess($operation, $params, $allowCaching);
}
}
public function executeBizRule($bizRule,$params,$data)
{
return $bizRule==='' || $bizRule===null || ($this->showErrors ? eval($bizRule)!=0 : @eval($bizRule)!=0);
}
Ask checkAccess function to use the new function we defined
/**
* Performs access check for this user.
* Overloads the parent method in order to allow superusers access implicitly.
* @param string $operation the name of the operation that need access check.
* @param array $params name-value pairs that would be passed to business rules associated
* with the tasks and roles assigned to the user.
* @param boolean $allowCaching whether to allow caching the result of access checki.
* This parameter has been available since version 1.0.5. When this parameter
* is true (default), if the access check of an operation was performed before,
* its result will be directly returned when calling this method to check the same operation.
* If this parameter is false, this method will always call {@link CAuthManager::checkAccess}
* to obtain the up-to-date access result. Note that this caching is effective
* only within the same request.
* @return boolean whether the operations can be performed by this user.
*/
public function checkAccess($operation, $params=array(), $allowCaching=true)
{
return $this->isSuperuser===true ? true : $this->checkAccessWithCache($operation, $params, $allowCaching);
}
4/ Edit layout to add Generate File Cache button
<?php $this->beginContent(Rights::module()->appLayout); ?>
<div id="rights" class="container">
<div id="content">
<?php if( $this->id!=='install' ): ?>
<?php Yii::app()->controller->menu= array(
array(
'label'=>Rights::t('core', 'Assignments'),
'url'=>array('assignment/view'),
'itemOptions'=>array('class'=>'item-assignments'),
'linkOptions'=>array('class'=>'button'),
),
array(
'label'=>Rights::t('core', 'Permissions'),
'url'=>array('authItem/permissions'),
'itemOptions'=>array('class'=>'item-permissions'),
'linkOptions'=>array('class'=>'button'),
),
array(
'label'=>Rights::t('core', 'Roles'),
'url'=>array('authItem/roles'),
'itemOptions'=>array('class'=>'item-roles'),
'linkOptions'=>array('class'=>'button'),
),
array(
'label'=>Rights::t('core', 'Tasks'),
'url'=>array('authItem/tasks'),
'itemOptions'=>array('class'=>'item-tasks'),
'linkOptions'=>array('class'=>'button'),
),
array(
'label'=>Rights::t('core', 'Operations'),
'url'=>array('authItem/operations'),
'itemOptions'=>array('class'=>'item-operations'),
'linkOptions'=>array('class'=>'button'),
),
array(
'label'=>Rights::t('core', 'Update Permission Cache File'),
'url'=>array('authItem/generateFile'),
'itemOptions'=>array('class'=>'item-operations'),
'linkOptions'=>array('class'=>'button'),
),
);
?>
<?php endif; ?>
<?php $this->renderPartial('/_flash'); ?>
<?php echo $content; ?>
</div><!-- content -->
</div>
<?php $this->endContent(); ?>
Maybe there are still some bugs but it worked for me so far. Hope this helps.
P/s: When edit permissions with Rights, remember to run generateFile to re-generate new Cache File