From 48884bbd460a37e652cbfa8400fc64fd23259d66 Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Tue, 21 May 2013 18:55:21 -0400 Subject: [PATCH] Fixed #10 - Use citext to make usernames case insensitive --- warehouse/accounts/migrations/0001_initial.py | 12 ++++++++++-- warehouse/accounts/models.py | 3 ++- warehouse/utils/db_fields.py | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 warehouse/utils/db_fields.py diff --git a/warehouse/accounts/migrations/0001_initial.py b/warehouse/accounts/migrations/0001_initial.py index 0cb638517f12..29495ac0923a 100644 --- a/warehouse/accounts/migrations/0001_initial.py +++ b/warehouse/accounts/migrations/0001_initial.py @@ -8,18 +8,26 @@ class Migration(SchemaMigration): def forwards(self, orm): + # CREATE the citext extension + db.execute("CREATE EXTENSION IF NOT EXISTS citext") + # Adding model 'User' db.create_table('accounts_user', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('password', self.gf('django.db.models.fields.CharField')(max_length=128)), ('last_login', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), ('is_superuser', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=50)), + ('username', self.gf('warehouse.utils.db_fields.CaseInsensitiveCharField')(unique=True, max_length=50)), ('name', self.gf('django.db.models.fields.CharField')(blank=True, max_length=100)), ('is_staff', self.gf('django.db.models.fields.BooleanField')(default=False)), ('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)), ('date_joined', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), )) + + # Adding constraint to model field 'User.username' + db.execute("ALTER TABLE accounts_user ADD CONSTRAINT accounts_user_username_length CHECK (length(username) <= 50)") + + # Send signal to show we've created the User model db.send_create_signal('accounts', ['User']) # Adding M2M table for field groups on 'User' @@ -110,4 +118,4 @@ def backwards(self, orm): } } - complete_apps = ['accounts'] \ No newline at end of file + complete_apps = ['accounts'] diff --git a/warehouse/accounts/models.py b/warehouse/accounts/models.py index ff1966af6dfe..cd232126adeb 100644 --- a/warehouse/accounts/models.py +++ b/warehouse/accounts/models.py @@ -13,6 +13,7 @@ from warehouse import accounts from warehouse.accounts import adapters +from warehouse.utils.db_fields import CaseInsensitiveCharField class UserManager(BaseUserManager): @@ -52,7 +53,7 @@ class User(AbstractBaseUser, PermissionsMixin): USERNAME_FIELD = "username" - username = models.CharField(_("username"), + username = CaseInsensitiveCharField(_("username"), max_length=50, unique=True, help_text=accounts.VALID_USERNAME_DESC, diff --git a/warehouse/utils/db_fields.py b/warehouse/utils/db_fields.py new file mode 100644 index 000000000000..e8f270e276e2 --- /dev/null +++ b/warehouse/utils/db_fields.py @@ -0,0 +1,15 @@ +from django.db.models import fields +from south.modelsinspector import add_introspection_rules + + +class CaseInsensitiveCharField(fields.CharField): + # NOTE: You MUST manually add a CHECK CONSTRAINT to the database for + # max_length to be respected in the DB. + + def db_type(self, connection): + return "citext" + + +add_introspection_rules([], + ["^warehouse\.utils\.db_fields\.CaseInsensitiveCharField"], +)