- Beacon detail endpoints (LiveView + REST API) now hide unapproved beacons from anonymous and unauthorized viewers; only the submitter and admins can see pending records before approval. Adds Beacons.get_visible_beacon/2 with scope-aware checks. - API contact pagination now honors per_page end-to-end. Radio.list_contacts/1 accepts :per_page and clamps to 200. - API rate limiter: ETS table is now owned by a long-lived Sweeper GenServer (won't die with a request task); Sweeper periodically prunes expired-window rows to bound memory; init_table/0 race is rescued. - /scores/cells and /weather/cells: add per-IP rate limiting and a shared GridBounds clamp/413 guard so global / oversized viewports no longer drive unbounded binary responses. - NEXRAD PNG unfilter (sub/up/average/paeth): replace acc++[byte] + Enum.at(acc, idx-bpp) with O(n) binary recursion. Decode time for the 12200x5400 n0q frame goes from quadratic to linear. - LiveTableFooter.parse_page and ScoresFile.fetch_bound: switch String.to_integer/String.to_float to Integer.parse/Float.parse, fall back to defaults instead of raising. - PathLive and MapLive band-event handlers: replace String.to_integer(params["band"]) with parse_int / parse_band_param so a non-numeric band parameter no longer crashes the LiveView.
46 lines
1.3 KiB
Elixir
46 lines
1.3 KiB
Elixir
defmodule MicrowavepropWeb.Api.V1.BeaconController do
|
|
@moduledoc "Read approved beacons; submit new beacons (pending approval)."
|
|
|
|
use Phoenix.Controller, formats: [:json]
|
|
|
|
alias Microwaveprop.Beacons
|
|
alias MicrowavepropWeb.Api.ErrorJSON
|
|
alias MicrowavepropWeb.Api.V1.BeaconJSON
|
|
|
|
plug :accepts, ["json"]
|
|
action_fallback MicrowavepropWeb.Api.FallbackController
|
|
|
|
def index(conn, _params) do
|
|
beacons = Beacons.list_beacons()
|
|
json(conn, BeaconJSON.index(%{beacons: beacons}))
|
|
end
|
|
|
|
def show(conn, %{"id" => id}) do
|
|
viewer = conn.assigns[:current_api_user]
|
|
|
|
case Beacons.get_visible_beacon(id, viewer) do
|
|
nil -> ErrorJSON.send_problem(conn, 404, "not_found", "Beacon not found.")
|
|
beacon -> json(conn, BeaconJSON.show(%{beacon: beacon}))
|
|
end
|
|
end
|
|
|
|
def create(conn, params) do
|
|
user = conn.assigns.current_api_user
|
|
|
|
attrs =
|
|
Map.take(
|
|
params,
|
|
~w(frequency_mhz callsign grid lat lon power_mw height_ft on_the_air keying bearing beamwidth_deg notes)
|
|
)
|
|
|
|
case Beacons.create_beacon(user, attrs) do
|
|
{:ok, beacon} ->
|
|
conn
|
|
|> put_status(:created)
|
|
|> json(BeaconJSON.show(%{beacon: beacon}))
|
|
|
|
{:error, changeset} ->
|
|
ErrorJSON.send_changeset(conn, changeset)
|
|
end
|
|
end
|
|
end
|