Commit 81f26254 authored by Richard Mansfield's avatar Richard Mansfield

Expire users when they've been inactive for too long (bug #890929)

The "Default account inactivity time" setting allows the admin to
specify a time period after which users who have not used the site
will be unable to login, but this is not currently enforced.

This change modifies the inactivity cron job to set the expiry date to
the current date for any user who has been inactive for longer than
the 'defaultaccountinactiveexpire' period.  It also now considers the
lastaccess and ctime fields as well as the lastlogin field.

This allows the admin to reactivate inactive users by resetting their
expiry dates in account settings.

The active column on the user table is currently only used to decide
whether users should be displayed in search results, and users are set
to inactive whenever they are deleted, suspended, or expire.

Change-Id: Ieaf7a0b36865af726fc2526895146373efbb2741
Signed-off-by: default avatarRichard Mansfield <richard.mansfield@catalyst.net.nz>
parent abda43b5
......@@ -302,8 +302,16 @@ function edituser_site_submit(Pieform $form, $values) {
if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
$user->quota = $values['quota'];
}
$user->expiry = db_format_timestamp($values['expiry']);
$unexpire = $user->expiry && strtotime($user->expiry) < time() && (empty($values['expiry']) || $values['expiry'] > time());
$newexpiry = db_format_timestamp($values['expiry']);
if ($user->expiry != $newexpiry) {
$user->expiry = $newexpiry;
if ($unexpire) {
$user->expirymailsent = 0;
$user->lastaccess = db_format_timestamp(time());
}
}
// Try to kick the user from any active login sessions, before saving data.
require_once(get_config('docroot') . 'auth/session.php');
......
......@@ -1478,10 +1478,21 @@ function auth_handle_account_expiries() {
if ($expire) {
// Inactivity (lastlogin is too old)
if ($users = get_records_sql_array('SELECT u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.admin, u.staff
// MySQL doesn't want to compare intervals, so when editing the where clauses below, make sure
// the intervals are always added to datetimes first.
$dbexpire = db_interval($expire);
$dbwarn = db_interval($warn);
$installationtime = get_config('installation_time');
$lastactive = "COALESCE(u.lastaccess, u.lastlogin, u.ctime, ?)";
if ($users = get_records_sql_array("
SELECT u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.admin, u.staff
FROM {usr} u
WHERE (? - ' . db_format_tsfield('u.lastlogin', false) . ') > ' . ($expire - $warn) . '
AND inactivemailsent = 0 AND deleted = 0', array(time()))) {
WHERE $lastactive + $dbexpire < current_timestamp + $dbwarn
AND (u.expiry IS NULL OR u.expiry > current_timestamp)
AND inactivemailsent = 0 AND deleted = 0", array($installationtime))) {
foreach ($users as $user) {
$displayname = display_name($user);
_email_or_notify($user, get_string('accountinactivewarning'),
......@@ -1493,9 +1504,11 @@ function auth_handle_account_expiries() {
}
// Actual inactive users
if ($users = get_records_sql_array('SELECT u.id
if ($users = get_records_sql_array("
SELECT u.id
FROM {usr} u
WHERE (? - ' . db_format_tsfield('lastlogin', false) . ') > ?', array(time(), $expire))) {
WHERE $lastactive + $dbexpire < current_timestamp
AND (u.expiry IS NULL OR u.expiry > current_timestamp)", array($installationtime))) {
// Users have become inactive!
foreach ($users as $user) {
deactivate_user($user->id);
......@@ -1818,8 +1831,11 @@ class PluginAuth extends Plugin {
else if ($user->expiry && $user->expiry < time()) {
$active = false;
}
else if ($inactivetime && $user->lastlogin + $inactivetime < time()) {
$active = false;
else if ($inactivetime) {
$lastactive = max($user->lastlogin, $user->lastaccess, $user->ctime);
if ($lastactive && ($lastactive + $inactivetime < time())) {
$active = false;
}
}
else if ($user->deleted) {
$active = false;
......
......@@ -1679,3 +1679,12 @@ function db_replace($replacearray) {
}
}
}
function db_interval($s) {
if (is_postgres()) {
return "INTERVAL '$s seconds'";
}
if (is_mysql()) {
return "INTERVAL $s SECOND";
}
}
......@@ -1288,8 +1288,7 @@ function unexpire_user($userid) {
/**
* Marks a user as inactive
*
* Nothing amazing needs to happen here, but this function is here for
* consistency.
* Sets the account expiry to the current time to disable login.
*
* This function is called when a user account is detected to be inactive.
* It is assumed that the account actually is inactive.
......@@ -1297,6 +1296,11 @@ function unexpire_user($userid) {
* @param int $userid The ID of user to mark inactive
*/
function deactivate_user($userid) {
execute_sql('
UPDATE {usr} SET expiry = current_timestamp
WHERE id = ? AND (expiry IS NULL OR expiry > current_timestamp)',
array($userid)
);
handle_event('deactivateuser', $userid);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment