lib/openagents_web/controllers/repository_json.ex

58e6347eeb72 · 2 KB

defmodule OpenAgentsWeb.RepositoryJSON do
  @moduledoc "JSON projections for hosted repositories."

  alias OpenAgents.Repositories.Repository

  def repository(%Repository{} = repository, permissions, base_url) do
    owner = repository.namespace.slug

    %{
      "id" => repository.id,
      "name" => repository.name,
      "full_name" => owner <> "/" <> repository.name,
      "owner" => %{
        "id" => repository.namespace.provider_account_id,
        "login" => owner,
        "type" => if(repository.namespace.kind == "user", do: "User", else: "Organization")
      },
      "private" => repository.visibility == "private",
      "visibility" => repository.visibility,
      "description" => repository.description,
      "default_branch" => repository.default_branch,
      "pull_requests_enabled" => repository.pull_requests_enabled,
      "lifecycle_state" => repository.lifecycle_state,
      "provision_error_code" => repository.provision_error_code,
      "clone_url" => base_url <> "/#{owner}/#{repository.name}.git",
      "html_url" => base_url <> "/#{owner}/#{repository.name}",
      "permissions" => permissions,
      "mirror" => Repository.mirror?(repository),
      "upstream" => upstream(repository),
      "created_at" => DateTime.to_iso8601(repository.inserted_at),
      "updated_at" => DateTime.to_iso8601(repository.updated_at)
    }
  end

  # A mirror names its upstream in the response body, not only in the
  # database. `"mirror" => false` and `"upstream" => nil` are published for
  # every owned repository too, so a reader learns the distinction exists
  # from any repository rather than only from a mirror.
  #
  # `"license"` here is what the upstream published at the moment the copy was
  # taken, or the literal `"none"`. It is a record of the upstream's terms,
  # never a claim about the copy.
  defp upstream(%Repository{upstream_url: nil}), do: nil

  defp upstream(%Repository{} = repository) do
    %{
      "url" => repository.upstream_url,
      "license" => repository.upstream_license,
      "direction" => "one_way",
      "accepts_pushes" => false
    }
  end

  # `"push"` is a claim about what the Git plane will accept, so a mirror
  # reports `false` for every role. An owner who reads `true` here and then
  # has the push refused has been told two different things by one system.
  def permissions(repository, role) do
    %{
      "admin" => role in ~w(owner maintainer),
      "push" => role in ~w(owner maintainer contributor) and not Repository.mirror?(repository),
      "pull" => repository.visibility == "public" or not is_nil(role)
    }
  end
end