/[drupal]/contributions/modules/roleassign/roleassign.module
ViewVC logotype

Contents of /contributions/modules/roleassign/roleassign.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.19 - (show annotations) (download) (as text)
Fri Oct 3 18:01:58 2008 UTC (13 months, 3 weeks ago) by tbarregren
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-BETA1, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.18: +3 -9 lines
File MIME type: text/x-php
#233463: Removed copyright and GPL notices in help text.
1 <?php
2
3 // $Id: roleassign.module,v 1.18 2008/10/03 17:59:06 tbarregren Exp $
4
5 /**
6 * @file
7 * Allows site administrators to further delegate the task of managing user's
8 * roles.
9 */
10
11
12 /*
13 * PHP4 implementation of the PHP5 function array_intersect_key().
14 * See http://php.net/manual/function.array-intersect-key.php#68179.
15 * Thanks pjb <http://drupal.org/user/77935> for point it out.
16 */
17 if (!function_exists('array_intersect_key'))
18 {
19 function array_intersect_key()
20 {
21 $arrs = func_get_args();
22 $result = array_shift($arrs);
23 foreach ($arrs as $array)
24 foreach ($result as $key => $v)
25 if (!array_key_exists($key, $array))
26 unset($result[$key]);
27 return $result;
28 }
29 }
30
31 /**
32 * Implementation of hook_help().
33 *
34 * Returns various help texts.
35 */
36 function roleassign_help($section="admin/help#roleassign")
37 {
38 switch ($section)
39 {
40 case 'admin/user/roleassign':
41 return _roleassign_settings_help();
42 case 'admin/help#roleassign':
43 return _roleassign_help_help();
44 }
45 }
46
47 /**
48 * Implementation of hook_perm().
49 *
50 * While editing a user's account information, a user with <code>assign
51 * roles</code> permission will be able to select roles for the user from
52 * a set of available roles. Roles available are configured by the site
53 * administrator.
54 */
55 function roleassign_perm()
56 {
57 return array('assign roles');
58 }
59
60 /**
61 * Implementation of hook_menu().
62 *
63 * Adds <code>role assign</code> to <code>administer » user management</code>.
64 */
65 function roleassign_menu($may_cache)
66 {
67 $items = array();
68 if ($may_cache)
69 {
70 $items[] = array('path' => 'admin/user/roleassign',
71 'title' => t('Role assign'),
72 'callback' => 'drupal_get_form',
73 'callback arguments' => array('roleassign_admin'),
74 'description' => t('Allows site administrators to further delegate the task of managing user\'s roles.'),
75 'access' => user_access('administer access control'));
76 }
77 return $items;
78 }
79
80 /**
81 * Returns a system settings form for the administrator to select which roles
82 * will be avaiable to assign for users with the <code>assign roles</code>
83 * permission.
84 */
85 function roleassign_admin()
86 {
87
88 // To admister roleassign, 'administer access control' permission
89 // is required.
90 if (!user_access('administer access control'))
91 return;
92
93 // Get all avaiable roles except for 'anonymous user'
94 // and 'authenticated user'.
95 $roles = user_roles(true);
96 unset($roles[DRUPAL_AUTHENTICATED_RID]);
97
98 // Show checkboxes with roles that can be delegated if any.
99 if ($roles)
100 $form['roleassign_roles'] = array
101 (
102 '#type' => 'checkboxes',
103 '#title' => t('Roles'),
104 '#options' => $roles,
105 '#default_value' => variable_get('roleassign_roles', array()),
106 '#description' => t('Select roles that should be available for assignment.')
107 );
108 else
109 $form['roleassign_roles'] = array
110 (
111 '#type' => 'markup',
112 '#value' => '<p>No assignable roles avaiable. You have to ' . l(t('create roles'), 'admin/user/roles') . ' that can be assigned.</p>'
113 );
114
115 // Return system settings form.
116 return system_settings_form($form);
117
118 }
119
120 /**
121 * Implementation of hook_form_alter().
122 *
123 * Adds checkboxes for assignable roles to the user edit form.
124 */
125 function roleassign_form_alter($form_id, &$form)
126 {
127
128 // Do nothing if the user already has 'administer access control'
129 // permission.
130 if (user_access('administer access control'))
131 return;
132
133 // Do nothing if the user hasn't both 'administer users' and
134 // 'assign roles' permissions.
135 if (!user_access('administer users') || !user_access('assign roles'))
136 return;
137
138 // Do nothing if right form isn't shown.
139 if ($form_id != 'user_register' && ($form_id != 'user_edit' || !isset($form['account'])))
140 return;
141
142 // Get all roles that are available.
143 $roles = user_roles(true);
144
145 // Get roles that are available for assignment.
146 $assignable_roles = _roleassign_assignable_roles($roles);
147
148 // Get roles already assigned to the user.
149 // The use of the superfluous $user variable is required by PHP4.
150 $user = user_load(array('uid' => arg(1)));
151 $assigned_roles = $user->roles;
152
153 // A user might already have a role that isn't avaiable for
154 // assignment through this module. A such role is called "sticky".
155 // Get sticky roles.
156 $sticky_roles = array_diff($assigned_roles, $assignable_roles);
157 $sticky_roles = array_intersect_key($roles, $sticky_roles);
158
159 // Store sticky roles for later use in roleassign_user().
160 _roleassign_sticky_roles($sticky_roles);
161
162 // Make a string of all sticky roles.
163 $sticky_roles[DRUPAL_AUTHENTICATED_RID] = $roles[DRUPAL_AUTHENTICATED_RID];
164 foreach ($sticky_roles as $role)
165 $sticky_roles_str .= $role.', ';
166 $sticky_roles_str = substr($sticky_roles_str, 0, strlen($sticky_roles_str) - 2);
167
168 // Build the assign roles checkboxes.
169 $roles_field = array
170 (
171 '#type' => 'checkboxes',
172 '#title' => t('Assignable roles'),
173 '#options' => $assignable_roles,
174 '#default_value' => array_keys($assigned_roles),
175 '#description' => t('The user receives the combined permissions of all roles selected here and following roles: %roles.', array('%roles' => $sticky_roles_str)),
176 );
177
178 // The user form is sometimes within an 'account' fieldset.
179 if (isset($form['account']))
180 $user_form =& $form['account'];
181 else
182 $user_form =& $form;
183
184 // Add the assign roles checkboxes to the user form, and make sure
185 // that the notify user checkbox comes last.
186 $notify_field = $user_form['notify'];
187 unset($user_form['notify']);
188 $user_form['roleassign_roles'] = $roles_field;
189 $user_form['notify'] = $notify_field;
190
191 }
192
193 /**
194 * Implementation of hook_user().
195 *
196 * Replace the validation of the user form field 'roles' by using
197 * another user form field 'roleassign_roles'. Copies the form field
198 * roleassign_roles into form field roles on insert or submit.
199 */
200 function roleassign_user($type, &$edit, &$user, $category = NULL)
201 {
202
203 // If this isn't the account category, or there is no roleassign_roles
204 // field, there isn't much to do.
205 if ($category != 'account' || !isset($edit['roleassign_roles']))
206 return;
207
208 // If someone is trying to update user's roles, it's a malicious
209 // attempt to alter user's roles.
210 if ($type == 'validate' && !user_access('assign roles'))
211 {
212 $message = t('Detected malicious attempt to alter user\'s roles.');
213 watchdog('security', $message, WATCHDOG_WARNING);
214 form_set_error('category', $message);
215 }
216
217 // On submit, copy sticky and assigned roles from 'roleassign_roles'
218 // to 'roles'.
219 if ($type == 'insert' || $type == 'submit')
220 $edit['roles'] = array_filter(_roleassign_sticky_roles() + $edit['roleassign_roles']);
221
222 }
223
224 /**
225 * Implementation of hook_user_operations().
226 *
227 * Add or remove roles to selected users.
228 * Thanks hunmonk <http://drupal.org/user/22079> for the original code.
229 */
230 function roleassign_user_operations()
231 {
232
233 global $form_values;
234
235 // Do nothing if add and remove roles operations already is shown or
236 // the user hasn't right to assign roles.
237 if (user_access('administer access control') || !user_access('assign roles'))
238 return;
239
240 // Get roles that are available for assignment.
241 $assignable_roles = _roleassign_assignable_roles(user_roles(true));
242
243 // Build an array of available operations.
244 if (count($assignable_roles))
245 {
246 foreach ($assignable_roles as $key => $value)
247 {
248 $add_roles['roleassign_add_role-'. $key] = $value;
249 $remove_roles['roleassign_remove_role-'. $key] = $value;
250 }
251 $operations = array
252 (
253 t('Add a role to the selected users') => array('label' => $add_roles),
254 t('Remove a role from the selected users') => array('label' => $remove_roles)
255 );
256 }
257 else
258 $operations = array();
259
260 // The required 'callback' key and optional 'callback arguments' key are
261 // actually only needed when someone has posted. We therefore postpone
262 // the attachement of these until $form_values is set.
263 if ($form_values)
264 {
265
266 // Get operation and role id.
267 $op = explode('-', $form_values['operation']);
268 $rid = $op[1];
269 $op = $op[0];
270
271 // If not a RoleAssign operation, there is not much to do.
272 if ($op != 'roleassign_add_role' && $op != 'roleassign_remove_role')
273 return;
274
275 // If someone is trying to update user's roles, it's a malicious
276 // attempt to alter user's roles.
277 if (!user_access('assign roles'))
278 {
279 $message = t('Detected malicious attempt to alter user\'s roles.');
280 watchdog('security', $message, WATCHDOG_WARNING);
281 form_set_error('category', $message);
282 }
283
284 // Form the name of the core callback functions for adding and
285 // removing roles by choping off the 'roleassign_' part of the
286 // operation string.
287 $operations[$form_values['operation']] = array
288 (
289 'callback' => 'user_multiple_role_edit',
290 'callback arguments' => array(substr($op, 11), $rid)
291 );
292
293 }
294
295 return $operations;
296
297 }
298
299 /**
300 * Returns assignable roles.
301 */
302 function _roleassign_assignable_roles($roles)
303 {
304 return array_intersect_key($roles, array_filter(variable_get('roleassign_roles', array())));
305 }
306
307 /**
308 * Store and retrive sticky roles.
309 */
310 function _roleassign_sticky_roles($new_sticky_roles = null)
311 {
312 static $sticky_roles;
313 if (isset($new_sticky_roles))
314 $sticky_roles = $new_sticky_roles;
315 return $sticky_roles;
316 }
317
318 /**
319 * Returns short helptext to be used on the settings page.
320 */
321 function _roleassign_settings_help()
322 {
323 return t
324 (
325 '<p>Users with both <code>administer users</code> and <code>assign roles</code> permissions are allowed to assign the roles selected below. For more information, see the !help.</p>',
326 array('!help' => l(t('help page'), 'admin/help/roleassign'))
327 );
328 }
329
330 /**
331 * Returns full help text.
332 */
333 function _roleassign_help_help()
334 {
335 $version = str_replace(array('$Re'.'vision:', ' $'), array('', ''), '$Revision: 1.18 $');
336 $year = substr('$Date: 2008/10/03 17:59:06 $', 7, 4);
337 return
338 '
339 <style type="text/css" media="all">
340 code,
341 kbd
342 {
343 padding: 1px;
344 font-family: "Bitstream Vera Sans Mono", Monaco, "Lucida Console", monospace;
345 background-color: #EDF1F3;
346 }
347 </style>
348 ' . t
349 (
350 '<p>RoleAssign specifically allows site administrators to further delegate the task of managing user\'s roles.</p>
351 <p>RoleAssign introduces a new permission called <code>assign roles</code>. Users with this permission are able to assign selected roles to still other users. Only users with the <code>administer access control</code> permission may select which roles are available for assignment through this module.</p>
352 <p>This module is sponsored by <a href="http://www.webbredaktoren.se/">Webbredaktören</a>.</p>
353 <!--break-->
354 <h2>Background</h2>
355 <p>It is possible for site administrators to delegate the user administration through the <code>administer users</code> permission. But that doesn\'t include the right to assign roles to users. That is necessary if the delegatee should be able to administrate user accounts without intervention from a site administrator.</p>
356 <p>To delegate the assignment of roles, site administrators have had until now no other choice than also grant the <code>administer access control</code> permission. But that is not advisable, since it gives right to access all roles, and worse, to grant any rights to any role. That can be abused by the delegatee, who can assign himself all rights and thereby take control over the site.</p>
357 <p>This module solves this dilemma by introducing the <code>assign roles</code> permission. While editing a user\'s account information, a user with this permission will be able to select roles for the user from a set of available roles. Roles available are configured by users with the <code>administer access control</code> permission.</p>
358 <h2>Install</h2>
359 <ol>
360 <li>Copy the entire <kbd>roleassign</kbd> directory, containing the <kbd>roleassign.module</kbd> and other files, to your Drupal modules directory.</li>
361 <li>Log in as site administrator.</li>
362 <li>Go to the administration page for modules and enable the module.</li>
363 </ol>
364 <h2>Configuration</h2>
365 <ol>
366 <li>Log in as site administrator.</li>
367 <li>Go to the administration page for access control and grant <code>assign roles</code> permission to those roles that should be able to assign roles to other users. Notice that besides the <code>assign roles</code> permission, these roles also must have the <code>administer users</code> permission.</li>
368 <li>Go to the administration page for role assign and select those roles that should be available for assignment by users with <code>assign roles</code> permission.</li>
369 <li>For each user that should be able to assign roles, go to the user\'s account and select a role with both the <code>assign roles</code> and the <code>administer users</code> permissions.</li>
370 </ol>
371 <h2>Usage</h2>
372 <ol>
373 <li>Log in as a user with both the <code>assign roles</code> and the <code>administer users</code> permissions.</li>
374 <li>To change the roles of a user, go to the user\'s account and review the assignable roles and change them as necessary.</li>
375 </ol>
376 ',
377 array('!version' => $version, '!year' => $year)
378 );
379 }

  ViewVC Help
Powered by ViewVC 1.1.2