0
# Access Control and Authentication
1
2
Comprehensive authentication and authorization mixins for Django class-based views. These mixins provide fine-grained access control, from simple login requirements to complex permission checking and secure connection enforcement.
3
4
## Capabilities
5
6
### Common Access Control Attributes
7
8
All access control mixins inherit common functionality for login redirects and permission handling. These attributes are available on all access mixins:
9
10
- `login_url = None` - URL to redirect to for login (defaults to settings.LOGIN_URL)
11
- `raise_exception = False` - Whether to raise PermissionDenied or redirect
12
- `redirect_field_name = 'next'` - Field name for storing redirect URL
13
- `redirect_unauthenticated_users = False` - Special handling for unauthenticated users
14
15
Common methods available on access mixins:
16
- `get_login_url()` - Get the login URL (can be overridden)
17
- `get_redirect_field_name()` - Get redirect field name (can be overridden)
18
- `handle_no_permission(request)` - Handle permission failures
19
- `no_permissions_fail(request)` - Default failure handler (redirects to login)
20
21
### User Authentication
22
23
Require user authentication with flexible redirect handling.
24
25
```python { .api }
26
class LoginRequiredMixin(AccessMixin):
27
"""Requires the user to be authenticated"""
28
29
def dispatch(self, request, *args, **kwargs):
30
"""Call appropriate method after checking authentication"""
31
```
32
33
Usage example:
34
35
```python
36
from django.views.generic import ListView
37
from braces.views import LoginRequiredMixin
38
39
class ProtectedListView(LoginRequiredMixin, ListView):
40
model = MyModel
41
login_url = '/accounts/login/'
42
redirect_field_name = 'next'
43
raise_exception = False # Redirect instead of 403
44
```
45
46
### Anonymous User Requirement
47
48
Require user to be unauthenticated, useful for login/register pages.
49
50
```python { .api }
51
class AnonymousRequiredMixin(AccessMixin):
52
"""Requires the user to be unauthenticated"""
53
authenticated_redirect_url = '/accounts/profile/'
54
55
def dispatch(self, request, *args, **kwargs):
56
"""Call appropriate handler after guaranteeing anonymity"""
57
58
def get_authenticated_redirect_url(self):
59
"""Return the reversed authenticated redirect url"""
60
```
61
62
Usage example:
63
64
```python
65
from django.views.generic import TemplateView
66
from braces.views import AnonymousRequiredMixin
67
68
class LoginPageView(AnonymousRequiredMixin, TemplateView):
69
template_name = 'registration/login.html'
70
authenticated_redirect_url = '/dashboard/'
71
```
72
73
### Permission-Based Access
74
75
Require specific Django permissions before granting access.
76
77
```python { .api }
78
class PermissionRequiredMixin(AccessMixin):
79
"""Requires user to have specific permission(s)"""
80
permission_required = None
81
object_level_permissions = False
82
83
def get_permission_required(self, request=None):
84
"""Get required permissions and return them"""
85
86
def check_permissions(self, request):
87
"""Returns whether user has permissions"""
88
89
def dispatch(self, request, *args, **kwargs):
90
"""Check user has required permission"""
91
```
92
93
Usage example:
94
95
```python
96
from django.views.generic import UpdateView
97
from braces.views import PermissionRequiredMixin
98
99
class EditPostView(PermissionRequiredMixin, UpdateView):
100
model = Post
101
permission_required = 'blog.change_post'
102
object_level_permissions = True # Check permission on specific object
103
raise_exception = True # Return 403 instead of redirect
104
```
105
106
### Multiple Permission Requirements
107
108
Complex permission checking with AND/OR logic for multiple permissions.
109
110
```python { .api }
111
class MultiplePermissionsRequiredMixin(PermissionRequiredMixin):
112
"""Allows specifying multiple permissions with 'all' and 'any' logic"""
113
permissions = None # Dict with 'all' and/or 'any' keys
114
115
def get_permission_required(self, request=None):
116
"""Get which permission is required"""
117
118
def check_permissions(self, request):
119
"""Get the permissions, both all and any"""
120
```
121
122
Usage example:
123
124
```python
125
from django.views.generic import CreateView
126
from braces.views import MultiplePermissionsRequiredMixin
127
128
class CreatePostView(MultiplePermissionsRequiredMixin, CreateView):
129
model = Post
130
permissions = {
131
'all': ('blog.add_post', 'blog.change_post'), # Must have ALL of these
132
'any': ('blog.publish_post', 'user.is_editor') # Must have ANY of these
133
}
134
```
135
136
### Group Membership
137
138
Require membership in specific Django groups.
139
140
```python { .api }
141
class GroupRequiredMixin(AccessMixin):
142
"""Requires user membership in specific group(s)"""
143
group_required = None # String, list, or tuple of group names
144
145
def get_group_required(self):
146
"""Get which group's membership is required"""
147
148
def check_membership(self, groups):
149
"""Check user's membership in required groups"""
150
151
def dispatch(self, request, *args, **kwargs):
152
"""Call appropriate handler if user is group member"""
153
```
154
155
Usage example:
156
157
```python
158
from django.views.generic import ListView
159
from braces.views import GroupRequiredMixin
160
161
class AdminListView(GroupRequiredMixin, ListView):
162
model = MyModel
163
group_required = ['admins', 'moderators'] # User must be in one of these groups
164
```
165
166
### Custom User Tests
167
168
Custom validation logic for user access control.
169
170
```python { .api }
171
class UserPassesTestMixin(AccessMixin):
172
"""User must pass custom test before accessing view"""
173
174
def test_func(self, user):
175
"""The function to test the user with - must be implemented"""
176
177
def get_test_func(self):
178
"""Get the test function"""
179
180
def dispatch(self, request, *args, **kwargs):
181
"""Call appropriate handler if user passes test"""
182
```
183
184
Usage example:
185
186
```python
187
from django.views.generic import DetailView
188
from braces.views import UserPassesTestMixin
189
190
class ProfileView(UserPassesTestMixin, DetailView):
191
model = Profile
192
193
def test_func(self, user):
194
profile = self.get_object()
195
return user == profile.user or user.is_staff
196
```
197
198
### Superuser and Staff Requirements
199
200
Quick access control for administrative users.
201
202
```python { .api }
203
class SuperuserRequiredMixin(AccessMixin):
204
"""Require users to be superusers"""
205
206
def dispatch(self, request, *args, **kwargs):
207
"""Call appropriate handler if user is superuser"""
208
209
class StaffuserRequiredMixin(AccessMixin):
210
"""Require users to be marked as staff"""
211
212
def dispatch(self, request, *args, **kwargs):
213
"""Call appropriate handler if user is staff member"""
214
```
215
216
Usage example:
217
218
```python
219
from django.views.generic import ListView
220
from braces.views import SuperuserRequiredMixin
221
222
class AdminOnlyView(SuperuserRequiredMixin, ListView):
223
model = SensitiveModel
224
raise_exception = True
225
```
226
227
### Secure Connection Requirement
228
229
Enforce HTTPS connections with automatic redirect or error handling.
230
231
```python { .api }
232
class SSLRequiredMixin:
233
"""Require requests to be made over secure connection"""
234
raise_exception = False
235
236
def dispatch(self, request, *args, **kwargs):
237
"""Call appropriate handler if connection is secure"""
238
```
239
240
Usage example:
241
242
```python
243
from django.views.generic import FormView
244
from braces.views import SSLRequiredMixin
245
246
class PaymentFormView(SSLRequiredMixin, FormView):
247
template_name = 'payment.html'
248
raise_exception = True # Return 404 for non-HTTPS requests
249
```
250
251
### Recent Login Requirement
252
253
Force re-authentication after a specified time period.
254
255
```python { .api }
256
class RecentLoginRequiredMixin(LoginRequiredMixin):
257
"""Require user to have logged in within number of seconds"""
258
max_last_login_delta = 1800 # Default 30 minutes
259
260
def dispatch(self, request, *args, **kwargs):
261
"""Call appropriate method if user's login is recent"""
262
```
263
264
Usage example:
265
266
```python
267
from django.views.generic import UpdateView
268
from braces.views import RecentLoginRequiredMixin
269
270
class SensitiveUpdateView(RecentLoginRequiredMixin, UpdateView):
271
model = UserProfile
272
max_last_login_delta = 900 # Require login within last 15 minutes
273
```
274
275
## Common Usage Patterns
276
277
### Combining Access Controls
278
279
Multiple access mixins can be combined for layered security:
280
281
```python
282
from braces.views import LoginRequiredMixin, PermissionRequiredMixin, SSLRequiredMixin
283
284
class SecureAdminView(SSLRequiredMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
285
model = SensitiveModel
286
permission_required = 'myapp.change_sensitivemodel'
287
raise_exception = True
288
```
289
290
### Mixin Order
291
292
Access mixins should be placed leftmost in the inheritance chain (except when combined with CsrfExemptMixin, which should be leftmost).