-
-
Save caot/74d10f35f95df4fa1f34f0d6271fb1c9 to your computer and use it in GitHub Desktop.
Django middleware component that wraps the login_required decorator around all URL patterns be default, with exceptions. Can also require user to belong to a group ("admin" in this gist) or be adapted if using the Django admin app.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Middleware component that wraps the login_required decorator around all URL patterns be default, with exceptions. | |
Define PUBLIC_URLS and ADMIN_URLS using regex in settings.py, where: | |
PUBLIC_URLS do not require user to be logged in. | |
ADMIN_URLS require user to be in admin group. | |
Source: http://stackoverflow.com/a/2164224/720054 | |
""" | |
# settings.py | |
PUBLIC_URLS = ( | |
r'/accounts/register/(.*)$', | |
r'/accounts/activate/(.*)$', | |
r'/accounts/password/reset/(.*)$', | |
r'/accounts/login/(.*)$', | |
r'/api/(.*)$', | |
) | |
ADMIN_URLS = ( | |
r'/admin/(.*)$', | |
) | |
MIDDLEWARE_CLASSES = ( | |
# Other middleware... | |
'middleware.LoginRequiredMiddleware', | |
) | |
# middleware.py | |
import re | |
from django.conf import settings | |
from django.contrib.auth.decorators import login_required, user_passes_test | |
class LoginRequiredMiddleware(object): | |
def __init__(self): | |
self.admin = tuple(re.compile(url) for url in settings.ADMIN_URLS) | |
self.public = tuple(re.compile(url) for url in settings.PUBLIC_URLS) | |
def process_view(self, request, view_func, view_args, view_kwargs): | |
# No need to process URLs if user is admin | |
if request.user.groups.filter(name="admin").exists(): | |
return None | |
# Requests matching an admin URL pattern are returned wrapped with the user_passes_test decorator | |
for url in self.admin: | |
if url.match(request.path): | |
return user_passes_test(lambda u: u.groups.filter(name="admin").exists())(view_func)(request, *view_args, **view_kwargs) | |
# No need to process remaining URLs if user already logged in | |
if request.user.is_authenticated(): | |
return None | |
# An exception match (public) should immediately return None | |
for url in self.public: | |
if url.match(request.path): | |
return None | |
# Require login for all non-matching requests | |
return login_required(view_func)(request, *view_args, **view_kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment