PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/controller/components/auth.php

https://github.com/mariuz/firetube
PHP | 879 lines | 483 code | 37 blank | 359 comment | 117 complexity | 0164f63c547712b9cb6ac0a4bdaf2b45 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Authentication component
  5. *
  6. * Manages user logins and permissions.
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  11. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  12. *
  13. * Licensed under The MIT License
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  17. * @link http://cakephp.org CakePHP(tm) Project
  18. * @package cake
  19. * @subpackage cake.cake.libs.controller.components
  20. * @since CakePHP(tm) v 0.10.0.1076
  21. * @version $Revision$
  22. * @modifiedby $LastChangedBy$
  23. * @lastmodified $Date$
  24. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  25. */
  26. App::import(array('Router', 'Security'));
  27. /**
  28. * Authentication control component class
  29. *
  30. * Binds access control with user authentication and session management.
  31. *
  32. * @package cake
  33. * @subpackage cake.cake.libs.controller.components
  34. */
  35. class AuthComponent extends Object {
  36. /**
  37. * Maintains current user login state.
  38. *
  39. * @var boolean
  40. * @access private
  41. */
  42. var $_loggedIn = false;
  43. /**
  44. * Other components utilized by AuthComponent
  45. *
  46. * @var array
  47. * @access public
  48. */
  49. var $components = array('Session', 'RequestHandler');
  50. /**
  51. * A reference to the object used for authentication
  52. *
  53. * @var object
  54. * @access public
  55. */
  56. var $authenticate = null;
  57. /**
  58. * The name of the component to use for Authorization or set this to
  59. * 'controller' will validate against Controller::isAuthorized()
  60. * 'actions' will validate Controller::action against an AclComponent::check()
  61. * 'crud' will validate mapActions against an AclComponent::check()
  62. * array('model'=> 'name'); will validate mapActions against model $name::isAuthorized(user, controller, mapAction)
  63. * 'object' will validate Controller::action against object::isAuthorized(user, controller, action)
  64. *
  65. * @var mixed
  66. * @access public
  67. */
  68. var $authorize = false;
  69. /**
  70. * The name of an optional view element to render when an Ajax request is made
  71. * with an invalid or expired session
  72. *
  73. * @var string
  74. * @access public
  75. */
  76. var $ajaxLogin = null;
  77. /**
  78. * The name of the model that represents users which will be authenticated. Defaults to 'User'.
  79. *
  80. * @var string
  81. * @access public
  82. */
  83. var $userModel = 'User';
  84. /**
  85. * Additional query conditions to use when looking up and authenticating users,
  86. * i.e. array('User.is_active' => 1).
  87. *
  88. * @var array
  89. * @access public
  90. */
  91. var $userScope = array();
  92. /**
  93. * Allows you to specify non-default login name and password fields used in
  94. * $userModel, i.e. array('username' => 'login_name', 'password' => 'passwd').
  95. *
  96. * @var array
  97. * @access public
  98. */
  99. var $fields = array('username' => 'username', 'password' => 'password');
  100. /**
  101. * The session key name where the record of the current user is stored. If
  102. * unspecified, it will be "Auth.{$userModel name}".
  103. *
  104. * @var string
  105. * @access public
  106. */
  107. var $sessionKey = null;
  108. /**
  109. * If using action-based access control, this defines how the paths to action
  110. * ACO nodes is computed. If, for example, all controller nodes are nested
  111. * under an ACO node named 'Controllers', $actionPath should be set to
  112. * "Controllers/".
  113. *
  114. * @var string
  115. * @access public
  116. */
  117. var $actionPath = null;
  118. /**
  119. * A URL (defined as a string or array) to the controller action that handles
  120. * logins.
  121. *
  122. * @var mixed
  123. * @access public
  124. */
  125. var $loginAction = null;
  126. /**
  127. * Normally, if a user is redirected to the $loginAction page, the location they
  128. * were redirected from will be stored in the session so that they can be
  129. * redirected back after a successful login. If this session value is not
  130. * set, the user will be redirected to the page specified in $loginRedirect.
  131. *
  132. * @var mixed
  133. * @access public
  134. */
  135. var $loginRedirect = null;
  136. /**
  137. * The the default action to redirect to after the user is logged out. While AuthComponent does
  138. * not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout().
  139. * Defaults to AuthComponent::$loginAction.
  140. *
  141. * @var mixed
  142. * @access public
  143. * @see AuthComponent::$loginAction
  144. * @see AuthComponent::logout()
  145. */
  146. var $logoutRedirect = null;
  147. /**
  148. * The name of model or model object, or any other object has an isAuthorized method.
  149. *
  150. * @var string
  151. * @access public
  152. */
  153. var $object = null;
  154. /**
  155. * Error to display when user login fails. For security purposes, only one error is used for all
  156. * login failures, so as not to expose information on why the login failed.
  157. *
  158. * @var string
  159. * @access public
  160. */
  161. var $loginError = null;
  162. /**
  163. * Error to display when user attempts to access an object or action to which they do not have
  164. * acccess.
  165. *
  166. * @var string
  167. * @access public
  168. */
  169. var $authError = null;
  170. /**
  171. * Determines whether AuthComponent will automatically redirect and exit if login is successful.
  172. *
  173. * @var boolean
  174. * @access public
  175. */
  176. var $autoRedirect = true;
  177. /**
  178. * Controller actions for which user validation is not required.
  179. *
  180. * @var array
  181. * @access public
  182. * @see AuthComponent::allow()
  183. */
  184. var $allowedActions = array();
  185. /**
  186. * Maps actions to CRUD operations. Used for controller-based validation ($validate = 'controller').
  187. *
  188. * @var array
  189. * @access public
  190. * @see AuthComponent::mapActions()
  191. */
  192. var $actionMap = array(
  193. 'index' => 'read',
  194. 'add' => 'create',
  195. 'edit' => 'update',
  196. 'view' => 'read',
  197. 'remove' => 'delete'
  198. );
  199. /**
  200. * Form data from Controller::$data
  201. *
  202. * @var array
  203. * @access public
  204. */
  205. var $data = array();
  206. /**
  207. * Parameter data from Controller::$params
  208. *
  209. * @var array
  210. * @access public
  211. */
  212. var $params = array();
  213. /**
  214. * Method list for bound controller
  215. *
  216. * @var array
  217. * @access protected
  218. */
  219. var $_methods = array();
  220. /**
  221. * Initializes AuthComponent for use in the controller
  222. *
  223. * @param object $controller A reference to the instantiating controller object
  224. * @return void
  225. * @access public
  226. */
  227. function initialize(&$controller) {
  228. $this->params = $controller->params;
  229. $crud = array('create', 'read', 'update', 'delete');
  230. $this->actionMap = array_merge($this->actionMap, array_combine($crud, $crud));
  231. $this->_methods = $controller->methods;
  232. $admin = Configure::read('Routing.admin');
  233. if (!empty($admin)) {
  234. $this->actionMap = array_merge($this->actionMap, array(
  235. $admin . '_index' => 'read',
  236. $admin . '_add' => 'create',
  237. $admin . '_edit' => 'update',
  238. $admin . '_view' => 'read',
  239. $admin . '_remove' => 'delete',
  240. $admin . '_create' => 'create',
  241. $admin . '_read' => 'read',
  242. $admin . '_update' => 'update',
  243. $admin . '_delete' => 'delete'
  244. ));
  245. }
  246. if (Configure::read() > 0) {
  247. App::import('Debugger');
  248. Debugger::checkSessionKey();
  249. }
  250. }
  251. /**
  252. * Main execution method. Handles redirecting of invalid users, and processing
  253. * of login form data.
  254. *
  255. * @param object $controller A reference to the instantiating controller object
  256. * @return boolean
  257. * @access public
  258. */
  259. function startup(&$controller) {
  260. $isErrorOrTests = (
  261. strtolower($controller->name) == 'cakeerror' ||
  262. (strtolower($controller->name) == 'tests' && Configure::read() > 0)
  263. );
  264. if ($isErrorOrTests) {
  265. return true;
  266. }
  267. $methods = array_flip($controller->methods);
  268. $action = strtolower($controller->params['action']);
  269. $isMissingAction = (
  270. $controller->scaffold === false &&
  271. !isset($methods[$action])
  272. );
  273. if ($isMissingAction) {
  274. return true;
  275. }
  276. if (!$this->__setDefaults()) {
  277. return false;
  278. }
  279. $this->data = $controller->data = $this->hashPasswords($controller->data);
  280. $url = '';
  281. if (isset($controller->params['url']['url'])) {
  282. $url = $controller->params['url']['url'];
  283. }
  284. $url = Router::normalize($url);
  285. $loginAction = Router::normalize($this->loginAction);
  286. $allowedActions = array_map('strtolower', $this->allowedActions);
  287. $isAllowed = (
  288. $this->allowedActions == array('*') ||
  289. in_array($action, $allowedActions)
  290. );
  291. if ($loginAction != $url && $isAllowed) {
  292. return true;
  293. }
  294. if ($loginAction == $url) {
  295. if (empty($controller->data) || !isset($controller->data[$this->userModel])) {
  296. if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) {
  297. $this->Session->write('Auth.redirect', $controller->referer(null, true));
  298. }
  299. return false;
  300. }
  301. $isValid = !empty($controller->data[$this->userModel][$this->fields['username']]) &&
  302. !empty($controller->data[$this->userModel][$this->fields['password']]);
  303. if ($isValid) {
  304. $username = $controller->data[$this->userModel][$this->fields['username']];
  305. $password = $controller->data[$this->userModel][$this->fields['password']];
  306. $data = array(
  307. $this->userModel . '.' . $this->fields['username'] => $username,
  308. $this->userModel . '.' . $this->fields['password'] => $password
  309. );
  310. if ($this->login($data)) {
  311. if ($this->autoRedirect) {
  312. $controller->redirect($this->redirect(), null, true);
  313. }
  314. return true;
  315. }
  316. }
  317. $this->Session->setFlash($this->loginError, 'default', array(), 'auth');
  318. $controller->data[$this->userModel][$this->fields['password']] = null;
  319. return false;
  320. } else {
  321. if (!$this->user()) {
  322. if (!$this->RequestHandler->isAjax()) {
  323. $this->Session->setFlash($this->authError, 'default', array(), 'auth');
  324. if (!empty($controller->params['url']) && count($controller->params['url']) >= 2) {
  325. $query = $controller->params['url'];
  326. unset($query['url'], $query['ext']);
  327. $url .= Router::queryString($query, array());
  328. }
  329. $this->Session->write('Auth.redirect', $url);
  330. $controller->redirect($loginAction);
  331. return false;
  332. } elseif (!empty($this->ajaxLogin)) {
  333. $controller->viewPath = 'elements';
  334. echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
  335. $this->_stop();
  336. return false;
  337. } else {
  338. $controller->redirect(null, 403);
  339. }
  340. }
  341. }
  342. if (!$this->authorize) {
  343. return true;
  344. }
  345. extract($this->__authType());
  346. switch ($type) {
  347. case 'controller':
  348. $this->object =& $controller;
  349. break;
  350. case 'crud':
  351. case 'actions':
  352. if (isset($controller->Acl)) {
  353. $this->Acl =& $controller->Acl;
  354. } else {
  355. $err = 'Could not find AclComponent. Please include Acl in ';
  356. $err .= 'Controller::$components.';
  357. trigger_error(__($err, true), E_USER_WARNING);
  358. }
  359. break;
  360. case 'model':
  361. if (!isset($object)) {
  362. $hasModel = (
  363. isset($controller->{$controller->modelClass}) &&
  364. is_object($controller->{$controller->modelClass})
  365. );
  366. $isUses = (
  367. !empty($controller->uses) && isset($controller->{$controller->uses[0]}) &&
  368. is_object($controller->{$controller->uses[0]})
  369. );
  370. if ($hasModel) {
  371. $object = $controller->modelClass;
  372. } elseif ($isUses) {
  373. $object = $controller->uses[0];
  374. }
  375. }
  376. $type = array('model' => $object);
  377. break;
  378. }
  379. if ($this->isAuthorized($type)) {
  380. return true;
  381. }
  382. $this->Session->setFlash($this->authError, 'default', array(), 'auth');
  383. $controller->redirect($controller->referer(), null, true);
  384. return false;
  385. }
  386. /**
  387. * Attempts to introspect the correct values for object properties including
  388. * $userModel and $sessionKey.
  389. *
  390. * @param object $controller A reference to the instantiating controller object
  391. * @return boolean
  392. * @access private
  393. */
  394. function __setDefaults() {
  395. if (empty($this->userModel)) {
  396. trigger_error(__("Could not find \$userModel. Please set AuthComponent::\$userModel in beforeFilter().", true), E_USER_WARNING);
  397. return false;
  398. }
  399. $defaults = array(
  400. 'loginAction' => array(
  401. 'controller' => Inflector::underscore(Inflector::pluralize($this->userModel)),
  402. 'action' => 'login'
  403. ),
  404. 'sessionKey' => 'Auth.' . $this->userModel,
  405. 'logoutRedirect' => $this->loginAction,
  406. 'loginError' => __('Login failed. Invalid username or password.', true),
  407. 'authError' => __('You are not authorized to access that location.', true)
  408. );
  409. foreach ($defaults as $key => $value) {
  410. if (empty($this->{$key})) {
  411. $this->{$key} = $value;
  412. }
  413. }
  414. return true;
  415. }
  416. /**
  417. * Determines whether the given user is authorized to perform an action. The type of
  418. * authorization used is based on the value of AuthComponent::$authorize or the
  419. * passed $type param.
  420. *
  421. * Types:
  422. * 'controller' will validate against Controller::isAuthorized() if controller instance is
  423. * passed in $object
  424. * 'actions' will validate Controller::action against an AclComponent::check()
  425. * 'crud' will validate mapActions against an AclComponent::check()
  426. * array('model'=> 'name'); will validate mapActions against model
  427. * $name::isAuthorized(user, controller, mapAction)
  428. * 'object' will validate Controller::action against
  429. * object::isAuthorized(user, controller, action)
  430. *
  431. * @param string $type Type of authorization
  432. * @param mixed $object object, model object, or model name
  433. * @param mixed $user The user to check the authorization of
  434. * @return boolean True if $user is authorized, otherwise false
  435. * @access public
  436. */
  437. function isAuthorized($type = null, $object = null, $user = null) {
  438. if (empty($user) && !$this->user()) {
  439. return false;
  440. } elseif (empty($user)) {
  441. $user = $this->user();
  442. }
  443. extract($this->__authType($type));
  444. if (!$object) {
  445. $object = $this->object;
  446. }
  447. $valid = false;
  448. switch ($type) {
  449. case 'controller':
  450. $valid = $object->isAuthorized();
  451. break;
  452. case 'actions':
  453. $valid = $this->Acl->check($user, $this->action());
  454. break;
  455. case 'crud':
  456. $this->mapActions();
  457. if (!isset($this->actionMap[$this->params['action']])) {
  458. $err = 'Auth::startup() - Attempted access of un-mapped action "%1$s" in';
  459. $err .= ' controller "%2$s"';
  460. trigger_error(
  461. sprintf(__($err, true), $this->params['action'], $this->params['controller']),
  462. E_USER_WARNING
  463. );
  464. } else {
  465. $valid = $this->Acl->check(
  466. $user,
  467. $this->action(':controller'),
  468. $this->actionMap[$this->params['action']]
  469. );
  470. }
  471. break;
  472. case 'model':
  473. $this->mapActions();
  474. $action = $this->params['action'];
  475. if (isset($this->actionMap[$action])) {
  476. $action = $this->actionMap[$action];
  477. }
  478. if (is_string($object)) {
  479. $object = $this->getModel($object);
  480. }
  481. case 'object':
  482. if (!isset($action)) {
  483. $action = $this->action(':action');
  484. }
  485. if (empty($object)) {
  486. trigger_error(sprintf(__('Could not find %s. Set AuthComponent::$object in beforeFilter() or pass a valid object', true), get_class($object)), E_USER_WARNING);
  487. return;
  488. }
  489. if (method_exists($object, 'isAuthorized')) {
  490. $valid = $object->isAuthorized($user, $this->action(':controller'), $action);
  491. } elseif ($object) {
  492. trigger_error(sprintf(__('%s::isAuthorized() is not defined.', true), get_class($object)), E_USER_WARNING);
  493. }
  494. break;
  495. case null:
  496. case false:
  497. return true;
  498. break;
  499. default:
  500. trigger_error(__('Auth::isAuthorized() - $authorize is set to an incorrect value. Allowed settings are: "actions", "crud", "model" or null.', true), E_USER_WARNING);
  501. break;
  502. }
  503. return $valid;
  504. }
  505. /**
  506. * Get authorization type
  507. *
  508. * @param string $auth Type of authorization
  509. * @return array Associative array with: type, object
  510. * @access private
  511. */
  512. function __authType($auth = null) {
  513. if ($auth == null) {
  514. $auth = $this->authorize;
  515. }
  516. $object = null;
  517. if (is_array($auth)) {
  518. $type = key($auth);
  519. $object = $auth[$type];
  520. } else {
  521. $type = $auth;
  522. return compact('type');
  523. }
  524. return compact('type', 'object');
  525. }
  526. /**
  527. * Takes a list of actions in the current controller for which authentication is not required, or
  528. * no parameters to allow all actions.
  529. *
  530. * @param string $action Controller action name
  531. * @param string $action Controller action name
  532. * @param string ... etc.
  533. * @return void
  534. * @access public
  535. */
  536. function allow() {
  537. $args = func_get_args();
  538. if (empty($args) || $args == array('*')) {
  539. $this->allowedActions = $this->_methods;
  540. } else {
  541. if (isset($args[0]) && is_array($args[0])) {
  542. $args = $args[0];
  543. }
  544. $this->allowedActions = array_merge($this->allowedActions, $args);
  545. }
  546. }
  547. /**
  548. * Removes items from the list of allowed actions.
  549. *
  550. * @param string $action Controller action name
  551. * @param string $action Controller action name
  552. * @param string ... etc.
  553. * @return void
  554. * @see AuthComponent::allow()
  555. * @access public
  556. */
  557. function deny() {
  558. $args = func_get_args();
  559. foreach ($args as $arg) {
  560. $i = array_search($arg, $this->allowedActions);
  561. if (is_int($i)) {
  562. unset($this->allowedActions[$i]);
  563. }
  564. }
  565. $this->allowedActions = array_values($this->allowedActions);
  566. }
  567. /**
  568. * Maps action names to CRUD operations. Used for controller-based authentication.
  569. *
  570. * @param array $map Actions to map
  571. * @return void
  572. * @access public
  573. */
  574. function mapActions($map = array()) {
  575. $crud = array('create', 'read', 'update', 'delete');
  576. foreach ($map as $action => $type) {
  577. if (in_array($action, $crud) && is_array($type)) {
  578. foreach ($type as $typedAction) {
  579. $this->actionMap[$typedAction] = $action;
  580. }
  581. } else {
  582. $this->actionMap[$action] = $type;
  583. }
  584. }
  585. }
  586. /**
  587. * Manually log-in a user with the given parameter data. The $data provided can be any data
  588. * structure used to identify a user in AuthComponent::identify(). If $data is empty or not
  589. * specified, POST data from Controller::$data will be used automatically.
  590. *
  591. * After (if) login is successful, the user record is written to the session key specified in
  592. * AuthComponent::$sessionKey.
  593. *
  594. * @param mixed $data User object
  595. * @return boolean True on login success, false on failure
  596. * @access public
  597. */
  598. function login($data = null) {
  599. $this->__setDefaults();
  600. $this->_loggedIn = false;
  601. if (empty($data)) {
  602. $data = $this->data;
  603. }
  604. if ($user = $this->identify($data)) {
  605. $this->Session->write($this->sessionKey, $user);
  606. $this->_loggedIn = true;
  607. }
  608. return $this->_loggedIn;
  609. }
  610. /**
  611. * Logs a user out, and returns the login action to redirect to.
  612. *
  613. * @param mixed $url Optional URL to redirect the user to after logout
  614. * @return string AuthComponent::$loginAction
  615. * @see AuthComponent::$loginAction
  616. * @access public
  617. */
  618. function logout() {
  619. $this->__setDefaults();
  620. $this->Session->del($this->sessionKey);
  621. $this->Session->del('Auth.redirect');
  622. $this->_loggedIn = false;
  623. return Router::normalize($this->logoutRedirect);
  624. }
  625. /**
  626. * Get the current user from the session.
  627. *
  628. * @param string $key field to retrive. Leave null to get entire User record
  629. * @return mixed User record. or null if no user is logged in.
  630. * @access public
  631. */
  632. function user($key = null) {
  633. $this->__setDefaults();
  634. if (!$this->Session->check($this->sessionKey)) {
  635. return null;
  636. }
  637. if ($key == null) {
  638. return array($this->userModel => $this->Session->read($this->sessionKey));
  639. } else {
  640. $user = $this->Session->read($this->sessionKey);
  641. if (isset($user[$key])) {
  642. return $user[$key];
  643. }
  644. return null;
  645. }
  646. }
  647. /**
  648. * If no parameter is passed, gets the authentication redirect URL.
  649. *
  650. * @param mixed $url Optional URL to write as the login redirect URL.
  651. * @return string Redirect URL
  652. * @access public
  653. */
  654. function redirect($url = null) {
  655. if (!is_null($url)) {
  656. $redir = $url;
  657. $this->Session->write('Auth.redirect', $redir);
  658. } elseif ($this->Session->check('Auth.redirect')) {
  659. $redir = $this->Session->read('Auth.redirect');
  660. $this->Session->delete('Auth.redirect');
  661. if (Router::normalize($redir) == Router::normalize($this->loginAction)) {
  662. $redir = $this->loginRedirect;
  663. }
  664. } else {
  665. $redir = $this->loginRedirect;
  666. }
  667. return Router::normalize($redir);
  668. }
  669. /**
  670. * Validates a user against an abstract object.
  671. *
  672. * @param mixed $object The object to validate the user against.
  673. * @param mixed $user Optional. The identity of the user to be validated.
  674. * Uses the current user session if none specified. For
  675. * valid forms of identifying users, see
  676. * AuthComponent::identify().
  677. * @param string $action Optional. The action to validate against.
  678. * @see AuthComponent::identify()
  679. * @return boolean True if the user validates, false otherwise.
  680. * @access public
  681. */
  682. function validate($object, $user = null, $action = null) {
  683. if (empty($user)) {
  684. $user = $this->user();
  685. }
  686. if (empty($user)) {
  687. return false;
  688. }
  689. return $this->Acl->check($user, $object, $action);
  690. }
  691. /**
  692. * Returns the path to the ACO node bound to a controller/action.
  693. *
  694. * @param string $action Optional. The controller/action path to validate the
  695. * user against. The current request action is used if
  696. * none is specified.
  697. * @return boolean ACO node path
  698. * @access public
  699. */
  700. function action($action = ':controller/:action') {
  701. return str_replace(
  702. array(':controller', ':action'),
  703. array(Inflector::camelize($this->params['controller']), $this->params['action']),
  704. $this->actionPath . $action
  705. );
  706. }
  707. /**
  708. * Returns a reference to the model object specified, and attempts
  709. * to load it if it is not found.
  710. *
  711. * @param string $name Model name (defaults to AuthComponent::$userModel)
  712. * @return object A reference to a model object
  713. * @access public
  714. */
  715. function &getModel($name = null) {
  716. $model = null;
  717. if (!$name) {
  718. $name = $this->userModel;
  719. }
  720. if (PHP5) {
  721. $model = ClassRegistry::init($name);
  722. } else {
  723. $model =& ClassRegistry::init($name);
  724. }
  725. if (empty($model)) {
  726. trigger_error(__('Auth::getModel() - Model is not set or could not be found', true), E_USER_WARNING);
  727. return null;
  728. }
  729. return $model;
  730. }
  731. /**
  732. * Identifies a user based on specific criteria.
  733. *
  734. * @param mixed $user Optional. The identity of the user to be validated.
  735. * Uses the current user session if none specified.
  736. * @param array $conditions Optional. Additional conditions to a find.
  737. * @return array User record data, or null, if the user could not be identified.
  738. * @access public
  739. */
  740. function identify($user = null, $conditions = null) {
  741. if ($conditions === false) {
  742. $conditions = null;
  743. } elseif (is_array($conditions)) {
  744. $conditions = array_merge((array)$this->userScope, $conditions);
  745. } else {
  746. $conditions = $this->userScope;
  747. }
  748. if (empty($user)) {
  749. $user = $this->user();
  750. if (empty($user)) {
  751. return null;
  752. }
  753. } elseif (is_object($user) && is_a($user, 'Model')) {
  754. if (!$user->exists()) {
  755. return null;
  756. }
  757. $user = $user->read();
  758. $user = $user[$this->userModel];
  759. } elseif (is_array($user) && isset($user[$this->userModel])) {
  760. $user = $user[$this->userModel];
  761. }
  762. if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$this->userModel . '.' . $this->fields['username']]))) {
  763. if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']]) && !empty($user[$this->fields['password']])) {
  764. if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
  765. return false;
  766. }
  767. $find = array(
  768. $this->userModel.'.'.$this->fields['username'] => $user[$this->fields['username']],
  769. $this->userModel.'.'.$this->fields['password'] => $user[$this->fields['password']]
  770. );
  771. } elseif (isset($user[$this->userModel . '.' . $this->fields['username']]) && !empty($user[$this->userModel . '.' . $this->fields['username']])) {
  772. if (trim($user[$this->userModel . '.' . $this->fields['username']]) == '=' || trim($user[$this->userModel . '.' . $this->fields['password']]) == '=') {
  773. return false;
  774. }
  775. $find = array(
  776. $this->userModel.'.'.$this->fields['username'] => $user[$this->userModel . '.' . $this->fields['username']],
  777. $this->userModel.'.'.$this->fields['password'] => $user[$this->userModel . '.' . $this->fields['password']]
  778. );
  779. } else {
  780. return false;
  781. }
  782. $model =& $this->getModel();
  783. $data = $model->find(array_merge($find, $conditions), null, null, 0);
  784. if (empty($data) || empty($data[$this->userModel])) {
  785. return null;
  786. }
  787. } elseif (!empty($user) && is_string($user)) {
  788. $model =& $this->getModel();
  789. $data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));
  790. if (empty($data) || empty($data[$this->userModel])) {
  791. return null;
  792. }
  793. }
  794. if (!empty($data)) {
  795. if (!empty($data[$this->userModel][$this->fields['password']])) {
  796. unset($data[$this->userModel][$this->fields['password']]);
  797. }
  798. return $data[$this->userModel];
  799. }
  800. return null;
  801. }
  802. /**
  803. * Hash any passwords found in $data using $userModel and $fields['password']
  804. *
  805. * @param array $data Set of data to look for passwords
  806. * @return array Data with passwords hashed
  807. * @access public
  808. */
  809. function hashPasswords($data) {
  810. if (is_object($this->authenticate) && method_exists($this->authenticate, 'hashPasswords')) {
  811. return $this->authenticate->hashPasswords($data);
  812. }
  813. if (is_array($data) && isset($data[$this->userModel])) {
  814. if (isset($data[$this->userModel][$this->fields['username']]) && isset($data[$this->userModel][$this->fields['password']])) {
  815. $data[$this->userModel][$this->fields['password']] = $this->password($data[$this->userModel][$this->fields['password']]);
  816. }
  817. }
  818. return $data;
  819. }
  820. /**
  821. * Hash a password with the application's salt value (as defined with Configure::write('Security.salt');
  822. *
  823. * @param string $password Password to hash
  824. * @return string Hashed password
  825. * @access public
  826. */
  827. function password($password) {
  828. return Security::hash($password, null, true);
  829. }
  830. /**
  831. * Component shutdown. If user is logged in, wipe out redirect.
  832. *
  833. * @param object $controller Instantiating controller
  834. * @access public
  835. */
  836. function shutdown(&$controller) {
  837. if ($this->_loggedIn) {
  838. $this->Session->del('Auth.redirect');
  839. }
  840. }
  841. }
  842. ?>