AclTest.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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\Tests\Component\Security\Acl\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->assertEquals(3, count($acl->{'get'.$type.'Aces'}()));
  49. $acl->{'delete'.$type.'Ace'}(0);
  50. $this->assertEquals(2, count($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->assertEquals(1, count($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->assertEquals(3, count($acl->{'get'.$type.'Aces'}('foo')));
  87. $acl->{'delete'.$type.'Ace'}(0, 'foo');
  88. $this->assertEquals(2, count($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->assertEquals(1, count($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->assertEquals(3, count($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->assertEquals(3, count($aces = $acl->{'get'.$property}('foo')));
  154. $this->assertEquals(1, count($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. }
  213. public function testSetIsEntriesInheriting()
  214. {
  215. $acl = $this->getAcl();
  216. $listener = $this->getListener(array('entriesInheriting'));
  217. $acl->addPropertyChangedListener($listener);
  218. $this->assertTrue($acl->isEntriesInheriting());
  219. $acl->setEntriesInheriting(false);
  220. $this->assertFalse($acl->isEntriesInheriting());
  221. }
  222. public function testIsSidLoadedWhenAllSidsAreLoaded()
  223. {
  224. $acl = $this->getAcl();
  225. $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
  226. $this->assertTrue($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO', 'Foo')));
  227. }
  228. public function testIsSidLoaded()
  229. {
  230. $acl = new Acl(1, new ObjectIdentity('1', 'foo'), new PermissionGrantingStrategy(), array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar')), true);
  231. $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
  232. $this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('johannes', 'Bar')));
  233. $this->assertTrue($acl->isSidLoaded(array(
  234. new UserSecurityIdentity('foo', 'Foo'),
  235. new UserSecurityIdentity('johannes', 'Bar'),
  236. )));
  237. $this->assertFalse($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO')));
  238. $this->assertFalse($acl->isSidLoaded(new UserSecurityIdentity('schmittjoh@gmail.com', 'Moo')));
  239. $this->assertFalse($acl->isSidLoaded(array(
  240. new UserSecurityIdentity('foo', 'Foo'),
  241. new UserSecurityIdentity('johannes', 'Bar'),
  242. new RoleSecurityIdentity('ROLE_FOO'),
  243. )));
  244. }
  245. /**
  246. * @dataProvider getUpdateAceTests
  247. * @expectedException \OutOfBoundsException
  248. */
  249. public function testUpdateAceThrowsOutOfBoundsExceptionOnInvalidIndex($type)
  250. {
  251. $acl = $this->getAcl();
  252. $acl->{'update'.$type}(0, 1);
  253. }
  254. /**
  255. * @dataProvider getUpdateAceTests
  256. */
  257. public function testUpdateAce($type)
  258. {
  259. $acl = $this->getAcl();
  260. $acl->{'insert'.$type}(new RoleSecurityIdentity('foo'), 1);
  261. $listener = $this->getListener(array(
  262. 'mask', 'mask', 'strategy',
  263. ));
  264. $acl->addPropertyChangedListener($listener);
  265. $aces = $acl->{'get'.$type.'s'}();
  266. $ace = reset($aces);
  267. $this->assertEquals(1, $ace->getMask());
  268. $this->assertEquals('all', $ace->getStrategy());
  269. $acl->{'update'.$type}(0, 3);
  270. $this->assertEquals(3, $ace->getMask());
  271. $this->assertEquals('all', $ace->getStrategy());
  272. $acl->{'update'.$type}(0, 1, 'foo');
  273. $this->assertEquals(1, $ace->getMask());
  274. $this->assertEquals('foo', $ace->getStrategy());
  275. }
  276. public function getUpdateAceTests()
  277. {
  278. return array(
  279. array('classAce'),
  280. array('objectAce'),
  281. );
  282. }
  283. /**
  284. * @dataProvider getUpdateFieldAceTests
  285. * @expectedException \OutOfBoundsException
  286. */
  287. public function testUpdateFieldAceThrowsExceptionOnInvalidIndex($type)
  288. {
  289. $acl = $this->getAcl();
  290. $acl->{'update'.$type}(0, 'foo', 1);
  291. }
  292. /**
  293. * @dataProvider getUpdateFieldAceTests
  294. */
  295. public function testUpdateFieldAce($type)
  296. {
  297. $acl = $this->getAcl();
  298. $acl->{'insert'.$type}('foo', new UserSecurityIdentity('foo', 'Foo'), 1);
  299. $listener = $this->getListener(array(
  300. 'mask', 'mask', 'strategy'
  301. ));
  302. $acl->addPropertyChangedListener($listener);
  303. $aces = $acl->{'get'.$type.'s'}('foo');
  304. $ace = reset($aces);
  305. $this->assertEquals(1, $ace->getMask());
  306. $this->assertEquals('all', $ace->getStrategy());
  307. $acl->{'update'.$type}(0, 'foo', 3);
  308. $this->assertEquals(3, $ace->getMask());
  309. $this->assertEquals('all', $ace->getStrategy());
  310. $acl->{'update'.$type}(0, 'foo', 1, 'foo');
  311. $this->assertEquals(1, $ace->getMask());
  312. $this->assertEquals('foo', $ace->getStrategy());
  313. }
  314. public function getUpdateFieldAceTests()
  315. {
  316. return array(
  317. array('classFieldAce'),
  318. array('objectFieldAce'),
  319. );
  320. }
  321. /**
  322. * @dataProvider getUpdateAuditingTests
  323. * @expectedException \OutOfBoundsException
  324. */
  325. public function testUpdateAuditingThrowsExceptionOnInvalidIndex($type)
  326. {
  327. $acl = $this->getAcl();
  328. $acl->{'update'.$type.'Auditing'}(0, true, false);
  329. }
  330. /**
  331. * @dataProvider getUpdateAuditingTests
  332. */
  333. public function testUpdateAuditing($type)
  334. {
  335. $acl = $this->getAcl();
  336. $acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);
  337. $listener = $this->getListener(array(
  338. 'auditFailure', 'auditSuccess', 'auditFailure',
  339. ));
  340. $acl->addPropertyChangedListener($listener);
  341. $aces = $acl->{'get'.$type.'Aces'}();
  342. $ace = reset($aces);
  343. $this->assertFalse($ace->isAuditSuccess());
  344. $this->assertFalse($ace->isAuditFailure());
  345. $acl->{'update'.$type.'Auditing'}(0, false, true);
  346. $this->assertFalse($ace->isAuditSuccess());
  347. $this->assertTrue($ace->isAuditFailure());
  348. $acl->{'update'.$type.'Auditing'}(0, true, false);
  349. $this->assertTrue($ace->isAuditSuccess());
  350. $this->assertFalse($ace->isAuditFailure());
  351. }
  352. public function getUpdateAuditingTests()
  353. {
  354. return array(
  355. array('class'),
  356. array('object'),
  357. );
  358. }
  359. /**
  360. * @expectedException \InvalidArgumentException
  361. * @dataProvider getUpdateFieldAuditingTests
  362. */
  363. public function testUpdateFieldAuditingthrowsExceptionOnInvalidField($type)
  364. {
  365. $acl = $this->getAcl();
  366. $acl->{'update'.$type.'Auditing'}(0, 'foo', true, true);
  367. }
  368. /**
  369. * @expectedException \OutOfBoundsException
  370. * @dataProvider getUpdateFieldAuditingTests
  371. */
  372. public function testUpdateFieldAuditingThrowsExceptionOnInvalidIndex($type)
  373. {
  374. $acl = $this->getAcl();
  375. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
  376. $acl->{'update'.$type.'Auditing'}(1, 'foo', true, false);
  377. }
  378. /**
  379. * @dataProvider getUpdateFieldAuditingTests
  380. */
  381. public function testUpdateFieldAuditing($type)
  382. {
  383. $acl = $this->getAcl();
  384. $acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
  385. $listener = $this->getListener(array(
  386. 'auditSuccess', 'auditSuccess', 'auditFailure',
  387. ));
  388. $acl->addPropertyChangedListener($listener);
  389. $aces = $acl->{'get'.$type.'Aces'}('foo');
  390. $ace = reset($aces);
  391. $this->assertFalse($ace->isAuditSuccess());
  392. $this->assertFalse($ace->isAuditFailure());
  393. $acl->{'update'.$type.'Auditing'}(0, 'foo', true, false);
  394. $this->assertTrue($ace->isAuditSuccess());
  395. $this->assertFalse($ace->isAuditFailure());
  396. $acl->{'update'.$type.'Auditing'}(0, 'foo', false, true);
  397. $this->assertFalse($ace->isAuditSuccess());
  398. $this->assertTrue($ace->isAuditFailure());
  399. }
  400. public function getUpdateFieldAuditingTests()
  401. {
  402. return array(
  403. array('classField'),
  404. array('objectField'),
  405. );
  406. }
  407. protected function getListener($expectedChanges)
  408. {
  409. $aceProperties = array('aceOrder', 'mask', 'strategy', 'auditSuccess', 'auditFailure');
  410. $listener = $this->getMock('Doctrine\Common\PropertyChangedListener');
  411. foreach ($expectedChanges as $index => $property) {
  412. if (in_array($property, $aceProperties)) {
  413. $class = 'Symfony\Component\Security\Acl\Domain\Entry';
  414. } else {
  415. $class = 'Symfony\Component\Security\Acl\Domain\Acl';
  416. }
  417. $listener
  418. ->expects($this->at($index))
  419. ->method('propertyChanged')
  420. ->with($this->isInstanceOf($class), $this->equalTo($property))
  421. ;
  422. }
  423. return $listener;
  424. }
  425. protected function getAcl()
  426. {
  427. return new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), true);
  428. }
  429. public function setUp()
  430. {
  431. if (!class_exists('Doctrine\DBAL\DriverManager')) {
  432. $this->markTestSkipped('The Doctrine2 DBAL is required for this test');
  433. }
  434. }
  435. }