Add proper success messages for TOTP
authorTim Düsterhus <duesterhus@woltlab.com>
Fri, 13 Nov 2020 14:34:54 +0000 (15:34 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Mon, 16 Nov 2020 16:29:06 +0000 (17:29 +0100)
wcfsetup/install/files/lib/system/user/multifactor/TotpMultifactorMethod.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index d0be8faf7cac06f55e6812131bad13b4cfff8aff..5279a6d4f2dc59ea1e2c668c21e40acbee10ff19 100644 (file)
@@ -52,6 +52,18 @@ class TotpMultifactorMethod implements IMultifactorMethod {
         * @inheritDoc
         */
        public function createManagementForm(IFormDocument $form, ?Setup $setup, $returnData = null): void {
+               if ($returnData !== null) {
+                       \assert(\is_array($returnData));
+                       \assert(
+                               isset($returnData['action']) &&
+                               ($returnData['action'] === 'add' || $returnData['action'] === 'delete')
+                       );
+                       \assert(isset($returnData['deviceName']));
+                       $form->successMessage('wcf.user.security.multifactor.totp.success.'.$returnData['action'], [
+                               'deviceName' => $returnData['deviceName'],
+                       ]);
+               }
+
                $form->addDefaultButton(false);
                $newDeviceContainer = NewDeviceContainer::create()
                        ->label('wcf.user.security.multifactor.totp.newDevice')
@@ -136,7 +148,7 @@ class TotpMultifactorMethod implements IMultifactorMethod {
        /**
         * @inheritDoc
         */
-       public function processManagementForm(IFormDocument $form, Setup $setup): void {
+       public function processManagementForm(IFormDocument $form, Setup $setup): array {
                $formData = $form->getData();
                
                \assert(
@@ -145,6 +157,19 @@ class TotpMultifactorMethod implements IMultifactorMethod {
                );
                
                if (!empty($formData['delete'])) {
+                       // Fetch deviceName for success message.
+                       $sql = "SELECT  deviceName
+                               FROM    wcf".WCF_N."_user_multifactor_totp
+                               WHERE           setupID = ?
+                                       AND     deviceID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute([
+                               $setup->getId(),
+                               $formData['delete'],
+                       ]);
+                       $deviceName = $statement->fetchSingleColumn();
+                       
+                       // Remove the device.
                        $sql = "DELETE FROM     wcf".WCF_N."_user_multifactor_totp
                                WHERE           setupID = ?
                                        AND     deviceID = ?";
@@ -154,6 +179,7 @@ class TotpMultifactorMethod implements IMultifactorMethod {
                                $formData['delete'],
                        ]);
                        
+                       // Check the contract that the last device may not be removed.
                        $sql = "SELECT  COUNT(*)
                                FROM    wcf".WCF_N."_user_multifactor_totp
                                WHERE   setupID = ?";
@@ -165,9 +191,16 @@ class TotpMultifactorMethod implements IMultifactorMethod {
                        if (!$statement->fetchSingleColumn()) {
                                throw new \LogicException('Unreachable');
                        }
+                       
+                       return [
+                               'action' => 'delete',
+                               'deviceName' => $deviceName,
+                       ];
                }
                else {
                        $defaultName = WCF::getLanguage()->getDynamicVariable('wcf.user.security.multifactor.totp.deviceName.default');
+                       $deviceName = $formData['data']['deviceName'] ?: $defaultName;
+                       
                        $sql = "INSERT INTO     wcf".WCF_N."_user_multifactor_totp
                                                (setupID, deviceID, deviceName, secret, minCounter, createTime)
                                VALUES          (?, ?, ?, ?, ?, ?)";
@@ -175,11 +208,16 @@ class TotpMultifactorMethod implements IMultifactorMethod {
                        $statement->execute([
                                $setup->getId(),
                                Hex::encode(\random_bytes(16)),
-                               $formData['data']['deviceName'] ?: $defaultName,
+                               $deviceName,
                                $formData['data']['secret'],
                                $formData['data']['code']['minCounter'],
                                \TIME_NOW,
                        ]);
+                       
+                       return [
+                               'action' => 'add',
+                               'deviceName' => $deviceName,
+                       ];
                }
        }
        
index ee7e82bdb43c31e3d1860a7409ec2d749ed42f3c..7f237009245801f0629401b0fff2d71ab5039386 100644 (file)
@@ -4867,10 +4867,12 @@ Die E-Mail-Adresse des neuen Benutzers lautet: {@$user->email}
 <li>{if LANGUAGE_USE_INFORMAL_VARIANT}Scanne{else}Scannen Sie{/if} den QR-Code in der App.</li>
 <li>{if LANGUAGE_USE_INFORMAL_VARIANT}Gib{else}Geben Sie{/if} den durch die App generierten 6-stelligen Einmalcode ein.</li>
 </ol>]]></item>
+               <item name="wcf.user.security.multifactor.totp.success.add"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Dein{else}Ihr{/if} Smartphone <strong>{$deviceName}</strong> wurde erfolgreich hinterlegt.]]></item>
                <item name="wcf.user.security.multifactor.totp.createTime"><![CDATA[Eingerichtet]]></item>
                <item name="wcf.user.security.multifactor.totp.useTime"><![CDATA[Zuletzt Benutzt]]></item>
                <item name="wcf.user.security.multifactor.totp.lastDevice"><![CDATA[Wenn Sie ihr Smartphone wechseln möchten, fügen Sie bitte zunächst Ihr neues Smartphone hinzu, bevor Sie Ihr letztes Gerät <strong>{$deviceName}</strong> entfernen. Verwenden Sie bitte die <a href="{link controller='AccountSecurity'}{/link}">Übersicht in der Benutzerkonto-Sicherheit</a>, wenn Sie die Mehrfaktor-Authentifizierung deaktivieren möchten.]]></item>
                <item name="wcf.user.security.multifactor.totp.lastDevice.title"><![CDATA[Letztes Gerät]]></item>
+               <item name="wcf.user.security.multifactor.totp.success.delete"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Dein{else}Ihr{/if} Smartphone <strong>{$deviceName}</strong> wurde erfolgreich entfernt.]]></item>
        </category>
        <category name="wcf.user.trophy">
                <item name="wcf.user.trophy.trophyPoints"><![CDATA[Trophäen]]></item>
index 203dc377a8c92d759e9a218a5c67e35cbe1f0c2f..69aeb13db692a43005f92aa79815d53fc7c932d5 100644 (file)
@@ -4864,10 +4864,12 @@ Open the link below to access the user profile:
 <li>Scan the QR code within the app.</li>
 <li>Enter the 6 digit one time code generated by the app.</li>
 </ol>]]></item>
+               <item name="wcf.user.security.multifactor.totp.success.add"><![CDATA[Your smartphone <strong>{$deviceName}</strong> has successfully been added.]]></item>
                <item name="wcf.user.security.multifactor.totp.createTime"><![CDATA[Set Up]]></item>
                <item name="wcf.user.security.multifactor.totp.useTime"><![CDATA[Last Used]]></item>
                <item name="wcf.user.security.multifactor.totp.lastDevice"><![CDATA[Please add your new device before removing your last device <strong>{$deviceName}</strong> if you want to switch phones. Use the <a href="{link controller='AccountSecurity'}{/link}">Overview in Account Security</a> if you want to disable multi-factor authentication.]]></item>
                <item name="wcf.user.security.multifactor.totp.lastDevice.title"><![CDATA[Last Device]]></item>
+               <item name="wcf.user.security.multifactor.totp.success.delete"><![CDATA[Your smartphone <strong>{$deviceName}</strong> has successfully been removed.]]></item>
        </category>
        <category name="wcf.user.trophy">
                <item name="wcf.user.trophy.trophyPoints"><![CDATA[Trophies]]></item>