예제 #1
0
/**
 *  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 core_login_process_password_reset_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()) {
            // Requesting user has submitted form data.
            // Next find the user account in the database which the requesting user claims to own.
            if (!empty($data->username)) {
                // Username has been specified - load the user record based on that.
                $username = core_text::strtolower($data->username);
                // Mimic the login page process.
                $userparams = array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id, 'deleted' => 0, 'suspended' => 0);
                $user = $DB->get_record('user', $userparams);
            } else {
                // Try to load the user record based on email address.
                // this is tricky because
                // 1/ the email is not guaranteed to be unique - TODO: send email with all usernames to select the 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);
            }
            // Target user details have now been identified, or we know that there is no such account.
            // Send email address to account's email address if appropriate.
            $pwresetstatus = PWRESET_STATUS_NOEMAILSENT;
            if ($user and !empty($user->confirmed)) {
                $userauth = get_auth_plugin($user->auth);
                if (!$userauth->can_reset_password() or !is_enabled_auth($user->auth) or !has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
                    if (send_password_change_info($user)) {
                        $pwresetstatus = PWRESET_STATUS_OTHEREMAILSENT;
                    } else {
                        print_error('cannotmailconfirm');
                    }
                } else {
                    // The account the requesting user claims to be is entitled to change their password.
                    // Next, check if they have an existing password reset in progress.
                    $resetinprogress = $DB->get_record('user_password_resets', array('userid' => $user->id));
                    if (empty($resetinprogress)) {
                        // Completely new reset request - common case.
                        $resetrecord = core_login_generate_password_reset($user);
                        $sendemail = true;
                    } else {
                        if ($resetinprogress->timerequested < time() - $CFG->pwresettime) {
                            // Preexisting, but expired request - delete old record & create new one.
                            // Uncommon case - expired requests are cleaned up by cron.
                            $DB->delete_records('user_password_resets', array('id' => $resetinprogress->id));
                            $resetrecord = core_login_generate_password_reset($user);
                            $sendemail = true;
                        } else {
                            if (empty($resetinprogress->timererequested)) {
                                // Preexisting, valid request. This is the first time user has re-requested the reset.
                                // Re-sending the same email once can actually help in certain circumstances
                                // eg by reducing the delay caused by greylisting.
                                $resetinprogress->timererequested = time();
                                $DB->update_record('user_password_resets', $resetinprogress);
                                $resetrecord = $resetinprogress;
                                $sendemail = true;
                            } else {
                                // Preexisting, valid request. User has already re-requested email.
                                $pwresetstatus = PWRESET_STATUS_ALREADYSENT;
                                $sendemail = false;
                            }
                        }
                    }
                    if ($sendemail) {
                        $sendresult = send_password_change_confirmation_email($user, $resetrecord);
                        if ($sendresult) {
                            $pwresetstatus = PWRESET_STATUS_TOKENSENT;
                        } else {
                            print_error('cannotmailconfirm');
                        }
                    }
                }
            }
            // Any email has now been sent.
            // Next display results to requesting user if settings permit.
            echo $OUTPUT->header();
            if (!empty($CFG->protectusernames)) {
                // Neither confirm, nor deny existance of any username or email address in database.
                // Print general (non-commital) message.
                notice(get_string('emailpasswordconfirmmaybesent'), $CFG->wwwroot . '/index.php');
                die;
                // Never reached.
            } else {
                if (empty($user)) {
                    // Protect usernames is off, and we couldn't find the user with details specified.
                    // Print failure advice.
                    notice(get_string('emailpasswordconfirmnotsent'), $CFG->wwwroot . '/forgot_password.php');
                    die;
                    // Never reached.
                } else {
                    if (empty($user->email)) {
                        // User doesn't have an email set - can't send a password change confimation email.
                        notice(get_string('emailpasswordconfirmnoemail'), $CFG->wwwroot . '/index.php');
                        die;
                        // Never reached.
                    } else {
                        if ($pwresetstatus == PWRESET_STATUS_ALREADYSENT) {
                            // User found, protectusernames is off, but user has already (re) requested a reset.
                            // Don't send a 3rd reset email.
                            $stremailalreadysent = get_string('emailalreadysent');
                            notice($stremailalreadysent, $CFG->wwwroot . '/index.php');
                            die;
                            // Never reached.
                        } else {
                            if ($pwresetstatus == PWRESET_STATUS_NOEMAILSENT) {
                                // User found, protectusernames is off, but user is not confirmed.
                                // Pretend we sent them an email.
                                // This is a big usability problem - need to tell users why we didn't send them an email.
                                // Obfuscate email address to protect privacy.
                                $protectedemail = preg_replace('/([^@]*)@(.*)/', '******@$2', $user->email);
                                $stremailpasswordconfirmsent = get_string('emailpasswordconfirmsent', '', $protectedemail);
                                notice($stremailpasswordconfirmsent, $CFG->wwwroot . '/index.php');
                                die;
                                // Never reached.
                            } else {
                                // Confirm email sent. (Obfuscate email address to protect privacy).
                                $protectedemail = preg_replace('/([^@]*)@(.*)/', '******@$2', $user->email);
                                // This is a small usability problem - may be obfuscating the email address which the user has just supplied.
                                $stremailresetconfirmsent = get_string('emailresetconfirmsent', '', $protectedemail);
                                notice($stremailresetconfirmsent, $CFG->wwwroot . '/index.php');
                                die;
                                // Never reached.
                            }
                        }
                    }
                }
            }
            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'); // GWL - Forgot Pwd page remove header content
    echo '<div class="loginbox clearfix onecolumn forgot-password">';
    echo '<div class="loginpanel">';
    echo get_string('passwordforgotten2');
    echo get_string('cantaccessaccount2');
    echo get_string('dontpanic2');
    $mform->display();
    echo '</div>';
    echo '</div>';
    echo $OUTPUT->footer();
}
예제 #2
0
     if (has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) {
         // send email (make sure mail block is off)
         $user->emailstop = 0;
     }
     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);
         if (!set_field('user', 'secret', $user->secret, 'id', $user->id)) {
             $json_output["errors"][] = "Error setting user secret string.";
         }
         if (!send_password_change_confirmation_email($user)) {
             $json_output["errors"][] = "Error sending password change confirmation email.";
         }
     } else {
         if (send_password_change_info($user)) {
             $json_output["forgot_password"] = true;
         } else {
             $json_output["errors"][] = "Error sending password change confirmation email.";
         }
     }
 } else {
     $authmethod = $user->auth;
     if (is_internal_auth($authmethod) or !empty($CFG->{'auth_' . $authmethod . '_stdchangepassword'})) {
         // handle internal authentication
         // set 'secret' string
         $user->secret = random_string(15);
         if (!set_field('user', 'secret', $user->secret, 'id', $user->id)) {
             $json_output["errors"][] = "Error setting user secret string.";
         }
         // send email (make sure mail block is off)