diff --git a/CHANGELOG.md b/CHANGELOG.md index 81b51c9..2bf7c1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Fixes and improvements +- Fix form submission crash for anonymous attendees - Improve SMTP config and handling (#197) - Fix presentation slides URL (#200) - Fix custom S3 endpoint (#199) diff --git a/lib/claper/forms.ex b/lib/claper/forms.ex index f05daf0..2ec8931 100644 --- a/lib/claper/forms.ex +++ b/lib/claper/forms.ex @@ -324,6 +324,9 @@ defmodule Claper.Forms do nil -> broadcast({:ok, r, event_uuid}, :form_submit_created) _form_submit -> broadcast({:ok, r, event_uuid}, :form_submit_updated) end + + {:error, changeset} -> + {:error, changeset} end end @@ -344,6 +347,7 @@ defmodule Claper.Forms do |> Repo.delete() |> case do {:ok, r} -> broadcast({:ok, r, event_uuid}, :form_submit_deleted) + {:error, changeset} -> {:error, changeset} end end diff --git a/lib/claper/forms/form_submit.ex b/lib/claper/forms/form_submit.ex index f0c490f..3570e8d 100644 --- a/lib/claper/forms/form_submit.ex +++ b/lib/claper/forms/form_submit.ex @@ -25,6 +25,18 @@ defmodule Claper.Forms.FormSubmit do def changeset(form_submit, attrs) do form_submit |> cast(attrs, [:attendee_identifier, :user_id, :form_id, :response]) - |> validate_required([:form_id, :user_id, :response]) + |> validate_required([:form_id, :response]) + |> validate_user_or_attendee() + end + + defp validate_user_or_attendee(changeset) do + user_id = get_field(changeset, :user_id) + attendee_identifier = get_field(changeset, :attendee_identifier) + + if is_nil(user_id) and is_nil(attendee_identifier) do + add_error(changeset, :user_id, "either user_id or attendee_identifier must be present") + else + changeset + end end end diff --git a/lib/claper_web/live/event_live/form_component.ex b/lib/claper_web/live/event_live/form_component.ex index e70ac45..b601e45 100644 --- a/lib/claper_web/live/event_live/form_component.ex +++ b/lib/claper_web/live/event_live/form_component.ex @@ -148,6 +148,9 @@ defmodule ClaperWeb.EventLive.FormComponent do {:noreply, socket |> assign(:current_form_submit, form_submit)} + + {:error, _changeset} -> + {:noreply, socket} end end @@ -167,6 +170,9 @@ defmodule ClaperWeb.EventLive.FormComponent do {:noreply, socket |> assign(:current_form_submit, form_submit)} + + {:error, _changeset} -> + {:noreply, socket} end end diff --git a/test/claper/forms_test.exs b/test/claper/forms_test.exs index 5a299b2..63f1ccb 100644 --- a/test/claper/forms_test.exs +++ b/test/claper/forms_test.exs @@ -126,5 +126,62 @@ defmodule Claper.FormsTest do } ) end + + test "create_or_update_form_submit/2 with attendee_identifier creates a form_submit" do + presentation_file = presentation_file_fixture(%{}, [:event]) + f = form_fixture(%{presentation_file_id: presentation_file.id}) + + assert {:ok, %Claper.Forms.FormSubmit{} = form_submit} = + Forms.create_or_update_form_submit( + presentation_file.event.uuid, + %{ + "attendee_identifier" => "test-attendee-123", + "form_id" => f.id, + "response" => %{"Name" => "Daniel"} + } + ) + + assert form_submit.attendee_identifier == "test-attendee-123" + assert is_nil(form_submit.user_id) + assert form_submit.form_id == f.id + end + + test "create_or_update_form_submit/2 with attendee_identifier updates existing form_submit" do + presentation_file = presentation_file_fixture(%{}, [:event]) + f = form_fixture(%{presentation_file_id: presentation_file.id}) + + {:ok, _first_submit} = + Forms.create_or_update_form_submit( + presentation_file.event.uuid, + %{ + "attendee_identifier" => "test-attendee-123", + "form_id" => f.id, + "response" => %{"Name" => "Daniel"} + } + ) + + assert {:ok, %Claper.Forms.FormSubmit{} = updated_submit} = + Forms.create_or_update_form_submit( + presentation_file.event.uuid, + %{ + "attendee_identifier" => "test-attendee-123", + "form_id" => f.id, + "response" => %{"Name" => "Updated Name"} + } + ) + + assert updated_submit.response == %{"Name" => "Updated Name"} + end + + test "create_or_update_form_submit/2 without user_id or attendee_identifier returns error" do + presentation_file = presentation_file_fixture(%{}, [:event]) + f = form_fixture(%{presentation_file_id: presentation_file.id}) + + assert {:error, %Ecto.Changeset{}} = + Forms.create_form_submit(%{ + form_id: f.id, + response: %{"Name" => "Daniel"} + }) + end end end