Added support for querying by user.
[zzz-floof.git] / floof / controllers / account.py
index a32583c..2073d44 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,75 @@ 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)
+        # XXX hey, uh.  warn if this name is taken already.
+
+        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)
+
+        if not username:
+            h.flash(u'Please enter a username.')
+            return self.register()
+
+        if User.query.filter_by(name=username).count():
+            h.flash(u'This username is already taken.')
+            return self.register()
+
+        if not User.is_valid_name(username):
+            h.flash(u'This username is not valid.')
+            return self.register()
+
+        # Create db records
+        user = User(name=username, display_name=username)
+        user.identity_urls.append(IdentityURL(url=identity_url))
+        elixir.session.commit()
+
+        # Log in
+        session['user_id'] = user.id
+        session.save()
+        h.flash(u'You are now logged in.')
+
+        # XXX send me where I came from
+        redirect('/')