Coverage for src/model_permissions/views.py: 100.00%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2django-model-permissions - simple object permissions for django.
4Copyright (C) 2018 Mathias Stelzer
6This program is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
16You should have received a copy of the GNU General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18"""
19from django.contrib.auth.context_processors import PermLookupDict, PermWrapper
20from django.core.exceptions import PermissionDenied
21from django.views.generic import (
22 DetailView as DjangoDetailView,
23 UpdateView as DjangoUpdateView,
24 DeleteView as DjangoDeleteView,
25)
28class ObjPermLookupDict(PermLookupDict):
29 """Object permissions lookup dictionary."""
31 def __init__(self, user, app_label, obj=None):
32 """Initialize object permission lookup dictionary."""
33 super(ObjPermLookupDict, self).__init__(user, app_label)
34 self.object = obj
36 def __getitem__(self, perm_name):
37 """Check whether the user has the given permission for the object."""
38 return self.user.has_perm('{}.{}'.format(self.app_label, perm_name), self.object)
41class ObjPermWrapper(PermWrapper):
42 """Object permissions wrapper to traverse a list of permissions."""
44 def __init__(self, user, obj=None):
45 """Initialize object permissions wrapper."""
46 super(ObjPermWrapper, self).__init__(user)
47 self.object = obj
49 def __getitem__(self, app_label):
50 """Get a lookup dictionary for the object."""
51 return ObjPermLookupDict(self.user, app_label, self.object)
54class PermissionContextMixin(object):
55 """
56 View mixin to insert permissions in the template context.
58 If the `get_context_data` method is called and the context contains
59 an `'object'` element, this will insert a `'object_perms'` permission
60 wrapper.
62 The `get_context_object_name` method will be used too, if it exists.
63 """
65 def get_context_data(self, **kwargs):
66 """Add object permissions to template context."""
67 kwargs = super().get_context_data(**kwargs)
68 if getattr(self, 'object', None):
69 permission_wrapper = ObjPermWrapper(self.request.user, self.object)
70 kwargs['object_perms'] = permission_wrapper
71 if hasattr(self, 'get_context_object_name'):
72 context_object_name = self.get_context_object_name(self.object)
73 if context_object_name:
74 kwargs[context_object_name + '_perms'] = permission_wrapper
75 return kwargs
78class RequirePermissionMixin(object):
79 """View mixin to require object permissions for access."""
81 required_permission = None
83 # noinspection PyMethodMayBeStatic
84 def get_required_permission_object(self, obj):
85 """Overwrite to check the required_permission against another model object."""
86 return obj
88 def check_required_permission(self, permission_object):
89 """
90 Check the `required_permission` on the given object.
92 :raises: :class:`django.core.exceptions.PermissionDenied` if the
93 current user does not have the `required_permission`.
94 """
95 if not self.has_perm(self.required_permission, permission_object):
96 raise PermissionDenied()
98 def get_object(self, queryset=None):
99 """
100 Get the object and check the `required_permission` on it.
102 :raises: :class:`django.core.exceptions.PermissionDenied` if the
103 current user does not have the `required_permission`.
104 """
105 obj = super().get_object(queryset=queryset)
107 if self.required_permission is not None:
108 perm_obj = self.get_required_permission_object(obj)
109 self.check_required_permission(perm_obj)
111 return obj
113 def has_perm(self, perm, obj=None):
114 """Check the given permission on the given object."""
115 return self.request.user.has_perm(perm, obj=obj)
118class PermissionMixin(RequirePermissionMixin, PermissionContextMixin):
119 """View mixin to enable permissions."""
121 pass
124class DetailView(PermissionMixin, DjangoDetailView):
125 """DetailView with permissions."""
127 pass
130class UpdateView(PermissionMixin, DjangoUpdateView):
131 """UpdateView with permissions."""
133 pass
136class DeleteView(PermissionMixin, DjangoDeleteView):
137 """DeleteView with permissions."""
139 pass