/** * Проверяет наличие доступа * * @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; }
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(); } }