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