‪TYPO3CMS  11.5
MvcPropertyMappingConfigurationServiceTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
29 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
30 
35 {
42  {
43  return [
44  'Simple Case - Empty' => [
45  [],
46  [],
47  ],
48  'Simple Case - Single Value' => [
49  ['field1'],
50  ['field1' => 1],
51  ],
52  'Simple Case - Two Values' => [
53  ['field1', 'field2'],
54  [
55  'field1' => 1,
56  'field2' => 1,
57  ],
58  ],
59  'Recursion' => [
60  ['field1', 'field[subfield1]', 'field[subfield2]'],
61  [
62  'field1' => 1,
63  'field' => [
64  'subfield1' => 1,
65  'subfield2' => 1,
66  ],
67  ],
68  ],
69  'recursion with duplicated field name' => [
70  ['field1', 'field[subfield1]', 'field[subfield2]', 'field1'],
71  [
72  'field1' => 1,
73  'field' => [
74  'subfield1' => 1,
75  'subfield2' => 1,
76  ],
77  ],
78  ],
79  'Recursion with un-named fields at the end (...[]). There, they should be made explicit by increasing the counter' => [
80  ['field1', 'field[subfield1][]', 'field[subfield1][]', 'field[subfield2]'],
81  [
82  'field1' => 1,
83  'field' => [
84  'subfield1' => [
85  0 => 1,
86  1 => 1,
87  ],
88  'subfield2' => 1,
89  ],
90  ],
91  ],
92  ];
93  }
94 
102  {
103  return [
104  'Overriding form fields (string overridden by array) - 1' => [
105  ['field1', 'field2', 'field2[bla]', 'field2[blubb]'],
106  1255072196,
107  ],
108  'Overriding form fields (string overridden by array) - 2' => [
109  ['field1', 'field2[bla]', 'field2[bla][blubb][blubb]'],
110  1255072196,
111  ],
112  'Overriding form fields (array overridden by string) - 1' => [
113  ['field1', 'field2[bla]', 'field2[blubb]', 'field2'],
114  1255072587,
115  ],
116  'Overriding form fields (array overridden by string) - 2' => [
117  ['field1', 'field2[bla][blubb][blubb]', 'field2[bla]'],
118  1255072587,
119  ],
120  'Empty [] not as last argument' => [
121  ['field1', 'field2[][bla]'],
122  1255072832,
123  ],
124 
125  ];
126  }
127 
133  {
134  $requestHashService = $this->getMockBuilder(MvcPropertyMappingConfigurationService::class)
135  ->onlyMethods(['serializeAndHashFormFieldArray'])
136  ->getMock();
137  $requestHashService->expects(self::once())->method('serializeAndHashFormFieldArray')->with($expected);
138  $requestHashService->generateTrustedPropertiesToken($input);
139  }
140 
145  public function ‪generateTrustedPropertiesTokenThrowsExceptionInWrongCases(array $input, int $expectExceptionCode): void
146  {
147  $this->expectException(InvalidArgumentForHashGenerationException::class);
148  $this->expectExceptionCode($expectExceptionCode);
149  $requestHashService = $this->getMockBuilder(MvcPropertyMappingConfigurationService::class)
150  ->onlyMethods(['serializeAndHashFormFieldArray'])
151  ->getMock();
152  $requestHashService->generateTrustedPropertiesToken($input);
153  }
154 
159  {
160  $formFieldArray = [
161  'bla' => [
162  'blubb' => 1,
163  'hu' => 1,
164  ],
165  ];
166  $mockHash = '12345';
167 
168  $hashService = $this->getMockBuilder(HashService::class)
169  ->onlyMethods(['appendHmac'])
170  ->getMock();
171  $hashService->expects(self::once())->method('appendHmac')->with(json_encode($formFieldArray))->willReturn(json_encode($formFieldArray) . $mockHash);
172 
173  $requestHashService = $this->getAccessibleMock(MvcPropertyMappingConfigurationService::class, ['dummy']);
174  $requestHashService->injectHashService($hashService);
175 
176  $expected = json_encode($formFieldArray) . $mockHash;
177  $actual = $requestHashService->_call('serializeAndHashFormFieldArray', $formFieldArray);
178  self::assertEquals($expected, $actual);
179  }
180 
185  {
186  $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock();
187  $request->method('getInternalArgument')->with('__trustedProperties')->willReturn(null);
188  $arguments = new ‪Arguments();
189 
190  $requestHashService = new ‪MvcPropertyMappingConfigurationService();
191  $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
192  }
193 
198  {
199  $this->expectException(BadRequestException::class);
200  $this->expectExceptionCode(1581862822);
201 
202  $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock();
203  $request->method('getInternalArgument')->with('__trustedProperties')->willReturn('string with less than 40 characters');
204  $arguments = new ‪Arguments();
205 
206  $hashService = new ‪HashService();
207  $requestHashService = new ‪MvcPropertyMappingConfigurationService();
208  $requestHashService->injectHashService($hashService);
209  $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
210  }
211 
216  {
217  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'bar';
218  $hashService = new ‪HashService();
219  $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock();
220  $request->method('getInternalArgument')->with('__trustedProperties')->willReturn('garbage' . $hashService->generateHmac('garbage'));
221  $arguments = new ‪Arguments();
222 
223  $arguments = new ‪Arguments();
224  $requestHashService = new ‪MvcPropertyMappingConfigurationService();
225  $requestHashService->injectHashService($hashService);
226 
227  $this->expectException(BadRequestException::class);
228  $this->expectExceptionMessage('The HMAC of the form could not be utilized.');
229  $this->expectExceptionCode(1691267306);
230 
231  $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
232  }
233 
238  {
239  $hashService = new ‪HashService();
240  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'bar';
241  $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock();
242  $request->method('getInternalArgument')->with('__trustedProperties')->willReturn('a:1:{s:3:"foo";s:3:"bar";}' . $hashService->generateHmac('a:1:{s:3:"foo";s:3:"bar";}'));
243 
244  $arguments = new ‪Arguments();
245  $requestHashService = new ‪MvcPropertyMappingConfigurationService();
246  $requestHashService->injectHashService($hashService);
247 
248  $this->expectException(BadRequestException::class);
249  $this->expectExceptionMessage('Trusted properties used outdated serialization format instead of json.');
250  $this->expectExceptionCode(1699604555);
251 
252  $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
253  }
254 
259  {
260  $trustedProperties = [
261  'foo' => 1,
262  ];
263  $this->‪initializePropertyMappingConfiguration($trustedProperties);
264  }
265 
270  {
271  $trustedProperties = [
272  'nonExistingArgument' => 1,
273  ];
274  $arguments = $this->‪initializePropertyMappingConfiguration($trustedProperties);
275  self::assertFalse($arguments->hasArgument('nonExistingArgument'));
276  }
277 
282  {
283  $trustedProperties = [
284  'foo' => [
285  '__identity' => 1,
286  'nested' => [
287  '__identity' => 1,
288  ],
289  ],
290  ];
291  $arguments = $this->‪initializePropertyMappingConfiguration($trustedProperties);
292  $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
293  self::assertTrue($propertyMappingConfiguration->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED), 'ConfigurationValue is not CONFIGURATION_MODIFICATION_ALLOWED at line ' . __LINE__);
294  self::assertNull($propertyMappingConfiguration->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED), 'ConfigurationValue is not NULL at line ' . __LINE__);
295  self::assertFalse($propertyMappingConfiguration->shouldMap('someProperty'), 'Value is not FALSE at line ' . __LINE__);
296 
297  self::assertTrue($propertyMappingConfiguration->forProperty('nested')->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED), 'ConfigurationValue is not CONFIGURATION_MODIFICATION_ALLOWED at line ' . __LINE__);
298  self::assertNull($propertyMappingConfiguration->forProperty('nested')->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED), 'ConfigurationValue is not NULL at line ' . __LINE__);
299  self::assertFalse($propertyMappingConfiguration->forProperty('nested')->shouldMap('someProperty'), 'Value is not FALSE at line ' . __LINE__);
300  }
301 
306  {
307  $trustedProperties = [
308  'foo' => [
309  'bar' => [],
310  ],
311  ];
312  $arguments = $this->‪initializePropertyMappingConfiguration($trustedProperties);
313  $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
314  self::assertNull($propertyMappingConfiguration->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
315  self::assertTrue($propertyMappingConfiguration->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
316  self::assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
317 
318  self::assertNull($propertyMappingConfiguration->forProperty('bar')->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
319  self::assertTrue($propertyMappingConfiguration->forProperty('bar')->getConfigurationValue(PersistentObjectConverter::class, ‪PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
320  self::assertFalse($propertyMappingConfiguration->forProperty('bar')->shouldMap('someProperty'));
321  }
322 
327  {
328  $trustedProperties = [
329  'foo' => [
330  'bar' => 1,
331  ],
332  ];
333  $arguments = $this->‪initializePropertyMappingConfiguration($trustedProperties);
334  $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
335  self::assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
336  self::assertTrue($propertyMappingConfiguration->shouldMap('bar'));
337  }
338 
343  {
344  $trustedProperties = [
345  'foo' => [
346  'bar' => [
347  'foo' => 1,
348  ],
349  ],
350  ];
351  $arguments = $this->‪initializePropertyMappingConfiguration($trustedProperties);
352  $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
353  self::assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
354  self::assertTrue($propertyMappingConfiguration->shouldMap('bar'));
355  self::assertTrue($propertyMappingConfiguration->forProperty('bar')->shouldMap('foo'));
356  }
357 
365  protected function ‪initializePropertyMappingConfiguration(array $trustedProperties): ‪Arguments
366  {
367  $request = $this->getMockBuilder(Request::class)->onlyMethods(['getInternalArgument'])->disableOriginalConstructor()->getMock();
368  $request->method('getInternalArgument')->with('__trustedProperties')->willReturn('fooTrustedProperties');
369 
370  $mockHashService = $this->getMockBuilder(HashService::class)
371  ->onlyMethods(['validateAndStripHmac'])
372  ->getMock();
373  $mockHashService->expects(self::once())->method('validateAndStripHmac')->with('fooTrustedProperties')->willReturn(json_encode($trustedProperties));
374 
375  $requestHashService = $this->getAccessibleMock(MvcPropertyMappingConfigurationService::class, ['dummy']);
376  $requestHashService->_set('hashService', $mockHashService);
377 
378  $mockArgument = $this->getAccessibleMock(Argument::class, ['getName'], [], '', false);
379 
380  $propertyMappingConfiguration = new ‪MvcPropertyMappingConfiguration();
381 
382  $mockArgument->_set('propertyMappingConfiguration', $propertyMappingConfiguration);
383  $mockArgument->method('getName')->willReturn('foo');
384 
385  $arguments = $this->getAccessibleMock(Arguments::class, ['dummy']);
386  $arguments->addNewArgument('foo');
387 
388  $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
389 
390  return $arguments;
391  }
392 }
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationWithNonDecodableTrustedPropertiesThrowsException
‪initializePropertyMappingConfigurationWithNonDecodableTrustedPropertiesThrowsException()
Definition: MvcPropertyMappingConfigurationServiceTest.php:215
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationThrowsBadRequestExceptionOnInvalidHmac
‪initializePropertyMappingConfigurationThrowsBadRequestExceptionOnInvalidHmac()
Definition: MvcPropertyMappingConfigurationServiceTest.php:197
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationReturnsEarlyIfNoTrustedPropertiesAreSet
‪initializePropertyMappingConfigurationReturnsEarlyIfNoTrustedPropertiesAreSet()
Definition: MvcPropertyMappingConfigurationServiceTest.php:258
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller
Definition: ActionControllerTest.php:18
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationDoesNothingIfTrustedPropertiesAreNotSet
‪initializePropertyMappingConfigurationDoesNothingIfTrustedPropertiesAreNotSet()
Definition: MvcPropertyMappingConfigurationServiceTest.php:184
‪TYPO3\CMS\Extbase\Mvc\Controller\Arguments
Definition: Arguments.php:27
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationReturnsEarlyIfArgumentIsUnknown
‪initializePropertyMappingConfigurationReturnsEarlyIfArgumentIsUnknown()
Definition: MvcPropertyMappingConfigurationServiceTest.php:269
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationSetsAllowedFields
‪initializePropertyMappingConfigurationSetsAllowedFields()
Definition: MvcPropertyMappingConfigurationServiceTest.php:326
‪TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
Definition: InvalidArgumentForHashGenerationException.php:25
‪TYPO3\CMS\Core\Error\Http\BadRequestException
Definition: BadRequestException.php:24
‪TYPO3\CMS\Extbase\Security\Cryptography\HashService
Definition: HashService.php:31
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\generateTrustedPropertiesTokenThrowsExceptionInWrongCases
‪generateTrustedPropertiesTokenThrowsExceptionInWrongCases(array $input, int $expectExceptionCode)
Definition: MvcPropertyMappingConfigurationServiceTest.php:145
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationWithOutdatedTrustedPropertiesThrowsException
‪initializePropertyMappingConfigurationWithOutdatedTrustedPropertiesThrowsException()
Definition: MvcPropertyMappingConfigurationServiceTest.php:237
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\dataProviderForGenerateTrustedPropertiesToken
‪array dataProviderForGenerateTrustedPropertiesToken()
Definition: MvcPropertyMappingConfigurationServiceTest.php:41
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationSetsCreationAllowedIfIdentityPropertyIsNotSet
‪initializePropertyMappingConfigurationSetsCreationAllowedIfIdentityPropertyIsNotSet()
Definition: MvcPropertyMappingConfigurationServiceTest.php:305
‪TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter\CONFIGURATION_CREATION_ALLOWED
‪const CONFIGURATION_CREATION_ALLOWED
Definition: PersistentObjectConverter.php:52
‪TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter
Definition: PersistentObjectConverter.php:43
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest
Definition: MvcPropertyMappingConfigurationServiceTest.php:35
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\dataProviderForGenerateTrustedPropertiesTokenWithUnallowedValues
‪array dataProviderForGenerateTrustedPropertiesTokenWithUnallowedValues()
Definition: MvcPropertyMappingConfigurationServiceTest.php:101
‪TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration
Definition: MvcPropertyMappingConfiguration.php:26
‪TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter\CONFIGURATION_MODIFICATION_ALLOWED
‪const CONFIGURATION_MODIFICATION_ALLOWED
Definition: PersistentObjectConverter.php:47
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationSetsModificationAllowedIfIdentityPropertyIsSet
‪initializePropertyMappingConfigurationSetsModificationAllowedIfIdentityPropertyIsSet()
Definition: MvcPropertyMappingConfigurationServiceTest.php:281
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\serializeAndHashFormFieldArrayWorks
‪serializeAndHashFormFieldArrayWorks()
Definition: MvcPropertyMappingConfigurationServiceTest.php:158
‪TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService
Definition: MvcPropertyMappingConfigurationService.php:46
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfigurationSetsAllowedFieldsRecursively
‪initializePropertyMappingConfigurationSetsAllowedFieldsRecursively()
Definition: MvcPropertyMappingConfigurationServiceTest.php:342
‪TYPO3\CMS\Extbase\Mvc\Controller\Argument
Definition: Argument.php:27
‪TYPO3\CMS\Extbase\Mvc\Request
Definition: Request.php:39
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\generateTrustedPropertiesTokenGeneratesTheCorrectHashesInNormalOperation
‪generateTrustedPropertiesTokenGeneratesTheCorrectHashesInNormalOperation($input, $expected)
Definition: MvcPropertyMappingConfigurationServiceTest.php:132
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\MvcPropertyMappingConfigurationServiceTest\initializePropertyMappingConfiguration
‪TYPO3 CMS Extbase Mvc Controller Arguments initializePropertyMappingConfiguration(array $trustedProperties)
Definition: MvcPropertyMappingConfigurationServiceTest.php:365