diff --git a/lib/microwaveprop/radio/contact.ex b/lib/microwaveprop/radio/contact.ex index f5b2f570..0ff612e7 100644 --- a/lib/microwaveprop/radio/contact.ex +++ b/lib/microwaveprop/radio/contact.ex @@ -39,13 +39,14 @@ defmodule Microwaveprop.Radio.Contact do field :user_submitted, :boolean, default: false field :submitter_email, :string + field :user_id, :binary_id field :flagged_invalid, :boolean, default: false timestamps(type: :utc_datetime) end @required_fields ~w(station1 station2 qso_timestamp mode band)a - @optional_fields ~w(grid1 grid2 pos1 pos2 distance_km)a + @optional_fields ~w(grid1 grid2 pos1 pos2 distance_km user_id)a def changeset(contact, attrs) do contact @@ -53,14 +54,16 @@ defmodule Microwaveprop.Radio.Contact do |> validate_required(@required_fields) end - @submission_fields ~w(station1 station2 qso_timestamp mode band grid1 grid2 submitter_email)a + @submission_fields ~w(station1 station2 qso_timestamp mode band grid1 grid2 submitter_email user_id)a + @submission_required ~w(station1 station2 qso_timestamp mode band grid1 grid2)a @allowed_modes ~w(CW SSB FM FT8 FT4) @allowed_bands Enum.map(~w(1296 2304 3456 5760 10000 24000 47000 68000 75000 122000 134000 241000), &Decimal.new/1) def submission_changeset(contact, attrs) do contact |> cast(attrs, @submission_fields) - |> validate_required(@submission_fields) + |> validate_required(@submission_required) + |> validate_user_or_email() |> sanitize_callsign(:station1) |> sanitize_callsign(:station2) |> sanitize_grid(:grid1) @@ -71,12 +74,33 @@ defmodule Microwaveprop.Radio.Contact do |> validate_grid_format(:grid2) |> validate_inclusion(:mode, @allowed_modes) |> validate_inclusion(:band, @allowed_bands) - |> validate_format(:submitter_email, ~r/^[^\s<>]+@[^\s<>]+\.[^\s<>]+$/) + |> validate_email_format() |> validate_length(:submitter_email, max: 254) |> validate_length(:station1, max: 20) |> validate_length(:station2, max: 20) end + # Either a user_id (logged-in submitter) or a submitter_email (anonymous) + # must be present so we know who submitted the contact. + defp validate_user_or_email(changeset) do + user_id = get_field(changeset, :user_id) + email = get_field(changeset, :submitter_email) + + if user_id || (email && email != "") do + changeset + else + add_error(changeset, :submitter_email, "can't be blank") + end + end + + defp validate_email_format(changeset) do + case get_field(changeset, :submitter_email) do + nil -> changeset + "" -> changeset + _email -> validate_format(changeset, :submitter_email, ~r/^[^\s<>]+@[^\s<>]+\.[^\s<>]+$/) + end + end + # Strip whitespace and upcase callsigns defp sanitize_callsign(changeset, field) do case get_change(changeset, field) do diff --git a/lib/microwaveprop_web/live/submit_live.ex b/lib/microwaveprop_web/live/submit_live.ex index a09ba88e..6d566046 100644 --- a/lib/microwaveprop_web/live/submit_live.ex +++ b/lib/microwaveprop_web/live/submit_live.ex @@ -66,6 +66,8 @@ defmodule MicrowavepropWeb.SubmitLive do if recently_submitted?(socket) do {:noreply, put_flash(socket, :error, "Please wait before submitting another contact.")} else + contact_params = merge_user_params(contact_params, socket) + case Radio.create_contact(contact_params) do {:ok, contact} -> ContactWeatherEnqueueWorker.enqueue_for_contact(contact) @@ -82,8 +84,14 @@ defmodule MicrowavepropWeb.SubmitLive do end end - def handle_event("upload_csv", %{"submitter_email" => email}, socket) do - if String.trim(email) == "" do + def handle_event("upload_csv", params, socket) do + email = + case current_user(socket.assigns) do + %{email: user_email} -> user_email + _ -> params |> Map.get("submitter_email", "") |> String.trim() + end + + if email == "" do {:noreply, put_flash(socket, :error, "Email is required for CSV upload")} else uploaded_contents = @@ -144,6 +152,18 @@ defmodule MicrowavepropWeb.SubmitLive do end end + defp merge_user_params(params, socket) do + case current_user(socket.assigns) do + %{id: user_id, email: user_email} -> + params + |> Map.put("user_id", user_id) + |> Map.put("submitter_email", user_email) + + _ -> + params + end + end + @impl true def render(assigns) do ~H""" @@ -156,10 +176,10 @@ defmodule MicrowavepropWeb.SubmitLive do
Every contact matters
- Our propagation model improves with real-world data. Each verified microwave contact + Our propagation model improves with real-world data. Each verified contact you submit is matched against atmospheric conditions at the time of your contact, - helping us calibrate predictions for all bands from 10 GHz to 241 GHz. The more contacts - we have, the better our forecasts get for everyone. + helping us calibrate predictions for all amateur bands from 902 MHz and up. The + more contacts we have, the better our forecasts get for everyone.