Skip to content

A program host can accept multiple invitations to the same program, overwriting the earlier involvement. #1084

Description

@japsu

The same person can accept several invitations to the same program, and nothing in the code prevents it.

  • Evidence: the update_or_create key in Involvement.from_accepted_invitation, the lack of any uniqueness or "already a host" check in invite_program_host and AcceptInvitation, and the offerer case above (the role changes and the offer response is lost).
  • Suggested direction:
    • Reject or deduplicate invitations to someone who is already a host, or accept an invitation only from a matching email.
    • Make acceptance idempotent or an explicit edit.
    • When it is fixed, also clear stale propagated annotations.

Why nothing stops it

  • Program.invite_program_host creates an Invitation with no check for an existing invitation or host with the same email or person.
  • AcceptInvitation only checks that this one invitation hasn't been used. It doesn't check that the accepting user's email matches the invitation's.
  • Involvement has no unique constraint. from_accepted_invitation uses update_or_create on (universe, person, app, type, program).

What happens

  • Same guest accepts two invitations to one program: you get one involvement, not two. The second acceptance overwrites its response and invitation, so the first response is no longer reachable from program.responses. That property is built from the involvements' current responses.
  • The offerer accepts an invitation to their own program: their existing host involvement is overwritten. Its response changes from the program offer to the invite response, invitation is set, and program_host_role flips from OFFERER to INVITED. The offer response disappears from program.responses, so the program's own offer data stops feeding annotation extraction.
  • The same-guest case needs two invitations to the same person, for example the host being invited twice or from two email addresses. The offerer case needs only an invitation sent to the offerer's own address.

Discovered during review of #1080

Review comment: #1080 (comment)

It is valid only because of this behaviour, or when from_involvement re-runs from_accepted_invitation. On a first acceptance there is nothing stale. {**involvement.annotations, **passed_forward_annotations} leaves a key from the first response in place when the second response has no value for it, or has a value that fails validation. The fix would be small: drop the annotation slugs that the survey's fields propagate to, then merge the new ones, so unrelated keys stay. I'd leave it out of this PR and put it in the new issue, since it only matters once repeat acceptance exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions