Disallow registration when the proposed email is half-retired
Our learner retirement implementation shall allow re-use of email addresses, but we currently do not disallow re-use of emails for learners whose retirement is still in-progress (i.e. their retirement state is between PENDING and LMS_COMPLETE inclusive). The time between a user initiating retirement, and the jenkins job actually picking up the user and driving their account retirement might be as long as 1 hour, so this is a serious concern. Addresses EDUCATOR-2824.
This commit is contained in:
@@ -21,6 +21,7 @@ from util.password_policy_validators import validate_password
|
||||
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.user_api import errors, accounts, forms, helpers
|
||||
from openedx.core.djangoapps.user_api.accounts.utils import email_exists
|
||||
from openedx.core.djangoapps.user_api.config.waffle import PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle
|
||||
from openedx.core.djangoapps.user_api.errors import (
|
||||
AccountUpdateError,
|
||||
@@ -692,7 +693,7 @@ def _validate_email_doesnt_exist(email):
|
||||
:return: None
|
||||
:raises: errors.AccountEmailAlreadyExists
|
||||
"""
|
||||
if email is not None and User.objects.filter(email=email).exists():
|
||||
if email is not None and email_exists(email):
|
||||
raise errors.AccountEmailAlreadyExists(_(accounts.EMAIL_CONFLICT_MSG).format(email_address=email))
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import re
|
||||
import string
|
||||
from urlparse import urlparse
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext as _
|
||||
@@ -192,3 +193,29 @@ def generate_password(length=12, chars=string.letters + string.digits):
|
||||
password += choice(string.letters)
|
||||
password += ''.join([choice(chars) for _i in xrange(length - 2)])
|
||||
return password
|
||||
|
||||
|
||||
def email_exists(email):
|
||||
"""
|
||||
Check an email against the User and UserRetirementStatus models for
|
||||
existence.
|
||||
"""
|
||||
exists = False
|
||||
# Normal case, check users in the auth_user table.
|
||||
if User.objects.filter(email=email).exists():
|
||||
exists = True
|
||||
else:
|
||||
# Handle case where another user with the same email address has
|
||||
# initiated retirement (account deletion), but they are still in
|
||||
# the retirement queue in any state which is not COMPLETE.
|
||||
UserRetirementStatus = apps.get_model('user_api', 'UserRetirementStatus')
|
||||
try:
|
||||
if (UserRetirementStatus.objects
|
||||
.select_related('current_state')
|
||||
.filter(original_email=email)
|
||||
.exclude(current_state__state_name='COMPLETE')
|
||||
.exists()):
|
||||
exists = True
|
||||
except UserRetirementStatus.DoesNotExist:
|
||||
pass
|
||||
return exists
|
||||
|
||||
Reference in New Issue
Block a user