‪TYPO3CMS  ‪main
MfaInfoElementTest.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 
20 use PHPUnit\Framework\Attributes\Test;
28 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
29 
30 final class ‪MfaInfoElementTest extends FunctionalTestCase
31 {
32  protected function ‪setUp(): void
33  {
34  parent::setUp();
35  $this->importCSVDataSet(__DIR__ . '/../../../../../core/Tests/Functional/Authentication/Fixtures/be_users.csv');
36 
37  ‪$GLOBALS['BE_USER'] = GeneralUtility::makeInstance(BackendUserAuthentication::class);
38  ‪$GLOBALS['BE_USER']->enablecolumns = ['deleted' => true];
39  ‪$GLOBALS['BE_USER']->setBeUserByUid(1);
40 
41  // Default LANG mock just returns incoming value as label if calling ->sL()
42  $languageServiceMock = $this->createMock(LanguageService::class);
43  $languageServiceMock->method('sL')->with(self::anything())->willReturnArgument(0);
44  ‪$GLOBALS['LANG'] = $languageServiceMock;
45  }
46 
47  #[Test]
49  {
50  $result = $this->‪getFormElementResult([
51  'tableName' => 'some_table',
52  ]);
53 
54  self::assertEmpty($result['html']);
55  }
56 
57  #[Test]
59  {
60  $result = $this->‪getFormElementResult([
61  'tableName' => 'be_users',
62  'databaseRow' => [
63  'uid' => 3,
64  ],
65  'parameterArray' => [
66  'itemFormElValue' => '[]',
67  'fieldConf' => [
68  'label' => 'foo',
69  ],
70  ],
71  ]);
72 
73  // MFA is disabled
74  self::assertMatchesRegularExpression('/<span.*class="badge badge-danger.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.disabled/s', $result['html']);
75  self::assertDoesNotMatchRegularExpression('/<span.*class="badge badge-success.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.enabled/s', $result['html']);
76  // MFA can NOT be deactivated
77  self::assertMatchesRegularExpression('/<button.*class="t3js-deactivate-mfa-button btn btn-danger disabled".*disabled="disabled"/s', $result['html']);
78  // JavaScript is NOT added
79  self::assertEmpty($result['javaScriptModules']);
80  }
81 
82  #[Test]
84  {
85  $result = $this->‪getFormElementResult([
86  'tableName' => 'be_users',
87  'databaseRow' => [
88  'uid' => 4,
89  ],
90  'parameterArray' => [
91  'itemFormElValue' => '{"invalid":{"active":true}}',
92  'fieldConf' => [
93  'label' => 'foo',
94  ],
95  ],
96  ]);
97 
98  // MFA is disabled
99  self::assertMatchesRegularExpression('/<span.*class="badge badge-danger.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.disabled/s', $result['html']);
100  self::assertDoesNotMatchRegularExpression('/<span.*class="badge badge-success.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.enabled/s', $result['html']);
101  // MFA can NOT be deactivated
102  self::assertMatchesRegularExpression('/<button.*class="t3js-deactivate-mfa-button btn btn-danger disabled".*disabled="disabled"/s', $result['html']);
103  // JavaScript is NOT added
104  self::assertEmpty($result['javaScriptModules']);
105  }
106 
107  #[Test]
109  {
110  $result = $this->‪getFormElementResult([
111  'tableName' => 'be_users',
112  'databaseRow' => [
113  'uid' => 4,
114  ],
115  'parameterArray' => [
116  'itemFormElValue' => '{"totp":{"secret":"KRMVATZTJFZUC53FONXW2ZJB","active":true,"attempts":2}}',
117  'fieldConf' => [
118  'label' => 'foo',
119  ],
120  ],
121  ]);
122 
123  // Mfa is enabled
124  self::assertDoesNotMatchRegularExpression('/<span.*class="badge badge-danger.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.disabled/s', $result['html']);
125  self::assertMatchesRegularExpression('/<span.*class="badge badge-success.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.enabled/s', $result['html']);
126  // Totp item exist
127  self::assertMatchesRegularExpression('/<li.*class="list-group-item".*id="provider-totp"/s', $result['html']);
128  // Recovery codes item does NOT exist
129  self::assertStringNotContainsString('id="provider-recovery-codes"', $result['html']);
130  // No item is locked
131  self::assertDoesNotMatchRegularExpression('/<span.*class="badge badge-danger".*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.locked/s', $result['html']);
132  // Item can be deactivated
133  self::assertMatchesRegularExpression('/<button.*class="btn btn-default btn-sm float-end t3js-deactivate-provider-button"/s', $result['html']);
134  // MFA can be deactivated
135  self::assertMatchesRegularExpression('/<button.*class="t3js-deactivate-mfa-button btn btn-danger "/s', $result['html']);
136  // JavaScript is added
137  self::assertInstanceOf(JavaScriptModuleInstruction::class, $result['javaScriptModules'][0]);
138  self::assertSame('@typo3/backend/form-engine/element/mfa-info-element.js', $result['javaScriptModules'][0]->getName());
139  }
140 
141  #[Test]
143  {
144  $result = $this->‪getFormElementResult([
145  'tableName' => 'be_users',
146  'databaseRow' => [
147  'uid' => 5,
148  ],
149  'parameterArray' => [
150  'itemFormElValue' => '{"totp":{"secret":"KRMVATZTJFZUC53FONXW2ZJB","active":true,"attempts":2},"recovery-codes":{"active":true,"attempts":3,"codes":[]}}',
151  'fieldConf' => [
152  'label' => 'foo',
153  ],
154  ],
155  ]);
156 
157  // Mfa is enabled
158  self::assertDoesNotMatchRegularExpression('/<span.*class="badge badge-danger.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.disabled/s', $result['html']);
159  self::assertMatchesRegularExpression('/<span.*class="badge badge-success.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.enabled/s', $result['html']);
160  // Totp item exists
161  self::assertMatchesRegularExpression('/<li.*class="list-group-item".*id="provider-totp"/s', $result['html']);
162  // Recovery codes item exists
163  self::assertMatchesRegularExpression('/<li.*class="list-group-item".*id="provider-recovery-codes"/s', $result['html']);
164  // Item is locked
165  self::assertMatchesRegularExpression('/<span.*class="badge badge-danger".*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.locked/s', $result['html']);
166  // Items can be deactivated
167  self::assertMatchesRegularExpression('/<button.*class="btn btn-default btn-sm float-end t3js-deactivate-provider-button"/s', $result['html']);
168  // MFA can be deactivated
169  self::assertMatchesRegularExpression('/<button.*class="t3js-deactivate-mfa-button btn btn-danger "/s', $result['html']);
170  // JavaScript is added
171  self::assertInstanceOf(JavaScriptModuleInstruction::class, $result['javaScriptModules'][0]);
172  self::assertSame('@typo3/backend/form-engine/element/mfa-info-element.js', $result['javaScriptModules'][0]->getName());
173  }
174 
175  #[Test]
177  {
178  // Make the target user a system maintainer. Since the current user (1)
179  // is only admin, he is not allowed to deactivate the providers, nor MFA.
180  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] = ['5'];
181 
182  $result = $this->‪getFormElementResult([
183  'tableName' => 'be_users',
184  'databaseRow' => [
185  'uid' => 5,
186  ],
187  'parameterArray' => [
188  'itemFormElValue' => '{"totp":{"secret":"KRMVATZTJFZUC53FONXW2ZJB","active":true,"attempts":2},"recovery-codes":{"active":true,"attempts":3,"codes":[]}}',
189  'fieldConf' => [
190  'label' => 'foo',
191  ],
192  ],
193  ]);
194 
195  // Mfa is enabled
196  self::assertDoesNotMatchRegularExpression('/<span.*class="badge badge-danger.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.disabled/s', $result['html']);
197  self::assertMatchesRegularExpression('/<span.*class="badge badge-success.*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.mfa.enabled/s', $result['html']);
198  // Totp item exists
199  self::assertMatchesRegularExpression('/<li.*class="list-group-item".*id="provider-totp"/s', $result['html']);
200  // Recovery codes item exists
201  self::assertMatchesRegularExpression('/<li.*class="list-group-item".*id="provider-recovery-codes"/s', $result['html']);
202  // Item (recovery codes) is locked
203  self::assertMatchesRegularExpression('/<span.*class="badge badge-danger".*>LLL:EXT:core\/Resources\/Private\/Language\/locallang_core.xlf:labels.locked/s', $result['html']);
204  // Items deactivation button is not shown
205  self::assertStringNotContainsString('t3js-deactivate-provider-button', $result['html']);
206  // MFA deactivation button is not shown
207  self::assertStringNotContainsString('t3js-deactivate-mfa-button', $result['html']);
208  // JavaScript is NOT added
209  self::assertEmpty($result['javaScriptModules']);
210  }
211 
212  protected function ‪getFormElementResult(array $data): array
213  {
214  $node = new ‪MfaInfoElement($this->get(IconFactory::class), $this->get(MfaProviderRegistry::class));
215  $node->setData($data);
216  return $node->render();
217  }
218 }
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\renderReturnsElementWithMfaActiveAndLockedProvidersTest
‪renderReturnsElementWithMfaActiveAndLockedProvidersTest()
Definition: MfaInfoElementTest.php:142
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\getFormElementResult
‪getFormElementResult(array $data)
Definition: MfaInfoElementTest.php:212
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\renderReturnsElementWithMfaDisabledTest
‪renderReturnsElementWithMfaDisabledTest()
Definition: MfaInfoElementTest.php:58
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\renderReturnsElementWithoutInvalidProviderTest
‪renderReturnsElementWithoutInvalidProviderTest()
Definition: MfaInfoElementTest.php:83
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element
Definition: MfaInfoElementTest.php:18
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\renderReturnsElementWithoutDeactivationButtonsOnMissingPermissionsTest
‪renderReturnsElementWithoutDeactivationButtonsOnMissingPermissionsTest()
Definition: MfaInfoElementTest.php:176
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\renderReturnsEmptyResultOnInvalidTableTest
‪renderReturnsEmptyResultOnInvalidTableTest()
Definition: MfaInfoElementTest.php:48
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\renderReturnsElementWithMfaActiveTest
‪renderReturnsElementWithMfaActiveTest()
Definition: MfaInfoElementTest.php:108
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest\setUp
‪setUp()
Definition: MfaInfoElementTest.php:32
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Tests\Functional\Form\Element\MfaInfoElementTest
Definition: MfaInfoElementTest.php:31
‪TYPO3\CMS\Backend\Form\Element\MfaInfoElement
Definition: MfaInfoElement.php:37
‪TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry
Definition: MfaProviderRegistry.php:28