Files
FabledSteward/steward/templates/ansible/inventory/groups.html
T
bvandeusenandClaude Opus 5.5 f47fc23265 fix(ui): delete prompts use data-confirm, so a quote in a name no longer runs script (#5099)
#5099 "A name containing a quote runs script when an admin clicks Delete".
Inline handlers like onclick="return confirm('Delete {{ rule.name }}?')" are
HTML-decoded before the JavaScript is parsed, so autoescaping did not stop a
name such as  x');fetch(…);//  from running.

- Every prompt (22 handlers, plus the docker prune and token revoke ones)
  is now data-confirm="…", read through dataset by one submit listener in
  base.html; nothing rendered is parsed as JavaScript.
- The remaining inline handlers take integers only (|int), and the time
  range buttons pass this.dataset.range.
- tests/test_inline_handlers.py fails on any {{ }} in an inline handler that
  is not |int, with a self-test; tests/_templates.py is the one template
  walker the template guards now share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:30:13 -04:00

53 lines
2.0 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% from "_macros.html" import crumbs %}
{% block title %}Inventory Groups — Steward{% endblock %}
{% block breadcrumb %}{{ crumbs([("Ansible", "/ansible/"), ("Inventory", "/ansible/inventory/targets"), ("Groups", "")]) }}{% endblock %}
{% block content %}
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;">
<h1 class="page-title" style="margin-bottom:0;">Inventory Groups</h1>
<div style="display:flex;gap:0.5rem;">
<a href="/ansible/inventory/targets" class="btn btn-ghost btn-sm">Targets</a>
</div>
</div>
<div class="card" style="margin-bottom:1.5rem;">
<h3 class="section-title">New Group</h3>
<form method="post" action="/ansible/inventory/groups" style="display:flex;gap:0.75rem;align-items:flex-end;">{{ csrf_field() }}
<div class="form-group" style="flex:1;margin:0;">
<label>Name</label>
<input type="text" name="name" placeholder="webservers" required>
</div>
<button type="submit" class="btn">Create</button>
</form>
</div>
{% if not groups %}
<div class="card">
<p style="color:var(--text-muted);">No groups yet. Create one above.</p>
</div>
{% else %}
<div class="card-flush">
<table class="table">
<thead>
<tr><th>Name</th><th>Members</th><th></th></tr>
</thead>
<tbody>
{% for grp in groups %}
<tr>
<td><strong>{{ grp.name }}</strong></td>
<td style="color:var(--text-muted);font-size:0.9rem;">{{ grp.targets | length }}</td>
<td class="td-actions">
<a href="/ansible/inventory/groups/{{ grp.id }}" class="btn btn-sm btn-ghost">Edit</a>
<form method="post" action="/ansible/inventory/groups/{{ grp.id }}/delete" style="display:inline;">{{ csrf_field() }}
<button type="submit" class="btn btn-sm btn-danger"
data-confirm="Delete group {{ grp.name }}?">×</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% endblock %}