Fix callsign registration to be case-insensitive

Users could register duplicate callsigns with different casing (e.g.,
"w1aw" and "W1AW") because the database unique index was case-sensitive.
Additionally, live validation showed false "already taken" errors on
every keystroke.

Changes:
- Add case-insensitive unique index using lower(callsign)
- Skip callsign uniqueness validation during live form changes
- Add test verifying case-insensitive uniqueness enforcement
This commit is contained in:
Graham McIntire 2026-02-19 13:19:58 -06:00
parent e5659e889f
commit b4f85bf12c
No known key found for this signature in database
3 changed files with 32 additions and 1 deletions

View file

@ -103,7 +103,7 @@ defmodule Aprsme.Accounts do
"""
def change_user_registration(%User{} = user, attrs \\ %{}) do
User.registration_changeset(user, attrs, hash_password: false, validate_email: false)
User.registration_changeset(user, attrs, hash_password: false, validate_email: false, validate_callsign: false)
end
## Settings

View file

@ -0,0 +1,11 @@
defmodule Aprsme.Repo.Migrations.MakeCallsignCaseInsensitive do
use Ecto.Migration
def change do
# Drop the existing case-sensitive unique index
drop unique_index(:users, [:callsign])
# Create a case-insensitive unique index using LOWER()
create unique_index(:users, ["lower(callsign)"], name: :users_callsign_lower_index)
end
end

View file

@ -69,6 +69,26 @@ defmodule AprsmeWeb.UserRegistrationLiveTest do
assert result =~ "has already been taken"
end
test "renders errors for duplicated callsign (case-insensitive)", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/users/register", on_error: :warn)
_user = user_fixture(%{callsign: "W1AW"})
# Try to register with same callsign in different case
result =
lv
|> form("#registration_form",
user: %{
"email" => unique_user_email(),
"callsign" => "w1aw",
"password" => "valid_password123"
}
)
|> render_submit()
assert result =~ "has already been taken"
end
end
describe "registration navigation" do