2008-05-30 11:40:08 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Authentication component
|
|
|
|
*
|
|
|
|
* Manages user logins and permissions.
|
|
|
|
*
|
2010-10-03 16:38:58 +00:00
|
|
|
* PHP 5
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2009-11-06 06:46:59 +00:00
|
|
|
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
2011-05-29 21:31:39 +00:00
|
|
|
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* Licensed under The MIT License
|
|
|
|
* Redistributions of files must retain the above copyright notice.
|
|
|
|
*
|
2011-05-29 21:31:39 +00:00
|
|
|
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
2009-11-06 06:00:11 +00:00
|
|
|
* @link http://cakephp.org CakePHP(tm) Project
|
2011-07-26 06:16:14 +00:00
|
|
|
* @package Cake.Controller.Component
|
2008-10-30 17:30:26 +00:00
|
|
|
* @since CakePHP(tm) v 0.10.0.1076
|
2009-11-06 06:51:51 +00:00
|
|
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
|
|
|
|
2011-02-22 02:58:30 +00:00
|
|
|
|
2011-01-28 06:36:30 +00:00
|
|
|
App::uses('Component', 'Controller');
|
2010-12-04 07:04:30 +00:00
|
|
|
App::uses('Router', 'Routing');
|
2010-12-15 05:50:02 +00:00
|
|
|
App::uses('Security', 'Utility');
|
2010-12-04 07:04:30 +00:00
|
|
|
App::uses('Debugger', 'Utility');
|
2011-02-22 02:58:30 +00:00
|
|
|
App::uses('CakeSession', 'Model/Datasource');
|
2011-03-05 22:24:42 +00:00
|
|
|
App::uses('BaseAuthorize', 'Controller/Component/Auth');
|
|
|
|
App::uses('BaseAuthenticate', 'Controller/Component/Auth');
|
2008-05-30 11:40:08 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Authentication control component class
|
|
|
|
*
|
|
|
|
* Binds access control with user authentication and session management.
|
|
|
|
*
|
2011-07-26 06:16:14 +00:00
|
|
|
* @package Cake.Controller.Component
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1250/Authentication
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-07-04 19:12:42 +00:00
|
|
|
class AuthComponent extends Component {
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2011-01-22 00:56:23 +00:00
|
|
|
const ALL = 'all';
|
2011-01-21 22:55:04 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Other components utilized by AuthComponent
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $components = array('Session', 'RequestHandler');
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 23:18:42 +00:00
|
|
|
* An array of authentication objects to use for authenticating users. You can configure
|
|
|
|
* multiple adapters and they will be checked sequentially when users are identified.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-21 22:55:04 +00:00
|
|
|
* {{{
|
|
|
|
* $this->Auth->authenticate = array(
|
|
|
|
* 'Form' => array(
|
|
|
|
* 'userModel' => 'Users.User'
|
|
|
|
* )
|
|
|
|
* );
|
|
|
|
* }}}
|
|
|
|
*
|
|
|
|
* Using the class name without 'Authenticate' as the key, you can pass in an array of settings for each
|
|
|
|
* authentication object. Additionally you can define settings that should be set to all authentications objects
|
2011-01-25 03:13:39 +00:00
|
|
|
* using the 'all' key:
|
2011-01-21 22:55:04 +00:00
|
|
|
*
|
|
|
|
* {{{
|
|
|
|
* $this->Auth->authenticate = array(
|
2011-01-25 03:13:39 +00:00
|
|
|
* 'all' => array(
|
2011-01-21 22:55:04 +00:00
|
|
|
* 'userModel' => 'Users.User',
|
|
|
|
* 'scope' => array('User.active' => 1)
|
|
|
|
* ),
|
|
|
|
* 'Form',
|
|
|
|
* 'Basic'
|
|
|
|
* );
|
|
|
|
* }}}
|
|
|
|
*
|
2011-01-25 03:13:39 +00:00
|
|
|
* You can also use AuthComponent::ALL instead of the string 'all'.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-21 22:55:04 +00:00
|
|
|
* @var array
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1278/authenticate
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-03 23:18:42 +00:00
|
|
|
public $authenticate = array('Form');
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 23:18:42 +00:00
|
|
|
* Objects that will be used for authentication checks.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-03 23:18:42 +00:00
|
|
|
* @var array
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-03 23:18:42 +00:00
|
|
|
protected $_authenticateObjects = array();
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 23:18:42 +00:00
|
|
|
* An array of authorization objects to use for authorizing users. You can configure
|
|
|
|
* multiple adapters and they will be checked sequentially when authorization checks are done.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-21 22:55:04 +00:00
|
|
|
* {{{
|
|
|
|
* $this->Auth->authorize = array(
|
|
|
|
* 'Crud' => array(
|
|
|
|
* 'actionPath' => 'controllers/'
|
|
|
|
* )
|
|
|
|
* );
|
|
|
|
* }}}
|
|
|
|
*
|
|
|
|
* Using the class name without 'Authorize' as the key, you can pass in an array of settings for each
|
|
|
|
* authorization object. Additionally you can define settings that should be set to all authorization objects
|
2011-01-25 03:13:39 +00:00
|
|
|
* using the 'all' key:
|
2011-01-21 22:55:04 +00:00
|
|
|
*
|
|
|
|
* {{{
|
|
|
|
* $this->Auth->authorize = array(
|
2011-01-25 03:13:39 +00:00
|
|
|
* 'all' => array(
|
2011-01-21 22:55:04 +00:00
|
|
|
* 'actionPath' => 'controllers/'
|
|
|
|
* ),
|
|
|
|
* 'Crud',
|
|
|
|
* 'CustomAuth'
|
|
|
|
* );
|
|
|
|
* }}}
|
|
|
|
*
|
2011-01-25 03:13:39 +00:00
|
|
|
* You can also use AuthComponent::ALL instead of the string 'all'
|
|
|
|
*
|
2008-05-30 11:40:08 +00:00
|
|
|
* @var mixed
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1275/authorize
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $authorize = false;
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2009-08-13 15:18:46 +00:00
|
|
|
/**
|
2011-01-03 21:48:16 +00:00
|
|
|
* Objects that will be used for authorization checks.
|
2009-08-13 15:18:46 +00:00
|
|
|
*
|
2011-01-03 21:48:16 +00:00
|
|
|
* @var array
|
2009-08-13 15:18:46 +00:00
|
|
|
*/
|
2011-01-03 21:48:16 +00:00
|
|
|
protected $_authorizeObjects = array();
|
2009-08-13 15:18:46 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* The name of an optional view element to render when an Ajax request is made
|
|
|
|
* with an invalid or expired session
|
|
|
|
*
|
|
|
|
* @var string
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1277/ajaxLogin
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $ajaxLogin = null;
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-19 21:17:17 +00:00
|
|
|
* Settings to use when Auth needs to do a flash message with SessionComponent::setFlash().
|
|
|
|
* Available keys are:
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-19 21:17:17 +00:00
|
|
|
* - `element` - The element to use, defaults to 'default'.
|
|
|
|
* - `key` - The key to use, defaults to 'auth'
|
|
|
|
* - `params` - The array of additional params to use, defaults to array()
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2011-01-19 21:17:17 +00:00
|
|
|
public $flash = array(
|
|
|
|
'element' => 'default',
|
|
|
|
'key' => 'auth',
|
|
|
|
'params' => array()
|
|
|
|
);
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* The session key name where the record of the current user is stored. If
|
2011-01-19 21:53:58 +00:00
|
|
|
* unspecified, it will be "Auth.User".
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* @var string
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1276/sessionKey
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-21 21:55:02 +00:00
|
|
|
public static $sessionKey = 'Auth.User';
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* A URL (defined as a string or array) to the controller action that handles
|
2011-01-19 21:53:58 +00:00
|
|
|
* logins. Defaults to `/users/login`
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* @var mixed
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1269/loginAction
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-19 21:53:58 +00:00
|
|
|
public $loginAction = array(
|
|
|
|
'controller' => 'users',
|
|
|
|
'action' => 'login',
|
|
|
|
'plugin' => null
|
|
|
|
);
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Normally, if a user is redirected to the $loginAction page, the location they
|
|
|
|
* were redirected from will be stored in the session so that they can be
|
|
|
|
* redirected back after a successful login. If this session value is not
|
|
|
|
* set, the user will be redirected to the page specified in $loginRedirect.
|
|
|
|
*
|
|
|
|
* @var mixed
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1270/loginRedirect
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $loginRedirect = null;
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2010-07-19 22:17:02 +00:00
|
|
|
* The default action to redirect to after the user is logged out. While AuthComponent does
|
2008-05-30 11:40:08 +00:00
|
|
|
* not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout().
|
|
|
|
* Defaults to AuthComponent::$loginAction.
|
|
|
|
*
|
|
|
|
* @var mixed
|
|
|
|
* @see AuthComponent::$loginAction
|
|
|
|
* @see AuthComponent::logout()
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1271/logoutRedirect
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $logoutRedirect = null;
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Error to display when user attempts to access an object or action to which they do not have
|
|
|
|
* acccess.
|
|
|
|
*
|
|
|
|
* @var string
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1273/authError
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $authError = null;
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Controller actions for which user validation is not required.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
* @see AuthComponent::allow()
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1251/Setting-Auth-Component-Variables
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-04 07:14:00 +00:00
|
|
|
public $allowedActions = array();
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2010-05-15 04:55:15 +00:00
|
|
|
/**
|
|
|
|
* Request object
|
|
|
|
*
|
|
|
|
* @var CakeRequest
|
|
|
|
*/
|
|
|
|
public $request;
|
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-22 00:56:23 +00:00
|
|
|
* Response object
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-22 00:56:23 +00:00
|
|
|
* @var CakeResponse
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-22 00:56:23 +00:00
|
|
|
public $response;
|
2010-07-31 19:41:28 +00:00
|
|
|
|
2008-10-15 02:52:19 +00:00
|
|
|
/**
|
|
|
|
* Method list for bound controller
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2010-04-04 06:36:12 +00:00
|
|
|
protected $_methods = array();
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Initializes AuthComponent for use in the controller
|
|
|
|
*
|
|
|
|
* @param object $controller A reference to the instantiating controller object
|
2008-09-25 16:49:56 +00:00
|
|
|
* @return void
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-12-18 05:03:03 +00:00
|
|
|
public function initialize($controller) {
|
2010-05-15 04:55:15 +00:00
|
|
|
$this->request = $controller->request;
|
2011-01-22 00:56:23 +00:00
|
|
|
$this->response = $controller->response;
|
2008-11-11 16:34:05 +00:00
|
|
|
$this->_methods = $controller->methods;
|
2008-05-30 11:40:08 +00:00
|
|
|
|
2010-07-07 02:46:08 +00:00
|
|
|
if (Configure::read('debug') > 0) {
|
2010-01-15 21:56:26 +00:00
|
|
|
Debugger::checkSecurityKeys();
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Main execution method. Handles redirecting of invalid users, and processing
|
|
|
|
* of login form data.
|
|
|
|
*
|
|
|
|
* @param object $controller A reference to the instantiating controller object
|
2008-09-25 16:49:56 +00:00
|
|
|
* @return boolean
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-12-18 05:03:03 +00:00
|
|
|
public function startup($controller) {
|
2011-01-21 02:22:54 +00:00
|
|
|
if ($controller->name == 'CakeError') {
|
2008-10-15 02:52:19 +00:00
|
|
|
return true;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-02-06 23:23:12 +00:00
|
|
|
|
2010-01-20 22:18:55 +00:00
|
|
|
$methods = array_flip($controller->methods);
|
2010-07-10 16:00:09 +00:00
|
|
|
$action = $controller->request->params['action'];
|
2010-07-28 02:32:08 +00:00
|
|
|
|
2009-02-06 23:23:12 +00:00
|
|
|
$isMissingAction = (
|
|
|
|
$controller->scaffold === false &&
|
2009-07-03 00:20:54 +00:00
|
|
|
!isset($methods[$action])
|
2009-02-06 23:23:12 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if ($isMissingAction) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
if (!$this->__setDefaults()) {
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-13 04:05:44 +00:00
|
|
|
$request = $controller->request;
|
2011-01-21 21:22:29 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
$url = '';
|
2008-10-15 02:52:19 +00:00
|
|
|
|
2011-02-21 02:52:20 +00:00
|
|
|
if (isset($request->url)) {
|
|
|
|
$url = $request->url;
|
2008-07-31 19:00:12 +00:00
|
|
|
}
|
2008-05-30 11:40:08 +00:00
|
|
|
$url = Router::normalize($url);
|
|
|
|
$loginAction = Router::normalize($this->loginAction);
|
2009-02-06 23:23:12 +00:00
|
|
|
|
2010-07-10 16:00:09 +00:00
|
|
|
$allowedActions = $this->allowedActions;
|
2008-09-20 20:18:16 +00:00
|
|
|
$isAllowed = (
|
|
|
|
$this->allowedActions == array('*') ||
|
2009-07-03 00:20:54 +00:00
|
|
|
in_array($action, $allowedActions)
|
2008-09-20 20:18:16 +00:00
|
|
|
);
|
2008-05-31 12:36:38 +00:00
|
|
|
|
2008-09-20 20:18:16 +00:00
|
|
|
if ($loginAction != $url && $isAllowed) {
|
2008-10-15 02:52:19 +00:00
|
|
|
return true;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($loginAction == $url) {
|
2011-01-20 22:50:18 +00:00
|
|
|
if (empty($request->data)) {
|
2010-01-12 04:54:06 +00:00
|
|
|
if (!$this->Session->check('Auth.redirect') && !$this->loginRedirect && env('HTTP_REFERER')) {
|
2008-11-14 09:07:22 +00:00
|
|
|
$this->Session->write('Auth.redirect', $controller->referer(null, true));
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2011-02-17 12:44:41 +00:00
|
|
|
return true;
|
2008-05-30 11:40:08 +00:00
|
|
|
} else {
|
2011-02-05 23:41:00 +00:00
|
|
|
if (!$this->_getUser()) {
|
2010-09-15 02:12:14 +00:00
|
|
|
if (!$request->is('ajax')) {
|
2011-01-19 21:17:17 +00:00
|
|
|
$this->flash($this->authError);
|
2011-01-21 02:22:54 +00:00
|
|
|
$this->Session->write('Auth.redirect', Router::reverse($request));
|
2008-09-12 02:10:55 +00:00
|
|
|
$controller->redirect($loginAction);
|
2008-05-30 11:40:08 +00:00
|
|
|
return false;
|
|
|
|
} elseif (!empty($this->ajaxLogin)) {
|
2011-05-13 07:45:04 +00:00
|
|
|
$controller->viewPath = 'Elements';
|
2008-09-20 20:18:16 +00:00
|
|
|
echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
|
2008-06-04 19:04:58 +00:00
|
|
|
$this->_stop();
|
2008-05-30 11:40:08 +00:00
|
|
|
return false;
|
2008-09-12 02:10:55 +00:00
|
|
|
} else {
|
|
|
|
$controller->redirect(null, 403);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-03-23 14:39:12 +00:00
|
|
|
if (empty($this->authorize) || $this->isAuthorized($this->user())) {
|
2008-05-30 11:40:08 +00:00
|
|
|
return true;
|
|
|
|
}
|
2008-05-31 12:36:38 +00:00
|
|
|
|
2011-01-19 21:17:17 +00:00
|
|
|
$this->flash($this->authError);
|
2011-06-10 00:34:17 +00:00
|
|
|
$controller->redirect($controller->referer('/'), null, true);
|
2008-05-31 12:36:38 +00:00
|
|
|
return false;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Attempts to introspect the correct values for object properties including
|
|
|
|
* $userModel and $sessionKey.
|
|
|
|
*
|
|
|
|
* @param object $controller A reference to the instantiating controller object
|
2008-09-25 16:49:56 +00:00
|
|
|
* @return boolean
|
2008-05-30 11:40:08 +00:00
|
|
|
* @access private
|
|
|
|
*/
|
|
|
|
function __setDefaults() {
|
2008-05-31 12:36:38 +00:00
|
|
|
$defaults = array(
|
|
|
|
'logoutRedirect' => $this->loginAction,
|
2011-03-12 18:59:40 +00:00
|
|
|
'authError' => __d('cake', 'You are not authorized to access that location.')
|
2008-05-31 12:36:38 +00:00
|
|
|
);
|
|
|
|
foreach ($defaults as $key => $value) {
|
|
|
|
if (empty($this->{$key})) {
|
|
|
|
$this->{$key} = $value;
|
|
|
|
}
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 21:48:16 +00:00
|
|
|
* Uses the configured Authorization adapters to check whether or not a user is authorized.
|
2011-03-19 17:07:05 +00:00
|
|
|
* Each adapter will be checked in sequence, if any of them return true, then the user will
|
2011-01-03 21:48:16 +00:00
|
|
|
* be authorized for the request.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-03 23:18:42 +00:00
|
|
|
* @param mixed $user The user to check the authorization of. If empty the user in the session will be used.
|
|
|
|
* @param CakeRequest $request The request to authenticate for. If empty, the current request will be used.
|
2008-05-30 11:40:08 +00:00
|
|
|
* @return boolean True if $user is authorized, otherwise false
|
|
|
|
*/
|
2011-01-03 23:18:42 +00:00
|
|
|
public function isAuthorized($user = null, $request = null) {
|
2008-05-30 11:40:08 +00:00
|
|
|
if (empty($user) && !$this->user()) {
|
|
|
|
return false;
|
|
|
|
} elseif (empty($user)) {
|
|
|
|
$user = $this->user();
|
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
if (empty($request)) {
|
|
|
|
$request = $this->request;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
if (empty($this->_authorizeObjects)) {
|
2011-01-09 05:33:06 +00:00
|
|
|
$this->constructAuthorize();
|
2011-01-03 23:18:42 +00:00
|
|
|
}
|
2011-01-03 21:48:16 +00:00
|
|
|
foreach ($this->_authorizeObjects as $authorizer) {
|
2011-01-03 23:18:42 +00:00
|
|
|
if ($authorizer->authorize($user, $request) === true) {
|
2008-05-30 11:40:08 +00:00
|
|
|
return true;
|
2011-01-03 21:48:16 +00:00
|
|
|
}
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 21:48:16 +00:00
|
|
|
return false;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 21:48:16 +00:00
|
|
|
* Loads the authorization objects configured.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-03 21:48:16 +00:00
|
|
|
* @return mixed Either null when authorize is empty, or the loaded authorization objects.
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-09 05:33:06 +00:00
|
|
|
public function constructAuthorize() {
|
2011-01-03 21:48:16 +00:00
|
|
|
if (empty($this->authorize)) {
|
|
|
|
return;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
$this->_authorizeObjects = array();
|
2011-01-21 22:55:04 +00:00
|
|
|
$config = Set::normalize($this->authorize);
|
|
|
|
$global = array();
|
|
|
|
if (isset($config[AuthComponent::ALL])) {
|
|
|
|
$global = $config[AuthComponent::ALL];
|
|
|
|
unset($config[AuthComponent::ALL]);
|
|
|
|
}
|
|
|
|
foreach ($config as $class => $settings) {
|
2011-03-05 22:10:42 +00:00
|
|
|
list($plugin, $class) = pluginSplit($class, true);
|
2011-01-03 21:48:16 +00:00
|
|
|
$className = $class . 'Authorize';
|
2011-03-05 22:10:42 +00:00
|
|
|
App::uses($className, $plugin . 'Controller/Component/Auth');
|
|
|
|
if (!class_exists($className)) {
|
2011-03-20 15:35:43 +00:00
|
|
|
throw new CakeException(__d('cake_dev', 'Authorization adapter "%s" was not found.', $class));
|
2011-01-03 21:48:16 +00:00
|
|
|
}
|
|
|
|
if (!method_exists($className, 'authorize')) {
|
2011-03-20 15:35:43 +00:00
|
|
|
throw new CakeException(__d('cake_dev', 'Authorization objects must implement an authorize method.'));
|
2011-01-03 21:48:16 +00:00
|
|
|
}
|
2011-01-21 22:55:04 +00:00
|
|
|
$settings = array_merge($global, (array)$settings);
|
2011-02-18 04:17:07 +00:00
|
|
|
$this->_authorizeObjects[] = new $className($this->_Collection, $settings);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 21:48:16 +00:00
|
|
|
return $this->_authorizeObjects;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Takes a list of actions in the current controller for which authentication is not required, or
|
|
|
|
* no parameters to allow all actions.
|
|
|
|
*
|
2011-01-21 02:34:39 +00:00
|
|
|
* You can use allow with either an array, or var args.
|
|
|
|
*
|
2011-03-19 17:07:05 +00:00
|
|
|
* `$this->Auth->allow(array('edit', 'add'));` or
|
2011-01-21 02:34:39 +00:00
|
|
|
* `$this->Auth->allow('edit', 'add');`
|
|
|
|
*
|
|
|
|
* allow() also supports '*' as a wildcard to mean all actions.
|
|
|
|
*
|
|
|
|
* `$this->Auth->allow('*');`
|
|
|
|
*
|
2009-08-13 16:08:30 +00:00
|
|
|
* @param mixed $action Controller action name or array of actions
|
2008-05-30 11:40:08 +00:00
|
|
|
* @param string $action Controller action name
|
|
|
|
* @param string ... etc.
|
2008-09-25 16:49:56 +00:00
|
|
|
* @return void
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1257/allow
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-05 03:19:38 +00:00
|
|
|
public function allow() {
|
2008-05-30 11:40:08 +00:00
|
|
|
$args = func_get_args();
|
2008-10-15 02:52:19 +00:00
|
|
|
if (empty($args) || $args == array('*')) {
|
|
|
|
$this->allowedActions = $this->_methods;
|
2008-05-30 11:40:08 +00:00
|
|
|
} else {
|
|
|
|
if (isset($args[0]) && is_array($args[0])) {
|
|
|
|
$args = $args[0];
|
|
|
|
}
|
2010-07-10 16:00:09 +00:00
|
|
|
$this->allowedActions = array_merge($this->allowedActions, $args);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-21 02:34:39 +00:00
|
|
|
* Removes items from the list of allowed/no authentication required actions.
|
|
|
|
*
|
|
|
|
* You can use deny with either an array, or var args.
|
|
|
|
*
|
2011-03-19 17:07:05 +00:00
|
|
|
* `$this->Auth->deny(array('edit', 'add'));` or
|
2011-01-21 02:34:39 +00:00
|
|
|
* `$this->Auth->deny('edit', 'add');`
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2009-08-13 16:08:30 +00:00
|
|
|
* @param mixed $action Controller action name or array of actions
|
2008-05-30 11:40:08 +00:00
|
|
|
* @param string $action Controller action name
|
|
|
|
* @param string ... etc.
|
2008-09-25 16:49:56 +00:00
|
|
|
* @return void
|
2008-05-30 11:40:08 +00:00
|
|
|
* @see AuthComponent::allow()
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1258/deny
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-05 03:19:38 +00:00
|
|
|
public function deny() {
|
2008-05-30 11:40:08 +00:00
|
|
|
$args = func_get_args();
|
2009-08-13 16:08:30 +00:00
|
|
|
if (isset($args[0]) && is_array($args[0])) {
|
|
|
|
$args = $args[0];
|
|
|
|
}
|
2008-05-30 11:40:08 +00:00
|
|
|
foreach ($args as $arg) {
|
2010-07-10 16:00:09 +00:00
|
|
|
$i = array_search($arg, $this->allowedActions);
|
2008-05-30 11:40:08 +00:00
|
|
|
if (is_int($i)) {
|
|
|
|
unset($this->allowedActions[$i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->allowedActions = array_values($this->allowedActions);
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-05 04:12:37 +00:00
|
|
|
* Maps action names to CRUD operations. Used for controller-based authentication. Make sure
|
|
|
|
* to configure the authorize property before calling this method. As it delegates $map to all the
|
|
|
|
* attached authorize objects.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* @param array $map Actions to map
|
2008-09-25 16:49:56 +00:00
|
|
|
* @return void
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1260/mapActions
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-05 03:19:38 +00:00
|
|
|
public function mapActions($map = array()) {
|
2011-01-05 04:12:37 +00:00
|
|
|
if (empty($this->_authorizeObjects)) {
|
2011-01-09 05:33:06 +00:00
|
|
|
$this->constructAuthorize();
|
2011-01-05 04:12:37 +00:00
|
|
|
}
|
|
|
|
foreach ($this->_authorizeObjects as $auth) {
|
|
|
|
$auth->mapActions($map);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-05 04:27:16 +00:00
|
|
|
* Log a user in. If a $user is provided that data will be stored as the logged in user. If `$user` is empty or not
|
2011-01-21 02:22:54 +00:00
|
|
|
* specified, the request will be used to identify a user. If the identification was successful,
|
2011-01-05 04:27:16 +00:00
|
|
|
* the user record is written to the session key specified in AuthComponent::$sessionKey.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-05 04:27:16 +00:00
|
|
|
* @param mixed $user Either an array of user data, or null to identify a user using the current request.
|
2008-05-30 11:40:08 +00:00
|
|
|
* @return boolean True on login success, false on failure
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1261/login
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-05 04:27:16 +00:00
|
|
|
public function login($user = null) {
|
2008-05-30 11:40:08 +00:00
|
|
|
$this->__setDefaults();
|
|
|
|
|
2011-01-05 04:27:16 +00:00
|
|
|
if (empty($user)) {
|
2011-01-22 00:56:23 +00:00
|
|
|
$user = $this->identify($this->request, $this->response);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-05 04:27:16 +00:00
|
|
|
if ($user) {
|
2011-01-21 21:55:02 +00:00
|
|
|
$this->Session->write(self::$sessionKey, $user);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-05-10 01:54:59 +00:00
|
|
|
return $this->loggedIn();
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Logs a user out, and returns the login action to redirect to.
|
2011-07-03 16:53:21 +00:00
|
|
|
* Triggers the logout() method of all the authenticate objects, so they can perform
|
|
|
|
* custom logout logic. AuthComponent will remove the session data, so
|
|
|
|
* there is no need to do that in an authentication object.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* @param mixed $url Optional URL to redirect the user to after logout
|
|
|
|
* @return string AuthComponent::$loginAction
|
|
|
|
* @see AuthComponent::$loginAction
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1262/logout
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2010-04-05 03:19:38 +00:00
|
|
|
public function logout() {
|
2008-05-30 11:40:08 +00:00
|
|
|
$this->__setDefaults();
|
2011-07-03 16:53:21 +00:00
|
|
|
if (empty($this->_authenticateObjects)) {
|
|
|
|
$this->constructAuthenticate();
|
|
|
|
}
|
|
|
|
$user = $this->user();
|
|
|
|
foreach ($this->_authenticateObjects as $auth) {
|
|
|
|
$auth->logout($user);
|
|
|
|
}
|
2011-01-21 21:55:02 +00:00
|
|
|
$this->Session->delete(self::$sessionKey);
|
2009-09-11 10:58:23 +00:00
|
|
|
$this->Session->delete('Auth.redirect');
|
2008-05-30 11:40:08 +00:00
|
|
|
return Router::normalize($this->logoutRedirect);
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Get the current user from the session.
|
|
|
|
*
|
2008-09-25 16:49:56 +00:00
|
|
|
* @param string $key field to retrive. Leave null to get entire User record
|
|
|
|
* @return mixed User record. or null if no user is logged in.
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1264/user
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-21 21:55:02 +00:00
|
|
|
public static function user($key = null) {
|
|
|
|
if (!CakeSession::check(self::$sessionKey)) {
|
2008-05-30 11:40:08 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($key == null) {
|
2011-01-21 21:55:02 +00:00
|
|
|
return CakeSession::read(self::$sessionKey);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-05-27 21:13:57 +00:00
|
|
|
|
|
|
|
$user = CakeSession::read(self::$sessionKey);
|
|
|
|
if (isset($user[$key])) {
|
|
|
|
return $user[$key];
|
|
|
|
}
|
|
|
|
return null;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-02-05 23:41:00 +00:00
|
|
|
* Similar to AuthComponent::user() except if the session user cannot be found, connected authentication
|
|
|
|
* objects will have their getUser() methods called. This lets stateless authentication methods function correctly.
|
|
|
|
*
|
|
|
|
* @return boolean true if a user can be found, false if one cannot.
|
|
|
|
*/
|
|
|
|
protected function _getUser() {
|
|
|
|
$user = $this->user();
|
|
|
|
if ($user) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (empty($this->_authenticateObjects)) {
|
|
|
|
$this->constructAuthenticate();
|
|
|
|
}
|
|
|
|
foreach ($this->_authenticateObjects as $auth) {
|
|
|
|
$result = $auth->getUser($this->request);
|
|
|
|
if (!empty($result) && is_array($result)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-03-19 17:07:05 +00:00
|
|
|
* If no parameter is passed, gets the authentication redirect URL. Pass a url in to
|
|
|
|
* set the destination a user should be redirected to upon logging in. Will fallback to
|
2011-01-21 02:39:59 +00:00
|
|
|
* AuthComponent::$loginRedirect if there is no stored redirect value.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
|
|
|
* @param mixed $url Optional URL to write as the login redirect URL.
|
|
|
|
* @return string Redirect URL
|
|
|
|
*/
|
2010-04-05 03:19:38 +00:00
|
|
|
public function redirect($url = null) {
|
2008-05-30 11:40:08 +00:00
|
|
|
if (!is_null($url)) {
|
2008-12-24 05:40:05 +00:00
|
|
|
$redir = $url;
|
|
|
|
$this->Session->write('Auth.redirect', $redir);
|
2008-12-17 07:30:55 +00:00
|
|
|
} elseif ($this->Session->check('Auth.redirect')) {
|
2008-05-30 11:40:08 +00:00
|
|
|
$redir = $this->Session->read('Auth.redirect');
|
|
|
|
$this->Session->delete('Auth.redirect');
|
|
|
|
|
|
|
|
if (Router::normalize($redir) == Router::normalize($this->loginAction)) {
|
|
|
|
$redir = $this->loginRedirect;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$redir = $this->loginRedirect;
|
|
|
|
}
|
|
|
|
return Router::normalize($redir);
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 23:18:42 +00:00
|
|
|
* Use the configured authentication adapters, and attempt to identify the user
|
|
|
|
* by credentials contained in $request.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-03 23:18:42 +00:00
|
|
|
* @param CakeRequest $request The request that contains authentication data.
|
|
|
|
* @return array User record data, or false, if the user could not be identified.
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-22 00:56:23 +00:00
|
|
|
public function identify(CakeRequest $request, CakeResponse $response) {
|
2011-01-03 23:18:42 +00:00
|
|
|
if (empty($this->_authenticateObjects)) {
|
2011-01-09 05:33:06 +00:00
|
|
|
$this->constructAuthenticate();
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
foreach ($this->_authenticateObjects as $auth) {
|
2011-01-22 00:56:23 +00:00
|
|
|
$result = $auth->authenticate($request, $response);
|
2011-01-03 23:18:42 +00:00
|
|
|
if (!empty($result) && is_array($result)) {
|
|
|
|
return $result;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
return false;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
2011-01-03 23:18:42 +00:00
|
|
|
* loads the configured authentication objects.
|
2008-05-30 11:40:08 +00:00
|
|
|
*
|
2011-01-03 23:18:42 +00:00
|
|
|
* @return mixed either null on empty authenticate value, or an array of loaded objects.
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-09 05:33:06 +00:00
|
|
|
public function constructAuthenticate() {
|
2011-01-03 23:18:42 +00:00
|
|
|
if (empty($this->authenticate)) {
|
|
|
|
return;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
$this->_authenticateObjects = array();
|
2011-01-21 22:55:04 +00:00
|
|
|
$config = Set::normalize($this->authenticate);
|
|
|
|
$global = array();
|
|
|
|
if (isset($config[AuthComponent::ALL])) {
|
|
|
|
$global = $config[AuthComponent::ALL];
|
|
|
|
unset($config[AuthComponent::ALL]);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-21 22:55:04 +00:00
|
|
|
foreach ($config as $class => $settings) {
|
2011-03-05 22:10:42 +00:00
|
|
|
list($plugin, $class) = pluginSplit($class, true);
|
2011-01-03 23:18:42 +00:00
|
|
|
$className = $class . 'Authenticate';
|
2011-03-05 22:10:42 +00:00
|
|
|
App::uses($className, $plugin . 'Controller/Component/Auth');
|
|
|
|
if (!class_exists($className)) {
|
2011-03-20 15:35:43 +00:00
|
|
|
throw new CakeException(__d('cake_dev', 'Authentication adapter "%s" was not found.', $class));
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
if (!method_exists($className, 'authenticate')) {
|
2011-03-20 15:35:43 +00:00
|
|
|
throw new CakeException(__d('cake_dev', 'Authentication objects must implement an authenticate method.'));
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-02-02 02:24:46 +00:00
|
|
|
$settings = array_merge($global, (array)$settings);
|
2011-02-18 04:17:07 +00:00
|
|
|
$this->_authenticateObjects[] = new $className($this->_Collection, $settings);
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2011-01-03 23:18:42 +00:00
|
|
|
return $this->_authenticateObjects;
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Hash a password with the application's salt value (as defined with Configure::write('Security.salt');
|
|
|
|
*
|
|
|
|
* @param string $password Password to hash
|
|
|
|
* @return string Hashed password
|
2010-04-05 01:12:13 +00:00
|
|
|
* @link http://book.cakephp.org/view/1263/password
|
2008-05-30 11:40:08 +00:00
|
|
|
*/
|
2011-01-30 21:06:01 +00:00
|
|
|
public static function password($password) {
|
2008-05-30 11:40:08 +00:00
|
|
|
return Security::hash($password, null, true);
|
|
|
|
}
|
2009-07-24 19:18:37 +00:00
|
|
|
|
2008-05-30 11:40:08 +00:00
|
|
|
/**
|
|
|
|
* Component shutdown. If user is logged in, wipe out redirect.
|
|
|
|
*
|
|
|
|
* @param object $controller Instantiating controller
|
|
|
|
*/
|
2010-12-18 05:03:03 +00:00
|
|
|
public function shutdown($controller) {
|
2011-05-10 01:54:59 +00:00
|
|
|
if ($this->loggedIn()) {
|
2009-09-11 10:58:23 +00:00
|
|
|
$this->Session->delete('Auth.redirect');
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-10 04:33:49 +00:00
|
|
|
|
|
|
|
/**
|
2011-05-10 01:54:59 +00:00
|
|
|
* Check whether or not the current user has data in the session, and is considered logged in.
|
2010-06-10 04:33:49 +00:00
|
|
|
*
|
|
|
|
* @return boolean true if the user is logged in, false otherwise
|
|
|
|
* @access public
|
|
|
|
*/
|
2011-05-10 01:54:59 +00:00
|
|
|
public function loggedIn() {
|
|
|
|
return $this->user() != array();
|
2010-06-10 04:33:49 +00:00
|
|
|
}
|
2011-01-19 21:17:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a flash message. Uses the Session component, and values from AuthComponent::$flash.
|
|
|
|
*
|
|
|
|
* @param string $message The message to set.
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function flash($message) {
|
|
|
|
$this->Session->setFlash($message, $this->flash['element'], $this->flash['params'], $this->flash['key']);
|
|
|
|
}
|
2008-05-30 11:40:08 +00:00
|
|
|
}
|