defmodule ToweropsWeb.Api.V1.MembersController do @moduledoc "API controller for organization members." use ToweropsWeb, :controller alias Towerops.Organizations def index(conn, _params) do organization_id = conn.assigns.current_organization_id members = organization_id |> Organizations.list_organization_members() |> Enum.map(&format_member/1) json(conn, %{data: members}) end def update(conn, %{"id" => user_id, "role" => role}) do organization_id = conn.assigns.current_organization_id case Organizations.update_member_role(organization_id, user_id, role) do {:ok, membership} -> membership = Towerops.Repo.preload(membership, :user) json(conn, %{data: format_member(membership)}) {:error, :cannot_change_owner_role} -> conn |> put_status(:forbidden) |> json(%{error: "Cannot change owner role"}) {:error, :not_found} -> conn |> put_status(:not_found) |> json(%{error: "Member not found"}) {:error, changeset} -> conn |> put_status(:unprocessable_entity) |> json(%{errors: translate_errors(changeset)}) end end def update(conn, _params) do conn |> put_status(:bad_request) |> json(%{error: "Missing 'role' parameter"}) end def delete(conn, %{"id" => user_id}) do organization_id = conn.assigns.current_organization_id case Organizations.remove_member(organization_id, user_id) do {:ok, _} -> conn |> put_status(:no_content) |> send_resp(204, "") {:error, :cannot_remove_owner} -> conn |> put_status(:forbidden) |> json(%{error: "Cannot remove owner"}) {:error, :not_found} -> conn |> put_status(:not_found) |> json(%{error: "Member not found"}) end end defp format_member(membership) do %{ id: membership.user_id, email: membership.user.email, role: membership.role, inserted_at: membership.inserted_at } end defp translate_errors(changeset) do Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} -> Regex.replace(~r"%{(\w+)}", msg, fn _, key -> if String.length(key) <= 50 and String.match?(key, ~r/^[a-z_]+$/) do opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() else key end end) end) end end