PasswordableBehaviorTest.php 19 KB

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