fix: harden mobile channel numeric params

This commit is contained in:
Graham McIntire 2026-03-22 17:36:09 -05:00
parent 35962c195b
commit d234c313ca
No known key found for this signature in database
4 changed files with 51 additions and 8 deletions

View file

@ -258,7 +258,10 @@ defmodule Aprsme.Packets.PreparedQueries do
# Convert miles to meters for PostGIS (1 mile = 1609.34 meters)
radius_meters = radius_miles * 1609.34
cutoff_time = DateTime.add(DateTime.utc_now(), -hours * 3600, :second)
cutoff_time =
DateTime.utc_now()
|> DateTime.truncate(:second)
|> DateTime.add(-hours * 3600, :second)
# Build point for spatial query
point = %Geo.Point{coordinates: {lon, lat}, srid: 4326}

View file

@ -163,7 +163,7 @@ defmodule AprsmeWeb.MobileChannel do
# Trim whitespace and control characters from query
query = String.trim(query)
limit = Map.get(payload, "limit", 50)
limit = payload |> Map.get("limit", 50) |> ensure_integer(50)
limit = min(limit, 500)
results = search_callsign(query, limit)
@ -175,7 +175,7 @@ defmodule AprsmeWeb.MobileChannel do
def handle_in("subscribe_callsign", %{"callsign" => callsign} = payload, socket) do
Logger.info("Mobile websocket received subscribe_callsign: #{inspect(payload)}")
hours_back = Map.get(payload, "hours_back", 24)
hours_back = payload |> Map.get("hours_back", 24) |> ensure_integer(24)
# Max 1 week
hours_back = min(hours_back, 168)
@ -278,6 +278,17 @@ defmodule AprsmeWeb.MobileChannel do
defp ensure_float(value) when is_binary(value), do: String.to_float(value)
defp ensure_float(value), do: value
defp ensure_integer(value, _default) when is_integer(value), do: value
defp ensure_integer(value, default) when is_binary(value) do
case Integer.parse(String.trim(value)) do
{int, _} -> int
:error -> default
end
end
defp ensure_integer(_value, default), do: default
defp build_mobile_packet(packet) do
# Extract coordinates
{lat, lon, _data_extended} = CoordinateUtils.get_coordinates(packet)
@ -335,8 +346,8 @@ defmodule AprsmeWeb.MobileChannel do
defp load_historical_packets(socket, bounds, payload) do
# Get optional parameters from payload
limit = Map.get(payload, "limit", 1000)
hours_back = Map.get(payload, "hours_back", 1)
limit = payload |> Map.get("limit", 1000) |> ensure_integer(1000)
hours_back = payload |> Map.get("hours_back", 1) |> ensure_integer(1)
# Ensure reasonable limits
limit = min(limit, 5000)

View file

@ -145,12 +145,12 @@ defmodule Aprsme.StreamingPacketsPubSubTest do
pid = Process.whereis(StreamingPacketsPubSub)
if pid do
GenServer.stop(pid)
:erlang.unregister(StreamingPacketsPubSub)
end
on_exit(fn ->
if !Process.whereis(StreamingPacketsPubSub) do
start_supervised!({StreamingPacketsPubSub, []})
if pid && !Process.whereis(StreamingPacketsPubSub) do
true = Process.register(pid, StreamingPacketsPubSub)
end
end)

View file

@ -261,6 +261,13 @@ defmodule AprsmeWeb.MobileChannelTest do
assert is_list(results)
end
test "accepts string limit values", %{socket: socket} do
ref = push(socket, "search_callsign", %{"query" => "W5ISP", "limit" => "1"})
assert_reply ref, :ok, %{count: count}
assert count <= 1
end
test "normalizes callsign to uppercase", %{socket: socket} do
ref = push(socket, "search_callsign", %{"query" => "w5isp"})
@ -291,6 +298,12 @@ defmodule AprsmeWeb.MobileChannelTest do
# Should not crash even with hours_back > 168
end
test "accepts string hours_back values", %{socket: socket} do
ref = push(socket, "subscribe_callsign", %{"callsign" => "W5ISP-9", "hours_back" => "24"})
assert_reply ref, :ok, %{callsign: "W5ISP-9"}
end
test "normalizes callsign to uppercase", %{socket: socket} do
ref = push(socket, "subscribe_callsign", %{"callsign" => "w5isp-9"})
@ -499,4 +512,20 @@ defmodule AprsmeWeb.MobileChannelTest do
refute Map.has_key?(pushed_packet, :path)
end
end
describe "subscribe_bounds with historical options" do
test "accepts string limit and hours_back values", %{socket: socket} do
ref =
push(socket, "subscribe_bounds", %{
"north" => 33.2,
"south" => 33.0,
"east" => -96.0,
"west" => -96.2,
"limit" => "10",
"hours_back" => "2"
})
assert_reply ref, :ok, %{message: "Subscribed to packet stream"}
end
end
end