Commit aa354acb authored by David Smith's avatar David Smith Committed by david

Openfire side of allowing MUC delegates to handle invitation requests...

Openfire side of allowing MUC delegates to handle invitation requests themselves, or reject them entirely. Relates to http://www.jivesoftware.com/issues/browse/CS-4034, r=Armando

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@10167 b35dd754-fafc-0310-a699-88a17e54d16e
parent 77bba26a
...@@ -7,6 +7,7 @@ import org.jivesoftware.util.StringUtils; ...@@ -7,6 +7,7 @@ import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.xmpp.packet.IQ; import org.xmpp.packet.IQ;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.Attribute; import org.dom4j.Attribute;
...@@ -36,6 +37,39 @@ public class ClearspaceMUCEventDelegate extends MUCEventDelegate { ...@@ -36,6 +37,39 @@ public class ClearspaceMUCEventDelegate extends MUCEventDelegate {
csComponentAddress = ClearspaceManager.CLEARSPACE_COMPONENT + "." + xmppDomain; csComponentAddress = ClearspaceManager.CLEARSPACE_COMPONENT + "." + xmppDomain;
} }
public InvitationResult sendingInvitation(MUCRoom room, JID userjid)
{
// Packet should look like:
// <iq to="clearspace.example.org" from="clearspace-conference.example.org">
// <room-invite xmlns="http://jivesoftware.com/clearspace">
// <user>username@example.org</user>
// <roomjid>14-1234@clearspace-conference.example.org</roomjid>
// </room-invite>
// </iq>
IQ query = new IQ();
query.setFrom(csMucDomain);
Element cmd = query.setChildElement("room-invite", "http://jivesoftware.com/clearspace");
Element userjidElement = cmd.addElement("userjid");
userjidElement.setText(userjid.toBareJID());
Element roomjidElement = cmd.addElement("roomjid");
roomjidElement.setText(room.getJID().toBareJID());
IQ result = ClearspaceManager.getInstance().query(query, 15000);
if (null != result) {
if (result.getType() != IQ.Type.error) {
// No error, that indicates that we were successful and the user is permitted.
return InvitationResult.HANDLED_BY_DELEGATE;
}
else if(result.getError().getType() == PacketError.Type.continue_processing) {
return InvitationResult.HANDLED_BY_OPENFIRE;
}
}
// No successful return, not allowed.
return InvitationResult.REJECTED;
}
/** /**
* This event will be triggered when an entity joins an existing room. * This event will be triggered when an entity joins an existing room.
* <p/> * <p/>
......
/**
* Copyright (C) 2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.muc;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* Exception used for representing the error when an external MUC delegate responds to an invite-user packet by rejecting the invitation attempt.
*
* @author David Smith
*/
public class CannotBeInvitedException extends Exception {
private static final long serialVersionUID = 1L;
private Throwable nestedThrowable = null;
public CannotBeInvitedException() {
super();
}
public CannotBeInvitedException(String msg) {
super(msg);
}
public CannotBeInvitedException(Throwable nestedThrowable) {
this.nestedThrowable = nestedThrowable;
}
public CannotBeInvitedException(String msg, Throwable nestedThrowable) {
super(msg);
this.nestedThrowable = nestedThrowable;
}
public void printStackTrace() {
super.printStackTrace();
if (nestedThrowable != null) {
nestedThrowable.printStackTrace();
}
}
public void printStackTrace(PrintStream ps) {
super.printStackTrace(ps);
if (nestedThrowable != null) {
nestedThrowable.printStackTrace(ps);
}
}
public void printStackTrace(PrintWriter pw) {
super.printStackTrace(pw);
if (nestedThrowable != null) {
nestedThrowable.printStackTrace(pw);
}
}
}
package org.jivesoftware.openfire.muc; package org.jivesoftware.openfire.muc;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.jivesoftware.openfire.muc.spi.LocalMUCRoom;
import java.util.Map; import java.util.Map;
...@@ -16,6 +15,12 @@ import java.util.Map; ...@@ -16,6 +15,12 @@ import java.util.Map;
*/ */
public abstract class MUCEventDelegate { public abstract class MUCEventDelegate {
public enum InvitationResult {
HANDLED_BY_DELEGATE,
HANDLED_BY_OPENFIRE,
REJECTED
}
/** /**
* This event will be triggered when an entity joins an existing room. * This event will be triggered when an entity joins an existing room.
* *
...@@ -27,12 +32,24 @@ public abstract class MUCEventDelegate { ...@@ -27,12 +32,24 @@ public abstract class MUCEventDelegate {
*/ */
public abstract boolean joiningRoom(MUCRoom room, JID userjid); public abstract boolean joiningRoom(MUCRoom room, JID userjid);
/**
* This event will be triggered when an entity attempts to invite someone to a room.
*
* Returns a String indicating whether the invitation should be abandoned, handled by the delegate, or handled by openfire.
*
* @param room the MUC room.
* @param inviteeJID the JID of the user the invitation will be sent to.
* @return true if the user is allowed to join the room.
*/
public abstract InvitationResult sendingInvitation(MUCRoom room, JID inviteeJID);
/** /**
* Returns a map containing room configuration variables and values. * Returns a map containing room configuration variables and values.
* *
* @param roomName the name of the room the configuration map is associated with. * @param roomName the name of the room the configuration map is associated with.
* @returna map containing room configuration variables and values, or null if roomName was not valid. * @return a map containing room configuration variables and values, or null if roomName was not valid.
*/ */
public abstract Map<String, String> getRoomConfig(String roomName); public abstract Map<String, String> getRoomConfig(String roomName);
/** /**
......
...@@ -933,9 +933,10 @@ public interface MUCRoom extends Externalizable, Result { ...@@ -933,9 +933,10 @@ public interface MUCRoom extends Externalizable, Result {
* @param extensions the list of extensions sent with the original message invitation or null * @param extensions the list of extensions sent with the original message invitation or null
* if none. * if none.
* @throws ForbiddenException If the user is not allowed to send the invitation. * @throws ForbiddenException If the user is not allowed to send the invitation.
* @throws CannotBeInvitedException (Optionally) If the user being invited does not have access to the room
*/ */
public void sendInvitation(JID to, String reason, MUCRole role, List<Element> extensions) public void sendInvitation(JID to, String reason, MUCRole role, List<Element> extensions)
throws ForbiddenException; throws ForbiddenException, CannotBeInvitedException;
/** /**
* Sends the rejection to the inviter. The rejection will be sent as if the room is rejecting * Sends the rejection to the inviter. The rejection will be sent as if the room is rejecting
......
...@@ -13,10 +13,7 @@ package org.jivesoftware.openfire.muc.spi; ...@@ -13,10 +13,7 @@ package org.jivesoftware.openfire.muc.spi;
import org.dom4j.Element; import org.dom4j.Element;
import org.jivesoftware.openfire.PacketRouter; import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.muc.ConflictException; import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.openfire.muc.ForbiddenException;
import org.jivesoftware.openfire.muc.MUCRole;
import org.jivesoftware.openfire.muc.NotAllowedException;
import org.jivesoftware.openfire.user.UserNotFoundException; import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.IQ; import org.xmpp.packet.IQ;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
...@@ -66,9 +63,10 @@ public class IQAdminHandler { ...@@ -66,9 +63,10 @@ public class IQAdminHandler {
* @throws ConflictException If the desired room nickname is already reserved for the room or * @throws ConflictException If the desired room nickname is already reserved for the room or
* if the room was going to lose all of its owners. * if the room was going to lose all of its owners.
* @throws NotAllowedException Thrown if trying to ban an owner or an administrator. * @throws NotAllowedException Thrown if trying to ban an owner or an administrator.
* @throws CannotBeInvitedException If the user being invited as a result of being added to a members-only room still does not have permission
*/ */
public void handleIQ(IQ packet, MUCRole role) throws ForbiddenException, ConflictException, public void handleIQ(IQ packet, MUCRole role) throws ForbiddenException, ConflictException,
NotAllowedException { NotAllowedException, CannotBeInvitedException {
IQ reply = IQ.createResultIQ(packet); IQ reply = IQ.createResultIQ(packet);
Element element = packet.getChildElement(); Element element = packet.getChildElement();
...@@ -104,9 +102,10 @@ public class IQAdminHandler { ...@@ -104,9 +102,10 @@ public class IQAdminHandler {
* @throws ConflictException If the desired room nickname is already reserved for the room or * @throws ConflictException If the desired room nickname is already reserved for the room or
* if the room was going to lose all of its owners. * if the room was going to lose all of its owners.
* @throws NotAllowedException Thrown if trying to ban an owner or an administrator. * @throws NotAllowedException Thrown if trying to ban an owner or an administrator.
* @throws CannotBeInvitedException If the user being invited as a result of being added to a members-only room still does not have permission
*/ */
private void handleItemsElement(MUCRole senderRole, List itemsList, IQ reply) private void handleItemsElement(MUCRole senderRole, List itemsList, IQ reply)
throws ForbiddenException, ConflictException, NotAllowedException { throws ForbiddenException, ConflictException, NotAllowedException, CannotBeInvitedException {
Element item; Element item;
String affiliation; String affiliation;
String roleAttribute; String roleAttribute;
......
...@@ -22,6 +22,7 @@ import org.jivesoftware.openfire.forms.spi.XFormFieldImpl; ...@@ -22,6 +22,7 @@ import org.jivesoftware.openfire.forms.spi.XFormFieldImpl;
import org.jivesoftware.openfire.muc.ConflictException; import org.jivesoftware.openfire.muc.ConflictException;
import org.jivesoftware.openfire.muc.ForbiddenException; import org.jivesoftware.openfire.muc.ForbiddenException;
import org.jivesoftware.openfire.muc.MUCRole; import org.jivesoftware.openfire.muc.MUCRole;
import org.jivesoftware.openfire.muc.CannotBeInvitedException;
import org.jivesoftware.openfire.muc.cluster.RoomUpdatedEvent; import org.jivesoftware.openfire.muc.cluster.RoomUpdatedEvent;
import org.jivesoftware.openfire.user.UserNotFoundException; import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.LocaleUtils;
...@@ -74,7 +75,7 @@ public class IQOwnerHandler { ...@@ -74,7 +75,7 @@ public class IQOwnerHandler {
* @throws ForbiddenException if the user does not have enough permissions (ie. is not an owner). * @throws ForbiddenException if the user does not have enough permissions (ie. is not an owner).
* @throws ConflictException If the room was going to lose all of its owners. * @throws ConflictException If the room was going to lose all of its owners.
*/ */
public void handleIQ(IQ packet, MUCRole role) throws ForbiddenException, ConflictException { public void handleIQ(IQ packet, MUCRole role) throws ForbiddenException, ConflictException, CannotBeInvitedException {
// Only owners can send packets with the namespace "http://jabber.org/protocol/muc#owner" // Only owners can send packets with the namespace "http://jabber.org/protocol/muc#owner"
if (MUCRole.Affiliation.owner != role.getAffiliation()) { if (MUCRole.Affiliation.owner != role.getAffiliation()) {
throw new ForbiddenException(); throw new ForbiddenException();
...@@ -141,9 +142,10 @@ public class IQOwnerHandler { ...@@ -141,9 +142,10 @@ public class IQOwnerHandler {
* @param reply the iq packet that will be sent back as a reply to the client's request. * @param reply the iq packet that will be sent back as a reply to the client's request.
* @throws ForbiddenException if the user does not have enough permissions. * @throws ForbiddenException if the user does not have enough permissions.
* @throws ConflictException If the room was going to lose all of its owners. * @throws ConflictException If the room was going to lose all of its owners.
* @throws CannotBeInvitedException If the user being invited as a result of being added to a members-only room still does not have permission
*/ */
private void handleItemsElement(List itemsList, MUCRole senderRole, IQ reply) private void handleItemsElement(List itemsList, MUCRole senderRole, IQ reply)
throws ForbiddenException, ConflictException { throws ForbiddenException, ConflictException, CannotBeInvitedException {
Element item; Element item;
boolean hasJID = ((Element)itemsList.get(0)).attributeValue("jid") != null; boolean hasJID = ((Element)itemsList.get(0)).attributeValue("jid") != null;
boolean hasNick = ((Element)itemsList.get(0)).attributeValue("nick") != null; boolean hasNick = ((Element)itemsList.get(0)).attributeValue("nick") != null;
......
...@@ -1622,7 +1622,7 @@ public class LocalMUCRoom implements MUCRoom { ...@@ -1622,7 +1622,7 @@ public class LocalMUCRoom implements MUCRoom {
} }
public void sendInvitation(JID to, String reason, MUCRole senderRole, List<Element> extensions) public void sendInvitation(JID to, String reason, MUCRole senderRole, List<Element> extensions)
throws ForbiddenException { throws ForbiddenException, CannotBeInvitedException {
if (!isMembersOnly() || canOccupantsInvite() if (!isMembersOnly() || canOccupantsInvite()
|| MUCRole.Affiliation.admin == senderRole.getAffiliation() || MUCRole.Affiliation.admin == senderRole.getAffiliation()
|| MUCRole.Affiliation.owner == senderRole.getAffiliation()) { || MUCRole.Affiliation.owner == senderRole.getAffiliation()) {
...@@ -1631,6 +1631,21 @@ public class LocalMUCRoom implements MUCRoom { ...@@ -1631,6 +1631,21 @@ public class LocalMUCRoom implements MUCRoom {
Message message = new Message(); Message message = new Message();
message.setFrom(role.getRoleAddress()); message.setFrom(role.getRoleAddress());
message.setTo(to); message.setTo(to);
if (((MultiUserChatServiceImpl)mucService).getMUCDelegate() != null) {
switch(((MultiUserChatServiceImpl)mucService).getMUCDelegate().sendingInvitation(this, to)) {
case HANDLED_BY_DELEGATE:
//if the delegate is taking care of it, there's nothing for us to do
return;
case HANDLED_BY_OPENFIRE:
//continue as normal if we're asked to handle it
break;
case REJECTED:
//we can't invite that person
throw new CannotBeInvitedException();
}
}
// Add a list of extensions sent with the original message invitation (if any) // Add a list of extensions sent with the original message invitation (if any)
if (extensions != null) { if (extensions != null) {
for(Element element : extensions) { for(Element element : extensions) {
......
...@@ -324,6 +324,9 @@ public class LocalMUCUser implements MUCUser { ...@@ -324,6 +324,9 @@ public class LocalMUCUser implements MUCUser {
catch (ConflictException e) { catch (ConflictException e) {
sendErrorPacket(packet, PacketError.Condition.conflict); sendErrorPacket(packet, PacketError.Condition.conflict);
} }
catch (CannotBeInvitedException e) {
sendErrorPacket(packet, PacketError.Condition.not_acceptable);
}
} }
} }
} }
...@@ -400,6 +403,9 @@ public class LocalMUCUser implements MUCUser { ...@@ -400,6 +403,9 @@ public class LocalMUCUser implements MUCUser {
catch (NotAllowedException e) { catch (NotAllowedException e) {
sendErrorPacket(packet, PacketError.Condition.not_allowed); sendErrorPacket(packet, PacketError.Condition.not_allowed);
} }
catch (CannotBeInvitedException e) {
sendErrorPacket(packet, PacketError.Condition.not_acceptable);
}
catch (Exception e) { catch (Exception e) {
sendErrorPacket(packet, PacketError.Condition.internal_server_error); sendErrorPacket(packet, PacketError.Condition.internal_server_error);
Log.error(e); Log.error(e);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment