public function actionRightsAcoUpdate($aco_class, $aco_key, $aco_value, $operation, $value, $is_deny = 0) { $ret = true; $savedItems = AccessItem::model()->findAllByAttributes(array('aco_class' => $aco_class, 'aco_key' => $aco_key, 'aco_value' => $aco_value, 'action' => $operation, 'is_deny' => $is_deny)); $items = explode(',', $value); foreach ($items as $item) { list($aro_class, $aro_key, $aro_value) = explode(':', $item); $alreadySaved = false; foreach ($savedItems as $i => $saveItem) { if ($saveItem['aro_class'] == $aro_class && $saveItem['aro_key'] == $aro_key && $saveItem['aro_value'] == $aro_value) { $alreadySaved = true; unset($savedItems[$i]); break; } } if (!$alreadySaved) { $accessItem = new AccessItem(); $accessItem->aco_class = $aco_class; $accessItem->aco_key = $aco_key; $accessItem->aco_value = $aco_value; $accessItem->aro_class = $aro_class; $accessItem->aro_key = $aro_key; $accessItem->aro_value = $aro_value; $accessItem->action = $operation; $accessItem->is_deny = (bool) $is_deny; $ret = $ret && $accessItem->save(); } } foreach ($savedItems as $saveItem) { $saveItem->delete(); } echo intval($ret); }
/** * Проверяет наличие доступа * * @param $action идентификатор действия (create, update, read, delete etc) * @param $object может быть объектом, строкой (именем класса) * или одномерным массивом типа array($objectClassName, $objectId) * @return bool */ public function may($action, $object) { // 1. Проверяем на наличие полного доступа (fullAccess) if ($this->checkFullAccess()) { return true; } // 2. Выбираем из БД все правила, которые относятся к нужному действию, // а также к вопрошающему и контролируемому объектам $params = array('action' => $action); $acoWhere = array('(`aco_key` = "" AND `aco_value` = "")'); if (is_object($object)) { $params[':aco_class'] = get_class($object); $acoWhere[] = '(`aco_key` = "id" AND `aco_value` = :aco_id)'; $params['aco_id'] = $object->id; $cAttributes = AccessCBehavior::getAttributesByClassName($params['aco_class']); foreach ($cAttributes as $index => $attrName) { if ($object->hasAttribute($attrName) || $object->hasProperty($attrName)) { $acoWhere[] = '(`aco_key` = :aco_' . $index . ' AND `aco_value` = :aco_' . $attrName . ')'; $params['aco_' . $index] = $attrName; $params['aco_' . $attrName] = $object->{$attrName}; } } } elseif (is_array($object)) { $params['aco_class'] = $object[0]; $acoWhere[] = '(`aco_key` = "id" AND `aco_value` = :aco_id)'; $params['aco_id'] = $object[1]; } else { $params['aco_class'] = $object; } $aroWhere = self::generateAroWhereStatement($this->getOwner(), $params); $sql = 'SELECT * FROM`' . AccessItem::tableName() . '` WHERE `action` = :action AND `aco_class` = :aco_class AND `aro_class` = :aro_class AND ( ' . implode(' OR ', $acoWhere) . ' ) AND ( ' . $aroWhere . ' ) ORDER BY `is_deny` DESC'; $accessItems = Yii::app()->db->createCommand($sql)->bindValues($params)->queryAll(); // 3. Просматриваем все правила и определяем результат if (count($accessItems) == 0) { return false; } foreach ($accessItems as $accessItem) { if ($accessItem['is_deny']) { return false; } } return true; }
protected function rightsForOperation($operation, $is_deny = 0) { $params = array('aco_class' => $this->objects[0], 'aco_key' => !empty($this->objects[1]) ? $this->objects[1] : '', 'aco_value' => !empty($this->objects[2]) ? $this->objects[2] : '', 'action' => $operation); $items = AccessItem::model()->findAllByAttributes($params); $data = array(); foreach ($items as $item) { if ($item['aro_class']) { $data[] = array('id' => $item->getAroId(), 'text' => $item->getAroText()); } } $extraResults = array(); $buildInRoles = Role::builtInRoles(); foreach ($buildInRoles as $roleName => $roleTitle) { $extraResults['User:roles:' . $roleName] = $roleTitle; } return $this->widget('Select2', array('name' => $this->htmlOptions['name'] . '[' . $operation . ']', 'id' => $this->htmlOptions['id'] . '_' . $operation, 'data' => $data, 'htmlOptions' => array('class' => 'rightsselect', 'data-aco_class' => $params['aco_class'], 'data-aco_key' => $params['aco_key'], 'data-aco_value' => $params['aco_value'], 'data-operation' => $params['action'], 'data-is_deny' => $is_deny), 'classNames' => array(array('User', 'User:id:', 'id', 'email,login,displayname'), array('User', 'User:roles:', '_roles.name', 'title'), $extraResults)), true); }
public function allowed($action = 'read', $force = false) { // Не позволяем запускать условие два раза в одном запросе if (($force || !isset($this->getOwner()->getDbCriteria()->params['aco_class']) || !isset($this->getOwner()->getDbCriteria()->params['aro_class'])) && ClassHelper::getBehaviorPropertyByClassName(get_class($this->getOwner()), 'AccessCBehavior', 'class')) { $user = Yii::app()->user->data; if (ClassHelper::getBehaviorPropertyByClassName(get_class($user), 'AccessRBehavior', 'class') && !$user->checkFullAccess()) { $params = array('aco_class' => get_class($this->getOwner()), 'action' => $action); $acoWhere = array('(a.`aco_key` = "" AND a.`aco_value` = "")', '(a.`aco_key` = "id" AND a.`aco_value` = t.`id`)'); $cAttributes = AccessCBehavior::getAttributesByClassName($params['aco_class']); foreach ($cAttributes as $attrName) { $acoWhere[] = '(a.`aco_key` = "' . $attrName . '" AND a.`aco_value` = t.`' . $attrName . '`)'; } $acoWhereStatement = implode(' OR ', $acoWhere); $aroWhereStatement = AccessRBehavior::generateAroWhereStatement($user, $params, 'a.'); $this->getOwner()->getDbCriteria()->mergeWith(array('join' => 'INNER JOIN `' . AccessItem::tableName() . '` a ON a.action = :action AND a.aco_class = :aco_class AND a.aro_class = :aro_class AND (' . $acoWhereStatement . ') AND (' . $aroWhereStatement . ')', 'params' => $params)); } } return $this->getOwner(); }
public function installDefaultAccess($acoClass) { $sql = 'select count(*) from `' . AccessItem::tableName() . '` where `aco_class` = :aco_class'; $alreadyInstalled = Yii::app()->getDb()->createCommand($sql)->queryScalar(array('aco_class' => $acoClass)); $defaultRules = AccessCBehavior::getDefaultRulesByClassName($acoClass); if ($alreadyInstalled == 0 && !empty($defaultRules)) { $items = array(); foreach ($defaultRules as $action => $params) { if (is_array($params)) { foreach ($params as $aroClass => $datas) { if (is_array($datas)) { foreach ($datas as $data) { $aroKey = $data[0]; $aroValue = $data[1]; $isDeny = isset($data['deny']) ? $data['deny'] : false; $items[] = "('{$acoClass}', '', '', '{$aroClass}', '{$aroKey}', '{$aroValue}', '{$action}', '{$isDeny}')"; } } } } } $sql = 'insert into `' . AccessItem::tableName() . '` (`aco_class`, `aco_key`, `aco_value`, `aro_class`, `aro_key`, `aro_value`, `action`, `is_deny`) values ' . implode(', ', $items); return Yii::app()->getDb()->createCommand($sql)->execute(); } }