Login

middleware for user_passes_test

Author:
gsf0
Posted:
October 21, 2009
Language:
Python
Version:
1.1
Score:
-1 (after 1 ratings)

Middleware to decorate views with user_passes_test in a centralized, url-matching manner. Makes it easy to apply permissions across large sections or all of a site.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import re

import django.conf as conf
import django.contrib.auth.decorators as ad


class UserPassesTestMiddleware(object):
    """
    Originally adapted from mattgrayson's snippet at
    http://www.djangosnippets.org/snippets/1219/.

    Middleware component that wraps the user_passes_test decorator around 
    views for matching URL patterns. To use, add the class to 
    MIDDLEWARE_CLASSES and define USER_PASSES_TEST_URLS in your settings.py.

    The following example limits access to anything under "/topsecret/" to 
    authenticated users:
    
    USER_PASSES_TEST_URLS = (
        (r'^/topsecret/', lambda u: u.is_authenticated),
    )
    
    The following example locks down a typical site, giving access to 
    staff only:
    
    USER_PASSES_TEST_URLS = (
        (r'^/$', None), 
        (r'^/login/$', None),
        (r'^/logout/$', None),
        (r'^/media/', None),
        (r'^/passwordreset/', None),
        (r'', lambda u: u.is_staff),
    )

    Note that patterns with a test of "None" pass the matching view through
    unwrapped.  Also, this example works because the order of 
    USER_PASSES_TEST_URLS matters.  The first matching pattern is the only 
    one applied.  
    
    Views already wrapped in an auth decorator are untouched, so 
    permissions can still be controlled on a view-by-view basis.
    """
    def __init__(self):
        self.urls = [(re.compile(pattern), test) for pattern, test in
            conf.settings.USER_PASSES_TEST_URLS]

    def process_view(self, request, view_func, view_args, view_kwargs):
        # don't wrap if function is already wrapped
        if getattr(view_func, 'decorator', None):
            return
        for regex, test in self.urls:
            if regex.search(request.path):
                if test:  # return view wrapped in test
                    return ad.user_passes_test(test)(view_func)(request,
                        *view_args, **view_kwargs)
                else:  # no test, don't wrap
                    return

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

oduvan (on October 25, 2009):

Why this just don't make as decorator of view function?

#

gsf0 (on October 29, 2009):

@oduvan Because sometimes you want to apply permissions across a good section of a site without making sure there's a decorator on every view.

#

Please login first before commenting.