diff --git a/htdocs/css/files.css b/htdocs/css/files.css index 3c34ec89..e1d293ed 100644 --- a/htdocs/css/files.css +++ b/htdocs/css/files.css @@ -40,3 +40,8 @@ img { .file-tile { width: 32%; } + +.file-delete { + position: relative; + bottom : 5px; +} diff --git a/htdocs/files.html b/htdocs/files.html index 51c10bb1..2705304e 100644 --- a/htdocs/files.html +++ b/htdocs/files.html @@ -6,6 +6,7 @@ + ${header}
diff --git a/htdocs/files.js b/htdocs/files.js new file mode 100644 index 00000000..5977e6b2 --- /dev/null +++ b/htdocs/files.js @@ -0,0 +1,18 @@ +$.fn.fileTile = function() { + this.each(function() { + $(this).on('click', '.file-delete', function(e) { + $.ajax("/files/delete", { + data: JSON.stringify({ name: this.value }), + contentType: 'application/json', + method: 'POST' + }).done(function() { + document.location.reload(); + }); + return false; + }); + }); +}; + +$(function(){ + $('.file-tile').fileTile(); +}); diff --git a/owrx/controllers/file.py b/owrx/controllers/file.py index b90a2d6e..571c85e6 100644 --- a/owrx/controllers/file.py +++ b/owrx/controllers/file.py @@ -1,16 +1,41 @@ +from owrx.controllers.admin import Authentication, AuthorizationMixin from owrx.controllers.template import WebpageController from owrx.controllers.assets import AssetsController from owrx.storage import Storage +import json import re +import os +import logging + +logger = logging.getLogger(__name__) + class FileController(AssetsController): def getFilePath(self, file): return Storage.getFilePath(file) +class FileDeleteController(AuthorizationMixin, WebpageController): + def delete(self): + try: + data = json.loads(self.get_body().decode("utf-8")) + file = data["name"].strip() if "name" in data else "" + if len(file) > 0 and re.match(Storage.getNamePattern(), file): + file = Storage.getFilePath(file) + logger.info("Deleting '{0}'.".format(file)) + os.remove(file) + self.send_response("{}", content_type="application/json", code=200) + except Exception as e: + logger.debug("delete(): " + str(e)) + self.send_response("{}", content_type="application/json", code=400) + + class FilesController(WebpageController): def template_variables(self): + # We need to know if the user is authorized to delete files + user = Authentication().getUser(self.request) + admin = user is not None and user.is_enabled() and not user.must_change_password isimg = re.compile(r'.*\.(png|bmp|gif|jpg)$') issnd = re.compile(r'.*\.(mp3|wav)$') files = Storage.getSharedInstance().getStoredFiles() @@ -27,12 +52,19 @@ class FilesController(WebpageController): shot = "static/gfx/audio-file.png" else: shot = "static/gfx/text-file.png" + # Admin user gets to delete files + if admin: + buttons = ('') + else: + buttons = "" # Print out individual tiles rows += ('' + ('' % (files[i], files[i])) + ('' % (shot, files[i])) + ('

%s

' % files[i]) + - '
\n') + ('%s\n' % buttons)) # Finish a row if i % 3 == 2: rows += '\n' diff --git a/owrx/http.py b/owrx/http.py index 7727da9d..cb601a75 100644 --- a/owrx/http.py +++ b/owrx/http.py @@ -1,7 +1,7 @@ from owrx.controllers.status import StatusController from owrx.controllers.template import IndexController, MapController, PolicyController from owrx.controllers.feature import FeatureController -from owrx.controllers.file import FilesController, FileController +from owrx.controllers.file import FilesController, FileController, FileDeleteController from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController from owrx.controllers.websocket import WebSocketController from owrx.controllers.api import ApiController @@ -102,6 +102,7 @@ class Router(object): StaticRoute("/features", FeatureController), StaticRoute("/files", FilesController), RegexRoute("^/files/(%s)$" % Storage.getNamePattern(), FileController), + StaticRoute("/files/delete", FileDeleteController, method="POST", options={"action": "delete"}), StaticRoute("/api/features", ApiController), StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}), StaticRoute("/metrics.json", MetricsController),