Current section

Files

Jump to
sobelow lib sobelow finding_log.ex
Raw

lib/sobelow/finding_log.ex

defmodule Sobelow.FindingLog do
use GenServer
@json_template """
{
"sobelow_version": "<%= @version %>",
"total_findings": "<%= @total_findings %>",
"findings": {<%= for {confidence, items} <- @findings do %>
"<%= confidence %>": [<% last = List.last(items) %><%= for item <- items do %>
{<% {lk, _} = List.last(item) %><%= for {k, v} <- item do %>
"<%= k %>": "<%= v %>"<%= if lk != k do %>,<% end %><% end %>
}<%= if last != item do %>,<% end %><% end %>
]<%= if confidence != :low_confidence do %>,<% end %><% end %>
}
}
"""
def start_link() do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
def add(finding, severity) do
GenServer.cast(__MODULE__, {:add, finding, severity})
end
def log() do
GenServer.call(__MODULE__, :log)
end
def json(vsn) do
%{high: highs, medium: meds, low: lows} = log()
EEx.eval_string(
@json_template,
assigns: [
findings: [high_confidence: highs, medium_confidence: meds, low_confidence: lows],
total_findings: length(highs) + length(meds) + length(lows),
version: vsn
]
)
end
def quiet() do
total = total(log())
findings = if total > 1, do: "findings", else: "finding"
if total > 0 do
"Sobelow: #{total} #{findings} found. Run again without --quiet to review findings."
end
end
defp total(%{high: highs, medium: meds, low: lows}) do
length(highs) + length(meds) + length(lows)
end
def init(:ok) do
{:ok, %{:high => [], :medium => [], :low => []}}
end
def handle_cast({:add, finding, severity}, findings) do
{:noreply, Map.update!(findings, severity, &[finding | &1])}
end
def handle_call(:log, _from, findings) do
{:reply, findings, findings}
end
end