Hi,
I was writing code like this:
def create(conn, %{"device" => device_params}) do
device = Devices.get_device_by_id(device_params["device_id"])
case device do
nil ->
with {:ok, %Device{} = device} <- Devices.create_device(device_params) do
conn
|> put_status(:created)
|> render("show.json", device: device)
end
_ ->
device_params = Map.merge(device_params, %{"session_count" => device.session_count + 1})
with {:ok, %Device{} = device} <- Devices.update_device(device, device_params) do
render(conn, "show.json", device: device)
end
end
end
Thanks to Phoenix Tests it failed due to a security issue.
** (ArgumentError) comparison with nil is forbidden as it is unsafe. If you want to check if a value is nil, use is_nil/1 instead
code: conn = post(conn, Routes.device_path(conn, :create), device: @invalid_attrs)
My purpose is using one single route (POST) for client side, when the client app runs, it always makes POST call doesn’t have a PUT
logic on client side for some reasons so I needed this approach even I don’t like it.
So, I did some research about the problem and I saw Jose Valim’s comments on GitHub issues and try to solve it via on_conflict
feature of Ecto. Then I learnt (from another GitHub issue) that can’t be done in PostgreSQL adapter, we have to use fragment.
This is going to be very common usage for the app, I’ll eventually need to create or update data(s) such way. So, what’s the best practice without creating vulnerabilities?
Thank you all!