Dateien nach "/" hochladen
This commit is contained in:
1 parent
2e525989f7
commit
929c3f8c95
1 file changed
+121
-1
@@ -138,6 +138,68 @@ def is_public_target(url: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Rohreport lesbar aufbereiten: nach Severity gruppieren, Feldnamen
|
||||
# vereinheitlichen (SkillSpector nennt Detail-Felder je Version leicht anders).
|
||||
# --------------------------------------------------------------------------- #
|
||||
SEVERITY_ORDER = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]
|
||||
SEVERITY_LABELS_DE = {
|
||||
"CRITICAL": "Kritisch",
|
||||
"HIGH": "Hoch",
|
||||
"MEDIUM": "Mittel",
|
||||
"LOW": "Niedrig",
|
||||
"INFO": "Info",
|
||||
}
|
||||
|
||||
|
||||
def normalize_issues(raw_issues: list) -> dict:
|
||||
grouped: dict[str, list] = {}
|
||||
for issue in raw_issues or []:
|
||||
severity = str(issue.get("severity", "INFO")).upper()
|
||||
location = issue.get("location") or {}
|
||||
confidence = issue.get("confidence")
|
||||
if isinstance(confidence, (int, float)) and confidence <= 1:
|
||||
confidence_display = f"{round(confidence * 100)}%"
|
||||
else:
|
||||
confidence_display = confidence
|
||||
grouped.setdefault(severity, []).append(
|
||||
{
|
||||
"id": issue.get("id") or issue.get("rule_id") or "?",
|
||||
"category": issue.get("category") or issue.get("type") or "",
|
||||
"message": (
|
||||
issue.get("finding")
|
||||
or issue.get("message")
|
||||
or issue.get("description")
|
||||
or issue.get("title")
|
||||
or ""
|
||||
),
|
||||
"explanation": issue.get("explanation") or issue.get("rationale") or "",
|
||||
"file": location.get("file") or location.get("path") or "",
|
||||
"line": location.get("start_line") or location.get("line") or "",
|
||||
"confidence": confidence_display,
|
||||
}
|
||||
)
|
||||
ordered = {lvl: grouped[lvl] for lvl in SEVERITY_ORDER if lvl in grouped}
|
||||
for lvl, items in grouped.items():
|
||||
if lvl not in ordered:
|
||||
ordered[lvl] = items
|
||||
return ordered
|
||||
|
||||
|
||||
def normalize_components(raw_components: list) -> list:
|
||||
normalized = []
|
||||
for c in raw_components or []:
|
||||
normalized.append(
|
||||
{
|
||||
"file": c.get("path") or c.get("file") or c.get("name") or "-",
|
||||
"type": c.get("type") or c.get("kind") or "-",
|
||||
"lines": c.get("lines") or c.get("line_count") or "-",
|
||||
"executable": bool(c.get("executable")),
|
||||
}
|
||||
)
|
||||
return normalized
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Design im Stil von software.obraasch.de: dunkler Header, orange Akzente,
|
||||
# helle Cards.
|
||||
@@ -209,6 +271,19 @@ pre{
|
||||
padding:14px 16px;font-weight:600;
|
||||
}
|
||||
.notice{color:var(--ink-soft);font-size:.85em;margin-top:8px}
|
||||
.sev-heading{margin:0 0 14px;font-size:1.05em;font-weight:800;padding-bottom:8px;border-bottom:1px solid var(--border)}
|
||||
.sev-CRITICAL{color:#c62828}.sev-HIGH{color:#d9601a}.sev-MEDIUM{color:#b5720a}.sev-LOW{color:#5b6470}.sev-INFO{color:#5b6470}
|
||||
.issue{padding:14px 0;border-bottom:1px solid var(--border)}
|
||||
.issue:last-child{border-bottom:none;padding-bottom:0}
|
||||
.issue-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-size:.8em;color:var(--ink-soft);font-weight:700;text-transform:uppercase;letter-spacing:.3px}
|
||||
.issue-msg{margin:6px 0 4px;font-weight:600}
|
||||
.issue-loc{margin:0 0 4px;font-family:monospace;font-size:.85em;color:var(--ink-soft)}
|
||||
.issue-expl{margin:4px 0 0;font-size:.9em;color:var(--ink-soft)}
|
||||
.comp-table{width:100%;border-collapse:collapse;font-size:.88em}
|
||||
.comp-table th{text-align:left;color:var(--ink-soft);font-weight:700;padding:6px 8px;border-bottom:1px solid var(--border)}
|
||||
.comp-table td{padding:6px 8px;border-bottom:1px solid var(--border);font-family:monospace}
|
||||
details summary{cursor:pointer;font-weight:700;color:var(--ink-soft)}
|
||||
details pre{margin-top:14px}
|
||||
footer{
|
||||
max-width:760px;margin:0 auto;padding:0 24px 40px;color:#9aa2ab;font-size:.85em;
|
||||
}
|
||||
@@ -245,8 +320,49 @@ a{color:var(--orange)}
|
||||
<span class="score-num">{{ result.risk_assessment.score }}/100</span>
|
||||
<span class="badge {{ result.risk_assessment.recommendation }}">{{ result.risk_assessment.recommendation }}</span>
|
||||
</div>
|
||||
<pre>{{ result_json }}</pre>
|
||||
{% if not issues_by_severity %}
|
||||
<p class="notice">Keine Funde – das Ergebnis unten (Rohdaten) bestätigt das im Detail.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% for severity, items in issues_by_severity.items() %}
|
||||
<div class="card">
|
||||
<h3 class="sev-heading sev-{{ severity }}">{{ severity_labels.get(severity, severity) }} ({{ items|length }})</h3>
|
||||
{% for issue in items %}
|
||||
<div class="issue">
|
||||
<div class="issue-head">
|
||||
<span>{{ issue.category }}</span>
|
||||
{% if issue.confidence %}<span>Konfidenz: {{ issue.confidence }}</span>{% endif %}
|
||||
</div>
|
||||
<p class="issue-msg">{{ issue.message }}</p>
|
||||
{% if issue.file %}<p class="issue-loc">{{ issue.file }}{% if issue.line %}:{{ issue.line }}{% endif %}</p>{% endif %}
|
||||
{% if issue.explanation %}<p class="issue-expl">{{ issue.explanation }}</p>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if components %}
|
||||
<div class="card">
|
||||
<h3 class="sev-heading">Gescannte Komponenten ({{ components|length }})</h3>
|
||||
<table class="comp-table">
|
||||
<tr><th>Datei</th><th>Typ</th><th>Zeilen</th><th>Ausführbar</th></tr>
|
||||
{% for c in components %}
|
||||
<tr>
|
||||
<td>{{ c.file }}</td>
|
||||
<td>{{ c.type }}</td>
|
||||
<td>{{ c.lines }}</td>
|
||||
<td>{{ 'ja' if c.executable else 'nein' }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<details class="card">
|
||||
<summary>Rohdaten (vollständiges JSON)</summary>
|
||||
<pre>{{ result_json }}</pre>
|
||||
</details>
|
||||
{% elif error %}
|
||||
<div class="card">
|
||||
<p class="err">{{ error }}</p>
|
||||
@@ -329,10 +445,14 @@ def index():
|
||||
|
||||
if report_path.exists():
|
||||
result = json.loads(report_path.read_text())
|
||||
raw_issues = result.get("issues") or result.get("findings") or []
|
||||
return render_template_string(
|
||||
PAGE,
|
||||
allow_llm=ALLOW_LLM,
|
||||
result=result,
|
||||
issues_by_severity=normalize_issues(raw_issues),
|
||||
components=normalize_components(result.get("components", [])),
|
||||
severity_labels=SEVERITY_LABELS_DE,
|
||||
result_json=json.dumps(result, indent=2, ensure_ascii=False),
|
||||
error=None,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user