Index: og_user_roles.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/og_user_roles/og_user_roles.module,v
retrieving revision 1.40
diff -u -p -r1.40 og_user_roles.module
--- og_user_roles.module	14 Aug 2009 12:08:06 -0000	1.40
+++ og_user_roles.module	14 Aug 2009 14:45:19 -0000
@@ -180,7 +180,7 @@ function og_user_roles_determine_context
  *
  * In Drupal 7, this fork can probably be replaced with
  * @code
- * drupal_static_reset('menu_get_item');
+ *   drupal_static_reset('menu_get_item');
  * @endcode
  *
  * @see menu_get_item()
@@ -199,7 +199,8 @@ function og_user_roles_menu_get_item($pa
     list($ancestors, $placeholders) = menu_get_ancestors($parts);
 
     if ($router_item = db_fetch_array(db_query_range('SELECT * FROM {menu_router} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) {
-      $map = _menu_translate($router_item, $original_map);
+      // OGUR: Allow privilege escalation; do not invoke access callbacks.
+      $map = og_user_roles_menu_translate($router_item, $original_map);
       if ($map === FALSE) {
         $router_items[$path] = FALSE;
         return FALSE;
@@ -216,6 +217,64 @@ function og_user_roles_menu_get_item($pa
 }
 
 /**
+ * Handles dynamic path translation and menu access control.
+ *
+ * Certain menu access callbacks (like _node_revision_access()) statically cache
+ * the result of the access check for performance. We only want to retrieve and
+ * determine the group context in og_user_roles_init(), resp.
+ * og_user_roles_menu_get_item(), where no additional roles have been granted
+ * yet. _menu_translate() would normally also invoke the access callback for the
+ * current page. Therefore, certain menu access callbacks, which statically
+ * cache their result, would return that result in subsequent invocations (i.e.
+ * FALSE when the user does not have permissions).
+ *
+ * Since OG user roles only wants to retrieve context and all of the regular
+ * menu system's behavior is and should not be modified, we simply skip the
+ * access check in this fork.
+ *
+ * In Drupal 7, this wrapper can probably be replaced with (or similar):
+ * @code
+ *   drupal_static_reset('_node_revision_access');
+ * @endcode
+ *
+ * @see _menu_translate()
+ * @see og_user_roles_menu_get_item()
+ */
+function og_user_roles_menu_translate(&$router_item, $map, $to_arg = FALSE) {
+  if ($to_arg) {
+    // Fill in missing path elements, such as the current uid.
+    _menu_link_map_translate($map, $router_item['to_arg_functions']);
+  }
+  // The $path_map saves the pieces of the path as strings, while elements in
+  // $map may be replaced with loaded objects.
+  $path_map = $map;
+  if (!_menu_load_objects($router_item, $map)) {
+    // An error occurred loading an object.
+    $router_item['access'] = FALSE;
+    return FALSE;
+  }
+
+  // Generate the link path for the page request or local tasks.
+  $link_map = explode('/', $router_item['path']);
+  for ($i = 0; $i < $router_item['number_parts']; $i++) {
+    if ($link_map[$i] == '%') {
+      $link_map[$i] = $path_map[$i];
+    }
+  }
+  $router_item['href'] = implode('/', $link_map);
+  $router_item['options'] = array();
+  // OGUR: Allow privilege escalation; do not invoke access callbacks.
+  //_menu_check_access($router_item, $map);
+  
+  // For performance, don't localize an item the user can't access.
+  if (!empty($router_item['access'])) {
+    _menu_item_localize($router_item, $map);
+  }
+
+  return $map;
+}
+
+/**
  * Get a loaded object from a router item.
  *
  * @see menu_get_object()
Index: tests/og_user_roles.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/og_user_roles/tests/og_user_roles.test,v
retrieving revision 1.3
diff -u -p -r1.3 og_user_roles.test
--- tests/og_user_roles.test	14 Aug 2009 12:00:30 -0000	1.3
+++ tests/og_user_roles.test	14 Aug 2009 15:46:18 -0000
@@ -12,7 +12,7 @@ class OGUserRolesTestCase extends OgTest
   public static function getInfo() {
     return array(
       'name' => 'OG User Roles',
-      'description' => 'Add, edit and delete custom block. Configure and move a module-defined block.',
+      'description' => 'Test privilege escalation of Organic Groups User Roles.',
       'group' => 'Organic groups',
     );
   }
@@ -35,6 +35,12 @@ class OGUserRolesTestCase extends OgTest
     // Create a group post content type.
     $this->og_post_type = $this->drupalCreateContentType();
     variable_set('og_content_type_usage_' . $this->og_post_type->name, 'group_post');
+    // Enable revisions for group post content type.
+    $edit = array(
+      'node_options[revision]' => 1,
+    );
+    $type_url_str = str_replace('_', '-', $this->og_post_type->name);
+    $this->drupalPost('admin/content/node-type/' . $type_url_str, $edit, t('Save content type'));
 
     // Create two groups and a post for each group.
     $this->gid1 = $this->addOgGroup($this->og_group_type->name);
@@ -64,11 +70,13 @@ class OGUserRolesTestCase extends OgTest
     );
     $this->drupalPost('admin/og/og_user_roles', $edit, 'Save configuration');
 
-    // Allow users in role 'ogur' to alter stories and post comments.
+    // Allow users in role 'ogur' to create/edit/delete stories, view revisions,
+    // and post comments.
     $edit = array(
       $this->role_ogur . '[create ' . $this->og_post_type->name . ' content]' => 1,
       $this->role_ogur . '[delete any ' . $this->og_post_type->name . ' content]' => 1,
       $this->role_ogur . '[edit any ' . $this->og_post_type->name . ' content]' => 1,
+      $this->role_ogur . '[view revisions]' => 1,
       $this->role_ogur . '[post comments]' => 1,
       $this->role_ogur . '[post comments without approval]' => 1,
     );
@@ -108,6 +116,7 @@ class OGUserRolesTestCase extends OgTest
     // Verify that user cannot edit group post belonging to second group.
     $this->drupalGet('node/' . $node2->nid);
     $this->assertNoLink('Edit');
+    $this->assertNoLink('Revisions');
 
     // Verify that user can edit group post belonging to first group.
     $this->drupalGet('node/' . $node1->nid);
@@ -116,6 +125,10 @@ class OGUserRolesTestCase extends OgTest
     $this->drupalPost(NULL, array(), 'Save');
     $t_args = array('@type' => $this->og_post_type->name, '%title' => $node1->title);
     $this->assertRaw(t('@type %title has been updated.', $t_args), 'User can update post in group.');
+
+    // Verify that user can access revisions for first group post.
+    $this->assertLink('Revisions');
+    $this->clickLink('Revisions');
   }
 
   /**
