From 574b9d86e9ffcfbc16ba4465c1cc96ae53317e1c Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Thu, 22 Sep 2016 16:24:45 +0100 Subject: [PATCH 1/6] MDL-56092 core_auth: Move signup code from form to authlib --- lib/authlib.php | 100 ++++++++++++++++++++++++++++++++++++++++++ login/signup.php | 14 +----- login/signup_form.php | 69 ++--------------------------- 3 files changed, 106 insertions(+), 77 deletions(-) diff --git a/lib/authlib.php b/lib/authlib.php index 15dc7d471d5..082242f3a10 100644 --- a/lib/authlib.php +++ b/lib/authlib.php @@ -796,3 +796,103 @@ function login_unlock_account($user) { // Note: do not clear the lockout secret because user might click on the link repeatedly. } + +/** + * Returns whether or not the captcha element is enabled, and the admin settings fulfil its requirements. + * @return bool + */ +function signup_captcha_enabled() { + global $CFG; + $authplugin = get_auth_plugin($CFG->registerauth); + return !empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey) && $authplugin->is_captcha_enabled(); +} + +/** + * Validates the standard sign-up data (except recaptcha that is validated by the form element). + * + * @param array $data the sign-up data + * @param array $files files among the data + * @return array list of errors, being the key the data element name and the value the error itself + * @since Moodle 3.2 + */ +function signup_validate_data($data, $files) { + global $CFG, $DB; + + $errors = array(); + $authplugin = get_auth_plugin($CFG->registerauth); + + if ($DB->record_exists('user', array('username' => $data['username'], 'mnethostid' => $CFG->mnet_localhost_id))) { + $errors['username'] = get_string('usernameexists'); + } else { + // Check allowed characters. + if ($data['username'] !== core_text::strtolower($data['username'])) { + $errors['username'] = get_string('usernamelowercase'); + } else { + if ($data['username'] !== core_user::clean_field($data['username'], 'username')) { + $errors['username'] = get_string('invalidusername'); + } + + } + } + + // Check if user exists in external db. + // TODO: maybe we should check all enabled plugins instead. + if ($authplugin->user_exists($data['username'])) { + $errors['username'] = get_string('usernameexists'); + } + + if (! validate_email($data['email'])) { + $errors['email'] = get_string('invalidemail'); + + } else if ($DB->record_exists('user', array('email' => $data['email']))) { + $errors['email'] = get_string('emailexists').' '.get_string('newpassword').'?'; + } + if (empty($data['email2'])) { + $errors['email2'] = get_string('missingemail'); + + } else if ($data['email2'] != $data['email']) { + $errors['email2'] = get_string('invalidemail'); + } + if (!isset($errors['email'])) { + if ($err = email_is_not_allowed($data['email'])) { + $errors['email'] = $err; + } + } + + $errmsg = ''; + if (!check_password_policy($data['password'], $errmsg)) { + $errors['password'] = $errmsg; + } + + // Validate customisable profile fields. (profile_validation expects an object as the parameter with userid set). + $dataobject = (object)$data; + $dataobject->id = 0; + $errors += profile_validation($dataobject, $files); + + return $errors; +} + +/** + * Add the missing fields to a user that is going to be created + * + * @param stdClass $user the new user object + * @return stdClass the user filled + * @since Moodle 3.2 + */ +function signup_setup_new_user($user) { + global $CFG; + + $user->confirmed = 0; + $user->lang = current_language(); + $user->firstaccess = 0; + $user->timecreated = time(); + $user->mnethostid = $CFG->mnet_localhost_id; + $user->secret = random_string(15); + $user->auth = $CFG->registerauth; + // Initialize alternate name fields to empty strings. + $namefields = array_diff(get_all_user_name_fields(), useredit_get_required_name_fields()); + foreach ($namefields as $namefield) { + $user->$namefield = ''; + } + return $user; +} diff --git a/login/signup.php b/login/signup.php index 8e26ee6c14c..1e54597dbac 100644 --- a/login/signup.php +++ b/login/signup.php @@ -70,18 +70,8 @@ if ($mform_signup->is_cancelled()) { redirect(get_login_url()); } else if ($user = $mform_signup->get_data()) { - $user->confirmed = 0; - $user->lang = current_language(); - $user->firstaccess = 0; - $user->timecreated = time(); - $user->mnethostid = $CFG->mnet_localhost_id; - $user->secret = random_string(15); - $user->auth = $CFG->registerauth; - // Initialize alternate name fields to empty strings. - $namefields = array_diff(get_all_user_name_fields(), useredit_get_required_name_fields()); - foreach ($namefields as $namefield) { - $user->$namefield = ''; - } + // Add missing required fields. + $user = signup_setup_new_user($user); $authplugin->user_signup($user, true); // prints notice and link to login/index.php exit; //never reached diff --git a/login/signup_form.php b/login/signup_form.php index 9cbee53463c..185cb69ac66 100644 --- a/login/signup_form.php +++ b/login/signup_form.php @@ -92,7 +92,7 @@ class login_signup_form extends moodleform { profile_signup_fields($mform); - if ($this->signup_captcha_enabled()) { + if (signup_captcha_enabled()) { $mform->addElement('recaptcha', 'recaptcha_element', get_string('security_question', 'auth'), array('https' => $CFG->loginhttps)); $mform->addHelpButton('recaptcha_element', 'recaptcha', 'auth'); $mform->closeHeaderBefore('recaptcha_element'); @@ -122,57 +122,9 @@ class login_signup_form extends moodleform { } function validation($data, $files) { - global $CFG, $DB; $errors = parent::validation($data, $files); - $authplugin = get_auth_plugin($CFG->registerauth); - - if ($DB->record_exists('user', array('username'=>$data['username'], 'mnethostid'=>$CFG->mnet_localhost_id))) { - $errors['username'] = get_string('usernameexists'); - } else { - //check allowed characters - if ($data['username'] !== core_text::strtolower($data['username'])) { - $errors['username'] = get_string('usernamelowercase'); - } else { - if ($data['username'] !== core_user::clean_field($data['username'], 'username')) { - $errors['username'] = get_string('invalidusername'); - } - - } - } - - //check if user exists in external db - //TODO: maybe we should check all enabled plugins instead - if ($authplugin->user_exists($data['username'])) { - $errors['username'] = get_string('usernameexists'); - } - - - if (! validate_email($data['email'])) { - $errors['email'] = get_string('invalidemail'); - - } else if ($DB->record_exists('user', array('email'=>$data['email']))) { - $errors['email'] = get_string('emailexists').' '.get_string('newpassword').'?'; - } - if (empty($data['email2'])) { - $errors['email2'] = get_string('missingemail'); - - } else if ($data['email2'] != $data['email']) { - $errors['email2'] = get_string('invalidemail'); - } - if (!isset($errors['email'])) { - if ($err = email_is_not_allowed($data['email'])) { - $errors['email'] = $err; - } - - } - - $errmsg = ''; - if (!check_password_policy($data['password'], $errmsg)) { - $errors['password'] = $errmsg; - } - - if ($this->signup_captcha_enabled()) { + if (signup_captcha_enabled()) { $recaptcha_element = $this->_form->getElement('recaptcha_element'); if (!empty($this->_form->_submitValues['recaptcha_challenge_field'])) { $challenge_field = $this->_form->_submitValues['recaptcha_challenge_field']; @@ -184,23 +136,10 @@ class login_signup_form extends moodleform { $errors['recaptcha'] = get_string('missingrecaptchachallengefield'); } } - // Validate customisable profile fields. (profile_validation expects an object as the parameter with userid set) - $dataobject = (object)$data; - $dataobject->id = 0; - $errors += profile_validation($dataobject, $files); + + $errors += signup_validate_data($data, $files); return $errors; } - - /** - * Returns whether or not the captcha element is enabled, and the admin settings fulfil its requirements. - * @return bool - */ - function signup_captcha_enabled() { - global $CFG; - $authplugin = get_auth_plugin($CFG->registerauth); - return !empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey) && $authplugin->is_captcha_enabled(); - } - } From f1062815e21c576b27453b4792a548e2a1ff6219 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Thu, 22 Sep 2016 16:24:54 +0100 Subject: [PATCH 2/6] MDL-56092 core_auth: Refactor recaptcha lib --- lib/recaptchalib.php | 46 ++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/lib/recaptchalib.php b/lib/recaptchalib.php index 82fb9ba5579..79eb4a3fc61 100644 --- a/lib/recaptchalib.php +++ b/lib/recaptchalib.php @@ -96,6 +96,28 @@ function _recaptcha_http_post($host, $path, $data, $port = 80, $https=false) { } } +/** + * Return the recaptcha challenge and image and javascript urls + * + * @param string $server server url + * @param string $pubkey public key + * @param string $errorpart error part to append + * @return array the challenge hash, image and javascript url + * @since Moodle 3.2 + */ +function recaptcha_get_challenge_hash_and_urls($server, $pubkey, $errorpart = '') { + global $CFG; + + require_once($CFG->libdir . '/filelib.php'); + $html = download_file_content($server . '/noscript?k=' . $pubkey . $errorpart, null, null, false, 300, 20, true); + preg_match('/image\?c\=([A-Za-z0-9\-\_]*)\"/', $html, $matches); + $challengehash = $matches[1]; + $imageurl = $server . '/image?c=' . $challengehash; + + $jsurl = $server . '/challenge?k=' . $pubkey . $errorpart; + + return array($challengehash, $imageurl, $jsurl); +} /** @@ -111,7 +133,7 @@ function _recaptcha_http_post($host, $path, $data, $port = 80, $https=false) { * @return string - The HTML to be embedded in the user's form. */ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) { - global $CFG, $PAGE; + global $PAGE; $recaptchatype = optional_param('recaptcha', 'image', PARAM_TEXT); @@ -127,14 +149,10 @@ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) { $errorpart = ""; if ($error) { - $errorpart = "&error=" . $error; + $errorpart = "&error=" . $error; } - require_once $CFG->libdir . '/filelib.php'; - $html = download_file_content($server . '/noscript?k=' . $pubkey . $errorpart, null, null, false, 300, 20, true); - preg_match('/image\?c\=([A-Za-z0-9\-\_]*)\"/', $html, $matches); - $challenge_hash = $matches[1]; - $image_url = $server . '/image?c=' . $challenge_hash; + list($challengehash, $imageurl, $jsurl) = recaptcha_get_challenge_hash_and_urls($server, $pubkey, $errorpart); $strincorrectpleasetryagain = get_string('incorrectpleasetryagain', 'auth'); $strenterthewordsabove = get_string('enterthewordsabove', 'auth'); @@ -143,10 +161,10 @@ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) { $strgetanaudiocaptcha = get_string('getanaudiocaptcha', 'auth'); $strgetanimagecaptcha = get_string('getanimagecaptcha', 'auth'); - $return = html_writer::script('', $server . '/challenge?k=' . $pubkey . $errorpart); + $return = html_writer::script('', $jsurl); $return .= '