2dc0084122727dd979f6eac19c989c59dcca73ba
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Mvc / Controller / MvcPropertyMappingConfigurationServiceTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller;
3
4 /* *
5 * This script belongs to the Extbase framework *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License as published by the *
9 * Free Software Foundation, either version 3 of the License, or (at your *
10 * option) any later version. *
11 * *
12 * This script is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
15 * General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with the script. *
19 * If not, see http://www.gnu.org/licenses/lgpl.html *
20 * *
21 * The TYPO3 project - inspiring people to share! *
22 * */
23
24 /**
25 * Test case
26 */
27 class MvcPropertyMappingConfigurationServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
28
29 /**
30 * Data provider for generating the list of trusted properties
31 *
32 * @return array
33 */
34 public function dataProviderForgenerateTrustedPropertiesToken() {
35 return array(
36 'Simple Case - Empty' => array(
37 array(),
38 array(),
39 ),
40 'Simple Case - Single Value' => array(
41 array('field1'),
42 array('field1' => 1),
43 ),
44 'Simple Case - Two Values' => array(
45 array('field1', 'field2'),
46 array(
47 'field1' => 1,
48 'field2' => 1
49 ),
50 ),
51 'Recursion' => array(
52 array('field1', 'field[subfield1]', 'field[subfield2]'),
53 array(
54 'field1' => 1,
55 'field' => array(
56 'subfield1' => 1,
57 'subfield2' => 1
58 )
59 ),
60 ),
61 'recursion with duplicated field name' => array(
62 array('field1', 'field[subfield1]', 'field[subfield2]', 'field1'),
63 array(
64 'field1' => 1,
65 'field' => array(
66 'subfield1' => 1,
67 'subfield2' => 1
68 )
69 ),
70 ),
71 'Recursion with un-named fields at the end (...[]). There, they should be made explicit by increasing the counter' => array(
72 array('field1', 'field[subfield1][]', 'field[subfield1][]', 'field[subfield2]'),
73 array(
74 'field1' => 1,
75 'field' => array(
76 'subfield1' => array(
77 0 => 1,
78 1 => 1
79 ),
80 'subfield2' => 1
81 )
82 ),
83 ),
84 );
85 }
86
87 /**
88 * Data Provider for invalid values in generating the list of trusted properties,
89 * which should result in an exception
90 *
91 * @return array
92 */
93 public function dataProviderForgenerateTrustedPropertiesTokenWithUnallowedValues() {
94 return array(
95 'Overriding form fields (string overridden by array) - 1' => array(
96 array('field1', 'field2', 'field2[bla]', 'field2[blubb]'),
97 ),
98 'Overriding form fields (string overridden by array) - 2' => array(
99 array('field1', 'field2[bla]', 'field2[bla][blubb][blubb]'),
100 ),
101 'Overriding form fields (array overridden by string) - 1' => array(
102 array('field1', 'field2[bla]', 'field2[blubb]', 'field2'),
103 ),
104 'Overriding form fields (array overridden by string) - 2' => array(
105 array('field1', 'field2[bla][blubb][blubb]', 'field2[bla]'),
106 ),
107 'Empty [] not as last argument' => array(
108 array('field1', 'field2[][bla]'),
109 )
110
111 );
112 }
113
114 /**
115 * @test
116 * @dataProvider dataProviderForgenerateTrustedPropertiesToken
117 */
118 public function generateTrustedPropertiesTokenGeneratesTheCorrectHashesInNormalOperation($input, $expected) {
119 $requestHashService = $this->getMock('TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService', array('serializeAndHashFormFieldArray'));
120 $requestHashService->expects($this->once())->method('serializeAndHashFormFieldArray')->with($expected);
121 $requestHashService->generateTrustedPropertiesToken($input);
122 }
123
124 /**
125 * @test
126 * @dataProvider dataProviderForgenerateTrustedPropertiesTokenWithUnallowedValues
127 * @expectedException \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
128 */
129 public function generateTrustedPropertiesTokenThrowsExceptionInWrongCases($input) {
130 $requestHashService = $this->getMock('TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService', array('serializeAndHashFormFieldArray'));
131 $requestHashService->generateTrustedPropertiesToken($input);
132 }
133
134 /**
135 * @test
136 */
137 public function serializeAndHashFormFieldArrayWorks() {
138 $formFieldArray = array(
139 'bla' => array(
140 'blubb' => 1,
141 'hu' => 1
142 )
143 );
144 $mockHash = '12345';
145
146 $hashService = $this->getMock($this->buildAccessibleProxy('TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService'), array('appendHmac'));
147 $hashService->expects($this->once())->method('appendHmac')->with(serialize($formFieldArray))->will($this->returnValue(serialize($formFieldArray) . $mockHash));
148
149 $requestHashService = $this->getMock($this->buildAccessibleProxy('TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService'), array('dummy'));
150 $requestHashService->_set('hashService', $hashService);
151
152 $expected = serialize($formFieldArray) . $mockHash;
153 $actual = $requestHashService->_call('serializeAndHashFormFieldArray', $formFieldArray);
154 $this->assertEquals($expected, $actual);
155 }
156
157 /**
158 * @test
159 */
160 public function initializePropertyMappingConfigurationDoesNothingIfTrustedPropertiesAreNotSet() {
161 $request = $this->getMockBuilder('TYPO3\CMS\Extbase\Mvc\Request')->setMethods(array('getInternalArgument'))->disableOriginalConstructor()->getMock();
162 $request->expects($this->any())->method('getInternalArgument')->with('__trustedProperties')->will($this->returnValue(NULL));
163 $arguments = new \TYPO3\CMS\Extbase\Mvc\Controller\Arguments();
164
165 $requestHashService = new \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService;
166 $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
167 }
168
169 /**
170 * @test
171 */
172 public function initializePropertyMappingConfigurationReturnsEarlyIfNoTrustedPropertiesAreSet() {
173 $trustedProperties = array(
174 'foo' => 1
175 );
176 $this->initializePropertyMappingConfiguration($trustedProperties);
177 }
178
179 /**
180 * @test
181 */
182 public function initializePropertyMappingConfigurationReturnsEarlyIfArgumentIsUnknown() {
183 $trustedProperties = array(
184 'nonExistingArgument' => 1
185 );
186 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
187 $this->assertFalse($arguments->hasArgument('nonExistingArgument'));
188 }
189
190 /**
191 * @test
192 */
193 public function initializePropertyMappingConfigurationSetsModificationAllowedIfIdentityPropertyIsSet() {
194 $trustedProperties = array(
195 'foo' => array(
196 '__identity' => 1,
197 'nested' => array(
198 '__identity' => 1,
199 )
200 )
201 );
202 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
203 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
204 $this->assertTrue($propertyMappingConfiguration->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED), 'ConfigurationValue is not CONFIGURATION_MODIFICATION_ALLOWED at line ' . __LINE__);
205 $this->assertNull($propertyMappingConfiguration->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED), 'ConfigurationValue is not NULL at line ' . __LINE__);
206 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'), 'Value is not FALSE at line ' . __LINE__);
207
208 $this->assertTrue($propertyMappingConfiguration->forProperty('nested')->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED), 'ConfigurationValue is not CONFIGURATION_MODIFICATION_ALLOWED at line ' . __LINE__);
209 $this->assertNull($propertyMappingConfiguration->forProperty('nested')->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED), 'ConfigurationValue is not NULL at line ' . __LINE__);
210 $this->assertFalse($propertyMappingConfiguration->forProperty('nested')->shouldMap('someProperty'), 'Value is not FALSE at line ' . __LINE__);
211 }
212
213 /**
214 * @test
215 */
216 public function initializePropertyMappingConfigurationSetsCreationAllowedIfIdentityPropertyIsNotSet() {
217 $trustedProperties = array(
218 'foo' => array(
219 'bar' => array()
220 )
221 );
222 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
223 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
224 $this->assertNull($propertyMappingConfiguration->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
225 $this->assertTrue($propertyMappingConfiguration->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
226 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
227
228 $this->assertNull($propertyMappingConfiguration->forProperty('bar')->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
229 $this->assertTrue($propertyMappingConfiguration->forProperty('bar')->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
230 $this->assertFalse($propertyMappingConfiguration->forProperty('bar')->shouldMap('someProperty'));
231 }
232
233 /**
234 * @test
235 */
236 public function initializePropertyMappingConfigurationSetsAllowedFields() {
237 $trustedProperties = array(
238 'foo' => array(
239 'bar' => 1
240 )
241 );
242 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
243 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
244 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
245 $this->assertTrue($propertyMappingConfiguration->shouldMap('bar'));
246 }
247
248 /**
249 * @test
250 */
251 public function initializePropertyMappingConfigurationSetsAllowedFieldsRecursively() {
252 $trustedProperties = array(
253 'foo' => array(
254 'bar' => array(
255 'foo' => 1
256 )
257 )
258 );
259 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
260 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
261 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
262 $this->assertTrue($propertyMappingConfiguration->shouldMap('bar'));
263 $this->assertTrue($propertyMappingConfiguration->forProperty('bar')->shouldMap('foo'));
264 }
265
266 /**
267 * Helper which initializes the property mapping configuration and returns arguments
268 *
269 * @param array $trustedProperties
270 *
271 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Arguments
272 */
273 protected function initializePropertyMappingConfiguration(array $trustedProperties) {
274 $request = $this->getMockBuilder('TYPO3\CMS\Extbase\Mvc\Request')->setMethods(array('getInternalArgument'))->disableOriginalConstructor()->getMock();
275 $request->expects($this->any())->method('getInternalArgument')->with('__trustedProperties')->will($this->returnValue('fooTrustedProperties'));
276
277 $mockHashService = $this->getMock('TYPO3\CMS\Extbase\Security\Cryptography\HashService', array('validateAndStripHmac'));
278 $mockHashService->expects($this->once())->method('validateAndStripHmac')->with('fooTrustedProperties')->will($this->returnValue(serialize($trustedProperties)));
279
280 $requestHashService = $this->getAccessibleMock('TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService', array('dummy'));
281 $requestHashService->_set('hashService', $mockHashService);
282
283 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
284 $mockArgument = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Argument', array('getName'), array(), '', FALSE);
285
286 $propertyMappingConfiguration = new \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration();
287
288 $mockArgument->_set('propertyMappingConfiguration', $propertyMappingConfiguration);
289 $mockArgument->expects($this->any())->method('getName')->will($this->returnValue('foo'));
290 $mockObjectManager->expects($this->once())->method('get')->with('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Argument')->will($this->returnValue($mockArgument));
291
292 $arguments = $this->getAccessibleMock('TYPO3\CMS\Extbase\Mvc\Controller\Arguments', array('dummy'));
293 $arguments->_set('objectManager', $mockObjectManager);
294 $arguments->addNewArgument('foo');
295
296 $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
297
298 return $arguments;
299 }
300 }