Initial commit on Forgejo
Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
This commit is contained in:
commit
af6077b9c3
455 changed files with 78366 additions and 0 deletions
152
lib/tarakan_web/controllers/api/repository_controller.ex
Normal file
152
lib/tarakan_web/controllers/api/repository_controller.ex
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue