From a94df968e5e7dfbf459a659439a8773ca425b243 Mon Sep 17 00:00:00 2001
From: Freek van Rijt <freek.vanrijt@oneshoe.nl>
Date: Fri, 17 Apr 2015 13:30:14 +0200
Subject: [PATCH] #1492118 Apply node grants properly for viewing unpublished
 content

---
 tests/workbench_moderation.perms.test | 82 +++++++++++++++++++++++++++++++++++
 workbench_moderation.install          |  7 +++
 workbench_moderation.module           | 27 ++++++++++++
 3 files changed, 116 insertions(+)
 create mode 100644 tests/workbench_moderation.perms.test

diff --git a/tests/workbench_moderation.perms.test b/tests/workbench_moderation.perms.test
new file mode 100644
index 0000000..fd43b25
--- /dev/null
+++ b/tests/workbench_moderation.perms.test
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * @file
+ * Permissions-related tests for workbench_moderation.module.
+ */
+
+class WorkbenchModerationPermsTestCase extends DrupalWebTestCase {
+  protected $content_type;
+  protected $editor_user;
+  protected $author_user;
+
+  function setUp($modules = array()) {
+    $modules = array_merge($modules, array('workbench_moderation'));
+    parent::setUp($modules);
+
+    // Create a new content type and enable moderation on it.
+    $type = $this->drupalCreateContentType();
+    $this->content_type = $type->name;
+    variable_set('node_options_' . $this->content_type, array('revision', 'moderation'));
+// The editor should be able to view all unpublished content, even without authoring perms.
+    $editor_permissions = array(
+      0 => 'view all unpublished content',
+    );
+    $this->editor_user = $this->drupalCreateUser($editor_permissions);
+// The Author will create the content.
+    $author_permissions = array(
+      0 => 'create ' . $type->name . ' content',
+    );
+    $this->author_user = $this->drupalCreateUser($author_permissions);
+  }
+}
+
+class WorkbenchModerationViewUnpublishedTestCase extends WorkbenchModerationPermsTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'View all unpublished content',
+      'description' => 'Create a user who can view unpublished content. Create a node and leave it unpublished. Try to view it.',
+      'group' => 'Workbench Moderation',
+    );
+  }
+
+  function setUp($modules = array()) {
+    parent::setUp($modules);
+    $this->drupalLogin($this->author_user);
+  }
+
+  function testViewUnpublished() {
+    $is_moderated = workbench_moderation_node_type_moderated($this->content_type);
+    $this->assertTrue($is_moderated, t('The content type is moderated.'));
+
+    // Create a new node and make sure it is unpublished.
+    $body_name = 'body[' . LANGUAGE_NONE . '][0]';
+    $edit = array(
+      'title' => $this->randomName(),
+      "{$body_name}[value]" => $this->randomString(128),
+      "{$body_name}[format]" => filter_default_format(),
+    );
+    $this->drupalPost("node/add/{$this->content_type}", $edit, t('Save'));
+
+    // Get the new node.
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+
+    $this->assertFalse($node->status, t('New node is unpublished'));
+    $this->assertTrue(isset($node->workbench_moderation), t('Workbench moderation information is present on the node object'));
+    $this->assertFalse(isset($node->workbench_moderation['published']), t('Workbench moderation has no published revision'));
+    $this->assertEqual($node->uid, $this->author_user->uid, 'This node was authored by the author user.');
+    $this->verbose(print_r($this->loggedInUser, TRUE));
+
+    $this->drupalLogin($this->editor_user);
+    global $user;
+    $user = user_load($this->loggedInUser->uid);
+    $this->drupalGet($node->path['source']);
+    $this->assertFalse($node->status, t('This node is unpublished.'));
+    $this->assertResponse(200);
+    $this->assertFalse($node->uid == $this->loggedInUser->uid, t('The current user is not the author of this node.'));
+    $this->assertEqual($user->uid, $this->loggedInUser->uid, 'The current global user is the same as the logged in user.');
+    $this->assertEqual($user->uid, $this->editor_user->uid, 'The current user is the editor user.');
+    $this->assertTrue(user_access('view all unpublished content'), 'Current user has permission to view all unpublished content');
+  }
+}
diff --git a/workbench_moderation.install b/workbench_moderation.install
index 8d68ed3..94c7732 100644
--- a/workbench_moderation.install
+++ b/workbench_moderation.install
@@ -670,3 +670,10 @@ function workbench_moderation_update_7010() {
   db_change_field($table, $field, $field_new, $spec);
   return t("Renamed 'current' column in node_history table");
 }
+
+/**
+ * Rebuild access records for all existing content.
+ */
+function workbench_moderation_update_7011() {
+  node_access_rebuild(TRUE);
+}
diff --git a/workbench_moderation.module b/workbench_moderation.module
index 5a2ff16..0ab4003 100644
--- a/workbench_moderation.module
+++ b/workbench_moderation.module
@@ -447,6 +447,33 @@ function workbench_moderation_node_access($node, $op, $account) {
 }
 
 /**
+ * Implements hook_node_grants().
+ */
+function workbench_moderation_node_grants($account, $op) {
+  // Pass along gid = 1 for any user with unpublished content access.
+  $grants['workbench_moderation_unpublished'] = array((int) user_access('view all unpublished content', $account));
+  return $grants;
+}
+
+/**
+ * Implements hook_node_access_records().
+ */
+function workbench_moderation_node_access_records($node) {
+  // We only implement an access record for unpublished content.
+  if (!$node->status) {
+    $grants[] = array(
+      'realm' => 'workbench_moderation_unpublished',
+      'gid' => 1,
+      'grant_view' => 1,
+      'grant_update' => 0,
+      'grant_delete' => 0,
+      'priority' => 0,
+    );
+    return $grants;
+  }
+}
+
+/**
  * Custom access handler for node operations.
  *
  * @param $op
-- 
2.2.1

