Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix admin 2FA disable flow #3708

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions hypha/apply/users/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,18 +220,14 @@ def save(self, updated_email, name, slack, commit=True):
return self.user


class TWOFAPasswordForm(forms.Form):
class Disable2FAConfirmationForm(forms.Form):
confirmation_text = forms.CharField(
label=_('To proceed, type "disable" below and then click on "confirm":'),
strip=True,
# add widget with autofocus to avoid password autofill
widget=forms.TextInput(attrs={"autofocus": True, "autocomplete": "off"}),
)

def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user

def clean_confirmation_text(self):
text = self.cleaned_data["confirmation_text"]
if text != "disable":
Expand Down
9 changes: 4 additions & 5 deletions hypha/apply/users/templates/two_factor/admin/disable.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,21 @@
<form class="form" action="" method="POST" novalidate>
<div class="tab-content">
{% csrf_token %}

<section id="account" class="active nice-padding">
<p>{% trans "Are you sure you want to disable the Two Factor Authentication for this user? Please type your password to confirm." %}</p>
<p>{% trans "Are you sure you want to disable the Two Factor Authentication for this user?" %}</p>

<ul class="fields">
{% block fields %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.password %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.confirmation_text %}
{% endblock %}

<li>
<button class="button button--primary" type="submit">{% trans 'Disable 2FA' %}</button>
<button class="button button--primary" type="submit">{% trans 'Confirm' %}</button>
</li>
</ul>

</section>
</div>
</form>


{% endblock %}
22 changes: 5 additions & 17 deletions hypha/apply/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@
BecomeUserForm,
CustomAuthenticationForm,
CustomUserCreationForm,
Disable2FAConfirmationForm,
PasswordlessAuthForm,
ProfileForm,
TWOFAPasswordForm,
)
from .models import ConfirmAccessToken, PendingSignup
from .services import PasswordlessAuthService
Expand Down Expand Up @@ -500,39 +500,27 @@ class TWOFADisableView(ElevateMixin, TwoFactorDisableView):

template_name = "two_factor/profile/disable.html"
success_url = reverse_lazy("users:account")
form_class = TWOFAPasswordForm

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["user"] = self.request.user
return kwargs
form_class = Disable2FAConfirmationForm


@method_decorator(
permission_required(change_user_perm, raise_exception=True), name="dispatch"
)
class TWOFAAdminDisableView(FormView):
class TWOFAAdminDisableView(ElevateMixin, FormView):
"""
View for PasswordForm to confirm the Disable 2FA process on wagtail admin.
"""

form_class = TWOFAPasswordForm
form_class = Disable2FAConfirmationForm
template_name = "two_factor/admin/disable.html"
user = None

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
# pass request's user to form to validate the password
kwargs["user"] = self.request.user
# store the user from url for redirecting to the same user's account edit page
self.user = get_object_or_404(User, pk=self.kwargs.get("user_id"))
return kwargs

def get_form(self, form_class=None):
form = super(TWOFAAdminDisableView, self).get_form(form_class=form_class)
form.fields["password"].label = "Password"
return form

def form_valid(self, form):
for device in devices_for_user(self.user):
device.delete()
Expand All @@ -542,7 +530,7 @@ def get_success_url(self):
return reverse("wagtailusers_users:edit", args=[self.user.id])

def get_context_data(self, **kwargs):
ctx = super(TWOFAAdminDisableView, self).get_context_data(**kwargs)
ctx = super().get_context_data(**kwargs)
ctx["user"] = self.user
return ctx

Expand Down