MDL-42891 administration: Replace use of logtable in notify_login_failures() with new logging apis

This commit is contained in:
Ankit Agarwal
2014-04-01 17:35:01 +08:00
parent 52dc1de746
commit 53b9e63b80
2 changed files with 56 additions and 35 deletions
+1 -1
View File
@@ -1323,7 +1323,7 @@ $string['notice'] = 'Notice';
$string['noticenewerbackup'] = 'This backup file has been created with Moodle {$a->backuprelease} ({$a->backupversion}) and it\'s newer than your currently installed Moodle {$a->serverrelease} ({$a->serverversion}). This could cause some inconsistencies because backwards compatibility of backup files cannot be guaranteed.';
$string['notifications'] = 'Notifications';
$string['notifyloginfailuresmessage'] = '{$a->time}, IP: {$a->ip}, User: {$a->info}';
$string['notifyloginfailuresmessageend'] = 'You can view these logs at {$a}/report/log/index.php?id=1&chooselog=1&modid=site_errors.';
$string['notifyloginfailuresmessageend'] = 'You can view these logs at {$a}';
$string['notifyloginfailuresmessagestart'] = 'Here is a list of failed login attempts at {$a} since you were last notified';
$string['notifyloginfailuressubject'] = '{$a} :: Failed logins notification';
$string['notincluded'] = 'Not included';
@@ -42,7 +42,7 @@ class send_failed_login_notifications_task extends scheduled_task {
* Throw exceptions on errors (the job will be retried).
*/
public function execute() {
global $CFG, $DB, $OUTPUT;
global $CFG, $DB;
if (empty($CFG->notifyloginfailures)) {
return;
@@ -66,13 +66,23 @@ class send_failed_login_notifications_task extends scheduled_task {
// Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure
// and insert them into the cache_flags temp table.
$logmang = get_log_manager();
$readers = $logmang->get_readers('\core\log\sql_internal_reader');
$reader = reset($readers);
$readername = key($readers);
if (empty($reader) || empty($readername)) {
// No readers, no processing.
return true;
}
$logtable = $reader->get_internal_log_table_name();
$sql = "SELECT ip, COUNT(*)
FROM {log}
WHERE module = 'login' AND action = 'error'
AND time > ?
GROUP BY ip
HAVING COUNT(*) >= ?";
$params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
FROM {" . $logtable . "}
WHERE eventname = ?
AND timecreated > ?
GROUP BY ip
HAVING COUNT(*) >= ?";
$params = array('\core\event\user_login_failed', $CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $iprec) {
if (!empty($iprec->ip)) {
@@ -83,17 +93,17 @@ class send_failed_login_notifications_task extends scheduled_task {
// Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure
// and insert them into the cache_flags temp table.
$sql = "SELECT info, count(*)
FROM {log}
WHERE module = 'login' AND action = 'error'
AND time > ?
GROUP BY info
$sql = "SELECT userid, count(*)
FROM {" . $logtable . "}
WHERE eventname = ?
AND timecreated > ?
GROUP BY userid
HAVING count(*) >= ?";
$params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
$params = array('\core\event\user_login_failed', $CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $inforec) {
if (!empty($inforec->info)) {
set_cache_flag('login_failure_by_info', $inforec->info, '1', 0);
set_cache_flag('login_failure_by_id', $inforec->userid, '1', 0);
}
}
$rs->close();
@@ -101,23 +111,23 @@ class send_failed_login_notifications_task extends scheduled_task {
// Now, select all the login error logged records belonging to the ips and infos
// since lastnotifyfailure, that we have stored in the cache_flags table.
$sql = "SELECT * FROM (
SELECT l.*, u.firstname, u.lastname
FROM {log} l
JOIN {cache_flags} cf ON l.ip = cf.name
LEFT JOIN {user} u ON l.userid = u.id
WHERE l.module = 'login' AND l.action = 'error'
AND l.time > ?
AND cf.flagtype = 'login_failure_by_ip'
UNION ALL
SELECT l.*, u.firstname, u.lastname
FROM {log} l
JOIN {cache_flags} cf ON l.info = cf.name
LEFT JOIN {user} u ON l.userid = u.id
WHERE l.module = 'login' AND l.action = 'error'
AND l.time > ?
AND cf.flagtype = 'login_failure_by_info') t
ORDER BY t.time DESC";
$params = array($CFG->lastnotifyfailure, $CFG->lastnotifyfailure);
SELECT l.*, u.username
FROM {" . $logtable . "} l
JOIN {cache_flags} cf ON l.ip = cf.name
LEFT JOIN {user} u ON l.userid = u.id
WHERE l.eventname = ?
AND l.timecreated > ?
AND cf.flagtype = 'login_failure_by_ip'
UNION ALL
SELECT l.*, u.username
FROM {" . $logtable . "} l
JOIN {cache_flags} cf ON l.userid = " . $DB->sql_cast_char2int('cf.name') . "
LEFT JOIN {user} u ON l.userid = u.id
WHERE l.eventname = ?
AND l.timecreated > ?
AND cf.flagtype = 'login_failure_by_info') t
ORDER BY t.timecreated DESC";
$params = array('\core\event\user_login_failed', $CFG->lastnotifyfailure, '\core\event\user_login_failed', $CFG->lastnotifyfailure);
// Init some variables.
$count = 0;
@@ -125,8 +135,17 @@ class send_failed_login_notifications_task extends scheduled_task {
// Iterate over the logs recordset.
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $log) {
$log->time = userdate($log->time);
$messages .= get_string('notifyloginfailuresmessage', '', $log) . "\n";
$a = new \stdClass();
$a->time = userdate($log->timecreated);
if (empty($log->username)) {
// Entries with no valid username. We get attempted username from the event's other field.
$other = unserialize($log->other);
$a->info = empty($other['username']) ? '' : $other['username'];
} else {
$a->info = $log->username;
}
$a->ip = $log->ip;
$messages .= get_string('notifyloginfailuresmessage', '', $a)."\n";
$count++;
}
$rs->close();
@@ -136,10 +155,12 @@ class send_failed_login_notifications_task extends scheduled_task {
$site = get_site();
$subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
// Calculate the complete body of notification (start + messages + end).
$params = array('id' => 0, 'modid' => 'site_errors', 'chooselog' => '1', 'logreader' => $readername);
$url = new \moodle_url('/report/log/index.php', $params);
$body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) .
(($CFG->lastnotifyfailure != 0) ? '('.userdate($CFG->lastnotifyfailure).')' : '')."\n\n" .
$messages .
"\n\n" . get_string('notifyloginfailuresmessageend', '', $CFG->wwwroot) . "\n\n";
"\n\n".get_string('notifyloginfailuresmessageend', '', $url->out(false).' ')."\n\n";
// For each destination, send mail.
mtrace('Emailing admins about '. $count .' failed login attempts');