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