90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
from datetime import timedelta
|
|
|
|
from django.utils import timezone
|
|
|
|
from infrasynth.security.models import TwoFactorConfig
|
|
from infrasynth.security.two_factor.middleware import TwoFactorMiddleware
|
|
from infrasynth.security.two_factor.utils import (
|
|
generate_pre_auth_token,
|
|
get_pre_auth_expiry,
|
|
)
|
|
|
|
|
|
class TestPreAuthUtils:
|
|
def test_generate_pre_auth_token_length(self):
|
|
token = generate_pre_auth_token()
|
|
assert len(token) == 64
|
|
|
|
def test_generate_pre_auth_token_unique(self):
|
|
assert generate_pre_auth_token() != generate_pre_auth_token()
|
|
|
|
def test_get_pre_auth_expiry(self):
|
|
before = timezone.now()
|
|
expiry = get_pre_auth_expiry(minutes=5)
|
|
after = timezone.now()
|
|
assert before + timedelta(minutes=5) <= expiry <= after + timedelta(minutes=5)
|
|
|
|
|
|
class _Request:
|
|
def __init__(self, user, path="/api/features/active/"):
|
|
self.user = user
|
|
self.path = path
|
|
|
|
|
|
class TestTwoFactorMiddleware:
|
|
def test_anonymous_passes(self, rf, db):
|
|
request = rf.get("/api/features/active/")
|
|
request.user = type("Anon", (), {"is_authenticated": False})()
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|
|
|
|
def test_user_without_config_passes(self, rf, user):
|
|
request = rf.get("/api/features/active/")
|
|
request.user = user
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|
|
|
|
def test_disabled_config_passes(self, rf, user):
|
|
TwoFactorConfig.objects.create(user=user, is_enabled=False, is_configured=True)
|
|
request = rf.get("/api/features/active/")
|
|
request.user = user
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|
|
|
|
def test_unconfigured_enabled_passes(self, rf, user):
|
|
TwoFactorConfig.objects.create(user=user, is_enabled=True, is_configured=False)
|
|
request = rf.get("/api/features/active/")
|
|
request.user = user
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|
|
|
|
def test_redirects_when_2fa_required(self, rf, user):
|
|
TwoFactorConfig.objects.create(user=user, is_enabled=True, is_configured=True)
|
|
request = rf.get("/api/features/active/")
|
|
request.user = user
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is not None
|
|
assert result.status_code == 302
|
|
assert result.url == "/api/auth/2fa/verify/"
|
|
|
|
def test_exempt_paths_not_redirected(self, rf, user):
|
|
TwoFactorConfig.objects.create(user=user, is_enabled=True, is_configured=True)
|
|
request = rf.get("/api/auth/check/")
|
|
request.user = user
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|
|
|
|
def test_admin_path_not_redirected(self, rf, user):
|
|
TwoFactorConfig.objects.create(user=user, is_enabled=True, is_configured=True)
|
|
request = rf.get("/admin/")
|
|
request.user = user
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|
|
|
|
def test_verified_user_not_redirected(self, rf, user):
|
|
TwoFactorConfig.objects.create(user=user, is_enabled=True, is_configured=True)
|
|
request = rf.get("/api/features/active/")
|
|
request.user = user
|
|
request._2fa_verified = True
|
|
result = TwoFactorMiddleware(get_response=lambda r: None).process_request(request)
|
|
assert result is None
|