Skip to content

Commit

Permalink
OF-2795 / OF-2166: Remove MUC affiliation of a user that is being del…
Browse files Browse the repository at this point in the history
…eted. (#2420)

This prevents a new user by the same name to claim the affiliation.
  • Loading branch information
guusdk committed Feb 29, 2024
1 parent 03bafe9 commit d66bddd
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2008 Jive Software, 2016-2022 Ignite Realtime Foundation. All rights reserved.
* Copyright (C) 2004-2008 Jive Software, 2016-2024 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.
Expand All @@ -24,8 +24,10 @@
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.event.GroupEventListener;
import org.jivesoftware.openfire.event.UserEventListener;
import org.jivesoftware.openfire.group.*;
import org.jivesoftware.openfire.muc.spi.*;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.*;
Expand All @@ -48,6 +50,7 @@
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
Expand All @@ -61,7 +64,7 @@
* @author Guus der Kinderen, guus@goodbytes.nl
*/
@JiveID(JiveConstants.MUC_ROOM)
public class MUCRoom implements GroupEventListener, Externalizable, Result, Cacheable {
public class MUCRoom implements GroupEventListener, UserEventListener, Externalizable, Result, Cacheable {

private static final Logger Log = LoggerFactory.getLogger(MUCRoom.class);

Expand Down Expand Up @@ -3817,4 +3820,46 @@ private void applyAffiliationChangeAndSendPresence(JID groupMember) {
public void groupCreated(Group group, Map params) {
// ignore
}

@Override
public void userCreated(User user, Map<String, Object> params)
{}

@Override
public void userDeleting(User user, Map<String, Object> params)
{
// When a user is being deleted, all its affiliations need to be removed from chat rooms (OF-2166). Note that
// this event handler only works for rooms that are loaded into memory from the database. Corresponding code
// in MultiUserChatManager will remove affiliations from rooms that are not in memory, but only in the database.
final JID userJid = XMPPServer.getInstance().createJID(user.getUsername(), null);

final Lock lock = getMUCService().getChatRoomLock(getJID().getNode());
try {
lock.lock();

if (getAffiliation(userJid) == MUCRole.Affiliation.none) {
// User had no affiliation with this room.
return;
}

// Cannot remove the last owner of a chat room. To prevent issues, replace the owner with an administrative account.
if (getOwners().contains(userJid) && getOwners().size() == 1) {
final JID adminJid = XMPPServer.getInstance().getAdmins().iterator().next();
Log.info("User '{}' is being deleted, but is also the only owner of MUC room '{}'. To prevent having a room without owner, server admin '{}' was made owner of the room.", user.getUsername(), getJID(), adminJid);
addOwner(adminJid, getRole());
}

// Remove the affiliation of the deleted user with the room
addNone(userJid, getRole());
getMUCService().syncChatRoom(this);
} catch (Throwable t) {
Log.warn("A problem occurred while trying to update room '{}' as a result of user '{}' being deleted from Openfire.", getJID(), user);
} finally {
lock.unlock();
}
}

@Override
public void userModified(User user, Map<String, Object> params)
{}
}
Original file line number Diff line number Diff line change
Expand Up @@ -951,10 +951,11 @@ public void userCreated(User user, Map<String, Object> params) {

@Override
public void userDeleting(User user, Map<String, Object> params) {
// Delete any affiliation of the user to any room of any MUC service
// When a user is being deleted, all its affiliations need to be removed from chat rooms (OF-2166). Note that
// every room is an event listener for the same event, which should update rooms that are loaded into memory
// from the database. This event handler intends to update rooms that are not in memory, but only in the database.
MUCPersistenceManager
.removeAffiliationFromDB(XMPPServer.getInstance().createJID(user.getUsername(), null, true));
// TODO Delete any user information from the rooms loaded into memory (OF-2166)
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2023 Ignite Realtime Foundation. All rights reserved.
* Copyright (C) 2016-2024 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.
Expand All @@ -20,6 +20,7 @@
import org.jivesoftware.openfire.cluster.ClusteredCacheEntryListener;
import org.jivesoftware.openfire.cluster.NodeID;
import org.jivesoftware.openfire.event.GroupEventDispatcher;
import org.jivesoftware.openfire.event.UserEventDispatcher;
import org.jivesoftware.openfire.muc.MUCRole;
import org.jivesoftware.openfire.muc.MUCRoom;
import org.jivesoftware.openfire.muc.MultiUserChatService;
Expand All @@ -36,14 +37,7 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -160,6 +154,7 @@ void add(@Nonnull final MUCRoom room)
}

GroupEventDispatcher.addListener(room); // TODO this event listener is added only in the node where the room is created. Does this mean that events are not propagated in a cluster?
UserEventDispatcher.addListener(room);
}

/**
Expand Down Expand Up @@ -234,6 +229,7 @@ MUCRoom remove(@Nonnull final String roomName)
if (room != null) {
room.getRoomHistory().purge();
GroupEventDispatcher.removeListener(room);
UserEventDispatcher.removeListener(room);
updateNonPersistentRoomStat(room, null);
}
localRooms.remove(roomName);
Expand Down

0 comments on commit d66bddd

Please sign in to comment.