diff -r 000000000000 -r 4eba9c11703f web/Zend/Auth/Adapter/DbTable.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/Zend/Auth/Adapter/DbTable.php Mon Dec 13 18:29:26 2010 +0100 @@ -0,0 +1,561 @@ +_setDbAdapter($zendDb); + + if (null !== $tableName) { + $this->setTableName($tableName); + } + + if (null !== $identityColumn) { + $this->setIdentityColumn($identityColumn); + } + + if (null !== $credentialColumn) { + $this->setCredentialColumn($credentialColumn); + } + + if (null !== $credentialTreatment) { + $this->setCredentialTreatment($credentialTreatment); + } + } + + /** + * _setDbAdapter() - set the database adapter to be used for quering + * + * @param Zend_Db_Adapter_Abstract + * @throws Zend_Auth_Adapter_Exception + * @return Zend_Auth_Adapter_DbTable + */ + protected function _setDbAdapter(Zend_Db_Adapter_Abstract $zendDb = null) + { + $this->_zendDb = $zendDb; + + /** + * If no adapter is specified, fetch default database adapter. + */ + if(null === $this->_zendDb) { + require_once 'Zend/Db/Table/Abstract.php'; + $this->_zendDb = Zend_Db_Table_Abstract::getDefaultAdapter(); + if (null === $this->_zendDb) { + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('No database adapter present'); + } + } + + return $this; + } + + /** + * setTableName() - set the table name to be used in the select query + * + * @param string $tableName + * @return Zend_Auth_Adapter_DbTable Provides a fluent interface + */ + public function setTableName($tableName) + { + $this->_tableName = $tableName; + return $this; + } + + /** + * setIdentityColumn() - set the column name to be used as the identity column + * + * @param string $identityColumn + * @return Zend_Auth_Adapter_DbTable Provides a fluent interface + */ + public function setIdentityColumn($identityColumn) + { + $this->_identityColumn = $identityColumn; + return $this; + } + + /** + * setCredentialColumn() - set the column name to be used as the credential column + * + * @param string $credentialColumn + * @return Zend_Auth_Adapter_DbTable Provides a fluent interface + */ + public function setCredentialColumn($credentialColumn) + { + $this->_credentialColumn = $credentialColumn; + return $this; + } + + /** + * setCredentialTreatment() - allows the developer to pass a parameterized string that is + * used to transform or treat the input credential data. + * + * In many cases, passwords and other sensitive data are encrypted, hashed, encoded, + * obscured, or otherwise treated through some function or algorithm. By specifying a + * parameterized treatment string with this method, a developer may apply arbitrary SQL + * upon input credential data. + * + * Examples: + * + * 'PASSWORD(?)' + * 'MD5(?)' + * + * @param string $treatment + * @return Zend_Auth_Adapter_DbTable Provides a fluent interface + */ + public function setCredentialTreatment($treatment) + { + $this->_credentialTreatment = $treatment; + return $this; + } + + /** + * setIdentity() - set the value to be used as the identity + * + * @param string $value + * @return Zend_Auth_Adapter_DbTable Provides a fluent interface + */ + public function setIdentity($value) + { + $this->_identity = $value; + return $this; + } + + /** + * setCredential() - set the credential value to be used, optionally can specify a treatment + * to be used, should be supplied in parameterized form, such as 'MD5(?)' or 'PASSWORD(?)' + * + * @param string $credential + * @return Zend_Auth_Adapter_DbTable Provides a fluent interface + */ + public function setCredential($credential) + { + $this->_credential = $credential; + return $this; + } + + /** + * setAmbiguityIdentity() - sets a flag for usage of identical identities + * with unique credentials. It accepts integers (0, 1) or boolean (true, + * false) parameters. Default is false. + * + * @param int|bool $flag + * @return Zend_Auth_Adapter_DbTable + */ + public function setAmbiguityIdentity($flag) + { + if (is_integer($flag)) { + $this->_ambiguityIdentity = (1 === $flag ? true : false); + } elseif (is_bool($flag)) { + $this->_ambiguityIdentity = $flag; + } + return $this; + } + /** + * getAmbiguityIdentity() - returns TRUE for usage of multiple identical + * identies with different credentials, FALSE if not used. + * + * @return bool + */ + public function getAmbiguityIdentity() + { + return $this->_ambiguityIdentity; + } + + /** + * getDbSelect() - Return the preauthentication Db Select object for userland select query modification + * + * @return Zend_Db_Select + */ + public function getDbSelect() + { + if ($this->_dbSelect == null) { + $this->_dbSelect = $this->_zendDb->select(); + } + + return $this->_dbSelect; + } + + /** + * getResultRowObject() - Returns the result row as a stdClass object + * + * @param string|array $returnColumns + * @param string|array $omitColumns + * @return stdClass|boolean + */ + public function getResultRowObject($returnColumns = null, $omitColumns = null) + { + if (!$this->_resultRow) { + return false; + } + + $returnObject = new stdClass(); + + if (null !== $returnColumns) { + + $availableColumns = array_keys($this->_resultRow); + foreach ( (array) $returnColumns as $returnColumn) { + if (in_array($returnColumn, $availableColumns)) { + $returnObject->{$returnColumn} = $this->_resultRow[$returnColumn]; + } + } + return $returnObject; + + } elseif (null !== $omitColumns) { + + $omitColumns = (array) $omitColumns; + foreach ($this->_resultRow as $resultColumn => $resultValue) { + if (!in_array($resultColumn, $omitColumns)) { + $returnObject->{$resultColumn} = $resultValue; + } + } + return $returnObject; + + } else { + + foreach ($this->_resultRow as $resultColumn => $resultValue) { + $returnObject->{$resultColumn} = $resultValue; + } + return $returnObject; + + } + } + + /** + * authenticate() - defined by Zend_Auth_Adapter_Interface. This method is called to + * attempt an authentication. Previous to this call, this adapter would have already + * been configured with all necessary information to successfully connect to a database + * table and attempt to find a record matching the provided identity. + * + * @throws Zend_Auth_Adapter_Exception if answering the authentication query is impossible + * @return Zend_Auth_Result + */ + public function authenticate() + { + $this->_authenticateSetup(); + $dbSelect = $this->_authenticateCreateSelect(); + $resultIdentities = $this->_authenticateQuerySelect($dbSelect); + + if ( ($authResult = $this->_authenticateValidateResultSet($resultIdentities)) instanceof Zend_Auth_Result) { + return $authResult; + } + + if (true === $this->getAmbiguityIdentity()) { + $validIdentities = array (); + $zendAuthCredentialMatchColumn = $this->_zendDb->foldCase('zend_auth_credential_match'); + foreach ($resultIdentities as $identity) { + if (1 === (int) $identity[$zendAuthCredentialMatchColumn]) { + $validIdentities[] = $identity; + } + } + $resultIdentities = $validIdentities; + } + + $authResult = $this->_authenticateValidateResult(array_shift($resultIdentities)); + return $authResult; + } + + /** + * _authenticateSetup() - This method abstracts the steps involved with + * making sure that this adapter was indeed setup properly with all + * required pieces of information. + * + * @throws Zend_Auth_Adapter_Exception - in the event that setup was not done properly + * @return true + */ + protected function _authenticateSetup() + { + $exception = null; + + if ($this->_tableName == '') { + $exception = 'A table must be supplied for the Zend_Auth_Adapter_DbTable authentication adapter.'; + } elseif ($this->_identityColumn == '') { + $exception = 'An identity column must be supplied for the Zend_Auth_Adapter_DbTable authentication adapter.'; + } elseif ($this->_credentialColumn == '') { + $exception = 'A credential column must be supplied for the Zend_Auth_Adapter_DbTable authentication adapter.'; + } elseif ($this->_identity == '') { + $exception = 'A value for the identity was not provided prior to authentication with Zend_Auth_Adapter_DbTable.'; + } elseif ($this->_credential === null) { + $exception = 'A credential value was not provided prior to authentication with Zend_Auth_Adapter_DbTable.'; + } + + if (null !== $exception) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception($exception); + } + + $this->_authenticateResultInfo = array( + 'code' => Zend_Auth_Result::FAILURE, + 'identity' => $this->_identity, + 'messages' => array() + ); + + return true; + } + + /** + * _authenticateCreateSelect() - This method creates a Zend_Db_Select object that + * is completely configured to be queried against the database. + * + * @return Zend_Db_Select + */ + protected function _authenticateCreateSelect() + { + // build credential expression + if (empty($this->_credentialTreatment) || (strpos($this->_credentialTreatment, '?') === false)) { + $this->_credentialTreatment = '?'; + } + + $credentialExpression = new Zend_Db_Expr( + '(CASE WHEN ' . + $this->_zendDb->quoteInto( + $this->_zendDb->quoteIdentifier($this->_credentialColumn, true) + . ' = ' . $this->_credentialTreatment, $this->_credential + ) + . ' THEN 1 ELSE 0 END) AS ' + . $this->_zendDb->quoteIdentifier( + $this->_zendDb->foldCase('zend_auth_credential_match') + ) + ); + + // get select + $dbSelect = clone $this->getDbSelect(); + $dbSelect->from($this->_tableName, array('*', $credentialExpression)) + ->where($this->_zendDb->quoteIdentifier($this->_identityColumn, true) . ' = ?', $this->_identity); + + return $dbSelect; + } + + /** + * _authenticateQuerySelect() - This method accepts a Zend_Db_Select object and + * performs a query against the database with that object. + * + * @param Zend_Db_Select $dbSelect + * @throws Zend_Auth_Adapter_Exception - when an invalid select + * object is encountered + * @return array + */ + protected function _authenticateQuerySelect(Zend_Db_Select $dbSelect) + { + try { + if ($this->_zendDb->getFetchMode() != Zend_DB::FETCH_ASSOC) { + $origDbFetchMode = $this->_zendDb->getFetchMode(); + $this->_zendDb->setFetchMode(Zend_DB::FETCH_ASSOC); + } + $resultIdentities = $this->_zendDb->fetchAll($dbSelect->__toString()); + if (isset($origDbFetchMode)) { + $this->_zendDb->setFetchMode($origDbFetchMode); + unset($origDbFetchMode); + } + } catch (Exception $e) { + /** + * @see Zend_Auth_Adapter_Exception + */ + require_once 'Zend/Auth/Adapter/Exception.php'; + throw new Zend_Auth_Adapter_Exception('The supplied parameters to Zend_Auth_Adapter_DbTable failed to ' + . 'produce a valid sql statement, please check table and column names ' + . 'for validity.', 0, $e); + } + return $resultIdentities; + } + + /** + * _authenticateValidateResultSet() - This method attempts to make + * certain that only one record was returned in the resultset + * + * @param array $resultIdentities + * @return true|Zend_Auth_Result + */ + protected function _authenticateValidateResultSet(array $resultIdentities) + { + + if (count($resultIdentities) < 1) { + $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND; + $this->_authenticateResultInfo['messages'][] = 'A record with the supplied identity could not be found.'; + return $this->_authenticateCreateAuthResult(); + } elseif (count($resultIdentities) > 1 && false === $this->getAmbiguityIdentity()) { + $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS; + $this->_authenticateResultInfo['messages'][] = 'More than one record matches the supplied identity.'; + return $this->_authenticateCreateAuthResult(); + } + + return true; + } + + /** + * _authenticateValidateResult() - This method attempts to validate that + * the record in the resultset is indeed a record that matched the + * identity provided to this adapter. + * + * @param array $resultIdentity + * @return Zend_Auth_Result + */ + protected function _authenticateValidateResult($resultIdentity) + { + $zendAuthCredentialMatchColumn = $this->_zendDb->foldCase('zend_auth_credential_match'); + + if ($resultIdentity[$zendAuthCredentialMatchColumn] != '1') { + $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID; + $this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.'; + return $this->_authenticateCreateAuthResult(); + } + + unset($resultIdentity[$zendAuthCredentialMatchColumn]); + $this->_resultRow = $resultIdentity; + + $this->_authenticateResultInfo['code'] = Zend_Auth_Result::SUCCESS; + $this->_authenticateResultInfo['messages'][] = 'Authentication successful.'; + return $this->_authenticateCreateAuthResult(); + } + + /** + * _authenticateCreateAuthResult() - Creates a Zend_Auth_Result object from + * the information that has been collected during the authenticate() attempt. + * + * @return Zend_Auth_Result + */ + protected function _authenticateCreateAuthResult() + { + return new Zend_Auth_Result( + $this->_authenticateResultInfo['code'], + $this->_authenticateResultInfo['identity'], + $this->_authenticateResultInfo['messages'] + ); + } + +}