Author: david
Date: Thu Oct 22 13:25:45 2009
New Revision: 3798
Log:
Optimize alogrithm for determining user repository access permissions. Fixes
issue #1080.
Modified:
trunk/apps/qubit/modules/informationobject/actions/listAction.class.php
trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php
Modified:
trunk/apps/qubit/modules/informationobject/actions/listAction.class.php
==============================================================================
--- trunk/apps/qubit/modules/informationobject/actions/listAction.class.php
Thu Oct 22 11:14:11 2009 (r3797)
+++ trunk/apps/qubit/modules/informationobject/actions/listAction.class.php
Thu Oct 22 13:25:45 2009 (r3798)
@@ -80,50 +80,83 @@
{
$query = $request->query;
}
-
- // Filter out objects in forbidden repositories (no read access)
- if (0 < count($deniedRepositories =
QubitAcl::deniedRepositories(QubitInformationObject::getRoot(),
QubitAclAction::READ_ID)))
+ $repositoryAccess = QubitAcl::getRepositoryAccess(QubitAclAction::READ_ID);
+ if (1 == count($repositoryAccess))
{
- // If all repositories are denied, re-route user
- if (array('*') == $deniedRepositories)
+ // If all repositories are denied 'read' access, re-route user to login
+ if (array('id' => '*', 'access' => QubitAcl::DENY) == $repositoryAccess)
{
QubitAcl::forwardUnauthorized();
}
-
+ }
+ else
+ {
$subquery = new Zend_Search_Lucene_Search_Query_MultiTerm();
- foreach ($deniedRepositories as $repositoryId)
+ while ($repo = array_shift($repositoryAccess))
{
- $subquery->addTerm(new Zend_Search_Lucene_Index_Term($repositoryId,
'repositoryid'));
+ if ('*' != $repo['id'])
+ {
+ $subquery->addTerm(new Zend_Search_Lucene_Index_Term($repo['id'],
'repositoryid'));
+ if (QubitAcl::DENY == $repo['access'])
+ {
+ $deniedRepositories[] = $repo['id'];
+ }
+ }
+ else
+ {
+ if (QubitAcl::DENY == $repo['access'])
+ {
+ // Require repos to be specifically allowed (all others prohibited)
+ $query->addSubquery($subquery, true /* required */);
+ }
+ else
+ {
+ // Prohibit specified repos (all others allowed)
+ $query->addSubquery($subquery, false /* prohibited */);
+ }
+ }
}
-
- $query->addSubquery($subquery, false /* prohibited */);
}
// Filter out 'draft' items by repository
- $deniedStatusRepos =
QubitAcl::deniedRepositories(QubitInformationObject::getRoot(),
QubitAclAction::VIEW_DRAFT_ID);
- if (0 < count($deniedStatusRepos))
+ $repositoryViewDrafts =
QubitAcl::getRepositoryAccess(QubitAclAction::VIEW_DRAFT_ID);
+ if (1 == count($repositoryViewDrafts))
{
- if (array('*') == $deniedStatusRepos)
+ if (array('id' => '*', 'access' => QubitAcl::DENY) ==
$repositoryViewDrafts)
{
// Don't show *any* draft info objects
$query->addSubquery(new Zend_Search_Lucene_Search_Query_Term(new
Zend_Search_Lucene_Index_Term(QubitTerm::PUBLICATION_STATUS_DRAFT_ID,
'publicationStatusId')), false);
}
- else
+ }
+ else
+ {
+ $subquery = new Zend_Search_Lucene_Search_Query_MultiTerm();
+ while ($repo = array_shift($repositoryViewDrafts))
{
- $subquery = new Zend_Search_Lucene_Search_Query_MultiTerm();
- foreach ($deniedStatusRepos as $repositoryId)
+ // Don't bother excluding repos (again) that have no read access at all
+ if (in_array($repo['id'], $deniedRepositories))
{
- // Don't bother excluding repos (again) that have no read access at
all
- if (in_array($repositoryId, $deniedRepositories))
- {
- continue;
- }
+ continue;
+ }
- $subquery->addTerm(new Zend_Search_Lucene_Index_Term($repositoryId,
'repositoryid'), true);
+ if ('*' != $repo['id'])
+ {
+ $subquery->addTerm(new Zend_Search_Lucene_Index_Term($repo['id'],
'repositoryid'), true);
$subquery->addTerm(new
Zend_Search_Lucene_Index_Term(QubitTerm::PUBLICATION_STATUS_DRAFT_ID,
'publicationStatusId'), true);
}
-
- $query->addSubquery($subquery, false /* prohibited */);
+ else
+ {
+ if (QubitAcl::DENY == $repo['access'])
+ {
+ // Require repos to be specifically allowed (all others prohibited)
+ $query->addSubquery($subquery, true /* required */);
+ }
+ else
+ {
+ // Prohibit specified repos (all others allowed)
+ $query->addSubquery($subquery, false /* prohibited */);
+ }
+ }
}
}
Modified: trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php
==============================================================================
--- trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php Thu Oct 22 11:14:11
2009 (r3797)
+++ trunk/plugins/qbAclPlugin/lib/QubitAcl.class.php Thu Oct 22 13:25:45
2009 (r3798)
@@ -320,34 +320,102 @@
return self::evalGrantDeny($grantDeny);
}
- public static function deniedRepositories($informationObject, $actionId,
$options = array())
+ /**
+ * Add permissions to repository access array
+ *
+ * @param $repositoryAccess input access array
+ * @param $permissions QubitQuery permission list
+ * @return array output access array
+ */
+ public static function addRepositoryAccess($repositoryAccess, $permissions)
{
- $deniedRepositories = array();
-
- if (!$informationObject instanceof QubitInformationObject)
+ foreach ($permissions as $permission)
{
+ if (null === $permission->grantDeny)
+ {
+ continue;
+ }
+
+ $access = (1 == $permission->grantDeny) ? self::GRANT : self::DENY;
+
+ // If no repository specified, then apply rule to all repositories
+ if (null === ($repository = $permission->getRepository()))
+ {
+ $repositoryAccess[] = array('id' => '*', 'access' => $access);
+ break;
+ }
- return;
+ // Add repository access if it isn't set already
+ else if (!in_array($repository->id, array_keys($repositoryAccess)))
+ {
+ $repositoryAccess[] = array('id' => $repository->id, 'access' =>
$access);
+ }
}
- // get repository list
- $repositories = QubitRepository::getAll();
+ return $repositoryAccess;
+ }
- foreach ($repositories as $repository)
+ /**
+ * List the repository access rules for the current user
+ *
+ * @param $actionId integer Access privilige being requested
+ * @param $options array optional parameters
+ * @return array
+ */
+ public static function getRepositoryAccess(QubitAclAction $actionId,
$options = array())
+ {
+ $repositoryAccess = array();
+
+ // Test user permissions
+ $criteria = new Criteria;
+ $criteria->add(QubitAclPermission::ACTION_ID, $actionId);
+ $criteria->add(QubitAclPermission::USER_ID,
sfContext::getInstance()->getUser()->getUserId());
+ $criteria->addDescendingOrderByColumn(QubitAclPermission::ID);
+
+ if (0 < count($permissions = QubitAclPermission::get($criteria)))
+ {
+ $repositoryAccess = self::addRepositoryAccess($repositoryAccess,
$permissions);
+ }
+
+ if (0 == count($repositoryAccess) || '*' !=
$repositoryAccess[count($repositoryAccess) - 1]['id'])
{
- $options['parameters'] = array('repositoryId' => $repository->id);
- if (!self::check($informationObject, $actionId, $options))
+ // Test user group permissions
+ $userGroupIds = array();
+ foreach (sfContext::getInstance()->getUser()->listGroups() as $group)
{
- $deniedRepositories[] = $repository->id;
+ $userGroupIds[] = $group->id;
+ }
+
+ $criteria = new Criteria;
+ $criteria->add(QubitAclPermission::ACTION_ID, $actionId);
+ $criteria->add(QubitAclPermission::GROUP_ID, $userGroupIds,
Criteria::IN);
+ $criteria->addDescendingOrderByColumn(QubitAclPermission::ID);
+
+ if (0 < count($permissions = QubitAclPermission::get($criteria)))
+ {
+ $repositoryAccess = self::addRepositoryAccess($repositoryAccess,
$permissions);
}
}
- if (0 < count($repositories) && count($repositories) ==
count($deniedRepositories))
+ // Default is to deny access if no permissions specified
+ if (0 == count($repositoryAccess) || '*' !=
$repositoryAccess[count($repositoryAccess) - 1]['id'])
{
- $deniedRepositories = array('*');
+ $repositoryAccess[] = array('id' => '*', 'access' => self::DENY);
+ }
+
+ // Collapse access rules so that e.g.
+ // ('1' => deny, '2' => allow, '*' => deny) -> ('2' => allow, '*' => deny)
+ // ('1' => deny, '2' => allow, '*' => allow) -> (1' => deny, '*' => allow)
+ $globalPermission = $repositoryAccess[count($repositoryAccess) -
1]['access'];
+ foreach ($repositoryAccess as $i => $val)
+ {
+ if ('*' != $val['id'] && $globalPermission == $val['access'])
+ {
+ unset($repositoryAccess[$i]);
+ }
}
- return $deniedRepositories;
+ return $repositoryAccess;
}
public static function forwardUnauthorized()
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---