PasswordableBehaviorTest.php 21 KB

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