refactor(auth): Move check for verificated mail address to user class
This commit is contained in:
parent
b398d48533
commit
127a10f3d9
|
@ -1,4 +1,3 @@
|
||||||
from django.conf import settings
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
@ -12,14 +11,6 @@ from rest_framework import exceptions
|
||||||
from funkwhale_api.users import models as users_models
|
from funkwhale_api.users import models as users_models
|
||||||
|
|
||||||
|
|
||||||
def should_verify_email(user):
|
|
||||||
if user.is_superuser:
|
|
||||||
return False
|
|
||||||
has_unverified_email = not user.has_verified_primary_email
|
|
||||||
mandatory_verification = settings.ACCOUNT_EMAIL_VERIFICATION != "optional"
|
|
||||||
return has_unverified_email and mandatory_verification
|
|
||||||
|
|
||||||
|
|
||||||
class UnverifiedEmail(Exception):
|
class UnverifiedEmail(Exception):
|
||||||
def __init__(self, user):
|
def __init__(self, user):
|
||||||
self.user = user
|
self.user = user
|
||||||
|
@ -68,7 +59,7 @@ class ApplicationTokenAuthentication(object):
|
||||||
msg = _("User account is disabled.")
|
msg = _("User account is disabled.")
|
||||||
raise exceptions.AuthenticationFailed(msg)
|
raise exceptions.AuthenticationFailed(msg)
|
||||||
|
|
||||||
if should_verify_email(user):
|
if user.should_verify_email():
|
||||||
raise UnverifiedEmail(user)
|
raise UnverifiedEmail(user)
|
||||||
|
|
||||||
request.scopes = application.scope.split()
|
request.scopes = application.scope.split()
|
||||||
|
|
|
@ -27,7 +27,7 @@ def authenticate(username, password):
|
||||||
except (User.DoesNotExist, binascii.Error):
|
except (User.DoesNotExist, binascii.Error):
|
||||||
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
||||||
|
|
||||||
if common_authentication.should_verify_email(user):
|
if user.should_verify_email():
|
||||||
raise exceptions.AuthenticationFailed("You need to verify your e-mail address.")
|
raise exceptions.AuthenticationFailed("You need to verify your e-mail address.")
|
||||||
|
|
||||||
return (user, None)
|
return (user, None)
|
||||||
|
@ -46,7 +46,7 @@ def authenticate_salt(username, salt, token):
|
||||||
if expected != token:
|
if expected != token:
|
||||||
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
raise exceptions.AuthenticationFailed("Wrong username or password.")
|
||||||
|
|
||||||
if common_authentication.should_verify_email(user):
|
if user.should_verify_email():
|
||||||
raise exceptions.AuthenticationFailed("You need to verify your e-mail address.")
|
raise exceptions.AuthenticationFailed("You need to verify your e-mail address.")
|
||||||
|
|
||||||
return (user, None)
|
return (user, None)
|
||||||
|
|
|
@ -105,13 +105,7 @@ class UserQuerySet(models.QuerySet):
|
||||||
def for_auth(self):
|
def for_auth(self):
|
||||||
"""Optimization to avoid additional queries during authentication"""
|
"""Optimization to avoid additional queries during authentication"""
|
||||||
qs = self.select_related("actor__domain")
|
qs = self.select_related("actor__domain")
|
||||||
verified_emails = EmailAddress.objects.filter(
|
return qs.prefetch_related("plugins", "emailaddress_set")
|
||||||
user=models.OuterRef("id"), primary=True
|
|
||||||
).values("verified")[:1]
|
|
||||||
subquery = models.Subquery(verified_emails)
|
|
||||||
return qs.annotate(has_verified_primary_email=subquery).prefetch_related(
|
|
||||||
"plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UserManager(BaseUserManager):
|
class UserManager(BaseUserManager):
|
||||||
|
@ -315,6 +309,17 @@ class User(AbstractUser):
|
||||||
return
|
return
|
||||||
return self.actor.attachment_icon
|
return self.actor.attachment_icon
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_verified_primary_email(self) -> bool:
|
||||||
|
return len(self.emailaddress_set.filter(primary=True, verified=True)) > 0
|
||||||
|
|
||||||
|
def should_verify_email(self):
|
||||||
|
if self.is_superuser:
|
||||||
|
return False
|
||||||
|
has_unverified_email = not self.has_verified_primary_email
|
||||||
|
mandatory_verification = settings.ACCOUNT_EMAIL_VERIFICATION != "optional"
|
||||||
|
return has_unverified_email and mandatory_verification
|
||||||
|
|
||||||
|
|
||||||
def generate_code(length=10):
|
def generate_code(length=10):
|
||||||
return "".join(
|
return "".join(
|
||||||
|
|
|
@ -7,7 +7,7 @@ from funkwhale_api.common import authentication
|
||||||
def check(request):
|
def check(request):
|
||||||
user = request.user
|
user = request.user
|
||||||
request.user = user.__class__.objects.all().for_auth().get(pk=user.pk)
|
request.user = user.__class__.objects.all().for_auth().get(pk=user.pk)
|
||||||
if authentication.should_verify_email(request.user):
|
if request.user.should_verify_email():
|
||||||
raise authentication.UnverifiedEmail(user)
|
raise authentication.UnverifiedEmail(user)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,10 @@ def test_should_verify_email(
|
||||||
settings,
|
settings,
|
||||||
):
|
):
|
||||||
settings.ACCOUNT_EMAIL_VERIFICATION = setting_value
|
settings.ACCOUNT_EMAIL_VERIFICATION = setting_value
|
||||||
user = factories["users.User"](is_superuser=is_superuser)
|
user = factories["users.User"](
|
||||||
setattr(user, "has_verified_primary_email", has_verified_primary_email)
|
is_superuser=is_superuser, verified_email=has_verified_primary_email
|
||||||
assert authentication.should_verify_email(user) is expected
|
)
|
||||||
|
assert user.should_verify_email() is expected
|
||||||
|
|
||||||
|
|
||||||
def test_app_token_authentication(factories, api_request):
|
def test_app_token_authentication(factories, api_request):
|
||||||
|
|
|
@ -244,7 +244,7 @@ def test_get_by_natural_key_annotates_primary_email_verified_no_email(factories)
|
||||||
user = factories["users.User"]()
|
user = factories["users.User"]()
|
||||||
user = models.User.objects.get_by_natural_key(user.username)
|
user = models.User.objects.get_by_natural_key(user.username)
|
||||||
|
|
||||||
assert user.has_verified_primary_email is None
|
assert user.has_verified_primary_email is False
|
||||||
|
|
||||||
|
|
||||||
def test_get_by_natural_key_annotates_primary_email_verified_true(factories):
|
def test_get_by_natural_key_annotates_primary_email_verified_true(factories):
|
||||||
|
|
Loading…
Reference in New Issue