diff --git a/controller/Expose.py b/controller/Expose.py index e353390..067cebf 100644 --- a/controller/Expose.py +++ b/controller/Expose.py @@ -68,7 +68,7 @@ def expose( view = None, rss = None ): if rss and use_rss: cherrypy.response.headers[ u"Content-Type" ] = u"application/xml" return unicode( rss( **result ) ) - else: + elif view: return unicode( view( **result ) ) else: return unicode( view_override( **result ) ) diff --git a/controller/Users.py b/controller/Users.py index 2510f62..4654575 100644 --- a/controller/Users.py +++ b/controller/Users.py @@ -105,10 +105,12 @@ def update_auth( function ): # peek in the function's return value to see if we should tweak authentication status user = result.get( "authenticated" ) if user: + result.pop( "authenticated", None ) cherrypy.session[ u"user_id" ] = user.object_id cherrypy.session[ u"username" ] = user.username if result.get( "deauthenticated" ): + result.pop( "deauthenticated", None ) cherrypy.session.pop( u"user_id", None ) cherrypy.session.pop( u"username", None ) @@ -225,6 +227,72 @@ class Users( object ): authenticated = user, ) + @expose() + @grab_user_id + @update_auth + @wait_for_update + @async + @update_client + def demo( self, user_id = None ): + """ + Create a new guest User for purposes of the demo. Start that user with their own Notebook and + "welcome to your wiki" and "this is a demo" notes. For convenience, login the newly created + user as well. + + If the user is already logged in as a guest user when calling this function, then skip + creating a new user and notebook, and just redirect to the guest user's existing notebook. + + @type user_id: unicode + @param user_id: id of current logged-in user (if any), determined by @grab_user_id + @rtype: json dict + @return: { 'redirect': url, 'authenticated': userdict } + """ + # if the user is already logged in as a guest, then just redirect to their existing demo + # notebook + if user_id: + self.__database.load( user_id, self.__scheduler.thread ) + user = ( yield Scheduler.SLEEP ) + if user.username is None and len( user.notebooks ) > 0: + redirect = u"/notebooks/%s" % user.notebooks[ 0 ].object_id + yield dict( redirect = redirect ) + return + + # create a demo notebook for this user, along with a trash for that notebook + self.__database.next_id( self.__scheduler.thread ) + trash_id = ( yield Scheduler.SLEEP ) + trash = Notebook( trash_id, u"trash" ) + + self.__database.next_id( self.__scheduler.thread ) + notebook_id = ( yield Scheduler.SLEEP ) + notebook = Notebook( notebook_id, u"my notebook", trash ) + + # create startup notes for this user's notebook + self.__database.next_id( self.__scheduler.thread ) + note_id = ( yield Scheduler.SLEEP ) + note = Note( note_id, file( u"static/html/this is a demo.html" ).read() ) + notebook.add_note( note ) + notebook.add_startup_note( note ) + + self.__database.next_id( self.__scheduler.thread ) + note_id = ( yield Scheduler.SLEEP ) + note = Note( note_id, file( u"static/html/welcome to your wiki.html" ).read() ) + notebook.add_note( note ) + notebook.add_startup_note( note ) + + # actually create the new user. because this is just a demo user, we're not adding it to the User_list + self.__database.next_id( self.__scheduler.thread ) + user_id = ( yield Scheduler.SLEEP ) + + user = User( user_id, username = None, password = None, email_address = None, notebooks = [ notebook ] ) + self.__database.save( user ) + + redirect = u"/notebooks/%s" % notebook.object_id + + yield dict( + redirect = redirect, + authenticated = user, + ) + @expose( view = Json ) @update_auth @wait_for_update diff --git a/controller/test/Test_users.py b/controller/test/Test_users.py index 3a9e7ee..1167228 100644 --- a/controller/test/Test_users.py +++ b/controller/test/Test_users.py @@ -83,7 +83,6 @@ class Test_users( Test_controller ): ) ) assert result[ u"redirect" ].startswith( u"/notebooks/" ) - assert result[ u"authenticated" ] def test_current_after_signup( self, include_startup_notes = False ): result = self.http_post( "/users/signup", dict( @@ -139,6 +138,83 @@ class Test_users( Test_controller ): assert result[ u"error" ] + def test_demo( self ): + result = self.http_post( "/users/demo", dict() ) + + assert result[ u"redirect" ].startswith( u"/notebooks/" ) + + def test_current_after_demo( self, include_startup_notes = False ): + result = self.http_post( "/users/demo", dict() ) + session_id = result[ u"session_id" ] + + new_notebook_id = result[ u"redirect" ].split( u"/notebooks/" )[ -1 ] + + result = self.http_get( + "/users/current?include_startup_notes=%s" % include_startup_notes, + session_id = session_id, + ) + + assert result[ u"user" ].username == None + notebooks = result[ u"notebooks" ] + assert len( notebooks ) == 2 + assert notebooks[ 0 ] == self.anon_notebook + assert notebooks[ 0 ].trash == None + + notebook = notebooks[ 1 ] + assert notebook.object_id == new_notebook_id + assert notebook.trash + assert len( notebook.notes ) == 2 + assert len( notebook.startup_notes ) == 2 + + startup_notes = result[ "startup_notes" ] + if include_startup_notes: + assert len( startup_notes ) == 1 + assert startup_notes[ 0 ] == self.startup_note + else: + assert startup_notes == [] + + rate_plan = result[ u"rate_plan" ] + assert rate_plan[ u"name" ] == u"super" + assert rate_plan[ u"storage_quota_bytes" ] == 1337 + + def test_current_with_startup_notes_after_demo( self ): + self.test_current_after_demo( include_startup_notes = True ) + + def test_current_after_demo_twice( self, include_startup_notes = False ): + result = self.http_post( "/users/demo", dict() ) + session_id = result[ u"session_id" ] + + new_notebook_id = result[ u"redirect" ].split( u"/notebooks/" )[ -1 ] + + result = self.http_get( + "/users/current?include_startup_notes=%s" % include_startup_notes, + session_id = session_id, + ) + + user_id = result[ u"user" ].object_id + + # request a demo for a second time + result = self.http_post( "/users/demo", dict(), session_id = session_id ) + + assert result[ u"redirect" ].startswith( u"/notebooks/" ) + notebook_id_again = result[ u"redirect" ].split( u"/notebooks/" )[ -1 ] + + assert notebook_id_again == new_notebook_id + + result = self.http_get( + "/users/current?include_startup_notes=%s" % include_startup_notes, + session_id = session_id, + ) + + user_id_again = result[ u"user" ].object_id + + # since we're already logged in as a guest user with a demo notebook, requesting a demo again + # should just use the same guest user with the same notebook + assert user_id_again == user_id + + def test_current_with_startup_notes_after_demo_twice( self ): + self.test_current_after_demo_twice( include_startup_notes = True ) + def test_login( self ): result = self.http_post( "/users/login", dict( username = self.username, @@ -147,7 +223,6 @@ class Test_users( Test_controller ): ) ) assert result[ u"redirect" ] == u"/notebooks/%s" % self.notebooks[ 0 ].object_id - assert result[ u"authenticated" ] def test_login_with_unknown_user( self ): result = self.http_post( "/users/login", dict( @@ -157,7 +232,6 @@ class Test_users( Test_controller ): ) ) assert result[ u"error" ] - assert not result.get( u"authenticated" ) def test_login_with_invalid_password( self ): result = self.http_post( "/users/login", dict( @@ -167,13 +241,11 @@ class Test_users( Test_controller ): ) ) assert result[ u"error" ] - assert not result.get( u"authenticated" ) def test_logout( self ): result = self.http_post( "/users/logout", dict() ) assert result[ u"redirect" ] == self.settings[ u"global" ].get( u"luminotes.http_url" ) + u"/" - assert result[ u"deauthenticated" ] def test_current_after_login( self, include_startup_notes = False ): result = self.http_post( "/users/login", dict( diff --git a/static/html/features.html b/static/html/features.html index 9db8643..01777d9 100644 --- a/static/html/features.html +++ b/static/html/features.html @@ -35,6 +35,7 @@ your wiki.
Sound interesting? Then -take a tour or -try it out for yourself! +take a tour, +try the demo, or +sign up for a free account.
diff --git a/static/html/login.html b/static/html/login.html index ab36b50..a58957b 100644 --- a/static/html/login.html +++ b/static/html/login.html @@ -1,6 +1,7 @@