diff options
Diffstat (limited to 'src/hydrilla/proxy')
-rw-r--r-- | src/hydrilla/proxy/policies/base.py | 15 | ||||
-rw-r--r-- | src/hydrilla/proxy/policies/payload.py | 52 | ||||
-rw-r--r-- | src/hydrilla/proxy/state.py | 5 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/base.py | 3 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/concrete_state.py | 53 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/repos.py | 5 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/options.py | 69 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/prompts.py | 116 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/root.py | 4 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/base.html.jinja | 17 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/items/item_viewversion.html.jinja | 8 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/items/package_viewversion.html.jinja | 12 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/options.html.jinja | 86 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/prompts/auto_install_error.html.jinja | 37 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/prompts/package_suggestion.html.jinja | 58 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja | 6 |
16 files changed, 439 insertions, 107 deletions
diff --git a/src/hydrilla/proxy/policies/base.py b/src/hydrilla/proxy/policies/base.py index bb95d29..8ffc45e 100644 --- a/src/hydrilla/proxy/policies/base.py +++ b/src/hydrilla/proxy/policies/base.py @@ -58,22 +58,21 @@ class Policy(ABC): """....""" process_request: t.ClassVar[bool] = False process_response: t.ClassVar[bool] = False + anticache: t.ClassVar[bool] = True priority: t.ClassVar[PolicyPriority] - @property - def anticache(self) -> bool: - return self.process_request or self.process_response - def consume_request(self, request_info: http_messages.RequestInfo) \ -> t.Optional[ProducedMessage]: - """....""" - return None + raise NotImplementedError( + 'This kind of policy does not consume requests.' + ) def consume_response(self, response_info: http_messages.ResponseInfo) \ -> t.Optional[http_messages.ProducedResponse]: - """....""" - return None + raise NotImplementedError( + 'This kind of policy does not consume responses.' + ) # mypy needs to be corrected: diff --git a/src/hydrilla/proxy/policies/payload.py b/src/hydrilla/proxy/policies/payload.py index a063c7c..1069c41 100644 --- a/src/hydrilla/proxy/policies/payload.py +++ b/src/hydrilla/proxy/policies/payload.py @@ -60,6 +60,20 @@ class PayloadAwarePolicy(base.Policy): return f'{request_url.url_without_path}/{"/".join(base_path_segments)}/' + def _payload_details_to_signed_query_string( + self, + _salt: str, + **extra_keys: str + ) -> str: + params: t.Mapping[str, str] = { + 'payload_id': self.payload_data.ref.id, + **extra_keys + } + + serializer = URLSafeSerializer(self.payload_data.global_secret, _salt) + + return urlencode({'details': serializer.dumps(params)}) + @dc.dataclass(frozen=True) # type: ignore[misc] class PayloadAwarePolicyFactory(base.PolicyFactory): @@ -283,20 +297,18 @@ class AutoPayloadInjectPolicy(PayloadInjectPolicy): return super().consume_response(response_info) except (state.RepoCommunicationError, state.FileInstallationError, _PayloadHasProblemsError) as ex: - params = { - 'next_url': response_info.url.orig_url, - 'payload_id': self.payload_data.ref.id + extra_params: dict[str, str] = { + 'next_url': response_info.url.orig_url } - if isinstance(ex, state.FileInstallationError): - params['repo_id'] = ex.repo_id - params['file_sha256'] = ex.sha256 + extra_params['repo_id'] = ex.repo_id + extra_params['file_sha256'] = ex.sha256 - serializer = URLSafeSerializer( - self.payload_data.global_secret, - salt = 'auto_install_error' + query = self._payload_details_to_signed_query_string( + _salt = 'auto_install_error', + **extra_params ) - query = urlencode({'details': serializer.dumps(params)}) + redirect_url = 'https://hkt.mitm.it/auto_install_error?' + query msg = 'Error occured when installing payload. Redirecting.' @@ -310,13 +322,25 @@ class AutoPayloadInjectPolicy(PayloadInjectPolicy): @dc.dataclass(frozen=True) class PayloadSuggestPolicy(PayloadAwarePolicy): """....""" + process_request: t.ClassVar[bool] = True + priority: t.ClassVar[base.PolicyPriority] = base.PolicyPriority._ONE - def make_response(self, request_info: http_messages.RequestInfo) \ + def consume_request(self, request_info: http_messages.RequestInfo) \ -> http_messages.ProducedResponse: - """....""" - # TODO: implement - return http_messages.ProducedResponse(200, ((b'a', b'b'),), b'') + query = self._payload_details_to_signed_query_string( + _salt = 'package_suggestion', + next_url = request_info.url.orig_url + ) + + redirect_url = 'https://hkt.mitm.it/package_suggestion?' + query + msg = 'A package was found that could be used on this site. Redirecting.' + + return http_messages.ProducedResponse( + status_code = 303, + headers = [(b'Location', redirect_url.encode())], + body = msg.encode() + ) @dc.dataclass(frozen=True, unsafe_hash=True) diff --git a/src/hydrilla/proxy/state.py b/src/hydrilla/proxy/state.py index 491a865..abea7a7 100644 --- a/src/hydrilla/proxy/state.py +++ b/src/hydrilla/proxy/state.py @@ -448,11 +448,6 @@ class HaketiloState(ABC): ... @abstractmethod - def get_repo_iteration(self, repo_iteration_id: str) -> RepoIterationRef: - """....""" - ... - - @abstractmethod def mapping_store(self) -> MappingStore: ... diff --git a/src/hydrilla/proxy/state_impl/base.py b/src/hydrilla/proxy/state_impl/base.py index 0559a42..75d733f 100644 --- a/src/hydrilla/proxy/state_impl/base.py +++ b/src/hydrilla/proxy/state_impl/base.py @@ -140,10 +140,9 @@ class HaketiloStateWithFields(st.HaketiloState): """....""" store_dir: Path connection: sqlite3.Connection + settings: st.HaketiloGlobalSettings current_cursor: t.Optional[sqlite3.Cursor] = None - #settings: st.HaketiloGlobalSettings - secret: bytes = dc.field(default_factory=(lambda: secrets.token_bytes(16))) policy_tree: PolicyTree = PolicyTree() diff --git a/src/hydrilla/proxy/state_impl/concrete_state.py b/src/hydrilla/proxy/state_impl/concrete_state.py index 8bd25a9..3611db1 100644 --- a/src/hydrilla/proxy/state_impl/concrete_state.py +++ b/src/hydrilla/proxy/state_impl/concrete_state.py @@ -56,10 +56,24 @@ from . import _operations here = Path(__file__).resolve().parent -@dc.dataclass(frozen=True, unsafe_hash=True) -class ConcreteRepoIterationRef(st.RepoIterationRef): - pass - +def load_settings(cursor: sqlite3.Cursor) -> st.HaketiloGlobalSettings: + cursor.execute( + ''' + SELECT + default_allow_scripts, repo_refresh_seconds, mapping_use_mode + FROM + general + ''' + ) + + (default_allow_scripts, repo_refresh_seconds, + mapping_use_mode), = cursor.fetchall() + + return st.HaketiloGlobalSettings( + default_allow_scripts = default_allow_scripts, + repo_refresh_seconds = repo_refresh_seconds, + mapping_use_mode = st.MappingUseMode(mapping_use_mode) + ) @dc.dataclass class ConcreteHaketiloState(base.HaketiloStateWithFields): @@ -233,9 +247,6 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): def repo_store(self) -> st.RepoStore: return repos.ConcreteRepoStore(self) - def get_repo_iteration(self, repo_iteration_id: str) -> st.RepoIterationRef: - return ConcreteRepoIterationRef(repo_iteration_id) - def mapping_store(self) -> st.MappingStore: return items.ConcreteMappingStore(self) @@ -255,11 +266,8 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): return self.secret def get_settings(self) -> st.HaketiloGlobalSettings: - return st.HaketiloGlobalSettings( - mapping_use_mode = st.MappingUseMode.AUTO, - default_allow_scripts = False, - repo_refresh_seconds = 0 - ) + with self.lock: + return self.settings def update_settings( self, @@ -268,7 +276,18 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): default_allow_scripts: t.Optional[bool] = None, repo_refresh_seconds: t.Optional[int] = None ) -> None: - raise NotImplementedError() + with self.cursor(transaction=True) as cursor: + def set_opt(col_name: str, val: t.Union[bool, int, str]) -> None: + cursor.execute(f'UPDATE general SET {col_name} = ?;', (val,)) + + if mapping_use_mode is not None: + set_opt('mapping_use_mode', mapping_use_mode.value) + if default_allow_scripts is not None: + set_opt('default_allow_scripts', default_allow_scripts) + if repo_refresh_seconds is not None: + set_opt('repo_refresh_seconds', repo_refresh_seconds) + + self.settings = load_settings(cursor) @staticmethod def make(store_dir: Path) -> 'ConcreteHaketiloState': @@ -277,7 +296,11 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): isolation_level = None, check_same_thread = False ) + + global_settings = load_settings(connection.cursor()) + return ConcreteHaketiloState( - store_dir = store_dir, - connection = connection + store_dir = store_dir, + connection = connection, + settings = global_settings ) diff --git a/src/hydrilla/proxy/state_impl/repos.py b/src/hydrilla/proxy/state_impl/repos.py index 8a3fe64..383d147 100644 --- a/src/hydrilla/proxy/state_impl/repos.py +++ b/src/hydrilla/proxy/state_impl/repos.py @@ -363,8 +363,3 @@ class ConcreteRepoStore(st.RepoStore): result.append(make_repo_display_info(ref, *rest)) return result - - -@dc.dataclass(frozen=True, unsafe_hash=True) -class ConcreteRepoIterationRef(st.RepoIterationRef): - state: base.HaketiloStateWithFields diff --git a/src/hydrilla/proxy/web_ui/options.py b/src/hydrilla/proxy/web_ui/options.py new file mode 100644 index 0000000..f24c356 --- /dev/null +++ b/src/hydrilla/proxy/web_ui/options.py @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Proxy web UI options page. +# +# This file is part of Hydrilla&Haketilo. +# +# Copyright (C) 2022 Wojtek Kosior +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# +# I, Wojtek Kosior, thereby promise not to sue for violation of this +# file's license. Although I request that you do not make use this code +# in a proprietary program, I am not going to enforce this in court. + +# Enable using with Python 3.7. +from __future__ import annotations + +import typing as t + +import flask +import werkzeug + +from .. import state as st +from . import _app + + +bp = flask.Blueprint('options', __package__) + +@bp.route('/options', methods=['GET']) +def options(errors: t.Mapping[str, bool] = {}) -> werkzeug.Response: + html = flask.render_template( + 'options.html.jinja', + settings = _app.get_haketilo_state().get_settings(), + **errors + ) + return flask.make_response(html, 200) + +@bp.route('/options', methods=['POST']) +def options_post() -> werkzeug.Response: + action = flask.request.form['action'] + + state = _app.get_haketilo_state() + + if action == 'use_enabled': + state.update_settings(mapping_use_mode=st.MappingUseMode.WHEN_ENABLED) + elif action == 'use_auto': + state.update_settings(mapping_use_mode=st.MappingUseMode.AUTO) + elif action == 'use_question': + state.update_settings(mapping_use_mode=st.MappingUseMode.QUESTION) + elif action == 'allow_scripts': + state.update_settings(default_allow_scripts=True) + elif action == 'block_scripts': + state.update_settings(default_allow_scripts=False) + else: + raise ValueError() + + return flask.redirect(flask.url_for('.options'), 303) diff --git a/src/hydrilla/proxy/web_ui/prompts.py b/src/hydrilla/proxy/web_ui/prompts.py index b546e47..58b7906 100644 --- a/src/hydrilla/proxy/web_ui/prompts.py +++ b/src/hydrilla/proxy/web_ui/prompts.py @@ -42,30 +42,37 @@ from . import _app bp = flask.Blueprint('prompts', __package__) -@bp.route('/auto_install_error', methods=['GET']) -def auto_install_error_prompt() -> werkzeug.Response: - state = _app.get_haketilo_state() +def deserialized_request_details(salt: str) -> t.Mapping[str, str]: serializer = URLSafeSerializer( - state.get_secret(), - salt = 'auto_install_error' + _app.get_haketilo_state().get_secret(), + salt = salt ) + return serializer.loads(flask.request.args['details']) + + +@bp.route('/auto_install_error', methods=['GET']) +def auto_install_error_prompt(errors: t.Mapping[str, bool] = {}) \ + -> werkzeug.Response: try: - details: t.Mapping[str, str] = \ - serializer.loads(flask.request.args['details']) + details = deserialized_request_details('auto_install_error') except: return flask.redirect(flask.url_for('home')) try: - payload_ref = state.payload_store().get(details['payload_id']) + payload_store = _app.get_haketilo_state().payload_store() + payload_ref = payload_store.get(details['payload_id']) display_info = payload_ref.get_display_info() + if not display_info.has_problems: + return flask.redirect(details['next_url']) + html = flask.render_template( 'prompts/auto_install_error.html.jinja', display_info = display_info, - next_url = details['next_url'] + **errors ) return flask.make_response(html, 200) except st.MissingItemError: @@ -73,12 +80,16 @@ def auto_install_error_prompt() -> werkzeug.Response: @bp.route('/auto_install_error', methods=['POST']) def auto_install_error_prompt_post() -> werkzeug.Response: + try: + details = deserialized_request_details('auto_install_error') + except: + return flask.redirect(flask.url_for('home'), code=303) + form_data = flask.request.form action = form_data['action'] mapping_ver_id = str(int(form_data['mapping_ver_id'])) - payload_id = str(int(form_data['payload_id'])) - next_url = form_data['next_url'] + payload_id = str(int(details['payload_id'])) state = _app.get_haketilo_state() @@ -92,24 +103,81 @@ def auto_install_error_prompt_post() -> werkzeug.Response: if action == 'disable_mapping': mapping_ver_ref.update_mapping_status(st.EnabledStatus.DISABLED) elif action == 'retry_install': - payload_ref.ensure_items_installed() + payload_ref.ensure_items_installed() else: raise ValueError() - except (st.RepoCommunicationError, st.FileInstallationError): - params = {'payload_id': payload_id, 'next_url': next_url} + except st.RepoCommunicationError: + assert action == 'retry_install' + return auto_install_error_prompt({'repo_communication_error': True}) + except st.FileInstallationError: + assert action == 'retry_install' + return auto_install_error_prompt({'file_installation_error': True}) + except st.MissingItemError: + flask.abort(404) - serializer = URLSafeSerializer( - state.get_secret(), - salt = 'auto_install_error' - ) - query = urlencode({'details': params}) - redirect_url = flask.url_for( - '.auto_install_error_prompt', - details = serializer.dumps(params) + return flask.redirect(details['next_url']) + + +@bp.route('/package_suggestion', methods=['GET']) +def package_suggestion_prompt(errors: t.Mapping[str, bool] = {}) \ + -> werkzeug.Response: + try: + details = deserialized_request_details('package_suggestion') + except: + return flask.redirect(flask.url_for('home')) + + try: + payload_store = _app.get_haketilo_state().payload_store() + payload_ref = payload_store.get(details['payload_id']) + + display_info = payload_ref.get_display_info() + + if display_info.mapping_info.active != st.ActiveStatus.AUTO: + return flask.redirect(details['next_url']) + + html = flask.render_template( + 'prompts/package_suggestion.html.jinja', + display_info = display_info, + **errors ) + return flask.make_response(html, 200) + except st.MissingItemError: + flask.abort(404) + +@bp.route('/package_suggestion', methods=['POST']) +def package_suggestion_prompt_post() -> werkzeug.Response: + try: + details = deserialized_request_details('package_suggestion') + except: + return flask.redirect(flask.url_for('home')) + + form_data = flask.request.form + action = form_data['action'] - return flask.redirect(redirect_url) + mapping_ver_id = str(int(form_data['mapping_ver_id'])) + + state = _app.get_haketilo_state() + + try: + mapping_ver_store = state.mapping_version_store() + mapping_ver_ref = mapping_ver_store.get(mapping_ver_id) + + if action == 'disable_mapping': + mapping_ver_ref.update_mapping_status(st.EnabledStatus.DISABLED) + elif action == 'enable_mapping': + mapping_ver_ref.update_mapping_status( + enabled = st.EnabledStatus.ENABLED, + frozen = st.FrozenStatus.EXACT_VERSION + ) + else: + raise ValueError() + except st.RepoCommunicationError: + assert action == 'enable_mapping' + return package_suggestion_prompt({'repo_communication_error': True}) + except st.FileInstallationError: + assert action == 'enable_mapping' + return package_suggestion_prompt({'file_installation_error': True}) except st.MissingItemError: flask.abort(404) - return flask.redirect(next_url) + return flask.redirect(details['next_url']) diff --git a/src/hydrilla/proxy/web_ui/root.py b/src/hydrilla/proxy/web_ui/root.py index ff7c1f7..855345e 100644 --- a/src/hydrilla/proxy/web_ui/root.py +++ b/src/hydrilla/proxy/web_ui/root.py @@ -44,6 +44,7 @@ from ...translations import translation as make_translation from ... import item_infos from .. import state as st from .. import http_messages +from . import options from . import repos from . import items from . import prompts @@ -89,10 +90,11 @@ class WebUIAppImpl(_app.WebUIApp): self.jinja_env.globals['InstalledStatus'] = st.InstalledStatus self.jinja_env.globals['ActiveStatus'] = st.ActiveStatus self.jinja_env.globals['ItemType'] = item_infos.ItemType + self.jinja_env.globals['MappingUseMode'] = st.MappingUseMode self.before_request(authenticate_by_referrer) - for blueprint in [repos.bp, items.bp, prompts.bp]: + for blueprint in [repos.bp, items.bp, prompts.bp, options.bp]: self.register_blueprint(blueprint) # Flask app is not thread-safe and has to be accompanied by an ugly lock. This diff --git a/src/hydrilla/proxy/web_ui/templates/base.html.jinja b/src/hydrilla/proxy/web_ui/templates/base.html.jinja index 918fb28..06af7d9 100644 --- a/src/hydrilla/proxy/web_ui/templates/base.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/base.html.jinja @@ -20,9 +20,9 @@ in a proprietary work, I am not going to enforce this in court. -#} <!DOCTYPE html> -{% macro button_row(buttons_data) %} +{% macro button_row(buttons_data, common_fields={}) %} <div class="flex-row"> - {% for classes, text, action in buttons_data %} + {% for classes, text, extra_fields in buttons_data %} {% if not loop.first %} <div class="button-row-separator"></div> {% do classes.append('button-bordering-left') %} @@ -39,7 +39,13 @@ in a proprietary work, I am not going to enforce this in court. {% endif %} <form method="POST" class="flex-row"> - <input name="action" value="{{ action }}" type="hidden"> + {% for name, value in extra_fields.items() %} + <input name="{{ name }}" value="{{ value }}" type="hidden"> + {% endfor %} + {% for name, value in common_fields.items() %} + <input name="{{ name }}" value="{{ value }}" type="hidden"> + {% endfor %} + <button class="{{ classes|join(' ') }}"{{ disabled_attr }}> {{ text }} </button> @@ -92,6 +98,10 @@ in a proprietary work, I am not going to enforce this in court. background-color: #fcc; } + #main > .error-note:first-child { + margin-top: 10px; + } + .block-with-bottom-margin, .flex-row, aside, p { display: block; margin: 0 0 10px 0; @@ -226,6 +236,7 @@ in a proprietary work, I am not going to enforce this in court. {% set navigation_bar = [ ('home', _('web_ui.base.nav.home')), + ('options.options', _('web_ui.base.nav.options')), ('items.packages', _('web_ui.base.nav.packages')), ('items.libraries', _('web_ui.base.nav.libraries')), ('repos.repos', _('web_ui.base.nav.repos')), diff --git a/src/hydrilla/proxy/web_ui/templates/items/item_viewversion.html.jinja b/src/hydrilla/proxy/web_ui/templates/items/item_viewversion.html.jinja index f1d34cc..edfb772 100644 --- a/src/hydrilla/proxy/web_ui/templates/items/item_viewversion.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/items/item_viewversion.html.jinja @@ -91,10 +91,14 @@ in a proprietary work, I am not going to enforce this in court. {% do uninstall_but_classes.append('disabled-button') %} {% endif %} {% endif %}{# else/ version_display_info.installed == InstalledStatus.FA... #} + + {% set uninstall_fields = {'action': 'uninstall_item_version'} %} + {% set install_fields = {'action': 'install_item_version'} %} + {{ button_row([ - (uninstall_but_classes, uninstall_text, 'uninstall_item_version'), - (install_but_classes, install_text, 'install_item_version') + (uninstall_but_classes, uninstall_text, uninstall_fields), + (install_but_classes, install_text, install_fields) ]) }} {% endblock main_info %} diff --git a/src/hydrilla/proxy/web_ui/templates/items/package_viewversion.html.jinja b/src/hydrilla/proxy/web_ui/templates/items/package_viewversion.html.jinja index 1eb9878..c9448e7 100644 --- a/src/hydrilla/proxy/web_ui/templates/items/package_viewversion.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/items/package_viewversion.html.jinja @@ -89,9 +89,9 @@ in a proprietary work, I am not going to enforce this in court. {{ button_row([ - (disable_but_classes, disable_text, 'disable_item'), - (unenable_but_classes, unenable_text, 'unenable_item'), - (enable_but_classes, enable_text, 'enable_item_version') + (disable_but_classes, disable_text, {'action': 'disable_item'}), + (unenable_but_classes, unenable_text, {'action': 'unenable_item'}), + (enable_but_classes, enable_text, {'action': 'enable_item_version'}) ]) }} @@ -182,9 +182,9 @@ in a proprietary work, I am not going to enforce this in court. {{ button_row([ - (unpin_but_classes, unpin_text, 'unfreeze_item'), - (pin_repo_but_classes, pin_repo_text, 'freeze_to_repo'), - (pin_ver_but_classes, pin_ver_text, 'freeze_to_version') + (unpin_but_classes, unpin_text, {'action': 'unfreeze_item'}), + (pin_repo_but_classes, pin_repo_text, {'action': 'freeze_to_repo'}), + (pin_ver_but_classes, pin_ver_text, {'action': 'freeze_to_version'}) ]) }} diff --git a/src/hydrilla/proxy/web_ui/templates/options.html.jinja b/src/hydrilla/proxy/web_ui/templates/options.html.jinja new file mode 100644 index 0000000..69fc1b0 --- /dev/null +++ b/src/hydrilla/proxy/web_ui/templates/options.html.jinja @@ -0,0 +1,86 @@ +{# +SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + +Proxy web UI settings page. + +This file is part of Hydrilla&Haketilo. + +Copyright (C) 2022 Wojtek Kosior + +Dual licensed under +* GNU General Public License v3.0 or later and +* Creative Commons Attribution Share Alike 4.0 International. + +You can choose to use either of these licenses or both. + + +I, Wojtek Kosior, thereby promise not to sue for violation of this +file's licenses. Although I request that you do not make use this code +in a proprietary work, I am not going to enforce this in court. +#} +{% extends "base.html.jinja" %} + +{% block title %} {{ _('web_ui.options.title') }} {% endblock %} + +{% block main %} + <h3> + {{ _('web_ui.options.heading') }} + </h3> + + {% set use_enabled_but_classes = ['green-button'] %} + {% set use_auto_but_classes = ['green-button'] %} + {% set use_question_but_classes = ['green-button'] %} + + <p> + {% if settings.mapping_use_mode == MappingUseMode.WHEN_ENABLED %} + {% do use_enabled_but_classes.append('disabled-button') %} + {{ _('web_ui.options.packages_are_used_when_enabled') }} + {% elif settings.mapping_use_mode == MappingUseMode.QUESTION %} + {% do use_question_but_classes.append('disabled-button') %} + {{ _('web_ui.options.user_gets_asked_whether_to_enable_package') }} + {% else %} + {# settings.mapping_use_mode == MappingUseMode.AUTO #} + {% do use_auto_but_classes.append('disabled-button') %} + {{ _('web_ui.options.packages_are_used_automatically') }} + {% endif %} + </p> + + {{ + button_row([ + (use_enabled_but_classes, + _('web_ui.options.use_enabled_button'), + {'action': 'use_enabled'}), + (use_question_but_classes, + _('web_ui.options.use_question_button'), + {'action': 'use_question'}), + (use_auto_but_classes, + _('web_ui.options.use_auto_button'), + {'action': 'use_auto'}) + ]) + }} + + <div class="horizontal-separator"></div> + + {% set allow_but_classes = ['red-button'] %} + {% set block_but_classes = ['green-button'] %} + + <p> + {% if settings.default_allow_scripts %} + {% do allow_but_classes.append('disabled-button') %} + {{ _('web_ui.options.scripts_are_allowed_by_default') }} + {% else %} + {% do block_but_classes.append('disabled-button') %} + {{ _('web_ui.options.scripts_are_blocked_by_default') }} + {% endif %} + </p> + + {% set allow_but_text = _('web_ui.options.allow_scripts_button') %} + {% set block_but_text = _('web_ui.options.block_scripts_button') %} + + {{ + button_row([ + (allow_but_classes, allow_but_text, {'action': 'allow_scripts'}), + (block_but_classes, block_but_text, {'action': 'block_scripts'}) + ]) + }} +{% endblock %} diff --git a/src/hydrilla/proxy/web_ui/templates/prompts/auto_install_error.html.jinja b/src/hydrilla/proxy/web_ui/templates/prompts/auto_install_error.html.jinja index 01f5c19..82a12e5 100644 --- a/src/hydrilla/proxy/web_ui/templates/prompts/auto_install_error.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/prompts/auto_install_error.html.jinja @@ -24,19 +24,15 @@ in a proprietary work, I am not going to enforce this in court. {{ _('web_ui.prompts.auto_install_error.title') }} {% endblock %} -{% macro button_form(action, button_class, button_text) %} - <form class="flex-row" method="POST"> - <input name="next_url" value="{{ next_url }}" type="hidden"> - <input name="payload_id" value="{{ display_info.ref.id }}" type="hidden"> - {% set mapping_ver_id = display_info.mapping_info.ref.id %} - <input name="mapping_ver_id" value="{{ mapping_ver_id }}" type="hidden"> - - <input name="action" value="{{ action }}" type="hidden"> - <button class="{{ button_class }}">{{ button_text }}</button> - </form> -{% endmacro %} - {% block main %} + {% if file_installation_error is defined %} + {{ error_note(_('web_ui.err.retry_install.file_installation_error')) }} + {% endif %} + + {% if repo_communication_error is defined %} + {{ error_note(_('web_ui.err.retry_install.repo_communication_error')) }} + {% endif %} + <h3> {{ _('web_ui.prompts.auto_install_error.heading') }} </h3> @@ -48,13 +44,14 @@ in a proprietary work, I am not going to enforce this in court. }} </p> - <div class="flex-row"> - {% set but_text = _('web_ui.prompts.auto_install_error.disable_button') %} - {{ button_form('disable_mapping', 'red-button', but_text) }} - - <div class="button-row-separator"></div> + {% set disable_text = _('web_ui.prompts.auto_install_error.disable_button') %} + {% set retry_text = _('web_ui.prompts.auto_install_error.retry_button') %} - {% set but_text = _('web_ui.prompts.auto_install_error.retry_button') %} - {{ button_form('retry_install', 'green-button', but_text) }} - </div> + {{ + button_row([ + (['red-button'], disable_text, {'action': 'disable_mapping'}), + (['green-button'], retry_text, {'action': 'retry_install'}) + ], {'mapping_ver_id': display_info.mapping_info.ref.id} + ) + }} {% endblock %} diff --git a/src/hydrilla/proxy/web_ui/templates/prompts/package_suggestion.html.jinja b/src/hydrilla/proxy/web_ui/templates/prompts/package_suggestion.html.jinja new file mode 100644 index 0000000..ea906bb --- /dev/null +++ b/src/hydrilla/proxy/web_ui/templates/prompts/package_suggestion.html.jinja @@ -0,0 +1,58 @@ +{# +SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + +Proxy web UI page that asks whether to enable a package that can be used with +current site. + +This file is part of Hydrilla&Haketilo. + +Copyright (C) 2022 Wojtek Kosior + +Dual licensed under +* GNU General Public License v3.0 or later and +* Creative Commons Attribution Share Alike 4.0 International. + +You can choose to use either of these licenses or both. + + +I, Wojtek Kosior, thereby promise not to sue for violation of this +file's licenses. Although I request that you do not make use this code +in a proprietary work, I am not going to enforce this in court. +#} +{% extends "base.html.jinja" %} + +{% block title %} + {{ _('web_ui.prompts.package_suggestion.title') }} +{% endblock %} + +{% block main %} + {% if file_installation_error is defined %} + {{ error_note(_('web_ui.err.file_installation_error')) }} + {% endif %} + + {% if repo_communication_error is defined %} + {{ error_note(_('web_ui.err.repo_communication_error')) }} + {% endif %} + + <h3> + {{ _('web_ui.prompts.package_suggestion.heading') }} + </h3> + + <p> + {{ + _('web_ui.prompts.package_suggestion.do_you_want_to_enable_package_{}') + .format(display_info.mapping_info.info.long_name) + }} + </p> + + {% set disable_text = _('web_ui.prompts.package_suggestion.disable_button') %} + {% set enable_text = _('web_ui.prompts.package_suggestion.enable_button') %} + + {{ + button_row([ + (['red-button'], disable_text, {'action': 'disable_mapping'}), + (['blue-button'], enable_text, {'action': 'enable_mapping'}) + ], {'mapping_ver_id': display_info.mapping_info.ref.id} + ) + }} +{% endblock %} diff --git a/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja b/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja index 448c451..2c695d0 100644 --- a/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/repos/show_single.html.jinja @@ -152,7 +152,8 @@ in a proprietary work, I am not going to enforce this in court. </p> {% set button_text = _('web_ui.repos.single.refresh_now_button') %} - {{ button_row([[['green-button'], button_text, 'refresh_repo']]) }} + {% set extra_fields = {'action': 'refresh_repo'} %} + {{ button_row([(['green-button'], button_text, extra_fields)]) }} </div> <div class="horizontal-separator"></div> @@ -171,6 +172,7 @@ in a proprietary work, I am not going to enforce this in court. <div class="horizontal-separator"></div> {% set button_text = _('web_ui.repos.single.remove_button') %} - {{ button_row([[['green-button'], button_text, 'remove_repo']]) }} + {% set extra_fields = {'action': 'remove_repo'} %} + {{ button_row([(['green-button'], button_text, extra_fields)]) }} {% endif %} {% endblock %} |