From 78822fb1dbfda21a111538ca6299326895ef36e4 Mon Sep 17 00:00:00 2001 From: Edward Lee Date: Thu, 2 Feb 2023 18:01:10 -0800 Subject: [PATCH 1/2] Added lowercase email field to override Django's case sensitive email field --- .../migrations/0033_alter_user_email.py | 19 +++++++++++++++++++ csm_web/scheduler/models.py | 13 +++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 csm_web/scheduler/migrations/0033_alter_user_email.py diff --git a/csm_web/scheduler/migrations/0033_alter_user_email.py b/csm_web/scheduler/migrations/0033_alter_user_email.py new file mode 100644 index 00000000..35ad65d1 --- /dev/null +++ b/csm_web/scheduler/migrations/0033_alter_user_email.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.15 on 2023-02-03 01:55 + +from django.db import migrations +import scheduler.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scheduler', '0032_word_of_the_day'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='email', + field=scheduler.models.LowercaseEmailField(max_length=254, unique=True), + ), + ] diff --git a/csm_web/scheduler/models.py b/csm_web/scheduler/models.py index 828a50fa..7ca21a69 100644 --- a/csm_web/scheduler/models.py +++ b/csm_web/scheduler/models.py @@ -34,8 +34,21 @@ def week_bounds(date): return week_start, week_end +class LowercaseEmailField(models.EmailField): + """ + Override EmailField to convert emails to lowercase before saving. + """ + + def to_python(self, value): + value = super(LowercaseEmailField, self).to_python(value) + if isinstance(value, str): + return value.lower() + return value + + class User(AbstractUser): priority_enrollment = models.DateTimeField(null=True, blank=True) + email = LowercaseEmailField(unique=True) def can_enroll_in_course(self, course, bypass_enrollment_time=False): # check restricted first From d5e7d0bf8efc8e273aa98e25b54928c746a666ee Mon Sep 17 00:00:00 2001 From: Edward Lee Date: Thu, 9 Feb 2023 17:45:34 -0800 Subject: [PATCH 2/2] Added tests for unique email with case sensitivity --- csm_web/scheduler/tests/models/test_user.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/csm_web/scheduler/tests/models/test_user.py b/csm_web/scheduler/tests/models/test_user.py index f14141af..d25951a2 100644 --- a/csm_web/scheduler/tests/models/test_user.py +++ b/csm_web/scheduler/tests/models/test_user.py @@ -1,5 +1,6 @@ import pytest +from django.db.utils import IntegrityError from scheduler.models import User @@ -13,3 +14,22 @@ def test_create_user(): assert user.username == username assert User.objects.count() == 1 assert User.objects.get(email=email).username == username + + +@pytest.mark.django_db +def test_same_email(): + email = "test@berkeley.edu" + username = "test" + caps_email = "TEST@BERKELEY.EDU" + caps_username = "TEST" + user, created = User.objects.get_or_create(email=email, username=username) + with pytest.raises(IntegrityError): + caps_user, caps_created = User.objects.get_or_create(email=caps_email, username=caps_username) + + assert created + assert user.email == email + assert user.email != caps_email + assert user.username == username + assert user.username != caps_username + assert User.objects.count() == 1 + assert User.objects.get(email=email).username == username