witten
/
luminotes
Archived
1
0
Fork 0

Implemented delete forever for notebooks. And unit tests!

This commit is contained in:
Dan Helfman 2007-11-17 23:29:22 +00:00
parent 7bd83199a1
commit eec5ef6411
5 changed files with 154 additions and 8 deletions

View File

@ -835,7 +835,6 @@ class Notebooks( object ):
notebook = self.__database.load( Notebook, notebook_id )
# TODO: maybe if notebook.deleted is already True, then the notebook should be "deleted forever"
if not notebook:
raise Access_error()
@ -857,6 +856,47 @@ class Notebooks( object ):
redirect = u"/notebooks/%s?deleted_id=%s" % ( remaining_notebook.object_id, notebook.object_id ),
)
@expose( view = Json )
@grab_user_id
@validate(
notebook_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def delete_forever( self, notebook_id, user_id ):
"""
Delete the given notebook permanently (by simply revoking the user's access to it).
@type notebook_id: unicode
@param notebook_id: id of notebook to delete
@type user_id: unicode or NoneType
@param user_id: id of current logged-in user (if any)
@rtype dict
@return {}
@raise Access_error: the current user doesn't have access to the given notebook
@raise Validation_error: one of the arguments is invalid
"""
if user_id is None:
raise Access_error()
user = self.__database.load( User, user_id )
if not self.__users.check_access( user_id, notebook_id, read_write = True ):
raise Access_error()
notebook = self.__database.load( Notebook, notebook_id )
if not notebook:
raise Access_error()
# prevent deletion of a trash notebook directly
if notebook.name == u"trash":
raise Access_error()
self.__database.execute( user.sql_remove_notebook( notebook_id ), commit = False )
self.__database.commit()
return dict()
@expose( view = Json )
@grab_user_id
@validate(

View File

@ -26,6 +26,15 @@ class Test_controller( object ):
User.sql_save_notebook = lambda self, notebook_id, read_write = False: \
lambda database: sql_save_notebook( self, notebook_id, read_write, database )
def sql_remove_notebook( self, notebook_id, database ):
if self.object_id in database.user_notebook:
for access_tuple in database.user_notebook[ self.object_id ]:
if access_tuple[ 0 ] == notebook_id:
database.user_notebook[ self.object_id ].remove( access_tuple )
User.sql_remove_notebook = lambda self, notebook_id: \
lambda database: sql_remove_notebook( self, notebook_id, database )
def sql_load_notebooks( self, parents_only, undeleted_only, database ):
notebooks = []
notebook_tuples = database.user_notebook.get( self.object_id )

View File

@ -1805,7 +1805,26 @@ class Test_notebooks( Test_controller ):
def test_contents_after_delete( self ):
self.login()
result = self.http_post( "/notebooks/delete", dict(
self.http_post( "/notebooks/delete", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
result = cherrypy.root.notebooks.contents(
notebook_id = self.notebook.object_id,
user_id = self.user.object_id,
)
notebook = result[ "notebook" ]
assert notebook.deleted == True
def test_contents_after_delete_twice( self ):
self.login()
self.http_post( "/notebooks/delete", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
self.http_post( "/notebooks/delete", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
@ -1833,6 +1852,74 @@ class Test_notebooks( Test_controller ):
assert u"error" in result
def test_delete_forever( self ):
self.login()
result = self.http_post( "/notebooks/delete_forever", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
assert u"error" not in result
@raises( Access_error )
def test_contents_after_delete_forever( self ):
self.login()
self.http_post( "/notebooks/delete_forever", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
result = cherrypy.root.notebooks.contents(
notebook_id = self.notebook.object_id,
user_id = self.user.object_id,
)
def test_delete_then_delete_forever( self ):
self.login()
result = self.http_post( "/notebooks/delete", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
result = self.http_post( "/notebooks/delete_forever", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
assert u"error" not in result
@raises( Access_error )
def test_contents_after_delete_then_delete_forever( self ):
self.login()
self.http_post( "/notebooks/delete", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
self.http_post( "/notebooks/delete_forever", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
result = cherrypy.root.notebooks.contents(
notebook_id = self.notebook.object_id,
user_id = self.user.object_id,
)
def test_delete_forever_without_login( self ):
result = self.http_post( "/notebooks/delete_forever", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
assert result[ u"error" ]
def test_delete_forever_trash( self ):
self.login()
result = self.http_post( "/notebooks/delete_forever", dict(
notebook_id = self.notebook.trash_id,
), session_id = self.session_id )
assert u"error" in result
def test_undelete( self ):
self.login()

View File

@ -156,6 +156,13 @@ class User( Persistent ):
"insert into user_notebook ( user_id, notebook_id, read_write ) values " + \
"( %s, %s, %s );" % ( quote( self.object_id ), quote( notebook_id ), quote( read_write and 't' or 'f' ) )
def sql_remove_notebook( self, notebook_id ):
"""
Return a SQL string to remove this user's access to a particular notebook.
"""
return \
"delete from user_notebook where user_id = %s and notebook_id = %s;" % ( quote( self.object_id ), quote( notebook_id ) )
def sql_has_access( self, notebook_id, read_write = False ):
"""
Return a SQL string to determine whether this user has access to the given notebook.

View File

@ -185,7 +185,7 @@ Wiki.prototype.populate = function ( startup_notes, current_notes, note_read_wri
connect_undelete( notebook.object_id );
appendChildNodes( deleted_notebooks, createDOM( "div",
{ "id": "deleted_notebook_" + notebook.object_id },
{ "id": "deleted_notebook_" + notebook.object_id, "class": "deleted_notebook_item" },
createDOM( "span", {}, delete_button ),
createDOM( "span", {}, undelete_button ),
createDOM( "span", {}, notebook.name )
@ -304,9 +304,9 @@ Wiki.prototype.populate = function ( startup_notes, current_notes, note_read_wri
} );
}
var rename_notebook_link = getElement( "delete_notebook_link" );
if ( rename_notebook_link ) {
connect( rename_notebook_link, "onclick", function ( event ) {
var delete_notebook_link = getElement( "delete_notebook_link" );
if ( delete_notebook_link ) {
connect( delete_notebook_link, "onclick", function ( event ) {
self.delete_notebook();
event.stop();
} );
@ -1425,7 +1425,6 @@ Wiki.prototype.create_all_notes_link = function ( note_id, note_title ) {
}
Wiki.prototype.start_notebook_rename = function () {
this.clear_messages();
this.clear_pulldowns();
// if a renaming is already in progress, end the renaming instead of starting one
@ -1539,7 +1538,11 @@ Wiki.prototype.delete_notebook_forever = function ( event, notebook_id ) {
removeElement( deleted_notebook_node );
this.invoker.invoke( "/notebooks/delete", "POST", {
var items = getElementsByTagAndClassName( "div", "deleted_notebook_item" );
if ( items.length == 0 )
removeElement( "deleted_notebooks" );
this.invoker.invoke( "/notebooks/delete_forever", "POST", {
"notebook_id": notebook_id
} );