Skip to content

Commit

Permalink
Add PATCH/POST endpoints for updating contact data
Browse files Browse the repository at this point in the history
  • Loading branch information
wmnnd committed May 27, 2024
1 parent a3f4be4 commit 7597a37
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

## Added
- Added PATCH and POST API endpoints for updating just the data field of a
contact

## Fixed
- Liquid tags are now correctly rendered in layout blocks in the Block Editor

Expand Down
51 changes: 51 additions & 0 deletions lib/keila_web/api/controllers/api_contact_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,57 @@ defmodule KeilaWeb.ApiContactController do
end
end

operation(:update_data,
summary: "Update Contact data",
description:
"Update just the `data` field of a Contact. The existing JSON object is merged in a shallow merge with the provided data object.",
parameters: [id: [in: :path, type: :string, description: "Contact ID"]],
request_body: {"Contact data params", "application/json", Schemas.Contact.DataParams},
responses: [
ok: {"Contact response", "application/json", Schemas.Contact.Response}
]
)

@spec update_data(Plug.Conn.t(), map()) :: Plug.Conn.t()
def update_data(conn, %{id: id}) do
contact = Contacts.get_project_contact(project_id(conn), id)

if contact do
params = %{data: Map.merge(contact.data || %{}, conn.body_params.data)}

case Contacts.update_contact(id, params) do
{:ok, contact} -> render(conn, "contact.json", %{contact: contact})
{:error, changeset} -> Errors.send_changeset_error(conn, changeset)
end
else
Errors.send_404(conn)
end
end

operation(:replace_data,
summary: "Replace Contact data",
description: "Replace just the `data` field of a Contact with the provided data object.",
parameters: [id: [in: :path, type: :string, description: "Contact ID"]],
request_body: {"Contact data params", "application/json", Schemas.Contact.DataParams},
responses: [
ok: {"Contact response", "application/json", Schemas.Contact.Response}
]
)

@spec replace_data(Plug.Conn.t(), map()) :: Plug.Conn.t()
def replace_data(conn, %{id: id}) do
if Contacts.get_project_contact(project_id(conn), id) do
params = %{data: conn.body_params.data}

case Contacts.update_contact(id, params) do
{:ok, contact} -> render(conn, "contact.json", %{contact: contact})
{:error, changeset} -> Errors.send_changeset_error(conn, changeset)
end
else
Errors.send_404(conn)
end
end

operation(:delete,
summary: "Delete Contact",
parameters: [id: [in: :path, type: :string, description: "Contact ID"]],
Expand Down
15 changes: 15 additions & 0 deletions lib/keila_web/api/schemas/contact.ex
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,18 @@ defmodule KeilaWeb.Api.Schemas.Contact.Params do
@allowed_properties [:email, :first_name, :last_name, :data, :status]
build_open_api_schema(@properties, only: @allowed_properties)
end

defmodule KeilaWeb.Api.Schemas.Contact.DataParams do
require OpenApiSpex

%OpenApiSpex.Schema{
type: :object,
properties: %{
data: %OpenApiSpex.Schema{
type: :object,
example: %{"tags" => ["rocket-scientist"]}
}
}
}
|> OpenApiSpex.schema()
end
2 changes: 2 additions & 0 deletions lib/keila_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ defmodule KeilaWeb.Router do
pipe_through [:api, :open_api]

resources "/contacts", ApiContactController, only: [:index, :show, :create, :update, :delete]
patch "/contacts/:id/data", ApiContactController, :update_data
post "/contacts/:id/data", ApiContactController, :replace_data

resources "/campaigns", ApiCampaignController,
only: [:index, :show, :create, :update, :delete]
Expand Down
20 changes: 20 additions & 0 deletions test/keila_web/api/api_contact_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,26 @@ defmodule KeilaWeb.ApiContactControllerTest do
end
end

describe "PATCH /api/v1/contacts/:id/data" do
@tag :api_contact_controller
test "updates contact data", %{authorized_conn: conn, project: project} do
contact = insert!(:contact, project_id: project.id, data: %{"foo" => "bar"})
body = %{"data" => %{"fizz" => "buzz"}}
conn = patch_json(conn, Routes.api_contact_path(conn, :update_data, contact.id), body)
assert %{"foo" => "bar", "fizz" => "buzz"} == json_response(conn, 200)["data"]["data"]
end
end

describe "POST /api/v1/contacts/:id/data" do
@tag :api_contact_controller
test "replaces contact data", %{authorized_conn: conn, project: project} do
contact = insert!(:contact, project_id: project.id, data: %{"foo" => "bar"})
body = %{"data" => %{"fizz" => "buzz"}}
conn = post_json(conn, Routes.api_contact_path(conn, :update_data, contact.id), body)
assert %{"fizz" => "buzz"} == json_response(conn, 200)["data"]["data"]
end
end

describe "DELETE /api/v1/contacts/:id" do
@tag :api_contact_controller
test "always returns 204", %{authorized_conn: conn, project: project} do
Expand Down

0 comments on commit 7597a37

Please sign in to comment.