package org.buddycloud.channelserver.packetprocessor.iq.namespace.register; import java.util.Collection; import java.util.concurrent.BlockingQueue; import org.apache.log4j.Logger; import org.buddycloud.channelserver.Configuration; import org.buddycloud.channelserver.channel.ChannelManager; import org.buddycloud.channelserver.channel.Conf; import org.buddycloud.channelserver.db.exception.NodeStoreException; import org.buddycloud.channelserver.packetprocessor.PacketProcessor; import org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub.JabberPubsub; import org.buddycloud.channelserver.pubsub.accessmodel.AccessModels; import org.buddycloud.channelserver.pubsub.model.impl.NodeSubscriptionImpl; import org.buddycloud.channelserver.pubsub.subscription.Subscriptions; import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud; import org.dom4j.Element; import org.dom4j.QName; import org.xmpp.packet.IQ; import org.xmpp.packet.IQ.Type; import org.xmpp.packet.JID; import org.xmpp.packet.Packet; import org.xmpp.packet.PacketError; public class RegisterSet implements PacketProcessor<IQ> { public static final String ELEMENT_NAME = "query"; private static final Logger LOGGER = Logger.getLogger(RegisterSet.class); private final BlockingQueue<Packet> outQueue; private final ChannelManager channelManager; private IQ request; private IQ response; private final Configuration configuration; public RegisterSet(BlockingQueue<Packet> outQueue, ChannelManager channelManager) { this(Configuration.getInstance(), outQueue, channelManager); } public RegisterSet(Configuration configuration, BlockingQueue<Packet> outQueue, ChannelManager channelManager) { this.configuration = configuration; this.outQueue = outQueue; this.channelManager = channelManager; } @Override public void process(IQ reqIQ) throws Exception { this.request = reqIQ; this.response = IQ.createResultIQ(reqIQ); LOGGER.debug("Processing register request from " + request.getFrom()); String domain = reqIQ.getFrom().getDomain(); if (!Configuration.getInstance().isLocalDomain(domain)) { notThisDomain(reqIQ); return; } if (userRegistered()) { LOGGER.debug("User " + request.getFrom().toBareJID() + " is already registered"); outQueue.put(response); return; } LOGGER.debug("Registering new user " + request.getFrom()); channelManager.createPersonalChannel(request.getFrom()); outQueue.put(response); autosubscribeToChannels(request.getFrom()); } private void notThisDomain(IQ reqIQ) throws InterruptedException { // Request is coming from different domain than the // component is using. We will not allow this because // "buddycloud federation" cannot work for that. IQ reply = IQ.createResultIQ(reqIQ); reply.setType(Type.error); reply.setChildElement(reqIQ.getChildElement().createCopy()); PacketError pe = new PacketError( org.xmpp.packet.PacketError.Condition.not_allowed, org.xmpp.packet.PacketError.Type.cancel); reply.setError(pe); outQueue.put(reply); } private boolean userRegistered() throws Exception { return channelManager.nodeExists("/user/" + request.getFrom().toBareJID() + "/posts"); } // TODO(lloydwatkin): We should really be returning an error as per spec shouldn't we? // It should be up to the client to ignore the error, not the server. @SuppressWarnings("unused") private void userAlreadyRegistered() throws InterruptedException { // User is already registered. IQ reply = IQ.createResultIQ(request); reply.setType(Type.error); reply.setChildElement(request.getChildElement().createCopy()); PacketError pe = new PacketError( org.xmpp.packet.PacketError.Condition.conflict, org.xmpp.packet.PacketError.Type.cancel); reply.setError(pe); outQueue.put(reply); } private void autosubscribeToChannels(final JID from) { Collection<JID> channels = configuration.getAutosubscribeChannels(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Auto-subscribing " + from + " to " + channels.size() + " channel(s)"); } for (JID channel : channels) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Auto-subscribing " + from + " to " + channel); } IQ subscribe = new IQ(); subscribe.setType(Type.set); Element el = subscribe.getElement(); Element pubsubEl = el.addElement("pubsub", JabberPubsub.NAMESPACE_URI); Element subscribeEl = pubsubEl.addElement("subscribe"); String channelNodeId = Conf.getPostChannelNodename(channel); subscribeEl.addAttribute("node", channelNodeId); subscribeEl.addAttribute("jid", from.toBareJID().toString()); try { if (Configuration.getInstance().isLocalJID(channel)) { subscribe.setFrom(from); subscribe.setTo(configuration.getServerChannelsDomain()); } else { subscribe.setFrom(configuration.getServerChannelsDomain()); subscribe.setTo(channel.getDomain()); Element actorEl = pubsubEl.addElement(QName.get("actor", Buddycloud.NS)); actorEl.setText(from.toBareJID()); } outQueue.put(subscribe); // If auto-approve is set, and this is a local private channel // then set the user to subscribed if (configuration.getBooleanProperty( Configuration.CONFIGURATION_CHANNELS_AUTOSUBSCRIBE_AUTOAPPROVE, false) && Configuration.getInstance().isLocalJID(channel) && AccessModels.authorize.toString().equals( channelManager.getNodeConfValue(channelNodeId, Conf.ACCESS_MODEL))) { channelManager .addUserSubscription(new NodeSubscriptionImpl( channelNodeId, from, Subscriptions.subscribed, null)); channelManager.setUserAffiliation(channelNodeId, from, channelManager .getDefaultNodeAffiliation(channelNodeId)); } } catch (InterruptedException e) { LOGGER.error("Could not auto-subscribe " + from + " to " + channel, e); } catch (NodeStoreException e) { LOGGER.error("Could not auto-subscribe " + from + " to " + channel, e); } } } }