AclVoterTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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\Voter;
  11. use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
  12. use Symfony\Component\Security\Acl\Voter\FieldVote;
  13. use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
  14. use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
  15. use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
  16. use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
  17. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  18. use Symfony\Component\Security\Acl\Voter\AclVoter;
  19. class AclVoterTest extends \PHPUnit_Framework_TestCase
  20. {
  21. /**
  22. * @dataProvider getSupportsAttributeTests
  23. */
  24. public function testSupportsAttribute($attribute, $supported)
  25. {
  26. list($voter, , $permissionMap) = $this->getVoter(true, false);
  27. $permissionMap
  28. ->expects($this->once())
  29. ->method('contains')
  30. ->with($this->identicalTo($attribute))
  31. ->will($this->returnValue($supported))
  32. ;
  33. $this->assertSame($supported, $voter->supportsAttribute($attribute));
  34. }
  35. /**
  36. * @dataProvider getSupportsAttributeNonStringTests
  37. */
  38. public function testSupportsAttributeNonString($attribute)
  39. {
  40. list($voter) = $this->getVoter(true, false);
  41. $this->assertFalse($voter->supportsAttribute($attribute));
  42. }
  43. public function getSupportsAttributeTests()
  44. {
  45. return array(
  46. array('foo', true),
  47. array('foo', false),
  48. );
  49. }
  50. public function getSupportsAttributeNonStringTests()
  51. {
  52. return array(
  53. array(new \stdClass()),
  54. array(1),
  55. array(true),
  56. array(array()),
  57. );
  58. }
  59. /**
  60. * @dataProvider getSupportsClassTests
  61. */
  62. public function testSupportsClass($class)
  63. {
  64. list($voter) = $this->getVoter();
  65. $this->assertTrue($voter->supportsClass($class));
  66. }
  67. public function getSupportsClassTests()
  68. {
  69. return array(
  70. array('foo'),
  71. array('bar'),
  72. array('moo'),
  73. );
  74. }
  75. public function testVote()
  76. {
  77. list($voter, , $permissionMap) = $this->getVoter();
  78. $permissionMap
  79. ->expects($this->atLeastOnce())
  80. ->method('getMasks')
  81. ->will($this->returnValue(null))
  82. ;
  83. $this->assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($this->getToken(), null, array('VIEW', 'EDIT', 'DELETE')));
  84. }
  85. /**
  86. * @dataProvider getTrueFalseTests
  87. */
  88. public function testVoteWhenNoObjectIsPassed($allowIfObjectIdentityUnavailable)
  89. {
  90. list($voter, , $permissionMap) = $this->getVoter($allowIfObjectIdentityUnavailable);
  91. $permissionMap
  92. ->expects($this->once())
  93. ->method('getMasks')
  94. ->will($this->returnValue(array()))
  95. ;
  96. if ($allowIfObjectIdentityUnavailable) {
  97. $vote = VoterInterface::ACCESS_GRANTED;
  98. } else {
  99. $vote = VoterInterface::ACCESS_ABSTAIN;
  100. }
  101. $this->assertSame($vote, $voter->vote($this->getToken(), null, array('VIEW')));
  102. }
  103. /**
  104. * @dataProvider getTrueFalseTests
  105. */
  106. public function testVoteWhenOidStrategyReturnsNull($allowIfUnavailable)
  107. {
  108. list($voter, , $permissionMap, $oidStrategy) = $this->getVoter($allowIfUnavailable);
  109. $permissionMap
  110. ->expects($this->once())
  111. ->method('getMasks')
  112. ->will($this->returnValue(array()))
  113. ;
  114. $oidStrategy
  115. ->expects($this->once())
  116. ->method('getObjectIdentity')
  117. ->will($this->returnValue(null))
  118. ;
  119. if ($allowIfUnavailable) {
  120. $vote = VoterInterface::ACCESS_GRANTED;
  121. } else {
  122. $vote = VoterInterface::ACCESS_ABSTAIN;
  123. }
  124. $this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
  125. }
  126. public function getTrueFalseTests()
  127. {
  128. return array(array(true), array(false));
  129. }
  130. public function testVoteNoAclFound()
  131. {
  132. list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
  133. $permissionMap
  134. ->expects($this->once())
  135. ->method('getMasks')
  136. ->will($this->returnValue(array()))
  137. ;
  138. $oidStrategy
  139. ->expects($this->once())
  140. ->method('getObjectIdentity')
  141. ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
  142. ;
  143. $sidStrategy
  144. ->expects($this->once())
  145. ->method('getSecurityIdentities')
  146. ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
  147. ;
  148. $provider
  149. ->expects($this->once())
  150. ->method('findAcl')
  151. ->with($this->equalTo($oid), $this->equalTo($sids))
  152. ->will($this->throwException(new AclNotFoundException('Not found.')))
  153. ;
  154. $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
  155. }
  156. /**
  157. * @dataProvider getTrueFalseTests
  158. */
  159. public function testVoteGrantsAccess($grant)
  160. {
  161. list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
  162. $permissionMap
  163. ->expects($this->once())
  164. ->method('getMasks')
  165. ->with($this->equalTo('VIEW'))
  166. ->will($this->returnValue($masks = array(1, 2, 3)))
  167. ;
  168. $oidStrategy
  169. ->expects($this->once())
  170. ->method('getObjectIdentity')
  171. ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
  172. ;
  173. $sidStrategy
  174. ->expects($this->once())
  175. ->method('getSecurityIdentities')
  176. ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
  177. ;
  178. $provider
  179. ->expects($this->once())
  180. ->method('findAcl')
  181. ->with($this->equalTo($oid), $this->equalTo($sids))
  182. ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
  183. ;
  184. $acl
  185. ->expects($this->once())
  186. ->method('isGranted')
  187. ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
  188. ->will($this->returnValue($grant))
  189. ;
  190. if ($grant) {
  191. $vote = VoterInterface::ACCESS_GRANTED;
  192. } else {
  193. $vote = VoterInterface::ACCESS_DENIED;
  194. }
  195. $this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
  196. }
  197. public function testVoteNoAceFound()
  198. {
  199. list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
  200. $permissionMap
  201. ->expects($this->once())
  202. ->method('getMasks')
  203. ->with($this->equalTo('VIEW'))
  204. ->will($this->returnValue($masks = array(1, 2, 3)))
  205. ;
  206. $oidStrategy
  207. ->expects($this->once())
  208. ->method('getObjectIdentity')
  209. ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
  210. ;
  211. $sidStrategy
  212. ->expects($this->once())
  213. ->method('getSecurityIdentities')
  214. ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
  215. ;
  216. $provider
  217. ->expects($this->once())
  218. ->method('findAcl')
  219. ->with($this->equalTo($oid), $this->equalTo($sids))
  220. ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
  221. ;
  222. $acl
  223. ->expects($this->once())
  224. ->method('isGranted')
  225. ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
  226. ->will($this->throwException(new NoAceFoundException('No ACE')))
  227. ;
  228. $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
  229. }
  230. /**
  231. * @dataProvider getTrueFalseTests
  232. */
  233. public function testVoteGrantsFieldAccess($grant)
  234. {
  235. list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
  236. $permissionMap
  237. ->expects($this->once())
  238. ->method('getMasks')
  239. ->with($this->equalTo('VIEW'))
  240. ->will($this->returnValue($masks = array(1, 2, 3)))
  241. ;
  242. $oidStrategy
  243. ->expects($this->once())
  244. ->method('getObjectIdentity')
  245. ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
  246. ;
  247. $sidStrategy
  248. ->expects($this->once())
  249. ->method('getSecurityIdentities')
  250. ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
  251. ;
  252. $provider
  253. ->expects($this->once())
  254. ->method('findAcl')
  255. ->with($this->equalTo($oid), $this->equalTo($sids))
  256. ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
  257. ;
  258. $acl
  259. ->expects($this->once())
  260. ->method('isFieldGranted')
  261. ->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
  262. ->will($this->returnValue($grant))
  263. ;
  264. if ($grant) {
  265. $vote = VoterInterface::ACCESS_GRANTED;
  266. } else {
  267. $vote = VoterInterface::ACCESS_DENIED;
  268. }
  269. $this->assertSame($vote, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW')));
  270. }
  271. public function testVoteNoFieldAceFound()
  272. {
  273. list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
  274. $permissionMap
  275. ->expects($this->once())
  276. ->method('getMasks')
  277. ->with($this->equalTo('VIEW'))
  278. ->will($this->returnValue($masks = array(1, 2, 3)))
  279. ;
  280. $oidStrategy
  281. ->expects($this->once())
  282. ->method('getObjectIdentity')
  283. ->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
  284. ;
  285. $sidStrategy
  286. ->expects($this->once())
  287. ->method('getSecurityIdentities')
  288. ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
  289. ;
  290. $provider
  291. ->expects($this->once())
  292. ->method('findAcl')
  293. ->with($this->equalTo($oid), $this->equalTo($sids))
  294. ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
  295. ;
  296. $acl
  297. ->expects($this->once())
  298. ->method('isFieldGranted')
  299. ->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
  300. ->will($this->throwException(new NoAceFoundException('No ACE')))
  301. ;
  302. $this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW')));
  303. }
  304. public function testWhenReceivingAnObjectIdentityInterfaceWeDontRetrieveANewObjectIdentity()
  305. {
  306. list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
  307. $oid = new ObjectIdentity('someID', 'someType');
  308. $permissionMap
  309. ->expects($this->once())
  310. ->method('getMasks')
  311. ->with($this->equalTo('VIEW'))
  312. ->will($this->returnValue($masks = array(1, 2, 3)))
  313. ;
  314. $oidStrategy
  315. ->expects($this->never())
  316. ->method('getObjectIdentity')
  317. ;
  318. $sidStrategy
  319. ->expects($this->once())
  320. ->method('getSecurityIdentities')
  321. ->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
  322. ;
  323. $provider
  324. ->expects($this->once())
  325. ->method('findAcl')
  326. ->with($this->equalTo($oid), $this->equalTo($sids))
  327. ->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
  328. ;
  329. $acl
  330. ->expects($this->once())
  331. ->method('isGranted')
  332. ->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
  333. ->will($this->throwException(new NoAceFoundException('No ACE')))
  334. ;
  335. $voter->vote($this->getToken(), $oid, array('VIEW'));
  336. }
  337. protected function getToken()
  338. {
  339. return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
  340. }
  341. protected function getVoter($allowIfObjectIdentityUnavailable = true, $alwaysContains = true)
  342. {
  343. $provider = $this->getMock('Symfony\Component\Security\Acl\Model\AclProviderInterface');
  344. $permissionMap = $this->getMock('Symfony\Component\Security\Acl\Permission\PermissionMapInterface');
  345. $oidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface');
  346. $sidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface');
  347. if ($alwaysContains) {
  348. $permissionMap
  349. ->expects($this->any())
  350. ->method('contains')
  351. ->will($this->returnValue(true));
  352. }
  353. return array(
  354. new AclVoter($provider, $oidStrategy, $sidStrategy, $permissionMap, null, $allowIfObjectIdentityUnavailable),
  355. $provider,
  356. $permissionMap,
  357. $oidStrategy,
  358. $sidStrategy,
  359. );
  360. }
  361. }