[ Index ] |
PHP Cross Reference of ACL Module |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * RestrictedActiveRecordBehavior Class File 5 * This class serves as a behavior for all the objects which have to control 6 * their access 7 * 8 * @author dispy <dispyfree@googlemail.com> 9 * @license LGPLv2 10 * @package acl.base 11 */ 12 13 /** 14 * This class is intended tobe used as a behavior for objects which have restrictions on their access 15 * It automatically checks, if the current user has the permissions to commit the regular CRUD-tasks 16 */ 17 class RestrictedActiveRecordBehavior extends CActiveRecordBehavior{ 18 19 /** 20 * The following functions generates the CDbCriteria necessary to filter all accessable rows 21 * The CDbCriteria is solely passsed to the wrapped methods 22 * @param sql $conditions the conditions being passed to the real method 23 * @param array $params the params being passed to the real method 24 * @param array $options options to be used by the method itself (keys: disableInheritance) 25 * @return CDbCriteria the criteria assuring that the user only gets what he has access to 26 */ 27 protected function generateAccessCheck($conditions = '', $params = array(), $options = array()){ 28 if(is_object($conditions) && get_class($conditions) == 'CDbCriteria'){ 29 $criteria = $conditions; 30 } 31 else{ 32 $criteria = new CDbCriteria; 33 $criteria->mergeWith(array( 34 'condition' => $conditions, 35 'params' => $params 36 )); 37 } 38 39 //If he's generally allowed, don't filter at all 40 if(RestrictedActiveRecord::mayGenerally(get_class($this->getOwner()), 'read')) 41 return $criteria; 42 43 $options = array_merge(RestrictedActiveRecord::$defaultOptions, $options); 44 45 //If the check is bypassed, return criteria without check 46 if(RestrictedActiveRecord::$byPassCheck) 47 return $criteria; 48 49 $criteria->distinct = true; //Important: there can be multiple locations which grant permission 50 51 //Inner join to get the collection associated with this content 52 $acoClass = Strategy::getClass('Aco'); 53 $collection = 'INNER JOIN `'.$acoClass::model()->tableName().'` AS acoC ON acoC.model = :RAR_model AND acoC.foreign_key = t.id'; 54 $criteria->params[':RAR_model'] = get_class($this->getOwner()); 55 56 //Inner join to the associated aco-nodes themselves to get the positions 57 $acoNodeClass = Strategy::getClass('AcoNode'); 58 $nodes = ' INNER JOIN `'.$acoNodeClass::model()->tableName().'` AS aco ON aco.collection_id = acoC.id'; 59 60 //But before: fetch the positions of the current user 61 $aroClass = Strategy::getClass('Aro'); 62 $user = RestrictedActiveRecord::getUser(); 63 $aro = $aroClass::model()->find('model = :model AND foreign_key = :foreign_key', 64 array(':model'=> RestrictedActiveRecord::$model, ':foreign_key' => $user->id)); 65 66 //If we are nobody... we are a guest^^ 67 $guest = Strategy::get('guestGroup'); 68 if(!$aro && $guest){ 69 $aro = $aroClass::model()->find('alias = :alias', 70 array(':alias' => $guest)); 71 72 //If there's no guest group... we are nobody and we may nothing ;) 73 if(!$aro) 74 return array(); 75 } 76 77 78 $aroPositions = $aro->fetchComprisedPositions(); 79 $aroPositionCheck = $aro->addPositionCheck($aroPositions, "aro", "map"); 80 81 //Get our action :) 82 $action = Action::model()->find('name = :name', array(':name' => 'read')); 83 84 if($action === NULL) 85 throw new RuntimeException('Unable to find action read'); 86 87 //Now, join connecting table 88 $acoCondition = $acoClass::buildTreeQueryCondition( 89 array('table' => 'aco'), 90 array('table' => 'map', 'field' => 'aco'), 91 $options['disableInheritance'] 92 ); 93 $connection = ' INNER JOIN `'.Permission::model()->tableName().'` AS map ON '.$acoCondition.' AND '.$aroPositionCheck.' AND map.action_id = :acl_action_id'; 94 $criteria->params[':acl_action_id'] = $action->id; 95 96 $joins = array($collection, $nodes, $connection); 97 98 foreach($joins as $join){ 99 $criteria->mergeWith(array('join' => $join), true); 100 } 101 102 103 return $criteria; 104 } 105 106 public function beforeFind($event){ 107 $event = $this->generateAccessCheck($event->criteria); 108 } 109 110 111 /** 112 * Gets the Aros who are directly (no inheritance!) permitted to perform 113 * one of the specified actions on this object 114 * @param mixed $actions the actions to be considered 115 * @return array All of the objects which have one of the permissions 116 */ 117 public function getDirectlyPermitted($actions = '*'){ 118 //First, fetch all of the action Ids 119 $owner = $this->getOwner(); 120 $actions = Action::translateActions($owner, $actions); 121 $actionCondition = Util::generateInStatement($actions); 122 $actions = Action::model()->findAll('name '.$actionCondition); 123 124 $actionIds = array(); 125 foreach($actions as $action){ 126 $actionIds[] = $action->id; 127 } 128 $actionIdCondition = Util::generateInStatement($actionIds); 129 130 //Get the associated Aco first 131 $aco = AclObject::loadObjectStatic($owner, 'Aco'); 132 //Fetch all of the own positions and build condition 133 $positions = $aco->fetchComprisedPositions(); 134 $acoCondition = Util::generateInStatement($positions); 135 136 $aroNodeClass = Strategy::getClass('AroNode'); 137 138 $rGroupTable = RGroup::model()->tableName(); 139 $nodeTable = $aroNodeClass::model()->tableName(); 140 $permTable = Permission::model()->tableName(); 141 return Yii::app()->db->createCommand() 142 ->selectDistinct('t.id AS collection_id, t.foreign_key, t.model, p.action_id') 143 ->from($rGroupTable.' t') 144 ->join($nodeTable.' n', 'n.collection_id = t.id') 145 ->join($permTable.' p', 146 'p.aro_id = n.id AND p.aco_path '.$acoCondition.' AND p.action_id '. $actionIdCondition) 147 ->queryAll() 148 ; 149 } 150 151 /** 152 * This method checks whether the user has the right to update the current record 153 * By default, it's always allowed to create a new object. This object is automatically assigned to the user who created it with full permissions 154 */ 155 public function beforeSave($event){ 156 //The Record is updated 157 $aro = RestrictedActiveRecord::getUser(); 158 159 if(!$this->getOwner()->isNewRecord){ 160 if(!$aro->may($this->getOwner(), 'update')) 161 throw new RuntimeException('You are not allowed to update this record'); 162 } 163 else{ 164 if(!$aro->may(get_class($this->getOwner()), 'create')) 165 throw new RuntimeException('You are not allowed to create this object'); 166 } 167 168 return true; 169 } 170 171 /** 172 * This method checks whether the user has the right to delete the current record 173 * 174 */ 175 public function beforeDelete($event){ 176 $aro = RestrictedActiveRecord::getUser(); 177 $owner = $this->getOwner(); 178 179 //If he's generally allowed, don't filter at all 180 if(RestrictedActiveRecord::mayGenerally(get_class($this->getOwner()), 'delete')) 181 return true; 182 183 if(!$aro->may($owner, 'delete')) 184 throw new RuntimeException('You are not allowed to delete this record'); 185 186 //Ok he has the right to do that - remove all the ACL-objects associated with this object 187 $class = Strategy::getClass('Aco'); 188 $aco = $class::model()->find('model = :model AND foreign_key = :key', array(':model' => get_class($owner), ':key' => $owner->id)); 189 if(!$aco) 190 throw new RuntimeException('No associated Aco!'); 191 192 if(!$aco->delete()) 193 throw new RuntimeException('Unable to delete associated Aco'); 194 195 return true; 196 } 197 198 199 /** 200 * This method takes care to assign individual rights to newly created objects 201 * 202 * @param CEvent $evt 203 */ 204 public function afterSave($event){ 205 $owner = $this->getOwner(); 206 if($owner){ 207 $aro = RestrictedActiveRecord::getUser(); 208 //As the object is newly created, it needs a representation 209 //If strict mode is disabled, this is not necessary 210 $class = Strategy::getClass('Aco'); 211 $aco = new $class(); 212 $aco->model = get_class($owner); 213 $aco->foreign_key = $owner->getPrimaryKey(); 214 215 if(!$aco->save()){ 216 throw new RuntimeException('Unable to create corresponding Aco for new '.get_class($owner)); 217 } 218 219 $aro->grant($aco, RestrictedActiveRecord::getAutoPermissions($this->getOwner()), true); 220 } 221 } 222 223 224 /** 225 * Checks whether the current ARO has the given permission on this object 226 * @param string $permission 227 */ 228 public function grants($permission){ 229 $aro = RestrictedActiveRecord::getUser(); 230 return $aro->may($this->getOwner(), $permission); 231 } 232 233 234 } 235 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Jul 1 19:24:45 2012 | Cross-referenced by PHPXref 0.7.1 |