#32897: create_user() does not raise ValidationError
----------------------------------------+------------------------
               Reporter:  adamckay      |          Owner:  nobody
                   Type:  Bug           |         Status:  new
              Component:  contrib.auth  |        Version:  3.2
               Severity:  Normal        |       Keywords:
           Triage Stage:  Unreviewed    |      Has patch:  0
    Needs documentation:  0             |    Needs tests:  0
Patch needs improvement:  0             |  Easy pickings:  0
                  UI/UX:  0             |
----------------------------------------+------------------------
 The `django.contrib.auth.models.UserManager.create_user()` function does
 not perform validation checking of the user object prior to saving to the
 database.

 The documentation
 
([https://docs.djangoproject.com/en/3.2/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user])
 implies this is the canonical way to create a user object and indeed it
 performs functions to normalize the email address and username as well as
 setting an unusable password, however the object is not validated using
 `full_clean()` which results in an object that has validation errors
 attempting to be committed to the database raising an `IntegrityError`
 rather than a `ValidationError`.

 This impacts the ability to add errors to any forms which use
 `create_user()` as the `IntegrityError` does not return a user-friendly
 message, nor is it applied to a field element.

 Reproduction steps in a Django shell:

 {{{
 >>> from django.contrib.auth.models import User
 >>> User.objects.create_user('example')
 <User: example>
 >>> User.objects.create_user('example')
 Traceback (most recent call last):
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/utils.py", line 84, in _execute
     return self.cursor.execute(sql, params)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/sqlite3/base.py", line 423, in execute
     return Database.Cursor.execute(self, query, params)
 sqlite3.IntegrityError: UNIQUE constraint failed: auth_user.username

 The above exception was the direct cause of the following exception:

 Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/contrib/auth/models.py", line 152, in create_user
     return self._create_user(username, email, password, **extra_fields)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/contrib/auth/models.py", line 146, in _create_user
     user.save(using=self._db)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/contrib/auth/base_user.py", line 67, in save
     super().save(*args, **kwargs)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/base.py", line 726, in save
     self.save_base(using=using, force_insert=force_insert,
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/base.py", line 763, in save_base
     updated = self._save_table(
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/base.py", line 868, in _save_table
     results = self._do_insert(cls._base_manager, using, fields,
 returning_fields, raw)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/base.py", line 906, in _do_insert
     return manager._insert(
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/manager.py", line 85, in manager_method
     return getattr(self.get_queryset(), name)(*args, **kwargs)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/query.py", line 1270, in _insert
     return query.get_compiler(using=using).execute_sql(returning_fields)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
     cursor.execute(sql, params)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/utils.py", line 98, in execute
     return super().execute(sql, params)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/utils.py", line 66, in execute
     return self._execute_with_wrappers(sql, params, many=False,
 executor=self._execute)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
     return executor(sql, params, many, context)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/utils.py", line 84, in _execute
     return self.cursor.execute(sql, params)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/utils.py", line 90, in __exit__
     raise dj_exc_value.with_traceback(traceback) from exc_value
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/utils.py", line 84, in _execute
     return self.cursor.execute(sql, params)
   File "/.pyenv/versions/38-django-core/lib/python3.8/site-
 packages/django/db/backends/sqlite3/base.py", line 423, in execute
     return Database.Cursor.execute(self, query, params)
 django.db.utils.IntegrityError: UNIQUE constraint failed:
 auth_user.username

 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32897>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/051.f2a22f149fef5094b18a6b4874e83600%40djangoproject.com.

Reply via email to