From 6b5c4dabe43d0712b4c099c46458d2c646053586 Mon Sep 17 00:00:00 2001
From: Torben Hansen <derhansen@gmail.com>
Date: Wed, 28 Dec 2022 10:43:01 +0100
Subject: [PATCH] [FEATURE] Use password policy for new admin users created in
 ext:install

The password for a new administrative backend user created using the
install extension does now consider the configurable password policy
introduced in #97388

Resolves: #97392
Releases: main
Change-Id: I711071acdd7c8bcf10b04a1ca46b7d486c742f6e
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/77233
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: core-ci <typo3@b13.com>
---
 ...icyForNewAdminUsersCreatedInExtinstall.rst | 27 +++++++++++++++++++
 .../Controller/MaintenanceController.php      | 21 +++++++++++++--
 .../install/Classes/ServiceProvider.php       |  1 +
 .../Templates/Maintenance/CreateAdmin.html    | 15 ++++++-----
 4 files changed, 56 insertions(+), 8 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/12.2/Feature-97392-UsePasswordPolicyForNewAdminUsersCreatedInExtinstall.rst

diff --git a/typo3/sysext/core/Documentation/Changelog/12.2/Feature-97392-UsePasswordPolicyForNewAdminUsersCreatedInExtinstall.rst b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-97392-UsePasswordPolicyForNewAdminUsersCreatedInExtinstall.rst
new file mode 100644
index 000000000000..c08822e74d87
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-97392-UsePasswordPolicyForNewAdminUsersCreatedInExtinstall.rst
@@ -0,0 +1,27 @@
+.. include:: /Includes.rst.txt
+
+.. _feature-97392-1672220371:
+
+================================================================================
+Feature: #97392 - Use password policy for new admin users created in ext:install
+================================================================================
+
+See :issue:`97392`
+
+Description
+===========
+
+The password for a new administrative backend user created using the install
+extension does now consider the configurable password policy introduced in
+:ref:`#97388 <feature-97388>`.
+
+
+Impact
+======
+
+The globally configured password policy is now taken into account when a
+new administrative backend user is created using the install extension.
+Password policy requirements are shown below the password field and a message
+is shown, if the new password does not meet the password policy requirements.
+
+.. index:: Backend, ext:install
diff --git a/typo3/sysext/install/Classes/Controller/MaintenanceController.php b/typo3/sysext/install/Classes/Controller/MaintenanceController.php
index 7838cb844fea..88788fe6de0c 100644
--- a/typo3/sysext/install/Classes/Controller/MaintenanceController.php
+++ b/typo3/sysext/install/Classes/Controller/MaintenanceController.php
@@ -30,9 +30,13 @@ use TYPO3\CMS\Core\Database\Schema\SchemaMigrator;
 use TYPO3\CMS\Core\Database\Schema\SqlReader;
 use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
 use TYPO3\CMS\Core\Http\JsonResponse;
+use TYPO3\CMS\Core\Localization\LanguageServiceFactory;
 use TYPO3\CMS\Core\Localization\Locales;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
+use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction;
+use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator;
+use TYPO3\CMS\Core\PasswordPolicy\Validator\Dto\ContextData;
 use TYPO3\CMS\Core\Service\OpcodeCacheService;
 use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -48,15 +52,26 @@ use TYPO3\CMS\Install\Service\Typo3tempFileService;
  */
 class MaintenanceController extends AbstractController
 {
+    protected PasswordPolicyValidator $passwordPolicyValidator;
+
     public function __construct(
         private readonly LateBootService $lateBootService,
         private readonly ClearCacheService $clearCacheService,
         private readonly ConfigurationManager $configurationManager,
         private readonly PasswordHashFactory $passwordHashFactory,
         private readonly Locales $locales,
+        private readonly LanguageServiceFactory $languageServiceFactory,
         private readonly FormProtectionFactory $formProtectionFactory
     ) {
+        $GLOBALS['LANG'] = $this->languageServiceFactory->create('default');
+        $passwordPolicy = $GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] ?? 'default';
+        $this->passwordPolicyValidator = GeneralUtility::makeInstance(
+            PasswordPolicyValidator::class,
+            PasswordPolicyAction::NEW_USER_PASSWORD,
+            is_string($passwordPolicy) ? $passwordPolicy : ''
+        );
     }
+
     /**
      * Main "show the cards" view
      */
@@ -450,6 +465,7 @@ class MaintenanceController extends AbstractController
         $formProtection = $this->formProtectionFactory->createFromRequest($request);
         $view->assignMultiple([
             'createAdminToken' => $formProtection->generateToken('installTool', 'createAdmin'),
+            'passwordPolicyRequirements' => $this->passwordPolicyValidator->getRequirements(),
         ]);
         return new JsonResponse([
             'success' => true,
@@ -476,6 +492,7 @@ class MaintenanceController extends AbstractController
         $isSystemMaintainer = ((bool)$request->getParsedBody()['install']['userSystemMaintainer'] == '1') ? true : false;
 
         $messages = new FlashMessageQueue('install');
+        $contextData = new ContextData(newUsername: $username);
 
         if ($username === '') {
             $messages->enqueue(new FlashMessage(
@@ -489,9 +506,9 @@ class MaintenanceController extends AbstractController
                 'Administrator user not created',
                 ContextualFeedbackSeverity::ERROR
             ));
-        } elseif (strlen($password) < 8) {
+        } elseif (!$this->passwordPolicyValidator->isValidPassword($password, $contextData)) {
             $messages->enqueue(new FlashMessage(
-                'Password must be at least eight characters long.',
+                'The password does not meet the password policy requirements.',
                 'Administrator user not created',
                 ContextualFeedbackSeverity::ERROR
             ));
diff --git a/typo3/sysext/install/Classes/ServiceProvider.php b/typo3/sysext/install/Classes/ServiceProvider.php
index 2f0657bcd4b1..9b091f523246 100644
--- a/typo3/sysext/install/Classes/ServiceProvider.php
+++ b/typo3/sysext/install/Classes/ServiceProvider.php
@@ -287,6 +287,7 @@ class ServiceProvider extends AbstractServiceProvider
             $container->get(ConfigurationManager::class),
             $container->get(PasswordHashFactory::class),
             $container->get(Locales::class),
+            $container->get(LanguageServiceFactory::class),
             $container->get(FormProtectionFactory::class)
         );
     }
diff --git a/typo3/sysext/install/Resources/Private/Templates/Maintenance/CreateAdmin.html b/typo3/sysext/install/Resources/Private/Templates/Maintenance/CreateAdmin.html
index a9650125cd56..10f31bd91987 100644
--- a/typo3/sysext/install/Resources/Private/Templates/Maintenance/CreateAdmin.html
+++ b/typo3/sysext/install/Resources/Private/Templates/Maintenance/CreateAdmin.html
@@ -1,7 +1,7 @@
 <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
 
 <p>
-    After you've created the user, log in and add the rest of the user information, like email and real name.
+    After you've created the user, log in and add the rest of the user information, like real name.
 </p>
 
 <div class="t3js-module-content" data-create-admin-token="{createAdminToken}">
@@ -24,10 +24,15 @@
                 type="password"
                 autocomplete="off"
                 required
-                minlength="8"
-                pattern=".{8,}"
-                title="Password must be at least eight characters long."
             />
+            <f:if condition="{passwordPolicyRequirements}">
+                <p class="mt-2 mb-1 text-muted">The password must match the following requirements:</p>
+                <ul>
+                    <f:for each="{passwordPolicyRequirements}" as="requirement">
+                        <li class="text-muted">{requirement}</li>
+                    </f:for>
+                </ul>
+            </f:if>
         </div>
         <div class="form-group">
             <label for="t3-install-admin-password-repeat" class="control-label">Repeat password:</label>
@@ -37,8 +42,6 @@
                 type="password"
                 autocomplete="off"
                 required
-                minlength="8"
-                pattern=".{8,}"
             />
         </div>
         <div class="form-group">
-- 
GitLab