diff --git a/auth/nologin/auth.php b/auth/nologin/auth.php index 9a1ec28e591..7b7dd3a0128 100644 --- a/auth/nologin/auth.php +++ b/auth/nologin/auth.php @@ -103,6 +103,33 @@ class auth_plugin_nologin extends auth_plugin_base { function can_be_manually_set() { return true; } + + /** + * Returns information on how the specified user can change their password. + * User accounts with authentication type set to nologin are disabled accounts. + * They cannot change their password. + * + * @param stdClass $user A user object + * @return string[] An array of strings with keys subject and message + */ + public function get_password_change_info(stdClass $user) : array { + $site = get_site(); + + $data = new stdClass(); + $data->firstname = $user->firstname; + $data->lastname = $user->lastname; + $data->username = $user->username; + $data->sitename = format_string($site->fullname); + $data->admin = generate_email_signoff(); + + $message = get_string('emailpasswordchangeinfodisabled', '', $data); + $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname)); + + return [ + 'subject' => $subject, + 'message' => $message + ]; + } } diff --git a/auth/oauth2/classes/auth.php b/auth/oauth2/classes/auth.php index 1ecfca81cf7..448c00ea6c7 100644 --- a/auth/oauth2/classes/auth.php +++ b/auth/oauth2/classes/auth.php @@ -611,4 +611,30 @@ class auth extends \auth_plugin_base { $this->update_picture($user); redirect($redirecturl); } + + /** + * Returns information on how the specified user can change their password. + * The password of the oauth2 accounts is not stored in Moodle. + * + * @param stdClass $user A user object + * @return string[] An array of strings with keys subject and message + */ + public function get_password_change_info(stdClass $user) : array { + $site = get_site(); + + $data = new stdClass(); + $data->firstname = $user->firstname; + $data->lastname = $user->lastname; + $data->username = $user->username; + $data->sitename = format_string($site->fullname); + $data->admin = generate_email_signoff(); + + $message = get_string('emailpasswordchangeinfo', 'auth_oauth2', $data); + $subject = get_string('emailpasswordchangeinfosubject', 'auth_oauth2', format_string($site->fullname)); + + return [ + 'subject' => $subject, + 'message' => $message + ]; + } } diff --git a/auth/oauth2/lang/en/auth_oauth2.php b/auth/oauth2/lang/en/auth_oauth2.php index ed38e2dc744..b6fe4b6431a 100644 --- a/auth/oauth2/lang/en/auth_oauth2.php +++ b/auth/oauth2/lang/en/auth_oauth2.php @@ -70,6 +70,15 @@ $string['emailconfirmlinksent'] = '

An existing account was found with this em

An email should have been sent to your address at {$a}.

It contains easy instructions to link your accounts.

If you have any difficulty, contact the site administrator.

'; +$string['emailpasswordchangeinfo'] = 'Hi {$a->firstname}, + +Someone (probably you) has requested a new password for your account on \'{$a->sitename}\'. + +However your password cannot be reset because you are using your account on another site to log in. + +Please log in as before, using the link on the login page. +{$a->admin}'; +$string['emailpasswordchangeinfosubject'] = '{$a}: Change password information'; $string['info'] = 'External account'; $string['issuer'] = 'OAuth 2 Service'; $string['issuernologin'] = 'This issuer can not be used to login'; diff --git a/auth/oauth2/tests/auth_test.php b/auth/oauth2/tests/auth_test.php new file mode 100644 index 00000000000..ab5b2ff74b5 --- /dev/null +++ b/auth/oauth2/tests/auth_test.php @@ -0,0 +1,53 @@ +. + +/** + * Auth oauth2 auth functions tests. + * + * @package auth_oauth2 + * @category test + * @copyright 2019 Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +/** + * Tests for the \auth_oauth2\auth class. + * + * @copyright 2019 Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class auth_oauth2_auth_testcase extends advanced_testcase { + + public function test_get_password_change_info() { + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(['auth' => 'oauth2']); + $auth = get_auth_plugin($user->auth); + $info = $auth->get_password_change_info($user); + + $this->assertEquals( + ['subject', 'message'], + array_keys($info), + '', 0.0, 10, true); + $this->assertContains( + 'your password cannot be reset because you are using your account on another site to log in', + $info['message']); + } +} \ No newline at end of file diff --git a/auth/upgrade.txt b/auth/upgrade.txt index 4e0502be17f..917165985d3 100644 --- a/auth/upgrade.txt +++ b/auth/upgrade.txt @@ -1,6 +1,11 @@ This files describes API changes in /auth/* - plugins, information provided here is intended especially for developers. +=== 3.7 === + +* get_password_change_info() method is added to the base class and returns an array containing the subject and body of the message + to the user that contains instructions on how to change their password. Authentication plugins can override this method if needed. + === 3.6 === * Login forms generated from Moodle must include a login token to protect automated logins. See \core\session\manager::get_login_token(). diff --git a/lib/authlib.php b/lib/authlib.php index 33a193f094c..4308a43d00c 100644 --- a/lib/authlib.php +++ b/lib/authlib.php @@ -758,6 +758,45 @@ class auth_plugin_base { } return $data; } + + /** + * Returns information on how the specified user can change their password. + * + * @param stdClass $user A user object + * @return string[] An array of strings with keys subject and message + */ + public function get_password_change_info(stdClass $user) : array { + $site = get_site(); + $systemcontext = context_system::instance(); + + $data = new stdClass(); + $data->firstname = $user->firstname; + $data->lastname = $user->lastname; + $data->username = $user->username; + $data->sitename = format_string($site->fullname); + $data->admin = generate_email_signoff(); + + if ($this->can_change_password() and $this->change_password_url()) { + // We have some external url for password changing. + $data->link = $this->change_password_url(); + } else { + // No way to change password, sorry. + $data->link = ''; + } + + if (!empty($data->link) and has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) { + $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname)); + $message = get_string('emailpasswordchangeinfo', '', $data); + } else { + $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname)); + $message = get_string('emailpasswordchangeinfofail', '', $data); + } + + return [ + 'subject' => $subject, + 'message' => $message + ]; + } } /** diff --git a/lib/moodlelib.php b/lib/moodlelib.php index f3b227f6b4c..ad2c738b7ac 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -6431,17 +6431,14 @@ function send_password_change_confirmation_email($user, $resetrecord) { } /** - * Sends an email containinginformation on how to change your password. + * Sends an email containing information on how to change your password. * * @param stdClass $user A {@link $USER} object * @return bool Returns true if mail was sent OK and false if there was an error. */ function send_password_change_info($user) { - global $CFG; - $site = get_site(); $supportuser = core_user::get_support_user(); - $systemcontext = context_system::instance(); $data = new stdClass(); $data->firstname = $user->firstname; @@ -6450,35 +6447,18 @@ function send_password_change_info($user) { $data->sitename = format_string($site->fullname); $data->admin = generate_email_signoff(); - $userauth = get_auth_plugin($user->auth); - - if (!is_enabled_auth($user->auth) or $user->auth == 'nologin') { + if (!is_enabled_auth($user->auth)) { $message = get_string('emailpasswordchangeinfodisabled', '', $data); $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname)); // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber. return email_to_user($user, $supportuser, $subject, $message); } - if ($userauth->can_change_password() and $userauth->change_password_url()) { - // We have some external url for password changing. - $data->link .= $userauth->change_password_url(); - - } else { - // No way to change password, sorry. - $data->link = ''; - } - - if (!empty($data->link) and has_capability('moodle/user:changeownpassword', $systemcontext, $user->id)) { - $message = get_string('emailpasswordchangeinfo', '', $data); - $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname)); - } else { - $message = get_string('emailpasswordchangeinfofail', '', $data); - $subject = get_string('emailpasswordchangeinfosubject', '', format_string($site->fullname)); - } + $userauth = get_auth_plugin($user->auth); + ['subject' => $subject, 'message' => $message] = $userauth->get_password_change_info($user); // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber. return email_to_user($user, $supportuser, $subject, $message); - } /** diff --git a/lib/tests/moodlelib_test.php b/lib/tests/moodlelib_test.php index 199f3f10f36..fc742d5f948 100644 --- a/lib/tests/moodlelib_test.php +++ b/lib/tests/moodlelib_test.php @@ -4354,4 +4354,20 @@ class core_moodlelib_testcase extends advanced_testcase { $this->assertFalse($fetcheduser); } } + + /** + * Test for send_password_change_(). + */ + public function test_send_password_change_info() { + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(); + + $sink = $this->redirectEmails(); // Make sure we are redirecting emails. + send_password_change_info($user); + $result = $sink->get_messages(); + $sink->close(); + + $this->assertContains('passwords cannot be reset on this site', $result[0]->body); + } }