This repository has been archived by the owner on Jan 8, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored #3490. Split DbTable into 2 different (CallbackCheck and C…
…redentialTreatment) adapters
- Loading branch information
JustInVTime
committed
Mar 15, 2013
1 parent
e31b2c7
commit d392e6e
Showing
10 changed files
with
1,439 additions
and
850 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
383 changes: 383 additions & 0 deletions
383
library/Zend/Authentication/Adapter/DbTable/AbstractAdapter.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,383 @@ | ||
<?php | ||
/** | ||
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) | ||
* @license http://framework.zend.com/license/new-bsd New BSD License | ||
*/ | ||
|
||
namespace Zend\Authentication\Adapter\DbTable; | ||
|
||
|
||
use stdClass; | ||
use Zend\Authentication\Result as AuthenticationResult; | ||
use Zend\Authentication\Adapter\AbstractAdapter as BaseAdapter; | ||
use Zend\Db\Adapter\Adapter as DbAdapter; | ||
use Zend\Db\Sql; | ||
|
||
|
||
abstract class AbstractAdapter extends BaseAdapter | ||
{ | ||
|
||
/** | ||
* Database Connection | ||
* | ||
* @var DbAdapter | ||
*/ | ||
protected $zendDb = null; | ||
|
||
/** | ||
* @var Sql\Select | ||
*/ | ||
protected $dbSelect = null; | ||
/** | ||
* $tableName - the table name to check | ||
* | ||
* @var string | ||
*/ | ||
protected $tableName = null; | ||
|
||
/** | ||
* $identityColumn - the column to use as the identity | ||
* | ||
* @var string | ||
*/ | ||
protected $identityColumn = null; | ||
|
||
/** | ||
* $credentialColumns - columns to be used as the credentials | ||
* | ||
* @var string | ||
*/ | ||
protected $credentialColumn = null; | ||
|
||
/** | ||
* $authenticateResultInfo | ||
* | ||
* @var array | ||
*/ | ||
protected $authenticateResultInfo = null; | ||
|
||
/** | ||
* $resultRow - Results of database authentication query | ||
* | ||
* @var array | ||
*/ | ||
protected $resultRow = null; | ||
|
||
/** | ||
* $ambiguityIdentity - Flag to indicate same Identity can be used with | ||
* different credentials. Default is FALSE and need to be set to true to | ||
* allow ambiguity usage. | ||
* | ||
* @var bool | ||
*/ | ||
protected $ambiguityIdentity = false; | ||
|
||
|
||
/** | ||
* __construct() - Sets configuration options | ||
* | ||
* @param DbAdapter $zendDb | ||
* @param string $tableName Optional | ||
* @param string $identityColumn Optional | ||
* @param string $credentialColumn Optional | ||
* @return \Zend\Authentication\Adapter\DbTable | ||
*/ | ||
public function __construct(DbAdapter $zendDb, $tableName = null, $identityColumn = null, | ||
$credentialColumn = null) | ||
{ | ||
$this->zendDb = $zendDb; | ||
|
||
if (null !== $tableName) { | ||
$this->setTableName($tableName); | ||
} | ||
|
||
if (null !== $identityColumn) { | ||
$this->setIdentityColumn($identityColumn); | ||
} | ||
|
||
if (null !== $credentialColumn) { | ||
$this->setCredentialColumn($credentialColumn); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* setTableName() - set the table name to be used in the select query | ||
* | ||
* @param string $tableName | ||
* @return 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 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 DbTable Provides a fluent interface | ||
*/ | ||
public function setCredentialColumn($credentialColumn) | ||
{ | ||
$this->credentialColumn = $credentialColumn; | ||
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 DbTable Provides a fluent interface | ||
*/ | ||
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 | ||
* identities 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 Sql\Select | ||
*/ | ||
public function getDbSelect() | ||
{ | ||
if ($this->dbSelect == null) { | ||
$this->dbSelect = new Sql\Select(); | ||
} | ||
return $this->dbSelect; | ||
} | ||
|
||
/** | ||
* getResultRowObject() - Returns the result row as a stdClass object | ||
* | ||
* @param string|array $returnColumns | ||
* @param string|array $omitColumns | ||
* @return stdClass|bool | ||
*/ | ||
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; | ||
|
||
} | ||
|
||
foreach ($this->resultRow as $resultColumn => $resultValue) { | ||
$returnObject->{$resultColumn} = $resultValue; | ||
} | ||
return $returnObject; | ||
} | ||
|
||
|
||
/** | ||
* 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 Exception\RuntimeException if answering the authentication query is impossible | ||
* @return AuthenticationResult | ||
*/ | ||
public function authenticate() | ||
{ | ||
$this->_authenticateSetup(); | ||
$dbSelect = $this->_authenticateCreateSelect(); | ||
$resultIdentities = $this->_authenticateQuerySelect($dbSelect); | ||
|
||
if (($authResult = $this->_authenticateValidateResultSet($resultIdentities)) instanceof AuthenticationResult) { | ||
return $authResult; | ||
} | ||
|
||
// At this point, ambiguity is already done. Loop, check and break on success. | ||
foreach ($resultIdentities as $identity) { | ||
$authResult = $this->_authenticateValidateResult($identity); | ||
if ($authResult->isValid()) { | ||
break; | ||
} | ||
} | ||
|
||
return $authResult; | ||
} | ||
|
||
/** | ||
* _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 AuthenticationResult | ||
*/ | ||
abstract protected function _authenticateValidateResult($resultIdentity); | ||
|
||
/** | ||
* _authenticateCreateSelect() - This method creates a Zend\Db\Sql\Select object that | ||
* is completely configured to be queried against the database. | ||
* | ||
* @return Sql\Select | ||
*/ | ||
abstract protected function _authenticateCreateSelect(); | ||
|
||
/** | ||
* _authenticateSetup() - This method abstracts the steps involved with | ||
* making sure that this adapter was indeed setup properly with all | ||
* required pieces of information. | ||
* | ||
* @throws Exception\RuntimeException in the event that setup was not done properly | ||
* @return bool | ||
*/ | ||
protected function _authenticateSetup() | ||
{ | ||
$exception = null; | ||
|
||
if ($this->tableName == '') { | ||
$exception = 'A table must be supplied for the DbTable authentication adapter.'; | ||
} elseif ($this->identityColumn == '') { | ||
$exception = 'An identity column must be supplied for the DbTable authentication adapter.'; | ||
} elseif ($this->credentialColumn == '') { | ||
$exception = 'A credential column must be supplied for the DbTable authentication adapter.'; | ||
} elseif ($this->identity == '') { | ||
$exception = 'A value for the identity was not provided prior to authentication with DbTable.'; | ||
} elseif ($this->credential === null) { | ||
$exception = 'A credential value was not provided prior to authentication with DbTable.'; | ||
} | ||
|
||
if (null !== $exception) { | ||
throw new Exception\RuntimeException($exception); | ||
} | ||
|
||
$this->authenticateResultInfo = array( | ||
'code' => AuthenticationResult::FAILURE, | ||
'identity' => $this->identity, | ||
'messages' => array() | ||
); | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* _authenticateQuerySelect() - This method accepts a Zend\Db\Sql\Select object and | ||
* performs a query against the database with that object. | ||
* | ||
* @param Sql\Select $dbSelect | ||
* @throws Exception\RuntimeException when an invalid select object is encountered | ||
* @return array | ||
*/ | ||
protected function _authenticateQuerySelect(Sql\Select $dbSelect) | ||
{ | ||
$sql = new Sql\Sql($this->zendDb); | ||
$statement = $sql->prepareStatementForSqlObject($dbSelect); | ||
try { | ||
$result = $statement->execute(); | ||
$resultIdentities = array(); | ||
// iterate result, most cross platform way | ||
foreach ($result as $row) { | ||
$resultIdentities[] = $row; | ||
} | ||
} catch (\Exception $e) { | ||
throw new Exception\RuntimeException( | ||
'The supplied parameters to 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 bool|\Zend\Authentication\Result | ||
*/ | ||
protected function _authenticateValidateResultSet(array $resultIdentities) | ||
{ | ||
|
||
if (count($resultIdentities) < 1) { | ||
$this->authenticateResultInfo['code'] = AuthenticationResult::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'] = AuthenticationResult::FAILURE_IDENTITY_AMBIGUOUS; | ||
$this->authenticateResultInfo['messages'][] = 'More than one record matches the supplied identity.'; | ||
return $this->_authenticateCreateAuthResult(); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Creates a Zend\Authentication\Result object from the information that | ||
* has been collected during the authenticate() attempt. | ||
* | ||
* @return AuthenticationResult | ||
*/ | ||
protected function _authenticateCreateAuthResult() | ||
{ | ||
return new AuthenticationResult( | ||
$this->authenticateResultInfo['code'], | ||
$this->authenticateResultInfo['identity'], | ||
$this->authenticateResultInfo['messages'] | ||
); | ||
} | ||
|
||
|
||
|
||
} |
Oops, something went wrong.