Author: david
Date: Wed Sep 16 16:01:56 2009
New Revision: 3355

Log:
Initial commit of ACL authorization logic.

Added:
   trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php   (contents, props changed)
Modified:
   trunk/lib/model/QubitUser.php

Modified: trunk/lib/model/QubitUser.php
==============================================================================
--- trunk/lib/model/QubitUser.php       Wed Sep 16 16:00:54 2009        (r3354)
+++ trunk/lib/model/QubitUser.php       Wed Sep 16 16:01:56 2009        (r3355)
@@ -103,4 +103,38 @@
 
     return ($validCreds) ? $user : null;
   }
+
+  /**
+   * Check if user belongs to *any* of the checkGroup(s) listed
+   *
+   * @param mixed $groups - integer value for group id, or array of group ids
+   * @return boolean
+   */
+  public function hasGroup($checkGroups)
+  {
+    $hasGroup = false;
+
+    // Cast $checkGroups as an array
+    if (!is_array($checkGroups))
+    {
+      $checkGroups = array($checkGroups);
+    }
+
+    $criteria = new Criteria;
+    $criteria->add(QubitAclUserGroup::USER_ID, $this->id, Criteria::EQUAL);
+
+    if (0 < count($userGroups = QubitAclUserGroup::get($criteria)))
+    {
+      foreach ($userGroups as $userGroup)
+      {
+        if (in_array(intval($userGroup->groupId), $checkGroups))
+        {
+          $hasGroup = true;
+          break;
+        }
+      }
+    }
+
+    return $hasGroup;
+  }
 } // User

Added: trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php    Wed Sep 16 16:01:56 
2009        (r3355)
@@ -0,0 +1,238 @@
+<?php
+
+/*
+ * This file is part of Qubit Toolkit.
+ *
+ * Qubit Toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Qubit Toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Qubit Toolkit.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Access Control List (ACL) functionality
+ *
+ * @package    qbAclPlugin
+ * @subpackage acl
+ * @author     David Juhasz <[email protected]>
+ * @version    svn:$Id$
+ */
+class QubitAcl
+{
+  const GRANT = 2;
+  const INHERIT = 1;
+  const DENY  = 0;
+
+  /**
+   * Test user access to the given access control object (aco).
+   *
+   * Note: Current sf_user is assumed, but can be overridden with
+   * $options['userId'].
+   *
+   * @param mixed   $aco object to which user is requesting access
+   * @param integer $actionId requested action key
+   * @param array   $options optional parameters
+   */
+  public static function check($aco, $actionId, $options = array())
+  {
+    if (isset($options['userId']))
+    {
+      $user = QubitUser::getById($options['userId']);
+    }
+    else
+    {
+      $user = sfContext::getInstance()->getUser()->getQubitUser();
+    }
+
+    // TODO: Rely on ACO hierarchy exclusively for determining access, this
+    // requires having a ROOT object for all ACOs (Actor, Repository, etc.)
+    $hasAccess = false;
+    switch (get_class($aco))
+    {
+      // Check permissions with repository condition
+      case 'QubitInformationObject':
+        $options['repositoryId'] = $aco->getRepository()->id;
+        $hasAccess = self::allowAccess($user, $aco, $actionId, $options);
+        break;
+
+      // Allow to *any* user that is logged in, or if action is "read"
+      case 'QubitActor':
+      case 'QubitRepository':
+        $hasAccess = (null != $user || QubitAclAction::READ_ID == $actionId);
+        break;
+
+      // Administrator or editor
+      case 'QubitTerm':
+        $hasAccess = $user->hasGroup(array(
+          QubitAclGroup::ADMINISTRATOR_ID,
+          QubitAclGroup::EDITOR_ID
+        ));
+        break;
+
+      // Administrator only
+      case 'QubitUser':
+      case 'QubitMenu':
+      case 'QubitStaticPage':
+        $hasAccess = $user->hasGroup(QubitAclGroup::ADMINISTRATOR_ID);
+    }
+
+    return $hasAccess;
+  }
+
+  protected static function getGrantDeny($permission)
+  {
+    switch ($permission->grantDeny)
+    {
+      case '1':
+        return self::GRANT;
+      case '0':
+        return self::DENY;
+      default:
+        return self::INHERIT;
+    }
+  }
+
+  protected static function getAcoLineage($aco)
+  {
+    $lineage = array($aco->id);
+    foreach ($aco->getAscendants()->orderBy('rgt') as $ascendant)
+    {
+      $lineage[] = $scendant;
+    }
+
+    return $lineage;
+  }
+
+  protected static function allowAccess($user, $aco, $actionId, $options)
+  {
+    $permission = self::INHERIT;
+
+    // Check user permissions first
+    $permission = self::checkUserPermissions($user, $aco, $actionId, $options);
+
+    // Then check group permissions
+    if (self::INHERIT == $permission)
+    {
+      $permission = self::checkGroupPermissions($user, $aco, $actionId, 
$options);
+    }
+
+    return (self::GRANT == $permission);
+  }
+
+  protected static function checkUserPermissions($user, $aco, $actionId, 
$options = array())
+  {
+    $grantDeny = self::INHERIT;
+
+    $criteria = new Criteria;
+    $criteria->add(QubitAclPermission::USER_ID, $user->id, Criteria::EQUAL);
+    $criteria->add(QubitAclPermission::ACTION_ID, $actionId, Criteria::EQUAL);
+    $criteria = self::addObjectCriteria($criteria, $aco->id);
+
+    // Check 'last-in' permissions first
+    $criteria->addDescendingOrderyByColumn(QubitAclPermission::ID);
+
+    if (0 < count($permissions = QubitAclPermission::get($c)))
+    {
+      $grantDeny = self::evaluatePermissionList($permissions);
+    }
+
+    // If 'inherit' work way up permission chain
+    if (self::INHERIT == $grantDeny)
+    {
+      if (0 < count($ancestors = $aco->getAncestors()->orderBy('rgt')))
+      {
+        $parent = $ancestors->offsetGet(0);
+        $grantDeny = self::checkUserPermissions($user, $parent, $actionId, 
$options);
+      }
+      else
+      {
+        // Check for global (objectId == null) permissions if specific
+        // permissions for ACO chain are not found
+        $grantDeny = self::checkUserPermissions($user, null, $actionId, 
$options);
+      }
+    }
+
+    return $grantDeny;
+  }
+
+  protected static function checkGroupPermissions($user, $aco, $actionId, 
$options = array())
+  {
+    $grantDeny = self::INHERIT;
+
+    $criteria = new Criteria;
+    $criteria->add(QubitAclUserGroup::USER_ID, $user->id, Criteria::EQUAL);
+    $criteria->addJoin(QubitAclUserGroup::GROUP_ID, 
QubitAclPermission::GROUP_ID, Criteria::INNER_JOIN);
+    $criteria->add(QubitAclPermission::ACTION_ID, $actionId, Criteria::EQUAL);
+
+    $criteria = self::addObjectCriteria($criteria, $aco->id);
+
+    // Check 'higher level' groups first
+    $criteria->addAscendingOrderyByColumn(QubitAclPermission::GROUP_ID);
+
+    // Check 'last-in' permissions first
+    $criteria->addDescendingOrderyByColumn(QubitAclPermission::ID);
+
+    if (0 < count($permissions = QubitAclPermission::get($c)))
+    {
+      $grantDeny = self::evaluatePermissionList($permissions);
+    }
+
+    // If 'inherit' work way up permission chain
+    if (self::INHERIT == $grantDeny)
+    {
+      if (0 < count($ancestors = $aco->getAncestors()->orderBy('rgt')))
+      {
+        $parent = $ancestors->offsetGet(0);
+        $grantDeny = self::checkGroupPermissions($user, $parent, $actionId, 
$options);
+      }
+      else
+      {
+        // Check for global (objectId == null) permissions if specific
+        // permissions for ACO chain are not found
+        $grantDeny = self::checkGroupPermissions($user, null, $actionId, 
$options);
+      }
+    }
+
+    return $grantDeny;
+  }
+
+  protected static function addObjectCriteria($criteria, $objectId)
+  {
+    if (null == $objectId)
+    {
+      $criteria->add(QubitAclPermission::OBJECT_ID, null, Criteria::IS_NULL);
+    }
+    else
+    {
+      $criteria->add(QubitAclPermission::OBJECT_ID, $objectId, 
Criteria::EQUAL);
+    }
+
+    return $criteria;
+  }
+
+  protected static function evaluatePermissionList($permissions, $aco)
+  {
+    $grantDeny = self::INHERIT;
+
+    // Evaluate permission in descending order (last permission entered takes
+    // precedence)
+    foreach ($permissions as $permission)
+    {
+      if ($permission->objectId == $node->id)
+      {
+        $grantDeny = self::getGrantDeny($permission);
+        break;
+      }
+    }
+
+    return $grantDeny;
+  }
+}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Qubit Toolkit Commits" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.ca/group/qubit-commits?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to