From 6f793705318bf519ebf3b15a1fdb1cf52e494647 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Tue, 23 Oct 2018 16:09:47 +0200 Subject: [PATCH] MDL-63742 auth: New WS core_auth_resend_confirmation_email --- auth/classes/external.php | 91 +++++++++++++++++++++++++++ auth/tests/external_test.php | 116 +++++++++++++++++++++++++++++++++++ lib/db/services.php | 8 +++ version.php | 2 +- 4 files changed, 216 insertions(+), 1 deletion(-) diff --git a/auth/classes/external.php b/auth/classes/external.php index 7c083494a9d..2cb651dd162 100644 --- a/auth/classes/external.php +++ b/auth/classes/external.php @@ -336,4 +336,95 @@ class core_auth_external extends external_api { ) ); } + + /** + * Describes the parameters for resend_confirmation_email. + * + * @return external_function_parameters + * @since Moodle 3.6 + */ + public static function resend_confirmation_email_parameters() { + return new external_function_parameters( + array( + 'username' => new external_value(core_user::get_property_type('username'), 'Username.'), + 'password' => new external_value(core_user::get_property_type('password'), 'Plain text password.'), + 'redirect' => new external_value(PARAM_LOCALURL, 'Redirect the user to this site url after confirmation.', + VALUE_DEFAULT, ''), + ) + ); + } + + /** + * Requests resend the confirmation email. + * + * @param string $username user name + * @param string $password plain text password + * @param string $redirect redirect the user to this site url after confirmation + * @return array warnings and success status + * @since Moodle 3.6 + * @throws moodle_exception + */ + public static function resend_confirmation_email($username, $password, $redirect = '') { + global $PAGE; + + $warnings = array(); + $params = self::validate_parameters( + self::resend_confirmation_email_parameters(), + array( + 'username' => $username, + 'password' => $password, + 'redirect' => $redirect, + ) + ); + + $context = context_system::instance(); + $PAGE->set_context($context); // Need by internal APIs. + $username = trim(core_text::strtolower($params['username'])); + $password = $params['password']; + + if (is_restored_user($username)) { + throw new moodle_exception('restoredaccountresetpassword', 'webservice'); + } + + $user = authenticate_user_login($username, $password); + + if (empty($user)) { + throw new moodle_exception('invalidlogin'); + } + + if ($user->confirmed) { + throw new moodle_exception('alreadyconfirmed'); + } + + // Check if we should redirect the user once the user is confirmed. + $confirmationurl = null; + if (!empty($params['redirect'])) { + // Pass via moodle_url to fix thinks like admin links. + $redirect = new moodle_url($params['redirect']); + + $confirmationurl = new moodle_url('/login/confirm.php', array('redirect' => $redirect->out())); + } + $status = send_confirmation_email($user, $confirmationurl); + + return array( + 'status' => $status, + 'warnings' => $warnings, + ); + } + + /** + * Describes the resend_confirmation_email return value. + * + * @return external_single_structure + * @since Moodle 3.6 + */ + public static function resend_confirmation_email_returns() { + + return new external_single_structure( + array( + 'status' => new external_value(PARAM_BOOL, 'True if the confirmation email was sent, false otherwise.'), + 'warnings' => new external_warnings(), + ) + ); + } } diff --git a/auth/tests/external_test.php b/auth/tests/external_test.php index 84ffa1f8daa..237852ce6e5 100644 --- a/auth/tests/external_test.php +++ b/auth/tests/external_test.php @@ -40,6 +40,9 @@ require_once($CFG->dirroot . '/webservice/tests/helpers.php'); */ class core_auth_external_testcase extends externallib_advanced_testcase { + /** @var string Original error log */ + protected $oldlog; + /** * Set up for every test */ @@ -48,6 +51,18 @@ class core_auth_external_testcase extends externallib_advanced_testcase { $this->resetAfterTest(true); $CFG->registerauth = 'email'; + + // Discard error logs. + $this->oldlog = ini_get('error_log'); + ini_set('error_log', "$CFG->dataroot/testlog.log"); + } + + /** + * Tear down to restore old logging.. + */ + protected function tearDown() { + ini_set('error_log', $this->oldlog); + parent::tearDown(); } /** @@ -115,4 +130,105 @@ class core_auth_external_testcase extends externallib_advanced_testcase { core_auth_external::is_age_digital_consent_verification_enabled_returns(), $result); $this->assertTrue($result['status']); } + + /** + * Test resend_confirmation_email. + */ + public function test_resend_confirmation_email() { + global $DB; + + $username = 'pepe'; + $password = 'abcdefAª.ªª!!3'; + $firstname = 'Pepe'; + $lastname = 'Pérez'; + $email = 'myemail@no.zbc'; + + // Create new user. + $result = auth_email_external::signup_user($username, $password, $firstname, $lastname, $email); + $result = external_api::clean_returnvalue(auth_email_external::signup_user_returns(), $result); + $this->assertTrue($result['success']); + $this->assertEmpty($result['warnings']); + + $result = core_auth_external::resend_confirmation_email($username, $password); + $result = external_api::clean_returnvalue(core_auth_external::resend_confirmation_email_returns(), $result); + $this->assertTrue($result['status']); + $this->assertEmpty($result['warnings']); + $confirmed = $DB->get_field('user', 'confirmed', array('username' => $username)); + $this->assertEquals(0, $confirmed); + } + + /** + * Test resend_confirmation_email invalid username. + */ + public function test_resend_confirmation_email_invalid_username() { + + $username = 'pepe'; + $password = 'abcdefAª.ªª!!3'; + $firstname = 'Pepe'; + $lastname = 'Pérez'; + $email = 'myemail@no.zbc'; + + // Create new user. + $result = auth_email_external::signup_user($username, $password, $firstname, $lastname, $email); + $result = external_api::clean_returnvalue(auth_email_external::signup_user_returns(), $result); + $this->assertTrue($result['success']); + $this->assertEmpty($result['warnings']); + + $_SERVER['HTTP_USER_AGENT'] = 'no browser'; // Hack around missing user agent in CLI scripts. + $this->expectException('moodle_exception'); + $this->expectExceptionMessage('error/invalidlogin'); + $result = core_auth_external::resend_confirmation_email('abc', $password); + } + + /** + * Test resend_confirmation_email invalid password. + */ + public function test_resend_confirmation_email_invalid_password() { + + $username = 'pepe'; + $password = 'abcdefAª.ªª!!3'; + $firstname = 'Pepe'; + $lastname = 'Pérez'; + $email = 'myemail@no.zbc'; + + // Create new user. + $result = auth_email_external::signup_user($username, $password, $firstname, $lastname, $email); + $result = external_api::clean_returnvalue(auth_email_external::signup_user_returns(), $result); + $this->assertTrue($result['success']); + $this->assertEmpty($result['warnings']); + + $_SERVER['HTTP_USER_AGENT'] = 'no browser'; // Hack around missing user agent in CLI scripts. + $this->expectException('moodle_exception'); + $this->expectExceptionMessage('error/invalidlogin'); + $result = core_auth_external::resend_confirmation_email($username, 'abc'); + } + + /** + * Test resend_confirmation_email already confirmed user. + */ + public function test_resend_confirmation_email_already_confirmed_user() { + global $DB; + + $username = 'pepe'; + $password = 'abcdefAª.ªª!!3'; + $firstname = 'Pepe'; + $lastname = 'Pérez'; + $email = 'myemail@no.zbc'; + + // Create new user. + $result = auth_email_external::signup_user($username, $password, $firstname, $lastname, $email); + $result = external_api::clean_returnvalue(auth_email_external::signup_user_returns(), $result); + $this->assertTrue($result['success']); + $this->assertEmpty($result['warnings']); + $secret = $DB->get_field('user', 'secret', array('username' => $username)); + + // Confirm the user. + $result = core_auth_external::confirm_user($username, $secret); + $result = external_api::clean_returnvalue(core_auth_external::confirm_user_returns(), $result); + $this->assertTrue($result['success']); + + $this->expectException('moodle_exception'); + $this->expectExceptionMessage('error/alreadyconfirmed'); + core_auth_external::resend_confirmation_email($username, $password); + } } diff --git a/lib/db/services.php b/lib/db/services.php index f9e1185f5a5..1c4a37fc5d3 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -66,6 +66,14 @@ $functions = array( 'ajax' => true, 'loginrequired' => false, ), + 'core_auth_resend_confirmation_email' => array( + 'classname' => 'core_auth_external', + 'methodname' => 'resend_confirmation_email', + 'description' => 'Resend confirmation email.', + 'type' => 'write', + 'ajax' => true, + 'loginrequired' => false, + ), 'core_badges_get_user_badges' => array( 'classname' => 'core_badges_external', 'methodname' => 'get_user_badges', diff --git a/version.php b/version.php index 3b66a8e65b9..46c8bda27a8 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2018102700.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2018102700.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. -- 2.43.0