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):
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
def manage():
rules = [rule|{'index': index} for index, rule in enumerate(db.load('rules'))
if can_toggle(flask_login.current_user, rule)]
return flask.render_template('rules/manage.html', rules=rules)
@blueprint.route('/toggle/<int:index>/<enable>')
@flask_login.login_required
def toggle(index, enable):
try:
with db.locked():
rules = db.read('rules')
if not can_toggle(flask_login.current_user, rules[index]):
with db.locked():
rules = db.read('rules')
allowed = set(rule['name'] for rule in rules if can_toggle(flask_login.current_user, rule))
if flask.request.method == 'POST':
# check that all posted rules are allowed for this user
posted = set(flask.request.form.getlist('rule'))
if posted - allowed:
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)
system.run(system.save_config)
return flask.redirect(flask.url_for('rules.manage'))
except IndexError as e:
return flask.Response(f'invalid rule: {index}', status=400, mimetype='text/plain')
system.run(system.save_config)
return flask.redirect(flask.url_for('rules.manage'))
return flask.render_template('rules/manage.html', rules=[rule for rule in rules if rule['name'] in allowed])

View file

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