[TASK] Remove unit tests that do not test the subject
[Packages/TYPO3.CMS.git] / typo3 / sysext / felogin / Tests / Unit / Controller / FrontendLoginControllerTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Felogin\Tests\Unit\Controller;
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
18 use Psr\Log\NullLogger;
19 use TYPO3\CMS\Core\Authentication\LoginType;
20 use TYPO3\CMS\Core\Site\Entity\Site;
21 use TYPO3\CMS\Core\Site\SiteFinder;
22 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
23 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
24 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
25
26 /**
27 * Test case
28 */
29 class FrontendLoginControllerTest extends UnitTestCase
30 {
31 /**
32 * @var \TYPO3\CMS\Felogin\Controller\FrontendLoginController|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
33 */
34 protected $accessibleFixture;
35
36 /**
37 * @var string
38 */
39 protected $testHostName;
40
41 /**
42 * @var string
43 */
44 protected $testSitePath;
45
46 protected $resetSingletonInstances = true;
47
48 /**
49 * Set up
50 */
51 protected function setUp()
52 {
53 $GLOBALS['TSFE'] = new \stdClass();
54 $this->testHostName = 'hostname.tld';
55 $this->testSitePath = '/';
56 $this->accessibleFixture = $this->getAccessibleMock(\TYPO3\CMS\Felogin\Controller\FrontendLoginController::class, ['dummy']);
57 $this->accessibleFixture->cObj = $this->createMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class);
58 $this->accessibleFixture->_set('frontendController', $this->createMock(\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::class));
59 $this->accessibleFixture->setLogger(new NullLogger());
60
61 $site = new Site('dummy', 1, ['base' => 'http://sub.domainhostname.tld/path/']);
62 $mockedSiteFinder = $this->getAccessibleMock(SiteFinder::class, ['getSiteByPageId'], [], '', false, false);
63 $mockedSiteFinder->method('getSiteByPageId')->willReturn($site);
64 $this->accessibleFixture->_set('siteFinder', $mockedSiteFinder);
65
66 $this->setUpFakeSitePathAndHost();
67 }
68
69 /**
70 * Set up a fake site path and host
71 */
72 protected function setUpFakeSitePathAndHost()
73 {
74 $_SERVER['ORIG_PATH_INFO'] = $_SERVER['PATH_INFO'] = $_SERVER['ORIG_SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME'] = $this->testSitePath . TYPO3_mainDir;
75 $_SERVER['HTTP_HOST'] = $this->testHostName;
76 }
77
78 /**
79 * Data provider for validateRedirectUrlClearsUrl
80 *
81 * @return array
82 */
83 public function validateRedirectUrlClearsUrlDataProvider()
84 {
85 return [
86 'absolute URL, hostname not in site, trailing slash' => ['http://badhost.tld/'],
87 'absolute URL, hostname not in site, no trailing slash' => ['http://badhost.tld'],
88 'absolute URL, subdomain in site, but main domain not, trailing slash' => ['http://domainhostname.tld.badhost.tld/'],
89 'absolute URL, subdomain in site, but main domain not, no trailing slash' => ['http://domainhostname.tld.badhost.tld'],
90 'non http absolute URL 1' => ['its://domainhostname.tld/itunes/'],
91 'non http absolute URL 2' => ['ftp://domainhostname.tld/download/'],
92 'XSS attempt 1' => ['javascript:alert(123)'],
93 'XSS attempt 2' => ['" onmouseover="alert(123)"'],
94 'invalid URL, HTML break out attempt' => ['" >blabuubb'],
95 'invalid URL, UNC path' => ['\\\\foo\\bar\\'],
96 'invalid URL, backslashes in path' => ['http://domainhostname.tld\\bla\\blupp'],
97 'invalid URL, linefeed in path' => ['http://domainhostname.tld/bla/blupp' . LF],
98 'invalid URL, only one slash after scheme' => ['http:/domainhostname.tld/bla/blupp'],
99 'invalid URL, illegal chars' => ['http://(<>domainhostname).tld/bla/blupp'],
100 ];
101 }
102
103 /**
104 * @test
105 * @dataProvider validateRedirectUrlClearsUrlDataProvider
106 * @param string $url Invalid Url
107 */
108 public function validateRedirectUrlClearsUrl($url)
109 {
110 $this->assertEquals('', $this->accessibleFixture->_call('validateRedirectUrl', $url));
111 }
112
113 /**
114 * Data provider for validateRedirectUrlKeepsCleanUrl
115 *
116 * @return array
117 */
118 public function validateRedirectUrlKeepsCleanUrlDataProvider()
119 {
120 return [
121 'sane absolute URL' => ['http://sub.domainhostname.tld/path/'],
122 'sane absolute URL with script' => ['http://sub.domainhostname.tld/path/index.php?id=1'],
123 'sane absolute URL with realurl' => ['http://sub.domainhostname.tld/path/foo/bar/foo.html'],
124 'sane absolute URL with homedir' => ['http://sub.domainhostname.tld/path/~user/'],
125 'sane absolute URL with some strange chars encoded' => ['http://sub.domainhostname.tld/path/~user/a%cc%88o%cc%88%c3%9fa%cc%82/foo.html'],
126 'relative URL, no leading slash 1' => ['index.php?id=1'],
127 'relative URL, no leading slash 2' => ['foo/bar/index.php?id=2'],
128 'relative URL, leading slash, no realurl' => ['/index.php?id=1'],
129 'relative URL, leading slash, realurl' => ['/de/service/imprint.html'],
130 ];
131 }
132
133 /**
134 * @test
135 * @dataProvider validateRedirectUrlKeepsCleanUrlDataProvider
136 * @param string $url Clean URL to test
137 */
138 public function validateRedirectUrlKeepsCleanUrl($url)
139 {
140 $this->assertEquals($url, $this->accessibleFixture->_call('validateRedirectUrl', $url));
141 }
142
143 /**
144 * Data provider for validateRedirectUrlClearsInvalidUrlInSubdirectory
145 *
146 * @return array
147 */
148 public function validateRedirectUrlClearsInvalidUrlInSubdirectoryDataProvider()
149 {
150 return [
151 'absolute URL, missing subdirectory' => ['http://hostname.tld/'],
152 'absolute URL, wrong subdirectory' => ['http://hostname.tld/hacker/index.php'],
153 'absolute URL, correct subdirectory, no trailing slash' => ['http://hostname.tld/subdir'],
154 'relative URL, leading slash, no path' => ['/index.php?id=1'],
155 'relative URL, leading slash, wrong path' => ['/de/sub/site.html'],
156 'relative URL, leading slash, slash only' => ['/'],
157 ];
158 }
159
160 /**
161 * @test
162 * @dataProvider validateRedirectUrlClearsInvalidUrlInSubdirectoryDataProvider
163 * @param string $url Invalid Url
164 */
165 public function validateRedirectUrlClearsInvalidUrlInSubdirectory($url)
166 {
167 $this->testSitePath = '/subdir/';
168 $this->setUpFakeSitePathAndHost();
169 $this->assertEquals('', $this->accessibleFixture->_call('validateRedirectUrl', $url));
170 }
171
172 /**
173 * Data provider for validateRedirectUrlKeepsCleanUrlInSubdirectory
174 *
175 * @return array
176 */
177 public function validateRedirectUrlKeepsCleanUrlInSubdirectoryDataProvider()
178 {
179 return [
180 'absolute URL, correct subdirectory' => ['http://hostname.tld/subdir/'],
181 'absolute URL, correct subdirectory, realurl' => ['http://hostname.tld/subdir/de/imprint.html'],
182 'absolute URL, correct subdirectory, no realurl' => ['http://hostname.tld/subdir/index.php?id=10'],
183 'absolute URL, correct subdirectory of site base' => ['http://sub.domainhostname.tld/path/'],
184 'relative URL, no leading slash, realurl' => ['de/service/imprint.html'],
185 'relative URL, no leading slash, no realurl' => ['index.php?id=1'],
186 'relative nested URL, no leading slash, no realurl' => ['foo/bar/index.php?id=2']
187 ];
188 }
189
190 /**
191 * @test
192 * @dataProvider validateRedirectUrlKeepsCleanUrlInSubdirectoryDataProvider
193 * @param string $url Invalid Url
194 */
195 public function validateRedirectUrlKeepsCleanUrlInSubdirectory($url)
196 {
197 $this->testSitePath = '/subdir/';
198 $this->setUpFakeSitePathAndHost();
199 $this->assertEquals($url, $this->accessibleFixture->_call('validateRedirectUrl', $url));
200 }
201
202 /*************************
203 * Test concerning getPreverveGetVars
204 *************************/
205
206 /**
207 * @return array
208 */
209 public function getPreserveGetVarsReturnsCorrectResultDataProvider()
210 {
211 return [
212 'special get var id is not preserved' => [
213 [
214 'id' => 42,
215 ],
216 '',
217 [],
218 ],
219 'simple additional parameter is not preserved if not specified in preservedGETvars' => [
220 [
221 'id' => 42,
222 'special' => 23,
223 ],
224 '',
225 [],
226 ],
227 'all params except ignored ones are preserved if preservedGETvars is set to "all"' => [
228 [
229 'id' => 42,
230 'special1' => 23,
231 'special2' => [
232 'foo' => 'bar',
233 ],
234 'tx_felogin_pi1' => [
235 'forgot' => 1,
236 ],
237 ],
238 'all',
239 [
240 'special1' => 23,
241 'special2' => [
242 'foo' => 'bar',
243 ],
244 ]
245 ],
246 'preserve single parameter' => [
247 [
248 'L' => 42,
249 ],
250 'L',
251 [
252 'L' => 42,
253 ],
254 ],
255 'preserve whole parameter array' => [
256 [
257 'L' => 3,
258 'tx_someext' => [
259 'foo' => 'simple',
260 'bar' => [
261 'baz' => 'simple',
262 ],
263 ],
264 ],
265 'L,tx_someext',
266 [
267 'L' => 3,
268 'tx_someext' => [
269 'foo' => 'simple',
270 'bar' => [
271 'baz' => 'simple',
272 ],
273 ],
274 ],
275 ],
276 'preserve part of sub array' => [
277 [
278 'L' => 3,
279 'tx_someext' => [
280 'foo' => 'simple',
281 'bar' => [
282 'baz' => 'simple',
283 ],
284 ],
285 ],
286 'L,tx_someext[bar]',
287 [
288 'L' => 3,
289 'tx_someext' => [
290 'bar' => [
291 'baz' => 'simple',
292 ],
293 ],
294 ],
295 ],
296 'preserve keys on different levels' => [
297 [
298 'L' => 3,
299 'no-preserve' => 'whatever',
300 'tx_ext2' => [
301 'foo' => 'simple',
302 ],
303 'tx_ext3' => [
304 'bar' => [
305 'baz' => 'simple',
306 ],
307 'go-away' => '',
308 ],
309 ],
310 'L,tx_ext2,tx_ext3[bar]',
311 [
312 'L' => 3,
313 'tx_ext2' => [
314 'foo' => 'simple',
315 ],
316 'tx_ext3' => [
317 'bar' => [
318 'baz' => 'simple',
319 ],
320 ],
321 ],
322 ],
323 'preserved value that does not exist in get' => [
324 [],
325 'L,foo%5Bbar%5D',
326 [],
327 ],
328 ];
329 }
330
331 /**
332 * @test
333 * @dataProvider getPreserveGetVarsReturnsCorrectResultDataProvider
334 * @param array $getArray
335 * @param string $preserveVars
336 * @param string $expected
337 */
338 public function getPreserveGetVarsReturnsCorrectResult(array $getArray, $preserveVars, $expected)
339 {
340 $_GET = $getArray;
341 $this->accessibleFixture->conf['preserveGETvars'] = $preserveVars;
342 $this->assertSame($expected, $this->accessibleFixture->_call('getPreserveGetVars'));
343 }
344
345 /**************************************************
346 * Tests concerning isInLocalDomain
347 **************************************************/
348
349 /**
350 * Dataprovider for isInCurrentDomainIgnoresScheme
351 *
352 * @return array
353 */
354 public function isInCurrentDomainIgnoresSchemeDataProvider()
355 {
356 return [
357 'url https, current host http' => [
358 'example.com', // HTTP_HOST
359 '0', // HTTPS
360 'https://example.com/foo.html' // URL
361 ],
362 'url http, current host https' => [
363 'example.com',
364 '1',
365 'http://example.com/foo.html'
366 ],
367 'url https, current host https' => [
368 'example.com',
369 '1',
370 'https://example.com/foo.html'
371 ],
372 'url http, current host http' => [
373 'example.com',
374 '0',
375 'http://example.com/foo.html'
376 ]
377 ];
378 }
379
380 /**
381 * @test
382 * @dataProvider isInCurrentDomainIgnoresSchemeDataProvider
383 * @param string $host $_SERVER['HTTP_HOST']
384 * @param string $https $_SERVER['HTTPS']
385 * @param string $url The url to test
386 */
387 public function isInCurrentDomainIgnoresScheme($host, $https, $url)
388 {
389 $_SERVER['HTTP_HOST'] = $host;
390 $_SERVER['HTTPS'] = $https;
391 $this->assertTrue($this->accessibleFixture->_call('isInCurrentDomain', $url));
392 }
393
394 /**
395 * @return array
396 */
397 public function isInCurrentDomainReturnsFalseIfDomainsAreDifferentDataProvider()
398 {
399 return [
400 'simple difference' => [
401 'example.com', // HTTP_HOST
402 'http://typo3.org/foo.html' // URL
403 ],
404 'subdomain different' => [
405 'example.com',
406 'http://foo.example.com/bar.html'
407 ]
408 ];
409 }
410
411 /**
412 * @test
413 * @dataProvider isInCurrentDomainReturnsFalseIfDomainsAreDifferentDataProvider
414 * @param string $host $_SERVER['HTTP_HOST']
415 * @param string $url The url to test
416 */
417 public function isInCurrentDomainReturnsFalseIfDomainsAreDifferent($host, $url)
418 {
419 $_SERVER['HTTP_HOST'] = $host;
420 $this->assertFalse($this->accessibleFixture->_call('isInCurrentDomain', $url));
421 }
422
423 /**
424 * @test
425 */
426 public function processRedirectReferrerDomainsMatchesDomains()
427 {
428 $conf = [
429 'redirectMode' => 'refererDomains',
430 'domains' => 'example.com'
431 ];
432
433 $this->accessibleFixture->_set('conf', $conf);
434 $this->accessibleFixture->_set('logintype', LoginType::LOGIN);
435 $this->accessibleFixture->_set('referer', 'http://www.example.com/snafu');
436 /** @var TypoScriptFrontendController $tsfe */
437 $tsfe = $this->accessibleFixture->_get('frontendController');
438 $this->accessibleFixture->_set('userIsLoggedIn', true);
439 $this->assertSame(['http://www.example.com/snafu'], $this->accessibleFixture->_call('processRedirect'));
440 }
441
442 /**
443 *
444 */
445 public function processUserFieldsRespectsDefaultConfigurationForStdWrapDataProvider()
446 {
447 return [
448 'Simple casing' => [
449 [
450 'username' => 'Holy',
451 'lastname' => 'Wood',
452 ],
453 [
454 'username.' => [
455 'case' => 'upper'
456 ]
457 ],
458 [
459 '###FEUSER_USERNAME###' => 'HOLY',
460 '###FEUSER_LASTNAME###' => 'Wood',
461 '###USER###' => 'HOLY'
462 ]
463 ],
464 'Default config applies' => [
465 [
466 'username' => 'Holy',
467 'lastname' => 'O" Mally',
468 ],
469 [
470 'username.' => [
471 'case' => 'upper'
472 ]
473 ],
474 [
475 '###FEUSER_USERNAME###' => 'HOLY',
476 '###FEUSER_LASTNAME###' => 'O&quot; Mally',
477 '###USER###' => 'HOLY'
478 ]
479 ],
480 'Specific config overrides default config' => [
481 [
482 'username' => 'Holy',
483 'lastname' => 'O" Mally',
484 ],
485 [
486 'username.' => [
487 'case' => 'upper'
488 ],
489 'lastname.' => [
490 'htmlSpecialChars' => '0'
491 ]
492 ],
493 [
494 '###FEUSER_USERNAME###' => 'HOLY',
495 '###FEUSER_LASTNAME###' => 'O" Mally',
496 '###USER###' => 'HOLY'
497 ]
498 ],
499 'No given user returns empty array' => [
500 null,
501 [
502 'username.' => [
503 'case' => 'upper'
504 ],
505 'lastname.' => [
506 'htmlSpecialChars' => '0'
507 ]
508 ],
509 []
510 ],
511 ];
512 }
513
514 /**
515 * @test
516 * @dataProvider processUserFieldsRespectsDefaultConfigurationForStdWrapDataProvider
517 */
518 public function processUserFieldsRespectsDefaultConfigurationForStdWrap($userRecord, $fieldConf, $expectedMarkers)
519 {
520 $tsfe = new \stdClass();
521 $tsfe->fe_user = new \stdClass();
522 $tsfe->fe_user->user = $userRecord;
523 $conf = ['userfields.' => $fieldConf];
524 $this->accessibleFixture->_set('cObj', new ContentObjectRenderer());
525 $this->accessibleFixture->_set('frontendController', $tsfe);
526 $this->accessibleFixture->_set('conf', $conf);
527 $actualResult = $this->accessibleFixture->_call('getUserFieldMarkers');
528 $this->assertEquals($expectedMarkers, $actualResult);
529 }
530 }