Merge branch 'comments'
[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, h
9 from pylons.controllers.util import abort, redirect
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(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(url('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('/')
74
75 def logout(self):
76 """Log user out."""
77
78 if 'user_id' in session:
79 del session['user_id']
80 session.save()
81
82 # XXX success message
83 # XXX send me where I came from
84 redirect('/')
85
86 def register(self):
87 """Logging in with an unrecognized identity URL redirects here."""
88
89 c.identity_url = session['register:identity_url']
90 c.nickname = session.get('register:nickname', None)
91
92 return render('/account/register.mako')
93
94 def register_finish(self):
95 """Complete a new-user registration. Create the user and log in."""
96
97 identity_url = session['register:identity_url']
98 username = request.params.get('username', None)
99
100 # XXX how do we return errors in some useful way?
101
102 if not username:
103 return 'Please enter a username.'
104
105 if User.query.filter_by(name=username).count():
106 return 'That username is taken.'
107
108 # Create db records
109 user = User(name=username)
110 user.identity_urls.append(IdentityURL(url=identity_url))
111 elixir.session.commit()
112
113 # Log in
114 session['user_id'] = user.id
115 session.save()
116
117 # XXX how do we do success messages in some useful way?
118 # XXX send me where I came from
119 redirect('/')