Merge branch 'master' of git@veekun.com:floof
[zzz-floof.git] / floof / controllers / account.py
index a32583c..2c94736 100644 (file)
@@ -1,16 +1,18 @@
+import elixir
 import logging
 from openid.consumer.consumer import Consumer
 from openid.extensions.sreg import SRegRequest, SRegResponse
 from openid.store.filestore import FileOpenIDStore
 import logging
 from openid.consumer.consumer import Consumer
 from openid.extensions.sreg import SRegRequest, SRegResponse
 from openid.store.filestore import FileOpenIDStore
+from openid.yadis.discover import DiscoveryFailure
 from sqlalchemy.orm.exc import NoResultFound
 
 from sqlalchemy.orm.exc import NoResultFound
 
-from pylons import request, response, session, tmpl_context as c
-from pylons.controllers.util import abort, redirect_to
+from pylons import request, response, session, tmpl_context as c, url
+from pylons.controllers.util import abort, redirect, redirect_to
 from routes import url_for, request_config
 
 from routes import url_for, request_config
 
-from floof import model
-from floof.model.meta import Session
 from floof.lib.base import BaseController, render
 from floof.lib.base import BaseController, render
+import floof.lib.helpers as h
+from floof.model.users import IdentityURL, User
 
 log = logging.getLogger(__name__)
 
 
 log = logging.getLogger(__name__)
 
@@ -19,13 +21,20 @@ class AccountController(BaseController):
     openid_store = FileOpenIDStore('/var/tmp')
 
     def login(self):
     openid_store = FileOpenIDStore('/var/tmp')
 
     def login(self):
-        return render('/login.mako')
+        c.bogus_identity_url = request.params.get('bogus_identity_url', None)
+        return render('/account/login.mako')
 
     def login_begin(self):
         """Step one of logging in with OpenID; we redirect to the provider"""
 
 
     def login_begin(self):
         """Step one of logging in with OpenID; we redirect to the provider"""
 
+        identity_url = request.params['identity_url']
         cons = Consumer(session=session, store=self.openid_store)
         cons = Consumer(session=session, store=self.openid_store)
-        auth_request = cons.begin(request.params['identity_url'])
+        try:
+            auth_request = cons.begin(identity_url)
+        except DiscoveryFailure:
+            redirect_to(controller='account', action='login',
+                        bogus_identity_url=identity_url)
+
         sreg_req = SRegRequest(optional=['nickname', 'email', 'dob', 'gender',
                                          'country', 'language', 'timezone'])
         auth_request.addExtension(sreg_req)
         sreg_req = SRegRequest(optional=['nickname', 'email', 'dob', 'gender',
                                          'country', 'language', 'timezone'])
         auth_request.addExtension(sreg_req)
@@ -35,7 +44,7 @@ class AccountController(BaseController):
         return_url = url_for(host=host, controller='account', action='login_finish')
         new_url = auth_request.redirectURL(return_to=return_url,
                                            realm=protocol + '://' + host)
         return_url = url_for(host=host, controller='account', action='login_finish')
         new_url = auth_request.redirectURL(return_to=return_url,
                                            realm=protocol + '://' + host)
-        redirect_to(new_url)
+        redirect(new_url)
 
     def login_finish(self):
         """Step two of logging in; the OpenID provider redirects back here."""
 
     def login_finish(self):
         """Step two of logging in; the OpenID provider redirects back here."""
@@ -50,26 +59,70 @@ class AccountController(BaseController):
 
         try:
             # Grab an existing user record, if one exists
 
         try:
             # Grab an existing user record, if one exists
-            q = Session.query(model.User) \
-                       .filter(model.User.identity_urls.any(url=res.identity_url))
+            q = User.query.filter(User.identity_urls.any(url=res.identity_url))
             user = q.one()
         except NoResultFound:
             user = q.one()
         except NoResultFound:
+            # Unrecognized URL.  Redirect to a registration page to ask for a
+            # nickname, etc.
+            session['register:identity_url'] = res.identity_url
+
             # Try to pull a name out of the SReg response
             sreg_res = SRegResponse.fromSuccessResponse(res)
             # Try to pull a name out of the SReg response
             sreg_res = SRegResponse.fromSuccessResponse(res)
-            try:
-                username = sreg_res['nickname']
-            except:
-                username = 'Anonymous'
-
-            # Create db records
-            user = model.User(name=username)
-            Session.add(user)
-            identity_url = model.IdentityURL(url=res.identity_url)
-            user.identity_urls.append(identity_url)
-            Session.commit()
+            if sreg_res and 'nickname' in sreg_res:
+                session['register:nickname'] = sreg_res['nickname']
+
+            session.save()
+            redirect(url('register'))
 
         # Remember who's logged in, and we're good to go
         session['user_id'] = user.id
         session.save()
 
 
         # Remember who's logged in, and we're good to go
         session['user_id'] = user.id
         session.save()
 
-        return "Hello, %s from %s" % (user.name, res.identity_url)
+        # XXX send me where I came from
+        redirect('/')
+
+    def logout(self):
+        """Log user out."""
+
+        if 'user_id' in session:
+            del session['user_id']
+            session.save()
+
+        # XXX success message
+        # XXX send me where I came from
+        redirect('/')
+
+    def register(self):
+        """Logging in with an unrecognized identity URL redirects here."""
+
+        c.identity_url = session['register:identity_url']
+        c.nickname = session.get('register:nickname', None)
+
+        return render('/account/register.mako')
+
+    def register_finish(self):
+        """Complete a new-user registration.  Create the user and log in."""
+
+        identity_url = session['register:identity_url']
+        username = request.params.get('username', None)
+
+        # XXX how do we return errors in some useful way?
+
+        if not username:
+            return 'Please enter a username.'
+
+        if User.query.filter_by(name=username).count():
+            return 'That username is taken.'
+
+        # Create db records
+        user = User(name=username)
+        user.identity_urls.append(IdentityURL(url=identity_url))
+        elixir.session.commit()
+
+        # Log in
+        session['user_id'] = user.id
+        session.save()
+
+        # XXX how do we do success messages in some useful way?
+        # XXX send me where I came from
+        redirect('/')