user model: if we don't get an explicit username, use the active user

and while we're at it change spaces to tabs
This commit is contained in:
Karsten Heiken
2011-07-31 18:28:17 +02:00
parent f31d78ef96
commit 79e36493db

View File

@@ -7,524 +7,526 @@
*/ */
class User extends CI_Model { class User extends CI_Model {
/** /**
* Contains the forgotten password key. * Contains the forgotten password key.
* *
* @var string * @var string
*/ */
public $forgottenPasswordCode; public $forgottenPasswordCode;
public function __construct() { public function __construct() {
parent::__construct(); parent::__construct();
$this->load->config('auth', true); $this->load->config('auth', true);
$this->load->helper('cookie'); $this->load->helper('cookie');
$this->load->helper('date'); $this->load->helper('date');
$this->storeSalt = $this->config->item('store_salt', 'auth'); $this->storeSalt = $this->config->item('store_salt', 'auth');
$this->saltLength = $this->config->item('salt_length', 'auth'); $this->saltLength = $this->config->item('salt_length', 'auth');
} }
/** /**
* Hashes the password to be stored in the database. * Hashes the password to be stored in the database.
* *
* @param string $password * @param string $password
* @param boolean $salt * @param boolean $salt
* @return boolean|string * @return boolean|string
*/ */
public function hashPassword($password, $salt = false) { public function hashPassword($password, $salt = false) {
if (empty($password)) { if (empty($password)) {
return false; return false;
} }
if ($this->storeSalt && $salt) { if ($this->storeSalt && $salt) {
return sha1($password . $salt); return sha1($password . $salt);
} else { } else {
$salt = $this->salt(); $salt = $this->salt();
return $salt . substr(sha1($salt . $password), 0, -$this->saltLength); return $salt . substr(sha1($salt . $password), 0, -$this->saltLength);
} }
} }
/** /**
* Takes a password and validates it against an entry in the users table. * Takes a password and validates it against an entry in the users table.
* *
* @param string $username * @param string $username
* @param string $password * @param string $password
* @return boolean|string * @return boolean|string
*/ */
public function hashPasswordForDB($username, $password) { public function hashPasswordForDB($username, $password) {
if (empty($username) || empty($password)) { if (empty($username) || empty($password)) {
return false; return false;
} }
$query = $this->db->select('password, salt') $query = $this->db->select('password, salt')
->where('username', $username)->limit(1)->get('users'); ->where('username', $username)->limit(1)->get('users');
$result = $query->row(); $result = $query->row();
if ($query->num_rows() !== 1) { if ($query->num_rows() !== 1) {
return false; return false;
} }
if ($this->storeSalt) { if ($this->storeSalt) {
return sha1($password . $result->salt); return sha1($password . $result->salt);
} else { } else {
$salt = substr($result->password, 0, $this->saltLength); $salt = substr($result->password, 0, $this->saltLength);
return $salt . substr(sha1($salt . $password), 0, -$this->saltLength); return $salt . substr(sha1($salt . $password), 0, -$this->saltLength);
} }
} }
/** /**
* Generates a random salt value. * Generates a random salt value.
* *
* @return string * @return string
*/ */
private function salt() { private function salt() {
return substr(md5(uniqid(rand(), true)), 0, $this->saltLength); return substr(md5(uniqid(rand(), true)), 0, $this->saltLength);
} }
/** /**
* Changes the password of the given user. * Changes the password of the given user.
* *
* @param string $username * @param string $username
* @param string $old * @param string $old
* @param string $new * @param string $new
* @return boolean * @return boolean
*/ */
public function changePassword($username, $old, $new) { public function changePassword($username, $old, $new) {
$query = $this->db->select('password, salt') $query = $this->db->select('password, salt')
->where('username', $username)->limit(1)->get('users'); ->where('username', $username)->limit(1)->get('users');
$result = $query->row(); $result = $query->row();
$dbPassword = $result->password; $dbPassword = $result->password;
$old = $this->hashPasswordForDB($username, $old); $old = $this->hashPasswordForDB($username, $old);
$new = $this->hashPassword($new, $result->salt); $new = $this->hashPassword($new, $result->salt);
if ($dbPassword === $old) { if ($dbPassword === $old) {
// store the new password and reset the remember code so all remembered instances have to re-login // store the new password and reset the remember code so all remembered instances have to re-login
$data = array('password' => $new, 'remember_code' => ''); $data = array('password' => $new, 'remember_code' => '');
$this->db->update('users', $data, array('username' => $username)); $this->db->update('users', $data, array('username' => $username));
return $this->db->affected_rows() == 1; return $this->db->affected_rows() == 1;
} }
return false; return false;
} }
/** /**
* Checks entered usernames. * Checks entered usernames.
* *
* @return boolean * @return boolean
*/ */
public function checkUsername($username = '') { public function checkUsername($username = '') {
if (empty($username)) { if (empty($username)) {
return false; return false;
} }
return $this->db->where('username', $username)->count_all_results('users') > 0; return $this->db->where('username', $username)->count_all_results('users') > 0;
} }
/** /**
* Checks entered emails. * Checks entered emails.
* *
* @return boolean * @return boolean
*/ */
public function checkEmail($email = '') { public function checkEmail($email = '') {
if (empty($email)) { if (empty($email)) {
return false; return false;
} }
return $this->db->where('email', $email)->count_all_results('users') > 0; return $this->db->where('email', $email)->count_all_results('users') > 0;
} }
/** /**
* Inserts a forgotten password key. * Inserts a forgotten password key.
* *
* @return boolean * @return boolean
*/ */
public function forgottenPassword($email = '') { public function forgottenPassword($email = '') {
if (empty($email)) { if (empty($email)) {
return false; return false;
} }
$key = $this->hashPassword(microtime() . $email); $key = $this->hashPassword(microtime() . $email);
$this->forgottenPasswordCode = $key; $this->forgottenPasswordCode = $key;
$this->db->update('users', array('forgotten_password_code' => $key), array('email' => $email)); $this->db->update('users', array('forgotten_password_code' => $key), array('email' => $email));
return $this->db->affected_rows() == 1; return $this->db->affected_rows() == 1;
} }
/** /**
* Forgotten Password Complete * Forgotten Password Complete
* *
* @return string * @return string
*/ */
public function forgottenPasswordComplete($code, $salt = false) { public function forgottenPasswordComplete($code, $salt = false) {
if (empty($code)) { if (empty($code)) {
return false; return false;
} }
$this->db->where('forgotten_password_code', $code); $this->db->where('forgotten_password_code', $code);
if ($this->db->count_all_results('users') > 0) { if ($this->db->count_all_results('users') > 0) {
$password = $this->salt(); $password = $this->salt();
$data = array( $data = array(
'password' => $this->hashPassword($password, $salt), 'password' => $this->hashPassword($password, $salt),
'forgotten_password_code' => null 'forgotten_password_code' => null
); );
$this->db->update('users', $data, array('forgotten_password_code' => $code)); $this->db->update('users', $data, array('forgotten_password_code' => $code));
return $password; return $password;
} }
return false; return false;
} }
/** /**
* profile * profile
* *
* @return boolean|object * @return boolean|object
*/ */
public function profile($username = '', $isCode = false) { public function profile($username = '', $isCode = false) {
if (empty($username)) { if (empty($username)) {
return false; @$username = $this->session->userdata('username');
} if(empty($username))
return FALSE;
}
$this->db->select('users.*, groups.name AS `group`, groups.description AS `group_description`'); $this->db->select('users.*, groups.name AS `group`, groups.description AS `group_description`');
$this->db->join('groups', 'users.group_id = groups.id', 'left'); $this->db->join('groups', 'users.group_id = groups.id', 'left');
if ($isCode) { if ($isCode) {
$this->db->where('users.forgotten_password_code', $username); $this->db->where('users.forgotten_password_code', $username);
} else { } else {
$this->db->where('users.username', $username); $this->db->where('users.username', $username);
} }
$query = $this->db->limit(1)->get('users'); $query = $this->db->limit(1)->get('users');
return $query->num_rows > 0 ? $query->row() : false; return $query->num_rows > 0 ? $query->row() : false;
} }
/** /**
* register * register
* *
* @return boolean * @return boolean
*/ */
public function register($username, $password, $email, $additionalData = false, $groupName = false) { public function register($username, $password, $email, $additionalData = false, $groupName = false) {
if ($this->checkUsername($username)) { if ($this->checkUsername($username)) {
$this->access->setError('account_creation_duplicate_username'); $this->access->setError('account_creation_duplicate_username');
return false; return false;
} }
// if a groupID was passed, use it // if a groupID was passed, use it
if (isset($additional_data['group_id'])) { if (isset($additional_data['group_id'])) {
$groupID = $additional_data['group_id']; $groupID = $additional_data['group_id'];
unset($additional_data['group_id']); unset($additional_data['group_id']);
} else { // otherwise get default groupID } else { // otherwise get default groupID
$groupName = !$groupName ? 'users' : $groupName; $groupName = !$groupName ? 'users' : $groupName;
$groupID = $this->db->select('id')->where('name', $groupName)->get('groups')->row()->id; $groupID = $this->db->select('id')->where('name', $groupName)->get('groups')->row()->id;
} }
// IP Address // IP Address
$ipAddress = $this->input->ip_address(); $ipAddress = $this->input->ip_address();
$salt = $this->storeSalt ? $this->salt() : false; $salt = $this->storeSalt ? $this->salt() : false;
$password = $this->hashPassword($password, $salt); $password = $this->hashPassword($password, $salt);
// Users table. // Users table.
$data = array( $data = array(
'username' => $username, 'username' => $username,
'password' => $password, 'password' => $password,
'email' => $email, 'email' => $email,
'group_id' => $groupID, 'group_id' => $groupID,
'last_login' => now(), 'last_login' => now(),
); );
if ($this->storeSalt) { if ($this->storeSalt) {
$data['salt'] = $salt; $data['salt'] = $salt;
} }
$this->db->insert('users', $data); $this->db->insert('users', $data);
$id = $this->db->insert_id(); $id = $this->db->insert_id();
return $this->db->affected_rows() > 0 ? $id : false; return $this->db->affected_rows() > 0 ? $id : false;
} }
/** /**
* login * login
* *
* @return boolean * @return boolean
*/ */
public function login($username, $password, $remember = false) { public function login($username, $password, $remember = false) {
if (empty($username) || empty($password) || !$this->checkUsername($username)) { if (empty($username) || empty($password) || !$this->checkUsername($username)) {
return false; return false;
} }
$query = $this->db->select('id, username, password, group_id') $query = $this->db->select('id, username, password, group_id')
->where('username', $username)->limit(1)->get('users'); ->where('username', $username)->limit(1)->get('users');
$result = $query->row(); $result = $query->row();
if ($query->num_rows() == 1) { if ($query->num_rows() == 1) {
$password = $this->hashPasswordForDB($username, $password); $password = $this->hashPasswordForDB($username, $password);
if ($result->password === $password) { if ($result->password === $password) {
$this->updateLastLogin($result->id); $this->updateLastLogin($result->id);
$group = $this->db->select('name')->where('id', $result->group_id)->get('groups')->row(); $group = $this->db->select('name')->where('id', $result->group_id)->get('groups')->row();
$session_data = array( $session_data = array(
'username' => $result->username, 'username' => $result->username,
'user_id' => $result->id, 'user_id' => $result->id,
'group_id' => $result->group_id, 'group_id' => $result->group_id,
'group' => $group->name 'group' => $group->name
); );
$this->session->set_userdata($session_data); $this->session->set_userdata($session_data);
if ($remember && $this->config->item('remember_users', 'auth')) { if ($remember && $this->config->item('remember_users', 'auth')) {
$this->rememberUser($result->id); $this->rememberUser($result->id);
} }
return true; return true;
} }
} }
return false; return false;
} }
/** /**
* get * get
* *
* @return object * @return object
*/ */
public function get($group = false, $limit = null, $offset = null) { public function get($group = false, $limit = null, $offset = null) {
$this->db->select('users.*, groups.name AS `group`, groups.description AS `group_description`'); $this->db->select('users.*, groups.name AS `group`, groups.description AS `group_description`');
$this->db->join('groups', 'users.group_id = groups.id', 'left'); $this->db->join('groups', 'users.group_id = groups.id', 'left');
if (is_string($group)) { if (is_string($group)) {
$this->db->where('groups.name', $group); $this->db->where('groups.name', $group);
} else if (is_array($group)) { } else if (is_array($group)) {
$this->db->where_in('groups.name', $group); $this->db->where_in('groups.name', $group);
} }
if (isset($limit) && isset($offset)) { if (isset($limit) && isset($offset)) {
$this->db->limit($limit, $offset); $this->db->limit($limit, $offset);
} }
return $this->db->get('users'); return $this->db->get('users');
} }
/** /**
* Returns the number of users. * Returns the number of users.
* *
* @return integer The number of users * @return integer The number of users
*/ */
public function count($group = false) { public function count($group = false) {
if (is_string($group)) { if (is_string($group)) {
$this->db->where('groups.name', $group); $this->db->where('groups.name', $group);
} else if (is_array($group)) { } else if (is_array($group)) {
$this->db->where_in('groups.name', $group); $this->db->where_in('groups.name', $group);
} }
return $this->db->from('users')->count_all_results(); return $this->db->from('users')->count_all_results();
} }
/** /**
* getUserByID * getUserByID
* *
* @return object * @return object
*/ */
public function getUserByID($id = false) { public function getUserByID($id = false) {
// if no ID was passed use the current users ID // if no ID was passed use the current users ID
if (empty($id)) { if (empty($id)) {
$id = $this->session->userdata('user_id'); $id = $this->session->userdata('user_id');
} }
$this->db->where('users.id', $id); $this->db->where('users.id', $id);
$this->db->limit(1); $this->db->limit(1);
return $this->get(); return $this->get();
} }
/** /**
* getUserByEmail * getUserByEmail
* *
* @return object * @return object
*/ */
public function getUserByEmail($email) { public function getUserByEmail($email) {
$this->db->where('users.email', $email); $this->db->where('users.email', $email);
$this->db->limit(1); $this->db->limit(1);
return $this->get(); return $this->get();
} }
/** /**
* getUserByUsername * getUserByUsername
* *
* @return object * @return object
*/ */
public function getUserByUsername($username) { public function getUserByUsername($username) {
$this->db->where('users.username', $username); $this->db->where('users.username', $username);
$this->db->limit(1); $this->db->limit(1);
return $this->get(); return $this->get();
} }
/** /**
* getNewestUsers * getNewestUsers
* *
* @return object * @return object
*/ */
public function getNewestUsers($limit = 10) { public function getNewestUsers($limit = 10) {
$this->db->order_by('users.created_on DESC'); $this->db->order_by('users.created_on DESC');
$this->db->limit($limit); $this->db->limit($limit);
return $this->get(); return $this->get();
} }
/** /**
* getUsersGroup * getUsersGroup
* *
* @return object * @return object
*/ */
public function getUsersGroup($id = false) { public function getUsersGroup($id = false) {
// if no ID was passed use the current users ID // if no ID was passed use the current users ID
$id || $id = $this->session->userdata('user_id'); $id || $id = $this->session->userdata('user_id');
$user = $this->db->select('group_id')->where('id', $id)->get('users') $user = $this->db->select('group_id')->where('id', $id)->get('users')
->row(); ->row();
return $this->db->select('name, description') return $this->db->select('name, description')
->where('id', $user->group_id)->get('groups')->row(); ->where('id', $user->group_id)->get('groups')->row();
} }
/** /**
* update * update
* *
* @return boolean * @return boolean
*/ */
public function update($id, $data) { public function update($id, $data) {
$user = $this->getUserByID($id)->row(); $user = $this->getUserByID($id)->row();
$this->db->trans_begin(); $this->db->trans_begin();
if (array_key_exists('username', $data) && $this->checkUsername($data['username']) && $user->username !== $data['username']) { if (array_key_exists('username', $data) && $this->checkUsername($data['username']) && $user->username !== $data['username']) {
$this->db->trans_rollback(); $this->db->trans_rollback();
$this->access->setError('account_creation_duplicate_username'); $this->access->setError('account_creation_duplicate_username');
return false; return false;
} }
if (array_key_exists('username', $data) || array_key_exists('password', $data) || array_key_exists('email', $data)) { if (array_key_exists('username', $data) || array_key_exists('password', $data) || array_key_exists('email', $data)) {
if (array_key_exists('password', $data)) { if (array_key_exists('password', $data)) {
$data['password'] = $this->hashPassword($data['password'], $user->salt); $data['password'] = $this->hashPassword($data['password'], $user->salt);
} }
$this->db->update('users', $data, array('id' => $id)); $this->db->update('users', $data, array('id' => $id));
} }
if ($this->db->trans_status() === false) { if ($this->db->trans_status() === false) {
$this->db->trans_rollback(); $this->db->trans_rollback();
return false; return false;
} }
$this->db->trans_commit(); $this->db->trans_commit();
return true; return true;
} }
/** /**
* delete * delete
* *
* @return boolean * @return boolean
*/ */
public function delete($id) { public function delete($id) {
$this->db->trans_begin(); $this->db->trans_begin();
$this->db->delete('users', array('id' => $id)); $this->db->delete('users', array('id' => $id));
if ($this->db->trans_status() === false) { if ($this->db->trans_status() === false) {
$this->db->trans_rollback(); $this->db->trans_rollback();
return false; return false;
} }
$this->db->trans_commit(); $this->db->trans_commit();
return true; return true;
} }
/** /**
* updateLastLogin * updateLastLogin
* *
* @return boolean * @return boolean
*/ */
public function updateLastLogin($id) { public function updateLastLogin($id) {
$this->db->update('users', array('last_login' => now()), array('id' => $id)); $this->db->update('users', array('last_login' => now()), array('id' => $id));
return $this->db->affected_rows() == 1; return $this->db->affected_rows() == 1;
} }
/** /**
* loginRemembedUser * loginRemembedUser
* *
* @return boolean * @return boolean
*/ */
public function loginRememberedUser() { public function loginRememberedUser() {
if (!get_cookie('username') || !get_cookie('remember_code') || !$this->checkUsername(get_cookie('username'))) { if (!get_cookie('username') || !get_cookie('remember_code') || !$this->checkUsername(get_cookie('username'))) {
return false; return false;
} }
$query = $this->db->select('id, username, group_id') $query = $this->db->select('id, username, group_id')
->where('username', get_cookie('username')) ->where('username', get_cookie('username'))
->where('remember_code', get_cookie('remember_code'))->limit(1) ->where('remember_code', get_cookie('remember_code'))->limit(1)
->get('users'); ->get('users');
if ($query->num_rows() == 1) { if ($query->num_rows() == 1) {
$user = $query->row(); $user = $query->row();
$this->updateLastLogin($user->id); $this->updateLastLogin($user->id);
$group = $this->db->select('name')->where('id', $user->group_id) $group = $this->db->select('name')->where('id', $user->group_id)
->get('groups')->row(); ->get('groups')->row();
$session_data = array( $session_data = array(
'username' => $user->username, 'username' => $user->username,
'user_id' => $user->id, 'user_id' => $user->id,
'group_id' => $user->group_id, 'group_id' => $user->group_id,
'group' => $group->name 'group' => $group->name
); );
$this->session->set_userdata($session_data); $this->session->set_userdata($session_data);
// extend the users cookies if the option is enabled // extend the users cookies if the option is enabled
if ($this->config->item('user_extend_on_login', 'auth')) { if ($this->config->item('user_extend_on_login', 'auth')) {
$this->rememberUser($user->id); $this->rememberUser($user->id);
} }
return true; return true;
} }
return false; return false;
} }
/** /**
* rememberUser * rememberUser
* *
* @return boolean * @return boolean
*/ */
private function rememberUser($id) { private function rememberUser($id) {
if (!$id) { if (!$id) {
return false; return false;
} }
$user = $this->getUserByID($id)->row(); $user = $this->getUserByID($id)->row();
$salt = sha1($user->password); $salt = sha1($user->password);
$this->db->update('users', array('remember_code' => $salt), array('id' => $id)); $this->db->update('users', array('remember_code' => $salt), array('id' => $id));
if ($this->db->affected_rows() > -1) { if ($this->db->affected_rows() > -1) {
set_cookie(array( set_cookie(array(
'name' => 'username', 'name' => 'username',
'value' => $user->username, 'value' => $user->username,
'expire' => $this->config->item('user_expire', 'auth'), 'expire' => $this->config->item('user_expire', 'auth'),
)); ));
set_cookie(array( set_cookie(array(
'name' => 'remember_code', 'name' => 'remember_code',
'value' => $salt, 'value' => $salt,
'expire' => $this->config->item('user_expire', 'auth'), 'expire' => $this->config->item('user_expire', 'auth'),
)); ));
return true; return true;
} }
return false; return false;
} }
} }