Removed some reliance on the logged-in user.
[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 openid.yadis.discover import DiscoveryFailure
7 from sqlalchemy.orm.exc import NoResultFound
8
9 from pylons import request, response, session, tmpl_context as c, url
10 from pylons.controllers.util import abort, redirect, redirect_to
11 from routes import url_for, request_config
12
13 from floof.lib.base import BaseController, render
14 import floof.lib.helpers as h
15 from floof.model.users import IdentityURL, User
16
17 log = logging.getLogger(__name__)
18
19 from floof.model import UserPage
20
21 class AccountController(BaseController):
22
23 openid_store = FileOpenIDStore('/var/tmp')
24
25 def login(self):
26 c.bogus_identity_url = request.params.get('bogus_identity_url', None)
27 return render('/account/login.mako')
28
29 def login_begin(self):
30 """Step one of logging in with OpenID; we redirect to the provider"""
31
32 identity_url = request.params['identity_url']
33 cons = Consumer(session=session, store=self.openid_store)
34 try:
35 auth_request = cons.begin(identity_url)
36 except DiscoveryFailure:
37 redirect_to(controller='account', action='login',
38 bogus_identity_url=identity_url)
39
40 sreg_req = SRegRequest(optional=['nickname', 'email', 'dob', 'gender',
41 'country', 'language', 'timezone'])
42 auth_request.addExtension(sreg_req)
43
44 host = request.headers['host']
45 protocol = request_config().protocol
46 return_url = url_for(host=host, controller='account', action='login_finish')
47 new_url = auth_request.redirectURL(return_to=return_url,
48 realm=protocol + '://' + host)
49 redirect(new_url)
50
51 def login_finish(self):
52 """Step two of logging in; the OpenID provider redirects back here."""
53
54 cons = Consumer(session=session, store=self.openid_store)
55 host = request.headers['host']
56 return_url = url_for(host=host, controller='account', action='login_finish')
57 res = cons.complete(request.params, return_url)
58
59 if res.status != 'success':
60 return 'Error! %s' % res.message
61
62 try:
63 # Grab an existing user record, if one exists
64 q = User.query.filter(User.identity_urls.any(url=res.identity_url))
65 user = q.one()
66 except NoResultFound:
67 # Unrecognized URL. Redirect to a registration page to ask for a
68 # nickname, etc.
69 session['register:identity_url'] = res.identity_url
70
71 # Try to pull a name out of the SReg response
72 sreg_res = SRegResponse.fromSuccessResponse(res)
73 if sreg_res and 'nickname' in sreg_res:
74 session['register:nickname'] = sreg_res['nickname']
75
76 session.save()
77 redirect(url('register'))
78
79 # Remember who's logged in, and we're good to go
80 session['user_id'] = user.id
81 session.save()
82 h.flash(u'You are now logged in.')
83
84 # XXX send me where I came from
85 redirect('/')
86
87 def logout(self):
88 """Log user out."""
89
90 if 'user_id' in session:
91 del session['user_id']
92 session.save()
93
94 # XXX success message
95 # XXX send me where I came from
96 redirect('/')
97
98 def register(self):
99 """Logging in with an unrecognized identity URL redirects here."""
100
101 c.identity_url = session['register:identity_url']
102 c.nickname = session.get('register:nickname', None)
103 # XXX hey, uh. warn if this name is taken already.
104
105 return render('/account/register.mako')
106
107 def register_finish(self):
108 """Complete a new-user registration. Create the user and log in."""
109
110 identity_url = session['register:identity_url']
111 username = request.params.get('username', None)
112
113 if not username:
114 h.flash(u'Please enter a username.')
115 return self.register()
116
117 if User.query.filter_by(name=username).count():
118 h.flash(u'This username is already taken.')
119 return self.register()
120
121 if not User.is_valid_name(username):
122 h.flash(u'This username is not valid.')
123 return self.register()
124
125 if username in ['me']:
126 h.flash(u'This username is reserved.')
127 return self.register()
128
129 # Create db records
130 user = User(name=username, display_name=username)
131 user.identity_urls.append(IdentityURL(url=identity_url))
132
133 elixir.session.commit()
134
135 # Log in
136 session['user_id'] = user.id
137 session.save()
138 h.flash(u'You are now logged in.')
139
140 # XXX send me where I came from
141 redirect('/')