|
1 |
| -import sys |
2 |
| - |
3 |
| -from django.apps import apps |
4 |
| -from django.conf import settings |
5 |
| -from django.contrib.auth.models import Group, Permission |
6 |
| -from django.contrib.contenttypes.models import ContentType |
7 |
| -from django.core.exceptions import ObjectDoesNotExist |
8 |
| -from django.db.models.signals import post_migrate |
9 |
| - |
10 |
| -from smartmin.perms import assign_perm, remove_perm |
11 |
| - |
12 |
| -permissions_app_name = None |
13 |
| - |
14 |
| - |
15 |
| -def get_permissions_app_name(): |
16 |
| - """ |
17 |
| - Gets the app after which smartmin permissions should be installed. This can be specified by PERMISSIONS_APP in the |
18 |
| - Django settings or defaults to the last app with models |
19 |
| - """ |
20 |
| - global permissions_app_name |
21 |
| - |
22 |
| - if not permissions_app_name: |
23 |
| - permissions_app_name = getattr(settings, "PERMISSIONS_APP", None) |
24 |
| - |
25 |
| - if not permissions_app_name: |
26 |
| - app_names_with_models = [a.name for a in apps.get_app_configs() if a.models_module is not None] |
27 |
| - if app_names_with_models: |
28 |
| - permissions_app_name = app_names_with_models[-1] |
29 |
| - |
30 |
| - return permissions_app_name |
31 |
| - |
32 |
| - |
33 |
| -def is_permissions_app(app_config): |
34 |
| - """ |
35 |
| - Returns whether this is the app after which permissions should be installed. |
36 |
| - """ |
37 |
| - return app_config.name == get_permissions_app_name() |
38 |
| - |
39 |
| - |
40 |
| -def check_role_permissions(role, permissions, current_permissions): |
41 |
| - """ |
42 |
| - Checks the the passed in role (can be user, group or AnonymousUser) has all the passed |
43 |
| - in permissions, granting them if necessary. |
44 |
| - """ |
45 |
| - role_permissions = [] |
46 |
| - |
47 |
| - # get all the current permissions, we'll remove these as we verify they should still be granted |
48 |
| - for permission in permissions: |
49 |
| - splits = permission.split(".") |
50 |
| - if len(splits) != 2 and len(splits) != 3: |
51 |
| - sys.stderr.write(" invalid permission %s, ignoring\n" % permission) |
52 |
| - continue |
53 |
| - |
54 |
| - app = splits[0] |
55 |
| - codenames = [] |
56 |
| - |
57 |
| - if len(splits) == 2: |
58 |
| - codenames.append(splits[1]) |
59 |
| - else: |
60 |
| - (object, action) = splits[1:] |
61 |
| - |
62 |
| - # if this is a wildcard, then query our database for all the permissions that exist on this object |
63 |
| - if action == "*": |
64 |
| - for perm in Permission.objects.filter(codename__startswith="%s_" % object, content_type__app_label=app): |
65 |
| - codenames.append(perm.codename) |
66 |
| - # otherwise, this is an error, continue |
67 |
| - else: |
68 |
| - sys.stderr.write(" invalid permission %s, ignoring\n" % permission) |
69 |
| - continue |
70 |
| - |
71 |
| - if len(codenames) == 0: |
72 |
| - continue |
73 |
| - |
74 |
| - for codename in codenames: |
75 |
| - # the full codename for this permission |
76 |
| - full_codename = "%s.%s" % (app, codename) |
77 |
| - |
78 |
| - # this marks all the permissions which should remain |
79 |
| - role_permissions.append(full_codename) |
80 |
| - |
81 |
| - try: |
82 |
| - assign_perm(full_codename, role) |
83 |
| - except ObjectDoesNotExist: |
84 |
| - pass |
85 |
| - # sys.stderr.write(" unknown permission %s, ignoring\n" % permission) |
86 |
| - |
87 |
| - # remove any that are extra |
88 |
| - for permission in current_permissions: |
89 |
| - if isinstance(permission, str): |
90 |
| - key = permission |
91 |
| - else: |
92 |
| - key = "%s.%s" % (permission.content_type.app_label, permission.codename) |
93 |
| - |
94 |
| - if key not in role_permissions: |
95 |
| - remove_perm(key, role) |
96 |
| - |
97 |
| - |
98 |
| -def check_all_group_permissions(sender, **kwargs): |
99 |
| - """ |
100 |
| - Checks that all the permissions specified in our settings.py are set for our groups. |
101 |
| - """ |
102 |
| - if not is_permissions_app(sender): |
103 |
| - return |
104 |
| - |
105 |
| - config = getattr(settings, "GROUP_PERMISSIONS", dict()) |
106 |
| - |
107 |
| - # for each of our items |
108 |
| - for name, permissions in config.items(): |
109 |
| - # get or create the group |
110 |
| - (group, created) = Group.objects.get_or_create(name=name) |
111 |
| - if created: |
112 |
| - pass |
113 |
| - |
114 |
| - check_role_permissions(group, permissions, group.permissions.all()) |
115 |
| - |
116 |
| - |
117 |
| -def add_permission(content_type, permission): |
118 |
| - """ |
119 |
| - Adds the passed in permission to that content type. Note that the permission passed |
120 |
| - in should be a single word, or verb. The proper 'codename' will be generated from that. |
121 |
| - """ |
122 |
| - # build our permission slug |
123 |
| - codename = "%s_%s" % (content_type.model, permission) |
124 |
| - |
125 |
| - # sys.stderr.write("Checking %s permission for %s\n" % (permission, content_type.name)) |
126 |
| - |
127 |
| - # does it already exist |
128 |
| - if not Permission.objects.filter(content_type=content_type, codename=codename): |
129 |
| - Permission.objects.create( |
130 |
| - content_type=content_type, codename=codename, name="Can %s %s" % (permission, content_type.name) |
131 |
| - ) |
132 |
| - # sys.stderr.write("Added %s permission for %s\n" % (permission, content_type.name)) |
133 |
| - |
134 |
| - |
135 |
| -def check_all_permissions(sender, **kwargs): |
136 |
| - """ |
137 |
| - This syncdb checks our PERMISSIONS setting in settings.py and makes sure all those permissions |
138 |
| - actually exit. |
139 |
| - """ |
140 |
| - if not is_permissions_app(sender): |
141 |
| - return |
142 |
| - |
143 |
| - config = getattr(settings, "PERMISSIONS", dict()) |
144 |
| - |
145 |
| - # for each of our items |
146 |
| - for natural_key, permissions in config.items(): |
147 |
| - # if the natural key '*' then that means add to all objects |
148 |
| - if natural_key == "*": |
149 |
| - # for each of our content types |
150 |
| - for content_type in ContentType.objects.all(): |
151 |
| - for permission in permissions: |
152 |
| - add_permission(content_type, permission) |
153 |
| - |
154 |
| - # otherwise, this is on a specific content type, add for each of those |
155 |
| - else: |
156 |
| - app, model = natural_key.split(".") |
157 |
| - try: |
158 |
| - content_type = ContentType.objects.get_by_natural_key(app, model) |
159 |
| - except ContentType.DoesNotExist: |
160 |
| - continue |
161 |
| - |
162 |
| - # add each permission |
163 |
| - for permission in permissions: |
164 |
| - add_permission(content_type, permission) |
165 |
| - |
166 |
| - |
167 |
| -post_migrate.connect(check_all_permissions) |
168 |
| -post_migrate.connect(check_all_group_permissions) |
0 commit comments