Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • Net
  • None
  • PHP
  • system
    • base
    • caching
      • dependencies
    • collections
    • console
    • db
      • ar
      • schema
        • cubrid
        • mssql
        • mysql
        • oci
        • pgsql
        • sqlite
    • i18n
      • gettext
    • logging
    • test
    • utils
    • validators
    • web
      • actions
      • auth
      • filters
      • form
      • helpers
      • renderers
      • services
      • widgets
        • captcha
        • pagers
  • Text
    • Highlighter
  • zii
    • behaviors
    • widgets
      • grid
      • jui

Classes

  • CAccessControlFilter
  • CAccessRule
  • CAuthAssignment
  • CAuthItem
  • CAuthManager
  • CBaseUserIdentity
  • CDbAuthManager
  • CPhpAuthManager
  • CUserIdentity
  • CWebUser
  • X2WebUser
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * CDbAuthManager class file.
  4:  *
  5:  * @author Qiang Xue <qiang.xue@gmail.com>
  6:  * @link http://www.yiiframework.com/
  7:  * @copyright 2008-2013 Yii Software LLC
  8:  * @license http://www.yiiframework.com/license/
  9:  */
 10: 
 11: /**
 12:  * CDbAuthManager represents an authorization manager that stores authorization information in database.
 13:  *
 14:  * The database connection is specified by {@link connectionID}. And the database schema
 15:  * should be as described in "framework/web/auth/*.sql". You may change the names of
 16:  * the three tables used to store the authorization data by setting {@link itemTable},
 17:  * {@link itemChildTable} and {@link assignmentTable}.
 18:  *
 19:  * @property array $authItems The authorization items of the specific type.
 20:  *
 21:  * @author Qiang Xue <qiang.xue@gmail.com>
 22:  * @package system.web.auth
 23:  * @since 1.0
 24:  */
 25: class CDbAuthManager extends CAuthManager
 26: {
 27:     /**
 28:      * @var string the ID of the {@link CDbConnection} application component. Defaults to 'db'.
 29:      * The database must have the tables as declared in "framework/web/auth/*.sql".
 30:      */
 31:     public $connectionID='db';
 32:     /**
 33:      * @var string the name of the table storing authorization items. Defaults to 'AuthItem'.
 34:      */
 35:     public $itemTable='AuthItem';
 36:     /**
 37:      * @var string the name of the table storing authorization item hierarchy. Defaults to 'AuthItemChild'.
 38:      */
 39:     public $itemChildTable='AuthItemChild';
 40:     /**
 41:      * @var string the name of the table storing authorization item assignments. Defaults to 'AuthAssignment'.
 42:      */
 43:     public $assignmentTable='AuthAssignment';
 44:     /**
 45:      * @var CDbConnection the database connection. By default, this is initialized
 46:      * automatically as the application component whose ID is indicated as {@link connectionID}.
 47:      */
 48:     public $db;
 49: 
 50:     private $_usingSqlite;
 51: 
 52:     /**
 53:      * Initializes the application component.
 54:      * This method overrides the parent implementation by establishing the database connection.
 55:      */
 56:     public function init()
 57:     {
 58:         parent::init();
 59:         $this->_usingSqlite=!strncmp($this->getDbConnection()->getDriverName(),'sqlite',6);
 60:     }
 61: 
 62:     /**
 63:      * Performs access check for the specified user.
 64:      * @param string $itemName the name of the operation that need access check
 65:      * @param mixed $userId the user ID. This should can be either an integer and a string representing
 66:      * the unique identifier of a user. See {@link IWebUser::getId}.
 67:      * @param array $params name-value pairs that would be passed to biz rules associated
 68:      * with the tasks and roles assigned to the user.
 69:      * Since version 1.1.11 a param with name 'userId' is added to this array, which holds the value of <code>$userId</code>.
 70:      * @return boolean whether the operations can be performed by the user.
 71:      */
 72:     public function checkAccess($itemName,$userId,$params=array())
 73:     {
 74:         $assignments=$this->getAuthAssignments($userId);
 75:         return $this->checkAccessRecursive($itemName,$userId,$params,$assignments);
 76:     }
 77: 
 78:     /**
 79:      * Performs access check for the specified user.
 80:      * This method is internally called by {@link checkAccess}.
 81:      * @param string $itemName the name of the operation that need access check
 82:      * @param mixed $userId the user ID. This should can be either an integer and a string representing
 83:      * the unique identifier of a user. See {@link IWebUser::getId}.
 84:      * @param array $params name-value pairs that would be passed to biz rules associated
 85:      * with the tasks and roles assigned to the user.
 86:      * Since version 1.1.11 a param with name 'userId' is added to this array, which holds the value of <code>$userId</code>.
 87:      * @param array $assignments the assignments to the specified user
 88:      * @return boolean whether the operations can be performed by the user.
 89:      * @since 1.1.3
 90:      */
 91:     protected function checkAccessRecursive($itemName,$userId,$params,$assignments)
 92:     {
 93:         if(($item=$this->getAuthItem($itemName))===null)
 94:             return false;
 95:         Yii::trace('Checking permission "'.$item->getName().'"','system.web.auth.CDbAuthManager');
 96:         if(!isset($params['userId']))
 97:             $params['userId'] = $userId;
 98:         if($this->executeBizRule($item->getBizRule(),$params,$item->getData()))
 99:         {
100:             if(in_array($itemName,$this->defaultRoles))
101:                 return true;
102:             if(isset($assignments[$itemName]))
103:             {
104:                 $assignment=$assignments[$itemName];
105:                 if($this->executeBizRule($assignment->getBizRule(),$params,$assignment->getData()))
106:                     return true;
107:             }
108:             $parents=$this->db->createCommand()
109:                 ->select('parent')
110:                 ->from($this->itemChildTable)
111:                 ->where('child=:name', array(':name'=>$itemName))
112:                 ->queryColumn();
113:             foreach($parents as $parent)
114:             {
115:                 if($this->checkAccessRecursive($parent,$userId,$params,$assignments))
116:                     return true;
117:             }
118:         }
119:         return false;
120:     }
121: 
122:     /**
123:      * Adds an item as a child of another item.
124:      * @param string $itemName the parent item name
125:      * @param string $childName the child item name
126:      * @return boolean whether the item is added successfully
127:      * @throws CException if either parent or child doesn't exist or if a loop has been detected.
128:      */
129:     public function addItemChild($itemName,$childName)
130:     {
131:         if($itemName===$childName)
132:             throw new CException(Yii::t('yii','Cannot add "{name}" as a child of itself.',
133:                     array('{name}'=>$itemName)));
134: 
135:         $rows=$this->db->createCommand()
136:             ->select()
137:             ->from($this->itemTable)
138:             ->where('name=:name1 OR name=:name2', array(
139:                 ':name1'=>$itemName,
140:                 ':name2'=>$childName
141:             ))
142:             ->queryAll();
143: 
144:         if(count($rows)==2)
145:         {
146:             if($rows[0]['name']===$itemName)
147:             {
148:                 $parentType=$rows[0]['type'];
149:                 $childType=$rows[1]['type'];
150:             }
151:             else
152:             {
153:                 $childType=$rows[0]['type'];
154:                 $parentType=$rows[1]['type'];
155:             }
156:             $this->checkItemChildType($parentType,$childType);
157:             if($this->detectLoop($itemName,$childName))
158:                 throw new CException(Yii::t('yii','Cannot add "{child}" as a child of "{name}". A loop has been detected.',
159:                     array('{child}'=>$childName,'{name}'=>$itemName)));
160: 
161:             $this->db->createCommand()
162:                 ->insert($this->itemChildTable, array(
163:                     'parent'=>$itemName,
164:                     'child'=>$childName,
165:                 ));
166: 
167:             return true;
168:         }
169:         else
170:             throw new CException(Yii::t('yii','Either "{parent}" or "{child}" does not exist.',array('{child}'=>$childName,'{parent}'=>$itemName)));
171:     }
172: 
173:     /**
174:      * Removes a child from its parent.
175:      * Note, the child item is not deleted. Only the parent-child relationship is removed.
176:      * @param string $itemName the parent item name
177:      * @param string $childName the child item name
178:      * @return boolean whether the removal is successful
179:      */
180:     public function removeItemChild($itemName,$childName)
181:     {
182:         return $this->db->createCommand()
183:             ->delete($this->itemChildTable, 'parent=:parent AND child=:child', array(
184:                 ':parent'=>$itemName,
185:                 ':child'=>$childName
186:             )) > 0;
187:     }
188: 
189:     /**
190:      * Returns a value indicating whether a child exists within a parent.
191:      * @param string $itemName the parent item name
192:      * @param string $childName the child item name
193:      * @return boolean whether the child exists
194:      */
195:     public function hasItemChild($itemName,$childName)
196:     {
197:         return $this->db->createCommand()
198:             ->select('parent')
199:             ->from($this->itemChildTable)
200:             ->where('parent=:parent AND child=:child', array(
201:                 ':parent'=>$itemName,
202:                 ':child'=>$childName))
203:             ->queryScalar() !== false;
204:     }
205: 
206:     /**
207:      * Returns the children of the specified item.
208:      * @param mixed $names the parent item name. This can be either a string or an array.
209:      * The latter represents a list of item names.
210:      * @return array all child items of the parent
211:      */
212:     public function getItemChildren($names)
213:     {
214:         if(is_string($names))
215:             $condition='parent='.$this->db->quoteValue($names);
216:         elseif(is_array($names) && $names!==array())
217:         {
218:             foreach($names as &$name)
219:                 $name=$this->db->quoteValue($name);
220:             $condition='parent IN ('.implode(', ',$names).')';
221:         }
222: 
223:         $rows=$this->db->createCommand()
224:             ->select('name, type, description, bizrule, data')
225:             ->from(array(
226:                 $this->itemTable,
227:                 $this->itemChildTable
228:             ))
229:             ->where($condition.' AND name=child')
230:             ->queryAll();
231: 
232:         $children=array();
233:         foreach($rows as $row)
234:         {
235:             if(($data=@unserialize($row['data']))===false)
236:                 $data=null;
237:             $children[$row['name']]=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
238:         }
239:         return $children;
240:     }
241: 
242:     /**
243:      * Assigns an authorization item to a user.
244:      * @param string $itemName the item name
245:      * @param mixed $userId the user ID (see {@link IWebUser::getId})
246:      * @param string $bizRule the business rule to be executed when {@link checkAccess} is called
247:      * for this particular authorization item.
248:      * @param mixed $data additional data associated with this assignment
249:      * @return CAuthAssignment the authorization assignment information.
250:      * @throws CException if the item does not exist or if the item has already been assigned to the user
251:      */
252:     public function assign($itemName,$userId,$bizRule=null,$data=null)
253:     {
254:         if($this->usingSqlite() && $this->getAuthItem($itemName)===null)
255:             throw new CException(Yii::t('yii','The item "{name}" does not exist.',array('{name}'=>$itemName)));
256: 
257:         $this->db->createCommand()
258:             ->insert($this->assignmentTable, array(
259:                 'itemname'=>$itemName,
260:                 'userid'=>$userId,
261:                 'bizrule'=>$bizRule,
262:                 'data'=>serialize($data)
263:             ));
264:         return new CAuthAssignment($this,$itemName,$userId,$bizRule,$data);
265:     }
266: 
267:     /**
268:      * Revokes an authorization assignment from a user.
269:      * @param string $itemName the item name
270:      * @param mixed $userId the user ID (see {@link IWebUser::getId})
271:      * @return boolean whether removal is successful
272:      */
273:     public function revoke($itemName,$userId)
274:     {
275:         return $this->db->createCommand()
276:             ->delete($this->assignmentTable, 'itemname=:itemname AND userid=:userid', array(
277:                 ':itemname'=>$itemName,
278:                 ':userid'=>$userId
279:             )) > 0;
280:     }
281: 
282:     /**
283:      * Returns a value indicating whether the item has been assigned to the user.
284:      * @param string $itemName the item name
285:      * @param mixed $userId the user ID (see {@link IWebUser::getId})
286:      * @return boolean whether the item has been assigned to the user.
287:      */
288:     public function isAssigned($itemName,$userId)
289:     {
290:         return $this->db->createCommand()
291:             ->select('itemname')
292:             ->from($this->assignmentTable)
293:             ->where('itemname=:itemname AND userid=:userid', array(
294:                 ':itemname'=>$itemName,
295:                 ':userid'=>$userId))
296:             ->queryScalar() !== false;
297:     }
298: 
299:     /**
300:      * Returns the item assignment information.
301:      * @param string $itemName the item name
302:      * @param mixed $userId the user ID (see {@link IWebUser::getId})
303:      * @return CAuthAssignment the item assignment information. Null is returned if
304:      * the item is not assigned to the user.
305:      */
306:     public function getAuthAssignment($itemName,$userId)
307:     {
308:         $row=$this->db->createCommand()
309:             ->select()
310:             ->from($this->assignmentTable)
311:             ->where('itemname=:itemname AND userid=:userid', array(
312:                 ':itemname'=>$itemName,
313:                 ':userid'=>$userId))
314:             ->queryRow();
315:         if($row!==false)
316:         {
317:             if(($data=@unserialize($row['data']))===false)
318:                 $data=null;
319:             return new CAuthAssignment($this,$row['itemname'],$row['userid'],$row['bizrule'],$data);
320:         }
321:         else
322:             return null;
323:     }
324: 
325:     /**
326:      * Returns the item assignments for the specified user.
327:      * @param mixed $userId the user ID (see {@link IWebUser::getId})
328:      * @return array the item assignment information for the user. An empty array will be
329:      * returned if there is no item assigned to the user.
330:      */
331:     public function getAuthAssignments($userId)
332:     {
333:         $rows=$this->db->createCommand()
334:             ->select()
335:             ->from($this->assignmentTable)
336:             ->where('userid=:userid', array(':userid'=>$userId))
337:             ->queryAll();
338:         $assignments=array();
339:         foreach($rows as $row)
340:         {
341:             if(($data=@unserialize($row['data']))===false)
342:                 $data=null;
343:             $assignments[$row['itemname']]=new CAuthAssignment($this,$row['itemname'],$row['userid'],$row['bizrule'],$data);
344:         }
345:         return $assignments;
346:     }
347: 
348:     /**
349:      * Saves the changes to an authorization assignment.
350:      * @param CAuthAssignment $assignment the assignment that has been changed.
351:      */
352:     public function saveAuthAssignment($assignment)
353:     {
354:         $this->db->createCommand()
355:             ->update($this->assignmentTable, array(
356:                 'bizrule'=>$assignment->getBizRule(),
357:                 'data'=>serialize($assignment->getData()),
358:             ), 'itemname=:itemname AND userid=:userid', array(
359:                 'itemname'=>$assignment->getItemName(),
360:                 'userid'=>$assignment->getUserId()
361:             ));
362:     }
363: 
364:     /**
365:      * Returns the authorization items of the specific type and user.
366:      * @param integer $type the item type (0: operation, 1: task, 2: role). Defaults to null,
367:      * meaning returning all items regardless of their type.
368:      * @param mixed $userId the user ID. Defaults to null, meaning returning all items even if
369:      * they are not assigned to a user.
370:      * @return array the authorization items of the specific type.
371:      */
372:     public function getAuthItems($type=null,$userId=null)
373:     {
374:         if($type===null && $userId===null)
375:         {
376:             $command=$this->db->createCommand()
377:                 ->select()
378:                 ->from($this->itemTable);
379:         }
380:         elseif($userId===null)
381:         {
382:             $command=$this->db->createCommand()
383:                 ->select()
384:                 ->from($this->itemTable)
385:                 ->where('type=:type', array(':type'=>$type));
386:         }
387:         elseif($type===null)
388:         {
389:             $command=$this->db->createCommand()
390:                 ->select('name,type,description,t1.bizrule,t1.data')
391:                 ->from(array(
392:                     $this->itemTable.' t1',
393:                     $this->assignmentTable.' t2'
394:                 ))
395:                 ->where('name=itemname AND userid=:userid', array(':userid'=>$userId));
396:         }
397:         else
398:         {
399:             $command=$this->db->createCommand()
400:                 ->select('name,type,description,t1.bizrule,t1.data')
401:                 ->from(array(
402:                     $this->itemTable.' t1',
403:                     $this->assignmentTable.' t2'
404:                 ))
405:                 ->where('name=itemname AND type=:type AND userid=:userid', array(
406:                     ':type'=>$type,
407:                     ':userid'=>$userId
408:                 ));
409:         }
410:         $items=array();
411:         foreach($command->queryAll() as $row)
412:         {
413:             if(($data=@unserialize($row['data']))===false)
414:                 $data=null;
415:             $items[$row['name']]=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
416:         }
417:         return $items;
418:     }
419: 
420:     /**
421:      * Creates an authorization item.
422:      * An authorization item represents an action permission (e.g. creating a post).
423:      * It has three types: operation, task and role.
424:      * Authorization items form a hierarchy. Higher level items inherit permissions representing
425:      * by lower level items.
426:      * @param string $name the item name. This must be a unique identifier.
427:      * @param integer $type the item type (0: operation, 1: task, 2: role).
428:      * @param string $description description of the item
429:      * @param string $bizRule business rule associated with the item. This is a piece of
430:      * PHP code that will be executed when {@link checkAccess} is called for the item.
431:      * @param mixed $data additional data associated with the item.
432:      * @return CAuthItem the authorization item
433:      * @throws CException if an item with the same name already exists
434:      */
435:     public function createAuthItem($name,$type,$description='',$bizRule=null,$data=null)
436:     {
437:         $this->db->createCommand()
438:             ->insert($this->itemTable, array(
439:                 'name'=>$name,
440:                 'type'=>$type,
441:                 'description'=>$description,
442:                 'bizrule'=>$bizRule,
443:                 'data'=>serialize($data)
444:             ));
445:         return new CAuthItem($this,$name,$type,$description,$bizRule,$data);
446:     }
447: 
448:     /**
449:      * Removes the specified authorization item.
450:      * @param string $name the name of the item to be removed
451:      * @return boolean whether the item exists in the storage and has been removed
452:      */
453:     public function removeAuthItem($name)
454:     {
455:         if($this->usingSqlite())
456:         {
457:             $this->db->createCommand()
458:                 ->delete($this->itemChildTable, 'parent=:name1 OR child=:name2', array(
459:                     ':name1'=>$name,
460:                     ':name2'=>$name
461:             ));
462:             $this->db->createCommand()
463:                 ->delete($this->assignmentTable, 'itemname=:name', array(
464:                     ':name'=>$name,
465:             ));
466:         }
467: 
468:         return $this->db->createCommand()
469:             ->delete($this->itemTable, 'name=:name', array(
470:                 ':name'=>$name
471:             )) > 0;
472:     }
473: 
474:     /**
475:      * Returns the authorization item with the specified name.
476:      * @param string $name the name of the item
477:      * @return CAuthItem the authorization item. Null if the item cannot be found.
478:      */
479:     public function getAuthItem($name)
480:     {
481:         $row=$this->db->createCommand()
482:             ->select()
483:             ->from($this->itemTable)
484:             ->where('name=:name', array(':name'=>$name))
485:             ->queryRow();
486: 
487:         if($row!==false)
488:         {
489:             if(($data=@unserialize($row['data']))===false)
490:                 $data=null;
491:             return new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
492:         }
493:         else
494:             return null;
495:     }
496: 
497:     /**
498:      * Saves an authorization item to persistent storage.
499:      * @param CAuthItem $item the item to be saved.
500:      * @param string $oldName the old item name. If null, it means the item name is not changed.
501:      */
502:     public function saveAuthItem($item,$oldName=null)
503:     {
504:         if($this->usingSqlite() && $oldName!==null && $item->getName()!==$oldName)
505:         {
506:             $this->db->createCommand()
507:                 ->update($this->itemChildTable, array(
508:                     'parent'=>$item->getName(),
509:                 ), 'parent=:whereName', array(
510:                     ':whereName'=>$oldName,
511:                 ));
512:             $this->db->createCommand()
513:                 ->update($this->itemChildTable, array(
514:                     'child'=>$item->getName(),
515:                 ), 'child=:whereName', array(
516:                     ':whereName'=>$oldName,
517:                 ));
518:             $this->db->createCommand()
519:                 ->update($this->assignmentTable, array(
520:                     'itemname'=>$item->getName(),
521:                 ), 'itemname=:whereName', array(
522:                     ':whereName'=>$oldName,
523:                 ));
524:         }
525: 
526:         $this->db->createCommand()
527:             ->update($this->itemTable, array(
528:                 'name'=>$item->getName(),
529:                 'type'=>$item->getType(),
530:                 'description'=>$item->getDescription(),
531:                 'bizrule'=>$item->getBizRule(),
532:                 'data'=>serialize($item->getData()),
533:             ), 'name=:whereName', array(
534:                 ':whereName'=>$oldName===null?$item->getName():$oldName,
535:             ));
536:     }
537: 
538:     /**
539:      * Saves the authorization data to persistent storage.
540:      */
541:     public function save()
542:     {
543:     }
544: 
545:     /**
546:      * Removes all authorization data.
547:      */
548:     public function clearAll()
549:     {
550:         $this->clearAuthAssignments();
551:         $this->db->createCommand()->delete($this->itemChildTable);
552:         $this->db->createCommand()->delete($this->itemTable);
553:     }
554: 
555:     /**
556:      * Removes all authorization assignments.
557:      */
558:     public function clearAuthAssignments()
559:     {
560:         $this->db->createCommand()->delete($this->assignmentTable);
561:     }
562: 
563:     /**
564:      * Checks whether there is a loop in the authorization item hierarchy.
565:      * @param string $itemName parent item name
566:      * @param string $childName the name of the child item that is to be added to the hierarchy
567:      * @return boolean whether a loop exists
568:      */
569:     protected function detectLoop($itemName,$childName)
570:     {
571:         if($childName===$itemName)
572:             return true;
573:         foreach($this->getItemChildren($childName) as $child)
574:         {
575:             if($this->detectLoop($itemName,$child->getName()))
576:                 return true;
577:         }
578:         return false;
579:     }
580: 
581:     /**
582:      * @return CDbConnection the DB connection instance
583:      * @throws CException if {@link connectionID} does not point to a valid application component.
584:      */
585:     protected function getDbConnection()
586:     {
587:         if($this->db!==null)
588:             return $this->db;
589:         elseif(($this->db=Yii::app()->getComponent($this->connectionID)) instanceof CDbConnection)
590:             return $this->db;
591:         else
592:             throw new CException(Yii::t('yii','CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.',
593:                 array('{id}'=>$this->connectionID)));
594:     }
595: 
596:     /**
597:      * @return boolean whether the database is a SQLite database
598:      */
599:     protected function usingSqlite()
600:     {
601:         return $this->_usingSqlite;
602:     }
603: }
604: 
API documentation generated by ApiGen 2.8.0