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,152 @@
defmodule TarakanWeb.API.RepositoryController do
@moduledoc """
Discovery and registration of public repositories for scanning clients.
`GET` lists reviewable repositories (`status=unscanned` for the work queue).
`POST` registers a public GitHub repository by URL or `owner/name` so mass
importers (awesome lists, OSINT harvests) can feed the registry.
"""
use TarakanWeb, :controller
alias Tarakan.Repositories
def index(conn, params) do
opts =
[
status: params["status"],
limit: parse_limit(params["limit"]),
min_stars: parse_min_stars(params["min_stars"]),
language: parse_language(params["language"] || params["lang"])
]
|> Enum.reject(fn {_k, v} -> is_nil(v) or v == "" end)
repositories = Repositories.list_reviewable_repositories(opts)
json(conn, %{repositories: Enum.map(repositories, &repository_json/1)})
end
@doc """
Registers a public GitHub repository.
Body: `{"url": "owner/name"}` or `{"url": "https://github.com/owner/name"}`.
Idempotent: an already-registered repository is returned as 200.
"""
def create(conn, params) do
url =
params
|> Map.get("url")
|> Kernel.||(Map.get(params, "repository"))
|> case do
value when is_binary(value) -> String.trim(value)
_ -> ""
end
if url == "" do
conn
|> put_status(:unprocessable_entity)
|> json(%{errors: %{url: ["is required"]}})
else
case Repositories.register_github_repository(url, conn.assigns.current_scope) do
{:ok, repository} ->
# Idempotent: 200 whether newly inserted or already present.
json(conn, %{repository: repository_json(repository)})
{:error, reason} ->
registration_error(conn, reason)
end
end
end
defp registration_error(conn, :invalid_github_repository) do
conn
|> put_status(:unprocessable_entity)
|> json(%{error: "url must be a public GitHub owner/name or repository URL"})
end
defp registration_error(conn, reason) when reason in [:not_found, :not_public] do
conn
|> put_status(:not_found)
|> json(%{error: "repository was not found or is not public"})
end
defp registration_error(conn, :registration_limit) do
conn
|> put_status(:too_many_requests)
|> json(%{error: "daily repository registration limit reached"})
end
defp registration_error(conn, reason) when reason in [:rate_limited, :request_limited] do
conn
|> put_status(:too_many_requests)
|> json(%{error: "too many registration requests; try again shortly"})
end
defp registration_error(conn, :unavailable) do
conn
|> put_status(:service_unavailable)
|> json(%{error: "could not reach GitHub to verify the repository"})
end
defp registration_error(conn, :unauthorized) do
conn
|> put_status(:forbidden)
|> json(%{error: "this credential cannot register repositories"})
end
defp registration_error(conn, _reason) do
conn
|> put_status(:unprocessable_entity)
|> json(%{error: "repository could not be registered"})
end
defp parse_limit(nil), do: 100
defp parse_limit(value) when is_binary(value) do
case Integer.parse(value) do
{limit, ""} when limit > 0 -> min(limit, 500)
_other -> 100
end
end
defp parse_limit(_), do: 100
defp parse_min_stars(nil), do: nil
defp parse_min_stars(value) do
case Integer.parse(to_string(value)) do
{n, _} when n > 0 -> n
_ -> nil
end
end
defp parse_language(nil), do: nil
defp parse_language(value) when is_binary(value) do
case String.trim(value) do
"" -> nil
lang -> lang
end
end
defp parse_language(_), do: nil
defp repository_json(repository) do
status = Map.get(repository, :status) || repository.listing_status
%{
host: repository.host,
owner: repository.owner,
name: repository.name,
status: status,
listing_status: repository.listing_status,
default_branch: repository.default_branch,
primary_language: repository.primary_language,
stars_count: repository.stars_count,
scan_count: repository.scan_count,
last_scanned_at: repository.last_scanned_at,
registered_at: repository.inserted_at,
record_url:
TarakanWeb.Endpoint.url() <> TarakanWeb.RepositoryPaths.repository_path(repository)
}
end
end