0c53a6d1c635e0737a00bd7f382b7c78f35aed68
[zzz-floof.git] / floof / controllers / account.py
1 import elixir
2 import logging
3 from openid.consumer.consumer import Consumer
4 from openid.extensions.sreg import SRegRequest, SRegResponse
5 from openid.store.filestore import FileOpenIDStore
6 from sqlalchemy.orm.exc import NoResultFound
7
8 from pylons import request, response, session, tmpl_context as c, url
9 from pylons.controllers.util import abort, redirect_to
10 from routes import url_for, request_config
11
12 from floof.lib.base import BaseController, render
13 from floof.model.users import IdentityURL, User
14
15 log = logging.getLogger(__name__)
16
17 class AccountController(BaseController):
18
19 openid_store = FileOpenIDStore('/var/tmp')
20
21 def login(self):
22 return render('/login.mako')
23
24 def login_begin(self):
25 """Step one of logging in with OpenID; we redirect to the provider"""
26
27 cons = Consumer(session=session, store=self.openid_store)
28 auth_request = cons.begin(request.params['identity_url'])
29 sreg_req = SRegRequest(optional=['nickname', 'email', 'dob', 'gender',
30 'country', 'language', 'timezone'])
31 auth_request.addExtension(sreg_req)
32
33 host = request.headers['host']
34 protocol = request_config().protocol
35 return_url = url_for(host=host, controller='account', action='login_finish')
36 new_url = auth_request.redirectURL(return_to=return_url,
37 realm=protocol + '://' + host)
38 redirect_to(new_url)
39
40 def login_finish(self):
41 """Step two of logging in; the OpenID provider redirects back here."""
42
43 cons = Consumer(session=session, store=self.openid_store)
44 host = request.headers['host']
45 return_url = url_for(host=host, controller='account', action='login_finish')
46 res = cons.complete(request.params, return_url)
47
48 if res.status != 'success':
49 return 'Error! %s' % res.message
50
51 try:
52 # Grab an existing user record, if one exists
53 q = User.query.filter(User.identity_urls.any(url=res.identity_url))
54 user = q.one()
55 except NoResultFound:
56 # Unrecognized URL. Redirect to a registration page to ask for a
57 # nickname, etc.
58 session['register:identity_url'] = res.identity_url
59
60 # Try to pull a name out of the SReg response
61 sreg_res = SRegResponse.fromSuccessResponse(res)
62 if sreg_res and 'nickname' in sreg_res:
63 session['register:nickname'] = sreg_res['nickname']
64
65 session.save()
66 redirect_to(url.current(action='register'))
67
68 # Remember who's logged in, and we're good to go
69 session['user_id'] = user.id
70 session.save()
71
72 # XXX send me where I came from
73 redirect_to('/')
74
75 def register(self):
76 """Logging in with an unrecognized identity URL redirects here."""
77
78 c.identity_url = session['register:identity_url']
79 c.nickname = session.get('register:nickname', None)
80
81 return render('/account/register.mako')
82
83 def register_finish(self):
84 """Complete a new-user registration. Create the user and log in."""
85
86 identity_url = session['register:identity_url']
87 username = request.params.get('username', None)
88
89 # XXX how do we return errors in some useful way?
90
91 if not username:
92 return 'Please enter a username.'
93
94 if User.query.filter_by(name=username).count():
95 return 'That username is taken.'
96
97 # Create db records
98 user = User(name=username)
99 user.identity_urls.append(IdentityURL(url=identity_url))
100 elixir.session.commit()
101
102 # Log in
103 session['user_id'] = user.id
104 session.save()
105
106 # XXX how do we do success messages in some useful way?
107 # XXX send me where I came from
108 redirect_to('/')