1 | from mod_python import apache
|
---|
2 | import os
|
---|
3 | from django.core import signals
|
---|
4 | from django.dispatch import dispatcher
|
---|
5 | from django.core.handlers.base import BaseHandler
|
---|
6 | from django.core.handlers.modpython import ModPythonRequest
|
---|
7 | from django.contrib.auth import authenticate
|
---|
8 |
|
---|
9 | _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
|
---|
10 |
|
---|
11 | class 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 |
|
---|
19 | def 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 |
|
---|
28 | def 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 |
|
---|
36 | def 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 |
|
---|
49 | def 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 |
|
---|
82 | def 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)
|
---|