PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/C4/Library/Authentication/Adapter/MongoAuth.php

https://bitbucket.org/paulscott56/c4-new
PHP | 336 lines | 142 code | 38 blank | 156 comment | 18 complexity | cff81c76e0db4749acf61380c4fee8b0 MD5 | raw file
  1. <?php
  2. namespace C4\Library\Authentication\Adapter;
  3. use C4\Library\Authentication\Result as AuthenticationResult;
  4. use C4\Core\Framework as Framework;
  5. use C4\Core\Model\User as User;
  6. class MongoAuth implements AdapterInterface
  7. {
  8. /**
  9. * Database collection
  10. *
  11. * @var MongoCollection
  12. */
  13. protected $_collection = 'users';
  14. /**
  15. * $_identityKeyPath - the column to use as the identity
  16. *
  17. * @var string
  18. */
  19. protected $_identityKeyPath = null;
  20. /**
  21. * $_credentialKeyPaths - columns to be used as the credentials
  22. *
  23. * @var string
  24. */
  25. protected $_credentialKeyPath = null;
  26. /**
  27. * $_identity - Identity value
  28. *
  29. * @var string
  30. */
  31. protected $_identity = null;
  32. /**
  33. * $_credential - Credential values
  34. *
  35. * @var string
  36. */
  37. protected $_credential = null;
  38. /**
  39. * $_credentialTreatment - Treatment applied to the credential, such as MD5() or PASSWORD()
  40. *
  41. * @var string
  42. */
  43. protected $_credentialTreatment = null;
  44. /**
  45. * $_authenticateResultInfo
  46. *
  47. * @var array
  48. */
  49. protected $_authenticateResultInfo = null;
  50. /**
  51. * $_resultDoc - Results of database authentication query
  52. *
  53. * @var array
  54. */
  55. protected $_resultDoc = null;
  56. /**
  57. * $_ambiguityIdentity - Flag to indicate same Identity can be used with
  58. * different credentials.
  59. * Default is FALSE and need to be set to true to
  60. * allow ambiguity usage.
  61. *
  62. * @var boolean
  63. */
  64. protected $_ambiguityIdentity = false;
  65. /**
  66. * __construct() - Sets configuration options
  67. *
  68. * @param MongoCollection $collection If not set 'users' is assumed
  69. * @param string $identityKeyPath
  70. * @param string $credentialKeyPath
  71. * @param string $credentialTreatment
  72. * @return void
  73. */
  74. public function __construct(MongoCollection $collection = null, $identityKeyPath = null, $credentialKeyPath = null, $credentialTreatment = null)
  75. {
  76. $this->_setCollection($collection);
  77. if (null !== $identityKeyPath) {
  78. $this->setIdentityKeyPath($identityKeyPath);
  79. }
  80. if (null !== $credentialKeyPath) {
  81. $this->setCredentialKeyPath($credentialKeyPath); }
  82. if (null !== $credentialTreatment) {
  83. $this->setCredentialTreatment($credentialTreatment);
  84. }
  85. }
  86. /**
  87. * _setCollection() - set the database collection to be used for quering
  88. *
  89. * @param MongoCollection
  90. * @throws C4\Library\Authentication\Exception
  91. * @return this
  92. */
  93. protected function _setCollection(MongoCollection $collection = null)
  94. {
  95. $this->_collection = $collection;
  96. /**
  97. * If no adapter is specified, fetch default database adapter.
  98. */
  99. if(null === $this->_collection) {
  100. $this->_collection = 'users';
  101. if (null === $this->_collection) {
  102. throw new Exception('No collection specified!');
  103. }
  104. }
  105. return $this;
  106. }
  107. /**
  108. * setIdentityKeyPath() - set the column name to be used as the identity column
  109. *
  110. * @param string $identityKeyPath
  111. * @return Provides a fluent interface
  112. */
  113. public function setIdentityKeyPath($identityKeyPath)
  114. {
  115. $this->_identityKeyPath = $identityKeyPath;
  116. return $this;
  117. }
  118. /**
  119. * setCredentialKeyPath() - set the column name to be used as the credential column
  120. *
  121. * @param string $credentialKeyPath
  122. * @return Provides a fluent interface
  123. */
  124. public function setCredentialKeyPath($credentialKeyPath)
  125. {
  126. $this->_credentialKeyPath = $credentialKeyPath;
  127. return $this;
  128. }
  129. /**
  130. * setCredentialTreatment() - allows the developer to pass a parameterized string that is
  131. * used to transform or treat the input credential data.
  132. *
  133. * In many cases, passwords and other sensitive data are encrypted, hashed, encoded,
  134. * obscured, or otherwise treated through some function or algorithm. By specifying a
  135. * parameterized treatment string with this method, a developer may apply arbitrary SQL
  136. * upon input credential data.
  137. *
  138. * Examples:
  139. *
  140. * 'PASSWORD(?)'
  141. * 'MD5(?)'
  142. * 'SHA1(?)'
  143. *
  144. * @param string $treatment
  145. * @return Provides a fluent interface
  146. */
  147. public function setCredentialTreatment($treatment)
  148. {
  149. $this->_credentialTreatment = $treatment;
  150. return $this;
  151. }
  152. /**
  153. * setIdentity() - set the value to be used as the identity
  154. *
  155. * @param string $value
  156. * @return Provides a fluent interface
  157. */
  158. public function setIdentity($value)
  159. {
  160. $this->_identity = $value;
  161. return $this;
  162. }
  163. /**
  164. * setCredential() - set the credential value to be used, optionally can specify a treatment
  165. * to be used, should be supplied in parameterized form, such as 'MD5(?)' or 'PASSWORD(?)'
  166. *
  167. * @param string $credential
  168. * @return Provides a fluent interface
  169. */
  170. public function setCredential($credential)
  171. {
  172. $this->_credential = $credential;
  173. return $this;
  174. }
  175. /**
  176. * setAmbiguityIdentity() - sets a flag for usage of identical identities
  177. * with unique credentials. It accepts integers (0, 1) or boolean (true,
  178. * false) parameters. Default is false.
  179. *
  180. * @param int|bool $flag
  181. * @return Provides a fluent interface
  182. */
  183. public function setAmbiguityIdentity($flag)
  184. {
  185. if (is_integer($flag)) {
  186. $this->_ambiguityIdentity = (1 === $flag ? true : false);
  187. } elseif (is_bool($flag)) {
  188. $this->_ambiguityIdentity = $flag;
  189. }
  190. return $this;
  191. }
  192. /**
  193. * getAmbiguityIdentity() - returns TRUE for usage of multiple identical
  194. * identies with different credentials, FALSE if not used.
  195. *
  196. * @return bool
  197. */
  198. public function getAmbiguityIdentity()
  199. {
  200. return $this->_ambiguityIdentity;
  201. }
  202. /**
  203. * getResultDocObject() - Returns the result row as a stdClass object
  204. *
  205. * @param string|array $returnColumns
  206. * @param string|array $omitColumns
  207. * @return stdClass|boolean
  208. */
  209. public function getResultDocObject($returnColumns = null, $omitColumns = null)
  210. {
  211. if (!$this->_resultDoc) {
  212. return false;
  213. }
  214. return $this->_resultDoc;
  215. }
  216. /**
  217. * authenticate() - defined by C4\Library\Authentication\AuthenticationInterface.
  218. *
  219. * This method is called to
  220. * attempt an authentication. Previous to this call, this adapter would have already
  221. * been configured with all necessary information to successfully connect to a database
  222. * collection and attempt to find a record matching the provided identity.
  223. *
  224. * @throws C4\Library\Authentication\Exception if answering the authentication query is impossible
  225. * @return C4\Library\Authentication\Result
  226. */
  227. public function authenticate()
  228. {
  229. $this->_authenticateSetup();
  230. $cursor = $this->_collection->find(array(
  231. $this->_identityKeyPath => $this->_identity
  232. ));
  233. $count = $cursor->count();
  234. if ($count == 0) {
  235. $this->_authenticateResultInfo['code'] = AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND;
  236. $this->_authenticateResultInfo['messages'][] = 'A record with the supplied identity could not be found.';
  237. } elseif ($count == 1) {
  238. $resultIdentity = $cursor->getNext();
  239. $this->_resultDoc = $resultIdentity;
  240. if ($resultIdentity[$this->_credentialKeyPath] == $this->_credential) {
  241. $this->_authenticateResultInfo['code'] = AuthenticationResult::SUCCESS;
  242. $this->_authenticateResultInfo['messages'][] = 'Authentication successful.';
  243. } else {
  244. $this->_authenticateResultInfo['code'] = AuthenticationResult::FAILURE_CREDENTIAL_INVALID;
  245. $this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.';
  246. }
  247. } elseif ($count > 1) {
  248. $this->_authenticateResultInfo['code'] = AuthenticationResult::FAILURE_IDENTITY_AMBIGUOUS;
  249. $this->_authenticateResultInfo['messages'][] = 'More than one record matches the supplied identity.';
  250. }
  251. $authResult = $this->_authenticateCreateAuthResult();
  252. return $authResult;
  253. }
  254. /**
  255. * _authenticateSetup() - This method abstracts the steps involved with
  256. * making sure that this adapter was indeed setup properly with all
  257. * required pieces of information.
  258. *
  259. * @throws C4\Library\Authentication\Exception - in the event that setup was not done properly
  260. * @return true
  261. */
  262. protected function _authenticateSetup()
  263. {
  264. $exception = null;
  265. if ($this->_identityKeyPath == '') {
  266. $exception = 'An identity column must be supplied for the MongoAuth authentication adapter.';
  267. } elseif ($this->_credentialKeyPath == '') {
  268. $exception = 'A credential column must be supplied for the MongoAuth authentication adapter.';
  269. } elseif ($this->_identity == '') {
  270. $exception = 'A value for the identity was not provided prior to authentication with MongoAuth.';
  271. } elseif ($this->_credential === null) {
  272. $exception = 'A credential value was not provided prior to authentication with MongoAuth.';
  273. }
  274. if (null !== $exception) {
  275. throw new C4\Library\Authentication\Exception($exception);
  276. }
  277. $this->_authenticateResultInfo = array(
  278. 'code' => AuthenticationResult::FAILURE,
  279. 'identity' => $this->_identity,
  280. 'messages' => array()
  281. );
  282. return true;
  283. }
  284. /**
  285. * _authenticateCreateAuthResult() - Creates a AuthenticationResult object from
  286. * the information that has been collected during the authenticate() attempt.
  287. *
  288. * @return AuthenticationResult
  289. */
  290. protected function _authenticateCreateAuthResult()
  291. {
  292. return new AuthenticationResult(
  293. $this->_authenticateResultInfo['code'],
  294. $this->_authenticateResultInfo['identity'],
  295. $this->_authenticateResultInfo['messages']
  296. );
  297. }
  298. }