Merge pull request #4329 from wallabag/add-2fa-disable

Added a button to disable 2FA when enabled
This commit is contained in:
Nicolas Lœuillet 2020-04-14 19:59:54 +02:00 committed by GitHub
commit 35359a23c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 122 additions and 4 deletions

View file

@ -192,6 +192,30 @@ class ConfigController extends Controller
]);
}
/**
* Disable 2FA using email.
*
* @Route("/config/otp/email/disable", name="disable_otp_email")
*/
public function disableOtpEmailAction()
{
if (!$this->getParameter('twofactor_auth')) {
return $this->createNotFoundException('two_factor not enabled');
}
$user = $this->getUser();
$user->setEmailTwoFactor(false);
$this->container->get('fos_user.user_manager')->updateUser($user, true);
$this->addFlash(
'notice',
'flashes.config.notice.otp_disabled'
);
return $this->redirect($this->generateUrl('config') . '#set3');
}
/**
* Enable 2FA using email.
*
@ -219,6 +243,32 @@ class ConfigController extends Controller
return $this->redirect($this->generateUrl('config') . '#set3');
}
/**
* Disable 2FA using OTP app.
*
* @Route("/config/otp/app/disable", name="disable_otp_app")
*/
public function disableOtpAppAction()
{
if (!$this->getParameter('twofactor_auth')) {
return $this->createNotFoundException('two_factor not enabled');
}
$user = $this->getUser();
$user->setGoogleAuthenticatorSecret('');
$user->setBackupCodes(null);
$this->container->get('fos_user.user_manager')->updateUser($user, true);
$this->addFlash(
'notice',
'flashes.config.notice.otp_disabled'
);
return $this->redirect($this->generateUrl('config') . '#set3');
}
/**
* Enable 2FA using OTP app, user will need to confirm the generated code from the app.
*
@ -248,6 +298,11 @@ class ConfigController extends Controller
$this->container->get('fos_user.user_manager')->updateUser($user, true);
$this->addFlash(
'notice',
'flashes.config.notice.otp_enabled'
);
return $this->render('WallabagCoreBundle:Config:otp_app.html.twig', [
'backupCodes' => $backupCodes,
'qr_code' => $this->get('scheb_two_factor.security.google_authenticator')->getQRContent($user),

View file

@ -613,6 +613,7 @@ flashes:
# entries_reset: Entries reset
# archived_reset: Archived entries deleted
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Einträge zurücksetzen
archived_reset: Archiverte Einträge zurücksetzen
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Entries reset
archived_reset: Archived entries deleted
otp_enabled: Two-factor authentication enabled
otp_disabled: Two-factor authentication disabled
tagging_rules_imported: Tagging rules imported
tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Artículos reiniciados
archived_reset: Artículos archivados borrados
otp_enabled: Autenticación de dos pasos activada
# otp_disabled: Two-factor authentication disabled
tagging_rules_imported: Reglas de etiquetado importadas
tagging_rules_not_imported: Un error se ha producico en la importación de las reglas de etiquetado
entry:

View file

@ -613,6 +613,7 @@ flashes:
# entries_reset: Entries reset
# archived_reset: Archived entries deleted
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -614,6 +614,7 @@ flashes:
entries_reset: "Articles supprimés"
archived_reset: "Articles archivés supprimés"
otp_enabled: "Authentification à double-facteur activée"
otp_disabled: "Authentification à double-facteur désactivée"
tagging_rules_imported: Règles bien importées
tagging_rules_not_imported: Impossible d'importer les règles
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Reset articoli
# archived_reset: Archived entries deleted
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: 記事がリセットされました
archived_reset: アーカイブ済みの記事がリセットされました
otp_enabled: 2要素認証が有効化されました
# otp_disabled: Two-factor authentication disabled
tagging_rules_imported: タグ付けルールがインポートされました
tagging_rules_not_imported: タグ付けルールのインポート中にエラーが発生しました
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Articles levats
archived_reset: Articles archivat suprimits
otp_enabled: Autentificacion en dos temps activada
# otp_disabled: Two-factor authentication disabled
tagging_rules_imported: Règlas detiquetatge importadas
tagging_rules_not_imported: Error en important las règlas detiquetatge
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Zresetuj wpisy
archived_reset: Zarchiwizowane wpisy usunięte
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: Artigos reinicializados
archived_reset: Artigos arquivados apagados
otp_enabled: Autenticação de dois fatores ativada
# otp_disabled: Two-factor authentication disabled
tagging_rules_imported: Regras de tags importadas
tagging_rules_not_imported: Erro ao importar regras de tags
entry:

View file

@ -613,6 +613,7 @@ flashes:
# entries_reset: Entries reset
# archived_reset: Archived entries deleted
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: "Записи сброшены"
# archived_reset: Archived entries deleted
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: รีเซ็ตรายการ
archived_reset: การลบเอกสารของรายการ
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
# entries_reset: Entries reset
# archived_reset: Archived entries deleted
# otp_enabled: Two-factor authentication enabled
# otp_disabled: Two-factor authentication disabled
# tagging_rules_imported: Tagging rules imported
# tagging_rules_not_imported: Error while importing tagging rules
entry:

View file

@ -613,6 +613,7 @@ flashes:
entries_reset: 项目列表已重置
archived_reset: 所有存档项目已删除
otp_enabled: 两步验证已启用
# otp_disabled: Two-factor authentication disabled
tagging_rules_imported: 标签规则已导入
tagging_rules_not_imported: 导入标签规则时发生了错误
entry:

View file

@ -195,12 +195,12 @@
<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>
<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> {% if app.user.isEmailTwoFactor %}<a href="{{ path('disable_otp_email') }}" class="waves-effect waves-light btn">Disable</a>{% endif %}</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>
<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> {% if app.user.isGoogleTwoFactor %}<a href="{{ path('disable_otp_app') }}" class="waves-effect waves-light btn">Disable</a>{% endif %}</td>
</tr>
</tbody>
</table>

View file

@ -229,12 +229,12 @@
<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>
<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> {% if app.user.isEmailTwoFactor %}<a href="{{ path('disable_otp_email') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</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>
<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> {% if app.user.isGoogleTwoFactor %}<a href="{{ path('disable_otp_app') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
</tr>
</tbody>
</table>

View file

@ -1045,6 +1045,29 @@ class ConfigControllerTest extends WallabagCoreTestCase
$em->flush();
}
public function testUserDisable2faEmail()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/config/otp/email/disable');
$this->assertSame(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
$this->assertContains('flashes.config.notice.otp_disabled', $alert[0]);
// restore user
$em = $this->getEntityManager();
$user = $em
->getRepository('WallabagUserBundle:User')
->findOneByUsername('admin');
$this->assertFalse($user->isEmailTwoFactor());
}
public function testUserEnable2faGoogle()
{
$this->logInAs('admin');
@ -1099,6 +1122,30 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertEmpty($user->getBackupCodes());
}
public function testUserDisable2faGoogle()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/config/otp/app/disable');
$this->assertSame(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
$this->assertContains('flashes.config.notice.otp_disabled', $alert[0]);
// restore user
$em = $this->getEntityManager();
$user = $em
->getRepository('WallabagUserBundle:User')
->findOneByUsername('admin');
$this->assertEmpty($user->getGoogleAuthenticatorSecret());
$this->assertEmpty($user->getBackupCodes());
}
public function testExportTaggingRule()
{
$this->logInAs('admin');