aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/proxy/web_ui/packages.py
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-08-17 13:50:34 +0200
committerWojtek Kosior <koszko@koszko.org>2022-09-28 12:54:13 +0200
commitd54a95e0f9c689f2bbaaea90a3a16a855a408823 (patch)
tree2fcd758c6eaa7bc65a9744969a506c4ed24e0365 /src/hydrilla/proxy/web_ui/packages.py
parent2c98d04e4d4a344dc04a481b039a235678f7848e (diff)
downloadhaketilo-hydrilla-d54a95e0f9c689f2bbaaea90a3a16a855a408823.tar.gz
haketilo-hydrilla-d54a95e0f9c689f2bbaaea90a3a16a855a408823.zip
allow loading packages from zip files through web UI and listing installed mappings
Diffstat (limited to 'src/hydrilla/proxy/web_ui/packages.py')
-rw-r--r--src/hydrilla/proxy/web_ui/packages.py89
1 files changed, 87 insertions, 2 deletions
diff --git a/src/hydrilla/proxy/web_ui/packages.py b/src/hydrilla/proxy/web_ui/packages.py
index 7d67b63..a618ca0 100644
--- a/src/hydrilla/proxy/web_ui/packages.py
+++ b/src/hydrilla/proxy/web_ui/packages.py
@@ -31,14 +31,99 @@
# Enable using with Python 3.7.
from __future__ import annotations
+import tempfile
+import zipfile
import typing as t
+from urllib.parse import urlparse
+from pathlib import Path
+
import flask
+import werkzeug
+
+from ...exceptions import HaketiloException
+from ...translations import smart_gettext as _
+from .. import state as st
+from . import _app
+
+
+class InvalidUploadedMalcontent(HaketiloException):
+ def __init__(self):
+ super().__init__(_('err.proxy.uploaded_malcontent_invalid'))
bp = flask.Blueprint('load_packages', __package__)
-@bp.route('/packages/load_from_disk')
-def load_from_disk() -> flask.Response:
+@bp.route('/packages/load_from_disk', methods=['GET'])
+def load_from_disk_get() -> flask.Response:
html = flask.render_template('packages__load_from_disk.html.jinja')
return flask.make_response(html, 200)
+
+@bp.route('/packages/load_from_disk', methods=['POST'])
+def load_from_disk_post() -> werkzeug.Response:
+ parsed_url = urlparse(flask.request.referrer)
+ if parsed_url.netloc != 'hkt.mitm.it':
+ return load_from_disk_get()
+
+ zip_file_storage = flask.request.files.get('packages_zipfile')
+ if zip_file_storage is None:
+ return load_from_disk_get()
+
+ with tempfile.TemporaryDirectory() as tmpdir_str:
+ tmpdir = Path(tmpdir_str)
+ tmpdir_child = tmpdir / 'childdir'
+ tmpdir_child.mkdir()
+
+ try:
+ with zipfile.ZipFile(zip_file_storage) as zip_file:
+ zip_file.extractall(tmpdir_child)
+ except:
+ raise HaketiloException(_('err.proxy.uploaded_file_not_zip'))
+
+ extracted_top_level_files = tuple(tmpdir_child.iterdir())
+ if extracted_top_level_files == ():
+ raise InvalidUploadedMalcontent()
+
+ if len(extracted_top_level_files) == 1 and \
+ extracted_top_level_files[0].is_dir():
+ malcontent_dir_path = extracted_top_level_files[0]
+ else:
+ malcontent_dir_path = tmpdir_child
+
+ state = t.cast(_app.WebUIApp, flask.current_app)._haketilo_state
+
+ try:
+ state.import_packages(malcontent_dir_path)
+ except:
+ raise InvalidUploadedMalcontent()
+
+ return flask.redirect(flask.url_for('.packages'))
+
+@bp.route('/packages')
+def packages() -> flask.Response:
+ state = t.cast(_app.WebUIApp, flask.current_app)._haketilo_state
+
+ display_infos = state.mapping_version_store().get_display_infos()
+ sorted_infos = sorted(display_infos, key=(lambda di: di.info))
+
+ html = flask.render_template(
+ 'packages.html.jinja',
+ display_infos = sorted_infos
+ )
+ return flask.make_response(html, 200)
+
+@bp.route('/packages/view/<string:mapping_id>')
+def show_package(mapping_id: str) -> flask.Response:
+ state = t.cast(_app.WebUIApp, flask.current_app)._haketilo_state
+
+ try:
+ store = state.mapping_version_store()
+ display_info = store.get(mapping_id).get_display_info()
+
+ html = flask.render_template(
+ 'packages__show_single.html.jinja',
+ display_info = display_info
+ )
+ return flask.make_response(html, 200)
+ except st.MissingItemError:
+ flask.abort(404)