AclTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Security\Acl\Tests\Domain;
  11. use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
  12. use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
  13. use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
  14. use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
  15. use Symfony\Component\Security\Acl\Domain\Acl;
  16. class AclTest extends \PHPUnit_Framework_TestCase
  17. {
  18. public function testConstructor()
  19. {
  20. $acl = new Acl(1, $oid = new ObjectIdentity('foo', 'foo'), $permissionStrategy = new PermissionGrantingStrategy(), array(), true);
  21. $this->assertSame(1, $acl->getId());
  22. $this->assertSame($oid, $acl->getObjectIdentity());
  23. $this->assertNull($acl->getParentAcl());
  24. $this->assertTrue($acl->isEntriesInheriting());
  25. }
  26. /**
  27. * @expectedException \OutOfBoundsException
  28. * @dataProvider getDeleteAceTests
  29. */
  30. public function testDeleteAceThrowsExceptionOnInvalidIndex($type)
  31. {
  32. $acl = $this->getAcl();
  33. $acl->{'delete'.$type.'Ace'}(0);
  34. }
  35. /**
  36. * @dataProvider getDeleteAceTests
  37. */
  38. public function testDeleteAce($type)
  39. {
  40. $acl = $this->getAcl();
  41. $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);
  42. $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 2, 1);
  43. $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 3, 2);
  44. $listener = $this->getListener(array(
  45. $type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces',
  46. ));
  47. $acl->addPropertyChangedListener($listener);
  48. $this->assertCount(3, $acl->{'get'.$type.'Aces'}());
  49. $acl->{'delete'.$type.'Ace'}(0);
  50. $this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}());
  51. $this->assertEquals(2, $aces[0]->getMask());
  52. $this->assertEquals(3, $aces[1]->getMask());
  53. $acl->{'delete'.$type.'Ace'}(1);
  54. $this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}());
  55. $this->assertEquals(2, $aces[0]->getMask());
  56. }
  57. public function getDeleteAceTests()
  58. {
  59. return array(
  60. array('class'),
  61. array('object'),
  62. );
  63. }
  64. /**
  65. * @expectedException \OutOfBoundsException
  66. * @dataProvider getDeleteFieldAceTests
  67. */
  68. public function testDeleteFieldAceThrowsExceptionOnInvalidIndex($type)
  69. {
  70. $acl = $this->getAcl();
  71. $acl->{'delete'.$type.'Ace'}('foo', 0);
  72. }
  73. /**
  74. * @dataProvider getDeleteFieldAceTests
  75. */
  76. public function testDeleteFieldAce($type)
  77. {
  78. $acl = $this->getAcl();
  79. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1, 0);
  80. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 2, 1);
  81. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 3, 2);
  82. $listener = $this->getListener(array(
  83. $type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces',
  84. ));
  85. $acl->addPropertyChangedListener($listener);
  86. $this->assertCount(3, $acl->{'get'.$type.'Aces'}('foo'));
  87. $acl->{'delete'.$type.'Ace'}(0, 'foo');
  88. $this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}('foo'));
  89. $this->assertEquals(2, $aces[0]->getMask());
  90. $this->assertEquals(3, $aces[1]->getMask());
  91. $acl->{'delete'.$type.'Ace'}(1, 'foo');
  92. $this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}('foo'));
  93. $this->assertEquals(2, $aces[0]->getMask());
  94. }
  95. public function getDeleteFieldAceTests()
  96. {
  97. return array(
  98. array('classField'),
  99. array('objectField'),
  100. );
  101. }
  102. /**
  103. * @dataProvider getInsertAceTests
  104. */
  105. public function testInsertAce($property, $method)
  106. {
  107. $acl = $this->getAcl();
  108. $listener = $this->getListener(array(
  109. $property, 'aceOrder', $property, 'aceOrder', $property,
  110. ));
  111. $acl->addPropertyChangedListener($listener);
  112. $sid = new RoleSecurityIdentity('foo');
  113. $acl->$method($sid, 1);
  114. $acl->$method($sid, 2);
  115. $acl->$method($sid, 3, 1, false);
  116. $this->assertCount(3, $aces = $acl->{'get'.$property}());
  117. $this->assertEquals(2, $aces[0]->getMask());
  118. $this->assertEquals(3, $aces[1]->getMask());
  119. $this->assertEquals(1, $aces[2]->getMask());
  120. }
  121. /**
  122. * @expectedException \OutOfBoundsException
  123. * @dataProvider getInsertAceTests
  124. */
  125. public function testInsertClassAceThrowsExceptionOnInvalidIndex($property, $method)
  126. {
  127. $acl = $this->getAcl();
  128. $acl->$method(new RoleSecurityIdentity('foo'), 1, 1);
  129. }
  130. public function getInsertAceTests()
  131. {
  132. return array(
  133. array('classAces', 'insertClassAce'),
  134. array('objectAces', 'insertObjectAce'),
  135. );
  136. }
  137. /**
  138. * @dataProvider getInsertFieldAceTests
  139. */
  140. public function testInsertClassFieldAce($property, $method)
  141. {
  142. $acl = $this->getAcl();
  143. $listener = $this->getListener(array(
  144. $property, $property, 'aceOrder', $property,
  145. 'aceOrder', 'aceOrder', $property,
  146. ));
  147. $acl->addPropertyChangedListener($listener);
  148. $sid = new RoleSecurityIdentity('foo');
  149. $acl->$method('foo', $sid, 1);
  150. $acl->$method('foo2', $sid, 1);
  151. $acl->$method('foo', $sid, 3);
  152. $acl->$method('foo', $sid, 2);
  153. $this->assertCount(3, $aces = $acl->{'get'.$property}('foo'));
  154. $this->assertCount(1, $acl->{'get'.$property}('foo2'));
  155. $this->assertEquals(2, $aces[0]->getMask());
  156. $this->assertEquals(3, $aces[1]->getMask());
  157. $this->assertEquals(1, $aces[2]->getMask());
  158. }
  159. /**
  160. * @expectedException \OutOfBoundsException
  161. * @dataProvider getInsertFieldAceTests
  162. */
  163. public function testInsertClassFieldAceThrowsExceptionOnInvalidIndex($property, $method)
  164. {
  165. $acl = $this->getAcl();
  166. $acl->$method('foo', new RoleSecurityIdentity('foo'), 1, 1);
  167. }
  168. public function getInsertFieldAceTests()
  169. {
  170. return array(
  171. array('classFieldAces', 'insertClassFieldAce'),
  172. array('objectFieldAces', 'insertObjectFieldAce'),
  173. );
  174. }
  175. public function testIsFieldGranted()
  176. {
  177. $sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD'));
  178. $masks = array(1, 2, 4);
  179. $strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface');
  180. $acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true);
  181. $strategy
  182. ->expects($this->once())
  183. ->method('isFieldGranted')
  184. ->with($this->equalTo($acl), $this->equalTo('foo'), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue())
  185. ->will($this->returnValue(true))
  186. ;
  187. $this->assertTrue($acl->isFieldGranted('foo', $masks, $sids, true));
  188. }
  189. public function testIsGranted()
  190. {
  191. $sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD'));
  192. $masks = array(1, 2, 4);
  193. $strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface');
  194. $acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true);
  195. $strategy
  196. ->expects($this->once())
  197. ->method('isGranted')
  198. ->with($this->equalTo($acl), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue())
  199. ->will($this->returnValue(true))
  200. ;
  201. $this->assertTrue($acl->isGranted($masks, $sids, true));
  202. }
  203. public function testSetGetParentAcl()
  204. {
  205. $acl = $this->getAcl();
  206. $parentAcl = $this->getAcl();
  207. $listener = $this->getListener(array('parentAcl'));
  208. $acl->addPropertyChangedListener($listener);
  209. $this->assertNull($acl->getParentAcl());
  210. $acl->setParentAcl($parentAcl);
  211. $this->assertSame($parentAcl, $acl->getParentAcl());
  212. $acl->setParentAcl(null);
  213. $this->assertNull($acl->getParentAcl());
  214. }
  215. public function testSetIsEntriesInheriting()
  216. {
  217. $acl = $this->getAcl();
  218. $listener = $this->getListener(array('entriesInheriting'));
  219. $acl->addPropertyChangedListener($listener);
  220. $this->assertTrue($acl->isEntriesInheriting());
  221. $acl->setEntriesInheriting(false);
  222. $this->assertFalse($acl->isEntriesInheriting());
  223. }
  224. public function testIsSidLoadedWhenAllSidsAreLoaded()
  225. {
  226. $acl = $this->getAcl();
  227. $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
  228. $this->assertTrue($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO', 'Foo')));
  229. }
  230. public function testIsSidLoaded()
  231. {
  232. $acl = new Acl(1, new ObjectIdentity('1', 'foo'), new PermissionGrantingStrategy(), array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar')), true);
  233. $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
  234. $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('johannes', 'Bar')));
  235. $this->assertTrue($acl->isSidLoaded(array(
  236. new UserSecurityIdentity('foo', 'Foo'),
  237. new UserSecurityIdentity('johannes', 'Bar'),
  238. )));
  239. $this->assertFalse($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO')));
  240. $this->assertFalse($acl->isSidLoaded(new UserSecurityIdentity('schmittjoh@gmail.com', 'Moo')));
  241. $this->assertFalse($acl->isSidLoaded(array(
  242. new UserSecurityIdentity('foo', 'Foo'),
  243. new UserSecurityIdentity('johannes', 'Bar'),
  244. new RoleSecurityIdentity('ROLE_FOO'),
  245. )));
  246. }
  247. /**
  248. * @dataProvider getUpdateAceTests
  249. * @expectedException \OutOfBoundsException
  250. */
  251. public function testUpdateAceThrowsOutOfBoundsExceptionOnInvalidIndex($type)
  252. {
  253. $acl = $this->getAcl();
  254. $acl->{'update'.$type}(0, 1);
  255. }
  256. /**
  257. * @dataProvider getUpdateAceTests
  258. */
  259. public function testUpdateAce($type)
  260. {
  261. $acl = $this->getAcl();
  262. $acl->{'insert'.$type}(new RoleSecurityIdentity('foo'), 1);
  263. $listener = $this->getListener(array(
  264. 'mask', 'mask', 'strategy',
  265. ));
  266. $acl->addPropertyChangedListener($listener);
  267. $aces = $acl->{'get'.$type.'s'}();
  268. $ace = reset($aces);
  269. $this->assertEquals(1, $ace->getMask());
  270. $this->assertEquals('all', $ace->getStrategy());
  271. $acl->{'update'.$type}(0, 3);
  272. $this->assertEquals(3, $ace->getMask());
  273. $this->assertEquals('all', $ace->getStrategy());
  274. $acl->{'update'.$type}(0, 1, 'foo');
  275. $this->assertEquals(1, $ace->getMask());
  276. $this->assertEquals('foo', $ace->getStrategy());
  277. }
  278. public function getUpdateAceTests()
  279. {
  280. return array(
  281. array('classAce'),
  282. array('objectAce'),
  283. );
  284. }
  285. /**
  286. * @dataProvider getUpdateFieldAceTests
  287. * @expectedException \OutOfBoundsException
  288. */
  289. public function testUpdateFieldAceThrowsExceptionOnInvalidIndex($type)
  290. {
  291. $acl = $this->getAcl();
  292. $acl->{'update'.$type}(0, 'foo', 1);
  293. }
  294. /**
  295. * @dataProvider getUpdateFieldAceTests
  296. */
  297. public function testUpdateFieldAce($type)
  298. {
  299. $acl = $this->getAcl();
  300. $acl->{'insert'.$type}('foo', new UserSecurityIdentity('foo', 'Foo'), 1);
  301. $listener = $this->getListener(array(
  302. 'mask', 'mask', 'strategy',
  303. ));
  304. $acl->addPropertyChangedListener($listener);
  305. $aces = $acl->{'get'.$type.'s'}('foo');
  306. $ace = reset($aces);
  307. $this->assertEquals(1, $ace->getMask());
  308. $this->assertEquals('all', $ace->getStrategy());
  309. $acl->{'update'.$type}(0, 'foo', 3);
  310. $this->assertEquals(3, $ace->getMask());
  311. $this->assertEquals('all', $ace->getStrategy());
  312. $acl->{'update'.$type}(0, 'foo', 1, 'foo');
  313. $this->assertEquals(1, $ace->getMask());
  314. $this->assertEquals('foo', $ace->getStrategy());
  315. }
  316. public function getUpdateFieldAceTests()
  317. {
  318. return array(
  319. array('classFieldAce'),
  320. array('objectFieldAce'),
  321. );
  322. }
  323. /**
  324. * @dataProvider getUpdateAuditingTests
  325. * @expectedException \OutOfBoundsException
  326. */
  327. public function testUpdateAuditingThrowsExceptionOnInvalidIndex($type)
  328. {
  329. $acl = $this->getAcl();
  330. $acl->{'update'.$type.'Auditing'}(0, true, false);
  331. }
  332. /**
  333. * @dataProvider getUpdateAuditingTests
  334. */
  335. public function testUpdateAuditing($type)
  336. {
  337. $acl = $this->getAcl();
  338. $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);
  339. $listener = $this->getListener(array(
  340. 'auditFailure', 'auditSuccess', 'auditFailure',
  341. ));
  342. $acl->addPropertyChangedListener($listener);
  343. $aces = $acl->{'get'.$type.'Aces'}();
  344. $ace = reset($aces);
  345. $this->assertFalse($ace->isAuditSuccess());
  346. $this->assertFalse($ace->isAuditFailure());
  347. $acl->{'update'.$type.'Auditing'}(0, false, true);
  348. $this->assertFalse($ace->isAuditSuccess());
  349. $this->assertTrue($ace->isAuditFailure());
  350. $acl->{'update'.$type.'Auditing'}(0, true, false);
  351. $this->assertTrue($ace->isAuditSuccess());
  352. $this->assertFalse($ace->isAuditFailure());
  353. }
  354. public function getUpdateAuditingTests()
  355. {
  356. return array(
  357. array('class'),
  358. array('object'),
  359. );
  360. }
  361. /**
  362. * @expectedException \InvalidArgumentException
  363. * @dataProvider getUpdateFieldAuditingTests
  364. */
  365. public function testUpdateFieldAuditingThrowsExceptionOnInvalidField($type)
  366. {
  367. $acl = $this->getAcl();
  368. $acl->{'update'.$type.'Auditing'}(0, 'foo', true, true);
  369. }
  370. /**
  371. * @expectedException \OutOfBoundsException
  372. * @dataProvider getUpdateFieldAuditingTests
  373. */
  374. public function testUpdateFieldAuditingThrowsExceptionOnInvalidIndex($type)
  375. {
  376. $acl = $this->getAcl();
  377. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
  378. $acl->{'update'.$type.'Auditing'}(1, 'foo', true, false);
  379. }
  380. /**
  381. * @dataProvider getUpdateFieldAuditingTests
  382. */
  383. public function testUpdateFieldAuditing($type)
  384. {
  385. $acl = $this->getAcl();
  386. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
  387. $listener = $this->getListener(array(
  388. 'auditSuccess', 'auditSuccess', 'auditFailure',
  389. ));
  390. $acl->addPropertyChangedListener($listener);
  391. $aces = $acl->{'get'.$type.'Aces'}('foo');
  392. $ace = reset($aces);
  393. $this->assertFalse($ace->isAuditSuccess());
  394. $this->assertFalse($ace->isAuditFailure());
  395. $acl->{'update'.$type.'Auditing'}(0, 'foo', true, false);
  396. $this->assertTrue($ace->isAuditSuccess());
  397. $this->assertFalse($ace->isAuditFailure());
  398. $acl->{'update'.$type.'Auditing'}(0, 'foo', false, true);
  399. $this->assertFalse($ace->isAuditSuccess());
  400. $this->assertTrue($ace->isAuditFailure());
  401. }
  402. public function getUpdateFieldAuditingTests()
  403. {
  404. return array(
  405. array('classField'),
  406. array('objectField'),
  407. );
  408. }
  409. protected function getListener($expectedChanges)
  410. {
  411. $aceProperties = array('aceOrder', 'mask', 'strategy', 'auditSuccess', 'auditFailure');
  412. $listener = $this->getMock('Doctrine\Common\PropertyChangedListener');
  413. foreach ($expectedChanges as $index => $property) {
  414. if (in_array($property, $aceProperties)) {
  415. $class = 'Symfony\Component\Security\Acl\Domain\Entry';
  416. } else {
  417. $class = 'Symfony\Component\Security\Acl\Domain\Acl';
  418. }
  419. $listener
  420. ->expects($this->at($index))
  421. ->method('propertyChanged')
  422. ->with($this->isInstanceOf($class), $this->equalTo($property))
  423. ;
  424. }
  425. return $listener;
  426. }
  427. protected function getAcl()
  428. {
  429. return new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), true);
  430. }
  431. }