defmodule GitGudWeb.Api.Mobile.LabelController do
@moduledoc """
A repository's labels: the ones a pull request can be given.
The list is `Labels.list_labels/1` — the repository's own labels and
those it inherits from its organization, minus any it opted out of —
so it's exactly the set the pull request page offers. Labels are
attached to a pull request through `PullRequestController`.
Creating one makes a repository label, as the repository's labels page
does. That's repository configuration, so it takes a repository admin
(`RepoLive.Header.admin?/2`, the rule behind the page's admin
controls); organization labels are managed on the organization.
"""
use GitGudWeb, :controller
import GitGudWeb.Api.Mobile.Helpers
alias GitGud.Labels
alias GitGudWeb.Api.Mobile.Auth
alias GitGudWeb.Api.Mobile.JSON
# A neutral slate, for a label created without a colour.
@default_color "#64748b"
def index(conn, %{"owner" => owner, "name" => name}) do
with {:ok, user} <- Auth.require_scope(conn, "pulls:read"),
{:ok, repo} <- fetch_repo(conn, user, owner, name) do
json(conn, %{"labels" => Enum.map(Labels.list_labels(repo), &JSON.repo_label/1)})
else
{:error, conn} -> conn
end
end
@doc """
Create a repository label: `name`, and optionally `color` (`#RRGGBB`)
and `description`. A name the repository can already pick — its own
or inherited — is refused rather than shadowed.
"""
def create(conn, %{"owner" => owner, "name" => name} = params) do
with {:ok, user} <- Auth.require_scope(conn, "pulls:write"),
{:ok, repo} <- fetch_repo(conn, user, owner, name),
:ok <- authorize_admin(conn, user, repo, owner, name),
{:ok, label_name} <- require_name(conn, repo, params["label"]) do
attrs = %{
"name" => label_name,
"color" => present(params["color"]) || @default_color,
"description" => present(params["description"])
}
case Labels.create_label(repo, attrs) do
{:ok, label} ->
conn
|> put_status(201)
|> json(%{"label" => JSON.repo_label(Map.put(label, :inherited?, false))})
{:error, %Ecto.Changeset{} = cs} ->
send_error(conn, 422, changeset_message(cs))
end
else
{:error, conn} -> conn
end
end
defp authorize_admin(conn, user, repo, owner, name) do
if GitGudWeb.RepoLive.Header.admin?(user, repo),
do: :ok,
else: {:error, send_error(conn, 403, "requires admin access to #{owner}/#{name}")}
end
defp require_name(conn, repo, raw) do
label_name = String.trim(to_string(raw || ""))
cond do
label_name == "" ->
{:error, send_error(conn, 422, "label can't be blank")}
Enum.any?(Labels.list_labels(repo), &(&1.name == label_name)) ->
{:error, send_error(conn, 422, "a label named #{label_name} already exists")}
true ->
{:ok, label_name}
end
end
defp present(v) when is_binary(v) do
case String.trim(v) do
"" -> nil
trimmed -> trimmed
end
end
defp present(_), do: nil
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
3.1 KiB · text
History
b868907