Skip to content

Commit 3751344

Browse files
committed
Explicitly differentiate between CreateParams and UpdateParams in API
This allows settings fields as required when creating an entity but not required when updating
1 parent 00739dc commit 3751344

10 files changed

+85
-50
lines changed

lib/keila_web/api/controllers/api_campaign_controller.ex

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ defmodule KeilaWeb.ApiCampaignController do
3535
operation(:create,
3636
summary: "Create Campaign",
3737
parameters: [],
38-
request_body: {"Campaign params", "application/json", Schemas.MailingsCampaign.Params},
38+
request_body: {"Campaign params", "application/json", Schemas.MailingsCampaign.CreateParams},
3939
responses: [
4040
ok: {"Campaign response", "application/json", Schemas.MailingsCampaign.Response}
4141
]
@@ -68,7 +68,7 @@ defmodule KeilaWeb.ApiCampaignController do
6868
operation(:update,
6969
summary: "Update Campaign",
7070
parameters: [id: [in: :path, type: :string, description: "Campaign ID"]],
71-
request_body: {"Campaign params", "application/json", Schemas.MailingsCampaign.Params},
71+
request_body: {"Campaign params", "application/json", Schemas.MailingsCampaign.UpdateParams},
7272
responses: [
7373
ok: {"Campaign response", "application/json", Schemas.MailingsCampaign.Response}
7474
]
@@ -137,7 +137,7 @@ defmodule KeilaWeb.ApiCampaignController do
137137
summary: "Schedule Campaign",
138138
parameters: [id: [in: :path, type: :string, description: "Campaign ID"]],
139139
request_body:
140-
{"Campaign params", "application/json", Schemas.MailingsCampaign.ScheduleParams},
140+
{"Schedule params", "application/json", Schemas.MailingsCampaign.ScheduleParams},
141141
responses: %{
142142
ok: {"Campaign response", "application/json", Schemas.MailingsCampaign.Response}
143143
}

lib/keila_web/api/controllers/api_contact_controller.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ defmodule KeilaWeb.ApiContactController do
6565
operation(:create,
6666
summary: "Create Contact",
6767
parameters: [],
68-
request_body: {"Contact params", "application/json", Schemas.Contact.Params},
68+
request_body: {"Contact params", "application/json", Schemas.Contact.CreateParams},
6969
responses: [
7070
ok: {"Contact response", "application/json", Schemas.Contact.Response}
7171
]
@@ -98,7 +98,7 @@ defmodule KeilaWeb.ApiContactController do
9898
operation(:update,
9999
summary: "Update Contact",
100100
parameters: Schemas.Contact.id_parameters(),
101-
request_body: {"Contact params", "application/json", Schemas.Contact.Params},
101+
request_body: {"Contact params", "application/json", Schemas.Contact.UpdateParams},
102102
responses: [
103103
ok: {"Contact response", "application/json", Schemas.Contact.Response}
104104
]

lib/keila_web/api/controllers/api_form_controller.ex

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ defmodule KeilaWeb.ApiFormController do
3535
operation(:create,
3636
summary: "Create Form",
3737
parameters: [],
38-
request_body: {"Form params", "application/json", Schemas.Form.Params},
38+
request_body: {"Form params", "application/json", Schemas.Form.CreateParams},
3939
responses: [
4040
ok: {"Form response", "application/json", Schemas.Form.Response}
4141
]
@@ -72,7 +72,7 @@ defmodule KeilaWeb.ApiFormController do
7272
operation(:update,
7373
summary: "Update Form",
7474
parameters: [id: [in: :path, type: :string, description: "Form ID"]],
75-
request_body: {"Form params", "application/json", Schemas.Form.Params},
75+
request_body: {"Form params", "application/json", Schemas.Form.UpdateParams},
7676
responses: [
7777
ok: {"Form response", "application/json", Schemas.Form.Response}
7878
]
@@ -145,7 +145,7 @@ defmodule KeilaWeb.ApiFormController do
145145
requires a CAPTCHA.
146146
""",
147147
parameters: [id: [in: :path, type: :string, description: "Campaign ID"]],
148-
request_body: {"Contact params", "application/json", Schemas.Contact.Params},
148+
request_body: {"Contact params", "application/json", Schemas.Contact.CreateParams},
149149
responses: %{
150150
200 => {"Contact response", "application/json", Schemas.Contact.Response},
151151
202 => {"Double-Opt-In response", "application/json", Schemas.Form.DoubleOptInResponse}

lib/keila_web/api/controllers/api_segment_controller.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule KeilaWeb.ApiSegmentController do
3434
operation(:create,
3535
summary: "Create Segment",
3636
parameters: [],
37-
request_body: {"Segment params", "application/json", Schemas.ContactsSegment.Params},
37+
request_body: {"Segment params", "application/json", Schemas.ContactsSegment.CreateParams},
3838
responses: [
3939
ok: {"Segment response", "application/json", Schemas.ContactsSegment.Response}
4040
]
@@ -67,7 +67,7 @@ defmodule KeilaWeb.ApiSegmentController do
6767
operation(:update,
6868
summary: "Update Segment",
6969
parameters: [id: [in: :path, type: :string, description: "Segment ID"]],
70-
request_body: {"Segment params", "application/json", Schemas.ContactsSegment.Params},
70+
request_body: {"Segment params", "application/json", Schemas.ContactsSegment.UpdateParams},
7171
responses: [
7272
ok: {"Segment response", "application/json", Schemas.ContactsSegment.Response}
7373
]

lib/keila_web/api/schema.ex

+23-26
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,27 @@ defmodule KeilaWeb.Api.Schema do
7777

7878
def schema_build(properties, opts) when is_map(properties) do
7979
allowed_properties = Keyword.get(opts, :only, :all)
80-
required_properties = required_properties(properties, allowed_properties)
80+
properties = do_schema_build(properties, allowed_properties)
81+
8182
list? = Keyword.get(opts, :list, false)
8283
meta = Keyword.get(opts, :meta, nil)
8384
with_pagination? = Keyword.get(opts, :with_pagination, false)
85+
required = Keyword.get(opts, :required, nil)
8486

8587
data_schema =
8688
if list? do
8789
%OpenApiSpex.Schema{
8890
type: :array,
8991
items: %OpenApiSpex.Schema{
9092
type: :object,
91-
properties: do_schema_build(properties, allowed_properties),
92-
required: required_properties,
93+
properties: properties,
9394
additionalProperties: false
9495
}
9596
}
9697
else
9798
%OpenApiSpex.Schema{
9899
type: :object,
99-
properties: do_schema_build(properties, allowed_properties),
100-
required: required_properties,
100+
properties: properties,
101101
additionalProperties: false
102102
}
103103
end
@@ -110,6 +110,7 @@ defmodule KeilaWeb.Api.Schema do
110110
}
111111
|> maybe_add_meta(meta)
112112
|> maybe_put_pagination(with_pagination?)
113+
|> maybe_put_required(required)
113114
end
114115

115116
defp do_schema_build(properties, allowed_properties \\ :all)
@@ -119,7 +120,6 @@ defmodule KeilaWeb.Api.Schema do
119120
allowed_properties == :all || key in allowed_properties,
120121
into: %{} do
121122
properties = do_schema_build(Map.get(property, :properties))
122-
required_properties = required_properties(Map.get(property, :properties))
123123

124124
items =
125125
case do_schema_build(Map.get(property, :items)) do
@@ -135,8 +135,7 @@ defmodule KeilaWeb.Api.Schema do
135135
enum: Map.get(property, :enum),
136136
example: Map.get(property, :example),
137137
properties: properties,
138-
items: items,
139-
required: required_properties
138+
items: items
140139
}}
141140
end
142141
end
@@ -153,24 +152,22 @@ defmodule KeilaWeb.Api.Schema do
153152

154153
defp maybe_put_pagination(schema, true), do: maybe_add_meta(schema, @meta)
155154

156-
defp required_properties(properties, allowed_properties \\ :all)
157-
158-
defp required_properties(nil, _), do: nil
159-
defp required_properties([], _), do: nil
160-
161-
defp required_properties(properties, allowed_properties) do
162-
properties
163-
|> Enum.filter(fn
164-
{key, %{required: true}} ->
165-
allowed_properties == :all || key in allowed_properties
166-
167-
_ ->
168-
false
169-
end)
170-
|> Enum.map(fn {key, _} -> key end)
171-
|> then(fn
172-
[] -> nil
173-
required_properties -> required_properties
155+
defp maybe_put_required(schema, nil), do: schema
156+
157+
defp maybe_put_required(schema, required_fields) do
158+
Enum.reduce(required_fields, schema, fn
159+
field, schema when is_atom(field) ->
160+
update_in(schema, [:properties, :data, Access.key!(:required)], fn
161+
nil -> [field]
162+
required -> [field | required]
163+
end)
164+
165+
{path, required_fields}, schema when is_list(path) ->
166+
put_in(
167+
schema,
168+
[:properties, :data, Access.key!(:properties)] ++ path ++ [Access.key!(:required)],
169+
required_fields
170+
)
174171
end)
175172
end
176173
end

lib/keila_web/api/schemas/contact.ex

+9-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ defmodule KeilaWeb.Api.Schemas.Contact do
1010
email: %{
1111
type: :string,
1212
format: :email,
13-
required: true,
1413
example: "jane.doe@example.com"
1514
},
1615
external_id: %{
@@ -79,7 +78,15 @@ defmodule KeilaWeb.Api.Schemas.Contact.IndexResponse do
7978
build_open_api_schema(@properties, list: true, with_pagination: true)
8079
end
8180

82-
defmodule KeilaWeb.Api.Schemas.Contact.Params do
81+
defmodule KeilaWeb.Api.Schemas.Contact.CreateParams do
82+
use KeilaWeb.Api.Schema
83+
84+
@properties KeilaWeb.Api.Schemas.Contact.properties()
85+
@allowed_properties [:email, :external_id, :first_name, :last_name, :data, :status]
86+
build_open_api_schema(@properties, only: @allowed_properties, required: [:email])
87+
end
88+
89+
defmodule KeilaWeb.Api.Schemas.Contact.UpdateParams do
8390
use KeilaWeb.Api.Schema
8491

8592
@properties KeilaWeb.Api.Schemas.Contact.properties()

lib/keila_web/api/schemas/contact_segment.ex

+9-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,15 @@ defmodule KeilaWeb.Api.Schemas.ContactsSegment.IndexResponse do
4848
build_open_api_schema(@properties, list: true, with_pagination: true)
4949
end
5050

51-
defmodule KeilaWeb.Api.Schemas.ContactsSegment.Params do
51+
defmodule KeilaWeb.Api.Schemas.ContactsSegment.CreateParams do
52+
use KeilaWeb.Api.Schema
53+
54+
@properties KeilaWeb.Api.Schemas.ContactsSegment.properties()
55+
@allowed_properties [:name, :filter]
56+
build_open_api_schema(@properties, only: @allowed_properties, require: [:name, :filter])
57+
end
58+
59+
defmodule KeilaWeb.Api.Schemas.ContactsSegment.UpdateParams do
5260
use KeilaWeb.Api.Schema
5361

5462
@properties KeilaWeb.Api.Schemas.ContactsSegment.properties()

lib/keila_web/api/schemas/form.ex

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ defmodule KeilaWeb.Api.Schemas.Form do
99
},
1010
name: %{
1111
type: :string,
12-
required: true,
1312
example: "My Form"
1413
},
1514
sender_id: %{
@@ -107,7 +106,15 @@ defmodule KeilaWeb.Api.Schemas.Form.DoubleOptInResponse do
107106
build_open_api_schema(%{double_opt_in_required: %{type: :boolean, enum: [true]}})
108107
end
109108

110-
defmodule KeilaWeb.Api.Schemas.Form.Params do
109+
defmodule KeilaWeb.Api.Schemas.Form.CreateParams do
110+
use KeilaWeb.Api.Schema
111+
112+
@properties KeilaWeb.Api.Schemas.Form.properties()
113+
@allowed_properties [:name, :sender_id, :template_id, :settings, :fields]
114+
build_open_api_schema(@properties, only: @allowed_properties, required: [:name])
115+
end
116+
117+
defmodule KeilaWeb.Api.Schemas.Form.UpdateParams do
111118
use KeilaWeb.Api.Schema
112119

113120
@properties KeilaWeb.Api.Schemas.Form.properties()

lib/keila_web/api/schemas/mailings_campaign.ex

+24-7
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ defmodule KeilaWeb.Api.Schemas.MailingsCampaign do
77
},
88
subject: %{
99
type: :string,
10-
example: "🚀 Our Space Book is Now Available!",
11-
required: true
10+
example: "🚀 Our Space Book is Now Available!"
1211
},
1312
text_body: %{
1413
type: :string,
@@ -63,13 +62,11 @@ defmodule KeilaWeb.Api.Schemas.MailingsCampaign do
6362
properties: %{
6463
type: %{
6564
type: :string,
66-
required: true,
6765
enum: ["markdown", "text", "block", "mjml"],
6866
example: "markdown"
6967
},
7068
do_not_track: %{
71-
type: :boolean,
72-
required: false
69+
type: :boolean
7370
}
7471
}
7572
},
@@ -78,7 +75,6 @@ defmodule KeilaWeb.Api.Schemas.MailingsCampaign do
7875
},
7976
sender_id: %{
8077
type: :string,
81-
required: true,
8278
example: "ms_12345"
8379
},
8480
segment_id: %{
@@ -124,7 +120,28 @@ defmodule KeilaWeb.Api.Schemas.MailingsCampaign.IndexResponse do
124120
build_open_api_schema(@properties, list: true, with_pagination: true)
125121
end
126122

127-
defmodule KeilaWeb.Api.Schemas.MailingsCampaign.Params do
123+
defmodule KeilaWeb.Api.Schemas.MailingsCampaign.CreateParams do
124+
use KeilaWeb.Api.Schema
125+
126+
@properties KeilaWeb.Api.Schemas.MailingsCampaign.properties()
127+
@allowed_properties [
128+
:subject,
129+
:text_body,
130+
:json_body,
131+
:mjml_body,
132+
:settings,
133+
:template_id,
134+
:sender_id,
135+
:segment_id,
136+
:data
137+
]
138+
build_open_api_schema(@properties,
139+
only: @allowed_properties,
140+
required: [:subject, :settings, {[:settings], [:type]}]
141+
)
142+
end
143+
144+
defmodule KeilaWeb.Api.Schemas.MailingsCampaign.UpdateParams do
128145
use KeilaWeb.Api.Schema
129146

130147
@properties KeilaWeb.Api.Schemas.MailingsCampaign.properties()

lib/keila_web/api/schemas/mailings_sender.ex

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ defmodule KeilaWeb.Api.Schemas.MailingsSender do
77
},
88
name: %{
99
type: :string,
10-
example: "Space Inc. SMTP",
11-
required: true
10+
example: "Space Inc. SMTP"
1211
},
1312
from_email: %{
1413
type: :string,

0 commit comments

Comments
 (0)