defmodule TarakanWeb.API.FindingController do @moduledoc """ Public read access to disclosed findings. Anonymous reads pass through the same disclosure policy as the finding page (`Scans.get_finding/2` with a nil scope): restricted or summary-only reviews answer 404, never a redacted body. """ use TarakanWeb, :controller alias Tarakan.Scans def show(conn, %{"public_id" => public_id}) do case Scans.get_finding(nil, public_id) do {:ok, {scan, finding}} -> json(conn, %{finding: finding_json(scan, finding)}) {:error, :not_found} -> conn |> put_status(:not_found) |> json(%{error: "finding was not found or is not public"}) end end defp finding_json(scan, finding) do canonical = finding.canonical_finding repository = scan.repository %{ public_id: finding.public_id, title: (canonical && canonical.title) || finding.title, severity: finding.severity, status: (canonical && canonical.status) || "open", description: (canonical && canonical.description) || finding.description, reproduction_steps: canonical && canonical.reproduction_steps, affected_versions: canonical && canonical.affected_versions, cwe_id: canonical && canonical.cwe_id, cve_id: canonical && canonical.cve_id, file_path: finding.file_path, line_start: finding.line_start, line_end: finding.line_end, first_seen_commit_sha: canonical && canonical.first_seen_commit_sha, last_seen_commit_sha: canonical && canonical.last_seen_commit_sha, verified_at: canonical && canonical.verified_at, vendor_notified_at: canonical && canonical.vendor_notified_at, counters: %{ detections_count: (canonical && canonical.detections_count) || 0, distinct_submitters_count: (canonical && canonical.distinct_submitters_count) || 0, distinct_models_count: (canonical && canonical.distinct_models_count) || 0, confirmations_count: (canonical && canonical.confirmations_count) || 0, disputes_count: (canonical && canonical.disputes_count) || 0 }, repository: %{ host: repository.host, owner: repository.owner, name: repository.name }, record_url: TarakanWeb.Endpoint.url() <> ~p"/findings/#{finding.public_id}", inserted_at: finding.inserted_at } end end