diff options
Diffstat (limited to 'src/hydrilla/proxy/web_ui')
-rw-r--r-- | src/hydrilla/proxy/web_ui/root.py | 3 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/rules.py | 111 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/base.html.jinja | 1 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/rules/add.html.jinja | 64 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/rules/index.html.jinja | 61 | ||||
-rw-r--r-- | src/hydrilla/proxy/web_ui/templates/rules/show_single.html.jinja | 106 |
6 files changed, 345 insertions, 1 deletions
diff --git a/src/hydrilla/proxy/web_ui/root.py b/src/hydrilla/proxy/web_ui/root.py index 855345e..763abab 100644 --- a/src/hydrilla/proxy/web_ui/root.py +++ b/src/hydrilla/proxy/web_ui/root.py @@ -45,6 +45,7 @@ from ... import item_infos from .. import state as st from .. import http_messages from . import options +from . import rules from . import repos from . import items from . import prompts @@ -94,7 +95,7 @@ class WebUIAppImpl(_app.WebUIApp): self.before_request(authenticate_by_referrer) - for blueprint in [repos.bp, items.bp, prompts.bp, options.bp]: + for blueprint in [rules.bp, 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/rules.py b/src/hydrilla/proxy/web_ui/rules.py new file mode 100644 index 0000000..79d0b99 --- /dev/null +++ b/src/hydrilla/proxy/web_ui/rules.py @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Proxy web UI script blocking rule management. +# +# 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('rules', __package__) + +@bp.route('/rules/add', methods=['GET']) +def add_rule(errors: t.Mapping[str, bool] = {}) -> werkzeug.Response: + html = flask.render_template('rules/add.html.jinja', **errors) + return flask.make_response(html, 200) + +@bp.route('/rules/add', methods=['POST']) +def add_rule_post() -> werkzeug.Response: + form_data = flask.request.form + + try: + new_rule_ref = _app.get_haketilo_state().rule_store().add( + pattern = form_data['pattern'], + allow = form_data['allow'] == 'true' + ) + except st.RulePatternInvalid: + return add_rule({'rule_pattern_invalid': True}) + + return flask.redirect(flask.url_for('.show_rule', rule_id=new_rule_ref.id)) + +@bp.route('/rules', methods=['GET']) +def rules(errors: t.Mapping[str, bool] = {}) -> werkzeug.Response: + store = _app.get_haketilo_state().rule_store() + + html = flask.render_template( + 'rules/index.html.jinja', + display_infos = store.get_display_infos(), + **errors + ) + return flask.make_response(html, 200) + +@bp.route('/rules/view/<string:rule_id>') +def show_rule(rule_id: str, errors: t.Mapping[str, bool] = {}) \ + -> werkzeug.Response: + try: + store = _app.get_haketilo_state().rule_store() + display_info = store.get(rule_id).get_display_info() + + html = flask.render_template( + 'rules/show_single.html.jinja', + display_info = display_info, + **errors + ) + return flask.make_response(html, 200) + except st.MissingItemError: + flask.abort(404) + +@bp.route('/rules/view/<string:rule_id>', methods=['POST']) +def alter_rule(rule_id: str) -> werkzeug.Response: + form_data = flask.request.form + action = form_data['action'] + + try: + rule_ref = _app.get_haketilo_state().rule_store().get(rule_id) + + if action == 'remove_rule': + rule_ref.remove() + return flask.redirect(flask.url_for('.rules')) + elif action == 'update_rule_data': + allow_param = form_data.get('allow') + rule_ref.update( + pattern = form_data.get('pattern'), + allow = None if allow_param is None else allow_param == 'true' + ) + else: + raise ValueError() + except st.RulePatternInvalid: + return show_rule(rule_id, {'rule_pattern_invalid': True}) + except st.MissingItemError: + flask.abort(404) + + return flask.redirect(flask.url_for('.show_rule', rule_id=rule_id)) diff --git a/src/hydrilla/proxy/web_ui/templates/base.html.jinja b/src/hydrilla/proxy/web_ui/templates/base.html.jinja index 9808c16..5bdb837 100644 --- a/src/hydrilla/proxy/web_ui/templates/base.html.jinja +++ b/src/hydrilla/proxy/web_ui/templates/base.html.jinja @@ -238,6 +238,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')), + ('rules.rules', _('web_ui.base.nav.rules')), ('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/rules/add.html.jinja b/src/hydrilla/proxy/web_ui/templates/rules/add.html.jinja new file mode 100644 index 0000000..ab21834 --- /dev/null +++ b/src/hydrilla/proxy/web_ui/templates/rules/add.html.jinja @@ -0,0 +1,64 @@ +{# +SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + +Proxy web UI script blocking/allowing rule creation 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.rules.add.title') }} {% endblock %} + +{% block main %} + <h3>{{ _('web_ui.rules.add.heading') }}</h3> + <form method="POST"> + {% if rule_pattern_invalid is defined %} + {{ error_note(_('web_ui.err.rule_pattern_invalid')) }} + {% endif %} + + <label for="pattern_field" class="block-with-bottom-margin"> + {{ _('web_ui.rules.add.pattern_field_label') }} + </label> + + <div class="flex-row"> + <input id="pattern_field" name="pattern" required=""> + </div> + + <div class="horizontal-separator"></div> + + <label class="block-with-bottom-margin"> + {{ _('web_ui.rules.add.block_or_allow_label') }} + </label> + + <div class="block-with-bottom-margin"> + <input id="block_box" name="allow" type="radio" value="false" checked=""> + <label for="block_box"> {{ _('web_ui.rules.add.block_label') }} </label> + </div> + + <div class="block-with-bottom-margin"> + <input id="allow_box" name="allow" type="radio" value="true"> + <label for="allow_box"> {{ _('web_ui.rules.add.allow_label') }} </label> + </div> + + <div class="horizontal-separator"></div> + + <div class="flex-row block-with-bottom-margin"> + <button class="green-button"> + {{ _('web_ui.rules.add.submit_button') }} + </button> + </div> + </form> +{% endblock %} diff --git a/src/hydrilla/proxy/web_ui/templates/rules/index.html.jinja b/src/hydrilla/proxy/web_ui/templates/rules/index.html.jinja new file mode 100644 index 0000000..5f290e0 --- /dev/null +++ b/src/hydrilla/proxy/web_ui/templates/rules/index.html.jinja @@ -0,0 +1,61 @@ +{# +SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + +Proxy web UI script allowing/blocking rule list 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.rules.title') }}{% endblock %} + +{% block style %} + {{ super() }} + + {% include 'include/item_list_style.css.jinja' %} +{% endblock %} + +{% block main %} + <h3>{{ _('web_ui.rules.heading') }}</h3> + + <a href="{{ url_for('.add_rule') }}" + class="green-button block-with-bottom-margin"> + {{ _('web_ui.rules.add_rule_button') }} + </a> + + <div class="horizontal-separator"></div> + + <h4>{{ _('web_ui.rules.rule_list_heading') }}</h4> + + <ul id="item_list"> + {% for info in display_infos %} + + {% if info.allow_scripts %} + {% set entry_classes = ['entry-line-red'] %} + {% else %} + {% set entry_classes = ['entry-line-blue'] %} + {% endif %} + + <li class="{{ entry_classes|join(' ') }}"> + <a href="{{ url_for('.show_rule', rule_id=info.ref.id) }}"> + <div> + {{ info.pattern }} + </div> + </a> + </li> + {% endfor %} + </ul> +{% endblock %} diff --git a/src/hydrilla/proxy/web_ui/templates/rules/show_single.html.jinja b/src/hydrilla/proxy/web_ui/templates/rules/show_single.html.jinja new file mode 100644 index 0000000..ad0c19c --- /dev/null +++ b/src/hydrilla/proxy/web_ui/templates/rules/show_single.html.jinja @@ -0,0 +1,106 @@ +{# +SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0 + +Proxy web UI script allowing/blocking rule modification 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.rules.single.title') }} {% endblock %} + +{% block style %} + {{ super() }} + + {% include 'include/checkbox_tricks_style.css.jinja' %} +{% endblock %} + +{% block main %} + <h3> + {% if display_info.allow_scripts %} + {{ _('web_ui.rules.single.heading.allow') }} + {% else %} + {{ _('web_ui.rules.single.heading.block') }} + {% endif %} + </h3> + + <p> + {{ _('web_ui.rules.single.pattern_is_{}').format(display_info.pattern) }} + </p> + + {% if rule_pattern_invalid is defined %} + {% set checked_attr = '' %} + {% else %} + {% set checked_attr = 'checked=""' %} + {% endif %} + <input id="hide_pattern_edit_form" type="checkbox" + class="chbx-tricks-show-hide" {{ checked_attr }}> + <label for="hide_pattern_edit_form" + class="green-button block-with-bottom-margin"> + {{ _('web_ui.rules.single.update_pattern_button') }} + </label> + + <form method="POST"> + <input type="hidden" name="action" value="update_rule_data"> + + {% if rule_pattern_invalid is defined %} + {{ error_note(_('web_ui.err.rule_pattern_invalid')) }} + {% endif %} + + <div class="flex-row"> + <input name="pattern" value="{{ display_info.pattern }}" required=""> + </div> + + <div class="flex-row"> + <button class="green-button button-bordering-right"> + {{ _('web_ui.rules.single.commit_update_pattern_button') }} + </button> + <div class="button-row-separator"></div> + <label for="hide_pattern_edit_form" + class="green-button button-bordering-left"> + {{ _('web_ui.rules.single.abort_update_pattern_button') }} + </label> + </div> + </form> + + <div class="horizontal-separator"></div> + + {% set allow_but_classes = ['red-button'] %} + {% set block_but_classes = ['blue-button'] %} + + {% set allow_text = _('web_ui.rules.single.allow_button') %} + {% set block_text = _('web_ui.rules.single.block_button') %} + + {% if display_info.allow_scripts %} + {% do allow_but_classes.append('disabled-button') %} + {% else %} + {% do block_but_classes.append('disabled-button') %} + {% endif %} + + {{ + button_row([ + (allow_but_classes, allow_text, {'allow': 'true'}), + (block_but_classes, block_text, {'allow': 'false'}) + ], {'action': 'update_rule_data'} + ) + }} + + <div class="horizontal-separator"></div> + + {% set button_text = _('web_ui.rules.single.remove_button') %} + {% set extra_fields = {'action': 'remove_rule'} %} + {{ button_row([(['green-button'], button_text, extra_fields)]) }} +{% endblock %} |