Fix three security issues
1. Prevent user_id impersonation in contact submissions - Remove user_id from submission_changeset cast fields - Pass user_id as a separate server-side argument to create_contact/2 - Client form params can no longer forge account-linked contacts 2. Restrict flag toggle to admins only - Add admin? guard to toggle_flag event handler - Hide flag button from non-admin users in template 3. Reset enrichment on timestamp edits - Add qso_timestamp to the fields that trigger enrichment reset - Prevents stale weather/HRRR/IEMRE data after time changes
This commit is contained in:
parent
361a302736
commit
dd13a5f2a5
4 changed files with 25 additions and 15 deletions
|
|
@ -387,10 +387,13 @@ defmodule Microwaveprop.Radio do
|
|||
|
||||
@dedup_window_seconds 3600
|
||||
|
||||
@spec create_contact(map()) ::
|
||||
@spec create_contact(map(), String.t() | nil) ::
|
||||
{:ok, Contact.t()} | {:error, Ecto.Changeset.t()} | {:error, :duplicate, Contact.t()}
|
||||
def create_contact(attrs) do
|
||||
changeset = Contact.submission_changeset(%Contact{}, attrs)
|
||||
def create_contact(attrs, user_id \\ nil) do
|
||||
changeset =
|
||||
%Contact{}
|
||||
|> Contact.submission_changeset(attrs)
|
||||
|> maybe_put_user_id(user_id)
|
||||
|
||||
if changeset.valid? do
|
||||
insert_validated_contact(changeset)
|
||||
|
|
@ -399,6 +402,9 @@ defmodule Microwaveprop.Radio do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_put_user_id(changeset, nil), do: changeset
|
||||
defp maybe_put_user_id(changeset, user_id), do: Ecto.Changeset.put_change(changeset, :user_id, user_id)
|
||||
|
||||
defp insert_validated_contact(changeset) do
|
||||
if existing = find_duplicate_contact(changeset) do
|
||||
{:error, :duplicate, existing}
|
||||
|
|
@ -632,12 +638,13 @@ defmodule Microwaveprop.Radio do
|
|||
end
|
||||
|
||||
defp maybe_recompute_positions(changes, contact, proposed) do
|
||||
grids_or_band_changed =
|
||||
needs_recompute =
|
||||
Map.has_key?(proposed, "grid1") or
|
||||
Map.has_key?(proposed, "grid2") or
|
||||
Map.has_key?(proposed, "band")
|
||||
Map.has_key?(proposed, "band") or
|
||||
Map.has_key?(proposed, "qso_timestamp")
|
||||
|
||||
if grids_or_band_changed do
|
||||
if needs_recompute do
|
||||
recompute_positions(changes, contact, proposed)
|
||||
else
|
||||
changes
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ defmodule Microwaveprop.Radio.Contact do
|
|||
|> validate_required(@required_fields)
|
||||
end
|
||||
|
||||
@submission_fields ~w(station1 station2 qso_timestamp mode band grid1 grid2 submitter_email user_id)a
|
||||
@submission_fields ~w(station1 station2 qso_timestamp mode band grid1 grid2 submitter_email)a
|
||||
@submission_required ~w(station1 station2 qso_timestamp mode band grid1 grid2)a
|
||||
@allowed_modes ~w(CW SSB FM FT8 FT4 Q65)
|
||||
@allowed_bands Enum.map(~w(1296 2304 3456 5760 10000 24000 47000 68000 75000 122000 134000 241000), &Decimal.new/1)
|
||||
|
|
|
|||
|
|
@ -122,8 +122,12 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
end
|
||||
|
||||
def handle_event("toggle_flag", _params, socket) do
|
||||
contact = Radio.toggle_flagged_invalid!(socket.assigns.contact)
|
||||
{:noreply, assign(socket, contact: contact)}
|
||||
if admin?(socket.assigns.current_scope) do
|
||||
contact = Radio.toggle_flagged_invalid!(socket.assigns.contact)
|
||||
{:noreply, assign(socket, contact: contact)}
|
||||
else
|
||||
{:noreply, put_flash(socket, :error, "Admins only.")}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_event("toggle_profile", %{"id" => id}, socket) do
|
||||
|
|
@ -575,6 +579,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
</button>
|
||||
<% end %>
|
||||
<button
|
||||
:if={admin?(assigns)}
|
||||
phx-click="toggle_flag"
|
||||
class={[
|
||||
"btn btn-sm",
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@ 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)
|
||||
{contact_params, user_id} = merge_user_params(contact_params, socket)
|
||||
|
||||
case Radio.create_contact(contact_params) do
|
||||
case Radio.create_contact(contact_params, user_id) do
|
||||
{:ok, contact} ->
|
||||
ContactWeatherEnqueueWorker.enqueue_for_contact(contact)
|
||||
|
||||
|
|
@ -217,12 +217,10 @@ defmodule MicrowavepropWeb.SubmitLive do
|
|||
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)
|
||||
{Map.put(params, "submitter_email", user_email), user_id}
|
||||
|
||||
_ ->
|
||||
params
|
||||
{params, nil}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue