diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e6b54c72..b637b12fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to ## [Unreleased] +### Added + +- ⚡️(backend) add UPPER(email) index for case-insensitive user lookups + ## [1.35.0] - 2026-10-13 ### Added diff --git a/src/backend/core/migrations/0027_user_email_upper_idx.py b/src/backend/core/migrations/0027_user_email_upper_idx.py new file mode 100644 index 000000000..a17416de5 --- /dev/null +++ b/src/backend/core/migrations/0027_user_email_upper_idx.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.14 on 2026-10-07 18:45 + +from django.contrib.postgres.operations import AddIndexConcurrently +from django.db import migrations, models +from django.db.models.functions import Upper + + +class Migration(migrations.Migration): + atomic = False + + dependencies = [ + ('core', '0026_alter_application_scopes'), + ] + + operations = [ + AddIndexConcurrently( + model_name="user", + index=models.Index( + Upper("email"), + name="user_email_upper_idx", + ), + ), + ] diff --git a/src/backend/core/models.py b/src/backend/core/models.py index bcf6092b7..0cd48d8b8 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -246,6 +246,9 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin): name="unique_email_when_sub_is_null", ) ] + indexes = [ + models.Index(models.functions.Upper("email"), name="user_email_upper_idx"), + ] def __str__(self): return self.email or self.admin_email or str(self.id)