[ Index ]

PHP Cross Reference of Joomla 2.5.4 DE

title

Body

[close]

/libraries/joomla/access/ -> access.php (source)

   1  <?php
   2  /**
   3   * @package     Joomla.Platform
   4   * @subpackage  Access
   5   *
   6   * @copyright   Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
   7   * @license     GNU General Public License version 2 or later; see LICENSE
   8   */
   9  
  10  defined('JPATH_PLATFORM') or die;
  11  
  12  jimport('joomla.utilities.arrayhelper');
  13  
  14  /**
  15   * Class that handles all access authorisation routines.
  16   *
  17   * @package     Joomla.Platform
  18   * @subpackage  Access
  19   * @since       11.1
  20   */
  21  class JAccess
  22  {
  23      /**
  24       * Array of view levels
  25       *
  26       * @var    array
  27       * @since  11.1
  28       */
  29      protected static $viewLevels = array();
  30  
  31      /**
  32       * Array of rules for the asset
  33       *
  34       * @var    array
  35       * @since  11.1
  36       */
  37      protected static $assetRules = array();
  38  
  39      /**
  40       * Array of user groups.
  41       *
  42       * @var    array
  43       * @since  11.1
  44       */
  45      protected static $userGroups = array();
  46  
  47      /**
  48       * Array of user group paths.
  49       *
  50       * @var    array
  51       * @since  11.1
  52       */
  53      protected static $userGroupPaths = array();
  54  
  55      /**
  56       * Array of cached groups by user.
  57       *
  58       * @var    array
  59       * @since  11.1
  60       */
  61      protected static $groupsByUser = array();
  62  
  63      /**
  64       * Method for clearing static caches.
  65       *
  66       * @return  void
  67       *
  68       * @since   11.3
  69       */
  70  	public static function clearStatics()
  71      {
  72          self::$viewLevels = array();
  73          self::$assetRules = array();
  74          self::$userGroups = array();
  75          self::$userGroupPaths = array();
  76          self::$groupsByUser = array();
  77      }
  78  
  79      /**
  80       * Method to check if a user is authorised to perform an action, optionally on an asset.
  81       *
  82       * @param   integer  $userId  Id of the user for which to check authorisation.
  83       * @param   string   $action  The name of the action to authorise.
  84       * @param   mixed    $asset   Integer asset id or the name of the asset as a string.  Defaults to the global asset node.
  85       *
  86       * @return  boolean  True if authorised.
  87       *
  88       * @since   11.1
  89       */
  90  	public static function check($userId, $action, $asset = null)
  91      {
  92          // Sanitise inputs.
  93          $userId = (int) $userId;
  94  
  95          $action = strtolower(preg_replace('#[\s\-]+#', '.', trim($action)));
  96          $asset = strtolower(preg_replace('#[\s\-]+#', '.', trim($asset)));
  97  
  98          // Default to the root asset node.
  99          if (empty($asset))
 100          {
 101              $asset = 1;
 102          }
 103  
 104          // Get the rules for the asset recursively to root if not already retrieved.
 105          if (empty(self::$assetRules[$asset]))
 106          {
 107              self::$assetRules[$asset] = self::getAssetRules($asset, true);
 108          }
 109  
 110          // Get all groups against which the user is mapped.
 111          $identities = self::getGroupsByUser($userId);
 112          array_unshift($identities, $userId * -1);
 113  
 114          return self::$assetRules[$asset]->allow($action, $identities);
 115      }
 116  
 117      /**
 118       * Method to check if a group is authorised to perform an action, optionally on an asset.
 119       *
 120       * @param   integer  $groupId  The path to the group for which to check authorisation.
 121       * @param   string   $action   The name of the action to authorise.
 122       * @param   mixed    $asset    Integer asset id or the name of the asset as a string.  Defaults to the global asset node.
 123       *
 124       * @return  boolean  True if authorised.
 125       *
 126       * @since   11.1
 127       */
 128  	public static function checkGroup($groupId, $action, $asset = null)
 129      {
 130          // Sanitize inputs.
 131          $groupId = (int) $groupId;
 132          $action = strtolower(preg_replace('#[\s\-]+#', '.', trim($action)));
 133          $asset = strtolower(preg_replace('#[\s\-]+#', '.', trim($asset)));
 134  
 135          // Get group path for group
 136          $groupPath = self::getGroupPath($groupId);
 137  
 138          // Default to the root asset node.
 139          if (empty($asset))
 140          {
 141              $asset = 1;
 142          }
 143  
 144          // Get the rules for the asset recursively to root if not already retrieved.
 145          if (empty(self::$assetRules[$asset]))
 146          {
 147              self::$assetRules[$asset] = self::getAssetRules($asset, true);
 148          }
 149  
 150          return self::$assetRules[$asset]->allow($action, $groupPath);
 151      }
 152  
 153      /**
 154       * Gets the parent groups that a leaf group belongs to in its branch back to the root of the tree
 155       * (including the leaf group id).
 156       *
 157       * @param   mixed  $groupId  An integer or array of integers representing the identities to check.
 158       *
 159       * @return  mixed  True if allowed, false for an explicit deny, null for an implicit deny.
 160       *
 161       * @since   11.1
 162       */
 163  	protected static function getGroupPath($groupId)
 164      {
 165          // Preload all groups
 166          if (empty(self::$userGroups))
 167          {
 168              $db = JFactory::getDbo();
 169              $query = $db->getQuery(true)
 170                  ->select('parent.id, parent.lft, parent.rgt')
 171                  ->from('#__usergroups AS parent')
 172                  ->order('parent.lft');
 173              $db->setQuery($query);
 174              self::$userGroups = $db->loadObjectList('id');
 175          }
 176  
 177          // Make sure groupId is valid
 178          if (!array_key_exists($groupId, self::$userGroups))
 179          {
 180              return array();
 181          }
 182  
 183          // Get parent groups and leaf group
 184          if (!isset(self::$userGroupPaths[$groupId]))
 185          {
 186              self::$userGroupPaths[$groupId] = array();
 187  
 188              foreach (self::$userGroups as $group)
 189              {
 190                  if ($group->lft <= self::$userGroups[$groupId]->lft && $group->rgt >= self::$userGroups[$groupId]->rgt)
 191                  {
 192                      self::$userGroupPaths[$groupId][] = $group->id;
 193                  }
 194              }
 195          }
 196  
 197          return self::$userGroupPaths[$groupId];
 198      }
 199  
 200      /**
 201       * Method to return the JAccessRules object for an asset.  The returned object can optionally hold
 202       * only the rules explicitly set for the asset or the summation of all inherited rules from
 203       * parent assets and explicit rules.
 204       *
 205       * @param   mixed    $asset      Integer asset id or the name of the asset as a string.
 206       * @param   boolean  $recursive  True to return the rules object with inherited rules.
 207       *
 208       * @return  JAccessRules   JAccessRules object for the asset.
 209       *
 210       * @since   11.1
 211       */
 212  	public static function getAssetRules($asset, $recursive = false)
 213      {
 214          // Get the database connection object.
 215          $db = JFactory::getDbo();
 216  
 217          // Build the database query to get the rules for the asset.
 218          $query = $db->getQuery(true);
 219          $query->select($recursive ? 'b.rules' : 'a.rules');
 220          $query->from('#__assets AS a');
 221          //sqlsrv change
 222          $query->group($recursive ? 'b.id, b.rules, b.lft' : 'a.id, a.rules, a.lft');
 223  
 224          // If the asset identifier is numeric assume it is a primary key, else lookup by name.
 225          if (is_numeric($asset))
 226          {
 227              // Get the root even if the asset is not found
 228              $query->where('(a.id = ' . (int) $asset . ($recursive ? ' OR a.parent_id=0' : '') . ')');
 229          }
 230          else
 231          {
 232              // Get the root even if the asset is not found
 233              $query->where('(a.name = ' . $db->quote($asset) . ($recursive ? ' OR a.parent_id=0' : '') . ')');
 234          }
 235  
 236          // If we want the rules cascading up to the global asset node we need a self-join.
 237          if ($recursive)
 238          {
 239              $query->leftJoin('#__assets AS b ON b.lft <= a.lft AND b.rgt >= a.rgt');
 240              $query->order('b.lft');
 241          }
 242  
 243          // Execute the query and load the rules from the result.
 244          $db->setQuery($query);
 245          $result = $db->loadColumn();
 246  
 247          // Get the root even if the asset is not found and in recursive mode
 248          if ($recursive && empty($result))
 249          {
 250              $query = $db->getQuery(true);
 251              $query->select('rules');
 252              $query->from('#__assets');
 253              $query->where('parent_id = 0');
 254              $db->setQuery($query);
 255              $result = $db->loadColumn();
 256          }
 257  
 258          // Instantiate and return the JAccessRules object for the asset rules.
 259          $rules = new JAccessRules;
 260          $rules->mergeCollection($result);
 261  
 262          return $rules;
 263      }
 264  
 265      /**
 266       * Method to return a list of user groups mapped to a user. The returned list can optionally hold
 267       * only the groups explicitly mapped to the user or all groups both explicitly mapped and inherited
 268       * by the user.
 269       *
 270       * @param   integer  $userId     Id of the user for which to get the list of groups.
 271       * @param   boolean  $recursive  True to include inherited user groups.
 272       *
 273       * @return  array    List of user group ids to which the user is mapped.
 274       *
 275       * @since   11.1
 276       */
 277  	public static function getGroupsByUser($userId, $recursive = true)
 278      {
 279          // Creates a simple unique string for each parameter combination:
 280          $storeId = $userId . ':' . (int) $recursive;
 281  
 282          if (!isset(self::$groupsByUser[$storeId]))
 283          {
 284              // Guest user (if only the actually assigned group is requested)
 285              if (empty($userId) && !$recursive)
 286              {
 287                  $result = array(JComponentHelper::getParams('com_users')->get('guest_usergroup', 1));
 288              }
 289              // Registered user and guest if all groups are requested
 290              else
 291              {
 292                  $db = JFactory::getDbo();
 293  
 294                  // Build the database query to get the rules for the asset.
 295                  $query = $db->getQuery(true);
 296                  $query->select($recursive ? 'b.id' : 'a.id');
 297                  if (empty($userId))
 298                  {
 299                      $query->from('#__usergroups AS a');
 300                      $query->where('a.id = ' . (int) JComponentHelper::getParams('com_users')->get('guest_usergroup', 1));
 301                  }
 302                  else
 303                  {
 304                      $query->from('#__user_usergroup_map AS map');
 305                      $query->where('map.user_id = ' . (int) $userId);
 306                      $query->leftJoin('#__usergroups AS a ON a.id = map.group_id');
 307                  }
 308  
 309                  // If we want the rules cascading up to the global asset node we need a self-join.
 310                  if ($recursive)
 311                  {
 312                      $query->leftJoin('#__usergroups AS b ON b.lft <= a.lft AND b.rgt >= a.rgt');
 313                  }
 314  
 315                  // Execute the query and load the rules from the result.
 316                  $db->setQuery($query);
 317                  $result = $db->loadColumn();
 318  
 319                  // Clean up any NULL or duplicate values, just in case
 320                  JArrayHelper::toInteger($result);
 321  
 322                  if (empty($result))
 323                  {
 324                      $result = array('1');
 325                  }
 326                  else
 327                  {
 328                      $result = array_unique($result);
 329                  }
 330              }
 331  
 332              self::$groupsByUser[$storeId] = $result;
 333          }
 334  
 335          return self::$groupsByUser[$storeId];
 336      }
 337  
 338      /**
 339       * Method to return a list of user Ids contained in a Group
 340       *
 341       * @param   integer  $groupId    The group Id
 342       * @param   boolean  $recursive  Recursively include all child groups (optional)
 343       *
 344       * @return  array
 345       *
 346       * @since   11.1
 347       * @todo    This method should move somewhere else
 348       */
 349  	public static function getUsersByGroup($groupId, $recursive = false)
 350      {
 351          // Get a database object.
 352          $db = JFactory::getDbo();
 353  
 354          $test = $recursive ? '>=' : '=';
 355  
 356          // First find the users contained in the group
 357          $query = $db->getQuery(true);
 358          $query->select('DISTINCT(user_id)');
 359          $query->from('#__usergroups as ug1');
 360          $query->join('INNER', '#__usergroups AS ug2 ON ug2.lft' . $test . 'ug1.lft AND ug1.rgt' . $test . 'ug2.rgt');
 361          $query->join('INNER', '#__user_usergroup_map AS m ON ug2.id=m.group_id');
 362          $query->where('ug1.id=' . $db->Quote($groupId));
 363  
 364          $db->setQuery($query);
 365  
 366          $result = $db->loadColumn();
 367  
 368          // Clean up any NULL values, just in case
 369          JArrayHelper::toInteger($result);
 370  
 371          return $result;
 372      }
 373  
 374      /**
 375       * Method to return a list of view levels for which the user is authorised.
 376       *
 377       * @param   integer  $userId  Id of the user for which to get the list of authorised view levels.
 378       *
 379       * @return  array    List of view levels for which the user is authorised.
 380       *
 381       * @since   11.1
 382       */
 383  	public static function getAuthorisedViewLevels($userId)
 384      {
 385          // Get all groups that the user is mapped to recursively.
 386          $groups = self::getGroupsByUser($userId);
 387  
 388          // Only load the view levels once.
 389          if (empty(self::$viewLevels))
 390          {
 391              // Get a database object.
 392              $db = JFactory::getDBO();
 393  
 394              // Build the base query.
 395              $query = $db->getQuery(true);
 396              $query->select('id, rules');
 397              $query->from($query->qn('#__viewlevels'));
 398  
 399              // Set the query for execution.
 400              $db->setQuery((string) $query);
 401  
 402              // Build the view levels array.
 403              foreach ($db->loadAssocList() as $level)
 404              {
 405                  self::$viewLevels[$level['id']] = (array) json_decode($level['rules']);
 406              }
 407          }
 408  
 409          // Initialise the authorised array.
 410          $authorised = array(1);
 411  
 412          // Find the authorised levels.
 413          foreach (self::$viewLevels as $level => $rule)
 414          {
 415              foreach ($rule as $id)
 416              {
 417                  if (($id < 0) && (($id * -1) == $userId))
 418                  {
 419                      $authorised[] = $level;
 420                      break;
 421                  }
 422                  // Check to see if the group is mapped to the level.
 423                  elseif (($id >= 0) && in_array($id, $groups))
 424                  {
 425                      $authorised[] = $level;
 426                      break;
 427                  }
 428              }
 429          }
 430  
 431          return $authorised;
 432      }
 433  
 434      /**
 435       * Method to return a list of actions for which permissions can be set given a component and section.
 436       *
 437       * @param   string  $component  The component from which to retrieve the actions.
 438       * @param   string  $section    The name of the section within the component from which to retrieve the actions.
 439       *
 440       * @return  array  List of actions available for the given component and section.
 441       *
 442       * @since   11.1
 443       *
 444       * @todo    Need to decouple this method from the CMS. Maybe check if $component is a
 445       *          valid file (or create a getActionsFromFile method).
 446       */
 447  	public static function getActions($component, $section = 'component')
 448      {
 449          $actions = array();
 450  
 451          if (defined('JPATH_ADMINISTRATOR') && is_file(JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml'))
 452          {
 453              $xml = simplexml_load_file(JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml');
 454  
 455              foreach ($xml->children() as $child)
 456              {
 457                  if ($section == (string) $child['name'])
 458                  {
 459                      foreach ($child->children() as $action)
 460                      {
 461                          $actions[] = (object) array(
 462                              'name' => (string) $action['name'],
 463                              'title' => (string) $action['title'],
 464                              'description' => (string) $action['description']);
 465                      }
 466  
 467                      break;
 468                  }
 469              }
 470          }
 471  
 472          return $actions;
 473      }
 474  }


Generated: Tue Apr 3 11:40:28 2012 Cross-referenced by PHPXref 0.7.1