Skip to content

Commit

Permalink
fix: rest endpoints validations
Browse files Browse the repository at this point in the history
  • Loading branch information
gabheadz committed Dec 27, 2024
1 parent 990e902 commit 90838b6
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 39 deletions.
80 changes: 54 additions & 26 deletions channel-sender/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,70 @@ info:
license:
name: MIT
url: https://github.com/bancolombia/async-dataflow-channel-sender/blob/master/LICENSE
version: 0.1.0
version: 0.2.0
servers:
- url: https://virtserver.swaggerhub.com/santitigaga/async-data-flow-channel-sender/0.1.0
description: SwaggerHub API Auto Mocking
tags:
- name: /ext/channel/
description: Secured Admin-only calls
- name: channel
description: Available operations for channels

paths:
/create:
post:
tags:
- /ext/channel/
summary: Create Channel and session
description: |
By passing in the appropriate options, you can search for
available inventory in the system
By passing in the appropriate options, you can regisster a new channel in the system
operationId: createChannel
requestBody:
description: Channel to create
content:
application/json:
schema:
$ref: '#/components/schemas/Channel'
$ref: '#/components/schemas/ChannelRequest'
responses:
"200":
description: channel_ref and channel_secret
content:
application/json:
schema:
type: object
properties:
channel_ref:
type: string
example: UNIQUE APPLICATION IDENTIFIER
channel_secret:
type: string
example: TOKEN
"412":
description: No application {application_ref} found
$ref: '#/components/schemas/Credentials'
"400":
description: Bad request due to invalid body or missing required fields
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidRequest'

/deliver_message:
post:
tags:
- /ext/channel/
summary: Deliver an event from a message
description: Deliver an event from a message to a channel
description: Deliver an event message to a previusly registered channel_ref
operationId: deliverMessage
requestBody:
description: Inventory item to add
description: "Triggers internal workflow to deliver message. The message may not be delivered immediately, or not at all. Depends if the channel_ref was previusly registered. The message_data schema is not enforced, but its recommeded to use CloudEvents."
content:
application/json:
schema:
$ref: '#/components/schemas/Message'
responses:
"202":
description: Ok
content:
application/json:
schema:
type: object
properties:
result:
type: string
example: Ok
"400":
description: Invalid request
description: Bad request due to invalid body or missing required fields
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidRequest'
components:
schemas:
Message:
Expand All @@ -88,19 +93,42 @@ components:
example: d290f1ee-6c54-4b01-90e6-d701748f0851
message_data:
type: object
example: '{}'
example: {"product_id": "1234", "product_name": "product name"}
event_name:
type: string
example: event.productCreated
Channel:
ChannelRequest:
required:
- application_ref
- user_ref
type: object
properties:
application_ref:
type: string
example: UNIQUE APPLICATION IDENTIFIER
example: app01
user_ref:
type: string
example: USER@DOMAIN
example: jhon.doe
Credentials:
required:
- channel_ref
- channel_secret
type: object
properties:
channel_ref:
type: string
example: beec634503c238f5b84f737275bfd4ba.855b8193bb6f419381eac6cc087aea3f
channel_secret:
type: string
example: SFMyNTY.g2gDaANtAAAAQWJlZWM2MzQ1MDNjMjM4ZjViODRmNzM3Mjc1YmZkNGJhLjg1NWI4MTkzYmI2ZjQxOTM4MWVhYzZjYzA4N2FlYTNmbQAAAAZ4eHh4eHhtAAAAB3h4eHh4eHhuBgDbcXMIlAFiAAFRgA.......
InvalidRequest:
required:
- error
- request
type: object
properties:
error:
type: string
example: Invalid request
request:
type: object
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,27 @@ defmodule ChannelSenderEx.Transport.Rest.RestController do
route_create(conn.body_params, conn)
end

defp route_create(_message = %{
defp route_create(message = %{
application_ref: application_ref,
user_ref: user_ref
}, conn
) do
{channel_ref, channel_secret} = ChannelAuthenticator.create_channel(application_ref, user_ref)
response = %{channel_ref: channel_ref, channel_secret: channel_secret}

conn
|> put_resp_header("content-type", "application/json")
|> send_resp(200, Jason.encode!(response))
is_valid = message
|> Enum.all?(fn {_, value} -> is_binary(value) and value != "" end)

case is_valid do
true ->
{channel_ref, channel_secret} = ChannelAuthenticator.create_channel(application_ref, user_ref)
response = %{channel_ref: channel_ref, channel_secret: channel_secret}

conn
|> put_resp_header("content-type", "application/json")
|> send_resp(200, Jason.encode!(response))

false ->
invalid_body(conn)
end
end

defp route_create(_body, conn) do
Expand All @@ -60,13 +70,31 @@ defmodule ChannelSenderEx.Transport.Rest.RestController do
}, conn
) do

Task.start(fn -> PubSubCore.deliver_to_channel(channel_ref,
Map.drop(message, [:channel_ref]) |> ProtocolMessage.to_protocol_message)
# assert that minimum required fields are present
is_valid = message
|> Enum.all?(fn {key, value} ->
case key do
:message_data ->
not is_nil(value)
:correlation_id ->
true
_ ->
is_binary(value) and value != ""
end
end)

conn
|> put_resp_header("content-type", "application/json")
|> send_resp(202, Jason.encode!(%{result: "Ok"}))
case is_valid do
true ->
Task.start(fn -> PubSubCore.deliver_to_channel(channel_ref,
Map.drop(message, [:channel_ref]) |> ProtocolMessage.to_protocol_message)
end)
conn
|> put_resp_header("content-type", "application/json")
|> send_resp(202, Jason.encode!(%{result: "Ok"}))

false ->
invalid_body(conn)
end
end

defp route_deliver(_, conn), do: invalid_body(conn)
Expand All @@ -75,6 +103,6 @@ defmodule ChannelSenderEx.Transport.Rest.RestController do
defp invalid_body(conn = %{body_params: invalid_body}) do
conn
|> put_resp_header("content-type", "application/json")
|> send_resp(400, Jason.encode!(%{error: "Invalid request #{inspect(invalid_body)}"}))
|> send_resp(400, Jason.encode!(%{error: "Invalid request", request: invalid_body}))
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ defmodule ChannelSenderEx.Core.ChannelIntegrationTest do

Process.sleep(500)
assert Process.alive?(channel_pid) == false

on_exit(fn ->
Application.delete_env(:channel_sender_ex, :channel_shutdown_on_clean_close)
Application.delete_env(:channel_sender_ex, :channel_shutdown_on_disconnection)
Helper.compile(:channel_sender_ex)
end)
end

test "Should not restart channel when terminated normal (Waiting timeout)" do
Expand All @@ -145,7 +151,11 @@ defmodule ChannelSenderEx.Core.ChannelIntegrationTest do
Process.sleep(300)

assert :noproc == ChannelRegistry.lookup_channel_addr(channel)
Helper.compile(:channel_sender_ex)
on_exit(fn ->
Application.delete_env(:channel_sender_ex, :channel_shutdown_on_clean_close)
Application.delete_env(:channel_sender_ex, :channel_shutdown_on_disconnection)
Helper.compile(:channel_sender_ex)
end)
end

test "Should send pending messages to twin process when terminated by supervisor merge (name conflict)" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ defmodule ChannelSenderEx.Transport.Rest.RestControllerTest do

end

test "Should not create channel on bad request due to missing fields" do
body = Jason.encode!(%{application_ref: "some_application", user_ref: nil})

conn = conn(:post, "/ext/channel/create", body)
|> put_req_header("content-type", "application/json")

conn = RestController.call(conn, @options)

assert conn.status == 400
end

test "Should send message on request" do

body =
Expand Down Expand Up @@ -97,7 +108,27 @@ defmodule ChannelSenderEx.Transport.Rest.RestControllerTest do
assert conn.status == 400

assert %{"error" => "Invalid request" <> _rest} = Jason.decode!(conn.resp_body)
end

test "Should fail on invalid body due to invalid values" do
body =
Jason.encode!(%{
channel_ref: nil,
message_id: "message_id",
correlation_id: "correlation_id",
message_data: "message_data",
event_name: "event_name"
})

conn = conn(:post, "/ext/channel/deliver_message", body)
|> put_req_header("content-type", "application/json")

conn = RestController.call(conn, @options)

assert conn.status == 400

assert %{"error" => "Invalid request" <> _rest} = Jason.decode!(conn.resp_body)
end


end

0 comments on commit 90838b6

Please sign in to comment.