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

Contents of /contributions/modules/masquerade/masquerade.module

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


Revision 1.23 - (show annotations) (download) (as text)
Fri Mar 6 20:34:59 2009 UTC (8 months, 3 weeks ago) by deekayen
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +84 -69 lines
File MIME type: text/x-php
#392738 - increase sid column to match core sessions table length
#383500 - comma delimit quick switch users (broken autocomplete)
#390980 - revert cause it didn't work
misc sync with DRUPAL-6--1 changes
1 <?php
2 // $Id: masquerade.module,v 1.22 2009/03/04 21:03:15 deekayen Exp $
3
4 /**
5 * @file masquerade.module
6 *
7 * The masquerade module allows administrators to masquerade as other user.
8 */
9
10 /**
11 * Implementation of hook_help().
12 */
13 function masquerade_help($path, $arg) {
14 switch ($path) {
15 case 'admin/help#masquerade':
16 return t('<p>The masquerade module adds a link on a user\'s profile page that allows permitted users to masquerade as that user. Upon masquerading, the link to "switch back" to the original user will appear in the menu. While masquerading, the option to masquerade as another user will not appear. All masquerading transactions are logged, and $user->masquerading will be set; this could be displayed via theme.</p><p>In the masquerade settings a list of roles are presented; any checked role is considered an "administrator" and requires the second level "masquerade as admin" permission to masquerade as. User #1 is automatically considered an administrator, regardless of roles.</p>');
17 }
18 }
19
20 /**
21 * Implementation of hook_perm().
22 *
23 * @return array
24 */
25 function masquerade_perm() {
26 return array(
27 'masquerade as user' => array(
28 'title' => t("Masquerade as user"),
29 'description' => t('Grants permission to masquerade as a different user.')
30 ),
31 'masquerade as admin' => array(
32 'title' => t('Masquerade as administrator'),
33 'description' => t('Extra permission beyond regular user masquerading for users in selected roles.')
34 )
35 );
36 }
37
38 /**
39 * Implementation of hook_init().
40 */
41 function masquerade_init() {
42 global $user;
43
44 // load from table uid + session id
45 $query = db_select('masquerade', 'm');
46 $query->addField('m', 'uid_from');
47 $query->condition(db_and()->condition('sid', session_id(), '=')->condition('uid_as', $user->uid, '='));
48 $query->range(0, 1);
49 $result = $query->execute();
50 $uid = $result->fetchField();
51 // using if so that we get unset rather than false if not masqing
52 if ($uid) {
53 $GLOBALS['masquerading'] = $uid;
54 }
55 else {
56 $GLOBALS['masquerading'] = null;
57 }
58 }
59
60 /**
61 * Implementation of hook_cron()
62 *
63 * Cleanup masquerade records where people didn't use the switch back link
64 * that would have cleanly removed the user switch record.
65 */
66 function masquerade_cron() {
67 // see http://drupal.org/node/268487 before modifying this query
68 db_delete('masquerade')
69 ->condition('sid', db_select('sessions', 'sid'), 'NOT IN')
70 ->execute();
71 }
72
73 /**
74 * Implementation of hook_menu().
75 */
76 function masquerade_menu() {
77 $items = array();
78
79 $default_test_user = _masquerade_test_user();
80 if ($default_test_user->uid) {
81 $items['masquerade/switch/' . $default_test_user->uid] = array(
82 'title' => 'Masquerade as @testuser',
83 'title arguments' => array('@testuser' => $default_test_user->name),
84 'page callback' => 'masquerade_switch_user',
85 'page arguments' => array(2),
86 'access callback' => 'masquerade_access',
87 'access arguments' => array('switch'),
88 'type' => MENU_NORMAL_ITEM,
89 );
90 }
91
92 $items['masquerade/switch/%'] = array(
93 'title' => 'Masquerading',
94 'page callback' => 'masquerade_switch_user',
95 'page arguments' => array(2),
96 'access callback' => 'masquerade_access',
97 'access arguments' => array('switch'),
98 'type' => MENU_NORMAL_ITEM,
99 );
100 $items['masquerade/unswitch'] = array(
101 'title' => 'Switch back',
102 'page callback' => 'masquerade_switch_back',
103 'access callback' => 'masquerade_access',
104 'access arguments' => array('unswitch'),
105 'type' => MENU_NORMAL_ITEM,
106 );
107 $items['masquerade/autocomplete'] = array(
108 'title' => '',
109 'page callback' => 'masquerade_autocomplete',
110 'access callback' => 'masquerade_access',
111 'access arguments' => array('autocomplete'),
112 'type' => MENU_CALLBACK,
113 );
114 $items['masquerade/autocomplete/multiple'] = array(
115 'title' => '',
116 'page callback' => 'masquerade_autocomplete_multiple',
117 'access callback' => 'masquerade_access',
118 'access arguments' => array('autocomplete'),
119 'type' => MENU_CALLBACK,
120 );
121 $items['admin/settings/masquerade'] = array(
122 'title' => 'Masquerade',
123 'description' => 'Masquerade module allows administrators to masquerade as other users.',
124 'page callback' => 'drupal_get_form',
125 'page arguments' => array('masquerade_admin_settings'),
126 'access callback' => 'user_access',
127 'access arguments' => array('administer permissions'),
128 'type' => MENU_NORMAL_ITEM,
129 );
130
131 return $items;
132 }
133
134 function masquerade_access($type) {
135 switch ($type) {
136 case 'unswitch':
137 return $GLOBALS['masquerading'] || arg(2) == 'menu-customize' || arg(2) == 'menu';
138 case 'autocomplete':
139 return $GLOBALS['masquerading'] || (user_access('masquerade as user') || user_access('masquerade as admin'));
140 break;
141 case 'switch':
142 return empty($GLOBALS['masquerading']) && (user_access('masquerade as user') || user_access('masquerade as admin'));
143 break;
144 }
145 }
146
147 function masquerade_admin_settings() {
148 // create a list of roles; all selected roles are considered administrative.
149 $rids = array();
150 $result = db_select('role', 'r')
151 ->fields('r', array('rid', 'name'))
152 ->orderBy('name', 'ASC')
153 ->execute();
154 while ($obj = $result->fetchObject()) {
155 $rids[$obj->rid] = $obj->name;
156 }
157
158 $form['masquerade_admin_roles'] = array(
159 '#type' => 'checkboxes',
160 '#title' => t('Roles that are considered "administrators" for masquerading'),
161 '#options' => $rids,
162 '#default_value' => variable_get('masquerade_admin_roles', array()),
163 );
164
165 $test_name = _masquerade_test_user();
166
167 $form['masquerade_test_user'] = array(
168 '#type' => 'textfield',
169 '#title' => t('Menu <em>Quick Switch</em> user'),
170 '#autocomplete_path' => 'masquerade/autocomplete',
171 '#default_value' => check_plain($test_name->name),
172 '#description' => t('Enter the username of an account you wish to switch easily between via a menu item.')
173 );
174
175 $form['masquerade_quick_switches'] = array(
176 '#type' => 'textfield',
177 '#title' => t('Block <em>Quick Switch</em> users'),
178 '#autocomplete_path' => 'masquerade/autocomplete/multiple',
179 '#default_value' => variable_get('masquerade_quick_switches', ''),
180 '#description' => t('Enter the usernames, separated by commas, of accounts to show as quick switch links in the Masquerade block.')
181 );
182
183 $form['#validate'][] = 'masquerade_admin_settings_validate';
184 $form['#submit'][] = 'masquerade_admin_settings_submit';
185
186 return system_settings_form($form);
187 }
188
189 function masquerade_admin_settings_validate($form, &$form_state) {
190 unset($form);
191 $test_user = user_load(array('name' => $form_state['values']['masquerade_test_user']));
192 if (!$test_user) {
193 form_set_error('masquerade_test_user', t('%user does not exist. Please enter a valid username.', array('%user' => $form_state['values']['masquerade_test_user'])));
194 }
195
196 // A comma-separated list of users.
197 $masquerade_switches = drupal_explode_tags($form_state['values']['masquerade_quick_switches']);
198 foreach ($masquerade_switches as $switch_user) {
199 $test_user = user_load(array('name' => $switch_user));
200 if (!$test_user) {
201 form_set_error('masquerade_quick_switches', t('%user does not exist. Please enter a valid username.', array('%user' => $switch_user)));
202 }
203 }
204 }
205
206 function masquerade_admin_settings_submit($form, &$form_state) {
207 menu_rebuild();
208 }
209
210 function _masquerade_test_user() {
211 $test_user->uid = 0;
212 $test_user->name = '';
213
214 $test_user = user_load(array('name' => variable_get('masquerade_test_user', $test_user->name)));
215
216 return $test_user;
217 }
218
219 /**
220 * Implementation of hook_user_logout().
221 */
222 function masquerade_user_logout(&$edit, &$edit_user, $category = NULL) {
223 if (!empty($edit_user->masquerading)) {
224 global $user;
225 cache_clear_all($user->uid, 'cache_menu', true);
226 $real_user = user_load(array('uid' => $user->masquerading));
227 watchdog('masquerade', "User %user no longer masquerading as %masq_as.", array('%user' => $real_user->name, '%masq_as' => $user->name), WATCHDOG_INFO);
228 db_delete('masquerade')
229 ->condition(db_and()->condition('sid', session_id())->condition('uid_as', $edit_user->uid))
230 -execute();
231 }
232 }
233
234 /**
235 * Implementation of hook_user_view().
236 */
237 function masquerade_user_view(&$edit, &$edit_user, $category = NULL) {
238 // check if user qualifies as admin
239 $roles = array_keys(array_filter(variable_get('masquerade_admin_roles', array())));
240 $perm = $edit_user->uid == 1 || array_intersect(array_keys((array)$edit_user->roles), $roles) ?
241 'masquerade as admin' :
242 'masquerade as user';
243
244 global $user;
245 if (user_access($perm) && empty($edit_user->masquerading) && $user->uid != $edit_user->uid) {
246 $edit_user->content['Masquerade'] = array(
247 '#value' => l(t('Masquerade as !user', array('!user' => $edit_user->name)), 'masquerade/switch/'. $edit_user->uid, array('destination' => $_GET['q'])),
248 '#weight' => 10
249 );
250 }
251 }
252
253 /**
254 * Implementation of hook_block_list().
255 */
256 function masquerade_block_list($delta = 0, $edit = array()) {
257 $blocks[0]['info'] = t('Masquerade');
258 return $blocks;
259 }
260
261 /**
262 * Implementation of hook_block_list().
263 */
264 function masquerade_block_view($delta = 0, $edit = array()) {
265 if (masquerade_access('autocomplete')) {
266 switch ($delta) {
267 case 0:
268 $block['subject'] = t('Masquerade');
269 $block['content'] = drupal_get_form('masquerade_block_1');
270 break;
271 }
272 return $block;
273 }
274 }
275
276 /**
277 * Masquerade block form.
278 */
279 function masquerade_block_1($record) {
280 $markup_value = '';
281 if ($GLOBALS['masquerading']) {
282 global $user;
283 $quick_switch_link[] = l(t('Switch back'), 'masquerade/unswitch', array());
284 $markup_value = t('You are masquerading as:<br />%masq_as', array('%masq_as' => $user->name)) . theme('item_list', $quick_switch_link);
285 }
286 else {
287 // A comma-separated list of users.
288 $masquerade_switches = drupal_explode_tags(variable_get('masquerade_quick_switches', ''));
289 foreach ($masquerade_switches as $switch_user) {
290 if ($switch_user != $GLOBALS['user']->name) {
291 $user_name = user_load(array('name' => $switch_user));
292 if ($user_name->uid) {
293 $quick_switch_link[] = l($user_name->name, 'masquerade/switch/'. $user_name->uid);
294 }
295 }
296 }
297
298 $markup_value .= t('Enter username to masquerade as.') . '<br /><br />';
299 $form['masquerade_user_field'] = array(
300 '#prefix' => '<div class="container-inline">',
301 '#type' => 'textfield',
302 '#size' => '18',
303 '#default_value' => $GLOBALS['masquerading'] ? t('Switch back to use') : '',
304 '#autocomplete_path' => 'masquerade/autocomplete',
305 );
306 $form['submit'] = array(
307 '#type' => 'submit',
308 '#value' => t('Go'),
309 '#suffix' => '</div>',
310 );
311
312 if (isset($quick_switch_link) && count($quick_switch_link)) {
313 $markup_value .= '<div id="quick_switch_links">'. t('Quick switches:') . theme('item_list', $quick_switch_link) .'</div>';
314 }
315 }
316 $form['masquerade_desc'] = array(
317 '#prefix' => '<div class="form-item"><div class="description">',
318 '#type' => 'markup',
319 '#value' => $markup_value,
320 '#suffix' => '</div></div>',
321 );
322 return $form;
323 }
324
325 /**
326 * Masquerade block form validation.
327 */
328 function masquerade_block_1_validate($form, &$form_state) {
329 unset($form);
330 if ($form_state['values']['masquerade_user_field'] == '') {
331 form_set_error('masquerade_user_field', t('You cannot masquerade as %anonymous!', array('%anonymous' => variable_get('anonymous', 'Anonymous'))));
332 }
333 if ($GLOBALS['masquerading']) {
334 form_set_error('masquerade_user_field', t('You are already masquerading!'));
335 }
336 global $user;
337 $masq_user = user_load(array('name' => $form_state['values']['masquerade_user_field']));
338 if (!$masq_user) {
339 form_set_error('masquerade_user_field', t('User %masq_as does not exist. Please enter a valid username.', array('%masq_as' => $form_state['values']['masquerade_user_field'])));
340 }
341 if ($masq_user->uid == $user->uid) {
342 form_set_error('masquerade_user_field', t('You cannot masquerade on yourself!'));
343 }
344 if (variable_get('site_offline', 0)) {
345 form_set_error('masquerade_user_field', t('It is not possible to masquerade in off-line mode!'));
346 }
347 }
348
349 /**
350 * Masquerade block form submission.
351 */
352 function masquerade_block_1_submit($form, &$form_state) {
353 unset($form);
354 $masq_user = user_load(array('name' => $form_state['values']['masquerade_user_field']));
355 masquerade_switch_user($masq_user->uid);
356 }
357
358 /**
359 * Returns JS array for Masquerade autocomplete fields.
360 */
361 function masquerade_autocomplete($string) {
362 $matches = array();
363 $result = db_query_range("SELECT u.name FROM {users} u WHERE LOWER(u.name) LIKE LOWER(:name)", array(':name' => $string . "%"), 0, 10);
364 while ($user = $result->fetchObject()) {
365 $matches[$user->name] = check_plain($user->name);
366 }
367 exit(drupal_to_js($matches));
368 }
369
370 /**
371 * Returns JS array for Masquerade autocomplete fields. Supports multiple entries separated by a comma.
372 */
373 function masquerade_autocomplete_multiple($string) {
374 // The user enters a comma-separated list of users. We only autocomplete the last user.
375 $array = drupal_explode_tags($string);
376
377 // Fetch last tag
378 $last_string = trim(array_pop($array));
379
380 $matches = array();
381 $result = db_query_range("SELECT u.name FROM {users} u WHERE LOWER(u.name) LIKE LOWER(':name')", array(':name' => $last_string . '%'), 0, 10);
382
383 $prefix = count($array) ? implode(', ', $array) .', ' : '';
384
385 while ($user = $result->fetchObject()) {
386 $matches[$prefix . $user->name] = check_plain($user->name);
387 }
388 exit(drupal_to_js($matches));
389 }
390
391 /**
392 * Page callback that allows a user with the right permissions to become
393 * the selected user.
394 */
395 function masquerade_switch_user($uid) {
396 if (!is_numeric($uid)) {
397 drupal_set_message(t('A user id was not correctly passed to the switching function.'));
398 watchdog('masquerade', 'The user id provided to switch users was not numeric.', NULL, WATCHDOG_ERROR);
399 return drupal_goto($_SERVER['HTTP_REFERER']);
400 }
401
402 $new_user = user_load(array('uid' => $uid));
403
404 $roles = array_keys(array_filter(variable_get('masquerade_admin_roles', array())));
405 $perm = $uid == 1 || array_intersect(array_keys($new_user->roles), $roles) ?
406 'masquerade as admin' :
407 'masquerade as user';
408 // check to see if we need admin permission
409 if (!user_access($perm) && !$GLOBALS['masquerading']) {
410 return drupal_access_denied();
411 }
412
413 global $user;
414
415 if ($user->uid == $uid || isset($user->masquerading)) {
416 return drupal_access_denied();
417 }
418
419 if (variable_get('site_offline', 0) && !user_access('administer site configuration', $new_user)) {
420 drupal_set_message(t('The user is not allowed to access site in off-line mode!'), 'error');
421 return drupal_access_denied();
422 }
423
424 db_insert('masquerade')
425 ->fields(array(
426 'uid_from' => $user->uid,
427 'uid_as' => $new_user->uid,
428 'sid' => session_id()
429 ))
430 ->execute();
431 // switch user
432
433 watchdog('masquerade', 'User %user now masquerading as %masq_as.', array('%user' => $user->name, '%masq_as' => $new_user->name), WATCHDOG_INFO);
434 drupal_set_message(t('Now masquerading as %masq_as.', array('%masq_as' => $new_user->name)));
435 $user->masquerading = $new_user->uid;
436 $user = $new_user;
437 drupal_goto(referer_uri());
438 }
439
440 /**
441 * Page callback that allows a user who is currently masquerading to become
442 * a new user.
443 */
444 function masquerade_switch_back() {
445 // switch user
446 global $user;
447 cache_clear_all($user->uid, 'cache_menu', true);
448 $query = db_select('masquerade', 'm');
449 $query->addField('m', 'uid_from');
450 $query->condition(db_and()->condition('sid', session_id(), '=')->condition('uid_as', $user->uid, '='));
451 $query->range(0, 1);
452 $result = $query->execute();
453 $uid = $result->fetchField();
454 // erase record
455 db_delete('masquerade')
456 ->condition(db_and()->condition('sid', session_id())->condition('uid_as', $user->uid))
457 ->execute();
458 $oldname = $user->name;
459 $user = user_load(array('uid' => $uid));
460 watchdog('masquerade', 'User %user no longer masquerading as %masq_as.', array('%user' => $user->name, '%masq_as' => $oldname), WATCHDOG_INFO);
461 drupal_set_message(t('No longer masquerading as %masq_as.', array('%masq_as' => $oldname)));
462 drupal_goto($_SERVER['HTTP_REFERER']);
463 }

  ViewVC Help
Powered by ViewVC 1.1.2