File indexing completed on 2024-12-22 05:36:17
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Auth 0017 * @subpackage Adapter 0018 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id: DbTable.php 23775 2011-03-01 17:25:24Z ralph $ 0021 */ 0022 0023 0024 /** 0025 * @see Zend_Auth_Adapter_Interface 0026 */ 0027 require_once 'Zend/Auth/Adapter/Interface.php'; 0028 0029 /** 0030 * @see Zend_Auth_Result 0031 */ 0032 require_once 'Zend/Auth/Result.php'; 0033 0034 0035 /** 0036 * @category Zend 0037 * @package Zend_Auth 0038 * @subpackage Adapter 0039 * @copyright Copyright (c) 2011 Björn Schramke (http://www.schramke-online.de) 0040 * @license http://framework.zend.com/license/new-bsd New BSD License 0041 */ 0042 class CB_Auth_Adapter_Doctrine2 implements Zend_Auth_Adapter_Interface 0043 { 0044 0045 /** 0046 * Doctrine2 EntityManager 0047 * 0048 * @var \Doctrine\ORM\EntityManager 0049 */ 0050 protected $_em = null; 0051 0052 /** 0053 * $_modelName - the Doctrine2 entity to check 0054 * 0055 * @var string 0056 */ 0057 protected $_modelName = null; 0058 0059 /** 0060 * $_identityColumn - the column to use as the identity 0061 * 0062 * @var string 0063 */ 0064 protected $_identityColumn = null; 0065 0066 /** 0067 * $_credentialColumns - columns to be used as the credentials 0068 * 0069 * @var string 0070 */ 0071 protected $_credentialColumn = null; 0072 0073 /** 0074 * $_identity - Identity value 0075 * 0076 * @var string 0077 */ 0078 protected $_identity = null; 0079 0080 /** 0081 * $_credential - Credential values 0082 * 0083 * @var string 0084 */ 0085 protected $_credential = null; 0086 0087 /** 0088 * $_credentialTreatment - Treatment applied to the credential, such as MD5() or PASSWORD() 0089 * 0090 * @var string 0091 */ 0092 protected $_credentialTreatment = null; 0093 0094 /** 0095 * $_authenticateResultInfo 0096 * 0097 * @var array 0098 */ 0099 protected $_authenticateResultInfo = null; 0100 0101 /** 0102 * $_resultRow - Results of database authentication query 0103 * 0104 * @var array 0105 */ 0106 protected $_resultRow = null; 0107 0108 /** 0109 * $_ambiguityIdentity - Flag to indicate same Identity can be used with 0110 * different credentials. Default is FALSE and need to be set to true to 0111 * allow ambiguity usage. 0112 * 0113 * @var boolean 0114 */ 0115 protected $_ambiguityIdentity = false; 0116 0117 /** 0118 * __construct() - Sets configuration options 0119 * 0120 * @param \Doctrine\ORM\EntityManager $em If null, default database adapter assumed 0121 * @param string $tableName 0122 * @param string $identityColumn 0123 * @param string $credentialColumn 0124 * @param string $credentialTreatment 0125 * @return void 0126 */ 0127 public function __construct(\Doctrine\ORM\EntityManager $em = null, $modelName = null, $identityColumn = null, 0128 $credentialColumn = null, $credentialTreatment = null) 0129 { 0130 $this->_setEntityManager($em); 0131 0132 if (null !== $modelName) { 0133 $this->setModelName($modelName); 0134 } 0135 0136 if (null !== $identityColumn) { 0137 $this->setIdentityColumn($identityColumn); 0138 } 0139 0140 if (null !== $credentialColumn) { 0141 $this->setCredentialColumn($credentialColumn); 0142 } 0143 0144 if (null !== $credentialTreatment) { 0145 $this->setCredentialTreatment($credentialTreatment); 0146 } 0147 } 0148 0149 /** 0150 * _setEntityManager() - set the EntityManager to be used for quering 0151 * 0152 * @param \Doctrine\ORM\EntityManager 0153 * @throws Zend_Auth_Adapter_Exception 0154 * @return CB_Auth_Adapter_Doctrine2 0155 */ 0156 protected function _setEntityManager(\Doctrine\ORM\EntityManager $em = null) 0157 { 0158 $this->_em = $em; 0159 0160 /** 0161 * If no adapter is specified, fetch default database adapter. 0162 */ 0163 if(null === $this->_em) { 0164 require_once 'Zend/Auth/Adapter/Exception.php'; 0165 throw new Zend_Auth_Adapter_Exception('No Doctrine2 EntityManager present'); 0166 } 0167 0168 return $this; 0169 } 0170 0171 /** 0172 * setTableName() - set the table name to be used in the select query 0173 * 0174 * @param string $tableName 0175 * @return CB_Auth_Adapter_Doctrine2 Provides a fluent interface 0176 */ 0177 public function setModelName($modelName) 0178 { 0179 $this->_modelName = $modelName; 0180 return $this; 0181 } 0182 0183 /** 0184 * setIdentityColumn() - set the column name to be used as the identity column 0185 * 0186 * @param string $identityColumn 0187 * @return CB_Auth_Adapter_Doctrine2 Provides a fluent interface 0188 */ 0189 public function setIdentityColumn($identityColumn) 0190 { 0191 $this->_identityColumn = $identityColumn; 0192 return $this; 0193 } 0194 0195 /** 0196 * setCredentialColumn() - set the column name to be used as the credential column 0197 * 0198 * @param string $credentialColumn 0199 * @return CB_Auth_Adapter_Doctrine2 Provides a fluent interface 0200 */ 0201 public function setCredentialColumn($credentialColumn) 0202 { 0203 $this->_credentialColumn = $credentialColumn; 0204 return $this; 0205 } 0206 0207 /** 0208 * setCredentialTreatment() - allows the developer to pass a parameterized string that is 0209 * used to transform or treat the input credential data. 0210 * 0211 * In many cases, passwords and other sensitive data are encrypted, hashed, encoded, 0212 * obscured, or otherwise treated through some function or algorithm. By specifying a 0213 * parameterized treatment string with this method, a developer may apply arbitrary SQL 0214 * upon input credential data. 0215 * 0216 * Examples: 0217 * 0218 * 'PASSWORD(?)' 0219 * 'MD5(?)' 0220 * 0221 * @param string $treatment 0222 * @return CB_Auth_Adapter_Doctrine2 Provides a fluent interface 0223 */ 0224 public function setCredentialTreatment($treatment) 0225 { 0226 $this->_credentialTreatment = $treatment; 0227 return $this; 0228 } 0229 0230 /** 0231 * setIdentity() - set the value to be used as the identity 0232 * 0233 * @param string $value 0234 * @return CB_Auth_Adapter_Doctrine2 Provides a fluent interface 0235 */ 0236 public function setIdentity($value) 0237 { 0238 $this->_identity = $value; 0239 return $this; 0240 } 0241 0242 /** 0243 * setCredential() - set the credential value to be used, optionally can specify a treatment 0244 * to be used, should be supplied in parameterized form, such as 'MD5(?)' or 'PASSWORD(?)' 0245 * 0246 * @param string $credential 0247 * @return CB_Auth_Adapter_Doctrine2 Provides a fluent interface 0248 */ 0249 public function setCredential($credential) 0250 { 0251 $this->_credential = $credential; 0252 return $this; 0253 } 0254 0255 /** 0256 * getResultRowObject() - Returns the result row as a stdClass object 0257 * 0258 * @param string|array $returnColumns 0259 * @param string|array $omitColumns 0260 * @return stdClass|boolean 0261 */ 0262 public function getResultRowObject($returnColumns = null, $omitColumns = null) 0263 { 0264 if (!$this->_resultRow) { 0265 return false; 0266 } 0267 0268 return $this->_resultRow; 0269 } 0270 0271 /** 0272 * authenticate() - defined by Zend_Auth_Adapter_Interface. This method is called to 0273 * attempt an authentication. Previous to this call, this adapter would have already 0274 * been configured with all necessary information to successfully connect to a database 0275 * table and attempt to find a record matching the provided identity. 0276 * 0277 * @throws Zend_Auth_Adapter_Exception if answering the authentication query is impossible 0278 * @return Zend_Auth_Result 0279 */ 0280 public function authenticate() 0281 { 0282 $this->_authenticateSetup(); 0283 $query = $this->_authenticateCreateSelect(); 0284 $resultIdentities = $this->_authenticateQuerySelect($query); 0285 $authResult = $this->_authenticateValidateResultSet($resultIdentities); 0286 0287 if ( $authResult instanceof Zend_Auth_Result) 0288 { 0289 return $authResult; 0290 } 0291 0292 return $this->_authenticateValidateResult(array_shift($resultIdentities)); 0293 } 0294 0295 /** 0296 * _authenticateSetup() - This method abstracts the steps involved with 0297 * making sure that this adapter was indeed setup properly with all 0298 * required pieces of information. 0299 * 0300 * @throws Zend_Auth_Adapter_Exception - in the event that setup was not done properly 0301 * @return true 0302 */ 0303 protected function _authenticateSetup() 0304 { 0305 $exception = null; 0306 0307 if ($this->_modelName == '') { 0308 $exception = 'A model must be supplied for the CB_Auth_Adapter_Doctrine2 authentication adapter.'; 0309 } elseif ($this->_identityColumn == '') { 0310 $exception = 'An identity column must be supplied for the CB_Auth_Adapter_Doctrine2 authentication adapter.'; 0311 } elseif ($this->_credentialColumn == '') { 0312 $exception = 'A credential column must be supplied for the CB_Auth_Adapter_Doctrine2 authentication adapter.'; 0313 } elseif ($this->_identity == '') { 0314 $exception = 'A value for the identity was not provided prior to authentication with CB_Auth_Adapter_Doctrine2.'; 0315 } elseif ($this->_credential === null) { 0316 $exception = 'A credential value was not provided prior to authentication with CB_Auth_Adapter_Doctrine2.'; 0317 } 0318 0319 if (null !== $exception) { 0320 /** 0321 * @see Zend_Auth_Adapter_Exception 0322 */ 0323 require_once 'Zend/Auth/Adapter/Exception.php'; 0324 throw new Zend_Auth_Adapter_Exception($exception); 0325 } 0326 0327 $this->_authenticateResultInfo = array( 0328 'code' => Zend_Auth_Result::FAILURE, 0329 'identity' => $this->_identity, 0330 'messages' => array() 0331 ); 0332 0333 return true; 0334 } 0335 0336 /** 0337 * _authenticateCreateSelect() - This method creates a \Doctrine\ORM\Query object that 0338 * is completely configured to be queried against the database. 0339 * 0340 * @return \Doctrine\ORM\Query 0341 */ 0342 protected function _authenticateCreateSelect() 0343 { 0344 // build credential expression 0345 if (empty($this->_credentialTreatment) || (strpos($this->_credentialTreatment, '?') === false)) { 0346 $this->_credentialTreatment = '?'; 0347 } 0348 0349 $idExpr = 'u.'.$this->_identityColumn.' = :id'; 0350 // $credExpr = 'u.'.$this->_credentialColumn.' = :cred'; 0351 // $query = $this->_em->createQuery('SELECT u from Application_Model_User u WHERE '.$idExpr.' AND '.$credExpr); 0352 $query = $this->_em->createQuery('SELECT u from Application_Model_User u WHERE '.$idExpr); 0353 $query->setParameters(array( 0354 'id' => $this->_identity, 0355 // 'cred' => $this->_credential, 0356 )); 0357 0358 return $query; 0359 } 0360 0361 /** 0362 * _authenticateQuerySelect() - This method accepts a Zend_Db_Select object and 0363 * performs a query against the database with that object. 0364 * 0365 * @param Zend_Db_Select $dbSelect 0366 * @throws Zend_Auth_Adapter_Exception - when an invalid select 0367 * object is encountered 0368 * @return array 0369 */ 0370 0371 protected function _authenticateQuerySelect(\Doctrine\ORM\Query $query) 0372 { 0373 try { 0374 $resultIdentities = $query->getResult(); 0375 } catch (Exception $e) { 0376 /** 0377 * @see Zend_Auth_Adapter_Exception 0378 */ 0379 require_once 'Zend/Auth/Adapter/Exception.php'; 0380 throw new Zend_Auth_Adapter_Exception('The supplied parameters to CB_Auth_Adapter_Doctrine2 failed to ' 0381 . 'produce a valid DQL statement, please check table and column names ' 0382 . 'for validity.', 0, $e); 0383 } 0384 return $resultIdentities; 0385 } 0386 0387 /** 0388 * _authenticateValidateResultSet() - This method attempts to make 0389 * certain that only one record was returned in the resultset 0390 * 0391 * @param array $resultIdentities 0392 * @return true|Zend_Auth_Result 0393 */ 0394 protected function _authenticateValidateResultSet(array $resultIdentities) 0395 { 0396 0397 if (count($resultIdentities) < 1) { 0398 $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND; 0399 $this->_authenticateResultInfo['messages'][] = 'A record with the supplied identity could not be found.'; 0400 return $this->_authenticateCreateAuthResult(); 0401 } elseif (count($resultIdentities) > 1 && false === $this->getAmbiguityIdentity()) { 0402 $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS; 0403 $this->_authenticateResultInfo['messages'][] = 'More than one record matches the supplied identity.'; 0404 return $this->_authenticateCreateAuthResult(); 0405 } 0406 0407 return true; 0408 } 0409 0410 /** 0411 * _authenticateValidateResult() - This method attempts to validate that 0412 * the record in the resultset is indeed a record that matched the 0413 * identity provided to this adapter. 0414 * 0415 * @param array $resultIdentity 0416 * @return Zend_Auth_Result 0417 */ 0418 protected function _authenticateValidateResult($resultIdentity) 0419 { 0420 $credColumnFunc = 'get'.ucfirst($this->_credentialColumn); 0421 0422 if(!method_exists($resultIdentity,$credColumnFunc)) 0423 { 0424 $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID; 0425 $this->_authenticateResultInfo['messages'][] = 'Error on validating supplied credential.'; 0426 return $this->_authenticateCreateAuthResult(); 0427 } 0428 0429 $cred = $resultIdentity->{$credColumnFunc}(); 0430 if ($cred !== $this->_credential) 0431 { 0432 $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID; 0433 $this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.'; 0434 return $this->_authenticateCreateAuthResult(); 0435 } 0436 0437 $this->_resultRow = $resultIdentity; 0438 0439 $this->_authenticateResultInfo['code'] = Zend_Auth_Result::SUCCESS; 0440 $this->_authenticateResultInfo['messages'][] = 'Authentication successful.'; 0441 return $this->_authenticateCreateAuthResult(); 0442 } 0443 0444 /** 0445 * _authenticateCreateAuthResult() - Creates a Zend_Auth_Result object from 0446 * the information that has been collected during the authenticate() attempt. 0447 * 0448 * @return Zend_Auth_Result 0449 */ 0450 protected function _authenticateCreateAuthResult() 0451 { 0452 return new Zend_Auth_Result( 0453 $this->_authenticateResultInfo['code'], 0454 $this->_authenticateResultInfo['identity'], 0455 $this->_authenticateResultInfo['messages'] 0456 ); 0457 } 0458 0459 }