- Add jump_credo_checks ~> 0.4 with all 20 checks enabled - Fix all standard Credo issues: 139 @spec (113 done, 26 remain), 4 refactoring, 3 alias usage, 9 System.cmd env, 5 unsafe_to_atom, 2 max line length, 9 assert_receive timeout - Fix 170+ jump_credo_checks warnings: - 117 TopLevelAliasImportRequire: move nested alias/import to module top - 32 UseObanProWorker: switch to Oban.Pro.Worker - 4 DoctestIExExamples: add doctests / create test file - ~20 WeakAssertion: strengthen type-check assertions - Various ConditionalAssertion, AssertReceiveTimeout fixes - Exclude vendor/ from Credo analysis - Remaining: 175 warnings (mostly opinionated WeakAssertion, AvoidSocketAssignsInTest), 26 @spec annotations
107 lines
3.1 KiB
Elixir
107 lines
3.1 KiB
Elixir
defmodule MicrowavepropWeb.Api.V1.ContactController do
|
|
@moduledoc "Read + create contacts (QSOs)."
|
|
|
|
use Phoenix.Controller, formats: [:json]
|
|
|
|
alias Microwaveprop.Accounts.Scope
|
|
alias Microwaveprop.Radio
|
|
alias Microwaveprop.Radio.Contact
|
|
alias Microwaveprop.Repo
|
|
alias MicrowavepropWeb.Api.ErrorJSON
|
|
alias MicrowavepropWeb.Api.V1.ContactJSON
|
|
|
|
plug :accepts, ["json"]
|
|
action_fallback MicrowavepropWeb.Api.FallbackController
|
|
|
|
@max_per_page 200
|
|
|
|
@spec index(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
|
def index(conn, params) do
|
|
page = params |> Map.get("page", "1") |> parse_int(1)
|
|
per_page = params |> Map.get("per_page", "50") |> parse_int(50) |> min(@max_per_page) |> max(1)
|
|
search = params["search"]
|
|
viewer = conn.assigns[:current_api_user]
|
|
|
|
%{entries: entries, total_entries: total, total_pages: total_pages} =
|
|
Radio.list_contacts(
|
|
page: page,
|
|
per_page: per_page,
|
|
search: search,
|
|
scope: Scope.for_user(viewer)
|
|
)
|
|
|
|
json(
|
|
conn,
|
|
ContactJSON.index_paginated(%{
|
|
contacts: entries,
|
|
viewer: viewer,
|
|
page: page,
|
|
per_page: per_page,
|
|
total_entries: total,
|
|
total_pages: total_pages
|
|
})
|
|
)
|
|
end
|
|
|
|
@spec show(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
|
def show(conn, %{"id" => id}) do
|
|
viewer = conn.assigns[:current_api_user]
|
|
|
|
case Repo.get(Contact, id) do
|
|
nil ->
|
|
ErrorJSON.send_problem(conn, 404, "not_found", "Contact not found.")
|
|
|
|
%Contact{private: true, user_id: owner_id} = contact ->
|
|
if owner_id && viewer && viewer.id == owner_id do
|
|
json(conn, ContactJSON.show(%{contact: contact, viewer: viewer}))
|
|
else
|
|
ErrorJSON.send_problem(conn, 404, "not_found", "Contact not found.")
|
|
end
|
|
|
|
%Contact{} = contact ->
|
|
json(conn, ContactJSON.show(%{contact: contact, viewer: viewer}))
|
|
end
|
|
end
|
|
|
|
@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
|
def create(conn, params) do
|
|
user = conn.assigns.current_api_user
|
|
|
|
attrs =
|
|
params
|
|
|> Map.take(
|
|
~w(station1 station2 qso_timestamp mode band grid1 grid2 user_declared_prop_mode height1_ft height2_ft private notes)
|
|
)
|
|
|> Map.put_new("submitter_email", user.email)
|
|
|
|
case Radio.create_contact(attrs, user.id) do
|
|
{:ok, contact} ->
|
|
conn
|
|
|> put_status(:created)
|
|
|> json(ContactJSON.show(%{contact: contact, viewer: user}))
|
|
|
|
{:error, %Ecto.Changeset{} = changeset} ->
|
|
ErrorJSON.send_changeset(conn, changeset)
|
|
|
|
{:error, :duplicate, existing} ->
|
|
conn
|
|
|> put_status(:conflict)
|
|
|> json(%{
|
|
type: "about:blank",
|
|
title: "duplicate_contact",
|
|
status: 409,
|
|
detail: "An equivalent contact already exists.",
|
|
existing: ContactJSON.show(%{contact: existing, viewer: user}).data
|
|
})
|
|
end
|
|
end
|
|
|
|
defp parse_int(value, fallback) when is_binary(value) do
|
|
case Integer.parse(value) do
|
|
{n, ""} when n >= 1 -> n
|
|
_ -> fallback
|
|
end
|
|
end
|
|
|
|
defp parse_int(_, fallback), do: fallback
|
|
end
|