Ticket #3583: modpython.2.py

File modpython.2.py, 4.4 KB (added by TomFreudenberg, 8 years ago)

This is an update to apache_auth.2.patch. First: error of wrong "self" is fixed, second: The check was splitted to check if user is authenticated (if not raise UNAUTHORIZED) and the validate user for permissions (if not raise FORBIDDEN)

Line 
1from mod_python import apache
2import os
3from django.core import signals
4from django.dispatch import dispatcher
5from django.core.handlers.base import BaseHandler
6from django.core.handlers.modpython import ModPythonRequest
7from django.contrib.auth import authenticate
8
9_str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
10
11class ModPythonAuthOptions:
12    def __init__(self, req):
13        options = req.get_options()
14        self.permission_name = options.get('DjangoPermissionName', None)
15        self.staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))
16        self.superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))
17        self.settings_module = options.get('DJANGO_SETTINGS_MODULE', None)
18
19def setup_environment(req, options):
20    """
21    mod_python fakes the environ, and thus doesn't process SetEnv. This ensures
22    any future imports relying on settings will work.
23    """
24    os.environ.update(req.subprocess_env)
25    if options.settings_module:
26        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings_module
27
28def authenticate_user(user, options):
29    if not user:
30        return False
31    # Require an is_authenticated property and check it
32    if not hasattr(user, 'is_authenticated') or not user.is_authenticated():
33        return False
34    return True
35
36def validate_user(user, options):
37    # Don't require an is_active property, but if it's there then check it
38    if hasattr(user, 'is_active') and not user.is_active:
39        return False
40    if options.staff_only and not getattr(user, 'is_staff', None):
41        return False
42    if options.superuser_only and not getattr(user, 'is_superuser', None):
43        return False
44    # If a permission is required then user must have a has_perm function to validate
45    if options.permission_name and (not hasattr(user, 'has_perm') or not user.has_perm(options.permission_name)):
46        return False
47    return True
48
49def authenhandler(req, **kwargs):
50    """
51    mod_python authentication handler that checks against Django's auth
52    database.
53    """
54    options = ModPythonAuthOptions(req)
55    setup_environment(req, options)
56
57    dispatcher.send(signal=signals.request_started)
58    try:
59        # This populates req.user too, so it's important to do first
60        password = req.get_basic_auth_pw()
61
62        # Get the user from any of the installed backends
63        user = authenticate(username=req.user, password=password)
64
65        # Raise unauthorized if the user wasn't authenticated to bring up
66        # a password dialog box to allow the user to authenticate.
67
68        # Check authentification of the user
69        if not authenticate_user(user, options):
70            return apache.HTTP_UNAUTHORIZED
71
72        # Validate and check permission of the user
73        if validate_user(user, options):
74            return apache.OK
75        else:
76            # mod_python docs say that HTTP_FORBIDDEN should be raised if the
77            # user authenticates but doesn't validate.
78            return apache.HTTP_FORBIDDEN
79    finally:
80        dispatcher.send(signal=signals.request_finished)
81
82def accesshandler(req):
83    """
84    mod_python access handler that uses the contrib.auth framework (with
85    sessions and therefore requiring a session cookie).
86    """
87    options = ModPythonAuthOptions(req)
88    setup_environment(req, options)
89
90    # Set up middleware, now that settings works we can do it now.
91    base_handler = BaseHandler()
92    base_handler.load_middleware()
93
94    dispatcher.send(signal=signals.request_started)
95    try:
96        request = ModPythonRequest(req)
97
98        # Apply request middleware
99        for middleware_method in base_handler._request_middleware:
100            response = middleware_method(request)
101            if response:
102                # If we get a response, we should probably stop processing any
103                # remaining request middleware.
104                break
105
106        # get user object
107        user = getattr(request, 'user', None)
108
109        # Check authentification of the user
110        if not authenticate_user(user, options):
111            return apache.HTTP_UNAUTHORIZED
112
113        # Validate and check permission of the user
114        if validate_user(user, options):
115            return apache.OK
116        else:
117            # mod_python docs say that HTTP_FORBIDDEN should be raised if the
118            # user authenticates but doesn't validate.
119            return apache.HTTP_FORBIDDEN
120
121    finally:
122        dispatcher.send(signal=signals.request_finished)
Back to Top