View source
<?php
define('ROLE_WATCHDOG_SUPERUSER_RID', 999999);
define('ROLE_WATCHDOG_ROLE_ADD', 1);
define('ROLE_WATCHDOG_ROLE_REMOVE', 0);
define('ROLE_WATCHDOG_ROLE_CHANGE', 1);
define('ROLE_WATCHDOG_ROLE_NOCHANGE', 0);
function role_watchdog_help($path, $arg) {
switch ($path) {
case 'admin/help#role_watchdog':
return '<p>' . t('Role watchdog will automatically start recording all role changes. No further configuration is necessary for this functionality, the module will do this "out of the box". A record of these changes is shown in a Role history tab on each user\'s page and optionally in the Watchdog log if enabled. Users will need either "View role history" or "View own role history" access permissions to view the tab.') . '</p>' . '<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>';
}
}
function role_watchdog_perm() {
return array(
'view role history',
'view own role history',
);
}
function role_watchdog_menu() {
$items = array();
$items['admin/user/roles/role_watchdog'] = array(
'title' => 'Role watchdog',
'description' => 'Logs changes to user roles.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'role_watchdog_admin_settings',
),
'type' => MENU_NORMAL_ITEM,
'access arguments' => array(
'administer site configuration',
),
'file' => 'role_watchdog.admin.inc',
);
$items['admin/reports/role_watchdog'] = array(
'title' => 'Role grants report',
'description' => 'View changes to role assignments for users.',
'page callback' => 'role_watchdog_report',
'access arguments' => array(
'view role history',
),
'file' => 'role_watchdog.pages.inc',
);
$items['user/%user/track/role_history'] = array(
'title' => 'Track role history',
'page callback' => 'role_watchdog_history',
'page arguments' => array(
1,
),
'access callback' => '_role_watchdog_history_access',
'access arguments' => array(
1,
),
'type' => MENU_LOCAL_TASK,
'file' => 'role_watchdog.pages.inc',
'weight' => '20',
);
$items['user/%user/track/role_grants'] = array(
'title' => 'Track role grants',
'page callback' => 'role_watchdog_grants',
'page arguments' => array(
1,
),
'access callback' => '_role_watchdog_history_access',
'access arguments' => array(
1,
),
'type' => MENU_LOCAL_TASK,
'file' => 'role_watchdog.pages.inc',
'weight' => '21',
);
return $items;
}
function role_watchdog_user($type, &$edit, &$account, $category = NULL) {
switch ($type) {
case 'load':
_role_watchdog_user_roles_cache($account->uid, $account->roles);
break;
case 'insert':
if (isset($edit['roles'])) {
role_watchdog_user_save(isset($account->uid) ? $account->uid : FALSE, $edit, $account);
}
break;
case 'update':
global $user;
if (isset($edit['roles'])) {
role_watchdog_user_save(isset($account->uid) ? $account->uid : FALSE, $edit, $account);
}
if (isset($account->uid) && array_key_exists('status', $edit)) {
role_watchdog_user_block($account, $edit['status']);
}
break;
case 'delete':
db_query('DELETE FROM {role_watchdog} WHERE aid=%d', $account->uid);
db_query('UPDATE {role_watchdog} SET uid=0 WHERE uid=%d', $account->uid);
break;
}
}
function _role_watchdog_user_roles_cache($uid, $roles = FALSE) {
static $user_roles = array();
if (!isset($user_roles[$uid]) && is_array($roles)) {
$user_roles[$uid] = $roles;
}
if (!isset($user_roles[$uid])) {
return array();
}
else {
return $user_roles[$uid];
}
}
function role_watchdog_user_block($account, $status) {
if ($account->status != $status) {
if ($status) {
return _role_watchdog_process_role_changes($account, array(
DRUPAL_AUTHENTICATED_RID,
), array());
}
else {
return _role_watchdog_process_role_changes($account, array(), array(
DRUPAL_AUTHENTICATED_RID,
));
}
}
}
function role_watchdog_user_save($uid, &$form, $account) {
$old_roles = _role_watchdog_user_roles_cache($account->uid);
unset($old_roles[DRUPAL_AUTHENTICATED_RID]);
if (!empty($old_roles)) {
$old_roles = array_flip($old_roles);
}
$new_roles = $form['roles'];
unset($new_roles[DRUPAL_AUTHENTICATED_RID]);
if (!empty($new_roles)) {
$new_roles = array_flip($new_roles);
unset($new_roles[0]);
}
return _role_watchdog_process_role_changes($account, $new_roles, $old_roles);
}
function _role_watchdog_process_role_changes($account, $new_roles, $old_roles, $vars = array()) {
$result = array();
$count = 0;
foreach ($new_roles as $rid) {
$record = _role_watchdog_add_role($rid, $old_roles, $account, ROLE_WATCHDOG_ROLE_ADD, $vars);
if (is_array($record)) {
$result[] = $record;
$count = $count + 1;
}
}
foreach ($old_roles as $rid) {
$record = _role_watchdog_remove_role($rid, $new_roles, $account, FALSE, $vars);
if (is_array($record)) {
$result[] = $record;
$count = $count + 1;
}
}
if ($count) {
drupal_set_message(format_plural($count, t('Role change has been logged.'), t('Role changes have been logged.')));
}
return $result;
}
function role_watchdog_mail($key, &$message, $params) {
global $base_url;
$language = $message['language'];
$variables = array(
'!site' => variable_get('site_name', 'Drupal'),
'!uri' => $base_url,
);
$variables += $params;
$variables['!user'] .= ' (' . $variables['!uri'] . '/user/' . $params['!user_id'] . ')';
$variables['!account'] .= ' (' . $variables['!uri'] . '/user/' . $params['!account_id'] . ')';
switch ($key) {
case 'notification':
$message['subject'] = str_replace(array(
"\r",
"\n",
), '', t('Role watchdog notification on !site', $variables, $language->language));
$message['body'][] = strtr($params['body'], $variables);
break;
}
}
function _role_watchdog_add_role($rid, $old_roles = array(), $account, $action = ROLE_WATCHDOG_ROLE_ADD, $vars = array()) {
if (!in_array($rid, $old_roles)) {
global $user;
$roles = user_roles();
$record = array(
'aid' => $account->uid,
'rid' => $rid,
'action' => $action,
'uid' => $user->uid,
'stamp' => $_SERVER['REQUEST_TIME'],
);
if (drupal_write_record('role_watchdog', $record)) {
$vars += array(
'body' => 'Role !role!role_modifier added to !account by !user',
'!role' => check_plain($roles[$rid]),
'!role_modifier' => '',
'!user' => check_plain($user->name),
'!user_id' => $user->uid,
'!account' => check_plain($account->name),
'!account_id' => $account->uid,
);
watchdog('role_watchdog', $vars['body'], $vars, WATCHDOG_NOTICE, l(t('view'), 'user/' . $account->uid . '/track/role_history'));
_role_watchdog_notification($rid, $vars);
return $record;
}
else {
watchdog('role_watchdog', 'Unable to save record in _role_watchdog_add_role()', array(), WATCHDOG_ERROR, l(t('view'), 'user/' . $account->uid . '/track/role_history'));
return ROLE_WATCHDOG_ROLE_NOCHANGE;
}
}
return ROLE_WATCHDOG_ROLE_NOCHANGE;
}
function _role_watchdog_remove_role($rid, $old_roles = array(), $account, $in_array = TRUE, $vars = array()) {
if (in_array($rid, $old_roles) xor !$in_array) {
global $user;
$roles = user_roles();
$record = array(
'aid' => $account->uid,
'rid' => $rid,
'action' => 0,
'uid' => $user->uid,
'stamp' => $_SERVER['REQUEST_TIME'],
);
if (drupal_write_record('role_watchdog', $record)) {
$vars += array(
'body' => 'Role !role!role_modifier removed from !account by !user',
'!role' => check_plain($roles[$rid]),
'!role_modifier' => '',
'!user' => check_plain($user->name),
'!user_id' => $user->uid,
'!account' => check_plain($account->name),
'!account_id' => $account->uid,
);
watchdog('role_watchdog', $vars['body'], $vars, WATCHDOG_NOTICE, l(t('view'), 'user/' . $account->uid . '/track/role_history'));
_role_watchdog_notification($rid, $vars);
return $record;
}
else {
watchdog('role_watchdog', 'Unable to save record in _role_watchdog_remove_role()', array(), WATCHDOG_ERROR, l(t('view'), 'user/' . $account->uid . '/track/role_history'));
return ROLE_WATCHDOG_ROLE_NOCHANGE;
}
}
return ROLE_WATCHDOG_ROLE_NOCHANGE;
}
function _role_watchdog_notification($rid, $vars = array()) {
$monitor_roles = variable_get('role_watchdog_monitor_roles', NULL);
if (in_array($rid, (array) $monitor_roles)) {
foreach (_role_watchdog_get_notification_list() as $recipient) {
if (drupal_mail('role_watchdog', 'notification', $recipient, language_default(), $vars)) {
watchdog('role_watchdog', 'Sent notification to %recipient', array(
'%recipient' => $recipient,
), WATCHDOG_INFO);
}
else {
watchdog('role_watchdog', 'Unable to send notification to %recipient', array(
'%recipient' => $recipient,
), WATCHDOG_ERROR);
}
}
}
}
function _role_watchdog_get_notification_list() {
static $role_watchdog_notification_list;
if (!isset($role_watchdog_notification_list)) {
$role_watchdog_notification_list = array();
$notification_roles = variable_get('role_watchdog_notify_roles', array());
if (count($notification_roles)) {
$result = db_query("SELECT DISTINCT u.mail FROM {users} u INNER JOIN {users_roles} r ON u.uid = r.uid WHERE r.rid IN (%s)", implode(",", $notification_roles));
while ($account = db_fetch_object($result)) {
$role_watchdog_notification_list[] = $account->mail;
}
if (in_array(ROLE_WATCHDOG_SUPERUSER_RID, $notification_roles)) {
$result = db_result(db_query("SELECT u.mail FROM {users} u WHERE u.uid = %d", 1));
if (!in_array($result, $role_watchdog_notification_list)) {
$role_watchdog_notification_list[] = $result;
}
}
}
}
return $role_watchdog_notification_list;
}
function _role_watchdog_history_access($account) {
if (user_access('view role history')) {
return TRUE;
}
global $user;
return $user->uid == $account->uid && user_access('view own role history') ? TRUE : FALSE;
}