array('model' => 'user_token'), 'roles' => array('model' => 'role', 'through' => 'roles_users'), ); /** * Rules for the user model. Because the password is _always_ a hash * when it's set,you need to run an additional not_empty rule in your controller * to make sure you didn't hash an empty string. The password rules * should be enforced outside the model or with a model helper method. * * @return array Rules */ public function rules() { return array( 'username' => array( array('not_empty'), array('min_length', array(':value', 4)), array('max_length', array(':value', 32)), array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')), array(array($this, 'username_available'), array(':validation', ':field')), ), 'password' => array( array('not_empty'), ), 'email' => array( array('not_empty'), array('min_length', array(':value', 4)), array('max_length', array(':value', 127)), array('email'), array(array($this, 'email_available'), array(':validation', ':field')), ), ); } /** * Filters to run when data is set in this model. The password filter * automatically hashes the password when it's set in the model. * * @return array Filters */ public function filters() { return array( 'password' => array( array(array(Auth::instance(), 'hash')) ) ); } /** * Labels for fields in this model * * @return array Labels */ public function labels() { return array( 'username' => 'username', 'email' => 'email address', 'password' => 'password', ); } /** * Complete the login for a user by incrementing the logins and saving login timestamp * * @return void */ public function complete_login() { if ($this->_loaded) { // Update the number of logins $this->logins = new Database_Expression('logins + 1'); // Set the last login date $this->last_login = time(); // Save the user $this->update(); } } /** * Does the reverse of unique_key_exists() by triggering error if username exists. * Validation callback. * * @param Validation Validation object * @param string Field name * @return void */ public function username_available(Validation $validation, $field) { if ($this->unique_key_exists($validation[$field], 'username')) { $validation->error($field, 'username_available', array($validation[$field])); } } /** * Does the reverse of unique_key_exists() by triggering error if email exists. * Validation callback. * * @param Validation Validation object * @param string Field name * @return void */ public function email_available(Validation $validation, $field) { if ($this->unique_key_exists($validation[$field], 'email')) { $validation->error($field, 'email_available', array($validation[$field])); } } /** * Tests if a unique key value exists in the database. * * @param mixed the value to test * @param string field name * @return boolean */ public function unique_key_exists($value, $field = NULL) { if ($field === NULL) { // Automatically determine field by looking at the value $field = $this->unique_key($value); } return (bool) DB::select(array('COUNT("*")', 'total_count')) ->from($this->_table_name) ->where($field, '=', $value) ->where($this->_primary_key, '!=', $this->pk()) ->execute($this->_db) ->get('total_count'); } /** * Allows a model use both email and username as unique identifiers for login * * @param string unique value * @return string field name */ public function unique_key($value) { return Valid::email($value) ? 'email' : 'username'; } /** * Password validation for plain passwords. * * @param array $values * @return Validation */ public static function get_password_validation($values) { return Validation::factory($values) ->rule('password', 'min_length', array(':value', 8)) ->rule('password_confirm', 'matches', array(':validation', ':field', 'password')); } /** * Create a new user * * Example usage: * ~~~ * $user = ORM::factory('user')->create_user($_POST, array( * 'username', * 'password', * 'email', * ); * ~~~ * * @param array $values * @param array $expected * @throws ORM_Validation_Exception */ public function create_user($values, $expected) { // Validation for passwords $extra_validation = Model_User::get_password_validation($values) ->rule('password', 'not_empty'); return $this->values($values, $expected)->create($extra_validation); } /** * Update an existing user * * [!!] We make the assumption that if a user does not supply a password, that they do not wish to update their password. * * Example usage: * ~~~ * $user = ORM::factory('user') * ->where('username', '=', 'kiall') * ->find() * ->update_user($_POST, array( * 'username', * 'password', * 'email', * ); * ~~~ * * @param array $values * @param array $expected * @throws ORM_Validation_Exception */ public function update_user($values, $expected = NULL) { if (empty($values['password'])) { unset($values['password'], $values['password_confirm']); } // Validation for passwords $extra_validation = Model_User::get_password_validation($values); return $this->values($values, $expected)->update($extra_validation); } } // End Auth User Model