Merge pull request 'add public join form' (#466) from feature/308-web-form into main
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #466
This commit is contained in:
simon 2026-03-10 23:08:26 +01:00
commit f79c9ac515
26 changed files with 795 additions and 12 deletions

View file

@ -38,6 +38,21 @@ defmodule Mv.Membership.JoinRequestTest do
end
test "persists first_name, last_name and form_data when provided" do
# Allowlist must include custom fields so FilterFormDataByAllowlist persists them
{:ok, settings} = Membership.get_settings()
Mv.Membership.update_settings(settings, %{
join_form_enabled: true,
join_form_field_ids: ["email", "first_name", "last_name", "city", "notes"],
join_form_field_required: %{
"email" => true,
"first_name" => false,
"last_name" => false,
"city" => false,
"notes" => false
}
})
attrs =
@valid_submit_attrs
|> Map.put(:confirmation_token, "token-#{System.unique_integer([:positive])}")
@ -121,6 +136,33 @@ defmodule Mv.Membership.JoinRequestTest do
end
end
describe "allowlist (server-side field filter)" do
test "submit with non-allowlisted form_data keys does not persist those keys" do
# Allowlist restricts which fields are accepted; extra keys must not be stored.
{:ok, settings} = Membership.get_settings()
Mv.Membership.update_settings(settings, %{
join_form_enabled: true,
join_form_field_ids: ["email", "first_name", "city"],
join_form_field_required: %{"email" => true, "first_name" => false, "city" => false}
})
attrs = %{
email: "allowlist#{System.unique_integer([:positive])}@example.com",
first_name: "Allowed",
confirmation_token: "tok-#{System.unique_integer([:positive])}",
form_data: %{"city" => "Berlin", "internal_or_secret" => "must not persist"},
schema_version: 1
}
assert {:ok, request} = Membership.submit_join_request(attrs, actor: nil)
assert request.email == attrs.email
assert request.first_name == attrs.first_name
refute Map.has_key?(request.form_data || %{}, "internal_or_secret")
assert (request.form_data || %{})["city"] == "Berlin"
end
end
defp error_message(errors, field) do
errors
|> Enum.filter(fn err -> Map.get(err, :field) == field end)