Index: book_access.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/book_access/book_access.module,v retrieving revision 1.15 diff -u -r1.15 book_access.module --- book_access.module 26 Jan 2009 05:56:15 -0000 1.15 +++ book_access.module 7 Feb 2009 00:39:06 -0000 @@ -21,7 +21,7 @@ switch ($path) { case 'admin/content/book/access': return t(' -

Configure access control per book based on user roles. Settings +

Configure access control per book based on users or roles. Settings affect all pages within the given book. If a page is moved into a different book, it will assume that book\'s access control settings.

Important: If you are going to manage access control here, @@ -98,10 +98,11 @@ /** * This function supplies the book access grants. book_access simply uses - * roles as grant IDs. + * roles and user IDs as grant IDs. */ function book_access_node_grants($user, $op) { $grants['book_access'] = array_keys($user->roles); + $grants['book_access_user'] = array($user->uid); return $grants; } @@ -128,6 +129,19 @@ ); } + // Add the per-user grants. + $result = db_query("SELECT * FROM {book_access_user} WHERE nid = %d", $book_nid); + while ($grant = db_fetch_object($result)) { + $grants[] = array( + 'realm' => 'book_access_user', + 'gid' => $grant->uid, + 'grant_view' => $grant->grant_view, + 'grant_update' => $grant->grant_update, + 'grant_delete' => $grant->grant_delete, + 'priority' => BOOK_ACCESS_GRANT_PRIORITY, + ); + } + return $grants; } } @@ -241,6 +255,62 @@ '#title' => t('Delete pages in this book'), '#default_value' => $delete ); + + // Note that the autocomplete widget will only enable for users with the + // 'access profiles' permission. Other users will have to specify the name + // manually. + $form['access'][$book_nid]['search_user'] = array( + '#type' => 'textfield', + '#prefix' => '

', + '#suffix' => '
', + '#title' => t('Add a User'), + '#description' => t('Enter a user name to set permissions for that user on this book.'), + '#size' => 40, + '#autocomplete_path' => 'user/autocomplete', + ); + $form['access'][$book_nid]['user_view'] = array( + '#type' => 'checkbox', + '#title' => t('View this book'), + '#default_value' => TRUE, + ); + $form['access'][$book_nid]['user_update'] = array( + '#type' => 'checkbox', + '#title' => t('Edit pages in this book'), + ); + $form['access'][$book_nid]['user_delete'] = array( + '#type' => 'checkbox', + '#title' => t('Delete pages in this book'), + ); + + // Show a table of existing user grants. + $result = db_query("SELECT * FROM {book_access_user} where nid = %d", $book_nid); + $form['access'][$book_nid]['users'] = array(); + while ($book_access = db_fetch_object($result)) { + $user = user_load($book_access->uid); + $defaults = array(); + if ($book_access->grant_view) { + $defaults[] = 'view'; + } + if ($book_access->grant_update) { + $defaults[] = 'update'; + } + if ($book_access->grant_delete) { + $defaults[] = 'delete'; + } + $form['access'][$book_nid]['users'][$user->uid] = array( + '#type' => 'checkboxes', + '#title' => t('Permissions for %user', array('%user' => $user->name)), + '#prefix' => '
', + '#suffix' => '
', + '#options' => array( + 'view' => t('View pages in this book'), + 'update' => t('Edit pages in this book'), + 'delete' => t('Delete pages in this book'), + 'remove' => t('Reset permissions for this user to defaults'), + ), + '#default_value' => $defaults, + ); + } } $form['clearer'] = array( @@ -259,8 +329,31 @@ return $form; } -function book_access_admin_form_submit($form, &$form_state) { +/** + * Implementation of the Form API validation handler. + * + * @param $form + * The form to validate. + * @param $form_state + * The current state of the form as submitted. + */ +function book_access_admin_form_validate($form, &$form_state) { + foreach ($form_state['values']['access'] as $book_nid => $access) { + if (!empty($access['search_user']) && !user_load(array('name' => $access['search_user']))) { + form_set_error("access][$book_nid][search_user", t('%user is not a valid user name.', array('%user' => $access['search_user']))); + } + } +} +/** + * Implementation of the Form API submission handler. + * + * @param $form + * The form to validate. + * @param $form_state + * The current state of the form as submitted. + */ +function book_access_admin_form_submit($form, &$form_state) { foreach ($form_state['values']['access'] as $book_nid => $access) { db_query("DELETE FROM {book_access} WHERE nid = %d", $book_nid); @@ -276,6 +369,38 @@ db_query($sql, $book_nid, $rid, $grant_view, $grant_update, $grant_delete); } + + // If a user has been specified, update the permissions for that user. Also + // update a user if it currently has existing permissions. + if (!empty($access['search_user'])) { + $user = user_load(array('name' => $access['search_user'])); + db_query("DELETE FROM {book_access_user} WHERE nid = %d AND uid = %d", $book_nid, $user->uid); + $grant_view = ($access['user_view'] > 0); + $grant_update = ($access['user_update'] > 0); + $grant_delete = ($access['user_delete'] > 0); + $sql = " + INSERT INTO {book_access_user} (nid, uid, grant_view, grant_update, grant_delete) + VALUES (%d, %d, %d, %d, %d) + "; + db_query($sql, $book_nid, $user->uid, $grant_view, $grant_update, $grant_delete); + } + // If an existing user has been changed, update that user. + if (!empty($access['users'])) { + foreach($access['users'] as $uid => $checked) { + $user = user_load($uid); + db_query("DELETE FROM {book_access_user} WHERE nid = %d AND uid = %d", $book_nid, $user->uid); + if (!$checked['remove']) { + $grant_view = !empty($checked['view']); + $grant_update = !empty($checked['update']); + $grant_delete = !empty($checked['delete']); + $sql = " + INSERT INTO {book_access_user} (nid, uid, grant_view, grant_update, grant_delete) + VALUES (%d, %d, %d, %d, %d) + "; + db_query($sql, $book_nid, $user->uid, $grant_view, $grant_update, $grant_delete); + } + } + } } node_access_rebuild(); } @@ -331,6 +456,21 @@ $permitted_bids[$result->nid] = $result->nid; } + // Add in the per-user grants. + $sql = " + SELECT nid + FROM {node_access} + WHERE realm = 'book_access_user' + AND gid = %d + AND grant_update > 0 + "; + + $results = db_query($sql, $user->uid); + + while ($result = db_fetch_object($results)) { + $permitted_bids[$result->nid] = $result->nid; + } + if (isset($options)) { foreach ($options as $bid => $value) { // option uses current nid as the key, skip it @@ -338,7 +478,7 @@ continue; } if ($bid > 0 && !isset($permitted_bids[$bid])) { - unset($options[$nid]); + unset($options[$bid]); } } } Index: book_access.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/book_access/book_access.install,v retrieving revision 1.4 diff -u -r1.4 book_access.install --- book_access.install 5 Sep 2008 23:35:45 -0000 1.4 +++ book_access.install 7 Feb 2009 00:39:06 -0000 @@ -59,6 +59,48 @@ ), 'primary key' => array('nid', 'rid'), ); + $schema['book_access_user'] = array( + 'description' => t('Table for tracking book access by user.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary key: The node ID of the book.'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'uid' => array( + 'description' => t('Primary key: A user ID associated with a book node ID.'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'grant_view' => array( + 'description' => t('View book is allowed. 1 = TRUE, 0 = FALSE.'), + 'type' => 'int', + 'size' => 'tiny', + 'insigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'grant_update' => array( + 'description' => t('Edit book pages is allowed. 1 = TRUE, 0 = FALSE.'), + 'type' => 'int', + 'size' => 'tiny', + 'insigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'grant_delete' => array( + 'description' => t('Delete book pages is allowed. 1 = TRUE, 0 = FALSE.'), + 'type' => 'int', + 'size' => 'tiny', + 'insigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('nid', 'uid'), + ); return $schema; } @@ -69,3 +111,57 @@ function book_access_uninstall() { drupal_uninstall_schema('book_access'); } + +/** + * Add a table allowing specific users to be added to book access. + * @return + * Array of results from the update queries. + */ +function book_access_update_6001() { + $ret = array(); + $schema = array(); + $schema['book_access_user'] = array( + 'description' => t('Table for tracking book access by user.'), + 'fields' => array( + 'nid' => array( + 'description' => t('Primary key: The node ID of the book.'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'uid' => array( + 'description' => t('Primary key: A user ID associated with a book node ID.'), + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'grant_view' => array( + 'description' => t('View book is allowed. 1 = TRUE, 0 = FALSE.'), + 'type' => 'int', + 'size' => 'tiny', + 'insigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'grant_update' => array( + 'description' => t('Edit book pages is allowed. 1 = TRUE, 0 = FALSE.'), + 'type' => 'int', + 'size' => 'tiny', + 'insigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'grant_delete' => array( + 'description' => t('Delete book pages is allowed. 1 = TRUE, 0 = FALSE.'), + 'type' => 'int', + 'size' => 'tiny', + 'insigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('nid', 'uid'), + ); + db_create_table($ret, 'book_access_user', $schema['book_access_user']); + return $ret; +}