Fix: a duplicate group invite demoted a member who had already joined - #2218
Open
mpretty-cyro wants to merge 1 commit into
Open
mpretty-cyro wants to merge 1 commit into
mpretty-cyro wants to merge 1 commit into
Conversation
Issue session-foundation#2215, reported against every Session Android version. handleInvitation built a fresh ClosedGroupInfo and wrote it over the existing record, so a second invite for a group we were already in set us back to invited and discarded joinedAtSecs. It now mirrors the check handlePromotion already makes, and still rebuilds when we were kicked or the group was destroyed - a fresh invitation is how we get back in. The admin side of the same defect: inviteMembersInternal called setInvited() whatever state the member was in, so re-inviting someone who had accepted reset them in the group members config too. The regression test covers the receiving side only; GroupMember's setters are native, so a JVM unit test cannot reach the admin path.
mpretty-cyro
marked this pull request as ready for review
September 20, 2026 20:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue #2215, reported with a reliable repro and against every Session Android version.
Receiving side
GroupManagerV2Impl.handleInvitationhad no check for a group we are already in. It built a freshClosedGroupInfoand wrote it over the existing record, so a second invitation setinvitedback to true and resetjoinedAtSecsto 0 — a joined member was demoted to "invited" and their join time was lost.handlePromotionalready guards this case withif (group == null), and the invitation path now does the same thing — but conditionally, not literally. A literalgroup == nullcheck would break re-invitation after a kick:handleKickedkeeps the record withkicked = true, and an invitation that rebuilds it is the only way back in. The guard is therefore "already joined" — present, and not invited, kicked or destroyed.Admin side
inviteMembersInternalcalledsetInvited()whatever state the member was in, so re-inviting someone who had already accepted reset them in the group members config too. It now skips that forINVITE_ACCEPTEDandPROMOTION_ACCEPTED. Other promotion states are left exactly as they were.Tests
GroupManagerV2ImplTest, synthetic group config only:dangerouslyAccessMutableUserConfigs, so it covers both the membership flag andjoinedAtSecs)invited = true— a control, so the negative test above cannot pass by never reaching the codeThe first test was verified to fail with the guard reverted, reproducing the reported behaviour; the control passes either way, which is what makes the negative meaningful.
The admin half has no test:
GroupMember's state setters arenative, so a JVM unit test cannot reach them.Unit suite: 300 pass, 0 fail (298 on
devplus these two).