Skip to content

Commit

Permalink
OF-2918: Add option to clear history for a given MUC
Browse files Browse the repository at this point in the history
Changes from PR review

1. Add the chatManagement.bulkMsgRetractionEnabled configuration to allow administrators to skip sending bulk retraction messages.
2. Make the MucRoom.clearChatHistory() method asynchronous, as it can be a long-running process.
3. Iterate over the history from the end, sending a revocation for the most recently received message first. This message is much more likely to be currently displayed in a connected client than the oldest message in a chatroom.
4. Add a translatable muc.room.clear_chat.retraction_fallback_msg string.
  • Loading branch information
“Huy committed Dec 3, 2024
1 parent f8343f6 commit 5f3573a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 38 deletions.
4 changes: 4 additions & 0 deletions distribution/src/conf/openfire.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

<locale>en</locale>

<chatManagement>
<bulkMsgRetractionEnabled>true</bulkMsgRetractionEnabled>
</chatManagement>

<!-- Network settings. By default, Openfire will bind to all network interfaces.
Alternatively, you can specify a specific network interfaces that the server
will listen on. For example, 127.0.0.1. This setting is generally only useful
Expand Down
1 change: 1 addition & 0 deletions i18n/src/main/resources/openfire_i18n.properties
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ muc.room.clear_chat.title=Clear Chat History
muc.room.clear_chat.info=Are you sure you want to clear the current chat history for the room
muc.room.clear_chat.detail=from the system?
muc.room.clear_chat.clear_command=Clear Chat History
muc.room.clear_chat.retraction_fallback_msg=A request to retract a previous message to clear chat history was received, but your client does not support this.

# Muc room delete Page

Expand Down
82 changes: 44 additions & 38 deletions xmppserver/src/main/java/org/jivesoftware/openfire/muc/MUCRoom.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
*/
@JiveID(JiveConstants.MUC_ROOM)
public class MUCRoom implements GroupEventListener, UserEventListener, Externalizable, Result, Cacheable {
public static final boolean BULK_MSG_RETRACTION_ENABLED = JiveGlobals.getBooleanProperty("chatManagement.bulkMsgRetractionEnabled", true);

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

Expand Down Expand Up @@ -1309,45 +1310,50 @@ public void removeOccupant(@Nonnull final MUCOccupant occupant) {
}

/**
* Clears the chat history of a room. Sends out message retraction stanzas to all occupants, for all the message in the chat history.
*/
public void clearChatHistory() {
Iterator<Message> history = roomHistory.getMessageHistory();
while (history.hasNext()) {
Message originalMsg = history.next();
Message retractionMsg = new Message();

// Sets a unique ID for the retraction message by prefixing the original message ID with "retract-"
retractionMsg.setID("retract-" + originalMsg.getID());
// Sets the sender of the retraction message to be the chat room itself
retractionMsg.setFrom(selfOccupantData.getOccupantJID());
// Sets the recipient of the retraction message to be the chat room itself to send to all occupants
retractionMsg.setTo(new JID(getName(), getMUCService().getServiceDomain(), null).toBareJID());
retractionMsg.setType(Message.Type.groupchat);
// An XML element is added to the message to indicate that it is a retraction, with an attribute specifying
// the ID of the message being retracted
retractionMsg.addChildElement("retract", "urn:xmpp:message-retract:1").addAttribute(
"id",
new JID(getName(), getMUCService().getServiceDomain(), null).toBareJID()
);
// A fallback element is added to provide a fallback message for clients that do not support message retraction
retractionMsg.addChildElement("fallback", "urn:xmpp:fallback:0").addAttribute(
"for",
"urn:xmpp:message-retract:1"
);
retractionMsg.setBody("A request was received to retract a previous message as part of clearing the chat room history, but this is not supported by your client.");
// Finally, a hint is added to the message to indicate that it should be stored by the client.
// This ensures that the retraction event is recorded and can be referenced later.
retractionMsg.addChildElement("store", "urn:xmpp:hints");

// Broadcast the retraction message but don't store it in the history
broadcast(retractionMsg, false);
}
* Asynchronously remove the chat history of a room from run-time memory and database storage.
* If bulk message retraction is enabled, it sends message retraction stanzas to all occupants.
*/
public CompletableFuture<Void> clearChatHistory() {
return CompletableFuture.runAsync(() -> {
if(MUCRoom.BULK_MSG_RETRACTION_ENABLED) {
ListIterator<Message> reverseMessageHistory = roomHistory.getReverseMessageHistory();
while (reverseMessageHistory.hasPrevious()) {
Message originalMsg = reverseMessageHistory.previous();
Message retractionMsg = new Message();

// Sets a unique ID for the retraction message by prefixing the original message ID with "retract-"
retractionMsg.setID("retract-" + originalMsg.getID());
// Sets the sender of the retraction message to be the chat room itself
retractionMsg.setFrom(selfOccupantData.getOccupantJID());
// Sets the recipient of the retraction message to be the chat room itself to send to all occupants
retractionMsg.setTo(new JID(getName(), getMUCService().getServiceDomain(), null).toBareJID());
retractionMsg.setType(Message.Type.groupchat);
// An XML element is added to the message to indicate that it is a retraction, with an attribute specifying
// the ID of the message being retracted
retractionMsg.addChildElement("retract", "urn:xmpp:message-retract:1").addAttribute(
"id",
new JID(getName(), getMUCService().getServiceDomain(), null).toBareJID()
);
// A fallback element is added to provide a fallback message for clients that do not support message retraction
retractionMsg.addChildElement("fallback", "urn:xmpp:fallback:0").addAttribute(
"for",
"urn:xmpp:message-retract:1"
);
retractionMsg.setBody(LocaleUtils.getLocalizedString("muc.room.clear_chat.retraction_fallback_msg"));
// Finally, a hint is added to the message to indicate that it should be stored by the client.
// This ensures that the retraction event is recorded and can be referenced later.
retractionMsg.addChildElement("store", "urn:xmpp:hints");

// Broadcast the retraction message but don't store it in the history
broadcast(retractionMsg, false);
}
}

// Clear the history of the room from the DB if the room was persistent
MUCPersistenceManager.clearRoomChatFromDB(this);
// Remove the history of the room from memory (preventing it to pop up in a new room by the same name).
roomHistory.purge();
// Clear the history of the room from the DB if the room was persistent
MUCPersistenceManager.clearRoomChatFromDB(this);
// Remove the history of the room from memory (preventing it to pop up in a new room by the same name).
roomHistory.purge();
});
}

/**
Expand Down

0 comments on commit 5f3573a

Please sign in to comment.