Auth (A1) and ACL (A2, ACL): Pt 2, the Model
I’m no model lady. A model’s just an imitation of the real thing. – Mae West
Part 1: Introduction
Part 2: The Data Model
Part 3: The Controller
Part 4: It becomes a module
Part 5: Adding ACL
Need a Database
-- -- Table structure for table `roles` -- DROP TABLE IF EXISTS `roles`; CREATE TABLE IF NOT EXISTS `roles` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `description` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; -- -- Dumping data for table `roles` -- INSERT INTO `roles` (`id`, `name`, `description`) VALUES (1, 'login', NULL), (2, 'admin', NULL); -- -------------------------------------------------------- -- -- Table structure for table `roles_users` -- DROP TABLE IF EXISTS `roles_users`; CREATE TABLE IF NOT EXISTS `roles_users` ( `user_id` int(11) NOT NULL, `role_id` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- -- -- Table structure for table `users` -- DROP TABLE IF EXISTS `users`; CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL, `password` char(64) NOT NULL, `email` varchar(127) DEFAULT NULL, `created` int(11) NOT NULL, `modified` int(11) DEFAULT NULL, `logins` int(10) unsigned NOT NULL DEFAULT '0', `last_login` int(10) unsigned DEFAULT NULL, `failed_logins` int(10) unsigned NOT NULL DEFAULT '0', `last_failure` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
And a Model to access the table
Don’t need a Model_Role because the default one in orm/classes/Model/Auth/Role.php will do nicely
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Default A1 (auth) user
* Extend from Wouterrrs A1_User_ORM module
* (not Kohana ORM User, modulesormclassesModelAuthUser.php)
*
* @package Silver-Bullet Auth
* @author Silver-Bullet
* @copyright (c) 2013
* @license http://kohanaframework.org/license
*/
class Model_User extends Model_A1_User_ORM implements Acl_Role_Interface {
/**
* set ORM class variables because we want these fields (created, modified)
* automatically updated
* format=TRUE means we use UTC (Universal Time Coordinated)
* could have used 'format' => 'Y-m-d H:i:s' BUT UTC is better
* in this instance because:
* 1. We don't need to do MySQL date manipulations
* 2. Timestamps unambiguously reference a particular point in time
* 3. Easy to manipulate with PHP
*/
protected $_created_column = array('column' => 'created',
'format' => TRUE);
protected $_updated_column = array('column' => 'modified',
'format' => TRUE);
/**
* A user can have many roles
*/
protected $_has_many = array(
'roles' => array(
'model' => 'Role',
'through' => 'User_Role'));
// default filters
protected $_filters = array(
TRUE => array(
'trim' => NULL
)
);
// default rules
protected $_rules = array(
'username' => array(
array('not_empty'),
array('min_length', array(':value',4)),
array('max_length', array(':value',30)),
array('alpha_dash')
),
'email' => array(
array('not_empty'),
array('email'),
array('email_domain')
),
'password' => array(
'not_empty' => NULL,
'min_length' => array(5),
'max_length' => array(42),
),
'password_confirm' => array(
'matches' => array('password'),
)
);
protected $_callbacks = array(
'username' => array('username_available')
);
/**
* Columns to ignore, password_confirm does not exist in
* the User table, it is just used for the validation rule
*/
protected $_ignored_columns = array('password_confirm');
/**
* get user role(s)
* Return the names of the roles for the given user.
* These need to match the roles defined in the configuration
* file (a2.php).
* NB: The configuration file (a2.php) and role values in the
* database (Roles) must be kept in sync.
*
* @return array Array of available roles
*/
public function get_role_id()
{
$roles = array();
foreach( $this->roles->find_all() as $role)
{
$roles[] = $role->name;
}
return $roles;
}
/**
* Tests if a username exists in the database. This can be used as a
* Valdidation callback.
*
* @param object Validate object
* @param string Field
* @param array Array with errors
* @return array (Updated) array with errors
*/
public function username_available(Validate $array, $field)
{
if ($this->loaded() AND $this->_object[$field] === $array[$field])
{
// This value is unchanged
return TRUE;
}
if( ORM::factory($this->_user_model)->where($field,'=',$array[$field])->find_all(1)->count() )
{
$array->error($field,'username_available');
}
}
} // End User Model
