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
-~----------~----~----~----~------~----~------~--~---