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),