Added ability to delete files from storage, when authorized.

This commit is contained in:
Marat Fayzullin 2024-01-21 19:19:48 -05:00
parent 686850b2a3
commit fa913be306
5 changed files with 59 additions and 2 deletions

View File

@ -40,3 +40,8 @@ img {
.file-tile { .file-tile {
width: 32%; width: 32%;
} }
.file-delete {
position: relative;
bottom : 5px;
}

View File

@ -6,6 +6,7 @@
<link rel="stylesheet" type="text/css" href="static/css/files.css" /> <link rel="stylesheet" type="text/css" href="static/css/files.css" />
<script src="static/lib/jquery-3.2.1.min.js"></script> <script src="static/lib/jquery-3.2.1.min.js"></script>
<script src="static/lib/Header.js"></script> <script src="static/lib/Header.js"></script>
<script src="static/files.js"></script>
</HEAD><BODY> </HEAD><BODY>
${header} ${header}
<div class="container"> <div class="container">

18
htdocs/files.js Normal file
View File

@ -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();
});

View File

@ -1,16 +1,41 @@
from owrx.controllers.admin import Authentication, AuthorizationMixin
from owrx.controllers.template import WebpageController from owrx.controllers.template import WebpageController
from owrx.controllers.assets import AssetsController from owrx.controllers.assets import AssetsController
from owrx.storage import Storage from owrx.storage import Storage
import json
import re import re
import os
import logging
logger = logging.getLogger(__name__)
class FileController(AssetsController): class FileController(AssetsController):
def getFilePath(self, file): def getFilePath(self, file):
return Storage.getFilePath(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): class FilesController(WebpageController):
def template_variables(self): 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)$') isimg = re.compile(r'.*\.(png|bmp|gif|jpg)$')
issnd = re.compile(r'.*\.(mp3|wav)$') issnd = re.compile(r'.*\.(mp3|wav)$')
files = Storage.getSharedInstance().getStoredFiles() files = Storage.getSharedInstance().getStoredFiles()
@ -27,12 +52,19 @@ class FilesController(WebpageController):
shot = "static/gfx/audio-file.png" shot = "static/gfx/audio-file.png"
else: else:
shot = "static/gfx/text-file.png" shot = "static/gfx/text-file.png"
# Admin user gets to delete files
if admin:
buttons = ('<button type="button" ' +
'class="btn btn-sm btn-danger file-delete" ' +
'value="' + files[i] + '">delete</button>')
else:
buttons = ""
# Print out individual tiles # Print out individual tiles
rows += ('<td class="file-tile">' + rows += ('<td class="file-tile">' +
('<a href="/files/%s" download="%s">' % (files[i], files[i])) + ('<a href="/files/%s" download="%s">' % (files[i], files[i])) +
('<img src="%s" download="%s">' % (shot, files[i])) + ('<img src="%s" download="%s">' % (shot, files[i])) +
('<p class="file-title">%s</p>' % files[i]) + ('<p class="file-title">%s</p>' % files[i]) +
'</a></td>\n') ('</a>%s</td>\n' % buttons))
# Finish a row # Finish a row
if i % 3 == 2: if i % 3 == 2:
rows += '</tr>\n' rows += '</tr>\n'

View File

@ -1,7 +1,7 @@
from owrx.controllers.status import StatusController from owrx.controllers.status import StatusController
from owrx.controllers.template import IndexController, MapController, PolicyController from owrx.controllers.template import IndexController, MapController, PolicyController
from owrx.controllers.feature import FeatureController 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.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController
from owrx.controllers.websocket import WebSocketController from owrx.controllers.websocket import WebSocketController
from owrx.controllers.api import ApiController from owrx.controllers.api import ApiController
@ -102,6 +102,7 @@ class Router(object):
StaticRoute("/features", FeatureController), StaticRoute("/features", FeatureController),
StaticRoute("/files", FilesController), StaticRoute("/files", FilesController),
RegexRoute("^/files/(%s)$" % Storage.getNamePattern(), FileController), RegexRoute("^/files/(%s)$" % Storage.getNamePattern(), FileController),
StaticRoute("/files/delete", FileDeleteController, method="POST", options={"action": "delete"}),
StaticRoute("/api/features", ApiController), StaticRoute("/api/features", ApiController),
StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}), StaticRoute("/metrics", MetricsController, options={"action": "prometheusAction"}),
StaticRoute("/metrics.json", MetricsController), StaticRoute("/metrics.json", MetricsController),