mirror of
https://github.com/pretix/pretix.git
synced 2025-12-21 16:42:26 +00:00
Compare commits
1 Commits
widget-dia
...
recovery-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45bff138d7 |
@@ -57,6 +57,7 @@ from django.views.decorators.csrf import csrf_exempt
|
|||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django_otp import match_token
|
from django_otp import match_token
|
||||||
|
from django_otp.plugins.otp_static.models import StaticDevice
|
||||||
from webauthn.helpers import generate_challenge
|
from webauthn.helpers import generate_challenge
|
||||||
|
|
||||||
from pretix.base.auth import get_auth_backends
|
from pretix.base.auth import get_auth_backends
|
||||||
@@ -538,6 +539,10 @@ class Login2FAView(TemplateView):
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
valid = match_token(self.user, token)
|
valid = match_token(self.user, token)
|
||||||
|
if isinstance(valid, StaticDevice):
|
||||||
|
self.user.send_security_notice([
|
||||||
|
_("A recovery code for two-factor authentification was used to log in.")
|
||||||
|
])
|
||||||
|
|
||||||
if valid:
|
if valid:
|
||||||
logger.info(f"Backend login successful for user {self.user.pk} with 2FA.")
|
logger.info(f"Backend login successful for user {self.user.pk} with 2FA.")
|
||||||
|
|||||||
@@ -165,6 +165,9 @@ class UserEmergencyTokenView(AdministratorPermissionRequiredMixin, RecentAuthent
|
|||||||
d, __ = StaticDevice.objects.get_or_create(user=self.object, name='emergency')
|
d, __ = StaticDevice.objects.get_or_create(user=self.object, name='emergency')
|
||||||
token = d.token_set.create(token=get_random_string(length=12, allowed_chars='1234567890'))
|
token = d.token_set.create(token=get_random_string(length=12, allowed_chars='1234567890'))
|
||||||
self.object.log_action('pretix.user.settings.2fa.emergency', user=self.request.user)
|
self.object.log_action('pretix.user.settings.2fa.emergency', user=self.request.user)
|
||||||
|
self.object.send_security_notice([
|
||||||
|
_('A two-factor emergency code has been generated by a system administrator.')
|
||||||
|
])
|
||||||
|
|
||||||
messages.success(request, _(
|
messages.success(request, _(
|
||||||
'The emergency token for this user is "{token}". It can only be used once. Please make sure to transmit '
|
'The emergency token for this user is "{token}". It can only be used once. Please make sure to transmit '
|
||||||
|
|||||||
@@ -42,8 +42,10 @@ from django.contrib.auth.tokens import (
|
|||||||
)
|
)
|
||||||
from django.core import mail as djmail
|
from django.core import mail as djmail
|
||||||
from django.test import RequestFactory, TestCase, override_settings
|
from django.test import RequestFactory, TestCase, override_settings
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django_otp.oath import TOTP
|
from django_otp.oath import TOTP
|
||||||
|
from django_otp.plugins.otp_static.models import StaticDevice
|
||||||
from django_otp.plugins.otp_totp.models import TOTPDevice
|
from django_otp.plugins.otp_totp.models import TOTPDevice
|
||||||
from webauthn.authentication.verify_authentication_response import (
|
from webauthn.authentication.verify_authentication_response import (
|
||||||
VerifiedAuthentication,
|
VerifiedAuthentication,
|
||||||
@@ -492,6 +494,20 @@ class Login2FAFormTest(TestCase):
|
|||||||
|
|
||||||
m.undo()
|
m.undo()
|
||||||
|
|
||||||
|
def test_recovery_code_valid(self):
|
||||||
|
djmail.outbox = []
|
||||||
|
d, __ = StaticDevice.objects.get_or_create(user=self.user, name='emergency')
|
||||||
|
token = d.token_set.create(token=get_random_string(length=12, allowed_chars='1234567890'))
|
||||||
|
|
||||||
|
response = self.client.get('/control/login/2fa')
|
||||||
|
assert 'token' in response.content.decode()
|
||||||
|
response = self.client.post('/control/login/2fa', {
|
||||||
|
'token': token.token,
|
||||||
|
})
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertIn('/control/', response['Location'])
|
||||||
|
assert "recovery code" in djmail.outbox[0].body
|
||||||
|
|
||||||
|
|
||||||
class FakeRedis(object):
|
class FakeRedis(object):
|
||||||
def get_redis_connection(self, connection_string):
|
def get_redis_connection(self, connection_string):
|
||||||
|
|||||||
Reference in New Issue
Block a user