Skip to content
Snippets Groups Projects
Commit b40ab099 authored by Alexander Hass's avatar Alexander Hass
Browse files

#1450672: Cron task does not impersonate to admin user on automatic

content updates.
parent 31bdf2e0
No related branches found
No related tags found
No related merge requests found
linkchecker 6.x-dev, nightly
----------------------------
* #1450672: Cron task does not impersonate to admin user on automatic content updates.
* Added Drupal 6.14 warning to known issues.
* #1804842: Lots of warnings when comment module is not installed
* #1811908: Allow extracting protocol relative url's
......
......@@ -171,6 +171,16 @@ function linkchecker_admin_settings_form(&$form_state) {
'#description' => t('Defines error handling and custom actions to be executed if specific HTTP requests are failing.'),
'#collapsible' => FALSE,
);
$linkchecker_default_impersonate_user = user_load(1);
$form['error']['linkchecker_impersonate_user'] = array(
'#type' => 'textfield',
'#title' => t('Impersonate user account'),
'#description' => t('If below error handling actions are executed they can be impersonated with a custom user account. By default this is user %name, but you are able to assign a custom user to allow easier identification of these automatic revision updates. Make sure you select a user with <em>full</em> permissions on your site or the user may not able to access and save all content.', array('%name' => $linkchecker_default_impersonate_user->name)),
'#size' => 30,
'#maxlength' => 60,
'#autocomplete_path' => 'user/autocomplete',
'#default_value' => variable_get('linkchecker_impersonate_user', ''),
);
$form['error']['linkchecker_action_status_code_301'] = array(
'#title' => t('Update permanently moved links'),
'#description' => t('If enabled, outdated links in content providing a status <em>Moved Permanently</em> (status code 301) are automatically updated to the most recent URL. If used, it is recommended to use a value of <em>three</em> to make sure this is not only a temporarily change. This feature trust sites to provide a valid permanent redirect. A new node revision is automatically created on link updates if <em>create new revision</em> is enabled in the <a href="@node_types">node type</a> workflow settings. It is recommended to create new revisions for all link checker enabled node types. Link updates are nevertheless always logged in <a href="@dblog">recent log entries</a>.', array('@dblog' => url('admin/reports/dblog'), '@node_types' => url('admin/content/types'))),
......@@ -249,6 +259,12 @@ function linkchecker_admin_settings_form_validate($form, &$form_state) {
// reserved documentation domains and not "example" hostnames!
$linkchecker_disable_link_check_for_urls = array_filter(preg_split('/(\r\n?|\n)/', $form_state['values']['linkchecker_disable_link_check_for_urls']));
$form_state['values']['linkchecker_disable_link_check_for_urls'] = implode("\n", array_unique(array_merge(explode("\n", LINKCHECKER_RESERVED_DOCUMENTATION_DOMAINS), $linkchecker_disable_link_check_for_urls)));
// Validate impersonation user name.
$linkchecker_impersonate_user = user_load(array('name' => $form_state['values']['linkchecker_impersonate_user']));
if (empty($linkchecker_impersonate_user->uid)) {
form_set_error('linkchecker_impersonate_user', t('User account %name cannot found.', array('%name' => $form_state['values']['linkchecker_impersonate_user'])));
}
}
function linkchecker_admin_settings_form_submit($form, &$form_state) {
......
......@@ -19,6 +19,9 @@ define('LINKCHECKER_MINIMUM_MYSQL', '5.0');
*/
function linkchecker_install() {
drupal_install_schema('linkchecker');
$linkchecker_default_impersonate_user = user_load(1);
variable_set('linkchecker_impersonate_user', $linkchecker_default_impersonate_user->name);
}
/**
......@@ -45,6 +48,7 @@ function linkchecker_uninstall() {
variable_del('linkchecker_filter_blacklist');
variable_del('linkchecker_fqdn_only');
variable_del('linkchecker_ignore_response_codes');
variable_del('linkchecker_impersonate_user');
variable_del('linkchecker_scan_blocks');
variable_del('linkchecker_scan_comments');
variable_del('linkchecker_scan_nodetypes');
......@@ -629,3 +633,16 @@ function linkchecker_update_6216() {
return $ret;
}
/**
* #1450672: Set user 1 as default user to impersonate content updates.
*/
function linkchecker_update_6217() {
$ret = array();
$linkchecker_default_impersonate_user = user_load(1);
variable_set('linkchecker_impersonate_user', $linkchecker_default_impersonate_user->name);
$ret[] = array('success' => TRUE, 'query' => 'Set user 1 as default user to impersonate content updates.');
return $ret;
}
......@@ -424,6 +424,8 @@ function _linkchecker_status_handling($link, $response) {
// with the new one without any hand work.
$auto_repair_301 = variable_get('linkchecker_action_status_code_301', 0);
if ($auto_repair_301 && $auto_repair_301 <= ($link->fail_count+1) && valid_url($response->redirect_url, TRUE)) {
// Switch anonymous user to an admin.
linkchecker_impersonate_user(user_load(array('name' => variable_get('linkchecker_impersonate_user', ''))));
// NODES: Autorepair all nodes having this outdated link.
$res = db_query("SELECT * FROM {linkchecker_nodes} WHERE lid = %d", $link->lid);
......@@ -528,6 +530,8 @@ function _linkchecker_status_handling($link, $response) {
watchdog('linkchecker', 'Changed permanently moved link in box %bid from %src to %dst.', array('%bid' => $row->bid, '%src' => $link->url, '%dst' => $response->redirect_url), WATCHDOG_INFO);
}
// Revert user back to anonymous.
linkchecker_revert_user();
}
else {
watchdog('linkchecker', 'Link %link has changed and needs to be updated.', array('%link' => $link->url), WATCHDOG_NOTICE, l(t('Broken links'), 'admin/reports/linkchecker'));
......@@ -541,7 +545,10 @@ function _linkchecker_status_handling($link, $response) {
// If unpublishing limit is reached, unpublish all nodes having this link.
$linkchecker_action_status_code_404 = variable_get('linkchecker_action_status_code_404', 0);
if ($linkchecker_action_status_code_404 && $linkchecker_action_status_code_404 <= ($link->fail_count+1)) {
// Switch anonymous user to an admin.
linkchecker_impersonate_user(user_load(array('name' => variable_get('linkchecker_impersonate_user', ''))));
_linkchecker_unpublish_nodes($link->lid);
linkchecker_revert_user();
}
break;
......@@ -1705,3 +1712,62 @@ function _linkchecker_comment_load($cid) {
function linkchecker_link_load($lid) {
return db_fetch_array(db_query("SELECT * FROM {linkchecker_links} WHERE lid = %d", $lid));
}
/**
* Impersonates another user. http://drupal.org/node/287292#comment-3162350
*
* Each time this function is called, the active user is saved and $new_user
* becomes the active user. Multiple calls to this function can be nested,
* and session saving will be disabled until all impersonation attempts have
* been reverted using linkchecker_revert_user().
*
* @param $new_user
* User to impersonate, either a UID or a user object.
*
* @return
* Current user object.
*
* @see linkchecker_revert_user()
*/
function linkchecker_impersonate_user($new_user = NULL) {
global $user;
static $user_original;
if (!isset($new_user)) {
if (isset($user_original) && !empty($user_original)) {
// Restore the previous user from the stack.
$user = array_pop($user_original);
// Re-enable session saving if we are no longer impersonating a user.
if (empty($user_original)) {
session_save_session(TRUE);
}
}
}
else {
// Push the original user onto the stack and prevent session saving.
$user_original[] = $user;
session_save_session(FALSE);
if (is_numeric($new_user)) {
$user = user_load($new_user);
}
else {
$user = is_object($new_user) ? $new_user : (object) $new_user;
}
}
return $user;
}
/**
* Reverts to the previous user after impersonating.
*
* @return
* Current user.
*
* @see linkchecker_impersonate_user()
*/
function linkchecker_revert_user() {
return linkchecker_impersonate_user();
}
......@@ -373,3 +373,69 @@ EOT;
return db_result(db_query("SELECT COUNT(1) FROM {linkchecker_links}"));
}
}
/**
* Test case for impersonating users.
*
* Based on http://drupal.org/node/287292#comment-3162350
*/
class LinkCheckerUserImpersonatingUserTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Link checker impersonate users',
'description' => 'Temporarily impersonate another user, and then restore the original user.',
'group' => 'Link checker',
);
}
function setUp() {
parent::setUp('linkchecker');
}
function testLinkCheckerImpersonateUser() {
global $user;
$original_user = $user;
// If not currently logged in, use linkchecker_impersonate_user() to switch to
// user 1. If logged in, switch to the anonymous user instead.
if (user_is_anonymous()) {
linkchecker_impersonate_user(1);
}
else {
linkchecker_impersonate_user(0);
}
// Verify that the active user has changed, and that session saving is
// disabled.
$this->assertEqual($user->uid, ($original_user->uid == 0 ? 1 : 0), t('User switched'));
$this->assertFalse(session_save_session(), t('Session saving is disabled.'));
// Perform a second (nested) impersonation.
linkchecker_impersonate_user(1);
$this->assertEqual($user->uid, 1, t('User switched.'));
// Revert to the user which was active between the first and second
// impersonation attempt.
linkchecker_revert_user();
// Since we are still impersonating the user from the first attempt,
// session handling still needs to be disabled.
$this->assertEqual($user->uid, ($original_user->uid == 0 ? 1 : 0), t('User switched.'));
$this->assertFalse(session_save_session(), t('Session saving is disabled.'));
// Revert to the original user which was active before the first
// impersonation attempt.
linkchecker_revert_user();
// Assert that the original user is the active user again, and that session
// saving has been re-enabled.
$this->assertEqual($user->uid, $original_user->uid, t('Original user successfully restored.'));
// Simpletest uses linkchecker_impersonate_user() too, revert the impersonation by
// Simpletest to enable session saving again. This is safe because calling
// linkchecker_revert_user() too often simply results in returning the active user.
linkchecker_revert_user();
$this->assertTrue(session_save_session(), t('Session saving is enabled.'));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment