PasswordableBehaviorTest.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. <?php
  2. namespace Tools\Model\Behavior;
  3. use Cake\TestSuite\TestCase;
  4. use Cake\ORM\Behavior;
  5. use Cake\ORM\Entity;
  6. use Cake\ORM\Query;
  7. use Cake\ORM\Table;
  8. use Cake\Core\Configure;
  9. use Cake\Auth\DefaultPasswordHasher;
  10. use Cake\ORM\TableRegistry;
  11. use Cake\Utility\Security;
  12. use Cake\Routing\Router;
  13. use Cake\Network\Request;
  14. class PasswordableBehaviorTest extends TestCase {
  15. public $fixtures = array(
  16. 'plugin.tools.tools_users', 'plugin.tools.roles',
  17. );
  18. /**
  19. * SetUp method
  20. *
  21. * @return void
  22. */
  23. public function setUp() {
  24. parent::setUp();
  25. Configure::write('App.namespace', 'TestApp');
  26. Configure::delete('Passwordable');
  27. Configure::write('Passwordable.auth', 'AuthTest');
  28. $this->Users = TableRegistry::get('ToolsUsers');
  29. /*
  30. if (isset($this->Users->validate['pwd'])) {
  31. unset($this->Users->validate['pwd']);
  32. }
  33. if (isset($this->Users->validate['pwd_repeat'])) {
  34. unset($this->Users->validate['pwd_repeat']);
  35. }
  36. if (isset($this->Users->validate['pwd_current'])) {
  37. unset($this->Users->validate['pwd_current']);
  38. }
  39. if (isset($this->Users->order)) {
  40. unset($this->Users->order);
  41. }
  42. */
  43. $user = $this->Users->newEntity();
  44. $data = array(
  45. 'id' => '5',
  46. 'name' => 'admin',
  47. 'password' => Security::hash('somepwd', null, true),
  48. 'role_id' => '1'
  49. );
  50. $this->Users->patchEntity($user, $data);
  51. $result = $this->Users->save($user);
  52. $this->assertTrue((bool)$result);
  53. Router::setRequestInfo(new Request());
  54. }
  55. /**
  56. * PasswordableBehaviorTest::testObject()
  57. *
  58. * @return void
  59. */
  60. public function testObject() {
  61. $this->Users->Behaviors->load('Tools.Passwordable', array());
  62. $this->assertInstanceOf('PasswordableBehavior', $this->Users->Behaviors->Passwordable);
  63. $result = $this->Users->Behaviors->loaded('Passwordable');
  64. $this->assertTrue($result);
  65. }
  66. /**
  67. * Make sure validation is triggered correctly
  68. *
  69. * @return void
  70. */
  71. public function testValidate() {
  72. $this->Users->Behaviors->load('Tools.Passwordable', array());
  73. $this->Users->create();
  74. $data = array(
  75. 'pwd' => '123456',
  76. );
  77. $this->Users->set($data);
  78. $is = $this->Users->save();
  79. //debug($this->Users->validationErrors);
  80. $this->assertFalse($is);
  81. $this->assertEquals(array('pwd_repeat'), array_keys($this->Users->validationErrors));
  82. $this->Users->create();
  83. $data = array(
  84. 'pwd' => '1234ab',
  85. 'pwd_repeat' => '123456'
  86. );
  87. $this->Users->set($data);
  88. $is = $this->Users->save();
  89. //debug($this->Users->validationErrors);
  90. $this->assertFalse($is);
  91. $this->assertEquals(array(__d('tools', 'valErrPwdNotMatch')), $this->Users->validationErrors['pwd_repeat']);
  92. $this->Users->create();
  93. $data = array(
  94. 'pwd' => '123456',
  95. 'pwd_repeat' => '123456'
  96. );
  97. $this->Users->set($data);
  98. //debug($this->Users->validate);
  99. $is = $this->Users->validates();
  100. $this->assertTrue(!empty($is));
  101. }
  102. /**
  103. * Test that confirm false does not require confirmation
  104. *
  105. * @return void
  106. */
  107. public function testValidateNoConfirm() {
  108. $this->Users->Behaviors->load('Tools.Passwordable', array('confirm' => false));
  109. $this->Users->create();
  110. $data = array(
  111. 'pwd' => '123456',
  112. );
  113. $this->Users->set($data);
  114. $is = $this->Users->save();
  115. //debug($is);
  116. $this->assertTrue(!empty($is));
  117. }
  118. /**
  119. * Trigger validation and update process if no values are entered but are required
  120. *
  121. * @return void
  122. */
  123. public function testValidateRequired() {
  124. $this->Users->Behaviors->load('Tools.Passwordable');
  125. $this->Users->create();
  126. $data = array(
  127. 'pwd' => '',
  128. 'pwd_repeat' => ''
  129. );
  130. $this->Users->set($data);
  131. $is = $this->Users->save();
  132. $this->assertFalse($is);
  133. $this->assertEquals(array('pwd', 'pwd_repeat'), array_keys($this->Users->validationErrors));
  134. }
  135. /**
  136. * Validation and update process gets skipped if no values are entered
  137. *
  138. * @return void
  139. */
  140. public function testValidateNotRequired() {
  141. $this->Users->Behaviors->load('Tools.Passwordable', array('require' => false));
  142. $this->Users->create();
  143. $data = array(
  144. 'name' => 'foo', // we need at least one field besides the password on CREATE
  145. 'pwd' => '',
  146. 'pwd_repeat' => ''
  147. );
  148. $this->Users->set($data);
  149. $is = $this->Users->save();
  150. $this->assertTrue((bool)$is);
  151. $this->assertEquals(array('name', 'id'), array_keys($is[$this->Users->alias]));
  152. $id = $this->Users->id;
  153. $data = array(
  154. 'id' => $id,
  155. 'pwd' => '',
  156. 'pwd_repeat' => ''
  157. );
  158. $this->Users->set($data);
  159. $is = $this->Users->save();
  160. $this->assertTrue((bool)$is);
  161. $this->assertEquals(array('id'), array_keys($is[$this->Users->alias]));
  162. }
  163. /**
  164. * PasswordableBehaviorTest::testValidateEmptyWithCurrentPassword()
  165. *
  166. * @return void
  167. */
  168. public function testValidateEmptyWithCurrentPassword() {
  169. $this->Users->Behaviors->load('Tools.Passwordable', array('current' => true));
  170. $this->Users->create();
  171. $data = array(
  172. 'id' => '123',
  173. 'pwd' => '',
  174. 'pwd_repeat' => '',
  175. 'pwd_current' => '123456',
  176. );
  177. $this->Users->set($data);
  178. $is = $this->Users->save();
  179. //debug($this->Users->validationErrors);
  180. $this->assertFalse($is);
  181. $this->assertEquals(array('pwd', 'pwd_repeat', 'pwd_current'), array_keys($this->Users->validationErrors));
  182. $this->tearDown();
  183. $this->setUp();
  184. $this->Users->Behaviors->load('Tools.Passwordable', array('require' => false, 'current' => true));
  185. $this->Users->create();
  186. $data = array(
  187. 'name' => 'foo',
  188. 'pwd' => '',
  189. 'pwd_repeat' => '',
  190. 'pwd_current' => '',
  191. );
  192. $is = $this->Users->save($data);
  193. $this->assertTrue(!empty($is));
  194. }
  195. /**
  196. * Test aliases for field names
  197. */
  198. public function testDifferentFieldNames() {
  199. $this->Users->Behaviors->load('Tools.Passwordable', array(
  200. 'formField' => 'passw',
  201. 'formFieldRepeat' => 'passw_repeat',
  202. 'formFieldCurrent' => 'passw_current',
  203. ));
  204. $this->Users->create();
  205. $data = array(
  206. 'passw' => '123456',
  207. 'passw_repeat' => '123456'
  208. );
  209. $this->Users->set($data);
  210. //debug($this->Users->data);
  211. $is = $this->Users->save();
  212. $this->assertTrue(!empty($is));
  213. }
  214. /**
  215. * Assert that allowSame false does not allow storing the same password as previously entered
  216. */
  217. public function testNotSame() {
  218. $this->Users->Behaviors->load('Tools.Passwordable', array(
  219. 'formField' => 'passw',
  220. 'formFieldRepeat' => 'passw_repeat',
  221. 'formFieldCurrent' => 'passw_current',
  222. 'allowSame' => false,
  223. 'current' => true,
  224. ));
  225. $this->Users->create();
  226. $data = array(
  227. 'id' => '5',
  228. 'passw_current' => 'something',
  229. 'passw' => 'somepwd',
  230. 'passw_repeat' => 'somepwd'
  231. );
  232. $this->Users->set($data);
  233. $is = $this->Users->save();
  234. //debug($this->Users->validationErrors);
  235. $this->assertFalse($is);
  236. $this->Users->create();
  237. $data = array(
  238. 'id' => '5',
  239. 'passw_current' => 'somepwd',
  240. 'passw' => 'newpwd',
  241. 'passw_repeat' => 'newpwd'
  242. );
  243. $this->Users->set($data);
  244. $is = $this->Users->save();
  245. $this->assertTrue(!empty($is));
  246. }
  247. /**
  248. * Assert that allowSame false does not allow storing the same password as previously entered
  249. */
  250. public function testNotSameWithoutCurrentField() {
  251. $this->Users->Behaviors->load('Tools.Passwordable', array(
  252. 'formField' => 'passw',
  253. 'formFieldRepeat' => 'passw_repeat',
  254. 'allowSame' => false,
  255. 'current' => false
  256. ));
  257. $this->Users->create();
  258. $data = array(
  259. 'passw' => 'somepwd',
  260. 'passw_repeat' => 'somepwd'
  261. );
  262. $this->Users->set($data);
  263. $is = $this->Users->save();
  264. $this->assertTrue((bool)$is);
  265. $id = $is[$this->Users->alias]['id'];
  266. $this->Users->create();
  267. $data = array(
  268. 'id' => $id,
  269. 'passw' => 'somepwd',
  270. 'passw_repeat' => 'somepwd'
  271. );
  272. $this->Users->set($data);
  273. $is = $this->Users->save();
  274. $this->assertFalse((bool)$is);
  275. $this->Users->create();
  276. $data = array(
  277. 'id' => $id,
  278. 'passw' => 'newpwd',
  279. 'passw_repeat' => 'newpwd'
  280. );
  281. $this->Users->set($data);
  282. $is = $this->Users->save();
  283. $this->assertTrue((bool)$is);
  284. }
  285. /**
  286. * Assert that on edit it does not wrongly pass validation (require => false)
  287. */
  288. public function testRequireFalse() {
  289. $this->Users->Behaviors->load('Tools.Passwordable', array(
  290. 'formField' => 'passw',
  291. 'formFieldRepeat' => 'passw_repeat',
  292. 'require' => false
  293. ));
  294. $this->Users->create();
  295. $data = array(
  296. 'passw' => 'somepwd',
  297. 'passw_repeat' => 'somepwd'
  298. );
  299. $this->Users->set($data);
  300. $is = $this->Users->save();
  301. $this->assertTrue((bool)$is);
  302. $id = $is[$this->Users->alias]['id'];
  303. $this->Users->create();
  304. $data = array(
  305. 'id' => $id,
  306. 'passw' => 'somepwd2',
  307. 'passw_repeat' => ''
  308. );
  309. $this->Users->set($data);
  310. $is = $this->Users->save();
  311. $this->assertFalse((bool)$is);
  312. //debug($this->Users->validationErrors);
  313. $this->Users->create();
  314. $data = array(
  315. 'id' => $id,
  316. 'passw' => 'somepwd2',
  317. 'passw_repeat' => 'somepwd2'
  318. );
  319. $this->Users->set($data);
  320. $is = $this->Users->save();
  321. $this->assertTrue((bool)$is);
  322. }
  323. /**
  324. * Needs faking of pwd check...
  325. */
  326. public function testValidateCurrent() {
  327. $this->assertFalse($this->Users->Behaviors->loaded('Passwordable'));
  328. $this->Users->create();
  329. $data = array(
  330. 'name' => 'xyz',
  331. 'password' => Security::hash('somepwd', null, true));
  332. $result = $this->Users->save($data);
  333. $this->assertTrue(!empty($result));
  334. $uid = (string)$this->Users->id;
  335. $this->Users->Behaviors->load('Tools.Passwordable', array('current' => true));
  336. $this->Users->create();
  337. $data = array(
  338. 'id' => $uid,
  339. 'pwd' => '123456',
  340. 'pwd_repeat' => '12345678',
  341. //'pwd_current' => '',
  342. );
  343. $this->Users->set($data);
  344. $this->assertTrue($this->Users->Behaviors->loaded('Passwordable'));
  345. $is = $this->Users->save();
  346. $this->assertFalse($is);
  347. $this->Users->create();
  348. $data = array(
  349. 'id' => $uid,
  350. 'pwd_current' => 'somepwdx',
  351. 'pwd' => '123456',
  352. 'pwd_repeat' => '123456'
  353. );
  354. $this->Users->set($data);
  355. $is = $this->Users->save();
  356. $this->assertFalse($is);
  357. $this->Users->create();
  358. $data = array(
  359. 'id' => $uid,
  360. 'name' => 'Yeah',
  361. 'pwd_current' => 'somepwd',
  362. 'pwd' => '123456',
  363. 'pwd_repeat' => '123456'
  364. );
  365. $this->Users->set($data);
  366. // Test whitelist setting - only "password" needs to gets auto-added
  367. $options = array('validate' => true, 'fieldList' => array('id', 'pwd', 'pwd_repeat', 'pwd_current'));
  368. $is = $this->Users->save(null, $options);
  369. $this->assertTrue(!empty($is));
  370. $user = $this->Users->get($uid);
  371. // The password is updated, the name not
  372. $this->assertSame($is['ToolsUser']['password'], $user['ToolsUser']['password']);
  373. $this->assertSame('xyz', $user['ToolsUser']['name']);
  374. // Proof that we manually need to add pwd, pwd_repeat etc due to a bug in CakePHP<=2.4 allowing behaviors to only modify saving,
  375. // not validating of additional whitelist fields. Validation for those will be just skipped, no matter what the behavior tries
  376. // to set.
  377. $this->Users->create();
  378. $data = array(
  379. 'id' => $uid,
  380. 'name' => 'Yeah',
  381. 'pwd_current' => '123', // Obviously wrong
  382. 'pwd' => 'some', // Too short
  383. 'pwd_repeat' => 'somex' // Don't match
  384. );
  385. $this->Users->set($data);
  386. // Test whitelist setting - only "password" gets auto-added, pwd, pwd_repeat etc need to be added manually
  387. // NOTE that I had to remove the code for adding those fields from the behavior (as it was not functional)
  388. // So of course, this won't work now as expected. But feel free to try to add them in the behavior. Results will be the same.
  389. $options = array('validate' => true, 'fieldList' => array('id', 'name'));
  390. $is = $this->Users->save(null, $options);
  391. if ((float)Configure::version() >= 2.5) {
  392. // Validation errors triggered - as expected
  393. $this->assertFalse($is);
  394. $this->assertSame(array('pwd', 'pwd_repeat', 'pwd_current'), array_keys($this->Users->validationErrors));
  395. return;
  396. }
  397. // Save is successful
  398. $this->assertTrue(!empty($is));
  399. $user = $this->Users->get($uid);
  400. $this->assertSame('Yeah', $user['ToolsUser']['name']);
  401. // The password is not updated, the name is
  402. $this->assertSame($is['ToolsUser']['password'], $user['ToolsUser']['password']);
  403. $this->assertSame('Yeah', $user['ToolsUser']['name']);
  404. }
  405. /**
  406. * Test cake2.4 passwordHasher feature
  407. *
  408. * @return void
  409. */
  410. public function testPasswordHasher() {
  411. $this->skipIf((float)Configure::version() < 2.4, 'Needs 2.4 and above');
  412. $this->Users->Behaviors->load('Tools.Passwordable', array(
  413. 'formField' => 'pwd',
  414. 'formFieldRepeat' => 'pwd_repeat',
  415. 'allowSame' => false,
  416. 'current' => false,
  417. 'passwordHasher' => 'Complex',
  418. ));
  419. $this->Users->create();
  420. $data = array(
  421. 'pwd' => 'somepwd',
  422. 'pwd_repeat' => 'somepwd'
  423. );
  424. $this->Users->set($data);
  425. $result = $this->Users->save();
  426. $this->assertTrue((bool)$result);
  427. $uid = (string)$this->Users->id;
  428. $this->Users->Behaviors->load('Tools.Passwordable', array('current' => true));
  429. $this->Users->create();
  430. $data = array(
  431. 'id' => $uid,
  432. 'pwd' => '123456',
  433. 'pwd_repeat' => '12345678',
  434. //'pwd_current' => '',
  435. );
  436. $this->Users->set($data);
  437. $this->assertTrue($this->Users->Behaviors->loaded('Passwordable'));
  438. $is = $this->Users->save();
  439. $this->assertFalse($is);
  440. $this->Users->create();
  441. $data = array(
  442. 'id' => $uid,
  443. 'pwd_current' => 'somepwdx',
  444. 'pwd' => '123456',
  445. 'pwd_repeat' => '123456'
  446. );
  447. $this->Users->set($data);
  448. $is = $this->Users->save();
  449. $this->assertFalse($is);
  450. $this->Users->create();
  451. $data = array(
  452. 'id' => $uid,
  453. 'pwd_current' => 'somepwd',
  454. 'pwd' => '123456',
  455. 'pwd_repeat' => '123456'
  456. );
  457. $this->Users->set($data);
  458. $is = $this->Users->save();
  459. $this->assertTrue(!empty($is));
  460. }
  461. /**
  462. * PasswordableBehaviorTest::testBlowfish()
  463. *
  464. * @return void
  465. */
  466. public function testBlowfish() {
  467. $this->Users->Behaviors->load('Tools.Passwordable', array(
  468. 'allowSame' => false,
  469. 'current' => false,
  470. 'authType' => 'Blowfish',
  471. ));
  472. $this->Users->create();
  473. $data = array(
  474. 'pwd' => 'somepwd',
  475. 'pwd_repeat' => 'somepwd'
  476. );
  477. $this->Users->set($data);
  478. $result = $this->Users->save();
  479. $this->assertTrue((bool)$result);
  480. $uid = (string)$this->Users->id;
  481. $this->Users->Behaviors->load('Tools.Passwordable', array('current' => true));
  482. // Without the current password it will not continue
  483. $this->Users->create();
  484. $data = array(
  485. 'id' => $uid,
  486. 'pwd' => '123456',
  487. 'pwd_repeat' => '12345678',
  488. );
  489. $this->Users->set($data);
  490. $this->assertTrue($this->Users->Behaviors->loaded('Passwordable'));
  491. $result = $this->Users->save();
  492. $this->assertFalse($result);
  493. // Without the correct current password it will not continue
  494. $this->Users->create();
  495. $data = array(
  496. 'id' => $uid,
  497. 'pwd_current' => 'somepwdx',
  498. 'pwd' => '123456',
  499. 'pwd_repeat' => '123456'
  500. );
  501. $this->Users->set($data);
  502. $result = $this->Users->save();
  503. $this->assertFalse($result);
  504. // Now it will
  505. $this->Users->create();
  506. $data = array(
  507. 'id' => $uid,
  508. 'pwd_current' => 'somepwd',
  509. 'pwd' => '123456',
  510. 'pwd_repeat' => '123456'
  511. );
  512. $this->Users->set($data);
  513. $result = $this->Users->save();
  514. $this->assertTrue((bool)$result);
  515. }
  516. /**
  517. * Tests that passwords prior to PHP5.5 and/or password_hash() are still working
  518. * if Tools.Modern is being used.
  519. *
  520. * @return void
  521. */
  522. public function testBlowfishWithBC() {
  523. $this->skipIf(!function_exists('password_hash'), 'password_hash() is not available.');
  524. $oldHash = Security::hash('foobar', 'blowfish', false);
  525. $newHash = password_hash('foobar', PASSWORD_BCRYPT);
  526. $this->Users->Behaviors->load('Tools.Passwordable', array(
  527. 'allowSame' => false,
  528. 'current' => false,
  529. 'authType' => 'Blowfish',
  530. 'passwordHasher' => 'Tools.Modern'
  531. ));
  532. $this->Users->create();
  533. $data = array(
  534. 'pwd' => 'somepwd',
  535. 'pwd_repeat' => 'somepwd'
  536. );
  537. $this->Users->set($data);
  538. $result = $this->Users->save();
  539. $this->assertTrue((bool)$result);
  540. $uid = (string)$this->Users->id;
  541. // Same pwd is not allowed
  542. $this->Users->create();
  543. $data = array(
  544. 'id' => $uid,
  545. 'pwd' => 'somepwd',
  546. 'pwd_repeat' => 'somepwd'
  547. );
  548. $this->Users->set($data);
  549. $result = $this->Users->save();
  550. $this->assertFalse($result);
  551. $this->Users->Behaviors->load('Tools.Passwordable', array('current' => true));
  552. // Without the correct current password it will not continue
  553. $this->Users->create();
  554. $data = array(
  555. 'id' => $uid,
  556. 'pwd_current' => 'somepwdxyz',
  557. 'pwd' => '123456',
  558. 'pwd_repeat' => '123456'
  559. );
  560. $this->Users->set($data);
  561. $result = $this->Users->save();
  562. $this->assertFalse($result);
  563. // Now it will
  564. $this->Users->create();
  565. $data = array(
  566. 'id' => $uid,
  567. 'pwd_current' => 'somepwd',
  568. 'pwd' => '123456',
  569. 'pwd_repeat' => '123456'
  570. );
  571. $this->Users->set($data);
  572. $result = $this->Users->save();
  573. $this->assertTrue((bool)$result);
  574. // Lets set a BC password (without password_hash() method but Security class)
  575. $data = array(
  576. 'id' => $uid,
  577. 'password' => $oldHash,
  578. );
  579. $result = $this->Users->save($data, array('validate' => false));
  580. $this->assertTrue((bool)$result);
  581. // Now it will still work
  582. $this->Users->create();
  583. $data = array(
  584. 'id' => $uid,
  585. 'pwd_current' => 'foobar',
  586. 'pwd' => '123456',
  587. 'pwd_repeat' => '123456'
  588. );
  589. $this->Users->set($data);
  590. $result = $this->Users->save();
  591. $this->assertTrue((bool)$result);
  592. // Lets set an invalid BC password (without password_hash() method but Security class)
  593. $data = array(
  594. 'id' => $uid,
  595. 'password' => $oldHash . 'x',
  596. );
  597. $result = $this->Users->save($data, array('validate' => false));
  598. $this->assertTrue((bool)$result);
  599. // Now it will still work
  600. $this->Users->create();
  601. $data = array(
  602. 'id' => $uid,
  603. 'pwd_current' => 'foobar',
  604. 'pwd' => '123456',
  605. 'pwd_repeat' => '123456'
  606. );
  607. $this->Users->set($data);
  608. $result = $this->Users->save();
  609. $this->assertFalse($result);
  610. // Lets set a valid BC password (without password_hash() method but Security class)
  611. // But the provided pwd is incorrect
  612. $data = array(
  613. 'id' => $uid,
  614. 'password' => $oldHash,
  615. );
  616. $result = $this->Users->save($data, array('validate' => false));
  617. $this->assertTrue((bool)$result);
  618. // Now it will still work
  619. $this->Users->create();
  620. $data = array(
  621. 'id' => $uid,
  622. 'pwd_current' => 'foobarx',
  623. 'pwd' => '123456',
  624. 'pwd_repeat' => '123456'
  625. );
  626. $this->Users->set($data);
  627. $result = $this->Users->save();
  628. $this->assertFalse($result);
  629. }
  630. /**
  631. * Tests needsPasswordRehash()
  632. *
  633. * @return void
  634. */
  635. public function testNeedsPasswordRehash() {
  636. $this->skipIf(!function_exists('password_hash'), 'password_hash() is not available.');
  637. $this->Users->Behaviors->load('Tools.Passwordable', array(
  638. 'allowSame' => false,
  639. 'current' => false,
  640. 'authType' => 'Blowfish',
  641. 'passwordHasher' => 'Tools.Modern'
  642. ));
  643. $hash = password_hash('foobar', PASSWORD_BCRYPT);
  644. $result = $this->Users->needsPasswordRehash($hash);
  645. $this->assertFalse($result);
  646. $hash = sha1('foobar');
  647. $result = $this->Users->needsPasswordRehash($hash);
  648. $this->assertTrue($result);
  649. }
  650. /**
  651. * Tests needsPasswordRehash()
  652. *
  653. * @return void
  654. */
  655. public function testNeedsPasswordRehashWithNotSupportedHasher() {
  656. $this->Users->Behaviors->load('Tools.Passwordable', array(
  657. 'allowSame' => false,
  658. 'current' => false,
  659. 'authType' => 'Blowfish',
  660. ));
  661. $hash = password_hash('foobar', PASSWORD_BCRYPT);
  662. $result = $this->Users->needsPasswordRehash($hash);
  663. $this->assertFalse($result);
  664. $this->Users->Behaviors->load('Tools.Passwordable', array(
  665. 'allowSame' => false,
  666. 'current' => false,
  667. 'authType' => 'Blowfish',
  668. 'passwordHasher' => 'Simple'
  669. ));
  670. $hash = password_hash('foobar', PASSWORD_BCRYPT);
  671. $result = $this->Users->needsPasswordRehash($hash);
  672. $this->assertFalse($result);
  673. }
  674. /**
  675. * PasswordableBehaviorTest::testSettings()
  676. *
  677. * @return void
  678. */
  679. public function testSettings() {
  680. // Pwd min and max length
  681. $this->Users->Behaviors->load('Tools.Passwordable', array(
  682. 'allowSame' => false,
  683. 'current' => false,
  684. 'minLength' => 3,
  685. 'maxLength' => 6,
  686. ));
  687. $this->Users->create();
  688. $data = array(
  689. 'pwd' => '123',
  690. 'pwd_repeat' => '123'
  691. );
  692. $this->Users->set($data);
  693. $result = $this->Users->save();
  694. $this->assertTrue((bool)$result);
  695. $this->Users->create();
  696. $data = array(
  697. 'pwd' => '12345678',
  698. 'pwd_repeat' => '12345678'
  699. );
  700. $this->Users->set($data);
  701. $result = $this->Users->save();
  702. $this->assertFalse($result);
  703. $expected = array(
  704. 'pwd' => array(__d('tools', 'valErrBetweenCharacters %s %s', 3, 6)),
  705. 'pwd_repeat' => array(__d('tools', 'valErrBetweenCharacters %s %s', 3, 6))
  706. );
  707. $this->assertEquals($expected, $this->Users->validationErrors);
  708. }
  709. /**
  710. * Test that validate false also works.
  711. *
  712. * @return void
  713. */
  714. public function testSaveWithValidateFalse() {
  715. $this->Users->Behaviors->load('Tools.Passwordable');
  716. $this->Users->create();
  717. $data = array(
  718. 'pwd' => '123',
  719. );
  720. $this->Users->set($data);
  721. $result = $this->Users->save(null, array('validate' => false));
  722. $this->assertTrue((bool)$result);
  723. $uid = (string)$this->Users->id;
  724. $data = array(
  725. 'id' => $uid,
  726. 'pwd' => '1234'
  727. );
  728. $this->Users->set($data);
  729. $result2 = $this->Users->save(null, array('validate' => false));
  730. $this->assertTrue((bool)$result2);
  731. $this->assertTrue($result['ToolsUser']['password'] !== $result2['ToolsUser']['password']);
  732. }
  733. }
  734. class ComplexPasswordHasher extends DefaultPasswordHasher {
  735. }