MDL-23692 forgotpw: Move functionality to lib.

Move the password reset request handling into a function.
Move the password reset confirmation handling into a function.
This commit is contained in:
Peter Bulmer 2013-09-14 13:28:25 +12:00
parent d45e65ccad
commit f1fc0d3219
2 changed files with 153 additions and 132 deletions

View File

@ -28,6 +28,7 @@
require('../config.php');
require_once($CFG->libdir.'/authlib.php');
require_once('lib.php');
require_once('forgot_password_form.php');
$p_secret = optional_param('p', false, PARAM_RAW);
@ -59,136 +60,12 @@ if (isloggedin() and !isguestuser()) {
redirect($CFG->wwwroot.'/index.php', get_string('loginalready'), 5);
}
if ($p_secret !== false) {
///=====================
/// user clicked on link in email message
///=====================
$user = $DB->get_record('user', array('username'=>$p_username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0, 'suspended'=>0));
if ($user and ($user->auth === 'nologin' or !is_enabled_auth($user->auth))) {
// bad luck - user is not able to login, do not let them reset password
$user = false;
}
if (!empty($user) and $user->secret === '') {
echo $OUTPUT->header();
print_error('secretalreadyused');
} else if (!empty($user) and $user->secret == $p_secret) {
// make sure that url relates to a valid user
// check this isn't guest user
if (isguestuser($user)) {
print_error('cannotresetguestpwd');
}
// Reset login lockout even of the password reset fails.
login_unlock_account($user);
// make sure user is allowed to change password
require_capability('moodle/user:changeownpassword', $systemcontext, $user->id);
if (!reset_password_and_mail($user)) {
print_error('cannotresetmail');
}
// Clear secret so that it can not be used again
$user->secret = '';
$DB->set_field('user', 'secret', $user->secret, array('id'=>$user->id));
$changepasswordurl = "{$CFG->httpswwwroot}/login/change_password.php";
$a = new stdClass();
$a->email = $user->email;
$a->link = $changepasswordurl;
echo $OUTPUT->header();
notice(get_string('emailpasswordsent', '', $a), $changepasswordurl);
} else {
if (!empty($user) and strlen($p_secret) === 15) {
// somebody probably tries to hack in by guessing secret - stop them!
$DB->set_field('user', 'secret', '', array('id'=>$user->id));
}
echo $OUTPUT->header();
print_error('forgotteninvalidurl');
}
die; //never reached
if (empty($p_secret)) {
// This is a new password reset request
// identify the user & send confirmation email
forgotpw_process_request();
} else {
// User clicked on confirmation link in email message
// validate the token & set new password
forgotpw_process_pwset($p_secret, $p_username);
}
$mform = new login_forgot_password_form();
if ($mform->is_cancelled()) {
redirect(get_login_url());
} else if ($data = $mform->get_data()) {
/// find the user in the database and mail info
// first try the username
if (!empty($data->username)) {
$username = core_text::strtolower($data->username); // mimic the login page process, if they forget username they need to use email for reset
$user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0, 'suspended'=>0));
} else {
// this is tricky because
// 1/ the email is not guaranteed to be unique - TODO: send email with all usernames to select the correct account for pw reset
// 2/ mailbox may be case sensitive, the email domain is case insensitive - let's pretend it is all case-insensitive
$select = $DB->sql_like('email', ':email', false, true, false, '|'). " AND mnethostid = :mnethostid AND deleted=0 AND suspended=0";
$params = array('email'=>$DB->sql_like_escape($data->email, '|'), 'mnethostid'=>$CFG->mnet_localhost_id);
$user = $DB->get_record_select('user', $select, $params, '*', IGNORE_MULTIPLE);
}
if ($user and !empty($user->confirmed)) {
$userauth = get_auth_plugin($user->auth);
if (has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
// send email
}
if ($userauth->can_reset_password() and is_enabled_auth($user->auth)
and has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
// send reset password confirmation
// set 'secret' string
$user->secret = random_string(15);
$DB->set_field('user', 'secret', $user->secret, array('id'=>$user->id));
if (!send_password_change_confirmation_email($user)) {
print_error('cannotmailconfirm');
}
} else {
if (!send_password_change_info($user)) {
print_error('cannotmailconfirm');
}
}
}
echo $OUTPUT->header();
if (empty($user->email) or !empty($CFG->protectusernames)) {
// Print general confirmation message
notice(get_string('emailpasswordconfirmmaybesent'), $CFG->wwwroot.'/index.php');
} else {
// Confirm email sent
$protectedemail = preg_replace('/([^@]*)@(.*)/', '******@$2', $user->email); // obfuscate the email address to protect privacy
$stremailpasswordconfirmsent = get_string('emailpasswordconfirmsent', '', $protectedemail);
notice($stremailpasswordconfirmsent, $CFG->wwwroot.'/index.php');
}
die; // never reached
}
// make sure we really are on the https page when https login required
$PAGE->verify_https_required();
/// DISPLAY FORM
echo $OUTPUT->header();
echo $OUTPUT->box(get_string('passwordforgotteninstructions2'), 'generalbox boxwidthnormal boxaligncenter');
$mform->display();
echo $OUTPUT->footer();

144
login/lib.php Normal file
View File

@ -0,0 +1,144 @@
<?php
/* This function processes a user's request to set a new password in the event they forgot the old one.
If no user identifier has been supplied, it displays a form where they can submit their identifier.
Where they have supplied identifier, the function will check their status, and send email as appropriate.
*/
function forgotpw_process_request() {
global $DB, $OUTPUT, $CFG, $PAGE;
$systemcontext = context_system::instance();
$mform = new login_forgot_password_form();
if ($mform->is_cancelled()) {
redirect(get_login_url());
} else if ($data = $mform->get_data()) {
// User has submitted form data. Find the user in the database and mail info.
// First try the username.
if (!empty($data->username)) {
$username = core_text::strtolower($data->username); // mimic the login page process, if they forget username they need to use email for reset
$user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0, 'suspended'=>0));
} else {
// this is tricky because
// 1/ the email is not guaranteed to be unique - TODO: send email with all usernames to select the correct account for pw reset
// 2/ mailbox may be case sensitive, the email domain is case insensitive - let's pretend it is all case-insensitive
$select = $DB->sql_like('email', ':email', false, true, false, '|'). " AND mnethostid = :mnethostid AND deleted=0 AND suspended=0";
$params = array('email'=>$DB->sql_like_escape($data->email, '|'), 'mnethostid'=>$CFG->mnet_localhost_id);
$user = $DB->get_record_select('user', $select, $params, '*', IGNORE_MULTIPLE);
}
if ($user and !empty($user->confirmed)) {
$userauth = get_auth_plugin($user->auth);
if (has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
// send email
}
if ($userauth->can_reset_password() and is_enabled_auth($user->auth)
and has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
// send reset password confirmation
// set 'secret' string
$user->secret = random_string(15);
$DB->set_field('user', 'secret', $user->secret, array('id'=>$user->id));
if (!send_password_change_confirmation_email($user)) {
print_error('cannotmailconfirm');
}
} else {
if (!send_password_change_info($user)) {
print_error('cannotmailconfirm');
}
}
}
echo $OUTPUT->header();
if (empty($user->email) or !empty($CFG->protectusernames)) {
// Print general confirmation message
notice(get_string('emailpasswordconfirmmaybesent'), $CFG->wwwroot.'/index.php');
} else {
// Confirm email sent
$protectedemail = preg_replace('/([^@]*)@(.*)/', '******@$2', $user->email); // obfuscate the email address to protect privacy
$stremailpasswordconfirmsent = get_string('emailpasswordconfirmsent', '', $protectedemail);
notice($stremailpasswordconfirmsent, $CFG->wwwroot.'/index.php');
}
die; // never reached
}
// make sure we really are on the https page when https login required
$PAGE->verify_https_required();
/// DISPLAY FORM
echo $OUTPUT->header();
echo $OUTPUT->box(get_string('passwordforgotteninstructions2'), 'generalbox boxwidthnormal boxaligncenter');
$mform->display();
echo $OUTPUT->footer();
}
/* This function processes a user's submitted token to validate the request to set a new password
If the user's token is validated, they are emailed with a new password.
*/
function forgotpw_process_pwset($token, $username) {
global $DB, $CFG, $OUTPUT;
$systemcontext = context_system::instance();
$user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0, 'suspended'=>0));
if ($user and ($user->auth === 'nologin' or !is_enabled_auth($user->auth))) {
// bad luck - user is not able to login, do not let them reset password
$user = false;
}
if (!empty($user) and $user->secret === '') {
echo $OUTPUT->header();
print_error('secretalreadyused');
} else if (!empty($user) and $user->secret == $token) {
// make sure that url relates to a valid user
// check this isn't guest user
if (isguestuser($user)) {
print_error('cannotresetguestpwd');
}
// Reset login lockout even of the password reset fails.
login_unlock_account($user);
// make sure user is allowed to change password
require_capability('moodle/user:changeownpassword', $systemcontext, $user->id);
if (!reset_password_and_mail($user)) {
print_error('cannotresetmail');
}
// Clear secret so that it can not be used again
$user->secret = '';
$DB->set_field('user', 'secret', $user->secret, array('id'=>$user->id));
$changepasswordurl = "{$CFG->httpswwwroot}/login/change_password.php";
$a = new stdClass();
$a->email = $user->email;
$a->link = $changepasswordurl;
echo $OUTPUT->header();
notice(get_string('emailpasswordsent', '', $a), $changepasswordurl);
} else {
if (!empty($user) and strlen($token) === 15) {
// somebody probably tries to hack in by guessing secret - stop them!
$DB->set_field('user', 'secret', '', array('id'=>$user->id));
}
echo $OUTPUT->header();
print_error('forgotteninvalidurl');
}
die; //never reached
}
?>