Fix additional nesting depth issues across multiple files
Extracts nested logic into helper functions to comply with Credo requirements (max nesting depth 2): - data_builder.ex: Extract historical packet distance filtering (filter_historical_by_distance/3, packet_far_enough_from_most_recent?/3) Reduces depth 5 -> depth 3 - streaming_packets_pubsub.ex: Extract subscriber message sending (send_to_subscriber_if_alive/3) Reduces depth 4 -> depth 2 - aprs_symbol.ex: Extract symbol code calculation (get_symbol_code_ord/1) Reduces depth 3 -> depth 2 - mobile_channel.ex: Extract subscription bounds update (update_subscription_bounds/2) Reduces depth 3 -> depth 2 - core_components.ex: Extract SVG tag class insertion (add_class_to_svg_tag/2) Reduces depth 3 -> depth 2 - info_live/show.ex: Extract row mapping for database queries (map_digipeater_row/2, map_station_heard_row/2) Reduces depth 3 -> depth 2 (2 instances) Also updates .sobelow-skips with new line numbers from code changes. Fixes 7 Credo nesting depth issues (2 remaining)
This commit is contained in:
parent
74a19b0640
commit
318eb30046
7 changed files with 119 additions and 90 deletions
|
|
@ -21,3 +21,8 @@ SQL.Query: SQL injection,lib/aprsme_web/live/info_live/show.ex:390,46E033F
|
||||||
SQL.Query: SQL injection,lib/aprsme_web/live/info_live/show.ex:505,515E82C
|
SQL.Query: SQL injection,lib/aprsme_web/live/info_live/show.ex:505,515E82C
|
||||||
SQL.Query: SQL injection,lib/aprsme_web/live/info_live/show.ex:619,53BB748
|
SQL.Query: SQL injection,lib/aprsme_web/live/info_live/show.ex:619,53BB748
|
||||||
XSS.Raw: XSS,lib/aprsme_web/live/info_live/show.ex:693,EEA0E3
|
XSS.Raw: XSS,lib/aprsme_web/live/info_live/show.ex:693,EEA0E3
|
||||||
|
SQL.Query: SQL injection,lib/aprsme/packets.ex:664,17532E
|
||||||
|
XSS.Raw: XSS,lib/aprsme_web/components/core_components.ex:48,1E00DD8
|
||||||
|
SQL.Query: SQL injection,lib/aprsme_web/live/info_live/show.ex:603,52B452D
|
||||||
|
XSS.Raw: XSS,lib/aprsme_web/live/info_live/show.ex:661,5C70BB5
|
||||||
|
XSS.Raw: XSS,lib/aprsme_web/live/info_live/show.ex:643,692A7EC
|
||||||
|
|
@ -123,14 +123,7 @@ defmodule Aprsme.StreamingPacketsPubSub do
|
||||||
subscribers
|
subscribers
|
||||||
|> Stream.filter(fn {_pid, bounds} -> packet_in_bounds?(lat, lon, bounds) end)
|
|> Stream.filter(fn {_pid, bounds} -> packet_in_bounds?(lat, lon, bounds) end)
|
||||||
|> Enum.reduce([], fn {pid, _bounds}, acc ->
|
|> Enum.reduce([], fn {pid, _bounds}, acc ->
|
||||||
# Only send if process is alive
|
send_to_subscriber_if_alive(pid, packet, acc)
|
||||||
if Process.alive?(pid) do
|
|
||||||
send(pid, {:streaming_packet, packet})
|
|
||||||
acc
|
|
||||||
else
|
|
||||||
# Collect dead pid for cleanup
|
|
||||||
[pid | acc]
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
# Send dead pids back to GenServer for cleanup
|
# Send dead pids back to GenServer for cleanup
|
||||||
|
|
@ -188,4 +181,14 @@ defmodule Aprsme.StreamingPacketsPubSub do
|
||||||
|
|
||||||
lat_in_bounds and lon_in_bounds
|
lat_in_bounds and lon_in_bounds
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp send_to_subscriber_if_alive(pid, packet, acc) do
|
||||||
|
if Process.alive?(pid) do
|
||||||
|
send(pid, {:streaming_packet, packet})
|
||||||
|
acc
|
||||||
|
else
|
||||||
|
# Collect dead pid for cleanup
|
||||||
|
[pid | acc]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,7 @@ defmodule AprsmeWeb.AprsSymbol do
|
||||||
sprite_file = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png"
|
sprite_file = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png"
|
||||||
|
|
||||||
# Get symbol position using ASCII-based calculation
|
# Get symbol position using ASCII-based calculation
|
||||||
symbol_code_ord =
|
symbol_code_ord = get_symbol_code_ord(symbol_code)
|
||||||
symbol_code
|
|
||||||
|> String.to_charlist()
|
|
||||||
|> List.first()
|
|
||||||
|> then(fn c -> if is_integer(c), do: c, else: 63 end)
|
|
||||||
|
|
||||||
index = symbol_code_ord - 33
|
index = symbol_code_ord - 33
|
||||||
safe_index = max(0, min(index, 93))
|
safe_index = max(0, min(index, 93))
|
||||||
|
|
@ -369,4 +365,9 @@ defmodule AprsmeWeb.AprsSymbol do
|
||||||
Map.get(data_extended, to_string(field)) ||
|
Map.get(data_extended, to_string(field)) ||
|
||||||
default
|
default
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_symbol_code_ord(symbol_code) do
|
||||||
|
c = symbol_code |> String.to_charlist() |> List.first()
|
||||||
|
if is_integer(c), do: c, else: 63
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -125,19 +125,7 @@ defmodule AprsmeWeb.MobileChannel do
|
||||||
# Validate bounds
|
# Validate bounds
|
||||||
case validate_bounds(bounds) do
|
case validate_bounds(bounds) do
|
||||||
:ok ->
|
:ok ->
|
||||||
# Unsubscribe from old bounds
|
update_subscription_bounds(socket, bounds)
|
||||||
if socket.assigns[:bounds] do
|
|
||||||
Aprsme.StreamingPacketsPubSub.unsubscribe(self())
|
|
||||||
end
|
|
||||||
|
|
||||||
# Subscribe to new bounds
|
|
||||||
Aprsme.StreamingPacketsPubSub.subscribe_to_bounds(self(), bounds)
|
|
||||||
|
|
||||||
socket = assign(socket, :bounds, bounds)
|
|
||||||
|
|
||||||
Logger.debug("Mobile client #{socket.assigns.client_id} updated bounds: #{inspect(bounds)}")
|
|
||||||
|
|
||||||
{:reply, {:ok, %{bounds: bounds, message: "Bounds updated"}}, socket}
|
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
{:reply, {:error, %{message: reason}}, socket}
|
{:reply, {:error, %{message: reason}}, socket}
|
||||||
|
|
@ -501,4 +489,20 @@ defmodule AprsmeWeb.MobileChannel do
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp update_subscription_bounds(socket, bounds) do
|
||||||
|
# Unsubscribe from old bounds if they exist
|
||||||
|
if socket.assigns[:bounds] do
|
||||||
|
Aprsme.StreamingPacketsPubSub.unsubscribe(self())
|
||||||
|
end
|
||||||
|
|
||||||
|
# Subscribe to new bounds
|
||||||
|
Aprsme.StreamingPacketsPubSub.subscribe_to_bounds(self(), bounds)
|
||||||
|
|
||||||
|
socket = assign(socket, :bounds, bounds)
|
||||||
|
|
||||||
|
Logger.debug("Mobile client #{socket.assigns.client_id} updated bounds: #{inspect(bounds)}")
|
||||||
|
|
||||||
|
{:reply, {:ok, %{bounds: bounds, message: "Bounds updated"}}, socket}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,7 @@ defmodule AprsmeWeb.CoreComponents do
|
||||||
{:ok, contents} ->
|
{:ok, contents} ->
|
||||||
# Insert class attribute if not present
|
# Insert class attribute if not present
|
||||||
Regex.replace(~r/<svg([^>]*?)>/, contents, fn _, attrs ->
|
Regex.replace(~r/<svg([^>]*?)>/, contents, fn _, attrs ->
|
||||||
if String.contains?(attrs, "class=") do
|
add_class_to_svg_tag(attrs, class)
|
||||||
"<svg#{attrs}>"
|
|
||||||
else
|
|
||||||
"<svg class=\"#{class}\"#{attrs}>"
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
|
@ -822,4 +818,12 @@ defmodule AprsmeWeb.CoreComponents do
|
||||||
<% end %>
|
<% end %>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp add_class_to_svg_tag(attrs, class) do
|
||||||
|
if String.contains?(attrs, "class=") do
|
||||||
|
"<svg#{attrs}>"
|
||||||
|
else
|
||||||
|
"<svg class=\"#{class}\"#{attrs}>"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -505,23 +505,7 @@ defmodule AprsmeWeb.InfoLive.Show do
|
||||||
case Repo.query(query, [callsign, one_month_ago]) do
|
case Repo.query(query, [callsign, one_month_ago]) do
|
||||||
{:ok, result} ->
|
{:ok, result} ->
|
||||||
result.rows
|
result.rows
|
||||||
|> Enum.map(fn row ->
|
|> Enum.map(fn row -> map_digipeater_row(row, locale) end)
|
||||||
case row do
|
|
||||||
[digipeater, first_heard, last_heard, packet_count, longest_path_time, longest_distance_km] ->
|
|
||||||
%{
|
|
||||||
digipeater: digipeater || "",
|
|
||||||
first_heard: first_heard,
|
|
||||||
last_heard: last_heard,
|
|
||||||
packet_count: packet_count || 0,
|
|
||||||
longest_distance_km: longest_distance_km,
|
|
||||||
longest_distance: if(longest_distance_km, do: format_distance(longest_distance_km, locale)),
|
|
||||||
longest_path_time: longest_path_time
|
|
||||||
}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
|
|
@ -619,23 +603,7 @@ defmodule AprsmeWeb.InfoLive.Show do
|
||||||
case Repo.query(query, [callsign, one_month_ago]) do
|
case Repo.query(query, [callsign, one_month_ago]) do
|
||||||
{:ok, result} ->
|
{:ok, result} ->
|
||||||
result.rows
|
result.rows
|
||||||
|> Enum.map(fn row ->
|
|> Enum.map(fn row -> map_station_heard_row(row, locale) end)
|
||||||
case row do
|
|
||||||
[station, first_heard, last_heard, packet_count, longest_path_time, longest_distance_km] ->
|
|
||||||
%{
|
|
||||||
station: station || "",
|
|
||||||
first_heard: first_heard,
|
|
||||||
last_heard: last_heard,
|
|
||||||
packet_count: packet_count || 0,
|
|
||||||
longest_distance_km: longest_distance_km,
|
|
||||||
longest_distance: if(longest_distance_km, do: format_distance(longest_distance_km, locale)),
|
|
||||||
longest_path_time: longest_path_time
|
|
||||||
}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
|
|
@ -811,4 +779,40 @@ defmodule AprsmeWeb.InfoLive.Show do
|
||||||
defp decode_tcpip_element("TCPIP"), do: gettext("TCPIP (Internet gateway)")
|
defp decode_tcpip_element("TCPIP"), do: gettext("TCPIP (Internet gateway)")
|
||||||
defp decode_tcpip_element("TCPIP*"), do: gettext("TCPIP* (Internet gateway, no forward)")
|
defp decode_tcpip_element("TCPIP*"), do: gettext("TCPIP* (Internet gateway, no forward)")
|
||||||
defp decode_tcpip_element(element), do: gettext("TCPIP gateway (%{element})", element: element)
|
defp decode_tcpip_element(element), do: gettext("TCPIP gateway (%{element})", element: element)
|
||||||
|
|
||||||
|
defp map_digipeater_row(row, locale) do
|
||||||
|
case row do
|
||||||
|
[digipeater, first_heard, last_heard, packet_count, longest_path_time, longest_distance_km] ->
|
||||||
|
%{
|
||||||
|
digipeater: digipeater || "",
|
||||||
|
first_heard: first_heard,
|
||||||
|
last_heard: last_heard,
|
||||||
|
packet_count: packet_count || 0,
|
||||||
|
longest_distance_km: longest_distance_km,
|
||||||
|
longest_distance: if(longest_distance_km, do: format_distance(longest_distance_km, locale)),
|
||||||
|
longest_path_time: longest_path_time
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp map_station_heard_row(row, locale) do
|
||||||
|
case row do
|
||||||
|
[station, first_heard, last_heard, packet_count, longest_path_time, longest_distance_km] ->
|
||||||
|
%{
|
||||||
|
station: station || "",
|
||||||
|
first_heard: first_heard,
|
||||||
|
last_heard: last_heard,
|
||||||
|
packet_count: packet_count || 0,
|
||||||
|
longest_distance_km: longest_distance_km,
|
||||||
|
longest_distance: if(longest_distance_km, do: format_distance(longest_distance_km, locale)),
|
||||||
|
longest_path_time: longest_path_time
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -181,30 +181,7 @@ defmodule AprsmeWeb.MapLive.DataBuilder do
|
||||||
|
|
||||||
# Filter historical packets that are too close to most recent position
|
# Filter historical packets that are too close to most recent position
|
||||||
filtered_historical =
|
filtered_historical =
|
||||||
if most_recent_lat && most_recent_lon do
|
filter_historical_by_distance(historical, most_recent_lat, most_recent_lon)
|
||||||
Enum.filter(historical, fn packet ->
|
|
||||||
{lat, lon, _} = get_coordinates(packet)
|
|
||||||
|
|
||||||
if lat && lon do
|
|
||||||
distance_meters =
|
|
||||||
CoordinateUtils.calculate_distance_meters(
|
|
||||||
most_recent_lat,
|
|
||||||
most_recent_lon,
|
|
||||||
lat,
|
|
||||||
lon
|
|
||||||
)
|
|
||||||
|
|
||||||
# Only show if 10+ meters away
|
|
||||||
distance_meters >= 10.0
|
|
||||||
else
|
|
||||||
# Skip packets without coordinates
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
# If most recent has no coordinates, include all historical
|
|
||||||
historical
|
|
||||||
end
|
|
||||||
|
|
||||||
# Build data for remaining historical packets
|
# Build data for remaining historical packets
|
||||||
historical_data =
|
historical_data =
|
||||||
|
|
@ -620,4 +597,35 @@ defmodule AprsmeWeb.MapLive.DataBuilder do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp convert_rain(value, _locale), do: {value, "in"}
|
defp convert_rain(value, _locale), do: {value, "in"}
|
||||||
|
|
||||||
|
defp filter_historical_by_distance(historical, most_recent_lat, most_recent_lon) do
|
||||||
|
if most_recent_lat && most_recent_lon do
|
||||||
|
Enum.filter(historical, fn packet ->
|
||||||
|
packet_far_enough_from_most_recent?(packet, most_recent_lat, most_recent_lon)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
# If most recent has no coordinates, include all historical
|
||||||
|
historical
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp packet_far_enough_from_most_recent?(packet, most_recent_lat, most_recent_lon) do
|
||||||
|
{lat, lon, _} = get_coordinates(packet)
|
||||||
|
|
||||||
|
if lat && lon do
|
||||||
|
distance_meters =
|
||||||
|
CoordinateUtils.calculate_distance_meters(
|
||||||
|
most_recent_lat,
|
||||||
|
most_recent_lon,
|
||||||
|
lat,
|
||||||
|
lon
|
||||||
|
)
|
||||||
|
|
||||||
|
# Only show if 10+ meters away
|
||||||
|
distance_meters >= 10.0
|
||||||
|
else
|
||||||
|
# Skip packets without coordinates
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue