ClearspaceMUCEventDelegate.java 9.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**
 * Copyright (C) 2004-2009 Jive Software. 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.
 */

17 18
package org.jivesoftware.openfire.clearspace;

19 20 21 22 23
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

24 25
import org.dom4j.Attribute;
import org.dom4j.Element;
26
import org.jivesoftware.openfire.XMPPServer;
27
import org.jivesoftware.openfire.muc.MUCEventDelegate;
28
import org.jivesoftware.openfire.muc.MUCRoom;
29
import org.jivesoftware.util.StringUtils;
30 31
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
32
import org.xmpp.packet.IQ;
33
import org.xmpp.packet.JID;
34
import org.xmpp.packet.PacketError;
35 36

/**
37 38 39 40 41
 * Handles checking with Clearspace regarding whether a user can join a particular MUC room (based
 * on their permissions with the Clearspace JiveObject (eg. Community/Space) that the room is associated with).
 *
 * In addition, this MUCEventDelegate provides a means to obtain room configuration details from Clearspace
 * in the event that the Clearspace MUC service needs to create a room on-demand (eg. when a user first joins the room).
42 43 44 45
 *
 * @author Armando Jagucki
 */
public class ClearspaceMUCEventDelegate extends MUCEventDelegate {
46

47 48
	private static final Logger Log = LoggerFactory.getLogger(ClearspaceMUCEventDelegate.class);

49
    private String csMucDomain;
50 51
    private String csComponentAddress;
    private final String GET_ROOM_CONFIG_WARNING ="Clearspace sent an unexpected reply to a get-room-config request.";
52 53

    public ClearspaceMUCEventDelegate() {
54 55 56
        String xmppDomain = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
        csMucDomain = ClearspaceManager.MUC_SUBDOMAIN + "." + xmppDomain;
        csComponentAddress = ClearspaceManager.CLEARSPACE_COMPONENT + "." + xmppDomain;
57 58
    }

59 60
    @Override
	public InvitationResult sendingInvitation(MUCRoom room, JID invitee, JID inviter, String reason)
61 62 63 64
    {
        // Packet should look like:
        // <iq to="clearspace.example.org" from="clearspace-conference.example.org">
        //    <room-invite xmlns="http://jivesoftware.com/clearspace">
65 66 67 68
        //        <inviter>username@example.org</inviter>
        //        <room>14-1234@clearspace-conference.example.org</roomjid>
        //        <reason>Example Message</reason>
        //        <invitee>anotheruser@example.org</invitee>
69 70 71 72 73
        //    </room-invite>
        // </iq>

        IQ query = new IQ();
        query.setFrom(csMucDomain);
74
        Element cmd = query.setChildElement("invite-check", "http://jivesoftware.com/clearspace");
75 76 77 78 79
        Element inviterjidElement = cmd.addElement("inviter");
        inviterjidElement.setText(inviter.toBareJID());
        Element inviteejidElement = cmd.addElement("invitee");
        inviteejidElement.setText(invitee.toBareJID());
        Element roomjidElement = cmd.addElement("room");
80
        roomjidElement.setText(room.getJID().toBareJID());
81 82
        Element messageElement = cmd.addElement("reason");
        messageElement.setText(reason);
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98

        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;
    }

99
    /**
100 101
     * Returns true if the user is allowed to join the room. If the userjid is an owner of the room,
     * we will return true immediately.
102
     *
103
     * @param room the room the user is attempting to join.
104 105 106
     * @param userjid  the JID of the user attempting to join the room.
     * @return true if the user is allowed to join the room.
     */
107 108
    @Override
	public boolean joiningRoom(MUCRoom room, JID userjid) {
109 110
        // Always allow an owner to join the room (especially since they need to join to configure the
        // room on initial creation).
111
        Collection<JID> owners = room.getOwners();
112
        if (owners != null && owners.contains(userjid.asBareJID())) {
113 114 115
            return true;
        }

116 117 118 119 120 121 122
        // Packet should look like:
        // <iq to="clearspace.example.org" from="clearspace-conference.example.org">
        //    <join-check xmlns="http://jivesoftware.com/clearspace">
        //        <userjid>username@example.org</userjid>
        //        <roomjid>14-1234@clearspace-conference.example.org</roomjid>
        //    </join-check>
        // </iq>
123 124
        IQ query = new IQ();
        query.setFrom(csMucDomain);
125 126 127 128 129
        Element cmd = query.setChildElement("join-check", "http://jivesoftware.com/clearspace");
        Element userjidElement = cmd.addElement("userjid");
        userjidElement.setText(userjid.toBareJID());
        Element roomjidElement = cmd.addElement("roomjid");
        roomjidElement.setText(room.getJID().toBareJID());
130 131 132 133

        IQ result = ClearspaceManager.getInstance().query(query, 15000);
        if (result == null) {
            // No answer was received, assume false for security reasons.
134 135 136 137
            if (Log.isDebugEnabled()) {
                Log.debug("No answer from Clearspace on join-check in ClearspaceMUCEventDelegate. User: "
                        + userjid.toBareJID() + " Room: " + room.getJID().toBareJID());
            }
138 139 140 141 142 143 144 145 146 147
            return false;
        }

        if (result.getType() != IQ.Type.error) {
            // No error, that indicates that we were successful and the user is permitted.
            return true;
        }

        // No successful return, not allowed.
        return false;
148 149
    }

150 151
    @Override
	public boolean shouldRecreate(String roomName, JID userjid) {
152 153 154
        return !(roomName + "@" + csComponentAddress).equals(userjid.toBareJID());
    }

155 156
    @Override
	public Map<String, String> getRoomConfig(String roomName) {
157 158
        Map<String, String> roomConfig = new HashMap<String, String>();

159 160 161 162 163 164 165 166
        IQ iq = new IQ(IQ.Type.get);
        iq.setFrom(csMucDomain);
        iq.setID("get_room_config_" + StringUtils.randomString(3));
        Element child = iq.setChildElement("get-room-config", "http://jivesoftware.com/clearspace");
        Element roomjidElement = child.addElement("roomjid");
        JID roomJid = new JID(roomName + "@" + csMucDomain);
        roomjidElement.setText(roomJid.toBareJID());
        IQ result = ClearspaceManager.getInstance().query(iq, 15000);
167
        if (result == null) {
168
            // No answer was received from Clearspace, so return null.
169
            Log.warn(GET_ROOM_CONFIG_WARNING + " Room: " + roomJid.toBareJID());
170 171 172 173
            return null;
        }
        else if (result.getType() != IQ.Type.result) {
            // The reply was not a valid result containing the room configuration, so return null.
174
            Log.warn(GET_ROOM_CONFIG_WARNING + " Room: " + roomJid.toBareJID());
175
            return null;
176
        }
177 178 179 180

        // Setup room configuration based on the configuration values in the result packet.
        Element query = result.getChildElement();
        if (query == null) {
181
            Log.warn(GET_ROOM_CONFIG_WARNING + " Room: " + roomJid.toBareJID());
182 183 184 185
            return null;
        }
        Element xElement = query.element("x");
        if (xElement == null) {
186
            Log.warn(GET_ROOM_CONFIG_WARNING + " Room: " + roomJid.toBareJID());
187 188
            return null;
        }
189 190 191
        
        @SuppressWarnings("unchecked")
		Iterator<Element> fields = xElement.elementIterator("field");
192
        while (fields.hasNext()) {
193
            Element field = fields.next();
194 195 196 197 198 199 200 201 202 203
            Attribute varAttribute = field.attribute("var");
            if (varAttribute != null) {
                Element value = field.element("value");
                if (value != null) {
                    roomConfig.put(varAttribute.getValue(), value.getText());
                }
            }
        }

        String ownerJid = roomJid.getNode() + "@" + csComponentAddress;
204 205 206 207 208 209 210
        roomConfig.put("muc#roomconfig_roomowners", ownerJid);

        return roomConfig;
    }

    /**
     * This event will be triggered when an entity attempts to destroy a room.
211 212
     * <p>
     * Returns true if the user is allowed to destroy the room.</p>
213 214 215 216 217
     *
     * @param roomName the name of the MUC room being destroyed.
     * @param userjid  the JID of the user attempting to destroy the room.
     * @return true if the user is allowed to destroy the room.
     */
218 219
    @Override
	public boolean destroyingRoom(String roomName, JID userjid) {
220
        // We never allow destroying a room as a user, but clearspace components are permitted.
221
        return ClearspaceManager.getInstance().isFromClearspace(userjid);
222 223
    }
}