From 70bda4ecc97eac17312ad312d3b8838639a0b07a Mon Sep 17 00:00:00 2001 From: Conor Holden Date: Tue, 2 Jul 2024 16:48:17 +0200 Subject: [PATCH 1/2] :bug:[maykinmedia/open-api-framework#39] make user emails unique --- .../0002_user_filled_email_unique.py | 21 +++++++++++++++++++ src/objecttypes/accounts/models.py | 6 ++++++ .../accounts/tests/test_user_manager.py | 13 ++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/objecttypes/accounts/migrations/0002_user_filled_email_unique.py diff --git a/src/objecttypes/accounts/migrations/0002_user_filled_email_unique.py b/src/objecttypes/accounts/migrations/0002_user_filled_email_unique.py new file mode 100644 index 00000000..50d8499e --- /dev/null +++ b/src/objecttypes/accounts/migrations/0002_user_filled_email_unique.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.11 on 2024-07-02 14:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0001_initial"), + ] + + operations = [ + migrations.AddConstraint( + model_name="user", + constraint=models.UniqueConstraint( + condition=models.Q(("email", ""), _negated=True), + fields=("email",), + name="filled_email_unique", + ), + ), + ] diff --git a/src/objecttypes/accounts/models.py b/src/objecttypes/accounts/models.py index 05f53e34..d0990bb4 100644 --- a/src/objecttypes/accounts/models.py +++ b/src/objecttypes/accounts/models.py @@ -1,5 +1,6 @@ from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.db import models +from django.db.models import Q from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -46,6 +47,11 @@ class User(AbstractBaseUser, PermissionsMixin): class Meta: verbose_name = _("user") verbose_name_plural = _("users") + constraints = [ + models.UniqueConstraint( + fields=["email"], condition=~Q(email=""), name="filled_email_unique" + ) + ] def get_full_name(self): """ diff --git a/src/objecttypes/accounts/tests/test_user_manager.py b/src/objecttypes/accounts/tests/test_user_manager.py index 1a6ab7d2..3f4e0c90 100644 --- a/src/objecttypes/accounts/tests/test_user_manager.py +++ b/src/objecttypes/accounts/tests/test_user_manager.py @@ -1,3 +1,4 @@ +from django.db import IntegrityError from django.test import TestCase from ..models import User @@ -20,3 +21,15 @@ def test_create_user(self): self.assertFalse(user.is_superuser) self.assertFalse(user.is_staff) self.assertFalse(user.has_usable_password()) + + def test_create_users_with_same_email(self): + User.objects.create(username="AAA", email="aaa@aaa.aaa", password="aaa!") + + with self.assertRaises(IntegrityError): + User.objects.create(username="BBB", email="aaa@aaa.aaa", password="bbb!") + + def test_create_user_with_blank_emails(self): + User.objects.create(username="AAA", email="", password="aaa!") + User.objects.create(username="BBB", email="", password="bbb!") + + self.assertEqual(User.objects.count(), 2) From 254288dbcf53268180d3b03bde4816d8120f7c48 Mon Sep 17 00:00:00 2001 From: Conor Holden Date: Fri, 5 Jul 2024 12:49:58 +0200 Subject: [PATCH 2/2] :memo:[maykinmedia/open-api-framework#39] add warning to the changelog --- CHANGELOG.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3c07e4b9..37729cda 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,17 @@ Change history ============== +2.x (TBD) +------------------ + +**New features** + +* made user emails unique to prevent two users logging in with the same email, causing an error + +.. warning:: + User email addresses will now be unique on a database level. The database migration will fail if there are already + two or more users with the same email address. You must ensure this is not the case before upgrading. + 2.2.0 (2024-06-27) ------------------