diff --git a/assets/ts_src/event_listeners.ts b/assets/ts_src/event_listeners.ts index 91e82f96..9b202ec7 100644 --- a/assets/ts_src/event_listeners.ts +++ b/assets/ts_src/event_listeners.ts @@ -185,7 +185,7 @@ $(document).on("ajaxUI:start ajaxUI:reload", function() { }); $(document).on("ajaxUI:start ajaxUI:reload", function() { - $("[data-delete-form]").unbind('submit').submit(function(event) { + $("[data-delete-form]").unbind('submit').submit(function (event) { event.preventDefault(); let form = this; @@ -197,17 +197,38 @@ $(document).on("ajaxUI:start ajaxUI:reload", function() { let message = $(this).data("message"); bootbox.confirm({ - message: message, - title: title, - callback: function(result) { + message: message, title: title, callback: function (result) { //If the dialog was confirmed, then submit the form. - if(result) { + if (result) { ajaxUI.submitForm(form, btn); } - }}); + } + }); return false; }); + + //Register for forms with delete-buttons + $("[data-delete-btn]").parents('form').unbind('submit').submit(function (event) { + event.preventDefault(); + let form = this; + //Get the submit button + let btn = document.activeElement; + + let title = $(btn).data("title"); + let message = $(btn).data("message"); + + bootbox.confirm({ + message: message, title: title, callback: function (result) { + //If the dialog was confirmed, then submit the form. + if (result) { + ajaxUI.submitForm(form, btn); + } + } + }); + + }); + }); $(document).on("ajaxUI:start ajaxUI:reload", function() { diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 78ff39d4..775493c9 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -67,6 +67,29 @@ class UserController extends AdminPages\BaseAdminController */ public function edit(User $entity, Request $request, EntityManagerInterface $em) { + //Handle 2FA disabling + + if($request->request->has('reset_2fa')) { + //Check if the admin has the needed permissions + $this->denyAccessUnlessGranted('set_password', $entity); + if ($this->isCsrfTokenValid('reset_2fa'.$entity->getId(), $request->request->get('_token'))) { + //Disable Google authenticator + $entity->setGoogleAuthenticatorSecret(null); + $entity->setBackupCodes([]); + //Remove all U2F keys + foreach($entity->getU2FKeys() as $key) { + $em->remove($key); + } + //Invalidate trusted devices + $entity->invalidateTrustedDeviceTokens(); + $em->flush(); + + $this->addFlash('success', 'user.edit.reset_success'); + } else { + $this->addFlash('danger', 'csfr_invalid'); + } + } + return $this->_edit($entity, $request, $em); } diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 3249784d..02266dd5 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -33,6 +33,7 @@ use App\Services\MoneyFormatter; use App\Services\SIFormatter; use App\Services\TreeBuilder; use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; @@ -49,13 +50,14 @@ class AppExtension extends AbstractExtension protected $amountFormatter; protected $attachmentURLGenerator; protected $FAIconGenerator; + protected $translator; public function __construct(EntityURLGenerator $entityURLGenerator, MarkdownParser $markdownParser, - SerializerInterface $serializer, TreeBuilder $treeBuilder, - MoneyFormatter $moneyFormatter, - SIFormatter $SIFormatter, AmountFormatter $amountFormatter, - AttachmentURLGenerator $attachmentURLGenerator, - FAIconGenerator $FAIconGenerator) + SerializerInterface $serializer, TreeBuilder $treeBuilder, + MoneyFormatter $moneyFormatter, + SIFormatter $SIFormatter, AmountFormatter $amountFormatter, + AttachmentURLGenerator $attachmentURLGenerator, + FAIconGenerator $FAIconGenerator, TranslatorInterface $translator) { $this->entityURLGenerator = $entityURLGenerator; $this->markdownParser = $markdownParser; @@ -66,6 +68,7 @@ class AppExtension extends AbstractExtension $this->amountFormatter = $amountFormatter; $this->attachmentURLGenerator = $attachmentURLGenerator; $this->FAIconGenerator = $FAIconGenerator; + $this->translator = $translator; } public function getFilters() diff --git a/templates/AdminPages/UserAdmin.html.twig b/templates/AdminPages/UserAdmin.html.twig index 41a89232..60e82351 100644 --- a/templates/AdminPages/UserAdmin.html.twig +++ b/templates/AdminPages/UserAdmin.html.twig @@ -1,5 +1,9 @@ {% extends "AdminPages/EntityAdminBase.html.twig" %} +{% import "helper.twig" as helper %} + +{# @var entity \App\Entity\UserSystem\User #} + {% block card_title %} {% trans %}user.edit.caption{% endtrans %} {% endblock %} @@ -34,6 +38,42 @@ {{ form_row(form.new_password) }} {{ form_row(form.need_pw_change) }} {{ form_row(form.disabled) }} + + {% if entity.id is not null %} +
{% trans %}user.edit.tfa.google_active{% endtrans %}: {{ helper.boolean(entity.googleAuthenticatorEnabled) }}
+{% trans %}tfa_backup.remaining_tokens{% endtrans %}: {{ entity.backupCodes | length }}
+{% trans %}tfa_backup.generation_date{% endtrans %}: + {% if entity.backupCodesGenerationDate is not null %} + {{ entity.backupCodesGenerationDate | format_datetime }} + {% else %} + {% trans %}user.edit.tfa.disabled{% endtrans %} + {% endif %} +
+{% trans %}user.edit.tfa.u2f_keys_count{% endtrans %}: + {% if entity.u2FAuthEnabled %} + {{ entity.u2FKeys | length }} + {% else %} + {% trans %}user.edit.tfa.disabled{% endtrans %} + {% endif %} +
+ + {% set tfa_disable_disabled = not is_granted('set_password', entity) %} + {# Disable button when he has no 2FA activated #} + {% if not entity.u2FAuthEnabled and not entity.googleAuthenticatorEnabled and entity.backupCodes is empty %} + {% set tfa_disable_disabled = true %} + {% endif %} + + + +