Improve rule management page

Address rules by name instead of index. Still problematic if the rules
are changed while someone is managing them, but with names it’s
more likely to just not work instead of enabling or disabling the
wrong rule.

Also prevent bringing down the whole network with a single click.
This commit is contained in:
Timotej Lazar 2024-05-29 11:10:31 +02:00
parent 0e9d1ce6f0
commit 25ee4e8a44
2 changed files with 28 additions and 23 deletions

View file

@ -53,24 +53,24 @@ def edit(index):
def can_toggle(user, rule): def can_toggle(user, rule):
return user.is_admin or not user.groups.isdisjoint(rule.get('managers', ())) return user.is_admin or not user.groups.isdisjoint(rule.get('managers', ()))
@blueprint.route('/manage') @blueprint.route('/manage', methods=('GET', 'POST'))
@flask_login.login_required @flask_login.login_required
def manage(): def manage():
rules = [rule|{'index': index} for index, rule in enumerate(db.load('rules')) with db.locked():
if can_toggle(flask_login.current_user, rule)] rules = db.read('rules')
return flask.render_template('rules/manage.html', rules=rules) allowed = set(rule['name'] for rule in rules if can_toggle(flask_login.current_user, rule))
if flask.request.method == 'POST':
@blueprint.route('/toggle/<int:index>/<enable>') # check that all posted rules are allowed for this user
@flask_login.login_required posted = set(flask.request.form.getlist('rule'))
def toggle(index, enable): if posted - allowed:
try:
with db.locked():
rules = db.read('rules')
if not can_toggle(flask_login.current_user, rules[index]):
return flask.Response('forbidden', status=403, mimetype='text/plain') return flask.Response('forbidden', status=403, mimetype='text/plain')
rules[index]['enabled'] = (enable == 'true')
# set status for posted rules
enabled = set(flask.request.form.getlist('enabled'))
for rule in rules:
if rule['name'] in posted:
rule['enabled'] = (rule['name'] in enabled)
db.write('rules', rules) db.write('rules', rules)
system.run(system.save_config) system.run(system.save_config)
return flask.redirect(flask.url_for('rules.manage')) return flask.redirect(flask.url_for('rules.manage'))
except IndexError as e: return flask.render_template('rules/manage.html', rules=[rule for rule in rules if rule['name'] in allowed])
return flask.Response(f'invalid rule: {index}', status=400, mimetype='text/plain')

View file

@ -3,7 +3,10 @@
{% block header %} {% block header %}
<style> <style>
pre { pre {
margin: 0; margin: 0.5em 2em;
}
summary {
list-style: none;
} }
</style> </style>
{% endblock %} {% endblock %}
@ -12,17 +15,19 @@ pre {
<p> <p>
Tu lahko vklopite in izklopite posamezna pravila za požarni zid. Tu lahko vklopite in izklopite posamezna pravila za požarni zid.
<form id="request" method="POST">
{% for rule in rules %} {% for rule in rules %}
<details> <details>
<summary> <summary>
{% if rule.enabled %} <input name="rule" type="hidden" value="{{ rule.name }}" />
<font color="green"></font> {{ rule.name }} <a href="{{ url_for('rules.toggle', index=rule.index, enable='false') }}">izklopi</a> <input name="enabled" type="checkbox" value="{{ rule.name }}" autocomplete="off"{% if rule.enabled %} checked{% endif %} />
{% else %} {{ rule.name }}
<font color="red"></font> {{ rule.name }} <a href="{{ url_for('rules.toggle', index=rule.index, enable='true') }}">vklopi</a>
{% endif %}
</summary> </summary>
<pre><code>{{ rule.text }}</code></pre> <pre><code>{{ rule.text }}</code></pre>
</details> </details>
{% endfor %} {% endfor %}
<p>
<button>Potrdi</button>
</form>
{% endblock %} {% endblock %}