mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Allow team admins to require two-factor authentication (#4034)
* Allow team admins to require two-factor authentication * Add API tests * Improve logic * ADd button tooltip
This commit is contained in:
@@ -23,7 +23,7 @@ import time
|
||||
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from django.test import Client
|
||||
from django.test import Client, override_settings
|
||||
from tests.base import extract_form_fields
|
||||
|
||||
from pretix.base.models import Organizer
|
||||
@@ -66,6 +66,25 @@ def test_session_auth_relative_timeout(client, user, team):
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_session_auth_password_change_required(client, user, team):
|
||||
client.login(email=user.email, password='dummy')
|
||||
user.needs_password_change = True
|
||||
user.save()
|
||||
|
||||
resp = client.get('/api/v1/organizers/')
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA=True)
|
||||
def test_session_auth_2fa_setup_required(client, user, team):
|
||||
client.login(email=user.email, password='dummy')
|
||||
|
||||
resp = client.get('/api/v1/organizers/')
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_session_auth_csrf(user, team):
|
||||
team.members.add(user)
|
||||
|
||||
@@ -41,7 +41,8 @@ TEST_TEAM_RES = {
|
||||
'can_change_teams': True, 'can_change_organizer_settings': True, 'can_manage_gift_cards': True,
|
||||
'can_manage_customers': True, 'can_manage_reusable_media': True,
|
||||
'can_change_event_settings': True, 'can_change_items': True, 'can_view_orders': True, 'can_change_orders': True,
|
||||
'can_view_vouchers': True, 'can_change_vouchers': True, 'can_checkin_orders': False
|
||||
'can_view_vouchers': True, 'can_change_vouchers': True, 'can_checkin_orders': False,
|
||||
'require_2fa': False,
|
||||
}
|
||||
|
||||
SECOND_TEAM_RES = {
|
||||
@@ -50,7 +51,8 @@ SECOND_TEAM_RES = {
|
||||
'can_manage_customers': False, 'can_manage_reusable_media': False,
|
||||
'can_change_teams': False, 'can_change_organizer_settings': False, 'can_manage_gift_cards': False,
|
||||
'can_change_event_settings': False, 'can_change_items': False, 'can_view_orders': False, 'can_change_orders': False,
|
||||
'can_view_vouchers': False, 'can_change_vouchers': False, 'can_checkin_orders': False
|
||||
'can_view_vouchers': False, 'can_change_vouchers': False, 'can_checkin_orders': False,
|
||||
'require_2fa': False,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ from webauthn.authentication.verify_authentication_response import (
|
||||
VerifiedAuthentication,
|
||||
)
|
||||
|
||||
from pretix.base.models import U2FDevice, User
|
||||
from pretix.base.models import Organizer, Team, U2FDevice, User
|
||||
from pretix.helpers import security
|
||||
|
||||
|
||||
@@ -935,18 +935,19 @@ def test_staff_session_require_staff(user, client):
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA=True)
|
||||
class Obligatory2FATest(TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = User.objects.create_user('demo@demo.dummy', 'demo')
|
||||
self.client.login(email='demo@demo.dummy', password='demo')
|
||||
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA=True)
|
||||
def test_enabled_2fa_not_setup(self):
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 302
|
||||
assert response.url == '/control/settings/2fa/'
|
||||
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA=True)
|
||||
def test_enabled_2fa_setup_not_enabled(self):
|
||||
U2FDevice.objects.create(user=self.user, name='test', json_data="{}", confirmed=True)
|
||||
self.user.require_2fa = False
|
||||
@@ -956,6 +957,7 @@ class Obligatory2FATest(TestCase):
|
||||
assert response.status_code == 302
|
||||
assert response.url == '/control/settings/2fa/'
|
||||
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA=True)
|
||||
def test_enabled_2fa_setup_enabled(self):
|
||||
U2FDevice.objects.create(user=self.user, name='test', json_data="{}", confirmed=True)
|
||||
self.user.require_2fa = True
|
||||
@@ -964,6 +966,50 @@ class Obligatory2FATest(TestCase):
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 200
|
||||
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA="staff")
|
||||
def test_staff_only(self):
|
||||
self.user.require_2fa = False
|
||||
self.user.save()
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 200
|
||||
|
||||
self.user.is_staff = True
|
||||
self.user.save()
|
||||
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 302
|
||||
assert response.url == '/control/settings/2fa/'
|
||||
|
||||
@override_settings(PRETIX_OBLIGATORY_2FA=False)
|
||||
def test_by_team(self):
|
||||
session = self.client.session
|
||||
session['pretix_auth_long_session'] = True
|
||||
session['pretix_auth_login_time'] = int(time.time())
|
||||
session['pretix_auth_last_used'] = int(time.time())
|
||||
session.save()
|
||||
|
||||
organizer = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
team = Team.objects.create(organizer=organizer, can_change_teams=True, name='Admin team')
|
||||
team.members.add(self.user)
|
||||
self.user.require_2fa = False
|
||||
self.user.save()
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 200
|
||||
|
||||
team.require_2fa = True
|
||||
team.save()
|
||||
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 302
|
||||
assert response.url == '/control/settings/2fa/'
|
||||
|
||||
response = self.client.post('/control/settings/2fa/leaveteams')
|
||||
assert response.status_code == 302
|
||||
assert team.members.count() == 0
|
||||
|
||||
response = self.client.get('/control/events/')
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
class PasswordChangeRequiredTest(TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user