PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Tests/Unit/Security/Aspect/PersistenceQueryRewritingAspectTest.php

https://github.com/christianjul/FLOW3-Composer
PHP | 746 lines | 506 code | 146 blank | 94 comment | 0 complexity | 7a756b68c9e57935316de1f3b093b447 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. <?php
  2. namespace TYPO3\FLOW3\Tests\Unit\Security\Aspect;
  3. /* *
  4. * This script belongs to the FLOW3 framework. *
  5. * *
  6. * It is free software; you can redistribute it and/or modify it under *
  7. * the terms of the GNU Lesser General Public License, either version 3 *
  8. * of the License, or (at your option) any later version. *
  9. * *
  10. * The TYPO3 project - inspiring people to share! *
  11. * */
  12. /**
  13. * Testcase for the persistence query rewriting aspect
  14. *
  15. * @covers TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect
  16. */
  17. class PersistenceQueryRewritingAspectTest extends \TYPO3\FLOW3\Tests\UnitTestCase {
  18. /**
  19. * @test
  20. */
  21. public function rewriteQomQueryAddsTheConstraintsGivenByThePolicyServiceCorrectlyToTheQueryObject() {
  22. $entityType = 'MyClass';
  23. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  24. $mockQuery->expects($this->atLeastOnce())->method('getConstraint')->will($this->returnValue('existingConstraint'));
  25. $mockQuery->expects($this->once())->method('getType')->will($this->returnValue($entityType));
  26. $mockQuery->expects($this->once())->method('logicalAnd')->with('existingConstraint', 'newConstraints')->will($this->returnValue('mergedResultConstraints'));
  27. $mockQuery->expects($this->once())->method('matching')->with('mergedResultConstraints');
  28. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  29. $mockAdviceChain->expects($this->any())->method('proceed');
  30. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface', array(), array(), '', FALSE);
  31. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  32. $mockJoinPoint->expects($this->once())->method('getProxy')->will($this->returnValue($mockQuery));
  33. $roles = array('role1', 'role2');
  34. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  35. $mockSecurityContext->expects($this->once())->method('getRoles')->will($this->returnValue($roles));
  36. $mockSecurityContext->expects($this->any())->method('isInitialized')->will($this->returnValue(TRUE));
  37. $mockPolicyService = $this->getMock('TYPO3\FLOW3\Security\Policy\PolicyService', array(), array(), '', FALSE);
  38. $mockPolicyService->expects($this->once())->method('getResourcesConstraintsForEntityTypeAndRoles')->with($entityType, $roles)->will($this->returnValue(array('parsedConstraints')));
  39. $mockPolicyService->expects($this->once())->method('hasPolicyEntryForEntityType')->with($entityType)->will($this->returnValue(TRUE));
  40. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getQomConstraintForConstraintDefinitions'), array(), '', FALSE);
  41. $rewritingAspect->expects($this->once())->method('getQomConstraintForConstraintDefinitions')->with(array('parsedConstraints'), $mockQuery)->will($this->returnValue('newConstraints'));
  42. $rewritingAspect->_set('policyService', $mockPolicyService);
  43. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  44. $rewritingAspect->_set('alreadyRewrittenQueries', new \SplObjectStorage());
  45. $rewritingAspect->rewriteQomQuery($mockJoinPoint);
  46. }
  47. /**
  48. * @test
  49. */
  50. public function rewriteQomQueryUsesTheConstraintsGivenByThePolicyServiceInTheQueryObject() {
  51. $entityType = 'MyClass';
  52. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  53. $mockQuery->expects($this->atLeastOnce())->method('getConstraint')->will($this->returnValue(NULL));
  54. $mockQuery->expects($this->once())->method('getType')->will($this->returnValue($entityType));
  55. $mockQuery->expects($this->never())->method('logicalAnd');
  56. $mockQuery->expects($this->once())->method('matching')->with('newConstraints');
  57. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  58. $mockAdviceChain->expects($this->any())->method('proceed');
  59. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface', array(), array(), '', FALSE);
  60. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  61. $mockJoinPoint->expects($this->once())->method('getProxy')->will($this->returnValue($mockQuery));
  62. $roles = array('role1', 'role2');
  63. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  64. $mockSecurityContext->expects($this->once())->method('getRoles')->will($this->returnValue($roles));
  65. $mockSecurityContext->expects($this->any())->method('isInitialized')->will($this->returnValue(TRUE));
  66. $mockPolicyService = $this->getMock('TYPO3\FLOW3\Security\Policy\PolicyService', array(), array(), '', FALSE);
  67. $mockPolicyService->expects($this->once())->method('getResourcesConstraintsForEntityTypeAndRoles')->with($entityType, $roles)->will($this->returnValue(array('parsedConstraints')));
  68. $mockPolicyService->expects($this->once())->method('hasPolicyEntryForEntityType')->with($entityType)->will($this->returnValue(TRUE));
  69. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getQomConstraintForConstraintDefinitions'), array(), '', FALSE);
  70. $rewritingAspect->expects($this->once())->method('getQomConstraintForConstraintDefinitions')->with(array('parsedConstraints'), $mockQuery)->will($this->returnValue('newConstraints'));
  71. $rewritingAspect->_set('policyService', $mockPolicyService);
  72. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  73. $rewritingAspect->_set('alreadyRewrittenQueries', new \SplObjectStorage());
  74. $rewritingAspect->rewriteQomQuery($mockJoinPoint);
  75. }
  76. /**
  77. * @test
  78. */
  79. public function rewriteQomQueryDoesNotChangeTheOriginalQueryConstraintsIfThereIsAPolicyEntryButNoAdditionalConstraintsAreNeededInTheCurrentSituation() {
  80. $entityType = 'MyClass';
  81. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  82. $mockQuery->expects($this->once())->method('getType')->will($this->returnValue($entityType));
  83. $mockQuery->expects($this->never())->method('matching');
  84. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  85. $mockAdviceChain->expects($this->any())->method('proceed');
  86. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface', array(), array(), '', FALSE);
  87. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  88. $mockJoinPoint->expects($this->once())->method('getProxy')->will($this->returnValue($mockQuery));
  89. $roles = array('role1', 'role2');
  90. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  91. $mockSecurityContext->expects($this->once())->method('getRoles')->will($this->returnValue($roles));
  92. $mockSecurityContext->expects($this->any())->method('isInitialized')->will($this->returnValue(TRUE));
  93. $mockPolicyService = $this->getMock('TYPO3\FLOW3\Security\Policy\PolicyService', array(), array(), '', FALSE);
  94. $mockPolicyService->expects($this->once())->method('getResourcesConstraintsForEntityTypeAndRoles')->with($entityType, $roles)->will($this->returnValue(array('parsedConstraints')));
  95. $mockPolicyService->expects($this->once())->method('hasPolicyEntryForEntityType')->with($entityType)->will($this->returnValue(TRUE));
  96. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getQomConstraintForConstraintDefinitions'), array(), '', FALSE);
  97. $rewritingAspect->expects($this->once())->method('getQomConstraintForConstraintDefinitions')->with(array('parsedConstraints'), $mockQuery)->will($this->returnValue(NULL));
  98. $rewritingAspect->_set('policyService', $mockPolicyService);
  99. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  100. $rewritingAspect->_set('alreadyRewrittenQueries', new \SplObjectStorage());
  101. $rewritingAspect->rewriteQomQuery($mockJoinPoint);
  102. }
  103. /**
  104. * @test
  105. */
  106. public function rewriteQomQueryDoesNotRewriteQueryIfSecurityContextIsNotInitialized() {
  107. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  108. $mockAdviceChain->expects($this->any())->method('proceed');
  109. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface', array(), array(), '', FALSE);
  110. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  111. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  112. $mockSecurityContext->expects($this->once())->method('isInitialized')->will($this->returnValue(FALSE));
  113. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  114. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  115. $rewritingAspect->_set('alreadyRewrittenQueries', new \SplObjectStorage());
  116. $rewritingAspect->rewriteQomQuery($mockJoinPoint);
  117. }
  118. /**
  119. * @test
  120. */
  121. public function aQomQueryIsNotRewrittenIfThereIsNoPolicyEntryForItsEntityType() {
  122. $entityType = 'MyClass';
  123. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  124. $mockSecurityContext->expects($this->once())->method('isInitialized')->will($this->returnValue(TRUE));
  125. $mockSecurityContext->expects($this->once())->method('getRoles')->will($this->returnValue(array()));
  126. $mockPolicyService = $this->getMock('TYPO3\FLOW3\Security\Policy\PolicyService', array(), array(), '', FALSE);
  127. $mockPolicyService->expects($this->once())->method('hasPolicyEntryForEntityType')->with($entityType)->will($this->returnValue(FALSE));
  128. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  129. $mockQuery->expects($this->once())->method('getType')->will($this->returnValue($entityType));
  130. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  131. $mockAdviceChain->expects($this->any())->method('proceed');
  132. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface', array(), array(), '', FALSE);
  133. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  134. $mockJoinPoint->expects($this->once())->method('getProxy')->will($this->returnValue($mockQuery));
  135. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  136. $rewritingAspect->_set('policyService', $mockPolicyService);
  137. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  138. $rewritingAspect->_set('alreadyRewrittenQueries', new \SplObjectStorage());
  139. $rewritingAspect->rewriteQomQuery($mockJoinPoint);
  140. }
  141. /**
  142. * @test
  143. * @expectedException \TYPO3\FLOW3\Security\Exception\InvalidQueryRewritingConstraintException
  144. */
  145. public function getQomConstraintForSingleConstraintDefinitionThrowsAnExceptionIfAConstraintHasNoReferenceToTheCurrentObjectIndicatedByTheThisKeyword() {
  146. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  147. $constraint = array(
  148. 'operator' => '==',
  149. 'leftValue' => 'current.party',
  150. 'rightValue' => 'current.some.other.object'
  151. );
  152. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  153. $rewritingAspect->_call('getQomConstraintForSingleConstraintDefinition', $constraint, $mockQuery);
  154. }
  155. /**
  156. * @test
  157. */
  158. public function getQomConstraintFoSingleConstraintDefinitionBuildsTheCorrectConstraintObjectForAnEqualityOperatorComparingASimpleValue() {
  159. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  160. $mockQuery->expects($this->once())->method('equals')->with('party', 'Andi')->will($this->returnValue('resultQomConstraint'));
  161. $constraint = array(
  162. 'operator' => '==',
  163. 'leftValue' => '"Andi"',
  164. 'rightValue' => 'this.party'
  165. );
  166. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForGlobalObject'), array(), '', FALSE);
  167. $resultConstraint = $rewritingAspect->_call('getQomConstraintForSingleConstraintDefinition', $constraint, $mockQuery);
  168. $this->assertEquals('resultQomConstraint', $resultConstraint);
  169. }
  170. /**
  171. * @test
  172. */
  173. public function getQomConstraintForSingleConstraintDefinitionBuildsTheCorrectConstraintObjectForAnEqualityOperatorAccessingAGlobalObject() {
  174. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  175. $mockQuery->expects($this->once())->method('equals')->with('party', 'globalParty')->will($this->returnValue('resultQomConstraint'));
  176. $constraint = array(
  177. 'operator' => '==',
  178. 'leftValue' => 'current.party',
  179. 'rightValue' => 'this.party'
  180. );
  181. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand'), array(), '', FALSE);
  182. $rewritingAspect->expects($this->once())->method('getValueForOperand')->with('current.party')->will($this->returnValue('globalParty'));
  183. $resultConstraint = $rewritingAspect->_call('getQomConstraintForSingleConstraintDefinition', $constraint, $mockQuery);
  184. $this->assertEquals('resultQomConstraint', $resultConstraint);
  185. }
  186. /**
  187. * @test
  188. */
  189. public function getQomConstraintForSingleConstraintDefinitionBuildsTheCorrectConstraintObjectForTheInOperator() {
  190. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  191. $mockQuery->expects($this->once())->method('in')->with('party', 'globalParty')->will($this->returnValue('resultQomConstraint'));
  192. $constraint = array(
  193. 'operator' => 'in',
  194. 'leftValue' => 'current.party',
  195. 'rightValue' => 'this.party'
  196. );
  197. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand'), array(), '', FALSE);
  198. $rewritingAspect->expects($this->once())->method('getValueForOperand')->with('current.party')->will($this->returnValue('globalParty'));
  199. $resultConstraint = $rewritingAspect->_call('getQomConstraintForSingleConstraintDefinition', $constraint, $mockQuery);
  200. $this->assertEquals('resultQomConstraint', $resultConstraint);
  201. }
  202. /**
  203. * @test
  204. */
  205. public function getQomConstraintForSingleConstraintDefinitionBuildsTheCorrectConstraintObjectForTheContainsOperator() {
  206. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  207. $mockQuery->expects($this->once())->method('contains')->with('party', 'globalParty')->will($this->returnValue('resultQomConstraint'));
  208. $constraint = array(
  209. 'operator' => 'contains',
  210. 'leftValue' => 'current.party',
  211. 'rightValue' => 'this.party'
  212. );
  213. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand'), array(), '', FALSE);
  214. $rewritingAspect->expects($this->once())->method('getValueForOperand')->with('current.party')->will($this->returnValue('globalParty'));
  215. $resultConstraint = $rewritingAspect->_call('getQomConstraintForSingleConstraintDefinition', $constraint, $mockQuery);
  216. $this->assertEquals('resultQomConstraint', $resultConstraint);
  217. }
  218. /**
  219. * @test
  220. */
  221. public function getQomConstraintForSingleConstraintDefinitionBuildsTheCorrectConstraintObjectForTheMatchesOperator() {
  222. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  223. $mockQuery->expects($this->at(0))->method('contains')->with('accounts', 1)->will($this->returnValue('constraint1'));
  224. $mockQuery->expects($this->at(1))->method('contains')->with('accounts', 'two')->will($this->returnValue('constraint2'));
  225. $mockQuery->expects($this->at(2))->method('logicalAnd')->with('constraint2', 'constraint1')->will($this->returnValue('compositeConstraint1'));
  226. $mockQuery->expects($this->at(3))->method('contains')->with('accounts', 3)->will($this->returnValue('constraint3'));
  227. $mockQuery->expects($this->at(4))->method('logicalAnd')->with('constraint3', 'compositeConstraint1')->will($this->returnValue('compositeConstraint2'));
  228. $constraint = array(
  229. 'operator' => 'matches',
  230. 'leftValue' => array(1, '"two"', 3),
  231. 'rightValue' => 'this.accounts'
  232. );
  233. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand'), array(), '', FALSE);
  234. $rewritingAspect->expects($this->once())->method('getValueForOperand')->with(array(1, '"two"', 3))->will($this->returnValue(array(1, 'two', 3)));
  235. $resultConstraint = $rewritingAspect->_call('getQomConstraintForSingleConstraintDefinition', $constraint, $mockQuery);
  236. $this->assertEquals('compositeConstraint2', $resultConstraint);
  237. }
  238. /**
  239. * @test
  240. */
  241. public function getValueForOperandReturnsTheCorrectValueForSimpleValues() {
  242. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  243. $operandValues = array(
  244. '"Andi"' => 'Andi',
  245. '\'Andi\'' => 'Andi',
  246. 1 => 1,
  247. 'TRUE' => TRUE,
  248. 'FALSE' => FALSE,
  249. 'NULL' => NULL
  250. );
  251. foreach ($operandValues as $operand => $expectedResult) {
  252. $result = $rewritingAspect->_call('getValueForOperand', $operand);
  253. $this->assertEquals($result, $expectedResult, 'The wrong value has been returned!');
  254. }
  255. }
  256. /**
  257. * @test
  258. */
  259. public function getValueForOperandReturnsTheCorrectValueFromGlobalObjects() {
  260. $className = 'dummyParty' . md5(uniqid(mt_rand(), TRUE));
  261. eval('class ' . $className . ' {
  262. protected $name = "Andi";
  263. public function getName() {
  264. return $this->name;
  265. }
  266. }
  267. ');
  268. $globalObject = new $className();
  269. $settings = array(
  270. 'aop' => array(
  271. 'globalObjects' => array(
  272. 'party' => $className
  273. )
  274. )
  275. );
  276. $mockObjectManager = $this->getMock('TYPO3\FLOW3\Object\ObjectManagerInterface', array(), array(), '', FALSE);
  277. $mockObjectManager->expects($this->any())->method('get')->with($className)->will($this->returnValue($globalObject));
  278. $mockPersistenceManager = $this->getMock('TYPO3\FLOW3\Persistence\PersistenceManagerInterface', array(), array(), '', FALSE);
  279. $mockPersistenceManager->expects($this->any())->method('isNewObject')->will($this->returnValue(FALSE));
  280. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  281. $rewritingAspect->_set('persistenceManager', $mockPersistenceManager);
  282. $rewritingAspect->_set('objectManager', $mockObjectManager);
  283. $rewritingAspect->injectSettings($settings);
  284. $operand = 'current.party.name';
  285. $result = $rewritingAspect->_call('getValueForOperand', $operand);
  286. $this->assertEquals($result, 'Andi', 'The wrong value has been returned!');
  287. }
  288. /**
  289. * @test
  290. */
  291. public function getValueForOperandReturnsTheCorrectValueForArrayOperands() {
  292. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  293. $operand = array(1, '"Andi"', 3, '\'Andi\'');
  294. $result = $rewritingAspect->_call('getValueForOperand', $operand);
  295. $expectedResult = array(1, 'Andi', 3, 'Andi');
  296. $this->assertEquals($result, $expectedResult, 'The wrong value has been returned!');
  297. }
  298. /**
  299. * @test
  300. */
  301. public function checkAccessAfterFetchingAnObjectByIdentifierChecksTheConstraintsGivenByThePolicyServiceForTheReturnedObject() {
  302. $entityClassName = 'entityClass' . md5(uniqid(mt_rand(), TRUE));
  303. eval('class ' . $entityClassName . ' implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface {
  304. public function FLOW3_Aop_Proxy_invokeJoinPoint(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) {}
  305. public function __clone() {}
  306. public function __wakeup() {}
  307. }');
  308. $result = new $entityClassName();
  309. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  310. $mockAdviceChain->expects($this->any())->method('proceed')->will($this->returnValue($result));
  311. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface');
  312. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  313. $roles = array('role1', 'role2');
  314. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  315. $mockSecurityContext->expects($this->any())->method('getRoles')->will($this->returnValue($roles));
  316. $mockSecurityContext->expects($this->any())->method('isInitialized')->will($this->returnValue(TRUE));
  317. $mockPolicyService = $this->getMock('TYPO3\FLOW3\Security\Policy\PolicyService', array(), array(), '', FALSE);
  318. $mockPolicyService->expects($this->any())->method('getResourcesConstraintsForEntityTypeAndRoles')->with($entityClassName, $roles)->will($this->returnValue(array('parsedConstraints')));
  319. $mockPolicyService->expects($this->any())->method('hasPolicyEntryForEntityType')->with($entityClassName)->will($this->returnValue(TRUE));
  320. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('checkConstraintDefinitionsOnResultObject'), array(), '', FALSE);
  321. $rewritingAspect->expects($this->at(0))->method('checkConstraintDefinitionsOnResultObject')->with(array('parsedConstraints'), $result)->will($this->returnValue(TRUE));
  322. $rewritingAspect->expects($this->at(1))->method('checkConstraintDefinitionsOnResultObject')->with(array('parsedConstraints'), $result)->will($this->returnValue(FALSE));
  323. $rewritingAspect->_set('policyService', $mockPolicyService);
  324. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  325. $this->assertEquals($result, $rewritingAspect->checkAccessAfterFetchingAnObjectByIdentifier($mockJoinPoint));
  326. $this->assertEquals(NULL, $rewritingAspect->checkAccessAfterFetchingAnObjectByIdentifier($mockJoinPoint));
  327. }
  328. /**
  329. * @test
  330. */
  331. public function checkAccessAfterFetchingAnObjectByIdentifierFetchesTheSecurityContextOnTheFirstCallToBeSureTheSessionHasAlreadyBeenInitializedWhenTheContextIsBuilt() {
  332. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  333. $mockQuery->expects($this->any())->method('getType')->will($this->returnValue('MyClass'));
  334. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  335. $mockAdviceChain->expects($this->any())->method('proceed')->will($this->returnValue(NULL));
  336. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface');
  337. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  338. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  339. $mockSecurityContext->expects($this->any())->method('getRoles')->will($this->returnValue(array()));
  340. $mockPolicyService = $this->getMock('TYPO3\FLOW3\Security\Policy\PolicyService', array(), array(), '', FALSE);
  341. $mockPolicyService->expects($this->once())->method('hasPolicyEntryForEntityType')->will($this->returnValue(FALSE));
  342. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  343. $rewritingAspect->_set('policyService', $mockPolicyService);
  344. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  345. $rewritingAspect->checkAccessAfterFetchingAnObjectByIdentifier($mockJoinPoint);
  346. }
  347. /**
  348. * @test
  349. */
  350. public function checkAccessAfterFetchingAnObjectByIdentifierReturnsObjectIfSecurityContextIsNotInitialized() {
  351. $mockQuery = $this->getMock('TYPO3\FLOW3\Persistence\QueryInterface');
  352. $mockQuery->expects($this->any())->method('getType')->will($this->returnValue('MyClass'));
  353. $mockAdviceChain = $this->getMock('TYPO3\FLOW3\Aop\Advice\AdviceChain', array(), array(), '', FALSE);
  354. $mockAdviceChain->expects($this->any())->method('proceed')->will($this->returnValue(NULL));
  355. $mockJoinPoint = $this->getMock('TYPO3\FLOW3\Aop\JoinPointInterface');
  356. $mockJoinPoint->expects($this->any())->method('getAdviceChain')->will($this->returnValue($mockAdviceChain));
  357. $mockSecurityContext = $this->getMock('TYPO3\FLOW3\Security\Context', array(), array(), '', FALSE);
  358. $mockSecurityContext->expects($this->once())->method('isInitialized')->will($this->returnValue(FALSE));
  359. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  360. $rewritingAspect->_set('securityContext', $mockSecurityContext);
  361. $rewritingAspect->checkAccessAfterFetchingAnObjectByIdentifier($mockJoinPoint);
  362. }
  363. /**
  364. * @test
  365. */
  366. public function checkConstraintDefinitionsOnResultObjectBasicallyWorks() {
  367. $parsedConstraints = array(
  368. 'resource' => array(
  369. '&&' => array(
  370. array('firstConstraint'),
  371. 'subConstraints' => array(
  372. '&&' => array(
  373. array('thirdConstraint')
  374. )
  375. ),
  376. array('fourthConstraint')
  377. ),
  378. '||' => array(
  379. array('secondConstraint')
  380. ),
  381. '&&!' => array(
  382. array('fifthConstraint')
  383. ),
  384. '||!' => array(
  385. array('sixthConstraint')
  386. )
  387. )
  388. );
  389. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('checkSingleConstraintDefinitionOnResultObject'), array(), '', FALSE);
  390. $rewritingAspect->expects($this->at(0))->method('checkSingleConstraintDefinitionOnResultObject')->with(array('firstConstraint'), array())->will($this->returnValue(FALSE));
  391. $rewritingAspect->expects($this->at(1))->method('checkSingleConstraintDefinitionOnResultObject')->with(array('thirdConstraint'), array())->will($this->returnValue(FALSE));
  392. $rewritingAspect->expects($this->at(2))->method('checkSingleConstraintDefinitionOnResultObject')->with(array('fourthConstraint'), array())->will($this->returnValue(TRUE));
  393. $rewritingAspect->expects($this->at(3))->method('checkSingleConstraintDefinitionOnResultObject')->with(array('secondConstraint'), array())->will($this->returnValue(TRUE));
  394. $rewritingAspect->expects($this->at(4))->method('checkSingleConstraintDefinitionOnResultObject')->with(array('fifthConstraint'), array())->will($this->returnValue(FALSE));
  395. $rewritingAspect->expects($this->at(5))->method('checkSingleConstraintDefinitionOnResultObject')->with(array('sixthConstraint'), array())->will($this->returnValue(FALSE));
  396. $this->assertFalse($rewritingAspect->_call('checkConstraintDefinitionsOnResultObject', $parsedConstraints, array()));
  397. }
  398. /**
  399. * @test
  400. */
  401. public function checkSingleConstraintDefinitionOnResultObjectCallsGetObjectValueByPathForAllExpressionsStartingWithThis() {
  402. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  403. $rewritingAspect->expects($this->at(1))->method('getObjectValueByPath')->with(NULL, 'accounts.title');
  404. $rewritingAspect->expects($this->at(2))->method('getObjectValueByPath')->with(NULL, 'accounts.title');
  405. $rewritingAspect->expects($this->at(4))->method('getObjectValueByPath')->with(NULL, 'accounts.title');
  406. $rewritingAspect->expects($this->at(5))->method('getObjectValueByPath')->with(NULL, 'party.name');
  407. $constraint1 = array(
  408. 'operator' => '==',
  409. 'leftValue' => '"blub"',
  410. 'rightValue' => 'this.accounts.title'
  411. );
  412. $constraint2 = array(
  413. 'operator' => '==',
  414. 'leftValue' => 'this.accounts.title',
  415. 'rightValue' => '"blub"'
  416. );
  417. $constraint3 = array(
  418. 'operator' => '==',
  419. 'leftValue' => 'this.accounts.title',
  420. 'rightValue' => 'this.party.name'
  421. );
  422. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint1, NULL);
  423. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint2, NULL);
  424. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint3, NULL);
  425. }
  426. /**
  427. * @test
  428. */
  429. public function checkSingleConstraintDefinitionOnResultObjectCallsGetValueForOperandForAllExpressionsNotStartingWithThis() {
  430. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  431. $rewritingAspect->expects($this->at(0))->method('getValueForOperand')->with('"blub"');
  432. $rewritingAspect->expects($this->at(3))->method('getValueForOperand')->with('TRUE');
  433. $rewritingAspect->expects($this->at(5))->method('getValueForOperand')->with('NULL');
  434. $constraint1 = array(
  435. 'operator' => '==',
  436. 'leftValue' => '"blub"',
  437. 'rightValue' => 'this.accounts.title'
  438. );
  439. $constraint2 = array(
  440. 'operator' => '==',
  441. 'leftValue' => 'this.accounts.title',
  442. 'rightValue' => 'TRUE'
  443. );
  444. $constraint3 = array(
  445. 'operator' => '==',
  446. 'leftValue' => 'this.accounts.title',
  447. 'rightValue' => 'NULL'
  448. );
  449. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint1, NULL);
  450. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint2, NULL);
  451. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint3, NULL);
  452. }
  453. /**
  454. * @test
  455. * @expectedException \TYPO3\FLOW3\Security\Exception\InvalidQueryRewritingConstraintException
  456. */
  457. public function checkSingleConstraintDefinitionOnResultObjectThrowsAnExceptionIfAConstraintHasNoReferenceToTheCurrentObjectIndicatedByTheThisKeyword() {
  458. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('dummy'), array(), '', FALSE);
  459. $constraint = array(
  460. 'operator' => '==',
  461. 'leftValue' => '"blub"',
  462. 'rightValue' => 'NULL'
  463. );
  464. $rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, NULL);
  465. }
  466. /**
  467. * @test
  468. */
  469. public function checkSingleConstraintDefinitionOnResultObjectWorksForEqualityOperators() {
  470. $entityClassName = 'entityClass' . md5(uniqid(mt_rand(), TRUE));
  471. eval('class ' . $entityClassName . ' implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface {
  472. public function FLOW3_Aop_Proxy_invokeJoinPoint(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) {}
  473. public function __clone() {}
  474. public function __wakeup() {}
  475. }');
  476. $mockEntity = $this->getMock($entityClassName, array(), array(), '', FALSE);
  477. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  478. $rewritingAspect->expects($this->any())->method('getValueForOperand')->with('"blub"')->will($this->returnValue('blub'));
  479. $rewritingAspect->expects($this->any())->method('getObjectValueByPath')->with($mockEntity, 'accounts.title')->will($this->returnValue('blub'));
  480. $constraint1 = array(
  481. 'operator' => '==',
  482. 'leftValue' => '"blub"',
  483. 'rightValue' => 'this.accounts.title'
  484. );
  485. $constraint2 = array(
  486. 'operator' => '!=',
  487. 'leftValue' => '"blub"',
  488. 'rightValue' => 'this.accounts.title'
  489. );
  490. $this->assertTrue($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint1, $mockEntity));
  491. $this->assertFalse($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint2, $mockEntity));
  492. }
  493. /**
  494. * @test
  495. */
  496. public function checkSingleConstraintDefinitionOnResultObjectWorksForTheInOperator() {
  497. $entityClassName = 'entityClass' . md5(uniqid(mt_rand(), TRUE));
  498. eval('class ' . $entityClassName . ' implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface {
  499. public function FLOW3_Aop_Proxy_invokeJoinPoint(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) {}
  500. public function __clone() {}
  501. public function __wakeup() {}
  502. }');
  503. $mockEntity = $this->getMock($entityClassName, array(), array(), '', FALSE);
  504. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  505. $rewritingAspect->expects($this->any())->method('getValueForOperand')->with('current.party')->will($this->returnValue('blub'));
  506. $rewritingAspect->expects($this->at(1))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue(array('bla', 'blub', 'foo')));
  507. $rewritingAspect->expects($this->at(3))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue(array('bla', 'foo', 'bar')));
  508. $constraint = array(
  509. 'operator' => 'in',
  510. 'leftValue' => 'current.party',
  511. 'rightValue' => 'this.party'
  512. );
  513. $this->assertTrue($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, $mockEntity));
  514. $this->assertFalse($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, $mockEntity));
  515. }
  516. /**
  517. * @test
  518. */
  519. public function checkSingleConstraintDefinitionOnResultObjectWorksForTheContainsOperator() {
  520. $entityClassName = 'entityClass' . md5(uniqid(mt_rand(), TRUE));
  521. eval('class ' . $entityClassName . ' implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface {
  522. public function FLOW3_Aop_Proxy_invokeJoinPoint(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) {}
  523. public function __clone() {}
  524. public function __wakeup() {}
  525. }');
  526. $mockEntity = $this->getMock($entityClassName, array(), array(), '', FALSE);
  527. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  528. $rewritingAspect->expects($this->any())->method('getValueForOperand')->with('current.party')->will($this->returnValue(array('bla', 'blub', 'foo')));
  529. $rewritingAspect->expects($this->at(1))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue('blub'));
  530. $rewritingAspect->expects($this->at(3))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue('bar'));
  531. $constraint = array(
  532. 'operator' => 'contains',
  533. 'leftValue' => 'current.party',
  534. 'rightValue' => 'this.party'
  535. );
  536. $this->assertTrue($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, $mockEntity));
  537. $this->assertFalse($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, $mockEntity));
  538. }
  539. /**
  540. * @test
  541. */
  542. public function checkSingleConstraintDefinitionOnResultObjectWorksForTheMatchesOperator() {
  543. $entityClassName = 'entityClass' . md5(uniqid(mt_rand(), TRUE));
  544. eval('class ' . $entityClassName . ' implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface {
  545. public function FLOW3_Aop_Proxy_invokeJoinPoint(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) {}
  546. public function __clone() {}
  547. public function __wakeup() {}
  548. }');
  549. $mockEntity = $this->getMock($entityClassName, array(), array(), '', FALSE);
  550. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  551. $rewritingAspect->expects($this->any())->method('getValueForOperand')->with('current.party')->will($this->returnValue(array('bla', 'blub', 'blubber')));
  552. $rewritingAspect->expects($this->at(1))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue(array('hinz', 'blub', 'kunz')));
  553. $rewritingAspect->expects($this->at(3))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue(array('foo', 'bar', 'baz')));
  554. $constraint = array(
  555. 'operator' => 'matches',
  556. 'leftValue' => 'current.party',
  557. 'rightValue' => 'this.party'
  558. );
  559. $this->assertTrue($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, $mockEntity));
  560. $this->assertFalse($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint, $mockEntity));
  561. }
  562. /**
  563. * @test
  564. */
  565. public function checkSingleConstraintDefinitionOnResultObjectComparesTheIdentifierWhenComparingPersistedObjects() {
  566. $entityClassName = 'entityClass' . md5(uniqid(mt_rand(), TRUE));
  567. eval('class ' . $entityClassName . ' implements \TYPO3\FLOW3\Object\Proxy\ProxyInterface {
  568. public function FLOW3_Aop_Proxy_invokeJoinPoint(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) {}
  569. public function __clone() {}
  570. public function __wakeup() {}
  571. }');
  572. $mockEntity = $this->getMock($entityClassName, array(), array(), '', FALSE);
  573. $mockParty = $this->getMock('TYPO3\Party\Domain\Model\AbstractParty', array(), array(), '', FALSE);
  574. $mockPersistenceManager = $this->getMock('TYPO3\FLOW3\Persistence\PersistenceManagerInterface', array(), array(), '', FALSE);
  575. $mockPersistenceManager->expects($this->any())->method('getIdentifierByObject')->with($mockParty)->will($this->returnValue('uuid'));
  576. $mockReflectionService = $this->getMock('TYPO3\FLOW3\Reflection\ReflectionService', array(), array(), '', FALSE);
  577. $mockReflectionService->expects($this->any())->method('getClassNameByObject')->with($mockParty)->will($this->returnValue(get_class($mockParty)));
  578. $mockReflectionService->expects($this->any())->method('isClassAnnotatedWith')->with(get_class($mockParty), 'TYPO3\FLOW3\Annotations\Entity')->will($this->returnValue(TRUE));
  579. $rewritingAspect = $this->getAccessibleMock('TYPO3\FLOW3\Security\Aspect\PersistenceQueryRewritingAspect', array('getValueForOperand', 'getObjectValueByPath'), array(), '', FALSE);
  580. $rewritingAspect->expects($this->at(0))->method('getValueForOperand')->with('current.party')->will($this->returnValue($mockParty));
  581. $rewritingAspect->expects($this->at(1))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue($mockParty));
  582. $rewritingAspect->expects($this->at(2))->method('getObjectValueByPath')->with($mockEntity, 'party')->will($this->returnValue($mockParty));
  583. $rewritingAspect->expects($this->at(3))->method('getValueForOperand')->with('current.party')->will($this->returnValue($mockParty));
  584. $rewritingAspect->_set('reflectionService', $mockReflectionService);
  585. $rewritingAspect->_set('persistenceManager', $mockPersistenceManager);
  586. $constraint1 = array(
  587. 'operator' => '==',
  588. 'leftValue' => 'current.party',
  589. 'rightValue' => 'this.party'
  590. );
  591. $constraint2 = array(
  592. 'operator' => '==',
  593. 'leftValue' => 'this.party',
  594. 'rightValue' => 'current.party'
  595. );
  596. $this->assertTrue($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint1, $mockEntity));
  597. $this->assertTrue($rewritingAspect->_call('checkSingleConstraintDefinitionOnResultObject', $constraint2, $mockEntity));
  598. }
  599. }
  600. ?>