-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
104 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from allauth.mfa import app_settings | ||
from allauth.mfa.recovery_codes import RecoveryCodes | ||
|
||
|
||
def test_flow(user): | ||
rc = RecoveryCodes.activate(user) | ||
codes = rc.generate_codes() | ||
assert len(set(codes)) == app_settings.RECOVERY_CODE_COUNT | ||
for i in range(app_settings.RECOVERY_CODE_COUNT): | ||
assert not rc.is_code_used(i) | ||
idx = 3 | ||
assert rc.validate_code(codes[idx]) | ||
for i in range(app_settings.RECOVERY_CODE_COUNT): | ||
assert rc.is_code_used(i) == (i == idx) | ||
assert not rc.validate_code(codes[idx]) | ||
|
||
unused_codes = rc.get_unused_codes() | ||
assert codes[idx] not in unused_codes | ||
assert len(unused_codes) == app_settings.RECOVERY_CODE_COUNT - 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,9 @@ | |
import pytest | ||
|
||
from allauth.account.models import EmailAddress | ||
from allauth.mfa import app_settings | ||
from allauth.mfa.adapter import get_adapter | ||
from allauth.mfa.models import Authenticator | ||
|
||
|
||
@pytest.mark.parametrize( | ||
|
@@ -55,7 +57,7 @@ def test_activate_totp_with_unverified_email(auth_client, user, totp_validation_ | |
} | ||
|
||
|
||
def test_activate_totp_success(auth_client, totp_validation_bypass): | ||
def test_activate_totp_success(auth_client, totp_validation_bypass, user): | ||
resp = auth_client.get(reverse("mfa_activate_totp")) | ||
with totp_validation_bypass(): | ||
resp = auth_client.post( | ||
|
@@ -66,6 +68,28 @@ def test_activate_totp_success(auth_client, totp_validation_bypass): | |
}, | ||
) | ||
assert resp["location"] == reverse("mfa_view_recovery_codes") | ||
assert Authenticator.objects.filter( | ||
user=user, type=Authenticator.Type.TOTP | ||
).exists() | ||
assert Authenticator.objects.filter( | ||
user=user, type=Authenticator.Type.RECOVERY_CODES | ||
).exists() | ||
|
||
|
||
def test_index(auth_client, user_with_totp): | ||
resp = auth_client.get(reverse("mfa_index")) | ||
assert "authenticators" in resp.context | ||
|
||
|
||
def test_deactivate_totp_success(auth_client, user_with_totp, user_password): | ||
resp = auth_client.post(reverse("mfa_deactivate_totp")) | ||
assert resp.status_code == 302 | ||
assert resp["location"].startswith(reverse("account_reauthenticate")) | ||
resp = auth_client.post(resp["location"], {"password": user_password}) | ||
assert resp.status_code == 302 | ||
resp = auth_client.post(reverse("mfa_deactivate_totp")) | ||
assert resp.status_code == 302 | ||
assert resp["location"] == reverse("mfa_index") | ||
|
||
|
||
def test_user_without_totp_deactivate_totp(auth_client): | ||
|
@@ -99,3 +123,53 @@ def test_totp_login(client, user_with_totp, user_password, totp_validation_bypas | |
) | ||
assert resp.status_code == 302 | ||
assert resp["location"] == settings.LOGIN_REDIRECT_URL | ||
|
||
|
||
def test_download_recovery_codes(auth_client, user_with_recovery_codes, user_password): | ||
resp = auth_client.get(reverse("mfa_download_recovery_codes")) | ||
assert resp["location"].startswith(reverse("account_reauthenticate")) | ||
resp = auth_client.post(resp["location"], {"password": user_password}) | ||
assert resp.status_code == 302 | ||
resp = auth_client.get(resp["location"]) | ||
assert resp["content-disposition"] == 'attachment; filename="recovery-codes.txt"' | ||
|
||
|
||
def test_view_recovery_codes(auth_client, user_with_recovery_codes, user_password): | ||
resp = auth_client.get(reverse("mfa_view_recovery_codes")) | ||
assert resp["location"].startswith(reverse("account_reauthenticate")) | ||
resp = auth_client.post(resp["location"], {"password": user_password}) | ||
assert resp.status_code == 302 | ||
resp = auth_client.get(resp["location"]) | ||
assert len(resp.context["unused_codes"]) == app_settings.RECOVERY_CODE_COUNT | ||
|
||
|
||
def test_generate_recovery_codes(auth_client, user_with_recovery_codes, user_password): | ||
rc = Authenticator.objects.get( | ||
user=user_with_recovery_codes, type=Authenticator.Type.RECOVERY_CODES | ||
).wrap() | ||
prev_code = rc.get_unused_codes()[0] | ||
|
||
resp = auth_client.get(reverse("mfa_generate_recovery_codes")) | ||
assert resp["location"].startswith(reverse("account_reauthenticate")) | ||
resp = auth_client.post(resp["location"], {"password": user_password}) | ||
assert resp.status_code == 302 | ||
resp = auth_client.post(resp["location"]) | ||
assert resp["location"] == reverse("mfa_view_recovery_codes") | ||
|
||
rc = Authenticator.objects.get( | ||
user=user_with_recovery_codes, type=Authenticator.Type.RECOVERY_CODES | ||
).wrap() | ||
assert not rc.validate_code(prev_code) | ||
|
||
|
||
def test_add_email_not_allowed(auth_client, user_with_totp): | ||
resp = auth_client.post( | ||
reverse("account_email"), | ||
{"action_add": "", "email": "[email protected]"}, | ||
) | ||
assert resp.status_code == 200 | ||
assert resp.context["form"].errors == { | ||
"email": [ | ||
"You cannot add an email address to an account protected by two-factor authentication." | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters