summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBharat Mediratta <bharat@menalto.com>2008-12-11 19:06:40 +0000
committerBharat Mediratta <bharat@menalto.com>2008-12-11 19:06:40 +0000
commit914164d5ebd490d946541668eb78571d2f2c023b (patch)
tree4c487ffdb06f12bd6dabcd2b42fdad352960a3c4
parent1af3b8e10022323769a7080532a9a89f907407c6 (diff)
Split _update_access_cache into two functions separating view from
non-view. This is a step along the path towards moving the view access cache into the item model.
-rw-r--r--core/helpers/access.php238
1 files changed, 129 insertions, 109 deletions
diff --git a/core/helpers/access.php b/core/helpers/access.php
index 993f8e5b..ad62595d 100644
--- a/core/helpers/access.php
+++ b/core/helpers/access.php
@@ -136,7 +136,11 @@ class access_Core {
$access->__set("{$perm_name}_$group_id", $value);
$access->save();
- self::_update_access_cache($group, $perm_name, $item);
+ if ($perm_name =="view") {
+ self::_update_access_view_cache($group, $item);
+ } else {
+ self::_update_access_non_view_cache($group, $perm_name, $item);
+ }
}
/**
@@ -321,129 +325,76 @@ class access_Core {
}
/**
- * Update the Access_Cache model based on information from the Access_Intent model. This
- * creates a fast-lookup table for permissions based on the rules that the user has specified in
- * the intent model.
+ * Update the Access_Cache model based on information from the Access_Intent model for view
+ * permissions only.
*
* @todo: use database locking
*
* @param Group_Model $group
- * @param string $perm_name
* @param Item_Model $item
* @return void
*/
- public static function _update_access_cache($group, $perm_name, $item) {
+ public static function _update_access_view_cache($group, $item) {
$access = ORM::factory("access_intent")->where("item_id", $item->id)->find();
$group_id = $group ? $group->id : 0;
$db = Database::instance();
- $field = "{$perm_name}_$group_id";
-
- if ($perm_name == "view") {
- // With view permissions, deny values in the parent can override allow values in the child,
- // so start from the bottom of the tree and work upwards overlaying negative on top of
- // positive.
- //
- // If the item's intent is ALLOW or DEFAULT, it's possible that some ancestor has specified
- // DENY and this ALLOW cannot be obeyed. So in that case, back up the tree and find any
- // non-DEFAULT and non-ALLOW parent and propagate from there. If we can't find a matching
- // item, then its safe to propagate from here.
- if ($access->$field !== self::DENY) {
- $tmp_item = ORM::factory("item")
- ->join("access_intents", "items.id", "access_intents.item_id")
- ->where("left <", $item->left)
- ->where("right >", $item->right)
- ->where("$field", self::DENY)
- ->orderby("left", "DESC")
- ->limit(1)
- ->find();
- if ($tmp_item->loaded) {
- $item = $tmp_item;
- }
- }
+ $field = "view_$group_id";
- // We will have a problem if we're trying to change a DENY to an ALLOW because the
- // access_caches table will already contain DENY values and we won't be able to overwrite
- // them according the rule above. So mark every permission below this level as UNKNOWN so
- // that we can tell which permissions have been changed, and which ones need to be updated.
- $db->query("UPDATE `access_caches` SET `$field` = ? " .
- "WHERE `item_id` IN " .
- " (SELECT `id` FROM `items` " .
- " WHERE `left` >= $item->left " .
- " AND `right` <= $item->right)",
- array(self::UNKNOWN));
-
- $query = $db->query(
- "SELECT `access_intents`.`$field`, `items`.`left`, `items`.`right`, `items`.`id` " .
- "FROM `access_intents` JOIN (`items`) ON (`access_intents`.`item_id` = `items`.`id`) " .
- "WHERE `left` >= $item->left " .
- "AND `right` <= $item->right " .
- "AND `type` = 'album' " .
- "AND `$field` IS NOT NULL " .
- "ORDER BY `level` DESC ");
- foreach ($query as $row) {
- if ($row->$field == self::ALLOW) {
- // Propagate ALLOW for any row that is still UNKNOWN.
- $db->query(
- "UPDATE `access_caches` SET `$field` = {$row->$field} " .
- "WHERE `$field` = ? " .
- "AND `item_id` IN " .
- " (SELECT `id` FROM `items` " .
- " WHERE `left` >= $row->left " .
- " AND `right` <= $row->right)",
- array(self::UNKNOWN));
- } else if ($row->$field == self::DENY) {
- // DENY overwrites everything below it
- $db->query(
- "UPDATE `access_caches` SET `$field` = {$row->$field} " .
- "WHERE `item_id` IN " .
- " (SELECT `id` FROM `items` " .
- " WHERE `left` >= $row->left " .
- " AND `right` <= $row->right)");
- }
+ // With view permissions, deny values in the parent can override allow values in the child,
+ // so start from the bottom of the tree and work upwards overlaying negative on top of
+ // positive.
+ //
+ // If the item's intent is ALLOW or DEFAULT, it's possible that some ancestor has specified
+ // DENY and this ALLOW cannot be obeyed. So in that case, back up the tree and find any
+ // non-DEFAULT and non-ALLOW parent and propagate from there. If we can't find a matching
+ // item, then its safe to propagate from here.
+ if ($access->$field !== self::DENY) {
+ $tmp_item = ORM::factory("item")
+ ->join("access_intents", "items.id", "access_intents.item_id")
+ ->where("left <", $item->left)
+ ->where("right >", $item->right)
+ ->where("$field", self::DENY)
+ ->orderby("left", "DESC")
+ ->limit(1)
+ ->find();
+ if ($tmp_item->loaded) {
+ $item = $tmp_item;
}
+ }
- // Finally, if our intent is DEFAULT at this point it means that we were unable to find a
- // DENY parent in the hierarchy to propagate from. So we'll still have a UNKNOWN values in
- // the hierarchy, and all of those are safe to change to ALLOW.
- $db->query("UPDATE `access_caches` SET `$field` = ? " .
- "WHERE `$field` = ? " .
- "AND `item_id` IN " .
- " (SELECT `id` FROM `items` " .
- " WHERE `left` >= $item->left " .
- " AND `right` <= $item->right)",
- array(self::ALLOW, self::UNKNOWN));
- } else {
- // If the item's intent is DEFAULT, then we need to back up the chain to find the nearest
- // parent with an intent and propagate from there.
- //
- // @todo To optimize this, we wouldn't need to propagate from the parent, we could just
- // propagate from here with the parent's intent.
- if ($access->$field === null) {
- $tmp_item = ORM::factory("item")
- ->join("access_intents", "items.id", "access_intents.item_id")
- ->where("left <", $item->left)
- ->where("right >", $item->right)
- ->where("$field IS NOT", null)
- ->orderby("left", "DESC")
- ->limit(1)
- ->find();
- if ($tmp_item->loaded) {
- $item = $tmp_item;
- }
- }
+ // We will have a problem if we're trying to change a DENY to an ALLOW because the
+ // access_caches table will already contain DENY values and we won't be able to overwrite
+ // them according the rule above. So mark every permission below this level as UNKNOWN so
+ // that we can tell which permissions have been changed, and which ones need to be updated.
+ $db->query("UPDATE `access_caches` SET `$field` = ? " .
+ "WHERE `item_id` IN " .
+ " (SELECT `id` FROM `items` " .
+ " WHERE `left` >= $item->left " .
+ " AND `right` <= $item->right)",
+ array(self::UNKNOWN));
- // With non-view permissions, each level can override any permissions that came above it
- // so start at the top and work downwards, overlaying permissions as we go.
- $query = $db->query(
- "SELECT `access_intents`.`$field`, `items`.`left`, `items`.`right` " .
- "FROM `access_intents` JOIN (`items`) ON (`access_intents`.`item_id` = `items`.`id`) " .
- "WHERE `left` >= $item->left " .
- "AND `right` <= $item->right " .
- "AND `type` = 'album' " .
- "AND `$field` IS NOT NULL " .
- "ORDER BY `level` ASC");
- foreach ($query as $row) {
+ $query = $db->query(
+ "SELECT `access_intents`.`$field`, `items`.`left`, `items`.`right`, `items`.`id` " .
+ "FROM `access_intents` JOIN (`items`) ON (`access_intents`.`item_id` = `items`.`id`) " .
+ "WHERE `left` >= $item->left " .
+ "AND `right` <= $item->right " .
+ "AND `type` = 'album' " .
+ "AND `$field` IS NOT NULL " .
+ "ORDER BY `level` DESC ");
+ foreach ($query as $row) {
+ if ($row->$field == self::ALLOW) {
+ // Propagate ALLOW for any row that is still UNKNOWN.
+ $db->query(
+ "UPDATE `access_caches` SET `$field` = {$row->$field} " .
+ "WHERE `$field` = ? " .
+ "AND `item_id` IN " .
+ " (SELECT `id` FROM `items` " .
+ " WHERE `left` >= $row->left " .
+ " AND `right` <= $row->right)",
+ array(self::UNKNOWN));
+ } else if ($row->$field == self::DENY) {
+ // DENY overwrites everything below it
$db->query(
"UPDATE `access_caches` SET `$field` = {$row->$field} " .
"WHERE `item_id` IN " .
@@ -452,5 +403,74 @@ class access_Core {
" AND `right` <= $row->right)");
}
}
+
+ // Finally, if our intent is DEFAULT at this point it means that we were unable to find a
+ // DENY parent in the hierarchy to propagate from. So we'll still have a UNKNOWN values in
+ // the hierarchy, and all of those are safe to change to ALLOW.
+ $db->query("UPDATE `access_caches` SET `$field` = ? " .
+ "WHERE `$field` = ? " .
+ "AND `item_id` IN " .
+ " (SELECT `id` FROM `items` " .
+ " WHERE `left` >= $item->left " .
+ " AND `right` <= $item->right)",
+ array(self::ALLOW, self::UNKNOWN));
+ }
+
+ /**
+ * Update the Access_Cache model based on information from the Access_Intent model for non-view
+ * permissions.
+ *
+ * @todo: use database locking
+ *
+ * @param Group_Model $group
+ * @param string $perm_name
+ * @param Item_Model $item
+ * @return void
+ */
+ public static function _update_access_non_view_cache($group, $perm_name, $item) {
+ $access = ORM::factory("access_intent")->where("item_id", $item->id)->find();
+
+ $group_id = $group ? $group->id : 0;
+ $db = Database::instance();
+ $field = "{$perm_name}_$group_id";
+
+
+ // If the item's intent is DEFAULT, then we need to back up the chain to find the nearest
+ // parent with an intent and propagate from there.
+ //
+ // @todo To optimize this, we wouldn't need to propagate from the parent, we could just
+ // propagate from here with the parent's intent.
+ if ($access->$field === null) {
+ $tmp_item = ORM::factory("item")
+ ->join("access_intents", "items.id", "access_intents.item_id")
+ ->where("left <", $item->left)
+ ->where("right >", $item->right)
+ ->where("$field IS NOT", null)
+ ->orderby("left", "DESC")
+ ->limit(1)
+ ->find();
+ if ($tmp_item->loaded) {
+ $item = $tmp_item;
+ }
+ }
+
+ // With non-view permissions, each level can override any permissions that came above it
+ // so start at the top and work downwards, overlaying permissions as we go.
+ $query = $db->query(
+ "SELECT `access_intents`.`$field`, `items`.`left`, `items`.`right` " .
+ "FROM `access_intents` JOIN (`items`) ON (`access_intents`.`item_id` = `items`.`id`) " .
+ "WHERE `left` >= $item->left " .
+ "AND `right` <= $item->right " .
+ "AND `type` = 'album' " .
+ "AND `$field` IS NOT NULL " .
+ "ORDER BY `level` ASC");
+ foreach ($query as $row) {
+ $db->query(
+ "UPDATE `access_caches` SET `$field` = {$row->$field} " .
+ "WHERE `item_id` IN " .
+ " (SELECT `id` FROM `items` " .
+ " WHERE `left` >= $row->left " .
+ " AND `right` <= $row->right)");
+ }
}
}