From c5703391c8ff950313d8a274f048c7843474d862 Mon Sep 17 00:00:00 2001
From: Sascha Grossenbacher <saschagros+test@gmail.com>
Date: Thu, 17 Mar 2011 11:22:40 +0100
Subject: [PATCH] Issue #870126 by Berdir: Added separate write permission for each role.

---
 privatemsg_roles/privatemsg_roles.module |   45 ++++++++++++++++++++++++----
 privatemsg_roles/privatemsg_roles.test   |   47 +++++++++++++++++++-----------
 2 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/privatemsg_roles/privatemsg_roles.module b/privatemsg_roles/privatemsg_roles.module
index f63b65d..b2f48e4 100644
--- a/privatemsg_roles/privatemsg_roles.module
+++ b/privatemsg_roles/privatemsg_roles.module
@@ -9,9 +9,11 @@
  * Implements hook_perm().
  */
 function privatemsg_roles_perm() {
-  return array(
-    'write privatemsg to roles', 'view roles recipients',
-  );
+  $perms = array('view roles recipients', 'write privatemsg to all roles');
+  foreach (user_roles(TRUE) as $role) {
+    $perms[] = 'write privatemsg to role ' . $role;
+  }
+  return $perms;
 }
 
 function privatemsg_roles_theme() {
@@ -35,13 +37,40 @@ function privatemsg_roles_privatemsg_recipient_type_info() {
       'autocomplete' => 'privatemsg_roles_autocomplete',
       'generate recipients' => 'privatemsg_roles_load_recipients',
       'count' => 'privatemsg_roles_count_recipients',
-      'write access' => 'write privatemsg to roles',
+      'write callback' => 'privatemsg_roles_write_access',
       'view access' => 'view roles recipients',
     ),
   );
 }
 
 /**
+ * Write permission check for roles recipients.
+ */
+function privatemsg_roles_write_access($recipient) {
+
+  // Check if user has permission to write to all roles.
+  if (user_access('write privatemsg to all roles')) {
+    return TRUE;
+  }
+
+  if ($recipient) {
+    if (empty($recipient->name)) {
+      $recipient = reset(privatemsg_roles_load_multiple(array($recipient->recipient)));
+    }
+    // Check permission for this recipient.
+    return user_access('write privatemsg to role ' . $recipient->name);
+  }
+  // Check if user has permission to write at least one role.
+  foreach (user_roles(TRUE) as $role) {
+    if (user_access('write privatemsg to role ' . $role)) {
+      return TRUE;
+    }
+  }
+  // No permission, return FALSE.
+  return FALSE;
+}
+
+/**
  * Load a number of roles based on their rid.
  */
 function privatemsg_roles_load_multiple($rids) {
@@ -110,9 +139,11 @@ function privatemsg_roles_autocomplete($fragment, $names, $limit) {
   // 3: Build proper suggestions and print.
   $roles = array();
   while ($role = db_fetch_object($result)) {
-    $role->type = 'role';
-    $role->recipient = $role->rid;
-    $roles[privatemsg_recipient_key($role)] = $role;
+    if (user_access('write privatemsg to all roles') || user_access('write privatemsg to role ' . $role->name)) {
+      $role->type = 'role';
+      $role->recipient = $role->rid;
+      $roles[privatemsg_recipient_key($role)] = $role;
+    }
   }
   return $roles;
 }
diff --git a/privatemsg_roles/privatemsg_roles.test b/privatemsg_roles/privatemsg_roles.test
index 7c3ccaf..da34a1f 100644
--- a/privatemsg_roles/privatemsg_roles.test
+++ b/privatemsg_roles/privatemsg_roles.test
@@ -22,7 +22,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
   }
 
   function testSendMessagetoRoleAPI() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
     $user2 = $this->drupalCreateUser();
 
@@ -42,7 +42,6 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
   }
 
   function testSendMessagetoRoleCron() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     variable_set('privatemsg_recipient_small_threshold', 20);
@@ -57,7 +56,13 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
       user_save($users[$i], $edit);
     }
 
-    $recipient = (object)array('recipient' => 4, 'type' => 'role', 'name' => $user1->roles[4]);
+    // Update permissions.
+    $this->checkPermissions(array(), TRUE);
+
+    // Create user with specific role permission.
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to role ' . $user1->roles[3]));
+
+    $recipient = (object)array('recipient' => 3, 'type' => 'role', 'name' => $user1->roles[3]);
     privatemsg_new_thread(array($recipient), $subject = $this->randomName(10), $body = $this->randomName(50), array('author' => $admin));
 
     // Run cron.
@@ -96,7 +101,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
    * Disabled as it produces exceptions on some testslaves.
    */
   function disabledSendMessagetoRoleBatch() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     variable_set('privatemsg_recipient_small_threshold', 20);
@@ -132,12 +137,16 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
 
   function testPermission() {
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
-    $user2 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
-    $this->drupalLogin($user1);
+    // Update permissions.
+    $this->checkPermissions(array(), TRUE);
+    // Give permission to write only a specific role.
+    $user2 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to role ' . $user1->roles[3]));
+
+    $this->drupalLogin($user2);
 
     // Send a message to the role of user 1 and 2.
     $edit = array(
-      'recipient' => $user2->roles[4] . '[role]',
+      'recipient' => $user1->roles[DRUPAL_AUTHENTICATED_RID] . '[role]',
       'subject' => $this->randomName(10),
       'body' => $this->randomName(50),
     );
@@ -146,22 +155,26 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
   }
 
   function testSendMessageToRole() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
     $user2 = $this->drupalCreateUser(array('view roles recipients'));
 
     // Add role of user 1 to user 2;
     $edit = array('roles' => $user2->roles + $user1->roles);
     user_save($user2, $edit);
+
+    // Update permissions.
+    $this->checkPermissions(array(), TRUE);
+
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'view roles recipients', 'write privatemsg to role ' . $user1->roles[3]));
     $this->drupalLogin($admin);
 
     // Verify autocomplete feature.
-    $json = $this->drupalGet('messages/autocomplete/' . drupal_substr($user1->roles[4], 0, 2));
+    $json = $this->drupalGet('messages/autocomplete/' . drupal_substr($user1->roles[3], 0, 2));
     $autocomplete = (array)json_decode($json);
-    $this->assertEqual($autocomplete[$user1->roles[4] . ', '], $user1->roles[4]);
+    $this->assertEqual($autocomplete[$user1->roles[3] . ', '], $user1->roles[3]);
 
     // Access the form through a url that pre-fills the recipient field.
-    $this->drupalGet('messages/new/role_4');
+    $this->drupalGet('messages/new/role_3');
 
     // Send a message to the role of user 1 and 2.
     $edit = array(
@@ -169,7 +182,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
       'body' => $this->randomName(50),
     );
     $this->drupalPost(NULL, $edit, t('Send message'));
-    $this->assertText(t('A message has been sent to @role (role).', array('@role' => $user1->roles[4])));
+    $this->assertText(t('A message has been sent to @role (role).', array('@role' => $user1->roles[3])));
 
     // Log in as user1 and check that the message is listed, is marked as new
     // and can be marked as read.
@@ -181,7 +194,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
     $this->assertText($edit['body'], t('Thread starter body displayed.'));
 
     // Make sure that the user does not see the role.
-    $this->assertNoText(t('@role (role)', array('@role' => $user1->roles[4])));
+    $this->assertNoText(t('@role (role)', array('@role' => $user1->roles[3])));
 
     // Reply to the message, only admin should see this.
     $reply1 = array(
@@ -211,7 +224,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
     $this->drupalGet('messages');
     $this->assertRaw($edit['subject'] . '</a> <span class="marker">new</span>', t('Message is displayed as new'));
     $this->clickLink($edit['subject']);
-    $this->assertText(t('@role (role)', array('@role' => $user1->roles[4])));
+    $this->assertText(t('@role (role)', array('@role' => $user1->roles[3])));
 
     $this->assertText($edit['body'], t('Thread starter body is displayed'));
     $this->assertNoText($reply1['body'], t('Reply1 is not displayed'));
@@ -219,7 +232,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
   }
 
   function testSendMessageToRoleBlocked() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
     $user2 = $this->drupalCreateUser();
 
@@ -262,7 +275,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
   }
 
   function testNewUser() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     // Send a message to the role of user 1.
@@ -291,7 +304,7 @@ class PrivatemsgRolesTestCase extends DrupalWebTestCase {
    * Verify that deleting a user does not leave stale data behind.
    */
   function testDeleteUser() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     // Send a message to the role of user 1.
-- 
1.7.4.1

