/** * Creates a new user * @param string $user_name * @param string $password * @param string $real_name * @param string $jabber_id * @param string $email * @param integer $notify_type * @param integer $time_zone * @param integer $group_in * @access public * @return mixed false if username is already taken, otherwise integer uid * @version 1.0 * @notes This function does not have any permission checks (checked elsewhere) */ function create_user($user_name, $password, $real_name, $jabber_id, $email, $notify_type, $time_zone, $group_in) { global $fs, $db, $baseurl; $user_name = Backend::clean_username($user_name); // Limit lengths $real_name = substr(trim($real_name), 0, 100); // Remove doubled up spaces and control chars $real_name = preg_replace('![\\x00-\\x1f\\s]+!u', ' ', $real_name); // Check to see if the username is available $username_exists = $db->x->GetOne('SELECT COUNT(*) FROM {users} WHERE user_name = ?', null, $user_name); if ($username_exists) { return false; } $auto = false; // Autogenerate a password if (!$password) { $auto = true; $password = substr(md5(uniqid(mt_rand(), true)), 0, mt_rand(8, 12)); } $salt = md5(uniqid(mt_rand(), true)); $userdata = array('user_name' => $user_name, 'user_pass' => Flyspray::cryptPassword($password, $salt), 'password_salt' => $salt, 'real_name' => $real_name, 'jabber_id' => $jabber_id, 'email_address' => $email, 'notify_type' => $notify_type, 'time_zone' => $time_zone, 'register_date' => time(), 'account_enabled' => 1); $db->x->autoExecute('{users}', $userdata); // Get this user's id for the record $uid = Flyspray::UserNameToId($user_name); // Now, create a new record in the users_in_groups table $db->x->autoExecute('{users_in_groups}', array('user_id' => $uid, 'group_id' => $group_in)); Flyspray::logEvent(0, 30, serialize(Flyspray::getUserDetails($uid))); // Add user to project groups $sql = $db->x->getAll('SELECT anon_group FROM {projects} WHERE anon_group != 0'); if (count($sql)) { $stmt = $db->x->autoPrepare('{users_in_groups}', array('user_id', 'group_id')); foreach ($sql as $row) { $stmt->execute(array($uid, $row['anon_group'])); } $stmt->free(); } $varnames = array('iwatch', 'atome', 'iopened'); $toserialize = array('string' => null, 'type' => array(''), 'sev' => array(''), 'due' => array(''), 'dev' => null, 'cat' => array(''), 'status' => array('open'), 'order' => null, 'sort' => null, 'percent' => array(''), 'opened' => null, 'search_in_comments' => null, 'search_for_all' => null, 'reported' => array(''), 'only_primary' => null, 'only_watched' => null); foreach ($varnames as $tmpname) { if ($tmpname == 'iwatch') { $tmparr = array('only_watched' => '1'); } elseif ($tmpname == 'atome') { $tmparr = array('dev' => $uid); } elseif ($tmpname == 'iopened') { $tmparr = array('opened' => $uid); } ${$tmpname} = $tmparr + $toserialize; } // Now give him his default searches $stmt = $db->x->autoPrepare('{searches}', array('user_id', 'name', 'search_string', 'time')); $params = array(array($uid, L('taskswatched'), serialize($iwatch), time()), array($uid, L('assignedtome'), serialize($atome), time()), array($uid, L('tasksireported'), serialize($iopened), time())); $db->x->executeMultiple($stmt, $params); $stmt->free(); if ($jabber_id) { Notifications::JabberRequestAuth($jabber_id); } // Send a user his details (his username might be altered, password auto-generated) if ($fs->prefs['notify_registration']) { $admins = $db->x->GetCol('SELECT user_id FROM {users_in_groups} WHERE group_id = 1'); Notifications::send($admins, ADDRESS_USER, NOTIFY_NEW_USER, array($baseurl, $user_name, $real_name, $email, $jabber_id, $password, $auto)); } return $uid; }
/** * Creates a new user * @param string $user_name * @param string $password * @param string $real_name * @param string $jabber_id * @param string $email * @param integer $notify_type * @param integer $time_zone * @param integer $group_in * @access public * @return bool false if username is already taken * @version 1.0 * @notes This function does not have any permission checks (checked elsewhere) */ public static function create_user($user_name, $password, $real_name, $jabber_id, $email, $notify_type, $time_zone, $group_in, $enabled, $oauth_uid = '', $oauth_provider = '', $profile_image = '') { global $fs, $db, $notify, $baseurl; $user_name = Backend::clean_username($user_name); // TODO Handle this whole create_user better concerning return false. Why did it fail? if (empty($user_name)) { return false; } // Limit length $real_name = substr(trim($real_name), 0, 100); // Remove doubled up spaces and control chars $real_name = preg_replace('![\\x00-\\x1f\\s]+!u', ' ', $real_name); // Check to see if the username is available $sql = $db->Query('SELECT COUNT(*) FROM {users} WHERE user_name = ?', array($user_name)); if ($db->fetchOne($sql)) { return false; } $auto = false; // Autogenerate a password if (!$password) { $auto = true; $password = substr(md5(uniqid(mt_rand(), true)), 0, mt_rand(8, 12)); } // Check the emails before inserting anything to database. $emailList = explode(';', $email); foreach ($emailList as $mail) { //Still need to do: check email $count = $db->Query("SELECT COUNT(*) FROM {user_emails} WHERE email_address = ?", array($mail)); $count = $db->fetchOne($count); if ($count > 0) { Flyspray::show_error("Email address has alredy been taken"); return false; } } $db->Query("INSERT INTO {users}\n ( user_name, user_pass, real_name, jabber_id, profile_image, magic_url,\n email_address, notify_type, account_enabled,\n tasks_perpage, register_date, time_zone, dateformat,\n dateformat_extended, oauth_uid, oauth_provider, lang_code)\n VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, 25, ?, ?, ?, ?, ?, ?, ?)", array($user_name, Flyspray::cryptPassword($password), $real_name, strtolower($jabber_id), $profile_image, '', strtolower($email), $notify_type, $enabled, time(), $time_zone, '', '', $oauth_uid, $oauth_provider, $fs->prefs['lang_code'])); // Get this user's id for the record $uid = Flyspray::UserNameToId($user_name); foreach ($emailList as $mail) { if ($mail != '') { $db->Query("INSERT INTO {user_emails}(id,email_address,oauth_uid,oauth_provider) VALUES (?,?,?,?)", array($uid, strtolower($mail), $oauth_uid, $oauth_provider)); } } // Now, create a new record in the users_in_groups table $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) VALUES (?, ?)', array($uid, $group_in)); Flyspray::logEvent(0, 30, serialize(Flyspray::getUserDetails($uid))); $varnames = array('iwatch', 'atome', 'iopened'); $toserialize = array('string' => NULL, 'type' => array(''), 'sev' => array(''), 'due' => array(''), 'dev' => NULL, 'cat' => array(''), 'status' => array('open'), 'order' => NULL, 'sort' => NULL, 'percent' => array(''), 'opened' => NULL, 'search_in_comments' => NULL, 'search_for_all' => NULL, 'reported' => array(''), 'only_primary' => NULL, 'only_watched' => NULL); foreach ($varnames as $tmpname) { if ($tmpname == 'iwatch') { $tmparr = array('only_watched' => '1'); } elseif ($tmpname == 'atome') { $tmparr = array('dev' => $uid); } elseif ($tmpname == 'iopened') { $tmparr = array('opened' => $uid); } ${$tmpname} = $tmparr + $toserialize; } // Now give him his default searches $db->Query('INSERT INTO {searches} (user_id, name, search_string, time) VALUES (?, ?, ?, ?)', array($uid, L('taskswatched'), serialize($iwatch), time())); $db->Query('INSERT INTO {searches} (user_id, name, search_string, time) VALUES (?, ?, ?, ?)', array($uid, L('assignedtome'), serialize($atome), time())); $db->Query('INSERT INTO {searches} (user_id, name, search_string, time) VALUES (?, ?, ?, ?)', array($uid, L('tasksireported'), serialize($iopened), time())); if ($jabber_id) { Notifications::JabberRequestAuth($jabber_id); } // Send a user his details (his username might be altered, password auto-generated) // dont send notifications if the user logged in using oauth if (!$oauth_provider) { $recipients = self::GetAdminAddresses(); $newuser = array(); // Add the right message here depending on $enabled. if ($enabled === 0) { $newuser[0][$email] = array('recipient' => $email, 'lang' => $fs->prefs['lang_code']); } else { $newuser[0][$email] = array('recipient' => $email, 'lang' => $fs->prefs['lang_code']); } // Notify the appropriate users $notify->Create(NOTIFY_NEW_USER, null, array($baseurl, $user_name, $real_name, $email, $jabber_id, $password, $auto), $recipients, NOTIFY_EMAIL); // And also the new user $notify->Create(NOTIFY_OWN_REGISTRATION, null, array($baseurl, $user_name, $real_name, $email, $jabber_id, $password, $auto), $newuser, NOTIFY_EMAIL); } // If the account is created as not enabled, no matter what any // preferences might say or how the registration was made in first // place, it MUST be first approved by an admin. And a small // work-around: there's no field for email, so we use reason_given // for that purpose. if ($enabled === 0) { Flyspray::AdminRequest(3, 0, 0, $uid, $email); } return true; }
Flyspray::show_error(L('emailverificationwrong')); break; } $email = strtolower(Post::val('email_address')); $jabber_id = strtolower(Post::val('jabber_id')); //email is mandatory if (!$email || !Flyspray::check_email($email)) { Flyspray::show_error(L('novalidemail')); break; } //jabber_id is optional if ($jabber_id && !Jabber::check_jid($jabber_id)) { Flyspray::show_error(L('novalidjabber')); break; } $user_name = Backend::clean_username(Post::val('user_name')); // Limit length $real_name = substr(trim(Post::val('real_name')), 0, 100); // Remove doubled up spaces and control chars $real_name = preg_replace('![\\x00-\\x1f\\s]+!u', ' ', $real_name); if (!$user_name || empty($user_name) || !$real_name) { Flyspray::show_error(L('entervalidusername')); break; } // Delete registration codes older than 24 hours $yesterday = time() - 86400; $db->Query('DELETE FROM {registrations} WHERE reg_time < ?', array($yesterday)); $sql = $db->Query('SELECT COUNT(*) FROM {users} u, {registrations} r WHERE u.user_name = ? OR r.user_name = ?', array($user_name, $user_name)); if ($db->fetchOne($sql)) { Flyspray::show_error(L('usernametaken'));
<?php /********************************************************\ | User authentication (no output) | | ~~~~~~~~~~~~~~~~~~~ | \********************************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } if (Req::val('logout')) { $user->logout(); Flyspray::Redirect($baseurl); } if (Req::val('user_name') != '' && Req::val('password') != '') { // Otherwise, they requested login. See if they provided the correct credentials... $username = Backend::clean_username(Req::val('user_name')); $password = Req::val('password'); // Run the username and password through the login checker if (($user_id = Flyspray::checkLogin($username, $password)) < 1) { $_SESSION['failed_login'] = Req::val('user_name'); if ($user_id === -2) { Flyspray::show_error(L('usernotexist')); } elseif ($user_id === -1) { Flyspray::show_error(23); } else { // just some extra check here so that never ever an account can get locked when it's already disabled // ... that would make it easy to get enabled $db->Query('UPDATE {users} SET login_attempts = login_attempts+1 WHERE account_enabled = 1 AND user_name = ?', array($username)); // Lock account if failed too often for a limited amount of time $db->Query('UPDATE {users} SET lock_until = ?, account_enabled = 0 WHERE login_attempts > ? AND user_name = ?', array(time() + 60 * $fs->prefs['lock_for'], LOGIN_ATTEMPTS, $username)); if ($db->AffectedRows()) {
/** * Creates a new user * @param string $user_name * @param string $password * @param string $real_name * @param string $jabber_id * @param string $email * @param integer $notify_type * @param integer $time_zone * @param integer $group_in * @access public * @return bool false if username is already taken * @version 1.0 * @notes This function does not have any permission checks (checked elsewhere) */ public static function create_user($user_name, $password, $real_name, $jabber_id, $email, $notify_type, $time_zone, $group_in) { global $fs, $db, $notify, $baseurl; $user_name = Backend::clean_username($user_name); // Limit length $real_name = substr(trim($real_name), 0, 100); // Remove doubled up spaces and control chars $real_name = preg_replace('![\\x00-\\x1f\\s]+!u', ' ', $real_name); // Check to see if the username is available $sql = $db->Query('SELECT COUNT(*) FROM {users} WHERE user_name = ?', array($user_name)); if ($db->fetchOne($sql)) { return false; } $auto = false; // Autogenerate a password if (!$password) { $auto = true; $password = substr(md5(uniqid(mt_rand(), true)), 0, mt_rand(8, 12)); } $db->Query("INSERT INTO {users}\n ( user_name, user_pass, real_name, jabber_id, magic_url,\n email_address, notify_type, account_enabled,\n tasks_perpage, register_date, time_zone, dateformat, dateformat_extended)\n VALUES ( ?, ?, ?, ?, ?, ?, ?, 1, 25, ?, ?, ?, ?)", array($user_name, Flyspray::cryptPassword($password), $real_name, strtolower($jabber_id), '', strtolower($email), $notify_type, time(), $time_zone, '', '')); // Get this user's id for the record $uid = Flyspray::UserNameToId($user_name); // Now, create a new record in the users_in_groups table $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) VALUES (?, ?)', array($uid, $group_in)); Flyspray::logEvent(0, 30, serialize(Flyspray::getUserDetails($uid))); $varnames = array('iwatch', 'atome', 'iopened'); $toserialize = array('string' => NULL, 'type' => array(''), 'sev' => array(''), 'due' => array(''), 'dev' => NULL, 'cat' => array(''), 'status' => array('open'), 'order' => NULL, 'sort' => NULL, 'percent' => array(''), 'opened' => NULL, 'search_in_comments' => NULL, 'search_for_all' => NULL, 'reported' => array(''), 'only_primary' => NULL, 'only_watched' => NULL); foreach ($varnames as $tmpname) { if ($tmpname == 'iwatch') { $tmparr = array('only_watched' => '1'); } elseif ($tmpname == 'atome') { $tmparr = array('dev' => $uid); } elseif ($tmpname == 'iopened') { $tmparr = array('opened' => $uid); } ${$tmpname} = $tmparr + $toserialize; } // Now give him his default searches $db->Query('INSERT INTO {searches} (user_id, name, search_string, time) VALUES (?, ?, ?, ?)', array($uid, L('taskswatched'), serialize($iwatch), time())); $db->Query('INSERT INTO {searches} (user_id, name, search_string, time) VALUES (?, ?, ?, ?)', array($uid, L('assignedtome'), serialize($atome), time())); $db->Query('INSERT INTO {searches} (user_id, name, search_string, time) VALUES (?, ?, ?, ?)', array($uid, L('tasksireported'), serialize($iopened), time())); if ($jabber_id) { Notifications::JabberRequestAuth($jabber_id); } // Send a user his details (his username might be altered, password auto-generated) if ($fs->prefs['notify_registration']) { $sql = $db->Query('SELECT DISTINCT email_address FROM {users} u LEFT JOIN {users_in_groups} g ON u.user_id = g.user_id WHERE g.group_id = 1'); $notify->Create(NOTIFY_NEW_USER, null, array($baseurl, $user_name, $real_name, $email, $jabber_id, $password, $auto), $db->FetchCol($sql), NOTIFY_EMAIL); } return true; }
function action_sendcode() { global $user, $db, $fs, $conf, $baseurl; if (!Post::val('user_name') || !Post::val('real_name') || !Post::val('email_address')) { // If the form wasn't filled out correctly, show an error return array(ERROR_RECOVER, L('registererror')); } $email = Post::val('email_address'); $jabber_id = Post::val('jabber_id'); //email is mandatory if (!$email || !Flyspray::check_email($email)) { return array(ERROR_RECOVER, L('novalidemail')); } //jabber_id is optional if ($jabber_id && !Jabber::check_jid($jabber_id)) { return array(ERROR_RECOVER, L('novalidjabber')); } $user_name = Backend::clean_username(Post::val('user_name')); // Limit lengths $real_name = substr(trim(Post::val('real_name')), 0, 100); // Remove doubled up spaces and control chars $real_name = preg_replace('![\\x00-\\x1f\\s]+!u', ' ', $real_name); if (!$user_name || !$real_name) { return array(ERROR_RECOVER, L('entervalidusername')); } // Delete registration codes older than 24 hours $yesterday = time() - 86400; $db->x->execParam('DELETE FROM {registrations} WHERE reg_time < ?', $yesterday); $taken = $db->x->getRow('SELECT u.user_id FROM {users} u, {registrations} r WHERE u.user_name = ? OR r.user_name = ?', null, array($user_name, $user_name)); if ($taken) { return array(ERROR_RECOVER, L('usernametaken')); } $taken = $db->x->getRow("SELECT user_id\n FROM {users}\n WHERE jabber_id = ? AND jabber_id != NULL\n OR email_address = ? AND email_address != NULL", null, array($jabber_id, $email)); if ($taken) { return array(ERROR_RECOVER, L('emailtaken')); } if ($fs->prefs['use_recaptcha']) { $solution = new reCAPTCHA_Solution(); $solution->privatekey = $fs->prefs['recaptcha_priv_key']; $solution->challenge = Post::val('recaptcha_challenge_field'); $solution->response = Post::val('recaptcha_response_field'); $solution->remoteip = $_SERVER['REMOTE_ADDR']; if (!$solution->isValid()) { return array(ERROR_RECOVER, $solution->error_code); } } $magic_url = substr(md5(uniqid(rand(), true)), 0, 20); //send the email first. if (Notifications::send(Post::val('email_address'), ADDRESS_EMAIL, NOTIFY_CONFIRMATION, array($baseurl, $magic_url, $user_name))) { //email sent succefully, now update the database. $reg_values = array('reg_time' => time(), 'user_name' => $user_name, 'real_name' => $real_name, 'email_address' => Post::val('email_address'), 'jabber_id' => Post::val('jabber_id'), 'notify_type' => Post::num('notify_type'), 'magic_url' => $magic_url, 'time_zone' => Post::num('time_zone')); // Insert everything into the database $query = $db->x->autoExecute('{registrations}', $reg_values); if (!PEAR::isError($query)) { return array(SUBMIT_OK, L('codesent'), $baseurl); } } else { return array(ERROR_INPUT, L('codenotsent')); } }
function checkLogin($username, $password) { global $fs, $db, $proj, $conf, $baseurl; if ($username == '' || $password == '') { return array(ERROR_RECOVER, L('error8')); } $username = Backend::clean_username($username); // first a does-user-exist check $user = $db->x->getRow('SELECT * FROM {users} WHERE user_name = ?', null, $username); if (!$user) { // at this point, provide the possibility to ask for LDAP users etc. foreach ($this->authenticators as $auth) { $user = $auth->checkLogin($username, $password); if (is_array($user)) { return $user; // some error message } else { if ($user) { $user = $db->x->getRow('SELECT * FROM {users} WHERE user_id = ?', null, $user); break; } } } // still not? if (!$user) { return array(ERROR_RECOVER, L('usernotexist')); } } // now check if he is actually allowed to login $group = $db->x->getRow('SELECT g.* FROM {groups} g LEFT JOIN {users_in_groups} uig ON g.group_id = uig.group_id WHERE uig.user_id = ? AND g.project_id = 0 ORDER BY g.group_id', null, $user['user_id']); // that's not good. a user always has to be in a single global group if (!$group) { return array(ERROR_INPUT, L('usernotinglobalgroup')); } // revert lock if any if ($user['lock_until'] > 0 && $user['lock_until'] < time()) { $db->x->execParam('UPDATE {users} SET lock_until = 0, account_enabled = 1, login_attempts = 0 WHERE user_id = ?', $user['user_id']); $user['account_enabled'] = 1; $_SESSION['was_locked'] = true; } // may not login if ($group['group_id'] != 1 && (!$user['account_enabled'] || !$group['group_open'])) { return array(ERROR_INPUT, L('error23')); } $salt = $user['password_salt'] ? $user['password_salt'] : null; // now check password if ($user['user_pass'] !== Flyspray::cryptPassword($password, $salt)) { // possibly we have to lock the account // just some extra check here so that never ever an account can get locked when it's already disabled // ... that would make it easy to get enabled $db->x->execParam('UPDATE {users} SET login_attempts = login_attempts+1 WHERE account_enabled = 1 AND user_id = ?', $user['user_id']); // Lock account if failed too often for a limited amount of time $num = $db->x->execParam('UPDATE {users} SET lock_until = ?, account_enabled = 0 WHERE login_attempts > ? AND user_id = ?', array(time() + 60 * $fs->prefs['lock_for'], LOGIN_ATTEMPTS, $user['user_id'])); if ($num) { // let user know about the lock return array(ERROR_RECOVER, sprintf(L('error71'), $fs->prefs['lock_for'])); } else { // just plain wrong password return array(ERROR_RECOVER, L('error7')); } } // [BC] let's add a user's password salt if he doesn't have one yet if (!$user['password_salt']) { $salt = md5(uniqid(mt_rand(), true)); $db->x->execParam('UPDATE {users} SET user_pass = ?, password_salt = ? WHERE user_id = ?', array(Flyspray::cryptPassword($password, $salt), $salt, $user['user_id'])); } // last, some post-login stuff // Determine if the user should be remembered on this machine $cookie_time = Post::has('remember_login') ? time() + 60 * 60 * 24 * 30 : 0; Flyspray::setcookie('flyspray_userid', $user['user_id'], $cookie_time); Flyspray::setcookie('flyspray_passhash', hash_hmac('md5', $user['user_pass'], $conf['general']['cookiesalt']), $cookie_time); // If the user had previously requested a password change, remove the magic url $db->x->execParam('UPDATE {users} SET magic_url = NULL WHERE user_id = ?', $user['user_id']); // Save for displaying if ($user['login_attempts'] > 0) { $_SESSION['login_attempts'] = $user['login_attempts']; } $db->x->execParam('UPDATE {users} SET login_attempts = 0 WHERE user_id = ?', $user['user_id']); return $user['user_id']; }