From a2c3201cd6417f7915f42d233bd44e7f3fb3c903 Mon Sep 17 00:00:00 2001 From: sangbingxing <18241996+sangbingxing@users.noreply.github.com> Date: Fri, 31 Jul 2026 09:48:24 +0800 Subject: [PATCH] Fix member invitations to members-only MUC rooms --- .../muc/spi/MultiUserChatServiceImpl.java | 15 ++++- .../muc/spi/MultiUserChatServiceImplTest.java | 66 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 xmppserver/src/test/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImplTest.java diff --git a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java index 6994bdd39a..3849e77803 100644 --- a/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java +++ b/xmppserver/src/main/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImpl.java @@ -1021,7 +1021,7 @@ private void processSendingInvitationMessage( // Add the user as a member of the room if the room is members only if (room.isMembersOnly()) { - room.addMember(jid, null, preExistingOccupantData.getAffiliation()); + addInviteeAsMember(room, jid, preExistingOccupantData); } // Send the invitation to the invitee @@ -1045,6 +1045,19 @@ private void processSendingInvitationMessage( } } + static void addInviteeAsMember( + @Nonnull final MUCRoom room, + @Nonnull final JID invitee, + @Nonnull final MUCOccupant inviter ) throws ForbiddenException, ConflictException + { + // An invitation that is allowed by the room grants membership on behalf of the room. Using the inviter's + // affiliation here would reject regular members even when the room explicitly allows occupants to invite. + final Affiliation actorAffiliation = room.canOccupantsInvite() + ? room.getSelfRepresentation().getAffiliation() + : inviter.getAffiliation(); + room.addMember(invitee, null, actorAffiliation); + } + /** * Process a declination of a room-invitation message sent by an occupant of the room. * diff --git a/xmppserver/src/test/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImplTest.java b/xmppserver/src/test/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImplTest.java new file mode 100644 index 0000000000..4b21ff9cf5 --- /dev/null +++ b/xmppserver/src/test/java/org/jivesoftware/openfire/muc/spi/MultiUserChatServiceImplTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2026 Ignite Realtime Foundation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.openfire.muc.spi; + +import org.jivesoftware.openfire.muc.Affiliation; +import org.jivesoftware.openfire.muc.MUCOccupant; +import org.jivesoftware.openfire.muc.MUCRoom; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.xmpp.packet.JID; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class MultiUserChatServiceImplTest +{ + @Mock + private MUCRoom room; + + @Mock + private MUCOccupant inviter; + + @Mock + private MUCOccupant roomSelfOccupant; + + @Test + public void testAddInviteeAsMemberUsesRoomAffiliationWhenOccupantInvitesAreAllowed() throws Exception + { + final JID invitee = new JID("invitee@example.org"); + when(room.canOccupantsInvite()).thenReturn(true); + when(room.getSelfRepresentation()).thenReturn(roomSelfOccupant); + when(roomSelfOccupant.getAffiliation()).thenReturn(Affiliation.owner); + + MultiUserChatServiceImpl.addInviteeAsMember(room, invitee, inviter); + + verify(room).addMember(invitee, null, Affiliation.owner); + } + + @Test + public void testAddInviteeAsMemberUsesInviterAffiliationWhenOccupantInvitesAreDisallowed() throws Exception + { + final JID invitee = new JID("invitee@example.org"); + when(room.canOccupantsInvite()).thenReturn(false); + when(inviter.getAffiliation()).thenReturn(Affiliation.member); + + MultiUserChatServiceImpl.addInviteeAsMember(room, invitee, inviter); + + verify(room).addMember(invitee, null, Affiliation.member); + } +}