Ensure colorbars can't escape their containers. #352
[zzz-spline-users.git] / splinext / users / controllers / accounts.py
1 import logging
2 from openid.consumer.consumer import Consumer, SUCCESS, CANCEL
3 from openid.extensions.sreg import SRegRequest, SRegResponse
4 from openid.store.filestore import FileOpenIDStore
5 from openid.yadis.discover import DiscoveryFailure
6 from sqlalchemy.orm.exc import NoResultFound
7
8 from pylons import config, request, response, session, tmpl_context as c, url
9 from pylons.controllers.util import abort, redirect
10 from pylons.decorators.secure import authenticate_form
11 from routes import request_config
12
13 from spline.model import meta
14 from spline.lib import helpers as h
15 from spline.lib.base import BaseController, render
16 from splinext.users import model as users_model
17
18 log = logging.getLogger(__name__)
19
20 class AccountsController(BaseController):
21
22 openid_store = FileOpenIDStore('/var/tmp')
23
24 def _bail(self, reason):
25 # Used for bailing on a login attempt; reshows the login page
26 c.error = reason
27 c.attempted_openid = request.params.get('openid_identifier', '')
28 return render('/users/login.mako')
29
30
31 def login(self):
32 c.error = None
33 c.attempted_openid = None
34 return render('/users/login.mako')
35
36 def login_begin(self):
37 """Step one of logging in with OpenID; we redirect to the provider"""
38
39 cons = Consumer(session=session, store=self.openid_store)
40
41 try:
42 openid_url = request.params['openid_identifier']
43 except KeyError:
44 return self._bail("Gotta enter an OpenID to log in.")
45
46 try:
47 auth_request = cons.begin(openid_url)
48 except DiscoveryFailure:
49 return self._bail(
50 "Can't connect to '{0}'. You sure it's an OpenID?"
51 .format(openid_url)
52 )
53
54 sreg_req = SRegRequest(optional=['nickname', 'email', 'dob', 'gender',
55 'country', 'language', 'timezone'])
56 auth_request.addExtension(sreg_req)
57
58 host = request.headers['host']
59 protocol = request_config().protocol
60 return_url = url(host=host, controller='accounts', action='login_finish')
61 new_url = auth_request.redirectURL(return_to=return_url,
62 realm=protocol + '://' + host)
63 redirect(new_url)
64
65 def login_finish(self):
66 """Step two of logging in; the OpenID provider redirects back here."""
67
68 cons = Consumer(session=session, store=self.openid_store)
69 host = request.headers['host']
70 return_url = url(host=host, controller='accounts', action='login_finish')
71 res = cons.complete(request.params, return_url)
72
73 if res.status == CANCEL:
74 # I guess.. just.. back to the homepage?
75 h.flash(u"""Login canceled.""", icon='user-silhouette')
76 redirect(url('/'))
77 elif res.status != SUCCESS:
78 return 'Error! %s' % res.message
79
80 try:
81 # Grab an existing user record, if one exists
82 q = meta.Session.query(users_model.User) \
83 .filter(users_model.User.openids.any(openid=res.identity_url))
84 user = q.one()
85 except NoResultFound:
86 # Try to pull a name out of the SReg response
87 sreg_res = SRegResponse.fromSuccessResponse(res)
88 try:
89 username = sreg_res['nickname']
90 except (KeyError, TypeError):
91 # KeyError if sreg has no nickname; TypeError if sreg is None
92 username = 'Anonymous'
93
94 # Create db records
95 user = users_model.User(name=username)
96 meta.Session.add(user)
97
98 openid = users_model.OpenID(openid=res.identity_url)
99 user.openids.append(openid)
100
101 meta.Session.commit()
102
103 # Remember who's logged in, and we're good to go
104 session['user_id'] = user.id
105 session.save()
106
107 h.flash(u"""Hello, {0}!""".format(user.name),
108 icon='user')
109
110 redirect(url('/'), code=303)
111
112 @authenticate_form
113 def logout(self):
114 """Logs the user out."""
115
116 if 'user_id' in session:
117 del session['user_id']
118 session.save()
119
120 h.flash(u"""Logged out.""",
121 icon='user-silhouette')
122
123 redirect(url('/'), code=303)