Index: user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user.module,v
retrieving revision 1.372
diff -u -r1.372 user.module
--- user.module	15 Aug 2004 14:23:28 -0000	1.372
+++ user.module	15 Aug 2004 22:36:44 -0000
@@ -676,6 +676,9 @@
   $items[] = array('path' => 'admin/user/configure/permission', 'title' => t('permissions'),
     'callback' => 'user_configure', 'access' => $access,
     'type' => MENU_LOCAL_TASK);
+  $items[] = array('path' => 'admin/user/configure/category', 'title' => t('category permissions'),
+    'callback' => 'user_configure', 'access' => $access,
+    'type' => MENU_LOCAL_TASK);
 
   if (module_exist('search')) {
     $items[] = array('path' => 'admin/user/search', 'title' => t('search'),
@@ -1399,7 +1402,7 @@
 
   // Render role/permission overview:
   $header = array_merge(array('&nbsp;'), $role_names);
-
+ 
   foreach ($perms as $perm) {
     $row[] = t($perm);
     foreach ($role_names as $rid => $name) {
@@ -1509,10 +1512,87 @@
   return theme('table', $header, $rows);
 }
 
+function user_admin_category($edit = array()) {
+  $tids = $_POST['tids'];
+  $rid = arg(4);
+  $output = '';
+  if ($edit) {
+    if (!isset($rid)) return t('Please select a role to update');
+    // Save permissions:
+    foreach ($tids as $tid)  {
+	if (isset($edit[$tid]))
+          foreach($edit[$tid] as $key => $val)  {
+            ($val == 'on') ? $edit[$tid][$key]=1 : $edit[$tid][$key]=0;
+	   }
+      taxonomy_grant_update($tid,$rid,$edit[$tid]);
+    }
+
+    // Clear the cache, as we might have changed the anonymous user's
+    // permissions.
+    cache_clear_all();
+  }
+  if (isset($rid))  {
+    // Get name of role
+    if ($rid == 0) $role_name = t('Default');
+    else $role_name = db_result(db_query('select name from {role} where rid='.$rid));
+    $output = '<h2>Permissions for \''.$role_name.'\'</h2><p>';
+    // Get all category permissions
+    $perm = taxonomy_get_grants($rid);
+    // Compile category permission overview
+    $term_list = array();
+    $header = array('Category','View','Update','Delete');
+    // Do the default row
+    $rows[] = array('Default Permissions',
+           '<input type="hidden" name="tids[]" value="0">'.
+           '<input type="checkbox" name="edit[0][view]" '. (($perm[0]['view']) ? 'checked>' : '>'),
+           '<input type="checkbox" name="edit[0][update]" '. (($perm[0]['update']) ? 'checked>' : '>'),
+           '<input type="checkbox" name="edit[0][delete]" '. (($perm[0]['delete']) ? 'checked>' : '>'));
+    $vocabs = taxonomy_get_vocabularies();
+    foreach($vocabs as $vocab)  {
+      $rows[] = array('<b>'.t($vocab->name).'</b>','&nbsp','&nbsp','&nbsp');
+      $terms = array();
+      $terms = taxonomy_get_tree($vocab->vid);
+      foreach($terms as $term)  {
+        $rows[] = array(str_repeat('-',$term->depth).$term->name,
+           '<input type="hidden" name="tids[]" value="'.$term->tid.'">'.
+	   '<input type="checkbox" name="edit['.$term->tid.'][view]" '. (($perm[$term->tid]['view']) ? 'checked>' : '>'),
+           '<input type="checkbox" name="edit['.$term->tid.'][update]" '. (($perm[$term->tid]['update']) ? 'checked>' : '>'),
+           '<input type="checkbox" name="edit['.$term->tid.'][delete]" '. (($perm[$term->tid]['delete']) ? 'checked>' : '>'));
+      }
+    }
+  } else {
+
+    // Compile role array:
+    $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name');
+    $roles = array();
+    while ($role = db_fetch_object($result)) {
+      $role_perms[$role->rid] = $role->perm;
+    }
+
+    $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
+    $role_names = array();
+    while ($role = db_fetch_object($result)) {
+      $role_names[$role->rid] = $role->name;
+    }
+
+    // Render role/permission overview:
+    $header = array("Role","Category Permissions");
+    // Default settings for categories
+    $rows[] = array(t('Default'),array('data'=>"<a href=\"admin/user/configure/category/0\">Edit</a>",'align'=>'right'));
+    foreach ($role_names as $rid => $name) {
+     $rows[] = array($name,array('data'=>"<a href=\"admin/user/configure/category/$rid\">Edit</a>", 'align'=>'right'));
+    }
+  }
+
+  $output .= theme('table', $header, $rows);
+  $output .= form_submit(t('Save category permissions'));
+
+  return form($output);
+}
+
 function user_configure() {
   $op = $_POST['op'];
   $edit = $_POST['edit'];
-
   if (empty($op)) {
     $op = arg(3);
   }
@@ -1535,6 +1615,11 @@
     case 'role':
       $output = user_admin_role($edit);
       break;
+    case t('Save category permissions'):
+      drupal_set_message(t('the user\'s category permissions have been saved.'));
+    case 'category':
+      $output = user_admin_category($edit);
+      break;
     default:
       if ($_POST) system_settings_save();
       $output = system_settings_form(user_configure_settings());
@@ -1584,6 +1669,8 @@
       return t('Setup and test the username access rules. The access function checks if you match a deny and not an allow. If you do then it is denied. Any other case, such as a deny pattern and an allow pattern, allows the pattern.');
     case 'admin/user/configure/permission':
       return t('In this area you will define the permissions for each user role (role names are defined on the <a href="%role">user roles page</a>). Each permission describes a fine-grained logical operation, such as being able to access the administration pages, or adding/modifying a user account. You could say a permission represents access granted to a user to perform a set of operations.', array('%role' => url('admin/user/configure/role')));
+    case 'admin/user/configure/category':
+      return t('In this area you will define the permissions that each <a href="%role">user role</a> has for each category.  Each category can have view, update and delete permissions set for each user role.  The "Default Permissions" are the permissions applied to all categories for this role.  The <a href="%default">Default</a> role allows you to set the default category permissions for all roles.', array('%role' => url('admin/user/configure/role'), '%default' => url('admin/user/configure/category/0')));
     case 'admin/user/configure/role':
       return t('
       Roles allow you to fine tune the security and administration of drupal.  A role defines a group of users that have certain privileges as defined in <a href="%permission">user permissions</a>.  Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the <em>role names</em> of the various roles. To delete a role choose "edit".<br />By default, Drupal comes with two user roles:
Index: taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy.module,v
retrieving revision 1.135
diff -u -r1.135 taxonomy.module
--- taxonomy.module	12 Aug 2004 22:16:01 -0000	1.135
+++ taxonomy.module	15 Aug 2004 22:36:45 -0000
@@ -270,6 +270,8 @@
   db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid);
   db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid);
   db_query('DELETE FROM {term_node} WHERE tid = %d', $tid);
+  // Delete taxonomy permissions
+  taxonomy_grant_del($tid);
 
   module_invoke_all('taxonomy', 'delete', 'term', $term);
 
@@ -1001,4 +1003,139 @@
   return $term->tid;
 }
 
+/**
+ * Implementation of hook_node_grants()
+ * Gives access to taxonomies based on the taxonomy_access table
+ */
+function taxonomy_node_grants($user, $op)  {
+
+    $sql = "SELECT tid from {term_access} where (rid=0 OR rid in ('"
+      . implode("','",array_keys($user->roles)) . "')) and grant_". $op . "=1";
+    $result = db_query($sql);
+    $nids = array();
+    $i=0;
+    while (($nid = db_result($result,$i)) != null)  {
+      $nids[] = $nid;
+      $i++;
+    }
+    return array('taxonomy'=>$nids);
+
+}
+
+/** 
+ * Inserts a permission for a role to a term
+ * @param $tid
+ *   The term to add the permission for. 
+ * @param $role 
+ *   The role to add the permission to.
+ *   Can be the name or the role id or blank for all term permissions
+ * @param $grants
+ *   A hash of the grants in the form of $grants['perm'] = boolean
+ *   A value of true will grant the permission for this user and term.
+ *   If omitted, only the permission for 'view' will be granted.
+**/
+function taxonomy_grant_add($tid,$role = null,$grants = null)  {
+  if (!isset($tid)) return false;
+  if (isset($role) && !is_numeric($role))
+    $role = db_result(db_query("SELECT rid from {role} where name='$role'"));
+  $ta_sql = "INSERT INTO {term_access} (tid";
+  $na_sql = "INSERT INTO {node_access} (nid,gid,realm,grant_view,grant_update,grant_delete)";
+  $ta_sql_values = " VALUES ($tid";
+  $na_sql_values = " VALUES (0,$tid,'taxonomy',1,1,1)"; // permissions in node_access are irrelevant
+  if (isset($role)) {
+    $ta_sql .= ",rid";
+    $ta_sql_values .= ",$role";
+  }
+  $sql = "";
+  if (isset($grants))  {
+    foreach ($grants as $perm => $value)
+    {
+      $sql .= ",grant_$perm";
+      $ta_sql_values .= ",$value";
+    }
+    $sql .= ")";
+    $ta_sql_values .= ")";
+  } else {
+    $sql .= ")";
+    $ta_sql_values .= ")";
+  }
+  $ta_sql .= $sql . $ta_sql_values;
+  $na_sql .= $na_sql_values;
+
+  db_query($ta_sql);  // insert into term_access
+  db_query($na_sql);  // insert into node_access
+
+}
+
+/**
+ * Deletes permissions for a role from a term
+ * @param $tid
+ *   The term to add the permission for.
+ * @param $role
+ *   The role to add the permission to. 
+ *   Can be the name or the role id or blank for all term permissions.
+**/
+function taxonomy_grant_del($tid,$role = null)  {
+  if (!isset($tid)) return false;
+  if (isset($role) && !is_numeric($role))
+    $role = db_result(db_query("SELECT rid from {role} where name='$role'"));
+  $ta_sql = "DELETE FROM {term_access} where tid=$tid";
+  $na_sql = "DELETE FROM {node_access} where gid=$tid and realm='taxonomy'";
+  if (isset($role))
+    $ta_sql .= " and rid=$role";
+  db_query($ta_sql);
+  db_query($na_sql);
+}
+/**
+ * Updates permissions for a role from a term
+ * @param $tid
+ *   The term to add the permission for.
+ * @param $role
+ *   The role to add the permission to.
+ *   Can be the name or the role id or blank for all term permissions.
+ * @param $grants
+ *   A hash of the grants in the form of $grants['perm'] = boolean
+ *   A value of true will grant the permission for this user and term.
+ *   If omitted, only the permission for 'view' will be granted.
+**/
+function taxonomy_grant_update($tid,$role = null, $grants = null)  {
+  if (!isset($tid)) return false;
+  if (isset($role) && !is_numeric($role))
+    $role = db_result(db_query("SELECT rid from {role} where name='$role'"));
+  taxonomy_grant_del($tid,$role);
+  if (isset($grants))
+    taxonomy_grant_add($tid,$role,$grants);
+}
+
+/**
+ * Gets permissions for a given role
+ * @param $role
+ *   The role to retrieve the permissions for.
+ *   Can be the name or the role id or blank for all term permissions.
+ * @return
+ *   A two dimensional hash of the form $grants[tid][grant] where
+ *   tid is the term id and
+ *   grant is the permission (i.e. 'view','delete',ect.)
+ *   this entry in the hash is true if permission is granted, false otherwise
+**/
+function taxonomy_get_grants($role)  {
+  if (!isset($role)) return false;
+  if (isset($role) && !is_numeric($role))
+    $role = db_result(db_query("SELECT rid from {role} where name='$role'"));
+  $result = db_query("SELECT * from {term_access} where rid='$role' OR rid=0");
+  $grants = array();
+  while ($grant = db_fetch_array($result))  {
+    $tid = $grant['tid'];
+    foreach($grant as $key => $grant_val)  {
+      if (strpos($key,'grant_') !== FALSE)  {
+        $grant_name = '';
+        $grant_name = str_replace('grant_','',$key);
+        if (!($grants[$tid][$grant_name]))  // If there's conflicting DB rules, take the most lenient
+          $grants[$tid][$grant_name] = $grant_val;
+      }
+    }
+  }
+  return $grants;
+}
+
 ?>
