diff --git a/controller/Forums.py b/controller/Forums.py
index 34b85ad..221cc55 100644
--- a/controller/Forums.py
+++ b/controller/Forums.py
@@ -98,4 +98,6 @@ class Forums( object ):
return result
# threads() is just an alias for Notebooks.default()
- threads = Notebooks.default
+ def threads( self, *args, **kwargs ):
+ return self.__notebooks.default( *args, **kwargs )
+ threads.exposed = True
diff --git a/controller/Users.py b/controller/Users.py
index ebc4557..fa53077 100644
--- a/controller/Users.py
+++ b/controller/Users.py
@@ -748,13 +748,14 @@ class Users( object ):
return None
# if a particular note_id is given, and the notebook is READ_WRITE_FOR_OWN_NOTES, then check
- # that the user is associated with that note
+ # that the user is associated with that note (if the note exists). this prevents a user
+ # from modifying someone else's note in a READ_WRITE_FOR_OWN_NOTES notebook
if note_id and notebook.read_write == Notebook.READ_WRITE_FOR_OWN_NOTES:
note = self.__database.load( Note, note_id )
- if not note:
- return None
-
- if user_id != note.user_id or notebook_id != note.notebook_id:
+ if note and (
+ ( note.user_id and user_id != note.user_id ) or
+ ( note.notebook_id and notebook_id != note.notebook_id )
+ ):
return None
return notebook
diff --git a/controller/test/Test_notebooks.py b/controller/test/Test_notebooks.py
index 2aa59bc..c9b5388 100644
--- a/controller/test/Test_notebooks.py
+++ b/controller/test/Test_notebooks.py
@@ -2412,6 +2412,48 @@ class Test_notebooks( Test_controller ):
def test_save_new_startup_note( self ):
self.test_save_new_note( startup = True )
+ def test_save_new_note_with_notebook_read_write_for_own_notes( self ):
+ self.login()
+
+ self.database.execute( self.user.sql_update_access(
+ self.notebook.object_id, read_write = Notebook.READ_WRITE_FOR_OWN_NOTES, owner = True,
+ ) )
+
+ # save a completely new note
+ new_note = Note.create( "55", u"
newest title
foo" )
+ previous_revision = new_note.revision
+ result = self.http_post( "/notebooks/save_note/", dict(
+ notebook_id = self.notebook.object_id,
+ note_id = new_note.object_id,
+ contents = new_note.contents,
+ startup = False,
+ previous_revision = None,
+ ), session_id = self.session_id )
+
+ assert result[ "new_revision" ]
+ assert result[ "new_revision" ] != previous_revision
+ assert result[ "new_revision" ].user_id == self.user.object_id
+ assert result[ "new_revision" ].username == self.username
+ assert result[ "previous_revision" ] == None
+ user = self.database.load( User, self.user.object_id )
+ assert user.storage_bytes > 0
+ assert result[ "storage_bytes" ] == user.storage_bytes
+
+ # make sure the new title is now loadable
+ result = self.http_post( "/notebooks/load_note_by_title/", dict(
+ notebook_id = self.notebook.object_id,
+ note_title = new_note.title,
+ ), session_id = self.session_id )
+
+ note = result[ "note" ]
+
+ assert note.object_id == new_note.object_id
+ assert note.title == new_note.title
+ assert note.contents == new_note.contents
+ assert note.startup == True # startup is forced to True in READ_WRITE_FOR_OWN_NOTES notebook
+ assert note.user_id == self.user.object_id
+ assert note.rank == 0
+
def test_save_new_note_with_disallowed_tags( self ):
self.login()
diff --git a/controller/test/Test_users.py b/controller/test/Test_users.py
index bbe2c00..1aaf6fa 100644
--- a/controller/test/Test_users.py
+++ b/controller/test/Test_users.py
@@ -974,7 +974,24 @@ class Test_users( Test_controller ):
notebook = cherrypy.root.users.load_notebook( self.user.object_id, self.notebooks[ 0 ].object_id,
note_id = u"unknownid" )
- assert notebook is None
+ # an unknown note id indicates that a new note is being created, which is allowed in a
+ # READ_WRITE_FOR_OWN_NOTES notebooks
+ assert notebook
+ assert notebook.object_id == self.notebooks[ 0 ].object_id
+
+ def test_load_notebook_with_stub_note( self ):
+ # don't fully create a note, but reserve an id for it
+ note_id = self.database.next_id( Note )
+
+ self.database.execute( self.user.sql_update_access(
+ self.notebooks[ 0 ].object_id, read_write = Notebook.READ_WRITE_FOR_OWN_NOTES, owner = False,
+ ) )
+
+ notebook = cherrypy.root.users.load_notebook( self.user.object_id, self.notebooks[ 0 ].object_id,
+ note_id = note_id )
+
+ assert notebook
+ assert notebook.object_id == self.notebooks[ 0 ].object_id
def test_load_notebook_with_note_id_in_another_notebook( self ):
self.database.execute( self.user.sql_update_access(