1
+ import inspect
1
2
import datetime
2
3
import re
3
4
import six
7
8
from django .contrib .auth .views import redirect_to_login , logout_then_login
8
9
from django .core .exceptions import ImproperlyConfigured , PermissionDenied
9
10
from django .http import (HttpResponseRedirect , HttpResponsePermanentRedirect ,
10
- Http404 )
11
+ Http404 , HttpResponse )
11
12
from django .shortcuts import resolve_url
12
13
from django .utils .encoding import force_text
13
14
from django .utils .timezone import now
14
15
16
+ # StreamingHttpResponse has been added in 1.5, and gets used for verification
17
+ # only.
18
+ try :
19
+ from django .http import StreamingHttpResponse
20
+ except ImportError :
21
+ class StreamingHttpResponse (object ):
22
+ pass
23
+
15
24
16
25
class AccessMixin (object ):
17
26
"""
18
27
'Abstract' mixin that gives access mixins the same customizable
19
28
functionality.
20
29
"""
21
30
login_url = None
22
- raise_exception = False # Default whether to raise an exception to none
31
+ raise_exception = False
23
32
redirect_field_name = REDIRECT_FIELD_NAME # Set by django.contrib.auth
33
+ redirect_unauthenticated_users = False
24
34
25
35
def get_login_url (self ):
26
36
"""
@@ -46,6 +56,30 @@ def get_redirect_field_name(self):
46
56
self .__class__ .__name__ ))
47
57
return self .redirect_field_name
48
58
59
+ def handle_no_permission (self , request ):
60
+ if self .raise_exception and not self .redirect_unauthenticated_users :
61
+ if (inspect .isclass (self .raise_exception )
62
+ and issubclass (self .raise_exception , Exception )):
63
+ raise self .raise_exception
64
+ if callable (self .raise_exception ):
65
+ ret = self .raise_exception (request )
66
+ if isinstance (ret , (HttpResponse , StreamingHttpResponse )):
67
+ return ret
68
+ raise PermissionDenied
69
+
70
+ return self .no_permissions_fail (request )
71
+
72
+ def no_permissions_fail (self , request = None ):
73
+ """
74
+ Called when the user has no permissions and no exception was raised.
75
+ This should only return a valid HTTP response.
76
+
77
+ By default we redirect to login.
78
+ """
79
+ return redirect_to_login (request .get_full_path (),
80
+ self .get_login_url (),
81
+ self .get_redirect_field_name ())
82
+
49
83
50
84
class LoginRequiredMixin (AccessMixin ):
51
85
"""
@@ -56,17 +90,9 @@ class LoginRequiredMixin(AccessMixin):
56
90
combined with CsrfExemptMixin - which in that case should
57
91
be the left-most mixin.
58
92
"""
59
- redirect_unauthenticated_users = False
60
-
61
93
def dispatch (self , request , * args , ** kwargs ):
62
94
if not request .user .is_authenticated ():
63
- if (self .raise_exception and
64
- not self .redirect_unauthenticated_users ):
65
- raise PermissionDenied # return a forbidden response
66
- else :
67
- return redirect_to_login (request .get_full_path (),
68
- self .get_login_url (),
69
- self .get_redirect_field_name ())
95
+ return self .handle_no_permission (request )
70
96
71
97
return super (LoginRequiredMixin , self ).dispatch (
72
98
request , * args , ** kwargs )
@@ -157,28 +183,15 @@ def check_permissions(self, request):
157
183
perms = self .get_permission_required (request )
158
184
return request .user .has_perm (perms )
159
185
160
- def no_permissions_fail (self , request = None ):
161
- """
162
- Called when the user has no permissions. This should only
163
- return a valid HTTP response.
164
-
165
- By default we redirect to login.
166
- """
167
- return redirect_to_login (request .get_full_path (),
168
- self .get_login_url (),
169
- self .get_redirect_field_name ())
170
-
171
186
def dispatch (self , request , * args , ** kwargs ):
172
187
"""
173
188
Check to see if the user in the request has the required
174
189
permission.
175
190
"""
176
191
has_permission = self .check_permissions (request )
177
192
178
- if not has_permission : # If the user lacks the permission
179
- if self .raise_exception :
180
- raise PermissionDenied # Return a 403
181
- return self .no_permissions_fail (request )
193
+ if not has_permission :
194
+ return self .handle_no_permission (request )
182
195
183
196
return super (PermissionRequiredMixin , self ).dispatch (
184
197
request , * args , ** kwargs )
@@ -318,13 +331,8 @@ def dispatch(self, request, *args, **kwargs):
318
331
in_group = self .check_membership (self .get_group_required ())
319
332
320
333
if not in_group :
321
- if self .raise_exception :
322
- raise PermissionDenied
323
- else :
324
- return redirect_to_login (
325
- request .get_full_path (),
326
- self .get_login_url (),
327
- self .get_redirect_field_name ())
334
+ return self .handle_no_permission (request )
335
+
328
336
return super (GroupRequiredMixin , self ).dispatch (
329
337
request , * args , ** kwargs )
330
338
@@ -354,13 +362,9 @@ def get_test_func(self):
354
362
def dispatch (self , request , * args , ** kwargs ):
355
363
user_test_result = self .get_test_func ()(request .user )
356
364
357
- if not user_test_result : # If user don't pass the test
358
- if self .raise_exception : # *and* if an exception was desired
359
- raise PermissionDenied
360
- else :
361
- return redirect_to_login (request .get_full_path (),
362
- self .get_login_url (),
363
- self .get_redirect_field_name ())
365
+ if not user_test_result :
366
+ return self .handle_no_permission (request )
367
+
364
368
return super (UserPassesTestMixin , self ).dispatch (
365
369
request , * args , ** kwargs )
366
370
@@ -370,13 +374,8 @@ class SuperuserRequiredMixin(AccessMixin):
370
374
Mixin allows you to require a user with `is_superuser` set to True.
371
375
"""
372
376
def dispatch (self , request , * args , ** kwargs ):
373
- if not request .user .is_superuser : # If the user is a standard user,
374
- if self .raise_exception : # *and* if an exception was desired
375
- raise PermissionDenied # return a forbidden response.
376
- else :
377
- return redirect_to_login (request .get_full_path (),
378
- self .get_login_url (),
379
- self .get_redirect_field_name ())
377
+ if not request .user .is_superuser :
378
+ return self .handle_no_permission (request )
380
379
381
380
return super (SuperuserRequiredMixin , self ).dispatch (
382
381
request , * args , ** kwargs )
@@ -387,13 +386,8 @@ class StaffuserRequiredMixin(AccessMixin):
387
386
Mixin allows you to require a user with `is_staff` set to True.
388
387
"""
389
388
def dispatch (self , request , * args , ** kwargs ):
390
- if not request .user .is_staff : # If the request's user is not staff,
391
- if self .raise_exception : # *and* if an exception was desired
392
- raise PermissionDenied # return a forbidden response
393
- else :
394
- return redirect_to_login (request .get_full_path (),
395
- self .get_login_url (),
396
- self .get_redirect_field_name ())
389
+ if not request .user .is_staff :
390
+ return self .handle_no_permission (request )
397
391
398
392
return super (StaffuserRequiredMixin , self ).dispatch (
399
393
request , * args , ** kwargs )
0 commit comments