Ticket #15915: 15915_patch.diff

File 15915_patch.diff, 5.2 KB (added by Nikolay Zakharov, 13 years ago)

Initial patch with test

Line 
1Index: django/contrib/auth/tests/permissions.py
2===================================================================
3--- django/contrib/auth/tests/permissions.py (revision 16342)
4+++ django/contrib/auth/tests/permissions.py (working copy)
5@@ -6,16 +6,21 @@
6 from django.contrib.auth.management import create_permissions
7 from django.contrib.auth import models as auth_models
8 from django.contrib.contenttypes import models as contenttypes_models
9-from django.core.management import call_command
10+from django.core.management import call_command, CommandError
11 from django.test import TestCase
12
13
14 class TestAuthPermissions(TestCase):
15+
16+ def setUp(self):
17+ self._original_user_permissions = auth_models.User._meta.permissions
18+
19 def tearDown(self):
20 # These tests mess with content types, but content type lookups
21 # are cached, so we need to make sure the effects of this test
22 # are cleaned up.
23 contenttypes_models.ContentType.objects.clear_cache()
24+ auth_models.User._meta.permissions = self._original_user_permissions
25
26 def test_permission_register_order(self):
27 """Test that the order of registered permissions doesn't break"""
28@@ -33,6 +38,34 @@
29 call_command('loaddata', 'test_permissions.json',
30 verbosity=0, commit=False, stderr=stderr)
31 self.assertEqual(stderr.getvalue(), '')
32+
33+ def test_permission_duplicates_checking(self):
34+ """Test that we show proper error message if we are trying to
35+ create duplicate permissions.
36+ """
37+ auth_models.User._meta.permissions = [
38+ ('change_user', 'Can edit user (duplicate)')]
39+ self.assertRaisesRegexp(CommandError,
40+ 'The permission codename change_user clashes with a builtin '
41+ 'for model auth.User.',
42+ create_permissions, auth_models, [], verbosity=0)
43+
44+ auth_models.User._meta.permissions = [
45+ ('my_custom_permission', 'Some permission'),
46+ ('other_one', 'Some other permission'),
47+ ('my_custom_permission', 'Some permission with duplicate code'),
48+ ]
49+ self.assertRaisesRegexp(CommandError,
50+ 'The permission codename is duplicated for model auth.User: '
51+ 'my_custom_permission',
52+ create_permissions, auth_models, [], verbosity=0)
53+
54+ # should not raise anything
55+ auth_models.User._meta.permissions = [
56+ ('my_custom_permission', 'Some permission'),
57+ ('other_one', 'Some other permission'),
58+ ]
59+ create_permissions(auth_models, [], verbosity=0)
60Index: django/contrib/auth/management/__init__.py
61===================================================================
62--- django/contrib/auth/management/__init__.py (revision 16342)
63+++ django/contrib/auth/management/__init__.py (working copy)
64@@ -7,23 +7,52 @@
65 from django.contrib.auth import models as auth_app
66 from django.db.models import get_models, signals
67 from django.contrib.auth.models import User
68+from django.core.management.base import CommandError
69
70
71+def _check_permissions_clashing(custom, builtin, ctype):
72+ "Raises CommandError if there are duplicate permissions."
73+ pool = set()
74+ builtin_codenames = set(p[0] for p in builtin)
75+ for codename, _name in custom:
76+ if codename in pool:
77+ raise CommandError(
78+ "The permission codename is duplicated for model %s.%s: %s" %
79+ (ctype.app_label, ctype.model_class().__name__, codename))
80+ elif codename in builtin_codenames:
81+ raise CommandError(
82+ "The permission codename %s clashes with a builtin for model "
83+ "%s.%s." %
84+ (codename, ctype.app_label, ctype.model_class().__name__))
85+ pool.add(codename)
86+
87+
88 def _get_permission_codename(action, opts):
89 return u'%s_%s' % (action, opts.object_name.lower())
90
91
92-def _get_all_permissions(opts):
93- "Returns (codename, name) for all permissions in the given opts."
94+def _get_builtin_permissions(opts):
95+ "Returns (codename, name) for all autogenerated permissions."
96 perms = []
97 for action in ('add', 'change', 'delete'):
98- perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))
99- return perms + list(opts.permissions)
100+ perms.append(
101+ (_get_permission_codename(action, opts),
102+ u'Can %s %s' % (action, opts.verbose_name_raw)))
103+ return perms
104
105
106+def _get_all_permissions(opts, ctype):
107+ "Returns (codename, name) for all permissions in the given opts."
108+ builtin = _get_builtin_permissions(opts)
109+ custom = list(opts.permissions)
110+ _check_permissions_clashing(custom, builtin, ctype)
111+ return builtin + custom
112+
113+
114 def create_permissions(app, created_models, verbosity, **kwargs):
115 from django.contrib.contenttypes.models import ContentType
116
117@@ -34,7 +63,7 @@
118 for klass in app_models:
119 ctype = ContentType.objects.get_for_model(klass)
120 ctypes.add(ctype)
121- for perm in _get_all_permissions(klass._meta):
122+ for perm in _get_all_permissions(klass._meta, ctype):
123 searched_perms.append((ctype, perm))
124
125 # Find all the Permissions that have a context_type for a model we're
Back to Top