1 """The visit and identity management *plugins* are defined here."""
2
3 __all__ = [
4 'IdentityVisitPlugin',
5 'create_extension_model',
6 'shutdown_extension',
7 'start_extension',
8 ]
9
10 import base64
11 import logging
12
13 from cherrypy import request
14
15 from turbogears import config, visit
16 from turbogears.identity import (create_default_provider, set_current_identity,
17 set_current_provider, set_login_attempted)
18 from turbogears.util import pop_request_params
19
20 from turbogears.identity.exceptions import *
21
22
23 log = logging.getLogger("turbogears.identity")
24
25
26
27
48
49
51 """Stops the IdentityVisitPlugin.
52
53 This is practically a no-op currently.
54
55 """
56
57 if not config.get('identity.on', False):
58 return
59 log.info("Identity shutting down")
60
61
66
67
69 """Visit plug-in tying the Identity framework to the visit management."""
70
72 log.info("Identity visit plugin initialized")
73 get = config.get
74
75 self.provider = create_default_provider()
76
77
78
79
80 self.user_name_field = get('identity.form.user_name', 'user_name').split('.')
81 self.password_field = get('identity.form.password', 'password').split('.')
82 self.submit_button_name = get('identity.form.submit', 'login').split('.')
83
84
85
86
87 sources = filter(None, map(str.strip,
88 get('identity.source', 'form,http_auth,visit').split(',')))
89 if not sources:
90 raise IdentityConfigurationException(
91 "You must set some identity source (via identity.source).")
92 if 'http_auth' in sources and not get('identity.http_basic_auth'):
93 sources.remove('http_auth')
94 if 'visit' in sources and not get('visit.on'):
95 sources.remove('visit')
96 if not sources:
97 raise IdentityConfigurationException(
98 "You must activate at least one of the identity sources.")
99 self.identity_sources = list()
100 for s in sources:
101 if s:
102 try:
103 source_method = getattr(self, 'identity_from_' + s)
104 except AttributeError:
105 raise IdentityConfigurationException(
106 "Invalid identity source: %s" % s)
107 self.identity_sources.append(source_method)
108
110 """Retrieve identity information from the HTTP request.
111
112 Checks first for form fields defining the identity then for a cookie.
113 If no identity is found, returns an anonymous identity.
114
115 """
116 identity = None
117 log.debug("Retrieving identity for visit: %s", visit_key)
118 for source in self.identity_sources:
119 identity = source(visit_key)
120 if identity:
121 return identity
122
123 log.debug("No identity found")
124
125 identity = self.provider.anonymous_identity()
126 return identity
127
129 """Decode base64 user_name:password credentials used in Basic Auth.
130
131 Returns a list with username in element 0 and password in element 1.
132
133 """
134 credentials = base64.decodestring(credentials.strip())
135 try:
136 credentials = credentials.decode('utf-8')
137 except UnicodeError:
138 try:
139 credentials = credentials.decode('latin-1')
140 except UnicodeError:
141 credentials = ''
142 credentials = credentials.split(':', 1)
143 if len(credentials) < 2:
144 credentials.append('')
145 return credentials
146
148 """Try to get authentication data from Authorization request header.
149
150 Only HTTP basic auth is handled at the moment.
151
152 """
153 try:
154 authorisation = request.headers['Authorization']
155 except KeyError:
156 return None
157
158 authScheme, schemeData = authorisation.split(' ', 1)
159
160 if authScheme.lower() != 'basic':
161 log.error("HTTP Auth is not basic")
162 return None
163
164
165 user_name, password = self.decode_basic_credentials(schemeData)
166 set_login_attempted(True)
167 return self.provider.validate_identity(user_name, password, visit_key)
168
172
210
231