Code

Ticket #15915: 15915.2.diff

File 15915.2.diff, 4.8 KB (added by ptone, 3 years ago)

updated patch for 16730

Line 
1diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py
2index f82060e..6fabdc2 100644
3--- a/django/contrib/auth/management/__init__.py
4+++ b/django/contrib/auth/management/__init__.py
5@@ -7,18 +7,44 @@ import unicodedata
6 from django.contrib.auth import models as auth_app
7 from django.db.models import get_models, signals
8 from django.contrib.auth.models import User
9+from django.core.management.base import CommandError
10 
11 
12 def _get_permission_codename(action, opts):
13     return u'%s_%s' % (action, opts.object_name.lower())
14 
15 
16-def _get_all_permissions(opts):
17-    "Returns (codename, name) for all permissions in the given opts."
18+def _check_permissions_clashing(custom, builtin, ctype):
19+    "Raises CommandError if there are duplicate permissions."
20+    pool = set()
21+    builtin_codenames = set(p[0] for p in builtin)
22+    for codename, _name in custom:
23+        if codename in pool:
24+            raise CommandError(
25+                "The permission codename is duplicated for model %s.%s: %s" %
26+                (ctype.app_label, ctype.model_class().__name__, codename))
27+        elif codename in builtin_codenames:
28+            raise CommandError(
29+                "The permission codename %s clashes with a builtin for model "
30+                "%s.%s." %
31+                (codename, ctype.app_label, ctype.model_class().__name__))
32+        pool.add(codename)
33+
34+def _get_builtin_permissions(opts):
35+    "Returns (codename, name) for all autogenerated permissions."
36     perms = []
37     for action in ('add', 'change', 'delete'):
38-        perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))
39-    return perms + list(opts.permissions)
40+        perms.append(
41+            (_get_permission_codename(action, opts),
42+             u'Can %s %s' % (action, opts.verbose_name_raw)))
43+    return perms
44+
45+def _get_all_permissions(opts, ctype):
46+    "Returns (codename, name) for all permissions in the given opts."
47+    builtin = _get_builtin_permissions(opts)
48+    custom = list(opts.permissions)
49+    _check_permissions_clashing(custom, builtin, ctype)
50+    return builtin + custom
51 
52 
53 def create_permissions(app, created_models, verbosity, **kwargs):
54@@ -34,7 +60,7 @@ def create_permissions(app, created_models, verbosity, **kwargs):
55     for klass in app_models:
56         ctype = ContentType.objects.get_for_model(klass)
57         ctypes.add(ctype)
58-        for perm in _get_all_permissions(klass._meta):
59+        for perm in _get_all_permissions(klass._meta, ctype):
60             searched_perms.append((ctype, perm))
61 
62     # Find all the Permissions that have a context_type for a model we're
63diff --git a/django/contrib/auth/tests/management.py b/django/contrib/auth/tests/management.py
64index 0af6873..ab1a29c 100644
65--- a/django/contrib/auth/tests/management.py
66+++ b/django/contrib/auth/tests/management.py
67@@ -1,6 +1,7 @@
68 from django.test import TestCase
69+from django.contrib.auth.management import create_permissions
70 from django.contrib.auth import models, management
71-
72+from django.core.management import CommandError
73 
74 class GetDefaultUsernameTestCase(TestCase):
75 
76@@ -25,3 +26,41 @@ class GetDefaultUsernameTestCase(TestCase):
77         # 'Julia' with accented 'u':
78         management.get_system_username = lambda: u'J\xfalia'
79         self.assertEqual(management.get_default_username(), 'julia')
80+
81+class TestPermissionDuplication(TestCase):
82+
83+    def setUp(self):
84+        self._original_user_permissions = models.User._meta.permissions
85+
86+    def tearDown(self):
87+        models.User._meta.permissions = self._original_user_permissions
88+
89+
90+    def test_permission_duplicates_checking(self):
91+        """Test that we show proper error message if we are trying to
92+        create duplicate permissions.
93+        """
94+        models.User._meta.permissions = [
95+           ('change_user', 'Can edit user (duplicate)')]
96+        self.assertRaisesRegexp(CommandError,
97+            'The permission codename change_user clashes with a builtin '
98+            'for model auth.User.',
99+            create_permissions, models, [], verbosity=0)
100+
101+        models.User._meta.permissions = [
102+            ('my_custom_permission', 'Some permission'),
103+            ('other_one', 'Some other permission'),
104+            ('my_custom_permission', 'Some permission with duplicate code'),
105+        ]
106+        self.assertRaisesRegexp(CommandError,
107+            'The permission codename is duplicated for model auth.User: '
108+            'my_custom_permission',
109+            create_permissions, models, [], verbosity=0)
110+
111+        # should not raise anything
112+        models.User._meta.permissions = [
113+            ('my_custom_permission', 'Some permission'),
114+            ('other_one', 'Some other permission'),
115+        ]
116+        create_permissions(models, [], verbosity=0)
117+