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
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
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
18 log
= logging
.getLogger(__name__
)
20 class AccountsController(BaseController
):
22 openid_store
= FileOpenIDStore('/var/tmp')
24 def _bail(self
, reason
):
25 # Used for bailing on a login attempt; reshows the login page
27 c
.attempted_openid
= request
.params
.get('openid_identifier', '')
28 return render('/users/login.mako')
33 c
.attempted_openid
= None
34 return render('/users/login.mako')
36 def login_begin(self
):
37 """Step one of logging in with OpenID; we redirect to the provider"""
39 cons
= Consumer(session
=session
, store
=self
.openid_store
)
42 openid_url
= request
.params
['openid_identifier']
44 return self
._bail("Gotta enter an OpenID to log in.")
47 auth_request
= cons
.begin(openid_url
)
48 except DiscoveryFailure
:
50 "Can't connect to '{0}'. You sure it's an OpenID?"
54 sreg_req
= SRegRequest(optional
=['nickname', 'email', 'dob', 'gender',
55 'country', 'language', 'timezone'])
56 auth_request
.addExtension(sreg_req
)
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
)
65 def login_finish(self
):
66 """Step two of logging in; the OpenID provider redirects back here."""
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
)
73 if res
.status
== CANCEL
:
74 # I guess.. just.. back to the homepage?
75 h
.flash(u
"""Login canceled.""", icon
='user-silhouette')
77 elif res
.status
!= SUCCESS
:
78 return 'Error! %s' % res
.message
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
))
86 # Try to pull a name out of the SReg response
87 sreg_res
= SRegResponse
.fromSuccessResponse(res
)
89 username
= sreg_res
['nickname']
90 except (KeyError, TypeError):
91 # KeyError if sreg has no nickname; TypeError if sreg is None
92 username
= 'Anonymous'
95 user
= users_model
.User(name
=username
)
96 meta
.Session
.add(user
)
98 openid
= users_model
.OpenID(openid
=res
.identity_url
)
99 user
.openids
.append(openid
)
101 meta
.Session
.commit()
103 # Remember who's logged in, and we're good to go
104 session
['user_id'] = user
.id
107 h
.flash(u
"""Hello, {0}!""".format(user
.name
),
110 redirect(url('/'), code
=303)
114 """Logs the user out."""
116 if 'user_id' in session
:
117 del session
['user_id']
120 h
.flash(u
"""Logged out.""",
121 icon
='user-silhouette')
123 redirect(url('/'), code
=303)