/** * Sets the specified account settings to the current user. * A table with | Setting label | value | is expected. * * @Given /^I set the following account settings values:$/ * @param TableNode $table */ public function i_set_account_settings(TableNode $table) { global $USER; $prefs = array(); foreach ($table->getHash() as $accountpref) { $prefs[$accountpref['field']] = $accountpref['value']; } // Validate the settings if (isset($prefs['urlid']) && get_config('cleanurls') && $prefs['urlid'] != $USER->get('urlid')) { if (strlen($prefs['urlid']) < 3) { throw new Exception("Invalid urlid: " . get_string('rule.minlength.minlength', 'pieforms', 3)); } else { if (record_exists('usr', 'urlid', $prefs['urlid'])) { throw new Exception("Invalid urlid: " . get_string('urlalreadytaken', 'account')); } } } if (get_config('allowmobileuploads')) { foreach ($prefs['mobileuploadtoken'] as $k => $text) { if (strlen($text) > 0 && !preg_match('/^[a-zA-Z0-9 !@#$%^&*()\\-_=+\\[{\\]};:\'",<\\.>\\/?]{6,}$/', $text)) { throw new Exception("Invalid mobileuploadtoken: " . get_string('badmobileuploadtoken', 'account')); } } } // Update user's account settings db_begin(); // use this as looping through values is not safe. $expectedprefs = expected_account_preferences(); if (isset($prefs['maildisabled']) && $prefs['maildisabled'] == 0 && get_account_preference($USER->get('id'), 'maildisabled') == 1) { // Reset the sent and bounce counts otherwise mail will be disabled // on the next send attempt $u = new StdClass(); $u->email = $USER->get('email'); $u->id = $USER->get('id'); update_bounce_count($u, true); update_send_count($u, true); } // Remember the user's language & theme prefs, so we can reload the page if they change them $oldlang = $USER->get_account_preference('lang'); $oldtheme = $USER->get_account_preference('theme'); $oldgroupsideblockmaxgroups = $USER->get_account_preference('groupsideblockmaxgroups'); $oldgroupsideblocksortby = $USER->get_account_preference('groupsideblocksortby'); if (get_config('allowmobileuploads') && isset($prefs['mobileuploadtoken'])) { // Make sure the mobile token is formatted / saved correctly $prefs['mobileuploadtoken'] = array_filter($prefs['mobileuploadtoken']); $new_token_pref = '|' . join('|', $prefs['mobileuploadtoken']) . '|'; $USER->set_account_preference('mobileuploadtoken', $new_token_pref); unset($prefs['mobileuploadtoken']); } // Set user account preferences foreach ($expectedprefs as $eprefkey => $epref) { if (isset($prefs[$eprefkey]) && $prefs[$eprefkey] !== get_account_preference($USER->get('id'), $eprefkey)) { $USER->set_account_preference($eprefkey, $prefs[$eprefkey]); } } db_commit(); }
function edituser_site_submit(Pieform $form, $values) { global $USER, $authobj, $SESSION; if (!($user = get_record('usr', 'id', $values['id']))) { return false; } if (is_using_probation()) { // Value should be between 0 and 10 inclusive $user->probation = ensure_valid_probation_points($values['probationpoints']); } if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) { $user->quota = $values['quota']; // check if the user has gone over the quota notify limit $quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit'); if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) { $quotanotifylimit = 100; } $user->quotausedpercent = $user->quotaused / $user->quota * 100; $overlimit = false; if ($quotanotifylimit <= $user->quotausedpercent) { $overlimit = true; } $notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $user->id); if ($overlimit && '1' !== $notified) { require_once get_config('docroot') . 'artefact/file/lib.php'; ArtefactTypeFile::notify_users_threshold_exceeded(array($user), false); // no need to email admin as we can alert them right now $SESSION->add_error_msg(get_string('useroverquotathreshold', 'artefact.file', display_name($user))); } else { if ($notified && !$overlimit) { set_account_preference($user->id, 'quota_exceeded_notified', false); } } } $unexpire = $user->expiry && strtotime($user->expiry) < time() && (empty($values['expiry']) || $values['expiry'] > time()); $newexpiry = db_format_timestamp($values['expiry']); if ($user->expiry != $newexpiry) { $user->expiry = $newexpiry; if ($unexpire) { $user->expirymailsent = 0; $user->lastaccess = db_format_timestamp(time()); } } // Try to kick the user from any active login sessions, before saving data. require_once get_config('docroot') . 'auth/session.php'; remove_user_sessions($user->id); if ($USER->get('admin')) { // Not editable by institutional admins $user->staff = (int) ($values['staff'] == 'on'); $user->admin = (int) ($values['admin'] == 'on'); if ($user->admin) { activity_add_admin_defaults(array($user->id)); } } if ($values['maildisabled'] == 0 && get_account_preference($user->id, 'maildisabled') == 1) { // Reset the sent and bounce counts otherwise mail will be disabled // on the next send attempt $u = new StdClass(); $u->email = $user->email; $u->id = $user->id; update_bounce_count($u, true); update_send_count($u, true); } set_account_preference($user->id, 'maildisabled', $values['maildisabled']); // process the change of the authinstance and or the remoteuser if (isset($values['authinstance']) && isset($values['remoteusername'])) { // Authinstance can be changed by institutional admins if both the // old and new authinstances belong to the admin's institutions $authinst = get_records_select_assoc('auth_instance', 'id = ? OR id = ?', array($values['authinstance'], $user->authinstance)); // But don't bother if the auth instance doesn't take a remote username $authobj = AuthFactory::create($values['authinstance']); if ($USER->get('admin') || $USER->is_institutional_admin($authinst[$values['authinstance']]->institution) && ($USER->is_institutional_admin($authinst[$user->authinstance]->institution) || $user->authinstance == 1)) { if ($authobj->needs_remote_username()) { // determine the current remoteuser $current_remotename = get_field('auth_remote_user', 'remoteusername', 'authinstance', $user->authinstance, 'localusr', $user->id); if (!$current_remotename) { $current_remotename = $user->username; } // if the remoteuser is empty if (strlen(trim($values['remoteusername'])) == 0) { delete_records('auth_remote_user', 'authinstance', $user->authinstance, 'localusr', $user->id); } // what should the new remoteuser be $new_remoteuser = get_field('auth_remote_user', 'remoteusername', 'authinstance', $values['authinstance'], 'localusr', $user->id); // save the remotename for the target existence check $target_remotename = $new_remoteuser; if (!$new_remoteuser) { $new_remoteuser = $user->username; } if (strlen(trim($values['remoteusername'])) > 0) { // value changed on page - use it if ($values['remoteusername'] != $current_remotename) { $new_remoteuser = $values['remoteusername']; } } // only update remote name if the input actually changed on the page or it doesn't yet exist if ($current_remotename != $new_remoteuser || !$target_remotename) { // only remove the ones related to this traget authinstance as we now allow multiple // for dual login mechanisms delete_records('auth_remote_user', 'authinstance', $values['authinstance'], 'localusr', $user->id); insert_record('auth_remote_user', (object) array('authinstance' => $values['authinstance'], 'remoteusername' => $new_remoteuser, 'localusr' => $user->id)); } } // update the ai on the user master $user->authinstance = $values['authinstance']; // update the global $authobj to match the new authinstance // this is used by the password/username change methods // if either/both has been requested at the same time $authobj = AuthFactory::create($user->authinstance); } } // Only change the pw if the new auth instance allows for it if (method_exists($authobj, 'change_password')) { $user->passwordchange = (int) (isset($values['passwordchange']) && $values['passwordchange'] == 'on' ? 1 : 0); if (isset($values['password']) && $values['password'] !== '') { $userobj = new User(); $userobj = $userobj->find_by_id($user->id); $user->password = $authobj->change_password($userobj, $values['password']); $user->salt = $userobj->salt; unset($userobj); } } else { // inform the user that the chosen auth instance doesn't allow password changes // but only if they tried changing it if (isset($values['password']) && $values['password'] !== '') { $SESSION->add_error_msg(get_string('passwordchangenotallowed', 'admin')); // Set empty pw with salt $user->password = ''; $user->salt = auth_get_random_salt(); } } if (isset($values['username']) && $values['username'] !== '') { $userobj = new User(); $userobj = $userobj->find_by_id($user->id); if ($userobj->username != $values['username']) { // Only change the username if the auth instance allows for it if (method_exists($authobj, 'change_username')) { // check the existence of the chosen username try { if ($authobj->user_exists($values['username'])) { // set an error message if it is already in use $SESSION->add_error_msg(get_string('usernameexists', 'account')); } } catch (AuthUnknownUserException $e) { // update the username otherwise $user->username = $authobj->change_username($userobj, $values['username']); } } else { // inform the user that the chosen auth instance doesn't allow username changes $SESSION->add_error_msg(get_string('usernamechangenotallowed', 'admin')); } } unset($userobj); } // OVERWRITE 4: insert if (isset($values['email']) && !empty($values['email']) && $values['email'] != $user->email) { global $CFG; $user->email = $values['email']; $mhr_user = $CFG->current_app->getUserById($user->id); $mhr_user->setEmailAddress($values['email']); } // END OVERWRITE 4 db_begin(); update_record('usr', $user); delete_records('usr_tag', 'usr', $user->id); if (is_array($values['tags'])) { $values['tags'] = check_case_sensitive($values['tags'], 'usr_tag'); foreach (array_unique($values['tags']) as $tag) { if (empty($tag)) { continue; } insert_record('usr_tag', (object) array('usr' => $user->id, 'tag' => strtolower($tag))); } } db_commit(); $SESSION->add_ok_msg(get_string('usersitesettingschanged', 'admin')); redirect('/admin/users/edit.php?id=' . $user->id); }
/** * Process an incoming email * * @param string $address the email address to process */ function process_email($address) { $email = new StdClass(); if (strlen($address) <= 30) { log_debug('-- Email address not long enough to contain valid data.'); return $email; } if (!strstr($address, '@')) { log_debug('-- Email address does not contain @.'); return $email; } list($email->localpart, $email->domain) = explode('@', $address); // The prefix is stored in the first four characters $email->prefix = substr($email->localpart, 0, 4); // The type of message received is a one letter code $email->type = substr($email->localpart, 4, 1); // The userid should be available immediately afterwards list(, $email->userid) = unpack('V', base64_decode(substr($email->localpart, 5, 8))); // Any additional arguments $email->args = substr($email->localpart, 13, -16); // And a hash of the intended recipient for authentication $email->addresshash = substr($email->localpart, -16); if (!$email->userid) { log_debug('-- no userid associated with this email address'); return $email; } switch ($email->type) { case 'B': // E-mail bounces if ($user = get_record_select('artefact_internal_profile_email', '"owner" = ? AND principal = 1', array($email->userid))) { $mailprefix = get_config('bounceprefix'); $maildomain = get_config('bouncedomain'); $installation_key = get_config('installation_key'); // check the half md5 of their email $md5check = substr(md5($mailprefix . $user->email . $installation_key), 0, 16); $user->id = $user->owner; if ($md5check == substr($email->addresshash, -16)) { update_bounce_count($user); check_overcount($user); } // else maybe they've already changed their email address } break; // No more cases yet } return $email; }
function edituser_site_submit(Pieform $form, $values) { if (!($user = get_record('usr', 'id', $values['id']))) { return false; } if (isset($values['password']) && $values['password'] !== '') { $user->password = $values['password']; $user->salt = ''; } $user->passwordchange = (int) ($values['passwordchange'] == 'on'); $user->quota = $values['quota']; $user->expiry = db_format_timestamp($values['expiry']); global $USER; if ($USER->get('admin')) { // Not editable by institutional admins $user->staff = (int) ($values['staff'] == 'on'); $user->admin = (int) ($values['admin'] == 'on'); if ($user->admin) { activity_add_admin_defaults(array($user->id)); } } if ($values['maildisabled'] == 0 && get_account_preference($user->id, 'maildisabled') == 1) { // Reset the sent and bounce counts otherwise mail will be disabled // on the next send attempt $u = new StdClass(); $u->email = $user->email; $u->id = $user->id; update_bounce_count($u, true); update_send_count($u, true); } set_account_preference($user->id, 'maildisabled', $values['maildisabled']); // Authinstance can be changed by institutional admins if both the // old and new authinstances belong to the admin's institutions $remotename = get_field('auth_remote_user', 'remoteusername', 'authinstance', $user->authinstance, 'localusr', $user->id); if (!$remotename) { $remotename = $user->username; } if (isset($values['authinstance']) && ($values['authinstance'] != $user->authinstance || isset($values['remoteusername']) && $values['remoteusername'] != $remotename)) { $authinst = get_records_select_assoc('auth_instance', 'id = ? OR id = ?', array($values['authinstance'], $user->authinstance)); if ($USER->get('admin') || $USER->is_institutional_admin($authinst[$values['authinstance']]->institution) && $USER->is_institutional_admin($authinst[$user->authinstance]->institution)) { delete_records('auth_remote_user', 'localusr', $user->id); if ($authinst[$values['authinstance']]->authname != 'internal') { if (isset($values['remoteusername']) && strlen($values['remoteusername']) > 0) { $un = $values['remoteusername']; } else { $un = $remotename; } insert_record('auth_remote_user', (object) array('authinstance' => $values['authinstance'], 'remoteusername' => $un, 'localusr' => $user->id)); } $user->authinstance = $values['authinstance']; } } update_record('usr', $user); redirect('/admin/users/edit.php?id=' . $user->id); }
/** * Process an incoming email * * @param string $address the email address to process */ function process_email($address) { $email = new StdClass(); if (strlen($address) <= 30) { log_debug('-- Email address not long enough to contain valid data.'); return $email; } if (!strstr($address, '@')) { log_debug('-- Email address does not contain @.'); return $email; } $mailprefix = get_config('bounceprefix'); $prefixlength = strlen($mailprefix); list($email->localpart, $email->domain) = explode('@', $address); // The prefix is stored in the first characters denoted by $prefixlength $email->prefix = substr($email->localpart, 0, $prefixlength); // The type of message received is a one letter code $email->type = substr($email->localpart, $prefixlength, 1); // The userid should be available immediately afterwards // Postfix and other smtp servers don't like the use of / in the extension part of an email // We may of replaced it with another valid email character which isn't in base64, namely '-' // If we didn't, then the preg_replace won't do anything list(, $email->userid) = unpack('V', base64_decode(preg_replace('/-/', '/', substr($email->localpart, $prefixlength + 1, 8)))); // Any additional arguments $email->args = substr($email->localpart, $prefixlength + 9, -16); // And a hash of the intended recipient for authentication $email->addresshash = substr($email->localpart, -16); if (!$email->userid) { log_debug('-- no userid associated with this email address'); return $email; } switch ($email->type) { case 'B': // E-mail bounces if ($user = get_record_select('artefact_internal_profile_email', '"owner" = ? AND principal = 1', array($email->userid))) { $maildomain = get_config('bouncedomain'); $installation_key = get_config('installation_key'); // check the half md5 of their email $md5check = substr(md5($mailprefix . $user->email . $installation_key), 0, 16); $user->id = $user->owner; if ($md5check == substr($email->addresshash, -16)) { update_bounce_count($user); check_overcount($user); } // else maybe they've already changed their email address } break; // No more cases yet } return $email; }
function accountprefs_submit(Pieform $form, $values) { global $USER, $SESSION; $authobj = AuthFactory::create($USER->authinstance); db_begin(); $ispasswordchanged = false; if (isset($values['password1']) && $values['password1'] !== '') { global $authclass; $password = $authobj->change_password($USER, $values['password1']); $USER->password = $password; $USER->passwordchange = 0; $USER->commit(); $ispasswordchanged = true; } // use this as looping through values is not safe. $expectedprefs = expected_account_preferences(); if ($values['maildisabled'] == 0 && get_account_preference($USER->get('id'), 'maildisabled') == 1) { // Reset the sent and bounce counts otherwise mail will be disabled // on the next send attempt $u = new StdClass(); $u->email = $USER->get('email'); $u->id = $USER->get('id'); update_bounce_count($u, true); update_send_count($u, true); } // Remember the user's language & theme prefs, so we can reload the page if they change them $oldlang = $USER->get_account_preference('lang'); $oldtheme = $USER->get_account_preference('theme'); $oldgroupsideblockmaxgroups = $USER->get_account_preference('groupsideblockmaxgroups'); $oldgroupsideblocksortby = $USER->get_account_preference('groupsideblocksortby'); if (get_config('allowmobileuploads')) { // Make sure the mobile token is formatted / saved correctly $values['mobileuploadtoken'] = array_filter($values['mobileuploadtoken']); $new_token_pref = empty($values['mobileuploadtoken']) ? null : '|' . join('|', $values['mobileuploadtoken']) . '|'; $USER->set_account_preference('mobileuploadtoken', $new_token_pref); unset($values['mobileuploadtoken']); } // Set user account preferences foreach ($expectedprefs as $eprefkey => $epref) { if (isset($values[$eprefkey]) && $values[$eprefkey] !== get_account_preference($USER->get('id'), $eprefkey)) { $USER->set_account_preference($eprefkey, $values[$eprefkey]); } } $returndata = array(); if (isset($values['username']) && $values['username'] != $USER->get('username')) { $USER->username = $values['username']; $USER->commit(); $returndata['username'] = $values['username']; } $reload = false; if (get_config('cleanurls') && isset($values['urlid']) && $values['urlid'] != $USER->get('urlid')) { $USER->urlid = $values['urlid']; $USER->commit(); $reload = true; } if ($ispasswordchanged) { // Destroy other sessions of the user require_once get_config('docroot') . 'auth/session.php'; remove_user_sessions($USER->get('id')); } db_commit(); $returndata['message'] = get_string('prefssaved', 'account'); if (isset($values['theme']) && $values['theme'] != $oldtheme) { $USER->update_theme(); $reload = true; } if (isset($values['lang']) && $values['lang'] != $oldlang) { // The session language pref is used when the user has no user pref, // and when logged out. $SESSION->set('lang', $values['lang']); $returndata['message'] = get_string_from_language($values['lang'], 'prefssaved', 'account'); $reload = true; } if (isset($values['groupsideblockmaxgroups']) && $values['groupsideblockmaxgroups'] != $oldgroupsideblockmaxgroups) { $reload = true; } if ($values['groupsideblocksortby'] != $oldgroupsideblocksortby) { $reload = true; } $reload = plugin_account_prefs_submit($form, $values) || $reload; if (!empty($reload)) { // Use PIEFORM_CANCEL here to force a page reload and show the new language. $returndata['location'] = get_config('wwwroot') . 'account/index.php'; $SESSION->add_ok_msg($returndata['message']); $form->json_reply(PIEFORM_CANCEL, $returndata); } $form->json_reply(PIEFORM_OK, $returndata); }
function accountprefs_submit(Pieform $form, $values) { global $USER; $authobj = AuthFactory::create($USER->authinstance); db_begin(); if (isset($values['password1']) && $values['password1'] !== '') { global $authclass; $password = $authobj->change_password($USER, $values['password1']); $USER->password = $password; $USER->passwordchange = 0; $USER->commit(); } // use this as looping through values is not safe. $expectedprefs = expected_account_preferences(); if ($values['maildisabled'] == 0 && get_account_preference($USER->get('id'), 'maildisabled') == 1) { // Reset the sent and bounce counts otherwise mail will be disabled // on the next send attempt $u = new StdClass(); $u->email = $USER->get('email'); $u->id = $USER->get('id'); update_bounce_count($u, true); update_send_count($u, true); } foreach (array_keys($expectedprefs) as $pref) { if (isset($values[$pref])) { $USER->set_account_preference($pref, $values[$pref]); } } $returndata = array(); if (isset($values['username']) && $values['username'] != $USER->get('username')) { $USER->username = $values['username']; $USER->commit(); $returndata['username'] = $values['username']; } db_commit(); $returndata['message'] = get_string('prefssaved', 'account'); $form->json_reply(PIEFORM_OK, $returndata); }