Implemented delete forever for notebooks. And unit tests!
This commit is contained in:
parent
7bd83199a1
commit
eec5ef6411
|
@ -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(
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
} );
|
||||
|
||||
|
|
Reference in New Issue
Block a user