core (memory, memory/sqlite): implemented fileDelete

This commit is contained in:
Goffi 2019-04-28 08:55:13 +02:00
commit 80da9a6591
2 changed files with 71 additions and 1 deletions

View file

@ -1541,6 +1541,67 @@ class Memory(object):
"""
return self.storage.fileUpdate(file_id, column, update_cb)
@defer.inlineCallbacks
def _deleteFile(self, client, peer_jid, recursive, files_path, file_data):
"""Internal method to delete files/directories recursively
@param peer_jid(jid.JID): entity requesting the deletion (must be owner of files
to delete)
@param recursive(boolean): True if recursive deletion is needed
@param files_path(unicode): path of the directory containing the actual files
@param file_data(dict): data of the file to delete
"""
if file_data[u'owner'] != peer_jid:
raise exceptions.PermissionError(
u"file {file_name} can't be deleted, {peer_jid} is not the owner"
.format(file_name=file_data[u'name'], peer_jid=peer_jid.full()))
if file_data[u'type'] == C.FILE_TYPE_DIRECTORY:
sub_files = yield self.getFiles(client, peer_jid, parent=file_data[u'id'])
if sub_files and not recursive:
raise exceptions.DataError(_(u"Can't delete directory, it is not empty"))
# we first delete the sub-files
for sub_file_data in sub_files:
yield self._deleteFile(client, peer_jid, recursive, sub_file_data)
# then the directory itself
yield self.storage.fileDelete(file_data[u'id'])
elif file_data[u'type'] == C.FILE_TYPE_FILE:
log.info(_(u"deleting file {name} with hash {file_hash}").format(
name=file_data[u'name'], file_hash=file_data[u'file_hash']))
yield self.storage.fileDelete(file_data[u'id'])
references = yield self.getFiles(
client, peer_jid, file_hash=file_data[u'file_hash'])
if references:
log.debug(u"there are still references to the file, we keep it")
else:
file_path = os.path.join(files_path, file_data[u'file_hash'])
log.info(_(u"no reference left to {file_path}, deleting").format(
file_path=file_path))
os.unlink(file_path)
else:
raise exceptions.InternalError(u'Unexpected file type: {file_type}'
.format(file_type=file_data[u'type']))
@defer.inlineCallbacks
def fileDelete(self, client, peer_jid, file_id, recursive=False):
"""Delete a single file or a directory and all its sub-files
@param file_id(unicode): id of the file to delete
@param peer_jid(jid.JID): entity requesting the deletion,
must be owner of all files to delete
@param recursive(boolean): must be True to delete a directory and all sub-files
"""
# FIXME: we only allow owner of file to delete files for now, but WRITE access
# should be checked too
files_data = yield self.getFiles(client, peer_jid, file_id)
if not files_data:
raise exceptions.NotFound(u"Can't find the file with id {file_id}".format(
file_id=file_id))
file_data = files_data[0]
if file_data[u"type"] != C.FILE_TYPE_DIRECTORY and recursive:
raise ValueError(u"recursive can only be set for directories")
files_path = self.host.getLocalPath(None, C.FILES_DIR, profile=False)
yield self._deleteFile(client, peer_jid, recursive, files_path, file_data)
## Misc ##
def isEntityAvailable(self, client, entity_jid):

View file

@ -931,7 +931,7 @@ class SqliteStorage(object):
log.error(_(u"Can't update file table"))
def fileUpdate(self, file_id, column, update_cb):
"""update a column value using a method to avoid race conditions
"""Update a column value using a method to avoid race conditions
the older value will be retrieved from database, then update_cb will be applied
to update it, and file will be updated checking that older value has not been changed meanwhile
@ -948,6 +948,15 @@ class SqliteStorage(object):
raise exceptions.InternalError('bad column name')
return self.dbpool.runInteraction(self._fileUpdate, file_id, column, update_cb)
def fileDelete(self, file_id):
"""Delete file metadata from the database
@param file_id(unicode): id of the file to delete
NOTE: file itself must still be removed, this method only handle metadata in
database
"""
return self.dbpool.runQuery("DELETE FROM files WHERE id = ?", (file_id,))
##Helper methods##
def __getFirstResult(self, result):