#15915: Permission codename duplication is not handled well
------------------------+------------------------------
 Reporter:  valyagolev  |          Owner:  nobody
     Type:  Bug         |         Status:  new
Milestone:              |      Component:  contrib.auth
  Version:  1.3         |       Severity:  Normal
 Keywords:              |   Triage Stage:  Unreviewed
Has patch:  0           |  Easy pickings:  1
------------------------+------------------------------
 Example:

 {{{

 from django.db import models

 # Create your models here.


 class Tweet(models.Model):
     message = models.CharField(max_length=140)

     class Meta:
         permissions = (("change_tweet", "can, like, change tweet or
 something..."),)


 }}}

 Stacktrace:

 {{{

 (bug-with-perms)[.../bugwithperms]$ python manage.py syncdb
 Creating tables ...
 Creating table auth_permission
 Creating table auth_group_permissions
 Creating table auth_group
 Creating table auth_user_user_permissions
 Creating table auth_user_groups
 Creating table auth_user
 Creating table auth_message
 Creating table django_content_type
 Creating table django_session
 Creating table django_site
 Creating table trybug_tweet

 You just installed Django's auth system, which means you don't have any
 superusers defined.
 Would you like to create one now? (yes/no): no
 Traceback (most recent call last):
   File "manage.py", line 14, in <module>
     execute_manager(settings)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/__init__.py", line 438, in
 execute_manager
     utility.execute()
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/__init__.py", line 379, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/base.py", line 191, in run_from_argv
     self.execute(*args, **options.__dict__)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/base.py", line 220, in execute
     output = self.handle(*args, **options)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/base.py", line 351, in handle
     return self.handle_noargs(**options)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/commands/syncdb.py", line 109, in
 handle_noargs
     emit_post_sync_signal(created_models, verbosity, interactive, db)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/core/management/sql.py", line 190, in
 emit_post_sync_signal
     interactive=interactive, db=db)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/dispatch/dispatcher.py", line 172, in send
     response = receiver(signal=self, sender=sender, **named)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/contrib/auth/management/__init__.py", line 51, in
 create_permissions
     content_type=ctype
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/manager.py", line 138, in create
     return self.get_query_set().create(**kwargs)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/query.py", line 360, in create
     obj.save(force_insert=True, using=self.db)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/base.py", line 460, in save
     self.save_base(using=using, force_insert=force_insert,
 force_update=force_update)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/base.py", line 553, in save_base
     result = manager._insert(values, return_id=update_pk, using=using)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/manager.py", line 195, in _insert
     return insert_query(self.model, values, **kwargs)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/query.py", line 1436, in insert_query
     return query.get_compiler(using=using).execute_sql(return_id)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/sql/compiler.py", line 791, in execute_sql
     cursor = super(SQLInsertCompiler, self).execute_sql(None)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
     cursor.execute(sql, params)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/backends/util.py", line 34, in execute
     return self.cursor.execute(sql, params)
   File "/media/oldroot/home/valentin/Envs/bug-with-perms/lib/python2.6
 /site-packages/django/db/backends/sqlite3/base.py", line 234, in execute
     return Database.Cursor.execute(self, query, params)
 django.db.utils.IntegrityError: columns content_type_id, codename are not
 unique

 }}}

 What's going on?

 Basically, if there are two permissions for a model with same codenames
 and different descriptions, Django tries to add both in the database, but
 there is a unique index on codename so it all crashes horribly.

 The code which is responsible for this is at create_permissions()
 function[1]. There is a set: `searched_perms`, so it should help to avoid
 duplicate values. But the second element of every tuple in set, namely
 "perm", is another tuple of (codename, name), and the "name" is a human-
 readable name and not an identifier. So if we have two permissions with
 same codenames, but different "name"s, set will see them as different
 permissions and django will try to insert them both in the database.
 However, the unique index is only on two fields: ctype and codename, so
 permissions with same ctype and codename, but different "names", can't be
 inserted. That results in a pretty odd stacktrace.

 [1]:
 
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/management/__init__.py#L19

 Either it is a bug, or a good error message should be added. This one is
 misleading (and it's much more misleading on postgres). I had to use pdb
 to investigate this pretty innocent code

-- 
Ticket URL: <http://code.djangoproject.com/ticket/15915>
Django <http://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 post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to