NOTE: Before you can use this tutorial, be sure to followed the previous one http://kerkness.ca/wiki/doku.php?id=extending_the_model_auth_user_class
If you haven't got the db tables yet, here is the MySQL code
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'), (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 DEFAULT NULL, 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;
function action_register() { #If user already signed-in if(Auth::instance()->logged_in()!= 0){ #redirect to the user account Request::instance()->redirect('account/myaccount'); } #Load the view $content = $this->template->content = View::factory('register'); #If there is a post and $_POST is not empty if ($_POST) { #Instantiate a new user $user = ORM::factory('user'); #Load the validation rules, filters etc... $post = $user->validate_create($_POST); #If the post data validates using the rules setup in the user model if ($post->check()) { #Affects the sanitized vars to the user object $user->values($post); #create the account $user->save(); #Add the login role to the user $login_role = new Model_Role(array('name' =>'login')); $user->add('roles',$login_role); #sign the user in Auth::instance()->login($post['username'], $post['password']); #redirect to the user account Request::instance()->redirect('account/myaccount'); } else { #Get errors for display in view $content->errors = $post->errors('register'); } } } public function action_signin() { #If user already signed-in if(Auth::instance()->logged_in()!= 0){ #redirect to the user account Request::instance()->redirect('account/myaccount'); } $content = $this->template->content = View::factory('signin'); #If there is a post and $_POST is not empty if ($_POST) { #Instantiate a new user $user = ORM::factory('user'); #Check Auth $status = $user->login($_POST); #If the post data validates using the rules setup in the user model if ($status) { #redirect to the user account Request::instance()->redirect('account/myaccount'); }else { #Get errors for display in view $content->errors = $_POST->errors('signin'); } } } public function action_signout() { #Sign out the user Auth::instance()->logout(); #redirect to the user account and then the signin page if logout worked as expected Request::instance()->redirect('account/myaccount'); }
Example of a layout controller extending Controller_Template:
<?php defined('SYSPATH') or die('No direct script access.'); class Controller_Layout extends Controller_Template { public $template = 'layout'; // Controls access for the whole controller, if not set to FALSE we will only allow user roles specified // Can be set to a string or an array, for example 'login' or array('login', 'admin') // Note that in second(array) example, user must have both 'login' AND 'admin' roles set in database public $auth_required = FALSE; // Controls access for separate actions // 'adminpanel' => 'admin' will only allow users with the role admin to access action_adminpanel // 'moderatorpanel' => array('login', 'moderator') will only allow users with the roles login and moderator to access action_moderatorpanel public $secure_actions = FALSE; /** * The before() method is called before your controller action. * In our template controller we override this method so that we can * set up default values. These variables are then available to our * controllers if they need to be modified. */ public function before() { parent::before(); #Open session $this->session= Session::instance(); #Check user auth and role $action_name = Request::instance()->action; if (($this->auth_required !== FALSE && Auth::instance()->logged_in($this->auth_required) === FALSE) || (is_array($this->secure_actions) && array_key_exists($action_name, $this->secure_actions) && Auth::instance()->logged_in($this->secure_actions[$action_name]) === FALSE)) { if (Auth::instance()->logged_in()){ Request::instance()->redirect('account/noaccess'); }else{ Request::instance()->redirect('account/signin'); } } if ($this->auto_render) { // Initialize empty values $this->template->title = ''; $this->template->content = ''; $this->template->styles = array(); $this->template->scripts = array(); } } /** * The after() method is called after your controller action. * In our template controller we override this method so that we can * make any last minute modifications to the template before anything * is rendered. */ public function after() { if ($this->auto_render) { $styles = array( 'css/main.css' => 'screen', ); $scripts = array( 'js/jquery-1.3.2.min.js', ); $this->template->styles = array_merge( $this->template->styles, $styles ); $this->template->scripts = array_merge( $this->template->scripts, $scripts ); } parent::after(); } } //End of ./application/controller/layout.php
Controller authorized to login and admin roles:
<?php defined('SYSPATH') or die('No direct script access.'); class Controller_Admin extends Controller_Layout { public $auth_required = array('login','admin'); //Auth is required to access this controller function action_index(){ $this->template->content = View::factory('adminindex'); } } // End of ./application/controller/admin.php
Only login and admin roles can post, edit, delete. Anyone (even not logged in) can view:
<?php defined('SYSPATH') or die('No direct script access.'); class Controller_Admin extends Controller_Layout { public $secure_actions = array('post' => array('login','admin'), 'edit' => array('login','admin'), 'delete' => array('login','admin')); function action_index(){ } function action_view(){ } function action_post(){ } function action_edit(){ } function action_delete(){ } } // End of ./application/controller/admin.php