]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Change the way to enable 2FA
authorJeremy Benoist <jeremy.benoist@gmail.com>
Fri, 18 Jan 2019 21:46:44 +0000 (22:46 +0100)
committerJeremy Benoist <jeremy.benoist@gmail.com>
Wed, 23 Jan 2019 12:28:24 +0000 (13:28 +0100)
And add a step to validate a generated code from the OTP app

20 files changed:
src/Wallabag/CoreBundle/Controller/ConfigController.php
src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml
src/Wallabag/CoreBundle/Resources/translations/messages.th.yml
src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/otp_app.html.twig [new file with mode: 0644]
src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/material/Config/otp_app.html.twig [new file with mode: 0644]
tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php

index c9fc570268c7fc09c21e4413cc046b5525396b3d..2643eed039298d996ff5ebfe90bcb9fc40ed250e 100644 (file)
@@ -81,28 +81,7 @@ class ConfigController extends Controller
         ]);
         $userForm->handleRequest($request);
 
-        // `googleTwoFactor` isn't a field within the User entity, we need to define it's value in a different way
-        if ($this->getParameter('twofactor_auth') && true === $user->isGoogleAuthenticatorEnabled() && false === $userForm->isSubmitted()) {
-            $userForm->get('googleTwoFactor')->setData(true);
-        }
-
         if ($userForm->isSubmitted() && $userForm->isValid()) {
-            // handle creation / reset of the OTP secret if checkbox changed from the previous state
-            if ($this->getParameter('twofactor_auth')) {
-                if (true === $userForm->get('googleTwoFactor')->getData() && false === $user->isGoogleAuthenticatorEnabled()) {
-                    $secret = $this->get('scheb_two_factor.security.google_authenticator')->generateSecret();
-
-                    $user->setGoogleAuthenticatorSecret($secret);
-                    $user->setEmailTwoFactor(false);
-                    $user->setBackupCodes((new BackupCodes())->toArray());
-
-                    $this->addFlash('OtpQrCode', $this->get('scheb_two_factor.security.google_authenticator')->getQRContent($user));
-                } elseif (false === $userForm->get('googleTwoFactor')->getData() && true === $user->isGoogleAuthenticatorEnabled()) {
-                    $user->setGoogleAuthenticatorSecret(null);
-                    $user->setBackupCodes(null);
-                }
-            }
-
             $userManager->updateUser($user, true);
 
             $this->addFlash(
@@ -175,11 +154,118 @@ class ConfigController extends Controller
             ],
             'twofactor_auth' => $this->getParameter('twofactor_auth'),
             'wallabag_url' => $this->getParameter('domain_name'),
-            'enabled_users' => $this->get('wallabag_user.user_repository')
-                ->getSumEnabledUsers(),
+            'enabled_users' => $this->get('wallabag_user.user_repository')->getSumEnabledUsers(),
         ]);
     }
 
+    /**
+     * Enable 2FA using email.
+     *
+     * @param Request $request
+     *
+     * @Route("/config/otp/email", name="config_otp_email")
+     */
+    public function otpEmailAction(Request $request)
+    {
+        if (!$this->getParameter('twofactor_auth')) {
+            return $this->createNotFoundException('two_factor not enabled');
+        }
+
+        $user = $this->getUser();
+
+        $user->setGoogleAuthenticatorSecret(null);
+        $user->setBackupCodes(null);
+        $user->setEmailTwoFactor(true);
+
+        $this->container->get('fos_user.user_manager')->updateUser($user, true);
+
+        $this->addFlash(
+            'notice',
+            'flashes.config.notice.otp_enabled'
+        );
+
+        return $this->redirect($this->generateUrl('config') . '#set3');
+    }
+
+    /**
+     * Enable 2FA using OTP app, user will need to confirm the generated code from the app.
+     *
+     * @Route("/config/otp/app", name="config_otp_app")
+     */
+    public function otpAppAction()
+    {
+        if (!$this->getParameter('twofactor_auth')) {
+            return $this->createNotFoundException('two_factor not enabled');
+        }
+
+        $user = $this->getUser();
+
+        if (!$user->isGoogleTwoFactor()) {
+            $secret = $this->get('scheb_two_factor.security.google_authenticator')->generateSecret();
+
+            $user->setGoogleAuthenticatorSecret($secret);
+            $user->setEmailTwoFactor(false);
+            $user->setBackupCodes((new BackupCodes())->toArray());
+
+            $this->container->get('fos_user.user_manager')->updateUser($user, true);
+        }
+
+        return $this->render('WallabagCoreBundle:Config:otp_app.html.twig', [
+            'qr_code' => $this->get('scheb_two_factor.security.google_authenticator')->getQRContent($user),
+        ]);
+    }
+
+    /**
+     * Cancelling 2FA using OTP app.
+     *
+     * @Route("/config/otp/app/cancel", name="config_otp_app_cancel")
+     */
+    public function otpAppCancelAction()
+    {
+        if (!$this->getParameter('twofactor_auth')) {
+            return $this->createNotFoundException('two_factor not enabled');
+        }
+
+        $user = $this->getUser();
+        $user->setGoogleAuthenticatorSecret(null);
+        $user->setBackupCodes(null);
+
+        $this->container->get('fos_user.user_manager')->updateUser($user, true);
+
+        return $this->redirect($this->generateUrl('config') . '#set3');
+    }
+
+    /**
+     * Validate OTP code.
+     *
+     * @param Request $request
+     *
+     * @Route("/config/otp/app/check", name="config_otp_app_check")
+     */
+    public function otpAppCheckAction(Request $request)
+    {
+        $isValid = $this->get('scheb_two_factor.security.google_authenticator')->checkCode(
+            $this->getUser(),
+            $request->get('_auth_code')
+        );
+
+        if (true === $isValid) {
+            $this->addFlash(
+                'notice',
+                'flashes.config.notice.otp_enabled'
+            );
+
+            return $this->redirect($this->generateUrl('config') . '#set3');
+        }
+
+        $this->addFlash(
+            'two_factor',
+            'scheb_two_factor.code_invalid'
+        );
+
+        return $this->redirect($this->generateUrl('config_otp_app'));
+    }
+
     /**
      * @param Request $request
      *
index ae8f8695dacfe02a7eb1bdbef44bb89dd4571c22..454f547dee58fd2d6baf88f7214d5d4b9a654b5e 100644 (file)
@@ -102,12 +102,16 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Navn'
         email_label: 'Emailadresse'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        two_factor:
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             # title: Delete my account (a.k.a danger zone)
             # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
@@ -165,6 +169,15 @@ config:
         #         and: 'One rule AND another'
         #         matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
         #         notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     # default_title: 'Title of the entry'
index 7b66e5dcc0f4f472043e3dfcb24c3d5e8bd256ac..dc1d4723f65f9d4380c58eebe170b7901a8d5b11 100644 (file)
@@ -102,12 +102,16 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Name'
         email_label: 'E-Mail-Adresse'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        two_factor:
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: 'Lösche mein Konto (a.k.a Gefahrenzone)'
             description: 'Wenn du dein Konto löschst, werden ALL deine Artikel, ALL deine Tags, ALL deine Anmerkungen und dein Konto dauerhaft gelöscht (kann NICHT RÜCKGÄNGIG gemacht werden). Du wirst anschließend ausgeloggt.'
index 567584b2d7430617bba8d00d958e6656e5d2a270..45145c8069061d3400822136f6b8d760e0e4b8f8 100644 (file)
@@ -102,12 +102,16 @@ config:
         two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Name'
         email_label: 'Email'
-        emailTwoFactor_label: 'Using email (receive a code by email)'
-        googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        two_factor_code_description_3: 'Or use that code:'
-        two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        two_factor:
+            emailTwoFactor_label: 'Using email (receive a code by email)'
+            googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            table_method: Method
+            table_state: State
+            table_action: Action
+            state_enabled: Enabled
+            state_disabled: Disabled
+            action_email: Use email
+            action_app: Use OTP App
         delete:
             title: Delete my account (a.k.a danger zone)
             description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
@@ -165,6 +169,15 @@ config:
                 and: 'One rule AND another'
                 matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
                 notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        page_title: Two-factor authentication
+        app:
+            two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+            two_factor_code_description_2: 'You can scan that QR Code with your app:'
+            two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            two_factor_code_description_4: 'Test an OTP code from your configured app:'
+            cancel: Cancel
+            enable: Enable
 
 entry:
     default_title: 'Title of the entry'
@@ -584,6 +597,7 @@ flashes:
             tags_reset: Tags reset
             entries_reset: Entries reset
             archived_reset: Archived entries deleted
+            otp_enabled: Two-factor authentication enabled
     entry:
         notice:
             entry_already_saved: 'Entry already saved on %date%'
index 1ba4bce4e6a15a01f500ca40e13999ce4b3b37ab..c1047e55a728849c3a7396a1676f8be2f1d93672 100644 (file)
@@ -102,12 +102,16 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Nombre'
         email_label: 'Dirección de e-mail'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        two_factor:
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: Eliminar mi cuenta (Zona peligrosa)
             description: Si eliminas tu cuenta, TODOS tus artículos, TODAS tus etiquetas, TODAS tus anotaciones y tu cuenta serán eliminadas de forma PERMANENTE (no se puede deshacer). Después serás desconectado.
@@ -165,6 +169,15 @@ config:
                 and: 'Una regla Y la otra'
                 matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>'
                 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: 'Título del artículo'
index d20c89d90b2bc0a3104f92d22227a4cd66554209..3042de2ef01b1633aa56f352e52860cf3d8a1cfc 100644 (file)
@@ -102,12 +102,16 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'نام'
         email_label: 'نشانی ایمیل'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        two_factor:
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             # title: Delete my account (a.k.a danger zone)
             # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
@@ -165,6 +169,15 @@ config:
         #         and: 'One rule AND another'
         #         matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
         #         notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     # default_title: 'Title of the entry'
index fd405059eb4aa3d29b5cc4ea396f7e2bba895523..57740ba235042d9bf7ade683a2a2afa1d4161c29 100644 (file)
@@ -102,12 +102,16 @@ config:
         two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel OU que vous devriez utiliser une application de mot de passe à usage unique (comme Google Authenticator, Authy or FreeOTP) pour obtenir un code temporaire à chaque nouvelle connexion non approuvée. Vous ne pouvez pas choisir les deux options."
         name_label: "Nom"
         email_label: "Adresse courriel"
-        emailTwoFactor_label: 'En utlisant l’email (recevez un code par email)'
-        googleTwoFactor_label: 'En utilisant une application de mot de passe à usage unique (ouvrez l’app, comme Google Authenticator, Authy or FreeOTP, pour obtenir un mot de passe à usage unique)'
-        two_factor_code_description_1: Vous venez d’activer l’authentification double-facteur, ouvrez votre application OTP pour configurer la génération du mot de passe à usage unique. Ces informations disparaîtront après un rechargement de la page.
-        two_factor_code_description_2: 'Vous pouvez scanner le QR code avec votre application :'
-        two_factor_code_description_3: 'Ou utiliser le code suivant :'
-        two_factor_code_description_4: 'N’oubliez pas de sauvegarder ces codes de secours dans un endroit sûr, vous pourrez les utiliser si vous ne pouvez plus accéder à votre application OTP :'
+        two_factor:
+            emailTwoFactor_label: 'En utlisant l’email (recevez un code par email)'
+            googleTwoFactor_label: 'En utilisant une application de mot de passe à usage unique (ouvrez l’app, comme Google Authenticator, Authy or FreeOTP, pour obtenir un mot de passe à usage unique)'
+            table_method: Méthode
+            table_state: État
+            table_action: Action
+            state_enabled: Activé
+            state_disabled: Désactivé
+            action_email: Utiliser l'email
+            action_app: Utiliser une app OTP
         delete:
             title: "Supprimer mon compte (attention danger !)"
             description: "Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c’est IRRÉVERSIBLE). Vous serez ensuite déconnecté."
@@ -165,6 +169,15 @@ config:
                 and: "Une règle ET l’autre"
                 matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>"
                 notmatches: "Teste si un <i>sujet</i> ne correspond pas à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title notmatches \"football\"</code>"
+    otp:
+        page_title: Authentification double-facteur
+        app:
+            two_factor_code_description_1: Vous venez d’activer l’authentification double-facteur, ouvrez votre application OTP pour configurer la génération du mot de passe à usage unique. Ces informations disparaîtront après un rechargement de la page.
+            two_factor_code_description_2: 'Vous pouvez scanner le QR code avec votre application :'
+            two_factor_code_description_3: 'N’oubliez pas de sauvegarder ces codes de secours dans un endroit sûr, vous pourrez les utiliser si vous ne pouvez plus accéder à votre application OTP :'
+            two_factor_code_description_4: 'Testez un code généré par votre application OTP :'
+            cancel: Annuler
+            enable: Activer
 
 entry:
     default_title: "Titre de l’article"
@@ -585,6 +598,7 @@ flashes:
             tags_reset: "Tags supprimés"
             entries_reset: "Articles supprimés"
             archived_reset: "Articles archivés supprimés"
+            otp_enabled: "Authentification à double-facteur activée"
     entry:
         notice:
             entry_already_saved: "Article déjà sauvegardé le %date%"
index 333262312a4fc2bcfbb7f351d4d2c4fb770a57f7..274e5338a50f44967bbb9d245707b02ce14f1712 100644 (file)
@@ -102,12 +102,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Nome'
         email_label: 'E-mail'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: Cancella il mio account (zona pericolosa)
             description: Rimuovendo il tuo account, TUTTI i tuoi articoli, TUTTE le tue etichette, TUTTE le tue annotazioni ed il tuo account verranno rimossi PERMANENTEMENTE (impossibile da ANNULLARE). Verrai poi disconnesso.
@@ -165,6 +168,15 @@ config:
                 and: "Una regola E un'altra"
                 matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>'
                 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: "Titolo del contenuto"
index 599490e1a09f0850dce90303b6566b23659a2236..4e5370f9884513d311326bd2a3ffcbb5f962961e 100644 (file)
@@ -102,12 +102,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Nom'
         email_label: 'Adreça de corrièl'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: Suprimir mon compte (Mèfi zòna perilhosa)
             description: Se confirmatz la supression de vòstre compte, TOTES vòstres articles, TOTAS vòstras etiquetas, TOTAS vòstras anotacions e vòstre compte seràn suprimits per totjorn. E aquò es IRREVERSIBLE. Puèi seretz desconnectat.
@@ -165,6 +168,15 @@ config:
                 and: "Una règla E l'autra"
                 matches: 'Teste se un <i>subjècte</i> correspond a una <i>recèrca</i> (non sensibla a la cassa).<br />Exemple : <code>title matches \"football\"</code>'
                 notmatches: 'Teste se <i>subjècte</i> correspond pas a una <i>recèrca</i> (sensibla a la cassa).<br />Example : <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: "Títol de l'article"
index 89fd34dcd09282ee5629e9564f77305b8ffe0b5a..a7a4d6c39243a261120c0ea07a977fa70acca387 100644 (file)
@@ -99,15 +99,18 @@ config:
             all: 'Wszystkie'
         rss_limit: 'Link do RSS'
     form_user:
-        two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
+        two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Nazwa'
         email_label: 'Adres email'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: Usuń moje konto (niebezpieczna strefa !)
             description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany.
@@ -165,6 +168,15 @@ config:
                 and: 'Jedna reguła I inna'
                 matches: 'Sprawdź czy <i>temat</i> pasuje <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł zawiera "piłka nożna"</code>'
                 notmatches: 'Sprawdź czy <i>temat</i> nie zawiera <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł nie zawiera "piłka nożna"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: 'Tytuł wpisu'
index f37aeb91f76e7b5d0f604e0d90c8e55767cc3814..a5483a6d3fbde2cb61e9d26927cbc6f707a22403 100644 (file)
@@ -102,12 +102,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Nome'
         email_label: 'E-mail'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             # title: Delete my account (a.k.a danger zone)
             # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
@@ -165,6 +168,15 @@ config:
                 and: 'Uma regra E outra'
                 matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>'
                 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: 'Título da entrada'
index c9d9500d21dd5e33101b967bafb0a6930bebc542..3b7fbd6917e134e44dad8db2790402fe308215a5 100644 (file)
@@ -102,12 +102,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Nume'
         email_label: 'E-mail'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             # title: Delete my account (a.k.a danger zone)
             # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
@@ -165,6 +168,15 @@ config:
         #         and: 'One rule AND another'
         #         matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
         #         notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     # default_title: 'Title of the entry'
index 62a078d405618d1ab68b648184ed1a37d38253e6..9274663140464d222ab1a4b11c0d9f2c4da4a582 100644 (file)
@@ -99,12 +99,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'Имя'
         email_label: 'Email'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: "Удалить мой аккаунт (или опасная зона)"
             description: "Если Вы удалите ваш аккаунт, ВСЕ ваши записи, теги и другие данные, будут БЕЗВОЗВРАТНО удалены (операция не может быть отменена после). Затем Вы выйдете из системы."
@@ -160,6 +163,15 @@ config:
                 or: 'Одно правило ИЛИ другое'
                 and: 'Одно правило И другое'
                 matches: 'Тесты, в которых <i> тема </i> соответствует <i> поиску </i> (без учета регистра). Пример: <code> title matches "футбол" </code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: 'Название записи'
index 78b5727a06466c142ccf611b1b110e890c1a2cf4..1fe4fa0ea51ae045cc7eda1460d86adc8a92cddd 100644 (file)
@@ -102,12 +102,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'ชื่อ'
         email_label: 'อีเมล'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             title: ลบบัญชีของฉัน (โซนที่เป็นภัย!)
             description: ถ้าคุณลบบัญชีของคุณIf , รายการทั้งหมดของคุณ, แท็กทั้งหมดของคุณ, หมายเหตุทั้งหมดของคุณและบัญชีของคุณจะถูกลบอย่างถาวร (มันไม่สามารถยกเลิกได้) คุณจะต้องลงชื่อออก
@@ -165,6 +168,15 @@ config:
                 and: 'หนึ่งข้อบังคับและอื่นๆ'
                 matches: 'ทดสอบว่า <i>เรื่อง</i> นี้ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อที่ตรงกับ "football"</code>'
                 notmatches: 'ทดสอบว่า <i>เรื่อง</i> นี้ไม่ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อทีไม่ตรงกับ "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: 'หัวข้อรายการ'
index 9f4c01f7965c260edb46e3d5904a6a345fd9e9b3..3b8a0d599948ece20605550b2f7f5519d48efcf2 100644 (file)
@@ -102,12 +102,15 @@ config:
         # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
         name_label: 'İsim'
         email_label: 'E-posta'
-        # emailTwoFactor_label: 'Using email (receive a code by email)'
-        # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
-        # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
-        # two_factor_code_description_2: 'You can scan that QR Code with your app:'
-        # two_factor_code_description_3: 'Or use that code:'
-        # two_factor_code_description_4: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+            # emailTwoFactor_label: 'Using email (receive a code by email)'
+            # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
+            # table_method: Method
+            # table_state: State
+            # table_action: Action
+            # state_enabled: Enabled
+            # state_disabled: Disabled
+            # action_email: Use email
+            # action_app: Use OTP App
         delete:
             # title: Delete my account (a.k.a danger zone)
             # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
@@ -165,6 +168,15 @@ config:
                 and: 'Bir kural ve diğeri'
                 # matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
                 # notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
+    otp:
+        # page_title: Two-factor authentication
+        # app:
+        #     two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
+        #     two_factor_code_description_2: 'You can scan that QR Code with your app:'
+        #     two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
+        #     two_factor_code_description_4: 'Test an OTP code from your configured app:'
+        #     cancel: Cancel
+        #     enable: Enable
 
 entry:
     default_title: 'Makalenin başlığı'
index cf4394081b867875bacdd35027903bd1d61a8bc8..93f8ddf8ace6fd319e8031e13389e92283a5c883 100644 (file)
             </div>
         </fieldset>
 
+        {{ form_widget(form.user.save) }}
+
         {% if twofactor_auth %}
+        <h5>{{ 'config.otp.page_title'|trans }}</h5>
+
         <div class="row">
             {{ 'config.form_user.two_factor_description'|trans }}
         </div>
 
-        <fieldset class="w500p inline">
-            <div class="row">
-                {{ form_label(form.user.emailTwoFactor) }}
-                {{ form_errors(form.user.emailTwoFactor) }}
-                {{ form_widget(form.user.emailTwoFactor) }}
-            </div>
-            <br/>
-            <div class="row">
-                {{ form_label(form.user.googleTwoFactor) }}
-                {{ form_widget(form.user.googleTwoFactor) }}
-                {{ form_errors(form.user.googleTwoFactor) }}
-            </div>
-            {% for OtpQrCode in app.session.flashbag.get('OtpQrCode') %}
-                <div class="row">
-                    {{ 'config.form_user.two_factor_code_description_1'|trans }}
-                    <br/>
-                    {{ 'config.form_user.two_factor_code_description_2'|trans }}
-                    <br/><br/>
-                    <img id="2faQrcode" class="hide-on-med-and-down" />
-                    <script>
-                        document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ OtpQrCode }}');
-                    </script>
-                    <br/><br/>
-                    {{ 'config.form_user.two_factor_code_description_3'|trans }}
-                    <br/><br/>
-                    <strong>{{ app.user.getGoogleAuthenticatorSecret }}</strong>
-                    <br/><br/>
-                    {{ 'config.form_user.two_factor_code_description_4'|trans }}
-                    <br/><br/>
-                    <strong>{{ app.user.getBackupCodes|join("\n")|nl2br }}</strong>
-                </div>
-            {% endfor %}
-        </fieldset>
+        <table>
+            <thead>
+                <tr>
+                    <th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
+                    <th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
+                    <th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
+                </tr>
+            </thead>
+
+            <tbody>
+                <tr>
+                    <td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
+                    <td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
+                    <td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a></td>
+                </tr>
+                <tr>
+                    <td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
+                    <td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
+                    <td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a></td>
+                </tr>
+            </tbody>
+        </table>
+
         {% endif %}
 
         {{ form_widget(form.user._token) }}
-        {{ form_widget(form.user.save) }}
     </form>
 
     {% if enabled_users > 1 %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/otp_app.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/otp_app.html.twig
new file mode 100644 (file)
index 0000000..2e4442e
--- /dev/null
@@ -0,0 +1,55 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'config.page_title'|trans }} > {{ 'config.otp.page_title'|trans }}{% endblock %}
+
+{% block content %}
+    <h5>{{ 'config.otp.page_title'|trans }}</h5>
+
+    <ol>
+        <li>
+            <p>{{ 'config.otp.app.two_factor_code_description_1'|trans }}</p>
+            <p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p>
+
+            <p>
+                <img id="2faQrcode" class="hide-on-med-and-down" />
+                <script>
+                    document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ qr_code }}');
+                </script>
+            </p>
+        </li>
+        <li>
+            <p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
+
+            <p><strong>{{ app.user.getBackupCodes|join("\n")|nl2br }}</strong></p>
+        </li>
+        <li>
+            <p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>
+
+            {% for flashMessage in app.session.flashbag.get("two_factor") %}
+            <div class="card-panel red darken-1 black-text">
+                {{ flashMessage|trans }}
+            </div>
+            {% endfor %}
+
+            <form class="form" action="{{ path("config_otp_app_check") }}" method="post">
+                <div class="card-content">
+                    <div class="row">
+                        <div class="input-field col s12">
+                            <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
+                            <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
+                        </div>
+                    </div>
+                </div>
+                <div class="card-action">
+                    <a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn">
+                        {{ 'config.otp.app.cancel'|trans }}
+                    </a>
+                    <button class="btn waves-effect waves-light" type="submit" name="send">
+                        {{ 'config.otp.app.enable'|trans }}
+                        <i class="material-icons right">send</i>
+                    </button>
+                </div>
+            </form>
+        </li>
+    </ol>
+{% endblock %}
index 5b00eb7bd1e011cf61c4c00f3d69f2fee3c59484..412c18f49f3bdac46dba42d4fe52df54aa8ec2e6 100644 (file)
                                 </div>
                             </div>
 
+                            {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
+
                             {% if twofactor_auth %}
+                                <br/>
+                                <br/>
                                 <div class="row">
-                                    {{ 'config.form_user.two_factor_description'|trans }}
-
-                                    <div class="input-field col s11">
-                                        {{ form_widget(form.user.emailTwoFactor) }}
-                                        {{ form_label(form.user.emailTwoFactor) }}
-                                        {{ form_errors(form.user.emailTwoFactor) }}
-                                    </div>
-                                    <div class="input-field col s11">
-                                        {{ form_widget(form.user.googleTwoFactor) }}
-                                        {{ form_label(form.user.googleTwoFactor) }}
-                                        {{ form_errors(form.user.googleTwoFactor) }}
-                                    </div>
+                                    <h5>{{ 'config.otp.page_title'|trans }}</h5>
+
+                                    <p>{{ 'config.form_user.two_factor_description'|trans }}</p>
+
+                                    <table>
+                                        <thead>
+                                            <tr>
+                                                <th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
+                                                <th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
+                                                <th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
+                                            </tr>
+                                        </thead>
+
+                                        <tbody>
+                                            <tr>
+                                                <td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
+                                                <td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
+                                                <td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a></td>
+                                            </tr>
+                                            <tr>
+                                                <td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
+                                                <td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
+                                                <td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a></td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
                                 </div>
-
-                                {% for OtpQrCode in app.session.flashbag.get('OtpQrCode') %}
-                                    <div class="card-panel yellow darken-1 black-text">
-                                        {{ 'config.form_user.two_factor_code_description_1'|trans }}
-                                        <br/>
-                                        {{ 'config.form_user.two_factor_code_description_2'|trans }}
-                                        <br/><br/>
-                                        <img id="2faQrcode" class="hide-on-med-and-down" />
-                                        <script>
-                                            document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ OtpQrCode }}');
-                                        </script>
-                                        <br/><br/>
-                                        {{ 'config.form_user.two_factor_code_description_3'|trans }}
-                                        <br/><br/>
-                                        <strong>{{ app.user.getGoogleAuthenticatorSecret }}</strong>
-                                        <br/><br/>
-                                        {{ 'config.form_user.two_factor_code_description_4'|trans }}
-                                        <br/><br/>
-                                        <strong>{{ app.user.getBackupCodes|join("\n")|nl2br }}</strong>
-                                    </div>
-                                {% endfor %}
                             {% endif %}
-
-                            {{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
                             {{ form_widget(form.user._token) }}
                         </form>
                     </div>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/otp_app.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/otp_app.html.twig
new file mode 100644 (file)
index 0000000..6aef355
--- /dev/null
@@ -0,0 +1,63 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'config.page_title'|trans }} > {{ 'config.otp.page_title'|trans }}{% endblock %}
+
+{% block content %}
+    <div class="row">
+        <div class="col s12">
+            <div class="card-panel settings">
+                <div class="row">
+                    <h5>{{ 'config.otp.page_title'|trans }}</h5>
+
+                    <ol>
+                        <li>
+                            <p>{{ 'config.otp.app.two_factor_code_description_1'|trans }}</p>
+                            <p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p>
+
+                            <p>
+                                <img id="2faQrcode" class="hide-on-med-and-down" />
+                                <script>
+                                    document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ qr_code }}');
+                                </script>
+                            </p>
+                        </li>
+                        <li>
+                            <p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
+
+                            <p><strong>{{ app.user.getBackupCodes|join("\n")|nl2br }}</strong></p>
+                        </li>
+                        <li>
+                            <p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>
+
+                            {% for flashMessage in app.session.flashbag.get("two_factor") %}
+                            <div class="card-panel red darken-1 black-text">
+                                {{ flashMessage|trans }}
+                            </div>
+                            {% endfor %}
+
+                            <form class="form" action="{{ path("config_otp_app_check") }}" method="post">
+                                <div class="card-content">
+                                    <div class="row">
+                                        <div class="input-field col s12">
+                                            <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
+                                            <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="card-action">
+                                    <a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn">
+                                        {{ 'config.otp.app.cancel'|trans }}
+                                    </a>
+                                    <button class="btn waves-effect waves-light" type="submit" name="send">
+                                        {{ 'config.otp.app.enable'|trans }}
+                                        <i class="material-icons right">send</i>
+                                    </button>
+                                </div>
+                            </form>
+                        </li>
+                    </ol>
+                </div>
+            </div>
+        </div>
+    </div>
+{% endblock %}
index 9ca52c643330abe35346f3196d5e8e444a3df767..1090a686bdd1ea1e2158755af568974f27e82e8f 100644 (file)
@@ -297,119 +297,6 @@ class ConfigControllerTest extends WallabagCoreTestCase
         $this->assertContains('flashes.config.notice.user_updated', $alert[0]);
     }
 
-    public function testUserEnable2faEmail()
-    {
-        $this->logInAs('admin');
-        $client = $this->getClient();
-
-        $crawler = $client->request('GET', '/config');
-
-        $this->assertSame(200, $client->getResponse()->getStatusCode());
-
-        $form = $crawler->filter('button[id=update_user_save]')->form();
-
-        $data = [
-            'update_user[emailTwoFactor]' => '1',
-        ];
-
-        $client->submit($form, $data);
-
-        $this->assertSame(302, $client->getResponse()->getStatusCode());
-
-        $crawler = $client->followRedirect();
-
-        $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.user_updated', $alert[0]);
-
-        // restore user
-        $em = $this->getEntityManager();
-        $user = $em
-            ->getRepository('WallabagUserBundle:User')
-            ->findOneByUsername('admin');
-
-        $this->assertTrue($user->isEmailTwoFactor());
-
-        $user->setEmailTwoFactor(false);
-        $em->persist($user);
-        $em->flush();
-    }
-
-    public function testUserEnable2faGoogle()
-    {
-        $this->logInAs('admin');
-        $client = $this->getClient();
-
-        $crawler = $client->request('GET', '/config');
-
-        $this->assertSame(200, $client->getResponse()->getStatusCode());
-
-        $form = $crawler->filter('button[id=update_user_save]')->form();
-
-        $data = [
-            'update_user[googleTwoFactor]' => '1',
-        ];
-
-        $client->submit($form, $data);
-
-        $this->assertSame(302, $client->getResponse()->getStatusCode());
-
-        $crawler = $client->followRedirect();
-
-        $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.user_updated', $alert[0]);
-
-        // restore user
-        $em = $this->getEntityManager();
-        $user = $em
-            ->getRepository('WallabagUserBundle:User')
-            ->findOneByUsername('admin');
-
-        $this->assertTrue($user->isGoogleAuthenticatorEnabled());
-
-        $user->setGoogleAuthenticatorSecret(null);
-        $em->persist($user);
-        $em->flush();
-    }
-
-    public function testUserEnable2faBoth()
-    {
-        $this->logInAs('admin');
-        $client = $this->getClient();
-
-        $crawler = $client->request('GET', '/config');
-
-        $this->assertSame(200, $client->getResponse()->getStatusCode());
-
-        $form = $crawler->filter('button[id=update_user_save]')->form();
-
-        $data = [
-            'update_user[googleTwoFactor]' => '1',
-            'update_user[emailTwoFactor]' => '1',
-        ];
-
-        $client->submit($form, $data);
-
-        $this->assertSame(302, $client->getResponse()->getStatusCode());
-
-        $crawler = $client->followRedirect();
-
-        $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.user_updated', $alert[0]);
-
-        // restore user
-        $em = $this->getEntityManager();
-        $user = $em
-            ->getRepository('WallabagUserBundle:User')
-            ->findOneByUsername('admin');
-
-        $this->assertTrue($user->isGoogleAuthenticatorEnabled());
-        $this->assertFalse($user->isEmailTwoFactor());
-
-        $user->setGoogleAuthenticatorSecret(null);
-        $em->persist($user);
-        $em->flush();
-    }
-
     public function testRssUpdateResetToken()
     {
         $this->logInAs('admin');
@@ -1113,4 +1000,85 @@ class ConfigControllerTest extends WallabagCoreTestCase
         $this->assertNotSame('yuyuyuyu', $client->getRequest()->getLocale());
         $this->assertNotSame('yuyuyuyu', $client->getContainer()->get('session')->get('_locale'));
     }
+
+    public function testUserEnable2faEmail()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/config/otp/email');
+
+        $this->assertSame(302, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->followRedirect();
+
+        $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
+        $this->assertContains('flashes.config.notice.otp_enabled', $alert[0]);
+
+        // restore user
+        $em = $this->getEntityManager();
+        $user = $em
+            ->getRepository('WallabagUserBundle:User')
+            ->findOneByUsername('admin');
+
+        $this->assertTrue($user->isEmailTwoFactor());
+
+        $user->setEmailTwoFactor(false);
+        $em->persist($user);
+        $em->flush();
+    }
+
+    public function testUserEnable2faGoogle()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/config/otp/app');
+
+        $this->assertSame(200, $client->getResponse()->getStatusCode());
+
+        // restore user
+        $em = $this->getEntityManager();
+        $user = $em
+            ->getRepository('WallabagUserBundle:User')
+            ->findOneByUsername('admin');
+
+        $this->assertTrue($user->isGoogleTwoFactor());
+        $this->assertGreaterThan(0, $user->getBackupCodes());
+
+        $user->setGoogleAuthenticatorSecret(false);
+        $user->setBackupCodes(null);
+        $em->persist($user);
+        $em->flush();
+    }
+
+    public function testUserEnable2faGoogleCancel()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/config/otp/app');
+
+        $this->assertSame(200, $client->getResponse()->getStatusCode());
+
+        // restore user
+        $em = $this->getEntityManager();
+        $user = $em
+            ->getRepository('WallabagUserBundle:User')
+            ->findOneByUsername('admin');
+
+        $this->assertTrue($user->isGoogleTwoFactor());
+        $this->assertGreaterThan(0, $user->getBackupCodes());
+
+        $crawler = $client->request('GET', '/config/otp/app/cancel');
+
+        $this->assertSame(302, $client->getResponse()->getStatusCode());
+
+        $user = $em
+            ->getRepository('WallabagUserBundle:User')
+            ->findOneByUsername('admin');
+
+        $this->assertFalse($user->isGoogleTwoFactor());
+        $this->assertEmpty($user->getBackupCodes());
+    }
 }