file_manager: simplify directory registration

Now that the file_manager directly  handles DELETE file requests, it is not necessary have the HTTP file handler perform any checks.   Thus it is no longer required to pass a "can_delete" parameter.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Arksine 2020-09-04 08:04:16 -04:00
parent 2a967303cb
commit 36c82d0c7f
3 changed files with 15 additions and 33 deletions

View File

@ -9,6 +9,7 @@ import mimetypes
import logging import logging
import tornado import tornado
from inspect import isclass from inspect import isclass
from tornado.escape import url_unescape
from tornado.routing import Rule, PathMatches, AnyMatches from tornado.routing import Rule, PathMatches, AnyMatches
from utils import ServerError from utils import ServerError
from websockets import WebsocketManager, WebSocket from websockets import WebsocketManager, WebSocket
@ -186,8 +187,7 @@ class MoonrakerApp:
self.wsm.register_local_handler(api_def, callback) self.wsm.register_local_handler(api_def, callback)
logging.info(msg) logging.info(msg)
def register_static_file_handler(self, pattern, file_path, def register_static_file_handler(self, pattern, file_path):
can_delete=False):
if pattern[0] != "/": if pattern[0] != "/":
pattern = "/server/files/" + pattern pattern = "/server/files/" + pattern
if os.path.isfile(file_path): if os.path.isfile(file_path):
@ -200,12 +200,7 @@ class MoonrakerApp:
logging.info(f"Invalid file path: {file_path}") logging.info(f"Invalid file path: {file_path}")
return return
logging.debug(f"Registering static file: ({pattern}) {file_path}") logging.debug(f"Registering static file: ({pattern}) {file_path}")
methods = ['GET'] params = {'server': self.server, 'auth': self.auth, 'path': file_path}
if can_delete:
methods.append('DELETE')
params = {
'server': self.server, 'auth': self.auth,
'path': file_path, 'methods': methods}
self.mutable_router.add_handler(pattern, FileRequestHandler, params) self.mutable_router.add_handler(pattern, FileRequestHandler, params)
def register_upload_handler(self, pattern): def register_upload_handler(self, pattern):
@ -321,12 +316,6 @@ class LocalRequestHandler(AuthorizedRequestHandler):
class FileRequestHandler(AuthorizedFileHandler): class FileRequestHandler(AuthorizedFileHandler):
def initialize(self, server, auth, path, methods,
default_filename=None):
super(FileRequestHandler, self).initialize(
server, auth, path, default_filename)
self.methods = methods
def set_extra_headers(self, path): def set_extra_headers(self, path):
# The call below shold never return an empty string, # The call below shold never return an empty string,
# as the path should have already been validated to be # as the path should have already been validated to be
@ -336,10 +325,8 @@ class FileRequestHandler(AuthorizedFileHandler):
"Content-Disposition", f"attachment; filename={basename}") "Content-Disposition", f"attachment; filename={basename}")
async def delete(self, path): async def delete(self, path):
if 'DELETE' not in self.methods:
raise tornado.web.HTTPError(405)
path = self.request.path.lstrip("/").split("/", 2)[-1] path = self.request.path.lstrip("/").split("/", 2)[-1]
path = url_unescape(path)
file_manager = self.server.lookup_plugin('file_manager') file_manager = self.server.lookup_plugin('file_manager')
try: try:
filename = await file_manager.delete_file(path) filename = await file_manager.delete_file(path)
@ -348,7 +335,7 @@ class FileRequestHandler(AuthorizedFileHandler):
raise tornado.web.HTTPError( raise tornado.web.HTTPError(
403, "File is loaded, DELETE not permitted") 403, "File is loaded, DELETE not permitted")
else: else:
raise tornado.web.HTTPError(400, str(e)) raise tornado.web.HTTPError(e.status_code, str(e))
self.finish({'result': filename}) self.finish({'result': filename})
class FileUploadHandler(AuthorizedRequestHandler): class FileUploadHandler(AuthorizedRequestHandler):

View File

@ -297,8 +297,7 @@ class Server:
vsd_path = vsd_config.get('path', None) vsd_path = vsd_config.get('path', None)
if vsd_path is not None: if vsd_path is not None:
file_manager = self.lookup_plugin('file_manager') file_manager = self.lookup_plugin('file_manager')
file_manager.register_directory( file_manager.register_directory('gcodes', vsd_path)
'gcodes', vsd_path, can_delete=True)
else: else:
logging.info( logging.info(
"Configuration for [virtual_sdcard] not found," "Configuration for [virtual_sdcard] not found,"

View File

@ -22,7 +22,6 @@ class FileManager:
self.server = config.get_server() self.server = config.get_server()
self.file_paths = {} self.file_paths = {}
self.file_lists = {} self.file_lists = {}
self.mutable_paths = set()
self.gcode_metadata = MetadataStorage(self.server) self.gcode_metadata = MetadataStorage(self.server)
self.fixed_path_args = {} self.fixed_path_args = {}
@ -48,8 +47,7 @@ class FileManager:
# Register Klippy Configuration Path # Register Klippy Configuration Path
config_path = config.get('config_path', None) config_path = config.get('config_path', None)
if config_path is not None: if config_path is not None:
ret = self.register_directory( ret = self.register_directory('config', config_path)
'config', config_path, can_delete=True)
if not ret: if not ret:
raise config.error( raise config.error(
"Option 'config_path' is not a valid directory") "Option 'config_path' is not a valid directory")
@ -73,7 +71,7 @@ class FileManager:
log_path = os.path.normpath(os.path.expanduser(log_file)) log_path = os.path.normpath(os.path.expanduser(log_file))
self.server.register_static_file_handler("klippy.log", log_path) self.server.register_static_file_handler("klippy.log", log_path)
def register_directory(self, base, path, can_delete=False): def register_directory(self, base, path):
if path is None: if path is None:
return False return False
home = os.path.expanduser('~') home = os.path.expanduser('~')
@ -87,10 +85,7 @@ class FileManager:
return False return False
if path != self.file_paths.get(base, ""): if path != self.file_paths.get(base, ""):
self.file_paths[base] = path self.file_paths[base] = path
if can_delete: self.server.register_static_file_handler(base, path)
self.mutable_paths.add(base)
self.server.register_static_file_handler(
base, path, can_delete=can_delete)
try: try:
self._update_file_list(base=base) self._update_file_list(base=base)
except Exception: except Exception:
@ -449,14 +444,15 @@ class FileManager:
return await self.delete_file(file_path) return await self.delete_file(file_path)
async def delete_file(self, path): async def delete_file(self, path):
parts = path.split("/", 1) parts = path.lstrip("/").split("/", 1)
if len(parts) != 2:
raise self.server.error(
f"Path not available for DELETE: {path}", 405)
root = parts[0] root = parts[0]
filename = parts[1] filename = parts[1]
if root not in self.file_paths or len(parts) != 2: if root not in self.file_paths or root not in FULL_ACCESS_ROOTS:
raise self.server.error(f"Invalid file path: {path}")
if root not in self.mutable_paths:
raise self.server.error( raise self.server.error(
f"Path not mutable, Cannot delete file: {path}") f"Path not available for DELETE: {path}", 405)
root_path = self.file_paths[root] root_path = self.file_paths[root]
full_path = os.path.join(root_path, filename) full_path = os.path.join(root_path, filename)
if not os.path.isfile(full_path): if not os.path.isfile(full_path):