defmodule Localiser.Web.Controllers.SetupController do use Phoenix.Controller, formats: [:json] use OpenApiSpex.ControllerSpecs alias Localiser.Domain.Users alias Localiser.Web.Token alias Localiser.Web.Schemas tags ["Auth"] operation :create, summary: "Create first admin user", description: "Only succeeds when no users exist. Blocked with 403 afterwards.", security: [], request_body: {"Setup params", "application/json", Schemas.SetupParams, required: true}, responses: [ created: {"Admin user created", "application/json", Schemas.TokenResponse}, bad_request: {"Missing username/password", "application/json", Schemas.Error}, forbidden: {"System already initialised", "application/json", Schemas.Error}, unprocessable_entity: {"Validation errors", "application/json", Schemas.ValidationErrors} ] def create(conn, %{"username" => username, "password" => password}) do attrs = %{"username" => username, "password" => password, "is_admin" => true} case Users.create_user(attrs) do {:ok, user} -> token = Token.generate(%{"sub" => user.id}) conn |> put_status(:created) |> json(%{token: token, user: render_user(user)}) {:error, changeset} -> conn |> put_status(:unprocessable_entity) |> json(%{errors: format_errors(changeset)}) end end def create(conn, _params) do conn |> put_status(:bad_request) |> json(%{error: "username and password are required"}) end defp render_user(user) do %{id: user.id, username: user.username, is_admin: user.is_admin} end defp format_errors(changeset) do Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} -> Enum.reduce(opts, msg, fn {key, val}, acc -> String.replace(acc, "%{#{key}}", to_string(val)) end) end) end end