DbAclTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. <?php
  2. /**
  3. * DbAclTest file.
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * For full copyright and license information, please see the LICENSE.txt
  12. * Redistributions of files must retain the above copyright notice.
  13. *
  14. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP(tm) Project
  16. * @package Cake.Test.Case.Controller.Component.Acl
  17. * @since CakePHP(tm) v 2.0
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. App::uses('ComponentCollection', 'Controller');
  21. App::uses('AclComponent', 'Controller/Component');
  22. App::uses('DbAcl', 'Controller/Component/Acl');
  23. App::uses('AclNode', 'Model');
  24. App::uses('Permission', 'Model');
  25. require_once dirname(dirname(dirname(dirname(__FILE__)))) . DS . 'Model' . DS . 'models.php';
  26. /**
  27. * AclNodeTwoTestBase class
  28. *
  29. * @package Cake.Test.Case.Controller.Component.Acl
  30. */
  31. class AclNodeTwoTestBase extends AclNode {
  32. /**
  33. * useDbConfig property
  34. *
  35. * @var string 'test'
  36. */
  37. public $useDbConfig = 'test';
  38. /**
  39. * cacheSources property
  40. *
  41. * @var bool false
  42. */
  43. public $cacheSources = false;
  44. }
  45. /**
  46. * AroTwoTest class
  47. *
  48. * @package Cake.Test.Case.Controller.Component.Acl
  49. */
  50. class AroTwoTest extends AclNodeTwoTestBase {
  51. /**
  52. * name property
  53. *
  54. * @var string 'AroTwoTest'
  55. */
  56. public $name = 'AroTwoTest';
  57. /**
  58. * useTable property
  59. *
  60. * @var string 'aro_twos'
  61. */
  62. public $useTable = 'aro_twos';
  63. /**
  64. * hasAndBelongsToMany property
  65. *
  66. * @var array
  67. */
  68. public $hasAndBelongsToMany = array('AcoTwoTest' => array('with' => 'PermissionTwoTest'));
  69. }
  70. /**
  71. * AcoTwoTest class
  72. *
  73. * @package Cake.Test.Case.Controller.Component.Acl
  74. */
  75. class AcoTwoTest extends AclNodeTwoTestBase {
  76. /**
  77. * name property
  78. *
  79. * @var string 'AcoTwoTest'
  80. */
  81. public $name = 'AcoTwoTest';
  82. /**
  83. * useTable property
  84. *
  85. * @var string 'aco_twos'
  86. */
  87. public $useTable = 'aco_twos';
  88. /**
  89. * hasAndBelongsToMany property
  90. *
  91. * @var array
  92. */
  93. public $hasAndBelongsToMany = array('AroTwoTest' => array('with' => 'PermissionTwoTest'));
  94. }
  95. /**
  96. * PermissionTwoTest class
  97. *
  98. * @package Cake.Test.Case.Controller.Component.Acl
  99. */
  100. class PermissionTwoTest extends Permission {
  101. /**
  102. * name property
  103. *
  104. * @var string 'PermissionTwoTest'
  105. */
  106. public $name = 'PermissionTwoTest';
  107. /**
  108. * useTable property
  109. *
  110. * @var string 'aros_aco_twos'
  111. */
  112. public $useTable = 'aros_aco_twos';
  113. /**
  114. * cacheQueries property
  115. *
  116. * @var bool false
  117. */
  118. public $cacheQueries = false;
  119. /**
  120. * belongsTo property
  121. *
  122. * @var array
  123. */
  124. public $belongsTo = array('AroTwoTest' => array('foreignKey' => 'aro_id'), 'AcoTwoTest' => array('foreignKey' => 'aco_id'));
  125. /**
  126. * actsAs property
  127. *
  128. * @var mixed null
  129. */
  130. public $actsAs = null;
  131. }
  132. /**
  133. * DbAclTwoTest class
  134. *
  135. * @package Cake.Test.Case.Controller.Component.Acl
  136. */
  137. class DbAclTwoTest extends DbAcl {
  138. /**
  139. * construct method
  140. *
  141. * @return void
  142. */
  143. public function __construct() {
  144. $this->Aro = new AroTwoTest();
  145. $this->Aro->Permission = new PermissionTwoTest();
  146. $this->Aco = new AcoTwoTest();
  147. $this->Aro->Permission = new PermissionTwoTest();
  148. $this->Permission = $this->Aro->Permission;
  149. $this->Permission->Aro = $this->Aro;
  150. $this->Permission->Aco = $this->Aco;
  151. }
  152. }
  153. /**
  154. * Test case for AclComponent using the DbAcl implementation.
  155. *
  156. * @package Cake.Test.Case.Controller.Component.Acl
  157. */
  158. class DbAclTest extends CakeTestCase {
  159. /**
  160. * fixtures property
  161. *
  162. * @var array
  163. */
  164. public $fixtures = array('core.aro_two', 'core.aco_two', 'core.aros_aco_two');
  165. /**
  166. * setUp method
  167. *
  168. * @return void
  169. */
  170. public function setUp() {
  171. parent::setUp();
  172. Configure::write('Acl.classname', 'DbAclTwoTest');
  173. Configure::write('Acl.database', 'test');
  174. $Collection = new ComponentCollection();
  175. $this->Acl = new AclComponent($Collection);
  176. }
  177. /**
  178. * tearDown method
  179. *
  180. * @return void
  181. */
  182. public function tearDown() {
  183. parent::tearDown();
  184. unset($this->Acl);
  185. }
  186. /**
  187. * testAclCreate method
  188. *
  189. * @return void
  190. */
  191. public function testCreate() {
  192. $this->Acl->Aro->create(array('alias' => 'Chotchkey'));
  193. $this->assertTrue((bool)$this->Acl->Aro->save());
  194. $parent = $this->Acl->Aro->id;
  195. $this->Acl->Aro->create(array('parent_id' => $parent, 'alias' => 'Joanna'));
  196. $this->assertTrue((bool)$this->Acl->Aro->save());
  197. $this->Acl->Aro->create(array('parent_id' => $parent, 'alias' => 'Stapler'));
  198. $this->assertTrue((bool)$this->Acl->Aro->save());
  199. $root = $this->Acl->Aco->node('ROOT');
  200. $parent = $root[0]['AcoTwoTest']['id'];
  201. $this->Acl->Aco->create(array('parent_id' => $parent, 'alias' => 'Drinks'));
  202. $this->assertTrue((bool)$this->Acl->Aco->save());
  203. $this->Acl->Aco->create(array('parent_id' => $parent, 'alias' => 'PiecesOfFlair'));
  204. $this->assertTrue((bool)$this->Acl->Aco->save());
  205. }
  206. /**
  207. * testAclCreateWithParent method
  208. *
  209. * @return void
  210. */
  211. public function testCreateWithParent() {
  212. $parent = $this->Acl->Aro->findByAlias('Peter', null, null, -1);
  213. $this->Acl->Aro->create();
  214. $this->Acl->Aro->save(array(
  215. 'alias' => 'Subordinate',
  216. 'model' => 'User',
  217. 'foreign_key' => 7,
  218. 'parent_id' => $parent['AroTwoTest']['id']
  219. ));
  220. $result = $this->Acl->Aro->findByAlias('Subordinate', null, null, -1);
  221. $this->assertEquals(16, $result['AroTwoTest']['lft']);
  222. $this->assertEquals(17, $result['AroTwoTest']['rght']);
  223. }
  224. /**
  225. * testDbAclAllow method
  226. *
  227. * @expectedException PHPUnit_Framework_Error_Warning
  228. * @return void
  229. */
  230. public function testAllow() {
  231. $this->assertFalse($this->Acl->check('Micheal', 'tpsReports', 'read'));
  232. $this->assertTrue($this->Acl->allow('Micheal', 'tpsReports', array('read', 'delete', 'update')));
  233. $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'update'));
  234. $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'read'));
  235. $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'delete'));
  236. $this->assertFalse($this->Acl->check('Micheal', 'tpsReports', 'create'));
  237. $this->assertTrue($this->Acl->allow('Micheal', 'ROOT/tpsReports', 'create'));
  238. $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'create'));
  239. $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'delete'));
  240. $this->assertTrue($this->Acl->allow('Micheal', 'printers', 'create'));
  241. // Michael no longer has his delete permission for tpsReports!
  242. $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'delete'));
  243. $this->assertTrue($this->Acl->check('Micheal', 'printers', 'create'));
  244. $this->assertFalse($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/view'));
  245. $this->assertTrue($this->Acl->allow('root/users/Samir', 'ROOT/tpsReports/view', '*'));
  246. $this->assertTrue($this->Acl->check('Samir', 'view', 'read'));
  247. $this->assertTrue($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/view', 'update'));
  248. $this->assertFalse($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/update','*'));
  249. $this->assertTrue($this->Acl->allow('root/users/Samir', 'ROOT/tpsReports/update', '*'));
  250. $this->assertTrue($this->Acl->check('Samir', 'update', 'read'));
  251. $this->assertTrue($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/update', 'update'));
  252. // Samir should still have his tpsReports/view permissions, but does not
  253. $this->assertTrue($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/view', 'update'));
  254. $this->assertFalse($this->Acl->allow('Lumbergh', 'ROOT/tpsReports/DoesNotExist', 'create'));
  255. }
  256. /**
  257. * testAllowInvalidNode method
  258. *
  259. * @expectedException PHPUnit_Framework_Error_Warning
  260. * @return void
  261. */
  262. public function testAllowInvalidNode() {
  263. $this->Acl->allow('Homer', 'tpsReports', 'create');
  264. }
  265. /**
  266. * testDbAclCheck method
  267. *
  268. * @return void
  269. */
  270. public function testCheck() {
  271. $this->assertTrue($this->Acl->check('Samir', 'print', 'read'));
  272. $this->assertTrue($this->Acl->check('Lumbergh', 'current', 'read'));
  273. $this->assertFalse($this->Acl->check('Milton', 'smash', 'read'));
  274. $this->assertFalse($this->Acl->check('Milton', 'current', 'update'));
  275. $this->assertFalse($this->Acl->check(null, 'printers', 'create'));
  276. $this->assertFalse($this->Acl->check('managers', null, 'read'));
  277. $this->assertTrue($this->Acl->check('Bobs', 'ROOT/tpsReports/view/current', 'read'));
  278. $this->assertFalse($this->Acl->check('Samir', 'ROOT/tpsReports/update', 'read'));
  279. $this->assertFalse($this->Acl->check('root/users/Milton', 'smash', 'delete'));
  280. }
  281. /**
  282. * testCheckInvalidNode method
  283. *
  284. * @expectedException PHPUnit_Framework_Error_Warning
  285. * @return void
  286. */
  287. public function testCheckInvalidNode() {
  288. $this->assertFalse($this->Acl->check('WRONG', 'tpsReports', 'read'));
  289. }
  290. /**
  291. * testCheckInvalidPermission method
  292. *
  293. * @expectedException PHPUnit_Framework_Error_Notice
  294. * @return void
  295. */
  296. public function testCheckInvalidPermission() {
  297. $this->Acl->check('Lumbergh', 'smash', 'foobar');
  298. }
  299. /**
  300. * testCheckMissingPermission method
  301. *
  302. * @expectedException PHPUnit_Framework_Error_Warning
  303. * @return void
  304. */
  305. public function testCheckMissingPermission() {
  306. $this->Acl->check('users', 'NonExistent', 'read');
  307. }
  308. /**
  309. * testDbAclCascadingDeny function
  310. *
  311. * Setup the acl permissions such that Bobs inherits from admin.
  312. * deny Admin delete access to a specific resource, check the permissions are inherited.
  313. *
  314. * @return void
  315. */
  316. public function testAclCascadingDeny() {
  317. $this->Acl->inherit('Bobs', 'ROOT', '*');
  318. $this->assertTrue($this->Acl->check('admin', 'tpsReports', 'delete'));
  319. $this->assertTrue($this->Acl->check('Bobs', 'tpsReports', 'delete'));
  320. $this->Acl->deny('admin', 'tpsReports', 'delete');
  321. $this->assertFalse($this->Acl->check('admin', 'tpsReports', 'delete'));
  322. $this->assertFalse($this->Acl->check('Bobs', 'tpsReports', 'delete'));
  323. }
  324. /**
  325. * testDbAclDeny method
  326. *
  327. * @expectedException PHPUnit_Framework_Error_Warning
  328. * @return void
  329. */
  330. public function testDeny() {
  331. $this->assertTrue($this->Acl->check('Micheal', 'smash', 'delete'));
  332. $this->Acl->deny('Micheal', 'smash', 'delete');
  333. $this->assertFalse($this->Acl->check('Micheal', 'smash', 'delete'));
  334. $this->assertTrue($this->Acl->check('Micheal', 'smash', 'read'));
  335. $this->assertTrue($this->Acl->check('Micheal', 'smash', 'create'));
  336. $this->assertTrue($this->Acl->check('Micheal', 'smash', 'update'));
  337. $this->assertFalse($this->Acl->check('Micheal', 'smash', '*'));
  338. $this->assertTrue($this->Acl->check('Samir', 'refill', '*'));
  339. $this->Acl->deny('Samir', 'refill', '*');
  340. $this->assertFalse($this->Acl->check('Samir', 'refill', 'create'));
  341. $this->assertFalse($this->Acl->check('Samir', 'refill', 'update'));
  342. $this->assertFalse($this->Acl->check('Samir', 'refill', 'read'));
  343. $this->assertFalse($this->Acl->check('Samir', 'refill', 'delete'));
  344. $result = $this->Acl->Aro->Permission->find('all', array('conditions' => array('AroTwoTest.alias' => 'Samir')));
  345. $expected = '-1';
  346. $this->assertEquals($expected, $result[0]['PermissionTwoTest']['_delete']);
  347. $this->assertFalse($this->Acl->deny('Lumbergh', 'ROOT/tpsReports/DoesNotExist', 'create'));
  348. }
  349. /**
  350. * testAclNodeLookup method
  351. *
  352. * @return void
  353. */
  354. public function testAclNodeLookup() {
  355. $result = $this->Acl->Aro->node('root/users/Samir');
  356. $expected = array(
  357. array('AroTwoTest' => array('id' => '7', 'parent_id' => '4', 'model' => 'User', 'foreign_key' => 3, 'alias' => 'Samir')),
  358. array('AroTwoTest' => array('id' => '4', 'parent_id' => '1', 'model' => 'Group', 'foreign_key' => 3, 'alias' => 'users')),
  359. array('AroTwoTest' => array('id' => '1', 'parent_id' => null, 'model' => null, 'foreign_key' => null, 'alias' => 'root'))
  360. );
  361. $this->assertEquals($expected, $result);
  362. $result = $this->Acl->Aco->node('ROOT/tpsReports/view/current');
  363. $expected = array(
  364. array('AcoTwoTest' => array('id' => '4', 'parent_id' => '3', 'model' => null, 'foreign_key' => null, 'alias' => 'current')),
  365. array('AcoTwoTest' => array('id' => '3', 'parent_id' => '2', 'model' => null, 'foreign_key' => null, 'alias' => 'view')),
  366. array('AcoTwoTest' => array('id' => '2', 'parent_id' => '1', 'model' => null, 'foreign_key' => null, 'alias' => 'tpsReports')),
  367. array('AcoTwoTest' => array('id' => '1', 'parent_id' => null, 'model' => null, 'foreign_key' => null, 'alias' => 'ROOT')),
  368. );
  369. $this->assertEquals($expected, $result);
  370. }
  371. /**
  372. * testDbInherit method
  373. *
  374. * @return void
  375. */
  376. public function testInherit() {
  377. //parent doesn't have access inherit should still deny
  378. $this->assertFalse($this->Acl->check('Milton', 'smash', 'delete'));
  379. $this->Acl->inherit('Milton', 'smash', 'delete');
  380. $this->assertFalse($this->Acl->check('Milton', 'smash', 'delete'));
  381. //inherit parent
  382. $this->assertFalse($this->Acl->check('Milton', 'smash', 'read'));
  383. $this->Acl->inherit('Milton', 'smash', 'read');
  384. $this->assertTrue($this->Acl->check('Milton', 'smash', 'read'));
  385. }
  386. /**
  387. * testDbGrant method
  388. *
  389. * @expectedException PHPUnit_Framework_Error_Warning
  390. * @return void
  391. */
  392. public function testGrant() {
  393. $this->assertFalse($this->Acl->check('Samir', 'tpsReports', 'create'));
  394. $this->Acl->allow('Samir', 'tpsReports', 'create');
  395. $this->assertTrue($this->Acl->check('Samir', 'tpsReports', 'create'));
  396. $this->assertFalse($this->Acl->check('Micheal', 'view', 'read'));
  397. $this->Acl->allow('Micheal', 'view', array('read', 'create', 'update'));
  398. $this->assertTrue($this->Acl->check('Micheal', 'view', 'read'));
  399. $this->assertTrue($this->Acl->check('Micheal', 'view', 'create'));
  400. $this->assertTrue($this->Acl->check('Micheal', 'view', 'update'));
  401. $this->assertFalse($this->Acl->check('Micheal', 'view', 'delete'));
  402. $this->assertFalse($this->Acl->allow('Peter', 'ROOT/tpsReports/DoesNotExist', 'create'));
  403. }
  404. /**
  405. * testDbRevoke method
  406. *
  407. * @expectedException PHPUnit_Framework_Error_Warning
  408. * @return void
  409. */
  410. public function testRevoke() {
  411. $this->assertTrue($this->Acl->check('Bobs', 'tpsReports', 'read'));
  412. $this->Acl->deny('Bobs', 'tpsReports', 'read');
  413. $this->assertFalse($this->Acl->check('Bobs', 'tpsReports', 'read'));
  414. $this->assertTrue($this->Acl->check('users', 'printers', 'read'));
  415. $this->Acl->deny('users', 'printers', 'read');
  416. $this->assertFalse($this->Acl->check('users', 'printers', 'read'));
  417. $this->assertFalse($this->Acl->check('Samir', 'printers', 'read'));
  418. $this->assertFalse($this->Acl->check('Peter', 'printers', 'read'));
  419. $this->Acl->deny('Bobs', 'ROOT/printers/DoesNotExist', 'create');
  420. }
  421. /**
  422. * debug function - to help editing/creating test cases for the ACL component
  423. *
  424. * To check the overall ACL status at any time call $this->_debug();
  425. * Generates a list of the current aro and aco structures and a grid dump of the permissions that are defined
  426. * Only designed to work with the db based ACL
  427. *
  428. * @param bool $treesToo
  429. * @return void
  430. */
  431. protected function _debug($printTreesToo = false) {
  432. $this->Acl->Aro->displayField = 'alias';
  433. $this->Acl->Aco->displayField = 'alias';
  434. $aros = $this->Acl->Aro->find('list', array('order' => 'lft'));
  435. $acos = $this->Acl->Aco->find('list', array('order' => 'lft'));
  436. $rights = array('*', 'create', 'read', 'update', 'delete');
  437. $permissions['Aros v Acos >'] = $acos;
  438. foreach ($aros as $aro) {
  439. $row = array();
  440. foreach ($acos as $aco) {
  441. $perms = '';
  442. foreach ($rights as $right) {
  443. if ($this->Acl->check($aro, $aco, $right)) {
  444. if ($right === '*') {
  445. $perms .= '****';
  446. break;
  447. }
  448. $perms .= $right[0];
  449. } elseif ($right !== '*') {
  450. $perms .= ' ';
  451. }
  452. }
  453. $row[] = $perms;
  454. }
  455. $permissions[$aro] = $row;
  456. }
  457. foreach ($permissions as $key => $values) {
  458. array_unshift($values, $key);
  459. $values = array_map(array(&$this, '_pad'), $values);
  460. $permissions[$key] = implode(' ', $values);
  461. }
  462. $permissions = array_map(array(&$this, '_pad'), $permissions);
  463. array_unshift($permissions, 'Current Permissions :');
  464. if ($printTreesToo) {
  465. debug(array('aros' => $this->Acl->Aro->generateTreeList(), 'acos' => $this->Acl->Aco->generateTreeList()));
  466. }
  467. debug(implode("\r\n", $permissions));
  468. }
  469. /**
  470. * pad function
  471. * Used by debug to format strings used in the data dump
  472. *
  473. * @param string $string
  474. * @param integer $len
  475. * @return void
  476. */
  477. protected function _pad($string = '', $len = 14) {
  478. return str_pad($string, $len);
  479. }
  480. }