Initial commit on Forgejo
All checks were successful
CI and deploy / Test (push) Successful in 4m52s
CI and deploy / Deploy production (push) Successful in 23s

Fresh repository history for elektrine/tarakan hosted at
https://git.elektrine.com/elektrine/tarakan.
This commit is contained in:
Maxfield Luke 2026-07-29 04:43:40 -04:00
commit af6077b9c3
455 changed files with 78366 additions and 0 deletions

View file

@ -0,0 +1,75 @@
defmodule TarakanWeb.BadgeController do
@moduledoc """
Embeddable SVG badges for a repository's security posture.
Served without authentication so a README on any host can render one, and
cached briefly so an embedded badge cannot be used to hammer the database.
The SVG is self-contained (no external fonts or images) because most hosts
proxy and sanitize badge images.
"""
use TarakanWeb, :controller
alias Tarakan.Repositories
alias Tarakan.SecurityPosture
@cache_seconds 900
def show(conn, %{"host" => host, "owner" => owner, "name" => name}) do
render_badge(conn, Repositories.get_repository(host, owner, name))
end
def show(conn, %{"owner" => owner, "name" => name}) do
render_badge(conn, Repositories.get_repository_by_slug(owner, name))
end
defp render_badge(conn, repository) do
badge =
case repository do
%{listing_status: "listed"} = repository ->
SecurityPosture.cached_badge(repository)
_unlisted_or_missing ->
%{label: "security", message: "not listed", color: "#5a6a72"}
end
conn
|> put_resp_content_type("image/svg+xml")
|> put_resp_header("cache-control", "public, max-age=#{@cache_seconds}")
|> send_resp(200, svg(badge))
end
# Flat two-part badge. Widths are estimated from character count because the
# SVG carries no font metrics; 6.6px per character matches the 11px
# sans-serif stack closely enough for the shape to stay tight.
defp svg(%{label: label, message: message, color: color}) do
label_width = text_width(label)
message_width = text_width(message)
total = label_width + message_width
"""
<svg xmlns="http://www.w3.org/2000/svg" width="#{total}" height="20" role="img" aria-label="#{escape(label)}: #{escape(message)}">
<title>#{escape(label)}: #{escape(message)}</title>
<g shape-rendering="crispEdges">
<rect width="#{label_width}" height="20" fill="#1c1f22"/>
<rect x="#{label_width}" width="#{message_width}" height="20" fill="#{escape(color)}"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="Verdana,DejaVu Sans,Geneva,sans-serif" font-size="11">
<text x="#{div(label_width, 2)}" y="14">#{escape(label)}</text>
<text x="#{label_width + div(message_width, 2)}" y="14">#{escape(message)}</text>
</g>
</svg>
"""
end
defp text_width(text), do: round(String.length(text) * 6.6) + 12
defp escape(value) do
value
|> to_string()
|> String.replace("&", "&amp;")
|> String.replace("<", "&lt;")
|> String.replace(">", "&gt;")
|> String.replace("\"", "&quot;")
end
end