Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save caot/74d10f35f95df4fa1f34f0d6271fb1c9 to your computer and use it in GitHub Desktop.
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.
"""
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