template refactor
This commit is contained in:
164
app/templates/report_body.html.j2
Normal file
164
app/templates/report_body.html.j2
Normal file
@@ -0,0 +1,164 @@
|
||||
{% extends "base_report.html.j2" %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{# ===== Title Card ===== #}
|
||||
<table role="presentation" class="section table-clean">
|
||||
<tr>
|
||||
<td class="card">
|
||||
<div class="title-xl">{{ title }}</div>
|
||||
<div class="meta muted">Generated: {{ generated }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{# ===== Summary Bar ===== #}
|
||||
<table role="presentation" class="section table-clean">
|
||||
<tr>
|
||||
<td class="card summary-row">
|
||||
Total hosts:
|
||||
<strong class="text-strong">{{ total_hosts }}</strong>
|
||||
Matching expected:
|
||||
<strong class="text-ok">{{ ok_hosts }}</strong>
|
||||
With issues:
|
||||
<strong class="text-issue">{{ hosts_with_issues|length }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% if not only_issues and ok_hosts == total_hosts and total_hosts > 0 %}
|
||||
<div class="note muted">All hosts matched expected ports.</div>
|
||||
{% endif %}
|
||||
|
||||
{% if only_issues and hosts_with_issues|length == 0 %}
|
||||
<div class="note muted">No hosts with issues found. ✅</div>
|
||||
{% endif %}
|
||||
|
||||
{# ===== Helpers ===== #}
|
||||
{% macro delta_row(label, ports) -%}
|
||||
<tr>
|
||||
<td colspan="5" class="delta-row">
|
||||
<strong>{{ label }}:</strong>
|
||||
<span class="muted">{{ fmt_ports(ports) }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
{%- endmacro %}
|
||||
|
||||
{# ================= 1) Issues (already sorted by IP in Python) ================= #}
|
||||
{% for hr in issues %}
|
||||
{% set ip_key = hr.ip %}
|
||||
{% set r = hr %}
|
||||
{% set host_row = host_results_by_ip.get(ip_key) %}
|
||||
{% set header_title = ip_key ~ ((' (' ~ host_row.host ~ ')') if host_row and host_row.host else '') %}
|
||||
|
||||
<table role="presentation" class="section table-clean table-ports">
|
||||
<tr>
|
||||
<td colspan="5" class="header">
|
||||
{{ header_title }} <span class="badge issue">ISSUES</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{ delta_row('Unexpected TCP open ports', r.unexpected_tcp) }}
|
||||
{{ delta_row('Expected TCP ports not seen', r.missing_tcp) }}
|
||||
{{ delta_row('Unexpected UDP open ports', r.unexpected_udp) }}
|
||||
{{ delta_row('Expected UDP ports not seen', r.missing_udp) }}
|
||||
|
||||
<tr>
|
||||
<td colspan="5" class="pad-s">
|
||||
<div class="subhead">Discovered Ports</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="th">Protocol</td>
|
||||
<td class="th">Port</td>
|
||||
<td class="th">State</td>
|
||||
<td class="th">Service</td>
|
||||
<td class="th">Expectation</td>
|
||||
</tr>
|
||||
|
||||
{% if host_row and host_row.ports %}
|
||||
{% set ns = namespace(visible_rows=0) %}
|
||||
|
||||
{% for p in host_row.ports %}
|
||||
{% set proto = (p.protocol|string|lower) %}
|
||||
{% set state = (p.state|string|lower) %}
|
||||
|
||||
{# hide closed UDP lines to reduce noise #}
|
||||
{% set skip_row = (proto == 'udp' and ('closed' in state)) %}
|
||||
|
||||
{% set is_tcp = (proto == 'tcp') %}
|
||||
{% set is_udp = (proto == 'udp') %}
|
||||
{% set is_open = ('open' in state) %}
|
||||
{% set is_issue = (is_open and (
|
||||
(is_tcp and (p.port in (r.unexpected_tcp or []))) or
|
||||
(is_udp and (p.port in (r.unexpected_udp or [])))
|
||||
)) %}
|
||||
|
||||
{% if is_issue %}
|
||||
{% set expectation_badge %}<span class="badge issue">Issue</span>{% endset %}
|
||||
{% elif is_open %}
|
||||
{% set expectation_badge %}<span class="badge ok">Expected</span>{% endset %}
|
||||
{% else %}
|
||||
{% set expectation_badge %}<span class="dash">—</span>{% endset %}
|
||||
{% endif %}
|
||||
|
||||
{% if not skip_row %}
|
||||
{% set ns.visible_rows = ns.visible_rows + 1 %}
|
||||
<tr>
|
||||
<td class="td proto">{{ pill_proto(p.protocol) | safe }}</td>
|
||||
<td class="td num">{{ p.port }}</td>
|
||||
<td class="td state">{{ pill_state(p.state) | safe }}</td>
|
||||
<td class="td svc">{{ p.service or '-' }}</td>
|
||||
<td class="td expect">{{ expectation_badge | safe }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if ns.visible_rows == 0 %}
|
||||
<tr>
|
||||
<td colspan="5" class="td muted">
|
||||
No per-port details to display after filtering closed UDP results.
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="5" class="td muted">
|
||||
No per-port details available for this host.
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endfor %}
|
||||
|
||||
{# ================= 2) Expected / OK hosts (only if not only_issues) ================= #}
|
||||
{% if not only_issues %}
|
||||
{% for hr in expected %}
|
||||
{% set ip_key = hr.ip %}
|
||||
{% set r = hr %}
|
||||
{% set host_row = host_results_by_ip.get(ip_key) %}
|
||||
{% set header_title = ip_key ~ ((' (' ~ host_row.host ~ ')') if host_row and host_row.host else '') %}
|
||||
|
||||
<table role="presentation" class="section table-clean">
|
||||
<tr>
|
||||
<td colspan="5" class="header">
|
||||
{{ header_title }} <span class="badge ok">OK</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="5" class="pad-s">
|
||||
<span class="badge ok">OK</span>
|
||||
<span class="muted">Matches expected ports.</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<div class="footer muted">
|
||||
Report generated by mass-scan-v2 • {{ generated }}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user