diff options
Diffstat (limited to 'quoins/openid_controllers.py')
-rw-r--r-- | quoins/openid_controllers.py | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/quoins/openid_controllers.py b/quoins/openid_controllers.py new file mode 100644 index 0000000..9491195 --- /dev/null +++ b/quoins/openid_controllers.py | |||
@@ -0,0 +1,186 @@ | |||
1 | # Quoins - A TurboGears blogging system. | ||
2 | # Copyright (C) 2008-2009 James E. Blair <corvus@gnu.org> | ||
3 | # | ||
4 | # This program is free software: you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation, either version 3 of the License, or | ||
7 | # (at your option) any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | from tg import controllers, expose, flash, require, validate, request, redirect, session | ||
18 | from tg import TGController | ||
19 | import tg | ||
20 | import pylons | ||
21 | from repoze.what import predicates | ||
22 | import openid.consumer.consumer | ||
23 | import openid.server.server | ||
24 | import openid.extensions.sreg | ||
25 | from openid.store.sqlstore import MySQLStore | ||
26 | import MySQLdb | ||
27 | import sqlalchemy.engine.url | ||
28 | import types | ||
29 | import os.path | ||
30 | |||
31 | from utils import get_oid_connection | ||
32 | |||
33 | class DecideController(object): | ||
34 | def __init__(self, oid_controller): | ||
35 | self.oid_controller = oid_controller | ||
36 | |||
37 | @expose(template="genshi:quoinstemplates.oid_confirm") | ||
38 | @require(predicates.not_anonymous()) | ||
39 | def index(self, **kw): | ||
40 | oid_request = request.environ['oid_request'] | ||
41 | self.oid_controller._validate_identity(oid_request.identity) | ||
42 | |||
43 | sreg_req = openid.extensions.sreg.SRegRequest.fromOpenIDRequest(oid_request) | ||
44 | user = request.identity['user'] | ||
45 | |||
46 | sr_required = [self.oid_controller.getSRegValue(user,x) for x in sreg_req.required] | ||
47 | sr_optional = [self.oid_controller.getSRegValue(user,x) for x in sreg_req.optional] | ||
48 | |||
49 | session['oid_request']=oid_request | ||
50 | session.save() | ||
51 | |||
52 | return dict(openid = self.oid_controller, | ||
53 | oid_request = oid_request, | ||
54 | required = sr_required, | ||
55 | optional = sr_optional, | ||
56 | ) | ||
57 | |||
58 | class ResponseController(object): | ||
59 | def __init__(self, oid_controller): | ||
60 | self.oid_controller = oid_controller | ||
61 | |||
62 | @expose() | ||
63 | def index(self, **kw): | ||
64 | webresponse = request.environ['oid_webresponse'] | ||
65 | |||
66 | pylons.response.status = webresponse.code | ||
67 | pylons.response.headers.update(webresponse.headers) | ||
68 | return webresponse.body | ||
69 | |||
70 | |||
71 | class OpenIDController(TGController): | ||
72 | sreg_friendly = { | ||
73 | 'nickname': 'Nickname', | ||
74 | 'email': 'Email address', | ||
75 | 'fullname': 'Full name', | ||
76 | 'dob': 'Date of birth', | ||
77 | 'gender': 'Gender', | ||
78 | 'postcode': 'Postal code', | ||
79 | 'country': 'Country', | ||
80 | 'language': 'Language', | ||
81 | 'timezone': 'Time zone', | ||
82 | } | ||
83 | |||
84 | def url(self, obj=None): | ||
85 | if obj is None: | ||
86 | u = tg.url(self.path) | ||
87 | elif isinstance(obj, basestring): | ||
88 | if obj.startswith('/'): obj = obj[1:] | ||
89 | u = tg.url(os.path.join(self.path, obj)) | ||
90 | return u | ||
91 | |||
92 | def absolute_url(self, obj): | ||
93 | port = tg.config.get('server.webport', '') | ||
94 | if port: | ||
95 | port = ':'+port | ||
96 | return 'http://%s%s%s'%(tg.config.get('server.webhost'), port, | ||
97 | self.url(obj)) | ||
98 | |||
99 | def __init__(self, *args, **kw): | ||
100 | self.get_name_from_id = kw.pop('get_name_from_id', lambda x: x) | ||
101 | self.path = kw.pop('path', '/') | ||
102 | super(OpenIDController, self).__init__(*args, **kw) | ||
103 | |||
104 | def getSRegValue(self, user, field): | ||
105 | val = None | ||
106 | if field=='nickname': val = user.user_name | ||
107 | if field=='fullname': val = user.display_name | ||
108 | if field=='email': val = user.email_address | ||
109 | return (field, self.sreg_friendly[field], val) | ||
110 | |||
111 | def isAuthorized(self, id, trust_root): | ||
112 | if not request.identity: return False | ||
113 | name = self.get_name_from_id(id) | ||
114 | if request.identity['user'].user_name == name: | ||
115 | # check to see if the user has set preferences for this trust | ||
116 | # root, and return True. also, sreg. XXX | ||
117 | return False | ||
118 | return False | ||
119 | |||
120 | def _validate_identity(self, id): | ||
121 | name = self.get_name_from_id(id) | ||
122 | if request.identity['user'].user_name != name: | ||
123 | raise Exception("Not your ID") | ||
124 | |||
125 | @expose() | ||
126 | def finish(self, **kw): | ||
127 | oid_request=session['oid_request'] | ||
128 | self._validate_identity(oid_request.identity) | ||
129 | |||
130 | sreg_req = openid.extensions.sreg.SRegRequest.fromOpenIDRequest(oid_request) | ||
131 | user = request.identity['user'] | ||
132 | |||
133 | store = MySQLStore(get_oid_connection()) | ||
134 | oserver = openid.server.server.Server(store, | ||
135 | self.absolute_url('/openid/server')) | ||
136 | |||
137 | data = {} | ||
138 | for field in sreg_req.required+sreg_req.optional: | ||
139 | if kw.has_key(field): | ||
140 | data[field]=self.getSRegValue(user, field)[2] | ||
141 | |||
142 | sreg_resp = openid.extensions.sreg.SRegResponse.extractResponse(sreg_req, data) | ||
143 | |||
144 | if kw.get('continue', None): | ||
145 | response = oid_request.answer(True) | ||
146 | response.addExtension(sreg_resp) | ||
147 | else: | ||
148 | response = oid_request.answer(False) | ||
149 | |||
150 | webresponse = oserver.encodeResponse(response) | ||
151 | |||
152 | pylons.response.status = webresponse.code | ||
153 | pylons.response.headers.update(webresponse.headers) | ||
154 | |||
155 | del session['oid_request'] | ||
156 | session.save() | ||
157 | return webresponse.body | ||
158 | |||
159 | @expose() | ||
160 | def lookup(self, *remainder): | ||
161 | store = MySQLStore(get_oid_connection()) | ||
162 | oserver = openid.server.server.Server(store, | ||
163 | self.absolute_url('/server')) | ||
164 | oid_request = oserver.decodeRequest(request.params) | ||
165 | request.environ['oid_request']=oid_request | ||
166 | |||
167 | if oid_request.mode in ['checkid_immediate', 'checkid_setup']: | ||
168 | if hasattr(oid_request, 'returnToVerified'): | ||
169 | if not (oid_request.trustRootValid() | ||
170 | and oid_request.returnToVerified()): | ||
171 | raise Exception("Not trusted") | ||
172 | else: | ||
173 | if not (oid_request.trustRootValid()): | ||
174 | raise Exception("Not trusted") | ||
175 | if self.isAuthorized(oid_request.identity, oid_request.trust_root): | ||
176 | response = oid_request.answer(True) | ||
177 | elif oid_request.immediate: | ||
178 | response = oid_request.answer(False) | ||
179 | else: | ||
180 | return (DecideController(self), ()) | ||
181 | else: | ||
182 | response = oserver.handleRequest(oid_request) | ||
183 | |||
184 | webresponse = oserver.encodeResponse(response) | ||
185 | request.environ['oid_webresponse']=webresponse | ||
186 | return (ResponseController(self), ()) | ||