PasswordableBehaviorTest.php 19 KB

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