- Escape HEEx template braces in GraphQL/API docs with raw(~S[...]) - Fix test assertions for updated marketing copy and UI text - Extract helper functions in GraphQL resolvers to reduce nesting depth - Create shared ErrorHelpers module for API controllers - Fix ETS race condition in brute force whitelist cache for async tests - Fix property test generators to use ASCII instead of printable unicode - Add alert_severity helper to site_live/show - Update accounts fixtures for explicit user confirmation
76 lines
2.5 KiB
Elixir
76 lines
2.5 KiB
Elixir
defmodule ToweropsWeb.GraphQL.Resolvers.Site do
|
|
@moduledoc "GraphQL resolvers for site queries and mutations."
|
|
|
|
alias Towerops.Repo
|
|
alias Towerops.Sites
|
|
alias Towerops.Sites.Site
|
|
|
|
def list(_parent, _args, %{context: %{organization_id: org_id}}) do
|
|
sites = Sites.list_organization_sites(org_id)
|
|
{:ok, sites}
|
|
end
|
|
|
|
def list(_parent, _args, _resolution), do: {:error, "Authentication required"}
|
|
|
|
def get(_parent, %{id: id}, %{context: %{organization_id: org_id}}) do
|
|
fetch_org_site(id, org_id)
|
|
end
|
|
|
|
def get(_parent, _args, _resolution), do: {:error, "Authentication required"}
|
|
|
|
def create(_parent, %{input: input}, %{context: %{organization_id: org_id}}) do
|
|
attrs =
|
|
input
|
|
|> Map.new(fn {k, v} -> {to_string(k), v} end)
|
|
|> Map.put("organization_id", org_id)
|
|
|
|
case Sites.create_site(attrs) do
|
|
{:ok, site} -> {:ok, site}
|
|
{:error, changeset} -> {:error, format_errors(changeset)}
|
|
end
|
|
end
|
|
|
|
def create(_parent, _args, _resolution), do: {:error, "Authentication required"}
|
|
|
|
def update(_parent, %{id: id, input: input}, %{context: %{organization_id: org_id}}) do
|
|
with {:ok, site} <- fetch_org_site(id, org_id) do
|
|
attrs = Map.new(input, fn {k, v} -> {to_string(k), v} end)
|
|
|
|
case Sites.update_site(site, attrs) do
|
|
{:ok, updated} -> {:ok, updated}
|
|
{:error, changeset} -> {:error, format_errors(changeset)}
|
|
end
|
|
end
|
|
end
|
|
|
|
def update(_parent, _args, _resolution), do: {:error, "Authentication required"}
|
|
|
|
def delete(_parent, %{id: id}, %{context: %{organization_id: org_id}}) do
|
|
with {:ok, site} <- fetch_org_site(id, org_id) do
|
|
case Sites.delete_site(site) do
|
|
{:ok, _} -> {:ok, %{success: true, message: "Site deleted"}}
|
|
{:error, _} -> {:ok, %{success: false, message: "Could not delete site"}}
|
|
end
|
|
end
|
|
end
|
|
|
|
def delete(_parent, _args, _resolution), do: {:error, "Authentication required"}
|
|
|
|
defp fetch_org_site(id, org_id) do
|
|
case Repo.get(Site, id) do
|
|
nil -> {:error, "Site not found"}
|
|
%Site{organization_id: ^org_id} = site -> {:ok, site}
|
|
%Site{} -> {:error, "Site not found"}
|
|
end
|
|
end
|
|
|
|
defp format_errors(changeset) do
|
|
changeset
|
|
|> Ecto.Changeset.traverse_errors(fn {msg, opts} ->
|
|
Regex.replace(~r"%{(\w+)}", msg, fn _, key ->
|
|
opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
|
|
end)
|
|
end)
|
|
|> Enum.map_join("; ", fn {field, messages} -> "#{field}: #{Enum.join(messages, ", ")}" end)
|
|
end
|
|
end
|