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

Contents of /contributions/modules/role_watchdog/role_watchdog.module

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


Revision 1.4 - (show annotations) (download) (as text)
Fri Apr 3 07:29:08 2009 UTC (7 months, 3 weeks ago) by gestaltware
Branch: MAIN
CVS Tags: DRUPAL-5--1-3, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.3: +43 -76 lines
File MIME type: text/x-php
- disable module config if no custom roles are setup
- added hook_user() update and delete support
- tested compatible with Role Delegation 5.x-1.2 and 6.x-1.1
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * Logs changes to user roles.
7 */
8
9 define('SUPERUSER_RID', -1);
10 define('IN_ARRAY', TRUE);
11 define('NOT_IN_ARRAY', FALSE);
12
13 /**
14 * Implementation of hook_help().
15 */
16 function role_watchdog_help($section) {
17 switch ($section) {
18 case 'admin/help#role_watchdog':
19 return
20 '<p>' . t('Role Watchdog has three modes of operation. The module will automatically start recording all role changes in the watchdog log. No further configuration is necessary for this functionality, the module will do this "out of the box".') . '</p>' .
21 '<p>' . t('Role Watchdog can optionally email members of selected Notify roles when selected Monitor roles are added or removed. This was specifically added to keep a closer eye on certain role changes, such as an Administrator role. At least one Monitor role and one Notify role must be selected for this functionality.') . '</p>' .
22 '<p>' . t('Role Watchdog can optionally log role changes in its own table and display the role history on each user\'s page. Users will need either "View role history" or "View own role history" access permissions to view the tab. This functionality was added for a more permanent audit of role history.') . '</p>';
23 }
24 }
25
26 /**
27 * Implementation of hook_perm()
28 */
29 function role_watchdog_perm() {
30 return array('view role history', 'view own role history');
31 }
32
33 /**
34 * Implementation of hook_menu().
35 */
36 function role_watchdog_menu($may_cache) {
37 $items = array();
38
39 if ($may_cache) {
40 $items[] = array(
41 'path' => 'admin/user/roles/role_watchdog',
42 'title' => 'Role watchdog',
43 'description' => t('Logs changes to user roles.'),
44 'callback' => 'drupal_get_form',
45 'callback arguments' => 'role_watchdog_admin_settings',
46 'type' => MENU_NORMAL_ITEM,
47 'access' => user_access('administer site configuration'), //do we *really* need yet another permission??
48 );
49 }
50
51 else {
52 if (arg(0) == 'user' && (int)arg(1) && variable_get('role_watchdog_history', 0)) {
53 if ($account = user_load(array('uid' => arg(1)))) {
54
55 $access = user_access('view role history');
56 if (!$access) {
57 global $user;
58 $access = ($user->uid == $account->uid && user_access('view own role history')) ? true: false;
59 }
60
61 $items[] = array(
62 'path' => 'user/' .arg(1). '/role_history',
63 'title' => t('Role History'),
64 'callback' => 'role_watchdog_history',
65 'callback arguments' => array($account),
66 'type' => MENU_LOCAL_TASK,
67 'access' => $access,
68 );
69
70 }
71 }
72 }
73 return $items;
74 }
75
76 /**
77 * Menu callback
78 *
79 * @return
80 * array of form content.
81 */
82 function role_watchdog_admin_settings() {
83 $form = array();
84
85 $role_names = array();
86 $sql = "SELECT * FROM {role} r WHERE r.rid > 2 ORDER BY name";
87 $results = db_query($sql);
88 while ($result = db_fetch_object($results)) {
89 $role_names[$result->rid] = $result->name;
90 }
91
92 if (!count($role_names)) {
93 $form['watchdog'] = array(
94 '#type' => 'fieldset',
95 '#title' => t('No roles found'),
96 '#description' => t('Role Watchdog requires custom roles to function. !add', array('!add' => l(t('Add Roles'), 'admin/user/roles'))),
97 );
98
99 return $form;
100 }
101
102 $form['watchdog'] = array(
103 '#type' => 'fieldset',
104 '#title' => t('Watchdog Logging'),
105 '#description' => t('Role Watchdog automatically logs all role changes made. No further configuration is necessary for this functionality.'),
106 );
107 $form['watchdog']['description'] = array(
108 '#type' => 'checkbox',
109 '#title' => t('Enable Watchdog Logging'),
110 '#default_value' => TRUE,
111 '#attributes' => array('disabled' => 'disabled'),
112 );
113
114 $form['email'] = array(
115 '#type' => 'fieldset',
116 '#title' => t('Email Notification'),
117 '#description' => t('Role Watchdog can monitor one or more roles for changes and notify members of selected roles via email whenever a change occurs. At least one Monitor and one Notify role must be selected for this functionality.'),
118 );
119 $form['email']['role_watchdog_monitor_roles'] = array(
120 '#type' => 'select',
121 '#title' => t('Monitor for change'),
122 '#options' => $role_names,
123 '#default_value' => variable_get('role_watchdog_monitor_roles', NULL),
124 '#description' => t('Select roles to monitor for change.'),
125 '#multiple' => TRUE,
126 );
127 $form['email']['role_watchdog_notify_roles'] = array(
128 '#type' => 'select',
129 '#title' => t('Notify on change'),
130 '#options' => array(SUPERUSER_RID => 'Superuser (uid 1)') + $role_names,
131 '#default_value' => variable_get('role_watchdog_notify_roles', NULL),
132 '#description' => t('Select roles to notify on change.'),
133 '#multiple' => TRUE,
134 );
135
136 if (db_table_exists('role_watchdog')) {
137 $form['history'] = array(
138 '#type' => 'fieldset',
139 '#title' => t('Role History'),
140 '#description' => t('Role Watchdog can log role changes in its own table and display the role history on each user\'s page. Users will need either "View role history" or "View own role history" !access to view the tab.', array('!access' => l(t('access permissions'), 'admin/user/access', NULL, NULL, 'module-role_watchdog'))),
141 );
142 $form['history']['role_watchdog_history'] = array(
143 '#type' => 'checkbox',
144 '#title' => t('Enable Role History'),
145 '#default_value' => variable_get('role_watchdog_history', 0),
146 );
147 }
148 else {
149 drupal_set_message(t('Your database schema is out of date. Please run !update.php to access the module\'s latest features.', array('!update.php' => l('update.php', 'update.php'))), 'warning');
150 }
151
152 return system_settings_form($form);
153 }
154
155 /**
156 * Implementation of hook_user().
157 *
158 * Adds submit hook to monitor role changes.
159 */
160 function role_watchdog_user($type, &$edit, &$account, $category = NULL) {
161 switch ($type) {
162 case 'update':
163 global $user;
164 if ($user->uid != $account->uid) {
165 if (isset($edit['roles'])) {
166 role_watchdog_user_save((isset($account->uid) ? $account->uid : FALSE), $edit, $account);
167 }
168 }
169 break;
170
171 case 'delete':
172 if (db_table_exists('role_watchdog')) {
173 db_query('DELETE FROM {role_watchdog} WHERE aid=%d', $account->uid);
174 db_query('UPDATE {role_watchdog} SET uid=0 WHERE uid=%d', $account->uid);
175 }
176 break;
177 }
178 }
179
180 /**
181 * Process role add/remove.
182 */
183 function role_watchdog_user_save($uid, &$form, $account) {
184 $old_roles = array_keys($account->roles);
185 $new_roles = array_keys($form['roles']);
186
187 //is role added?
188 foreach ($new_roles as $rid) {
189 $count += _role_watchdog_add_role($rid, $old_roles, $account);
190 }
191 //is role removed?
192 foreach ($old_roles as $rid) {
193 $count += _role_watchdog_remove_role($rid, $new_roles, $account, NOT_IN_ARRAY);
194 }
195 _role_watchdog_set_message($count);
196 }
197
198 /**
199 * Internal function
200 *
201 * Handles addition of roles.
202 */
203 function _role_watchdog_add_role($rid, $old_roles = array(), $account) {
204 if (!in_array($rid, $old_roles)) {
205 global $user;
206 $roles = user_roles();
207 $message = t('Role %role added to %account by %user', array('%user' => $user->name, '%role' => $roles[$rid], '%account' => $account->name));
208
209 watchdog('user', $message);
210 _role_watchdog_notification($rid, $message);
211 if (variable_get('role_watchdog_history', 0)) {
212 db_query('INSERT INTO {role_watchdog} (aid, rid, action, uid, stamp) VALUES (%d, %d, %d, %d, %d)', $account->uid, $rid, 1, $user->uid, time());
213 }
214
215 return 1;
216 }
217 return 0;
218 }
219
220 /**
221 * Internal function
222 *
223 * Handles removal of roles.
224 */
225 function _role_watchdog_remove_role($rid, $old_roles = array(), $account, $in_array = TRUE) {
226 if ($rid > 2 && (in_array($rid, $old_roles) xor !$in_array)) {
227 global $user;
228 $roles = user_roles();
229 $message = t('Role %role removed from %account by %user', array('%user' => $user->name, '%role' => $roles[$rid], '%account' => $account->name));
230
231 watchdog('user', $message);
232 _role_watchdog_notification($rid, $message);
233 if (variable_get('role_watchdog_history', 0)) {
234 db_query('INSERT INTO {role_watchdog} (aid, rid, action, uid, stamp) VALUES (%d, %d, %d, %d, %d)', $account->uid, $rid, 0, $user->uid, time());
235 }
236
237 return 1;
238 }
239 return 0;
240 }
241
242 /**
243 * Internal function
244 *
245 * Handles user message for any changes.
246 */
247 function _role_watchdog_set_message($count) {
248 if ($count) {
249 drupal_set_message(t('Role !change_has been logged.', array('!change_has' => format_plural($count, 'change has', 'changes have'))));
250 }
251 }
252
253 /**
254 * Internal function
255 *
256 * Handles notification of changes in selected roles.
257 */
258 function _role_watchdog_notification($rid, $message) {
259 $monitor_roles = variable_get('role_watchdog_monitor_roles', NULL);
260 if (in_array($rid, (array)$monitor_roles)) {
261 $site_name = variable_get('site_name', 'Drupal');
262 $from = "$site_name <" . variable_get('site_mail', ini_get('sendmail_from')) . '>';
263 $subject = t('Role Watchdog notification on !site_name', array('!site_name' => $site_name));
264 $message = strip_tags($message);
265
266 foreach (_role_watchdog_get_notification_list() as $recipient) {
267 if (drupal_mail('role_watchdog_notification', $recipient, $subject, $message, $from)) {
268 watchdog('role_watchdog', t('Sent email to %recipient', array('%recipient' => $recipient)));
269 }
270 else {
271 watchdog('error', t('Unable to send email to %recipient', array('%recipient' => $recipient)));
272 }
273 }
274 }
275 }
276
277 /**
278 * Internal function
279 *
280 * Handles building notification list
281 */
282 function _role_watchdog_get_notification_list() {
283 static $role_watchdog_notification_list;
284
285 if (!isset($role_watchdog_notification_list)) {
286 $role_watchdog_notification_list = array();
287 $notification_roles = variable_get('role_watchdog_notify_roles', NULL);
288
289 if (count($notification_roles)) {
290 $sql = "SELECT DISTINCT u.mail FROM {users} u INNER JOIN {users_roles} r ON u.uid = r.uid WHERE r.rid IN (%s)";
291 $result = db_query($sql, implode(',', $notification_roles));
292
293 while($account = db_fetch_object($result)) {
294 $role_watchdog_notification_list[] = $account->mail;
295 }
296
297 //special case: superuser
298 if (in_array(SUPERUSER_RID, (array)$notification_roles)) {
299 $sql = "SELECT u.mail FROM {users} u WHERE u.uid = %d";
300 $result = db_result(db_query($sql, 1));
301 if (!in_array($result, $role_watchdog_notification_list)) {
302 $role_watchdog_notification_list[] = $result;
303 }
304 }
305 }
306 }
307
308 return $role_watchdog_notification_list;
309 }
310
311 /**
312 * Display tab page from menu callback.
313 *
314 * @param $account
315 * User object.
316 */
317 function role_watchdog_history(&$account) {
318 if (!variable_get('role_watchdog_history', 0)) drupal_access_denied();
319 drupal_set_title($account->name);
320
321 $roles = $account->roles;
322 unset($roles[2]);
323 $output = sizeof($roles) ? '<h3>' . t('Roles') . '</h3>' . implode(", ", array_keys(array_flip($roles))) : '';
324
325 $view_profile = user_access('access user profiles');
326
327 $sql = 'SELECT rw.action, rw.uid, rw.stamp, u.name, r.name AS role FROM {role_watchdog} rw INNER JOIN {users} u USING (uid) INNER JOIN {role} r USING (rid) WHERE rw.aid=%d ORDER BY rw.stamp DESC';
328 $result = db_query($sql, $account->uid);
329 while ($row = db_fetch_object($result)) {
330 $rows[] = array(
331 format_date($row->stamp),
332 $row->role,
333 $row->action ? t('added by') : t('removed by'),
334 $view_profile ? l($row->name, 'user/' . $row->uid) : $row->name,
335 );
336 }
337
338 if (sizeof($rows)) {
339 $header = array(
340 array('data' => 'Date', 'style' => 'width: 25%;'),
341 array('data' => 'Role', 'style' => 'width: 30%;'),
342 array('data' => 'Change', 'style' => 'width: 15%;'),
343 array('data' => 'User', 'style' => 'width: 40%;')
344 );
345
346 $output .= '<h3>' . t('Role History') . '</h3>' . theme('table', $header, $rows, array('style' => 'width: 99%;'));
347 }
348
349 $sql = 'SELECT rw.action, rw.aid, rw.stamp, u.name, r.name AS role FROM {role_watchdog} rw INNER JOIN {users} u ON (rw.aid = u.uid) INNER JOIN {role} r USING (rid) WHERE rw.uid=%d ORDER BY rw.stamp DESC';
350 $result = db_query($sql, $account->uid);
351 while ($row = db_fetch_object($result)) {
352 $rows2[] = array(
353 format_date($row->stamp),
354 $row->role,
355 $row->action ? t('added to') : t('removed from'),
356 $view_profile ? l($row->name, 'user/' . $row->aid) : $row->name,
357 );
358 }
359
360 if (sizeof($rows2)) {
361 $header = array(
362 array('data' => 'Date', 'style' => 'width: 25%;'),
363 array('data' => 'Role', 'style' => 'width: 30%;'),
364 array('data' => 'Change', 'style' => 'width: 15%;'),
365 array('data' => 'User', 'style' => 'width: 40%;')
366 );
367
368 $output .= '<h3>' . t('Role Changes Made') . '</h3>' . theme('table', $header, $rows2, array('style' => 'width: 99%;'));
369 }
370
371 if (!$output) $output = t('No Role History found.');
372
373 return $output;
374 }

  ViewVC Help
Powered by ViewVC 1.1.2