/** * Creates a user * * @throws moodle_exception * @param stdClass $user user to create * @param bool $updatepassword if true, authentication plugin will update password. * @param bool $triggerevent set false if user_created event should not be triggred. * This will not affect user_password_updated event triggering. * @return int id of the newly created user */ function user_create_user($user, $updatepassword = true, $triggerevent = true) { global $CFG, $DB; // Set the timecreate field to the current time. if (!is_object($user)) { $user = (object) $user; } /* GWL : For Phone Field Remove Check */ /* // Check username. if ($user->username !== core_text::strtolower($user->username)) { throw new moodle_exception('usernamelowercase'); } else { if ($user->username !== clean_param($user->username, PARAM_USERNAME)) { throw new moodle_exception('invalidusername'); } } */ /* GWL : For Phone Field Remove Check */ // Save the password in a temp value for later. if ($updatepassword && isset($user->password)) { // Check password toward the password policy. if (!check_password_policy($user->password, $errmsg)) { throw new moodle_exception($errmsg); } $userpassword = $user->password; unset($user->password); } // Make sure calendartype, if set, is valid. if (!empty($user->calendartype)) { $availablecalendartypes = \core_calendar\type_factory::get_list_of_calendar_types(); if (empty($availablecalendartypes[$user->calendartype])) { $user->calendartype = $CFG->calendartype; } } else { $user->calendartype = $CFG->calendartype; } $user->timecreated = time(); $user->timemodified = $user->timecreated; // Insert the user into the database. $newuserid = $DB->insert_record('user', $user); // Create USER context for this user. $usercontext = context_user::instance($newuserid); // Update user password if necessary. if (isset($userpassword)) { // Get full database user row, in case auth is default. $newuser = $DB->get_record('user', array('id' => $newuserid)); $authplugin = get_auth_plugin($newuser->auth); $authplugin->user_update_password($newuser, $userpassword); } // Trigger event If required. if ($triggerevent) { \core\event\user_created::create_from_userid($newuserid)->trigger(); } return $newuserid; }
function application_user_signup($user) { // Derived from email->user_signup global $CFG, $PAGE, $OUTPUT; $user->password = hash_internal_user_password($user->password); if (empty($user->calendartype)) { $user->calendartype = $CFG->calendartype; } $user->id = user_create_user($user, false, false); // Save any custom profile field information profile_save_data($user); // Save contact information write_contact_details($user->id, $user); // Trigger event \core\event\user_created::create_from_userid($user->id)->trigger(); if (!send_application_confirmation_email($user)) { print_error('auth_emailnoemail', 'auth_email'); } $PAGE->set_title($CFG->pageheading . ': ' . get_string('emailconfirm')); echo $OUTPUT->header(); notice(get_string('emailconfirmsent', '', $user->email), $CFG->wwwroot . '/local/obu_application/login.php'); }
/** * Creates a bare-bones user record * * @todo Outline auth types and provide code example * * @param string $username New user's username to add to record * @param string $password New user's password to add to record * @param string $auth Form of authentication required * @return stdClass A complete user object */ function create_user_record($username, $password, $auth = 'manual') { global $CFG, $DB; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; // Just in case check text case. $username = trim(core_text::strtolower($username)); $authplugin = get_auth_plugin($auth); $customfields = $authplugin->get_custom_user_profile_fields(); $newuser = new stdClass(); if ($newinfo = $authplugin->get_userinfo($username)) { $newinfo = truncate_userinfo($newinfo); foreach ($newinfo as $key => $value) { if (in_array($key, $authplugin->userfields) || in_array($key, $customfields)) { $newuser->{$key} = $value; } } } if (!empty($newuser->email)) { if (email_is_not_allowed($newuser->email)) { unset($newuser->email); } } if (!isset($newuser->city)) { $newuser->city = ''; } $newuser->auth = $auth; $newuser->username = $username; // Fix for MDL-8480 // user CFG lang for user if $newuser->lang is empty // or $user->lang is not an installed language. if (empty($newuser->lang) || !get_string_manager()->translation_exists($newuser->lang)) { $newuser->lang = $CFG->lang; } $newuser->confirmed = 1; $newuser->lastip = getremoteaddr(); $newuser->timecreated = time(); $newuser->timemodified = $newuser->timecreated; $newuser->mnethostid = $CFG->mnet_localhost_id; $newuser->id = user_create_user($newuser, false, false); // Save user profile data. profile_save_data($newuser); $user = get_complete_user_data('id', $newuser->id); if (!empty($CFG->{'auth_' . $newuser->auth . '_forcechangepassword'})) { set_user_preference('auth_forcepasswordchange', 1, $user); } // Set the password. update_internal_user_password($user, $password); // Trigger event. \core\event\user_created::create_from_userid($newuser->id)->trigger(); return $user; }
/** * Sign up a new user ready for confirmation. * Password is passed in plaintext. * * @param object $user new user object * @param boolean $notify print notice with link and terminate * @return boolean success */ function user_signup($user, $notify = true) { global $CFG, $DB, $PAGE, $OUTPUT; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; if ($this->user_exists($user->username)) { print_error('auth_ldap_user_exists', 'auth_ldap'); } $plainslashedpassword = $user->password; unset($user->password); if (!$this->user_create($user, $plainslashedpassword)) { print_error('auth_ldap_create_error', 'auth_ldap'); } $user->id = user_create_user($user, false, false); user_add_password_history($user->id, $plainslashedpassword); // Save any custom profile field information profile_save_data($user); $this->update_user_record($user->username); // This will also update the stored hash to the latest algorithm // if the existing hash is using an out-of-date algorithm (or the // legacy md5 algorithm). update_internal_user_password($user, $plainslashedpassword); $user = $DB->get_record('user', array('id' => $user->id)); \core\event\user_created::create_from_userid($user->id)->trigger(); if (!send_confirmation_email($user)) { print_error('noemail', 'auth_ldap'); } if ($notify) { $emailconfirm = get_string('emailconfirm'); $PAGE->set_url('/auth/ldap/auth.php'); $PAGE->navbar->add($emailconfirm); $PAGE->set_title($emailconfirm); $PAGE->set_heading($emailconfirm); echo $OUTPUT->header(); notice(get_string('emailconfirmsent', '', $user->email), "{$CFG->wwwroot}/index.php"); } else { return true; } }
/** * Create a Moodle user from Azure AD user data. * * @param array $aaddata Array of Azure AD user data. * @return \stdClass An object representing the created Moodle user. */ public function create_user_from_aaddata($aaddata) { global $CFG; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; $newuser = (object) ['auth' => 'oidc', 'username' => trim(\core_text::strtolower($aaddata['userPrincipalName'])), 'email' => isset($aaddata['mail']) ? $aaddata['mail'] : '', 'firstname' => isset($aaddata['givenName']) ? $aaddata['givenName'] : '', 'lastname' => isset($aaddata['surname']) ? $aaddata['surname'] : '', 'city' => isset($aaddata['city']) ? $aaddata['city'] : '', 'country' => isset($aaddata['country']) ? $aaddata['country'] : '', 'department' => isset($aaddata['department']) ? $aaddata['department'] : '', 'lang' => isset($aaddata['preferredLanguage']) ? substr($aaddata['preferredLanguage'], 0, 2) : 'en', 'confirmed' => 1, 'timecreated' => time(), 'mnethostid' => $CFG->mnet_localhost_id]; $password = null; $newuser->idnumber = $newuser->username; if (!empty($newuser->email)) { if (email_is_not_allowed($newuser->email)) { unset($newuser->email); } } if (empty($newuser->lang) || !get_string_manager()->translation_exists($newuser->lang)) { $newuser->lang = $CFG->lang; } $newuser->timemodified = $newuser->timecreated; $newuser->id = user_create_user($newuser, false, false); // Save user profile data. profile_save_data($newuser); $user = get_complete_user_data('id', $newuser->id); if (!empty($CFG->{'auth_' . $newuser->auth . '_forcechangepassword'})) { set_user_preference('auth_forcepasswordchange', 1, $user); } // Set the password. update_internal_user_password($user, $password); // Trigger event. \core\event\user_created::create_from_userid($newuser->id)->trigger(); return $user; }
/** * Create one or more users. * * @throws invalid_parameter_exception * @param array $users An array of users to create. * @return array An array of arrays * @since Moodle 2.2 */ public static function create_users($users) { global $CFG, $DB; require_once $CFG->dirroot . "/lib/weblib.php"; require_once $CFG->dirroot . "/user/lib.php"; require_once $CFG->dirroot . "/user/profile/lib.php"; // Required for customfields related function. // Ensure the current user is allowed to run this function. $context = context_system::instance(); self::validate_context($context); require_capability('moodle/user:create', $context); // Do basic automatic PARAM checks on incoming data, using params description. // If any problems are found then exceptions are thrown with helpful error messages. $params = self::validate_parameters(self::create_users_parameters(), array('users' => $users)); $availableauths = core_component::get_plugin_list('auth'); unset($availableauths['mnet']); // These would need mnethostid too. unset($availableauths['webservice']); // We do not want new webservice users for now. $availablethemes = core_component::get_plugin_list('theme'); $availablelangs = get_string_manager()->get_list_of_translations(); $transaction = $DB->start_delegated_transaction(); $userids = array(); $createpassword = false; foreach ($params['users'] as $user) { // Make sure that the username doesn't already exist. if ($DB->record_exists('user', array('username' => $user['username'], 'mnethostid' => $CFG->mnet_localhost_id))) { throw new invalid_parameter_exception('Username already exists: ' . $user['username']); } // Make sure auth is valid. if (empty($availableauths[$user['auth']])) { throw new invalid_parameter_exception('Invalid authentication type: ' . $user['auth']); } // Make sure lang is valid. if (empty($availablelangs[$user['lang']])) { throw new invalid_parameter_exception('Invalid language code: ' . $user['lang']); } // Make sure lang is valid. if (!empty($user['theme']) && empty($availablethemes[$user['theme']])) { // Theme is VALUE_OPTIONAL, // so no default value // We need to test if the client sent it // => !empty($user['theme']). throw new invalid_parameter_exception('Invalid theme: ' . $user['theme']); } // Make sure we have a password or have to create one. if (empty($user['password']) && empty($user['createpassword'])) { throw new invalid_parameter_exception('Invalid password: you must provide a password, or set createpassword.'); } $user['confirmed'] = true; $user['mnethostid'] = $CFG->mnet_localhost_id; // Start of user info validation. // Make sure we validate current user info as handled by current GUI. See user/editadvanced_form.php func validation(). if (!validate_email($user['email'])) { throw new invalid_parameter_exception('Email address is invalid: ' . $user['email']); } else { if (empty($CFG->allowaccountssameemail) && $DB->record_exists('user', array('email' => $user['email'], 'mnethostid' => $CFG->mnet_localhost_id))) { throw new invalid_parameter_exception('Email address already exists: ' . $user['email']); } } // End of user info validation. $createpassword = !empty($user['createpassword']); unset($user['createpassword']); if ($createpassword) { $user['password'] = ''; $updatepassword = false; } else { $updatepassword = true; } // Create the user data now! $user['id'] = user_create_user($user, $updatepassword, false); // Custom fields. if (!empty($user['customfields'])) { foreach ($user['customfields'] as $customfield) { // Profile_save_data() saves profile file it's expecting a user with the correct id, // and custom field to be named profile_field_"shortname". $user["profile_field_" . $customfield['type']] = $customfield['value']; } profile_save_data((object) $user); } if ($createpassword) { $userobject = (object) $user; setnew_password_and_mail($userobject); unset_user_preference('create_password', $userobject); set_user_preference('auth_forcepasswordchange', 1, $userobject); } // Trigger event. \core\event\user_created::create_from_userid($user['id'])->trigger(); // Preferences. if (!empty($user['preferences'])) { foreach ($user['preferences'] as $preference) { set_user_preference($preference['type'], $preference['value'], $user['id']); } } $userids[] = array('id' => $user['id'], 'username' => $user['username']); } $transaction->allow_commit(); return $userids; }
/** * Synchronizes user from external db to moodle user table. * * Sync should be done by using idnumber attribute, not username. * You need to pass firstsync parameter to function to fill in * idnumbers if they don't exists in moodle user table. * * Syncing users removes (disables) users that don't exists anymore in external db. * Creates new users and updates coursecreator status of users. * * This implementation is simpler but less scalable than the one found in the LDAP module. * * @param progress_trace $trace * @param bool $do_updates Optional: set to true to force an update of existing accounts * @return int 0 means success, 1 means failure */ function sync_users(progress_trace $trace, $do_updates = false) { global $CFG, $DB; // List external users. $userlist = $this->get_userlist(); // Delete obsolete internal users. if (!empty($this->config->removeuser)) { $suspendselect = ""; if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) { $suspendselect = "AND u.suspended = 0"; } // Find obsolete users. if (count($userlist)) { list($notin_sql, $params) = $DB->get_in_or_equal($userlist, SQL_PARAMS_NAMED, 'u', false); $params['authtype'] = $this->authtype; $sql = "SELECT u.*\n FROM {user} u\n WHERE u.auth=:authtype AND u.deleted=0 AND u.mnethostid=:mnethostid {$suspendselect} AND u.username {$notin_sql}"; } else { $sql = "SELECT u.*\n FROM {user} u\n WHERE u.auth=:authtype AND u.deleted=0 AND u.mnethostid=:mnethostid {$suspendselect}"; $params = array(); $params['authtype'] = $this->authtype; } $params['mnethostid'] = $CFG->mnet_localhost_id; $remove_users = $DB->get_records_sql($sql, $params); if (!empty($remove_users)) { require_once $CFG->dirroot . '/user/lib.php'; $trace->output(get_string('auth_dbuserstoremove', 'auth_db', count($remove_users))); foreach ($remove_users as $user) { if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) { delete_user($user); $trace->output(get_string('auth_dbdeleteuser', 'auth_db', array('name' => $user->username, 'id' => $user->id)), 1); } else { if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) { $updateuser = new stdClass(); $updateuser->id = $user->id; $updateuser->suspended = 1; user_update_user($updateuser, false); $trace->output(get_string('auth_dbsuspenduser', 'auth_db', array('name' => $user->username, 'id' => $user->id)), 1); } } } } unset($remove_users); } if (!count($userlist)) { // Exit right here, nothing else to do. $trace->finished(); return 0; } // Update existing accounts. if ($do_updates) { // Narrow down what fields we need to update. $all_keys = array_keys(get_object_vars($this->config)); $updatekeys = array(); foreach ($all_keys as $key) { if (preg_match('/^field_updatelocal_(.+)$/', $key, $match)) { if ($this->config->{$key} === 'onlogin') { array_push($updatekeys, $match[1]); // The actual key name. } } } unset($all_keys); unset($key); // Only go ahead if we actually have fields to update locally. if (!empty($updatekeys)) { list($in_sql, $params) = $DB->get_in_or_equal($userlist, SQL_PARAMS_NAMED, 'u', true); $params['authtype'] = $this->authtype; $sql = "SELECT u.id, u.username\n FROM {user} u\n WHERE u.auth=:authtype AND u.deleted=0 AND u.username {$in_sql}"; if ($update_users = $DB->get_records_sql($sql, $params)) { $trace->output("User entries to update: " . count($update_users)); foreach ($update_users as $user) { if ($this->update_user_record($user->username, $updatekeys)) { $trace->output(get_string('auth_dbupdatinguser', 'auth_db', array('name' => $user->username, 'id' => $user->id)), 1); } else { $trace->output(get_string('auth_dbupdatinguser', 'auth_db', array('name' => $user->username, 'id' => $user->id)) . " - " . get_string('skipped'), 1); } } unset($update_users); } } } // Create missing accounts. // NOTE: this is very memory intensive and generally inefficient. $suspendselect = ""; if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) { $suspendselect = "AND u.suspended = 0"; } $sql = "SELECT u.id, u.username\n FROM {user} u\n WHERE u.auth=:authtype AND u.deleted='0' AND mnethostid=:mnethostid {$suspendselect}"; $users = $DB->get_records_sql($sql, array('authtype' => $this->authtype, 'mnethostid' => $CFG->mnet_localhost_id)); // Simplify down to usernames. $usernames = array(); if (!empty($users)) { foreach ($users as $user) { array_push($usernames, $user->username); } unset($users); } $add_users = array_diff($userlist, $usernames); unset($usernames); if (!empty($add_users)) { $trace->output(get_string('auth_dbuserstoadd', 'auth_db', count($add_users))); // Do not use transactions around this foreach, we want to skip problematic users, not revert everything. foreach ($add_users as $user) { $username = $user; if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) { if ($old_user = $DB->get_record('user', array('username' => $username, 'deleted' => 0, 'suspended' => 1, 'mnethostid' => $CFG->mnet_localhost_id, 'auth' => $this->authtype))) { $DB->set_field('user', 'suspended', 0, array('id' => $old_user->id)); $trace->output(get_string('auth_dbreviveduser', 'auth_db', array('name' => $username, 'id' => $old_user->id)), 1); // Trigger user_updated event. \core\event\user_updated::create_from_userid($old_user->id)->trigger(); continue; } } // Do not try to undelete users here, instead select suspending if you ever expect users will reappear. // Prep a few params. $user = $this->get_userinfo_asobj($user); $user->username = $username; $user->confirmed = 1; $user->auth = $this->authtype; $user->mnethostid = $CFG->mnet_localhost_id; if (empty($user->lang)) { $user->lang = $CFG->lang; } if (empty($user->calendartype)) { $user->calendartype = $CFG->calendartype; } $user->timecreated = time(); $user->timemodified = $user->timecreated; if ($collision = $DB->get_record_select('user', "username = :username AND mnethostid = :mnethostid AND auth <> :auth", array('username' => $user->username, 'mnethostid' => $CFG->mnet_localhost_id, 'auth' => $this->authtype), 'id,username,auth')) { $trace->output(get_string('auth_dbinsertuserduplicate', 'auth_db', array('username' => $user->username, 'auth' => $collision->auth)), 1); continue; } try { $id = $DB->insert_record('user', $user); // it is truly a new user // Trigger user_created event. \core\event\user_created::create_from_userid($id)->trigger(); $trace->output(get_string('auth_dbinsertuser', 'auth_db', array('name' => $user->username, 'id' => $id)), 1); } catch (moodle_exception $e) { $trace->output(get_string('auth_dbinsertusererror', 'auth_db', $user->username), 1); continue; } // If relevant, tag for password generation. if ($this->is_internal()) { set_user_preference('auth_forcepasswordchange', 1, $id); set_user_preference('create_password', 1, $id); } // Make sure user context is present. context_user::instance($id); } unset($add_users); } $trace->finished(); return 0; }
/** * Sign up a new user ready for confirmation. * Password is passed in plaintext. * * @param object $user new user object * @param boolean $notify print notice with link and terminate */ function user_signup($user, $notify = true) { global $CFG, $DB, $SESSION; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; if (isset($SESSION->wantsurl)) { $wantsurl = $SESSION->wantsurl; } $plainpassword = $user->password; $user->password = hash_internal_user_password($user->password); if (empty($user->calendartype)) { $user->calendartype = $CFG->calendartype; } $user->confirmed = 1; $user->id = user_create_user($user, false, false); user_add_password_history($user->id, $plainpassword); // Save any custom profile field information. profile_save_data($user); // Trigger event. \core\event\user_created::create_from_userid($user->id)->trigger(); $thisuser = authenticate_user_login($user->username, $plainpassword, false, $errorcode); if ($thisuser == false) { print_error('authfailure'); } else { complete_user_login($thisuser); if (isset($wantsurl)) { $urltogo = $wantsurl; if (isset($_SESSION["fiaction"]) && isset($_SESSION["ficourseid"]) && is_numeric($_SESSION["ficourseid"]) && $_SESSION["fiaction"] == "enroll") { $urltogo = $CFG->wwwroot . '/course/enrol.php?id=' . $_SESSION["ficourseid"]; unset($_SESSION['fiaction']); unset($_SESSION['ficourseid']); unset($SESSION->wantsurl); } } else { $urltogo = $CFG->wwwroot . '/'; } redirect($urltogo); } // if ($notify) { // global $CFG, $PAGE, $OUTPUT; // $emailconfirm = get_string('emailconfirm'); // $PAGE->navbar->add($emailconfirm); // $PAGE->set_title($emailconfirm); // $PAGE->set_heading($PAGE->course->fullname); // echo $OUTPUT->header(); // notice(get_string('emailconfirmsent', '', $user->email), "$CFG->wwwroot/index.php"); // } else { // return true; // } }
function user_signup($user, $notify = false) { global $CFG, $DB, $SESSION; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/enrol/token/lib.php'; $lang = empty($user->lang) ? $CFG->lang : $user->lang; $site = get_site(); $supportuser = core_user::get_support_user(); $newpassword = generate_password(); // the token the user entered (which is now validated) $tokenValue = $user->token; $newuser = new stdClass(); $newuser->auth = 'token'; // since technially this auth plugin is a skin $newuser->firstname = $user->firstname; $newuser->lastname = $user->lastname; $newuser->password = hash_internal_user_password($newpassword, false); $newuser->policyagreed = 1; // might need to put this in somewhere $newuser->username = $user->email; $newuser->email = $user->email; $newuser->lastip = getremoteaddr(); $newuser->timecreated = time(); $newuser->timemodified = $newuser->timecreated; $newuser->mnethostid = $CFG->mnet_localhost_id; $newuser = self::truncate_user_obj($newuser); if (($newuser->id = $DB->insert_record('user', $newuser)) === false) { notice(get_string('signupfailure', 'auth_token'), $CFG->wwwroot); return false; } $user = get_complete_user_data('id', $newuser->id); \core\event\user_created::create_from_userid($user->id)->trigger(); // just the query part of post-login redirect $params = empty($SESSION->wantsurl) === true ? '' : parse_url($SESSION->wantsurl, PHP_URL_QUERY); $a = new stdClass(); $a->firstname = $user->firstname; $a->lastname = $user->lastname; $a->username = $user->username; $a->password = $newpassword; $a->sitename = format_string($site->fullname); $a->link = $CFG->wwwroot . '/auth/token/login.php?' . $params; $a->signoff = generate_email_signoff(); $message = (string) new lang_string('signup_userregoemail', 'auth_token', $a, $lang); $subject = format_string($site->fullname) . ': ' . (string) new lang_string('newusernewpasswordsubj', '', $a, $lang); // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber. email_to_user($user, $supportuser, $subject, $message); // log the user in immediately if (($user = authenticate_user_login($user->username, $newpassword)) === false || complete_user_login($user) == null) { notice(get_string('autologinfailure', 'auth_token'), $CFG->wwwroot); return false; } // now, actually DO the enrolment for this course / user $token_plugin = new enrol_token_plugin(); $courseId = 0; $return_to_url = empty($SESSION->wantsurl) === true ? $CFG->wwwroot : $SESSION->wantsurl; $enrolled_ok = $token_plugin->doEnrolment($tokenValue, $courseId, $return_to_url); if ($enrolled_ok == true) { redirect($return_to_url); } return $enrolled_ok == true; }
/** * Test sql_reader::get_events_select_iterator. * @return void */ public function test_events_traversable() { global $DB; $this->resetAfterTest(); $this->preventResetByRollback(); $this->setAdminUser(); set_config('enabled_stores', 'logstore_standard', 'tool_log'); $manager = get_log_manager(true); $stores = $manager->get_readers(); $store = $stores['logstore_standard']; $events = $store->get_events_select_iterator('', array(), '', 0, 0); $this->assertFalse($events->valid()); // Here it should be already closed, but we should be allowed to // over-close it without exception. $events->close(); $user = $this->getDataGenerator()->create_user(); for ($i = 0; $i < 1000; $i++) { \core\event\user_created::create_from_userid($user->id)->trigger(); } $store->flush(); // Check some various sizes get the right number of elements. $this->assertEquals(1, iterator_count($store->get_events_select_iterator('', array(), '', 0, 1))); $this->assertEquals(2, iterator_count($store->get_events_select_iterator('', array(), '', 0, 2))); $iterator = $store->get_events_select_iterator('', array(), '', 0, 500); $this->assertInstanceOf('\\core\\event\\base', $iterator->current()); $this->assertEquals(500, iterator_count($iterator)); $iterator->close(); // Look for non-linear memory usage for the iterator version. $mem = memory_get_usage(); $events = $store->get_events_select('', array(), '', 0, 0); $arraymemusage = memory_get_usage() - $mem; $mem = memory_get_usage(); $eventsit = $store->get_events_select_iterator('', array(), '', 0, 0); $eventsit->close(); $itmemusage = memory_get_usage() - $mem; $this->assertInstanceOf('\\Traversable', $eventsit); $this->assertLessThan($arraymemusage / 10, $itmemusage); set_config('enabled_stores', '', 'tool_log'); get_log_manager(true); }
/** * Create a Moodle user from Azure AD user data. * * @param array $aaddata Array of Azure AD user data. * @return \stdClass An object representing the created Moodle user. */ public function create_user_from_aaddata($aaddata) { global $CFG; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; $creationallowed = $this->check_usercreationrestriction($aaddata); if ($creationallowed !== true) { mtrace('Cannot create user because they do not meet the configured user creation restrictions.'); return false; } // Locate country code. if (isset($aaddata['country'])) { $countries = get_string_manager()->get_list_of_countries(); foreach ($countries as $code => $name) { if ($aaddata['country'] == $name) { $aaddata['country'] = $code; } } if (strlen($aaddata['country']) > 2) { // Limit string to 2 chars to prevent sql error. $aaddata['country'] = substr($aaddata['country'], 0, 2); } } $newuser = (object) ['auth' => 'oidc', 'username' => trim(\core_text::strtolower($aaddata['userPrincipalName'])), 'lang' => 'en', 'confirmed' => 1, 'timecreated' => time(), 'mnethostid' => $CFG->mnet_localhost_id]; $newuser = static::apply_configured_fieldmap($aaddata, $newuser, 'create'); $password = null; $newuser->idnumber = $newuser->username; if (!empty($newuser->email)) { if (email_is_not_allowed($newuser->email)) { unset($newuser->email); } } if (empty($newuser->lang) || !get_string_manager()->translation_exists($newuser->lang)) { $newuser->lang = $CFG->lang; } $newuser->timemodified = $newuser->timecreated; $newuser->id = user_create_user($newuser, false, false); // Save user profile data. profile_save_data($newuser); $user = get_complete_user_data('id', $newuser->id); if (!empty($CFG->{'auth_' . $newuser->auth . '_forcechangepassword'})) { set_user_preference('auth_forcepasswordchange', 1, $user); } // Set the password. update_internal_user_password($user, $password); // Trigger event. \core\event\user_created::create_from_userid($newuser->id)->trigger(); return $user; }
/** * Creates a user * * @throws moodle_exception * @param stdClass $user user to create * @param bool $updatepassword if true, authentication plugin will update password. * @param bool $triggerevent set false if user_created event should not be triggred. * This will not affect user_password_updated event triggering. * @return int id of the newly created user */ function user_create_user($user, $updatepassword = true, $triggerevent = true) { global $DB; // Set the timecreate field to the current time. if (!is_object($user)) { $user = (object) $user; } // Check username. if ($user->username !== core_text::strtolower($user->username)) { throw new moodle_exception('usernamelowercase'); } else { if ($user->username !== core_user::clean_field($user->username, 'username')) { throw new moodle_exception('invalidusername'); } } // Save the password in a temp value for later. if ($updatepassword && isset($user->password)) { // Check password toward the password policy. if (!check_password_policy($user->password, $errmsg)) { throw new moodle_exception($errmsg); } $userpassword = $user->password; unset($user->password); } // Apply default values for user preferences that are stored in users table. if (!isset($user->calendartype)) { $user->calendartype = core_user::get_property_default('calendartype'); } if (!isset($user->maildisplay)) { $user->maildisplay = core_user::get_property_default('maildisplay'); } if (!isset($user->mailformat)) { $user->mailformat = core_user::get_property_default('mailformat'); } if (!isset($user->maildigest)) { $user->maildigest = core_user::get_property_default('maildigest'); } if (!isset($user->autosubscribe)) { $user->autosubscribe = core_user::get_property_default('autosubscribe'); } if (!isset($user->trackforums)) { $user->trackforums = core_user::get_property_default('trackforums'); } if (!isset($user->lang)) { $user->lang = core_user::get_property_default('lang'); } $user->timecreated = time(); $user->timemodified = $user->timecreated; // Validate user data object. $uservalidation = core_user::validate($user); if ($uservalidation !== true) { foreach ($uservalidation as $field => $message) { debugging("The property '{$field}' has invalid data and has been cleaned.", DEBUG_DEVELOPER); $user->{$field} = core_user::clean_field($user->{$field}, $field); } } // Insert the user into the database. $newuserid = $DB->insert_record('user', $user); // Create USER context for this user. $usercontext = context_user::instance($newuserid); // Update user password if necessary. if (isset($userpassword)) { // Get full database user row, in case auth is default. $newuser = $DB->get_record('user', array('id' => $newuserid)); $authplugin = get_auth_plugin($newuser->auth); $authplugin->user_update_password($newuser, $userpassword); } // Trigger event If required. if ($triggerevent) { \core\event\user_created::create_from_userid($newuserid)->trigger(); } return $newuserid; }
} if (isset($usernew->userdepartment) || isset($usernew->usertitle)) { $department = isset($usernew->userdepartment) ? $usernew->userdepartment : 0; $title = isset($usernew->usertitle) ? $usernew->usertitle : 0; assign_department_and_title_to_user($companyid, $department, $title, $usernew->id); } } // Reload from db. $usernew = $DB->get_record('user', array('id' => $usernew->id)); // Trigger events. if ($usercreated) { // Set default message preferences. if (!message_set_default_message_preferences($usernew)) { print_error('cannotsavemessageprefs', 'message'); } $event = \core\event\user_created::create_from_userid($usernew->id); $event->trigger(); } else { $event = \core\event\user_updated::create(array('context' => $systemcontext, 'userid' => $usernew->id, 'relateduserid' => $USER->id)); $event->trigger(); } if ($user->id == $USER->id) { // Override old $USER session variable. foreach ((array) $usernew as $variable => $value) { $USER->{$variable} = $value; } if (!empty($USER->newadminuser)) { unset($USER->newadminuser); // Apply defaults again - some of them might depend on admin user info, backup, roles, etc.. admin_apply_default_settings(null, false); // Redirect to admin/ to continue with installation.
/** * Sign up a new user ready for confirmation. * Password is passed in plaintext. * * @param object $user new user object * @param boolean $notify print notice with link and terminate */ public function user_signup($user, $notify = true) { global $CFG, $DB; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; $plainpassword = $user->password; $user->password = hash_internal_user_password($user->password); $user->mnethostid = $CFG->mnet_localhost_id; if (empty($user->secret)) { $user->secret = ''; } if (empty($user->calendartype)) { $user->calendartype = $CFG->calendartype; } $firstname = strtolower($user->firstname); $lastname = strtolower($user->lastname); $initials = $firstname[0] . $lastname[0]; try { $transaction = $DB->start_delegated_transaction(); do { $username = sprintf($initials . "%04d", rand(1, 9999)); } while ($DB->get_record('user', array("username" => $username), 'id', IGNORE_MISSING)); $user->username = $username; $userdetailstext = "Username: {$username}<br />Password: {$plainpassword}"; $user->id = user_create_user($user, false, false); user_add_password_history($user->id, $plainpassword); // Save any custom profile field information. $user->profile_field_typeofaccount = empty($user->profile_field_typeofaccount) ? 'student' : $user->profile_field_typeofaccount; $user->profile_field_yearlevel = empty($user->profile_field_yearlevel) ? 'N/A' : $user->profile_field_yearlevel; $user->profile_field_yearofbirth = empty($user->profile_field_yearofbirth) ? 'N/A' : $user->profile_field_yearofbirth; $user->profile_field_whereareyoufrom = empty($user->profile_field_whereareyoufrom) ? 'Perth' : $user->profile_field_whereareyoufrom; profile_save_data($user); $record = new stdClass(); $record->studentuserid = $user->id; $record->teacheruserid = $user->id; switch ($user->profile_field_typeofaccount) { case 'wceteacher': $this->add_teacher($user->id); break; case 'adult': case 'student': default: $this->add_student($user->id); break; } // Trigger event. \core\event\user_created::create_from_userid($user->id)->trigger(); // Assuming the both inserts work, we get to the following line. $transaction->allow_commit(); } catch (Exception $e) { $transaction->rollback($e); return false; } if (!send_confirmation_email($user)) { print_error('auth_emailnoemail, auth_email'); } if ($notify) { global $CFG, $PAGE, $OUTPUT; $emailconfirm = get_string('emailconfirm'); $PAGE->navbar->add($emailconfirm); $PAGE->set_title($emailconfirm); $PAGE->set_heading($PAGE->course->fullname); echo $OUTPUT->header(); notice(get_string('signup:emailconfirmsent:text', 'auth_watercorped', $userdetailstext), "{$CFG->wwwroot}/index.php"); } else { return true; } }
// Update mail bounces. useredit_update_bounces($user, $usernew); // Update forum track preference. useredit_update_trackforums($user, $usernew); // Save custom profile fields data. profile_save_data($usernew); // Reload from db. $usernew = $DB->get_record('user', array('id' => $usernew->id)); if ($createpassword) { setnew_password_and_mail($usernew); unset_user_preference('create_password', $usernew); set_user_preference('auth_forcepasswordchange', 1, $usernew); } // Trigger update/create event, after all fields are stored. if ($usercreated) { \core\event\user_created::create_from_userid($usernew->id)->trigger(); } else { \core\event\user_updated::create_from_userid($usernew->id)->trigger(); } if ($user->id == $USER->id) { // Override old $USER session variable. foreach ((array) $usernew as $variable => $value) { if ($variable === 'description' or $variable === 'password') { // These are not set for security nad perf reasons. continue; } $USER->{$variable} = $value; } // Preload custom fields. profile_load_custom_fields($USER); if (!empty($USER->newadminuser)) {
/** * Sign up a new user ready for confirmation. * Password is passed in plaintext. * * @param object $user new user object * @param boolean $notify print notice with link and terminate */ public function user_signup($user, $notify = true) { global $CFG, $DB; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/user/lib.php'; $plainpassword = $user->password; $user->password = hash_internal_user_password($user->password); if (empty($user->calendartype)) { $user->calendartype = $CFG->calendartype; } $user->id = user_create_user($user, false, false); user_add_password_history($user->id, $plainpassword); // Save any custom profile field information. profile_save_data($user); // Trigger event. \core\event\user_created::create_from_userid($user->id)->trigger(); if (!send_confirmation_email($user)) { print_error('auth_emailnoemail, auth_email'); } if ($notify) { global $CFG, $PAGE, $OUTPUT; $emailconfirm = get_string('emailconfirm'); $PAGE->navbar->add($emailconfirm); $PAGE->set_title($emailconfirm); $PAGE->set_heading($PAGE->course->fullname); echo $OUTPUT->header(); notice(get_string('emailconfirmsent', '', $user->email), "{$CFG->wwwroot}/index.php"); } else { return true; } }
/** * Create a user, role and token. Return the created token id. * @param string $rolename the role to create/use - will be assign to the user * @param string $servicename service to link to the new token * @param string $username user to link to the new token * @param array $capabilities list of capabilities to add to the role * @return object created token */ function create_hub_token($rolename, $servicename, $username, $capabilities) { global $CFG, $DB; //requires libraries require_once $CFG->dirroot . '/user/lib.php'; //check the hidden service //because we cannot know the id of the service, we consider that hidden services have unique name! $services = $DB->get_records('external_services', array('name' => $servicename)); //if ever we have two hidden service with the same name, it's due to a programmation error if (count($services) > 1) { throw new moodle_exception('hiddenservicewithsamename'); } if (count($services) < 1) { throw new moodle_exception('unknownservicename'); } $role = $DB->get_record('role', array('name' => $rolename)); if (empty($role)) { $roleid = create_role($rolename, clean_param($rolename, PARAM_ALPHAEXT), get_string('hubwsroledescription', 'local_hub'), '', true); } else { $roleid = $role->id; } //check and create a user $user = $DB->get_record('user', array('username' => $username, 'idnumber' => $username)); if (empty($user)) { $user = new stdClass(); $user->username = $username; $user->firstname = $username; $user->lastname = get_string('donotdeleteormodify', 'local_hub'); $user->password = ''; //login no authorised with webservice authentication $user->auth = 'webservice'; $user->confirmed = 1; //need to be confirmed otherwise got deleted $user->idnumber = $username; $user->mnethostid = 1; $user->description = get_string('hubwsuserdescription', 'local_hub'); $user->timecreated = time(); $user->timemodified = $user->timecreated; // Add extra fields to prevent a debug notice. $userfields = get_all_user_name_fields(); foreach ($userfields as $key => $field) { if (!isset($user->{$key})) { $user->{$key} = null; } } // Insert the "site" user into the database. $user->id = $DB->insert_record('user', $user); \core\event\user_created::create_from_userid($user->id)->trigger(); add_to_log(SITEID, 'user', get_string('create'), '/view.php?id=' . $user->id, fullname($user)); } //check and assign the role to user $context = context_system::instance(); $existingroleassign = $DB->get_records('role_assignments', array('roleid' => $roleid, 'contextid' => $context->id, 'userid' => $user->id), 'id'); if (empty($existingroleassign)) { role_assign($roleid, $user->id, $context->id); } //check and assign capabilities to role $capabilities[] = 'webservice/xmlrpc:use'; if (empty($role)) { $role = new stdClass(); $role->id = $roleid; } $rolecapabilities = get_capabilities_from_role_on_context($role, $context); if (!empty($capabilities)) { foreach ($capabilities as $capability) { $capabilityassigned = false; foreach ($rolecapabilities as $rolecapability) { if ($rolecapability->capability == $capability) { $capabilityassigned = true; break; } } if (!$capabilityassigned) { assign_capability($capability, CAP_ALLOW, $roleid, $context->id); } } } //enable the hidden service and assign it to the user foreach ($services as $service) { //there should be only one service into the array!!! //checked at beginning of the function $serviceid = $service->id; //if no hidden token was created for this service, we need to enable it if (!$service->enabled) { $service->enabled = 1; $DB->update_record('external_services', $service); } $serviceuser = $DB->get_record('external_services_users', array('externalserviceid' => $serviceid, 'userid' => $user->id)); if (empty($serviceuser)) { $serviceuser = new stdClass(); $serviceuser->externalserviceid = $serviceid; $serviceuser->userid = $user->id; $serviceuser->timecreated = time(); $DB->insert_record('external_services_users', $serviceuser); } } //check and create a token $resulttoken = new stdClass(); $resulttoken->userid = $user->id; $resulttoken->tokentype = EXTERNAL_TOKEN_PERMANENT; $resulttoken->externalserviceid = $serviceid; $resulttoken->contextid = $context->id; $resulttoken->creatorid = $user->id; $token = $DB->get_record('external_tokens', (array) $resulttoken); if (empty($token)) { $resulttoken->timecreated = time(); $resulttoken->token = md5(uniqid(rand(), 1)); $tokenid = $DB->insert_record('external_tokens', $resulttoken); $resulttoken->id = $tokenid; } else { //throw new moodle_exception('hiddentokenalreadyexist'); // Just return the found token instead of throwing an error. $resulttoken = $token; } return $resulttoken; }