Update Kohana to 3.1.3.1
This commit is contained in:
13
includes/kohana/modules/auth/README.md
Normal file
13
includes/kohana/modules/auth/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
New Age Auth
|
||||
---
|
||||
|
||||
I've forked the main Auth module because there were some fundamental flaws with it:
|
||||
|
||||
1. It's trivial to [bruteforce](http://dev.kohanaframework.org/issues/3163) publicly hidden salt hashes.
|
||||
- I've fixed this by switching the password hashing algorithm to the more secure secret-key based hash_hmac method.
|
||||
2. ORM drivers were included.
|
||||
- I've fixed this by simply removing them. They cause confusion with new users because they think that Auth requires ORM. The only driver currently provided by default is the file driver.
|
||||
3. Auth::get_user()'s api is inconsistent because it returns different data types.
|
||||
- I've fixed this by returning an empty user model by default. You can override what gets returned (if you've changed your user model class name for instance) by overloading the get_user() method in your application.
|
||||
|
||||
These changes should be merged into the mainline branch eventually, but they completely break the API, so likely won't be done until 3.1.
|
@@ -1,3 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Auth_ORM extends Kohana_Auth_ORM { }
|
@@ -27,7 +27,7 @@ abstract class Kohana_Auth {
|
||||
|
||||
if ( ! $type = $config->get('driver'))
|
||||
{
|
||||
$type = 'ORM';
|
||||
$type = 'file';
|
||||
}
|
||||
|
||||
// Set the session class name
|
||||
@@ -40,16 +40,6 @@ abstract class Kohana_Auth {
|
||||
return Auth::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of Auth.
|
||||
*
|
||||
* @return Auth
|
||||
*/
|
||||
public static function factory($config = array())
|
||||
{
|
||||
return new Auth($config);
|
||||
}
|
||||
|
||||
protected $_session;
|
||||
|
||||
protected $_config;
|
||||
@@ -61,9 +51,6 @@ abstract class Kohana_Auth {
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
// Clean up the salt pattern and split it into an array
|
||||
$config['salt_pattern'] = preg_split('/,\s*/', Kohana::config('auth')->get('salt_pattern'));
|
||||
|
||||
// Save the config in the object
|
||||
$this->_config = $config;
|
||||
|
||||
@@ -78,13 +65,13 @@ abstract class Kohana_Auth {
|
||||
|
||||
/**
|
||||
* Gets the currently logged in user from the session.
|
||||
* Returns FALSE if no user is currently logged in.
|
||||
* Returns NULL if no user is currently logged in.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_user()
|
||||
public function get_user($default = NULL)
|
||||
{
|
||||
return $this->_session->get($this->_config['session_key'], FALSE);
|
||||
return $this->_session->get($this->_config['session_key'], $default);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,11 +89,8 @@ abstract class Kohana_Auth {
|
||||
|
||||
if (is_string($password))
|
||||
{
|
||||
// Get the salt from the stored password
|
||||
$salt = $this->find_salt($this->password($username));
|
||||
|
||||
// Create a hashed password using the salt from the stored password
|
||||
$password = $this->hash_password($password, $salt);
|
||||
// Create a hashed password
|
||||
$password = $this->hash($password);
|
||||
}
|
||||
|
||||
return $this->_login($username, $password, $remember);
|
||||
@@ -141,90 +125,40 @@ abstract class Kohana_Auth {
|
||||
|
||||
/**
|
||||
* Check if there is an active session. Optionally allows checking for a
|
||||
* specific role.
|
||||
* specific role.
|
||||
*
|
||||
* @param string role name
|
||||
* @return mixed
|
||||
*/
|
||||
public function logged_in($role = NULL)
|
||||
{
|
||||
return FALSE !== $this->get_user();
|
||||
return ($this->get_user() !== NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hashed password from a plaintext password, inserting salt
|
||||
* based on the configured salt pattern.
|
||||
* Creates a hashed hmac password from a plaintext password. This
|
||||
* method is deprecated, [Auth::hash] should be used instead.
|
||||
*
|
||||
* @deprecated
|
||||
* @param string plaintext password
|
||||
* @return string hashed password string
|
||||
*/
|
||||
public function hash_password($password, $salt = FALSE)
|
||||
public function hash_password($password)
|
||||
{
|
||||
if ($salt === FALSE)
|
||||
{
|
||||
// Create a salt seed, same length as the number of offsets in the pattern
|
||||
$salt = substr($this->hash(uniqid(NULL, TRUE)), 0, count($this->_config['salt_pattern']));
|
||||
}
|
||||
|
||||
// Password hash that the salt will be inserted into
|
||||
$hash = $this->hash($salt.$password);
|
||||
|
||||
// Change salt to an array
|
||||
$salt = str_split($salt, 1);
|
||||
|
||||
// Returned password
|
||||
$password = '';
|
||||
|
||||
// Used to calculate the length of splits
|
||||
$last_offset = 0;
|
||||
|
||||
foreach ($this->_config['salt_pattern'] as $offset)
|
||||
{
|
||||
// Split a new part of the hash off
|
||||
$part = substr($hash, 0, $offset - $last_offset);
|
||||
|
||||
// Cut the current part out of the hash
|
||||
$hash = substr($hash, $offset - $last_offset);
|
||||
|
||||
// Add the part to the password, appending the salt character
|
||||
$password .= $part.array_shift($salt);
|
||||
|
||||
// Set the last offset to the current offset
|
||||
$last_offset = $offset;
|
||||
}
|
||||
|
||||
// Return the password, with the remaining hash appended
|
||||
return $password.$hash;
|
||||
return $this->hash($password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a hash, using the configured method.
|
||||
* Perform a hmac hash, using the configured method.
|
||||
*
|
||||
* @param string string to hash
|
||||
* @return string
|
||||
*/
|
||||
public function hash($str)
|
||||
{
|
||||
return hash($this->_config['hash_method'], $str);
|
||||
}
|
||||
if ( ! $this->_config['hash_key'])
|
||||
throw new Kohana_Exception('A valid hash key must be set in your auth config.');
|
||||
|
||||
/**
|
||||
* Finds the salt from a password, based on the configured salt pattern.
|
||||
*
|
||||
* @param string hashed password
|
||||
* @return string
|
||||
*/
|
||||
public function find_salt($password)
|
||||
{
|
||||
$salt = '';
|
||||
|
||||
foreach ($this->_config['salt_pattern'] as $i => $offset)
|
||||
{
|
||||
// Find salt characters, take a good long look...
|
||||
$salt .= substr($password, $offset + $i, 1);
|
||||
}
|
||||
|
||||
return $salt;
|
||||
return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']);
|
||||
}
|
||||
|
||||
protected function complete_login($user)
|
||||
@@ -238,4 +172,4 @@ abstract class Kohana_Auth {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Auth
|
||||
} // End Auth
|
||||
|
@@ -1,322 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* ORM Auth driver.
|
||||
*
|
||||
* @package Kohana/Auth
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2010 Kohana Team
|
||||
* @license http://kohanaframework.org/license
|
||||
*/
|
||||
class Kohana_Auth_ORM extends Auth {
|
||||
|
||||
/**
|
||||
* Checks if a session is active.
|
||||
*
|
||||
* @param mixed role name string, role ORM object, or array with role names
|
||||
* @param boolean check user for every role applied (TRUE, by default) or if any?
|
||||
* @return boolean
|
||||
*/
|
||||
public function logged_in($role = NULL, $all_required = TRUE)
|
||||
{
|
||||
$status = FALSE;
|
||||
|
||||
// Get the user from the session
|
||||
$user = $this->get_user();
|
||||
|
||||
if (is_object($user) AND $user instanceof Model_User AND $user->loaded())
|
||||
{
|
||||
// Everything is okay so far
|
||||
$status = TRUE;
|
||||
|
||||
if ( ! empty($role))
|
||||
{
|
||||
// Multiple roles to check
|
||||
if (is_array($role))
|
||||
{
|
||||
// set initial status
|
||||
$status = (bool) $all_required;
|
||||
|
||||
// Check each role
|
||||
foreach ($role as $_role)
|
||||
{
|
||||
if ( ! is_object($_role))
|
||||
{
|
||||
$_role = ORM::factory('role', array('name' => $_role));
|
||||
}
|
||||
|
||||
// If the user doesn't have the role
|
||||
if ( ! $user->has('roles', $_role))
|
||||
{
|
||||
// Set the status false and get outta here
|
||||
$status = FALSE;
|
||||
if ($all_required)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
elseif ( ! $all_required )
|
||||
{
|
||||
$status = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Single role to check
|
||||
else
|
||||
{
|
||||
if ( ! is_object($role))
|
||||
{
|
||||
// Load the role
|
||||
$role = ORM::factory('role', array('name' => $role));
|
||||
}
|
||||
|
||||
// Check that the user has the given role
|
||||
$status = $user->has('roles', $role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user in.
|
||||
*
|
||||
* @param string username
|
||||
* @param string password
|
||||
* @param boolean enable autologin
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _login($user, $password, $remember)
|
||||
{
|
||||
if ( ! is_object($user))
|
||||
{
|
||||
$username = $user;
|
||||
|
||||
// Load the user
|
||||
$user = ORM::factory('user');
|
||||
$user->where($user->unique_key($username), '=', $username)->find();
|
||||
}
|
||||
|
||||
// If the passwords match, perform a login
|
||||
if ($user->has('roles', ORM::factory('role', array('name' => 'login'))) AND $user->password === $password)
|
||||
{
|
||||
if ($remember === TRUE)
|
||||
{
|
||||
$this->remember($user);
|
||||
}
|
||||
|
||||
// Finish the login
|
||||
$this->complete_login($user);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Login failed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a user to be logged in, without specifying a password.
|
||||
*
|
||||
* @param mixed username string, or user ORM object
|
||||
* @param boolean mark the session as forced
|
||||
* @return boolean
|
||||
*/
|
||||
public function force_login($user, $mark_session_as_forced = FALSE)
|
||||
{
|
||||
if ( ! is_object($user))
|
||||
{
|
||||
$username = $user;
|
||||
|
||||
// Load the user
|
||||
$user = ORM::factory('user');
|
||||
$user->where($user->unique_key($username), '=', $username)->find();
|
||||
}
|
||||
|
||||
if ($mark_session_as_forced === TRUE)
|
||||
{
|
||||
// Mark the session as forced, to prevent users from changing account information
|
||||
$this->_session->set($this->_config['forced_key'], TRUE);
|
||||
}
|
||||
|
||||
// Run the standard completion
|
||||
$this->complete_login($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user in, based on the authautologin cookie.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function auto_login()
|
||||
{
|
||||
if ($token = Cookie::get($this->_config['autologin_key']))
|
||||
{
|
||||
// Load the token and user
|
||||
$token = ORM::factory('user_token', array('token' => $token));
|
||||
|
||||
if ($token->loaded() AND $token->user->loaded())
|
||||
{
|
||||
if ($token->user_agent === sha1(Request::$user_agent))
|
||||
{
|
||||
// Save the token to create a new unique token
|
||||
$token->save();
|
||||
|
||||
// Set the new token
|
||||
Cookie::set($this->_config['autologin_key'], $token->token, $token->expires - time());
|
||||
|
||||
// Complete the login with the found data
|
||||
$this->complete_login($token->user);
|
||||
|
||||
// Automatic login was successful
|
||||
return $token->user;
|
||||
}
|
||||
|
||||
// Token is invalid
|
||||
$token->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently logged in user from the session (with auto_login check).
|
||||
* Returns FALSE if no user is currently logged in.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_user()
|
||||
{
|
||||
$user = parent::get_user();
|
||||
|
||||
if ($user === FALSE)
|
||||
{
|
||||
// check for "remembered" login
|
||||
$user = $this->auto_login();
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a user out and remove any autologin cookies.
|
||||
*
|
||||
* @param boolean completely destroy the session
|
||||
* @param boolean remove all tokens for user
|
||||
* @return boolean
|
||||
*/
|
||||
public function logout($destroy = FALSE, $logout_all = FALSE)
|
||||
{
|
||||
// Set by force_login()
|
||||
$this->_session->delete($this->_config['forced_key']);
|
||||
|
||||
if ($token = Cookie::get($this->_config['autologin_key']))
|
||||
{
|
||||
// Delete the autologin cookie to prevent re-login
|
||||
Cookie::delete($this->_config['autologin_key']);
|
||||
|
||||
// Clear the autologin token from the database
|
||||
$token = ORM::factory('user_token', array('token' => $token));
|
||||
|
||||
if ($token->loaded() AND $logout_all)
|
||||
{
|
||||
ORM::factory('user_token')->where('user_id', '=', $token->user_id)->delete_all();
|
||||
}
|
||||
elseif ($token->loaded())
|
||||
{
|
||||
$token->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return parent::logout($destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored password for a username.
|
||||
*
|
||||
* @param mixed username string, or user ORM object
|
||||
* @return string
|
||||
*/
|
||||
public function password($user)
|
||||
{
|
||||
if ( ! is_object($user))
|
||||
{
|
||||
$username = $user;
|
||||
|
||||
// Load the user
|
||||
$user = ORM::factory('user');
|
||||
$user->where($user->unique_key($username), '=', $username)->find();
|
||||
}
|
||||
|
||||
return $user->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the login for a user by incrementing the logins and setting
|
||||
* session data: user_id, username, roles.
|
||||
*
|
||||
* @param object user ORM object
|
||||
* @return void
|
||||
*/
|
||||
protected function complete_login($user)
|
||||
{
|
||||
$user->complete_login();
|
||||
|
||||
return parent::complete_login($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare password with original (hashed). Works for current (logged in) user
|
||||
*
|
||||
* @param string $password
|
||||
* @return boolean
|
||||
*/
|
||||
public function check_password($password)
|
||||
{
|
||||
$user = $this->get_user();
|
||||
|
||||
if ($user === FALSE)
|
||||
{
|
||||
// nothing to compare
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$hash = $this->hash_password($password, $this->find_salt($user->password));
|
||||
|
||||
return $hash == $user->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember user (create token and save it in cookie)
|
||||
*
|
||||
* @param Model_User $user
|
||||
* @return boolean
|
||||
*/
|
||||
public function remember($user = NULL)
|
||||
{
|
||||
if (is_null($user))
|
||||
{
|
||||
$user = $this->get_user();
|
||||
}
|
||||
if ( ! $user)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create a new autologin token
|
||||
$token = ORM::factory('user_token');
|
||||
|
||||
// Set token data
|
||||
$token->user_id = $user->id;
|
||||
$token->expires = time() + $this->_config['lifetime'];
|
||||
$token->save();
|
||||
|
||||
// Set the autologin cookie
|
||||
Cookie::set($this->_config['autologin_key'], $token->token, $this->_config['lifetime']);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Auth ORM
|
@@ -1,27 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* Default auth role
|
||||
*
|
||||
* @package Kohana/Auth
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2010 Kohana Team
|
||||
* @license http://kohanaframework.org/license
|
||||
*/
|
||||
class Model_Auth_Role extends ORM {
|
||||
|
||||
// Relationships
|
||||
protected $_has_many = array('users' => array('through' => 'roles_users'));
|
||||
|
||||
// Validation rules
|
||||
protected $_rules = array(
|
||||
'name' => array(
|
||||
'not_empty' => NULL,
|
||||
'min_length' => array(4),
|
||||
'max_length' => array(32),
|
||||
),
|
||||
'description' => array(
|
||||
'max_length' => array(255),
|
||||
),
|
||||
);
|
||||
|
||||
} // End Auth Role Model
|
@@ -1,244 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* Default auth user
|
||||
*
|
||||
* @package Kohana/Auth
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2010 Kohana Team
|
||||
* @license http://kohanaframework.org/license
|
||||
*/
|
||||
class Model_Auth_User extends ORM {
|
||||
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'user_tokens' => array('model' => 'user_token'),
|
||||
'roles' => array('model' => 'role', 'through' => 'roles_users'),
|
||||
);
|
||||
|
||||
// Validation rules
|
||||
protected $_rules = array(
|
||||
'username' => array(
|
||||
'not_empty' => NULL,
|
||||
'min_length' => array(4),
|
||||
'max_length' => array(32),
|
||||
'regex' => array('/^[-\pL\pN_.]++$/uD'),
|
||||
),
|
||||
'password' => array(
|
||||
'not_empty' => NULL,
|
||||
'min_length' => array(5),
|
||||
'max_length' => array(42),
|
||||
),
|
||||
'password_confirm' => array(
|
||||
'matches' => array('password'),
|
||||
),
|
||||
'email' => array(
|
||||
'not_empty' => NULL,
|
||||
'min_length' => array(4),
|
||||
'max_length' => array(127),
|
||||
'email' => NULL,
|
||||
),
|
||||
);
|
||||
|
||||
// Validation callbacks
|
||||
protected $_callbacks = array(
|
||||
'username' => array('username_available'),
|
||||
'email' => array('email_available'),
|
||||
);
|
||||
|
||||
// Field labels
|
||||
protected $_labels = array(
|
||||
'username' => 'username',
|
||||
'email' => 'email address',
|
||||
'password' => 'password',
|
||||
'password_confirm' => 'password confirmation',
|
||||
);
|
||||
|
||||
// Columns to ignore
|
||||
protected $_ignored_columns = array('password_confirm');
|
||||
|
||||
/**
|
||||
* Validates login information from an array, and optionally redirects
|
||||
* after a successful login.
|
||||
*
|
||||
* @param array values to check
|
||||
* @param string URI or URL to redirect to
|
||||
* @return boolean
|
||||
*/
|
||||
public function login(array & $array, $redirect = FALSE)
|
||||
{
|
||||
$fieldname = $this->unique_key($array['username']);
|
||||
$array = Validate::factory($array)
|
||||
->label('username', $this->_labels[$fieldname])
|
||||
->label('password', $this->_labels['password'])
|
||||
->filter(TRUE, 'trim')
|
||||
->rules('username', $this->_rules[$fieldname])
|
||||
->rules('password', $this->_rules['password']);
|
||||
|
||||
// Get the remember login option
|
||||
$remember = isset($array['remember']);
|
||||
|
||||
// Login starts out invalid
|
||||
$status = FALSE;
|
||||
|
||||
if ($array->check())
|
||||
{
|
||||
// Attempt to load the user
|
||||
$this->where($fieldname, '=', $array['username'])->find();
|
||||
|
||||
if ($this->loaded() AND Auth::instance()->login($this, $array['password'], $remember))
|
||||
{
|
||||
if (is_string($redirect))
|
||||
{
|
||||
// Redirect after a successful login
|
||||
Request::instance()->redirect($redirect);
|
||||
}
|
||||
|
||||
// Login is successful
|
||||
$status = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$array->error('username', 'invalid');
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an array for a matching password and password_confirm field,
|
||||
* and optionally redirects after a successful save.
|
||||
*
|
||||
* @param array values to check
|
||||
* @param string URI or URL to redirect to
|
||||
* @return boolean
|
||||
*/
|
||||
public function change_password(array & $array, $redirect = FALSE)
|
||||
{
|
||||
$array = Validate::factory($array)
|
||||
->label('password', $this->_labels['password'])
|
||||
->label('password_confirm', $this->_labels['password_confirm'])
|
||||
->filter(TRUE, 'trim')
|
||||
->rules('password', $this->_rules['password'])
|
||||
->rules('password_confirm', $this->_rules['password_confirm']);
|
||||
|
||||
if ($status = $array->check())
|
||||
{
|
||||
// Change the password
|
||||
$this->password = $array['password'];
|
||||
|
||||
if ($status = $this->save() AND is_string($redirect))
|
||||
{
|
||||
// Redirect to the success page
|
||||
Request::instance()->redirect($redirect);
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the login for a user by incrementing the logins and saving login timestamp
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function complete_login()
|
||||
{
|
||||
if ( ! $this->_loaded)
|
||||
{
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
// 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->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the reverse of unique_key_exists() by triggering error if username exists.
|
||||
* Validation callback.
|
||||
*
|
||||
* @param Validate Validate object
|
||||
* @param string field name
|
||||
* @return void
|
||||
*/
|
||||
public function username_available(Validate $array, $field)
|
||||
{
|
||||
if ($this->unique_key_exists($array[$field], 'username'))
|
||||
{
|
||||
$array->error($field, 'username_available', array($array[$field]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the reverse of unique_key_exists() by triggering error if email exists.
|
||||
* Validation callback.
|
||||
*
|
||||
* @param Validate Validate object
|
||||
* @param string field name
|
||||
* @return void
|
||||
*/
|
||||
public function email_available(Validate $array, $field)
|
||||
{
|
||||
if ($this->unique_key_exists($array[$field], 'email'))
|
||||
{
|
||||
$array->error($field, 'email_available', array($array[$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 Validate::email($value) ? 'email' : 'username';
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current object. Will hash password if it was changed.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
if (array_key_exists('password', $this->_changed))
|
||||
{
|
||||
$this->_object['password'] = Auth::instance()->hash_password($this->_object['password']);
|
||||
}
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
} // End Auth User Model
|
@@ -1,101 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
/**
|
||||
* Default auth user toke
|
||||
*
|
||||
* @package Kohana/Auth
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2010 Kohana Team
|
||||
* @license http://kohanaframework.org/license
|
||||
*/
|
||||
class Model_Auth_User_Token extends ORM {
|
||||
|
||||
// Relationships
|
||||
protected $_belongs_to = array('user' => array());
|
||||
|
||||
// Current timestamp
|
||||
protected $_now;
|
||||
|
||||
/**
|
||||
* Handles garbage collection and deleting of expired objects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($id = NULL)
|
||||
{
|
||||
parent::__construct($id);
|
||||
|
||||
// Set the now, we use this a lot
|
||||
$this->_now = time();
|
||||
|
||||
if (mt_rand(1, 100) === 1)
|
||||
{
|
||||
// Do garbage collection
|
||||
$this->delete_expired();
|
||||
}
|
||||
|
||||
if ($this->expires < $this->_now)
|
||||
{
|
||||
// This object has expired
|
||||
$this->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload saving to set the created time and to create a new token
|
||||
* when the object is saved.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
if ($this->loaded() === FALSE)
|
||||
{
|
||||
// Set the created time, token, and hash of the user agent
|
||||
$this->created = $this->_now;
|
||||
$this->user_agent = sha1(Request::$user_agent);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
// Generate a new token
|
||||
$this->token = $this->create_token();
|
||||
|
||||
try
|
||||
{
|
||||
return parent::save();
|
||||
}
|
||||
catch (Kohana_Database_Exception $e)
|
||||
{
|
||||
// Collision occurred, token is not unique
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all expired tokens.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
public function delete_expired()
|
||||
{
|
||||
// Delete all expired tokens
|
||||
DB::delete($this->_table_name)
|
||||
->where('expires', '<', $this->_now)
|
||||
->execute($this->_db);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new unique token.
|
||||
*
|
||||
* @return string
|
||||
* @uses Text::random
|
||||
*/
|
||||
protected function create_token()
|
||||
{
|
||||
// Create a random token
|
||||
return Text::random('alnum', 32);
|
||||
}
|
||||
|
||||
} // End Auth User Token Model
|
@@ -1,7 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Model_Role extends Model_Auth_Role {
|
||||
|
||||
// This class can be replaced or extended
|
||||
|
||||
} // End Role Model
|
@@ -1,7 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Model_User extends Model_Auth_User {
|
||||
|
||||
// This class can be replaced or extended
|
||||
|
||||
} // End User Model
|
@@ -1,7 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Model_User_Token extends Model_Auth_User_Token {
|
||||
|
||||
// This class can be replaced or extended
|
||||
|
||||
} // End User Token Model
|
@@ -2,17 +2,15 @@
|
||||
|
||||
return array(
|
||||
|
||||
'driver' => 'ORM',
|
||||
'hash_method' => 'sha1',
|
||||
'salt_pattern' => '1, 3, 5, 9, 14, 15, 20, 21, 28, 30',
|
||||
'lifetime' => 1209600,
|
||||
'session_key' => 'auth_user',
|
||||
'autologin_key' => 'auth_autologin',
|
||||
'forced_key' => 'auth_forced',
|
||||
'driver' => 'file',
|
||||
'hash_method' => 'sha256',
|
||||
'hash_key' => NULL,
|
||||
'lifetime' => 1209600,
|
||||
'session_key' => 'auth_user',
|
||||
|
||||
// Username/password combinations for the Auth File driver
|
||||
'users' => array(
|
||||
// 'admin' => 'b3154acf3a344170077d11bdb5fff31532f679a1919e716a02',
|
||||
),
|
||||
|
||||
);
|
||||
);
|
||||
|
@@ -1,23 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
return array(
|
||||
// Leave this alone
|
||||
'modules' => array(
|
||||
|
||||
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
|
||||
'auth' => array(
|
||||
|
||||
// Whether this modules userguide pages should be shown
|
||||
'enabled' => TRUE,
|
||||
|
||||
// The name that should show up on the userguide index page
|
||||
'name' => 'Auth',
|
||||
|
||||
// A short description of this module, shown on the index page
|
||||
'description' => 'User authentication and authorization.',
|
||||
|
||||
// Copyright message, shown in the footer for this module
|
||||
'copyright' => '© 2008–2010 Kohana Team',
|
||||
)
|
||||
)
|
||||
);
|
@@ -1,48 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS `roles` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(32) NOT NULL,
|
||||
`description` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `roles` (`id`, `name`, `description`) VALUES(1, 'login', 'Login privileges, granted after account confirmation');
|
||||
INSERT INTO `roles` (`id`, `name`, `description`) VALUES(2, 'admin', 'Administrative user, has access to everything.');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `roles_users` (
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`role_id` int(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`user_id`,`role_id`),
|
||||
KEY `fk_role_id` (`role_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`email` varchar(127) NOT NULL,
|
||||
`username` varchar(32) NOT NULL DEFAULT '',
|
||||
`password` char(50) NOT NULL,
|
||||
`logins` int(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`last_login` int(10) UNSIGNED,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_username` (`username`),
|
||||
UNIQUE KEY `uniq_email` (`email`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_tokens` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) UNSIGNED NOT NULL,
|
||||
`user_agent` varchar(40) NOT NULL,
|
||||
`token` varchar(32) NOT NULL,
|
||||
`created` int(10) UNSIGNED NOT NULL,
|
||||
`expires` int(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_token` (`token`),
|
||||
KEY `fk_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `roles_users`
|
||||
ADD CONSTRAINT `roles_users_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `roles_users_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE `user_tokens`
|
||||
ADD CONSTRAINT `user_tokens_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
|
@@ -1,53 +0,0 @@
|
||||
CREATE TABLE roles
|
||||
(
|
||||
id serial,
|
||||
"name" varchar(32) NOT NULL,
|
||||
description text NOT NULL,
|
||||
CONSTRAINT roles_id_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT roles_name_key UNIQUE (name)
|
||||
);
|
||||
|
||||
CREATE TABLE roles_users
|
||||
(
|
||||
user_id integer,
|
||||
role_id integer
|
||||
);
|
||||
|
||||
CREATE TABLE users
|
||||
(
|
||||
id serial,
|
||||
email varchar(318) NOT NULL,
|
||||
username varchar(32) NOT NULL,
|
||||
"password" varchar(50) NOT NULL,
|
||||
logins integer NOT NULL DEFAULT 0,
|
||||
last_login integer,
|
||||
CONSTRAINT users_id_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT users_username_key UNIQUE (username),
|
||||
CONSTRAINT users_email_key UNIQUE (email),
|
||||
CONSTRAINT users_logins_check CHECK (logins >= 0)
|
||||
);
|
||||
|
||||
CREATE TABLE user_tokens
|
||||
(
|
||||
id serial,
|
||||
user_id integer NOT NULL,
|
||||
user_agent varchar(40) NOT NULL,
|
||||
token character varying(32) NOT NULL,
|
||||
created integer NOT NULL,
|
||||
expires integer NOT NULL,
|
||||
CONSTRAINT user_tokens_id_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT user_tokens_token_key UNIQUE (token)
|
||||
);
|
||||
|
||||
CREATE INDEX user_id_idx ON roles_users (user_id);
|
||||
CREATE INDEX role_id_idx ON roles_users (role_id);
|
||||
|
||||
ALTER TABLE roles_users
|
||||
ADD CONSTRAINT user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT role_id_fkey FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE user_tokens
|
||||
ADD CONSTRAINT user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO roles (name, description) VALUES ('login', 'Login privileges, granted after account confirmation');
|
||||
INSERT INTO roles (name, description) VALUES ('admin', 'Administrative user, has access to everything.');
|
Reference in New Issue
Block a user