Commit 6b4fa212 authored by BAIRE Anthony's avatar BAIRE Anthony
Browse files

fix the validation of allauth emails

Allauth supports multiple email addresses per user. While this is
not intended in allgo, it is still possible to configure multiple
addresses using the /accounts/email/ endpoint.

Problem: even with ACCOUNT_EMAIL_VERIFICATION="mandatory", allauth
does not ensure that all addresses are verified. It only ensure
that *any* address is verified.

--> even if the user is validted by all auth, we still need to ensure
that the relevant address is verified before granting access
parent f9ce65d5
......@@ -2,6 +2,7 @@ from django.conf import settings
from django.contrib.auth.mixins import UserPassesTestMixin
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse, JsonResponse
from django.shortcuts import redirect
from .models import Job
from .helpers import get_request_user
......@@ -12,11 +13,18 @@ class IsProviderMixin(object):
"""
def dispatch(self, request, *args, **kwargs):
local_part, domain = request.user.email.split("@")
if domain in settings.ALLOWED_DEVELOPER_DOMAINS:
return super().dispatch(request, *args, **kwargs)
else:
email_addr = request.user.provider_address
if email_addr is None:
# user has no valid email address in the allowed domains
raise PermissionDenied
elif not email_addr.verified:
# user has a valid address but it is still unverified
email_addr.send_confirmation(request)
return redirect("account_email_verification_sent")
else:
# user has a valid and verified address
return super().dispatch(request, *args, **kwargs)
class JobAuthMixin(UserPassesTestMixin):
......
......@@ -11,6 +11,7 @@ from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from taggit.managers import TaggableManager
from allauth.account.models import EmailAddress
from allauth.socialaccount.models import SocialAccount
from django.utils.crypto import get_random_string
......@@ -629,17 +630,43 @@ def create_user_profile(sender, instance, created, **kwargs):
def save_user_profile(sender, instance, **kwargs):
instance.allgouser.save()
@property
def provider_address(user):
"""Get the first EmailAddress in the allowed developer domains
WARNING: the returned EmailAddress may not be verified
This function finds the first allauth EmailAddress of the user that matches
a domain listed in settings.ALLOWED_DEVELOPER_DOMAINS
If None is returned, then the user is not allowed to create a webapp.
When the function returns an EmailAddress this does not automatically imply
that the user can create a webapp, because we still have to ensure that the
email is validated (however this is sufficient for displaying the "create
webapp"/"import webapp" buttons).
"""
for email_addr in EmailAddress.objects.filter(user=user):
try:
_, domain = email_addr.email.split("@")
except ValueError:
# malformatted email
continue
if domain in settings.ALLOWED_DEVELOPER_DOMAINS:
return email_addr
return None
def is_provider(user):
"""Return true if the user belongs to the allowed developer domains
"""Return true if the user has at least one email address in the allowed
developer domains
Warning: this function returns True even if the email address is not
verified
"""
local_part, domain = user.email.split("@")
if domain in settings.ALLOWED_DEVELOPER_DOMAINS:
return True
else:
return False
return user.provider_address is not None
# Add the `is_provider` function as a `User` model method
auth.models.User.add_to_class('provider_address', provider_address)
auth.models.User.add_to_class('is_provider', is_provider)
# NOTE: because there is a circular dependency between models.py and
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment