Skip to content

fix: POST /user must link to an existing Person by email instead of creating a duplicate #923

Description

@arturasmckwcz

Why

Follow-up from the epic #922 and
from review of need4deed-org/fe#955 (volunteer
self-registration, closes need4deed-org/fe#954).

POST /user (src/server/routes/user.ts, ~lines 293-350) only looks up an
existing Person when the request body explicitly passes person.id.
When person.id is omitted it unconditionally does new Person(personData)
— even when a Person with that exact email already exists, e.g. via an
existing Volunteer row created through the legacy public form.

This directly undermines the point of this epic: after we invite today's
Volunteer backlog to link up with real accounts (#920 / #921), anyone who
instead self-registers straight through /register/volunteer (fe#955) can
still create a brand-new, disconnected Person — splitting one human across
an orphaned Volunteer profile and a separate fresh account, with nothing
surfacing the collision to them or to a coordinator.

Scope

  • When POST /user's body omits person.id, look up an existing Person
    by the account email (case-insensitively) before falling through to
    new Person(personData).
  • If found, link the new User to that existing Person — mirror the
    person.id branch's "backfill the email only if the person had none,
    never overwrite" semantics — instead of creating a duplicate.
  • Decide the collision-handling behavior during TODO review: if the matched
    Person already has a User (of any role), does registration get
    rejected (409, mirroring the existing email-uniqueness ConflictError)
    or is a second User role allowed against the same Person? Default to
    the conservative option — reject and point the person at login/support —
    unless there's a concrete case for allowing multiple roles per person.
  • Applies to every self-registration entry point that hits POST /user
    without a person.id (today: agent registration, and now volunteer
    registration from fe#955) — fix once, in the shared route, not per-flow.

Acceptance criteria

  • Self-registering with an email that already has a Person (e.g. from
    an existing Volunteer row) links to that Person instead of
    creating a duplicate
  • Behavior for an email whose matched Person already has a User (any
    role) is explicit and tested, not accidental
  • Existing agent-registration flow is unaffected for genuinely new
    emails

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions