diff --git a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java index 70cda72f..da9e3cab 100644 --- a/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java +++ b/src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEvent.java @@ -25,174 +25,201 @@ public class AffiliationEvent extends PubSubElementProcessorAbstract { - Element requestedAffiliationElement; - NodeMembership usersCurrentMembership; - private Affiliations requestedAffiliation; + Element requestedAffiliationElement; + NodeMembership usersCurrentMembership; + private Affiliations requestedAffiliation; + + private static final Logger LOGGER = Logger.getLogger(AffiliationEvent.class); + + public static final String CAN_NOT_MODIFY_OWN_AFFILIATION = "can-not-modify-own-affiliation"; + + /** + * Constructor + * + * @param outQueue Outgoing message queue + * @param channelManager Data Access Object (DAO) + */ + public AffiliationEvent(BlockingQueue outQueue, ChannelManager channelManager) { + setChannelManager(channelManager); + setOutQueue(outQueue); + + acceptedElementName = XMLConstants.AFFILIATIONS_ELEM; + } + + /** + * Process incoming stanza + */ + public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exception { + element = elm; + response = IQ.createResultIQ(reqIQ); + request = reqIQ; + actor = actorJID; + node = element.attributeValue(XMLConstants.NODE_ATTR); + + if (actor == null) { + actor = request.getFrom(); + } - private static final Logger LOGGER = Logger.getLogger(AffiliationEvent.class); + if (!nodePresent()) { + outQueue.put(response); + return; + } - public static final String CAN_NOT_MODIFY_OWN_AFFILIATION = "can-not-modify-own-affiliation"; + if (false == Configuration.getInstance().isLocalNode(node)) { + makeRemoteRequest(); + return; + } - /** - * Constructor - * - * @param outQueue Outgoing message queue - * @param channelManager Data Access Object (DAO) - */ - public AffiliationEvent(BlockingQueue outQueue, ChannelManager channelManager) { - setChannelManager(channelManager); - setOutQueue(outQueue); + try { - acceptedElementName = XMLConstants.AFFILIATIONS_ELEM; + if ((false == isValidStanza()) || (false == checkNodeExists()) + || (false == actorHasPermissionToAuthorize()) + || (false == subscriberHasCurrentAffiliation()) + || (true == userIsModifyingTheirAffiliation()) + || (false == attemptToChangeAffiliationOfNodeOwner()) + || (true == isIllegalEphemeralNodeAffiliationChange())) { + outQueue.put(response); + return; + } + saveUpdatedAffiliation(); + sendNotifications(); + } catch (NodeStoreException e) { + LOGGER.error(e); + setErrorCondition(PacketError.Type.wait, PacketError.Condition.internal_server_error); + outQueue.put(response); + return; } + } - /** - * Process incoming stanza - */ - public void process(Element elm, JID actorJID, IQ reqIQ, Element rsm) throws Exception { - element = elm; - response = IQ.createResultIQ(reqIQ); - request = reqIQ; - actor = actorJID; - node = element.attributeValue(XMLConstants.NODE_ATTR); - - if (actor == null) { - actor = request.getFrom(); - } - - if (!nodePresent()) { - outQueue.put(response); - return; - } - - if (false == Configuration.getInstance().isLocalNode(node)) { - makeRemoteRequest(); - return; - } - - try { - - if ((false == isValidStanza()) || (false == checkNodeExists()) || (false == actorHasPermissionToAuthorize()) - || (false == subscriberHasCurrentAffiliation()) || (true == userIsModifyingTheirAffiliation()) - || (false == attemptToChangeAffiliationOfNodeOwner())) { - outQueue.put(response); - return; - } - saveUpdatedAffiliation(); - sendNotifications(); - } catch (NodeStoreException e) { - LOGGER.error(e); - setErrorCondition(PacketError.Type.wait, PacketError.Condition.internal_server_error); - outQueue.put(response); - return; - } + private boolean isIllegalEphemeralNodeAffiliationChange() throws NodeStoreException { + if (false == channelManager.isEphemeralNode(node)) { + return false; } - - private boolean userIsModifyingTheirAffiliation() { - if (actor.toBareJID().equals(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR))) { - createExtendedErrorReply(PacketError.Type.cancel, PacketError.Condition.not_allowed, CAN_NOT_MODIFY_OWN_AFFILIATION, Buddycloud.NS_ERROR); - return true; - } - return false; + if (requestedAffiliation.canAuthorize()) { + return false; + } + setErrorCondition(PacketError.Type.cancel, PacketError.Condition.not_allowed); + return true; + } + + private boolean userIsModifyingTheirAffiliation() { + if (actor.toBareJID().equals(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR))) { + createExtendedErrorReply(PacketError.Type.cancel, PacketError.Condition.not_allowed, + CAN_NOT_MODIFY_OWN_AFFILIATION, Buddycloud.NS_ERROR); + return true; } + return false; + } - private boolean attemptToChangeAffiliationOfNodeOwner() { - if (!usersCurrentMembership.getAffiliation().equals(Affiliations.owner)) { - return true; - } - setErrorCondition(PacketError.Type.modify, PacketError.Condition.not_acceptable); - return false; + private boolean attemptToChangeAffiliationOfNodeOwner() { + if (!usersCurrentMembership.getAffiliation().equals(Affiliations.owner)) { + return true; } + setErrorCondition(PacketError.Type.modify, PacketError.Condition.not_acceptable); + return false; + } - private void sendNotifications() throws Exception { + private void sendNotifications() throws Exception { - outQueue.put(response); + outQueue.put(response); - ResultSet subscribers = channelManager.getNodeSubscriptionListeners(node); - - Document document = getDocumentHelper(); - Element message = document.addElement(XMLConstants.MESSAGE_ELEM); - Element pubsub = message.addElement(XMLConstants.EVENT_ELEM); - message.addAttribute(XMLConstants.REMOTE_SERVER_DISCOVER_ATTR, Boolean.FALSE.toString()); - Element affiliations = pubsub.addElement(XMLConstants.AFFILIATIONS_ELEM); - Element affiliation = affiliations.addElement(XMLConstants.AFFILIATION_ELEM); - - pubsub.addNamespace("", JabberPubsub.NS_PUBSUB_EVENT); - message.addAttribute(XMLConstants.FROM_ATTR, request.getTo().toString()); - message.addAttribute(XMLConstants.TYPE_ATTR, "headline"); - - affiliations.addAttribute(XMLConstants.NODE_ATTR, node); - affiliation.addAttribute(XMLConstants.JID_ATTR, requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR)); - affiliation.addAttribute(XMLConstants.AFFILIATION_ELEM, requestedAffiliationElement.attributeValue(XMLConstants.AFFILIATION_ELEM)); - - Message rootElement = new Message(message); - - for (NodeSubscription subscriber : subscribers) { - Message notification = rootElement.createCopy(); - notification.setTo(subscriber.getListener()); - outQueue.put(notification); - } - - Collection admins = getAdminUsers(); - for (JID admin : admins) { - Message notification = rootElement.createCopy(); - notification.setTo(admin); - outQueue.put(notification); - } - } + ResultSet subscribers = channelManager.getNodeSubscriptionListeners(node); + + Document document = getDocumentHelper(); + Element message = document.addElement(XMLConstants.MESSAGE_ELEM); + Element pubsub = message.addElement(XMLConstants.EVENT_ELEM); + message.addAttribute(XMLConstants.REMOTE_SERVER_DISCOVER_ATTR, Boolean.FALSE.toString()); + Element affiliations = pubsub.addElement(XMLConstants.AFFILIATIONS_ELEM); + Element affiliation = affiliations.addElement(XMLConstants.AFFILIATION_ELEM); + + pubsub.addNamespace("", JabberPubsub.NS_PUBSUB_EVENT); + message.addAttribute(XMLConstants.FROM_ATTR, request.getTo().toString()); + message.addAttribute(XMLConstants.TYPE_ATTR, "headline"); - private void saveUpdatedAffiliation() throws NodeStoreException { - JID jid = new JID(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR)); - Affiliations affiliation = Affiliations.valueOf(requestedAffiliationElement.attributeValue(XMLConstants.AFFILIATION_ELEM)); + affiliations.addAttribute(XMLConstants.NODE_ATTR, node); + affiliation.addAttribute(XMLConstants.JID_ATTR, + requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR)); + affiliation.addAttribute(XMLConstants.AFFILIATION_ELEM, + requestedAffiliationElement.attributeValue(XMLConstants.AFFILIATION_ELEM)); - channelManager.setUserAffiliation(node, jid, affiliation); + Message rootElement = new Message(message); + + for (NodeSubscription subscriber : subscribers) { + Message notification = rootElement.createCopy(); + notification.setTo(subscriber.getListener()); + outQueue.put(notification); } - protected boolean isValidStanza() { - try { - requestedAffiliationElement = - request.getElement().element(XMLConstants.PUBSUB_ELEM).element(XMLConstants.AFFILIATIONS_ELEM).element(XMLConstants.AFFILIATION_ELEM); - if ((null == requestedAffiliationElement) || (null == requestedAffiliationElement.attribute(XMLConstants.JID_ATTR)) - || (null == requestedAffiliationElement.attribute(XMLConstants.AFFILIATION_ELEM))) { - setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request); - return false; - } - requestedAffiliation = Affiliations.createFromString(requestedAffiliationElement.attributeValue(XMLConstants.AFFILIATION_ELEM)); - - } catch (NullPointerException e) { - LOGGER.error(e); - setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request); - return false; - } - requestedAffiliationElement.addAttribute(XMLConstants.AFFILIATION_ELEM, requestedAffiliation.toString()); - return true; + Collection admins = getAdminUsers(); + for (JID admin : admins) { + Message notification = rootElement.createCopy(); + notification.setTo(admin); + outQueue.put(notification); } + } + + private void saveUpdatedAffiliation() throws NodeStoreException { + JID jid = new JID(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR)); + Affiliations affiliation = + Affiliations.valueOf(requestedAffiliationElement + .attributeValue(XMLConstants.AFFILIATION_ELEM)); + + channelManager.setUserAffiliation(node, jid, affiliation); + } + + protected boolean isValidStanza() { + try { + requestedAffiliationElement = + request.getElement().element(XMLConstants.PUBSUB_ELEM) + .element(XMLConstants.AFFILIATIONS_ELEM).element(XMLConstants.AFFILIATION_ELEM); + if ((null == requestedAffiliationElement) + || (null == requestedAffiliationElement.attribute(XMLConstants.JID_ATTR)) + || (null == requestedAffiliationElement.attribute(XMLConstants.AFFILIATION_ELEM))) { + setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request); + return false; + } + requestedAffiliation = + Affiliations.createFromString(requestedAffiliationElement + .attributeValue(XMLConstants.AFFILIATION_ELEM)); + + } catch (NullPointerException e) { + LOGGER.error(e); + setErrorCondition(PacketError.Type.modify, PacketError.Condition.bad_request); + return false; + } + requestedAffiliationElement.addAttribute(XMLConstants.AFFILIATION_ELEM, + requestedAffiliation.toString()); + return true; + } - private boolean subscriberHasCurrentAffiliation() throws NodeStoreException { + private boolean subscriberHasCurrentAffiliation() throws NodeStoreException { - usersCurrentMembership = channelManager.getNodeMembership(node, new JID(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR))); + usersCurrentMembership = + channelManager.getNodeMembership(node, + new JID(requestedAffiliationElement.attributeValue(XMLConstants.JID_ATTR))); - if (usersCurrentMembership.getAffiliation().equals(Affiliations.none)) { - setErrorCondition(PacketError.Type.modify, PacketError.Condition.unexpected_request); - return false; - } - return true; + if (usersCurrentMembership.getAffiliation().equals(Affiliations.none)) { + setErrorCondition(PacketError.Type.modify, PacketError.Condition.unexpected_request); + return false; } + return true; + } + + private boolean actorHasPermissionToAuthorize() throws NodeStoreException { - private boolean actorHasPermissionToAuthorize() throws NodeStoreException { - - NodeMembership membership = channelManager.getNodeMembership(node, actor); - if (!membership.getAffiliation().canAuthorize()) { - setErrorCondition(PacketError.Type.auth, PacketError.Condition.not_authorized); - return false; - } - if (membership.getAffiliation().equals(Affiliations.owner)) { - return true; - } - if (requestedAffiliation.equals(Affiliations.moderator) || requestedAffiliation.equals(Affiliations.owner)) { - setErrorCondition(PacketError.Type.auth, PacketError.Condition.forbidden); - return false; - } - return true; + NodeMembership membership = channelManager.getNodeMembership(node, actor); + if (!membership.getAffiliation().canAuthorize()) { + setErrorCondition(PacketError.Type.auth, PacketError.Condition.not_authorized); + return false; + } + if (membership.getAffiliation().equals(Affiliations.owner)) { + return true; + } + if (requestedAffiliation.equals(Affiliations.moderator) + || requestedAffiliation.equals(Affiliations.owner)) { + setErrorCondition(PacketError.Type.auth, PacketError.Condition.forbidden); + return false; } + return true; + } } diff --git a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java index 511d0e7b..eb464533 100644 --- a/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java +++ b/src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/AffiliationEventTest.java @@ -33,414 +33,366 @@ public class AffiliationEventTest extends IQTestHandler { - private IQ request; - private AffiliationEvent event; - private Element element; - private BlockingQueue queue = new LinkedBlockingQueue(); - - private String subscriber = "francisco@denmark.lit"; - private String node = "/user/pamela@denmark.lit/posts"; - private JID jid = new JID("juliet@shakespeare.lit"); - - private ChannelManager channelManager; - - @Before - public void setUp() throws Exception { - - channelManager = Mockito.mock(ChannelManager.class); - Configuration.getInstance().putProperty( - Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, Boolean.TRUE.toString()); - Mockito.when(channelManager.nodeExists(Mockito.anyString())) - .thenReturn(true); - - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(jid))).thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.subscribed, - Affiliations.owner, null)); - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(new JID("francisco@denmark.lit")))) - .thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.none, - Affiliations.publisher, null)); - - queue = new LinkedBlockingQueue(); - event = new AffiliationEvent(queue, channelManager); - request = readStanzaAsIq("/iq/pubsub/affiliation/affiliationChange.stanza"); - event.setServerDomain("shakespeare.lit"); - - element = new BaseElement("affiliations"); - element.addAttribute("node", node); - } + private IQ request; + private AffiliationEvent event; + private Element element; + private BlockingQueue queue = new LinkedBlockingQueue(); + + private String subscriber = "francisco@denmark.lit"; + private String node = "/user/pamela@denmark.lit/posts"; + private JID jid = new JID("juliet@shakespeare.lit"); + + private ChannelManager channelManager; + + @Before + public void setUp() throws Exception { + + channelManager = Mockito.mock(ChannelManager.class); + Configuration.getInstance().putProperty(Configuration.CONFIGURATION_LOCAL_DOMAIN_CHECKER, + Boolean.TRUE.toString()); + Mockito.when(channelManager.nodeExists(Mockito.anyString())).thenReturn(true); + + Mockito.when(channelManager.getNodeMembership(Mockito.anyString(), Mockito.eq(jid))) + .thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.owner, null)); + Mockito.when( + channelManager.getNodeMembership(Mockito.anyString(), + Mockito.eq(new JID("francisco@denmark.lit")))).thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.none, Affiliations.publisher, null)); + Mockito.when(channelManager.isEphemeralNode(Mockito.anyString())).thenReturn(false); + + queue = new LinkedBlockingQueue(); + event = new AffiliationEvent(queue, channelManager); + request = readStanzaAsIq("/iq/pubsub/affiliation/affiliationChange.stanza"); + event.setServerDomain("shakespeare.lit"); + + element = new BaseElement("affiliations"); + element.addAttribute("node", node); + } + + @Test + public void testPassingAffiliationsAsElementNameReturnsTrue() { + Element element = new BaseElement("affiliations"); + Assert.assertTrue(event.accept(element)); + } + + @Test + public void testPassingNotAffiliationsAsElementNameReturnsFalse() { + Element element = new BaseElement("not-affiliations"); + Assert.assertFalse(event.accept(element)); + } + + @Test + public void testNotProvidingNodeAttributeReturnsErrorStanza() throws Exception { + BaseElement element = new BaseElement("affiliations"); + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.modify, error.getType()); + Assert.assertEquals("nodeid-required", error.getApplicationConditionName()); + } + + @Test + public void testNotProvidingAffiliationChildNodeReturnsErrorStanza() throws Exception { + + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "", "")); + + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.modify, error.getType()); + Assert.assertEquals(PacketError.Condition.bad_request, error.getCondition()); + } + + @Test + public void testNotProvidingJidAttributeReturnsErrorStanza() throws Exception { + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "jid='francisco@denmark.lit'", "")); + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.modify, error.getType()); + Assert.assertEquals(PacketError.Condition.bad_request, error.getCondition()); + } + + @Test + public void testNotProvidingAffiliationAttributeReturnsErrorStanza() throws Exception { + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "affiliation='member'", "")); + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.modify, error.getType()); + Assert.assertEquals(PacketError.Condition.bad_request, error.getCondition()); + } + + @Test + public void testNodeStoreExceptionResultsInInternalServerErrorStanza() throws Exception { + + Mockito.when(channelManager.nodeExists(node)).thenThrow(NodeStoreException.class); + event.setChannelManager(channelManager); + + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.wait, error.getType()); + Assert.assertEquals(PacketError.Condition.internal_server_error, error.getCondition()); + } + + @Test + public void testNonExistantNodeRetunsErrorStanza() throws Exception { + + Mockito.when(channelManager.nodeExists(node)).thenReturn(false); + event.setChannelManager(channelManager); + + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.cancel, error.getType()); + Assert.assertEquals(PacketError.Condition.item_not_found, error.getCondition()); + } + + @Test + public void userWithoutAffiliationReturnsErrorStanza() throws Exception { + + Mockito.when(channelManager.nodeExists(node)).thenReturn(true); + Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.none, null)); + + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.auth, error.getType()); + Assert.assertEquals(PacketError.Condition.not_authorized, error.getCondition()); + } + + @Test + public void userWhoIsntOwnerOrModeratorCantUpdateAffiliation() throws Exception { + + Mockito.when(channelManager.getNodeMembership(Mockito.anyString(), Mockito.eq(jid))) + .thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.publisher, + null)); + + event.setChannelManager(channelManager); + + event.process(element, jid, request, null); + Packet response = queue.poll(); + + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.auth, error.getType()); + Assert.assertEquals(PacketError.Condition.not_authorized, error.getCondition()); + } + + @Test + public void userMustHaveExistingAffiliationToUpdate() throws Exception { + + Mockito.when(channelManager.getNodeMembership(Mockito.anyString(), Mockito.eq(jid))) + .thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.owner, null)); + Mockito.when( + channelManager.getNodeMembership(Mockito.anyString(), + Mockito.eq(new JID("francisco@denmark.lit")))).thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.none, Affiliations.none, null)); - @Test - public void testPassingAffiliationsAsElementNameReturnsTrue() { - Element element = new BaseElement("affiliations"); - Assert.assertTrue(event.accept(element)); - } + event.process(element, jid, request, null); + Packet response = queue.poll(); - @Test - public void testPassingNotAffiliationsAsElementNameReturnsFalse() { - Element element = new BaseElement("not-affiliations"); - Assert.assertFalse(event.accept(element)); - } + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.modify, error.getType()); + Assert.assertEquals(PacketError.Condition.unexpected_request, error.getCondition()); + } - @Test - public void testNotProvidingNodeAttributeReturnsErrorStanza() - throws Exception { - BaseElement element = new BaseElement("affiliations"); - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.modify, error.getType()); - Assert.assertEquals("nodeid-required", - error.getApplicationConditionName()); - } + @Test + public void notPossibleToChangeTheAffiliationOfNodeOwner() throws Exception { - @Test - public void testNotProvidingAffiliationChildNodeReturnsErrorStanza() - throws Exception { + Mockito.when(channelManager.nodeExists(node)).thenReturn(true); - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst( - "", - "")); + Mockito.when(channelManager.getNodeMembership(Mockito.anyString(), Mockito.eq(jid))) + .thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.owner, null)); + Mockito.when( + channelManager.getNodeMembership(Mockito.anyString(), + Mockito.eq(new JID("francisco@denmark.lit")))).thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.none, Affiliations.owner, null)); - event.process(element, jid, request, null); - Packet response = queue.poll(); + event.process(element, jid, request, null); + Packet response = queue.poll(); + PacketError error = response.getError(); + Assert.assertNotNull(error); + Assert.assertEquals(PacketError.Type.modify, error.getType()); + Assert.assertEquals(PacketError.Condition.not_acceptable, error.getCondition()); + + } + + @Test + public void passingInvalidAffiliationTypeSetsAffiliationToNone() throws Exception { + + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "affiliation='member'", "affiliation='i-can-haz-all-the-items'")); - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.modify, error.getType()); - Assert.assertEquals(PacketError.Condition.bad_request, - error.getCondition()); - } - - @Test - public void testNotProvidingJidAttributeReturnsErrorStanza() - throws Exception { - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst("jid='francisco@denmark.lit'", "")); - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.modify, error.getType()); - Assert.assertEquals(PacketError.Condition.bad_request, - error.getCondition()); - } + ResultSet subscriptions = + new ResultSetImpl(new ArrayList()); + Mockito.when(channelManager.getNodeSubscriptionListeners(Mockito.anyString())).thenReturn( + subscriptions); + + Mockito.when(channelManager.nodeExists(node)).thenReturn(true); + + event.setChannelManager(channelManager); + event.process(element, jid, request, null); + + Mockito.verify(channelManager).setUserAffiliation(Mockito.anyString(), Mockito.any(JID.class), + Mockito.eq(Affiliations.none)); + } + + @Test + public void testPassingValidAffiliationTypeUpdatesAffiliation() throws Exception { + + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "affiliation='member'", "affiliation='moderator'")); + + Mockito.when(channelManager.getNodeSubscriptionListeners(Mockito.anyString())).thenReturn( + new ResultSetImpl(new ArrayList())); + + Mockito.when(channelManager.nodeExists(node)).thenReturn(true); + + event.setChannelManager(channelManager); + event.process(element, jid, request, null); + + Mockito.verify(channelManager).setUserAffiliation(Mockito.anyString(), Mockito.any(JID.class), + Mockito.eq(Affiliations.moderator)); + } + + @Test + public void testPassingValidAffiliationSendsOutExpectedNotifications() throws Exception { + + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "affiliation='member'", "affiliation='moderator'")); - @Test - public void testNotProvidingAffiliationAttributeReturnsErrorStanza() - throws Exception { - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst("affiliation='member'", "")); - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.modify, error.getType()); - Assert.assertEquals(PacketError.Condition.bad_request, - error.getCondition()); - } - - @Test - public void testNodeStoreExceptionResultsInInternalServerErrorStanza() - throws Exception { - - Mockito.when(channelManager.nodeExists(node)).thenThrow( - NodeStoreException.class); - event.setChannelManager(channelManager); - - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.wait, error.getType()); - Assert.assertEquals(PacketError.Condition.internal_server_error, - error.getCondition()); - } + ArrayList subscribers = new ArrayList(); + subscribers.add(new NodeSubscriptionMock(new JID("romeo@shakespeare.lit"))); + subscribers.add(new NodeSubscriptionMock(new JID("hamlet@shakespeare.lit"))); + + Mockito.doReturn(new ResultSetImpl(subscribers)).when(channelManager) + .getNodeSubscriptionListeners(Mockito.anyString()); + + event.setChannelManager(channelManager); + event.process(element, jid, request, null); + + // One iq result, 2 user notifications and 2 admin notifications + Assert.assertEquals(5, queue.size()); + + boolean hasIqResult = false; + boolean hasNotification1 = false; + boolean hasNotification2 = false; + + for (int i = 0; i < 3; ++i) { + Packet packet = queue.poll(); - @Test - public void testNonExistantNodeRetunsErrorStanza() throws Exception { + if (packet.getElement().getName().equals("iq") + && packet.getTo().equals(new JID("francisco@denmark.lit/barracks"))) { + hasIqResult = true; + } - Mockito.when(channelManager.nodeExists(node)).thenReturn(false); - event.setChannelManager(channelManager); + if (packet.getElement().getName().equals("message") + && packet.getTo().equals(new JID("romeo@shakespeare.lit"))) { + hasNotification1 = true; - event.process(element, jid, request, null); - Packet response = queue.poll(); + Assert.assertEquals(node, packet.getElement().element("event").element("affiliations") + .attributeValue("node")); + Assert.assertTrue(packet.toXML().contains(JabberPubsub.NS_PUBSUB_EVENT)); + Assert.assertEquals(Affiliations.moderator.toString(), packet.getElement().element("event") + .element("affiliations").element("affiliation").attributeValue("affiliation")); + Assert.assertEquals(subscriber, packet.getElement().element("event") + .element("affiliations").element("affiliation").attributeValue("jid")); + } + + if (packet.getElement().getName().equals("message") + && packet.getTo().equals(new JID("hamlet@shakespeare.lit"))) { + hasNotification2 = true; - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.cancel, error.getType()); - Assert.assertEquals(PacketError.Condition.item_not_found, - error.getCondition()); + Assert.assertEquals(node, packet.getElement().element("event").element("affiliations") + .attributeValue("node")); + Assert.assertTrue(packet.toXML().contains(JabberPubsub.NS_PUBSUB_EVENT)); + Assert.assertEquals(Affiliations.moderator.toString(), packet.getElement().element("event") + .element("affiliations").element("affiliation").attributeValue("affiliation")); + Assert.assertEquals(subscriber, packet.getElement().element("event") + .element("affiliations").element("affiliation").attributeValue("jid")); + } } - @Test - public void userWithoutAffiliationReturnsErrorStanza() throws Exception { - - Mockito.when(channelManager.nodeExists(node)).thenReturn(true); - Mockito.when(channelManager.getNodeMembership(node, jid)).thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.subscribed, - Affiliations.none, null)); - - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.auth, error.getType()); - Assert.assertEquals(PacketError.Condition.not_authorized, - error.getCondition()); - } - - @Test - public void userWhoIsntOwnerOrModeratorCantUpdateAffiliation() - throws Exception { - - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(jid))).thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.subscribed, - Affiliations.publisher, null)); - - event.setChannelManager(channelManager); - - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.auth, error.getType()); - Assert.assertEquals(PacketError.Condition.not_authorized, - error.getCondition()); - } - - @Test - public void userMustHaveExistingAffiliationToUpdate() throws Exception { - - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(jid))).thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.subscribed, - Affiliations.owner, null)); - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(new JID("francisco@denmark.lit")))) - .thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.none, - Affiliations.none, null)); - - event.process(element, jid, request, null); - Packet response = queue.poll(); - - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.modify, error.getType()); - Assert.assertEquals(PacketError.Condition.unexpected_request, - error.getCondition()); - } - - @Test - public void notPossibleToChangeTheAffiliationOfNodeOwner() throws Exception { - - Mockito.when(channelManager.nodeExists(node)).thenReturn(true); - - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(jid))).thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.subscribed, - Affiliations.owner, null)); - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(new JID("francisco@denmark.lit")))) - .thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.none, - Affiliations.owner, null)); - - event.process(element, jid, request, null); - Packet response = queue.poll(); - PacketError error = response.getError(); - Assert.assertNotNull(error); - Assert.assertEquals(PacketError.Type.modify, error.getType()); - Assert.assertEquals(PacketError.Condition.not_acceptable, - error.getCondition()); - - } - - @Test - public void passingInvalidAffiliationTypeSetsAffiliationToNone() - throws Exception { - - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst("affiliation='member'", - "affiliation='i-can-haz-all-the-items'")); - - ResultSet subscriptions = new ResultSetImpl( - new ArrayList()); - Mockito.when( - channelManager.getNodeSubscriptionListeners(Mockito.anyString())) - .thenReturn(subscriptions); - - Mockito.when(channelManager.nodeExists(node)).thenReturn(true); - - event.setChannelManager(channelManager); - event.process(element, jid, request, null); - - Mockito.verify(channelManager).setUserAffiliation(Mockito.anyString(), - Mockito.any(JID.class), Mockito.eq(Affiliations.none)); - } - - @Test - public void testPassingValidAffiliationTypeUpdatesAffiliation() - throws Exception { - - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst("affiliation='member'", "affiliation='moderator'")); - - Mockito.when( - channelManager.getNodeSubscriptionListeners(Mockito.anyString())) - .thenReturn( - new ResultSetImpl( - new ArrayList())); - - Mockito.when(channelManager.nodeExists(node)).thenReturn(true); - - event.setChannelManager(channelManager); - event.process(element, jid, request, null); - - Mockito.verify(channelManager).setUserAffiliation(Mockito.anyString(), - Mockito.any(JID.class), Mockito.eq(Affiliations.moderator)); - } - - @Test - public void testPassingValidAffiliationSendsOutExpectedNotifications() - throws Exception { - - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst("affiliation='member'", "affiliation='moderator'")); - - ArrayList subscribers = new ArrayList(); - subscribers.add(new NodeSubscriptionMock(new JID( - "romeo@shakespeare.lit"))); - subscribers.add(new NodeSubscriptionMock(new JID( - "hamlet@shakespeare.lit"))); - - Mockito.doReturn(new ResultSetImpl(subscribers)) - .when(channelManager) - .getNodeSubscriptionListeners(Mockito.anyString()); - - event.setChannelManager(channelManager); - event.process(element, jid, request, null); - - // One iq result, 2 user notifications and 2 admin notifications - Assert.assertEquals(5, queue.size()); - - boolean hasIqResult = false; - boolean hasNotification1 = false; - boolean hasNotification2 = false; - - for (int i = 0; i < 3; ++i) { - Packet packet = queue.poll(); - - if (packet.getElement().getName().equals("iq") - && packet.getTo().equals( - new JID("francisco@denmark.lit/barracks"))) { - hasIqResult = true; - } - - if (packet.getElement().getName().equals("message") - && packet.getTo().equals(new JID("romeo@shakespeare.lit"))) { - hasNotification1 = true; - - Assert.assertEquals(node, packet.getElement().element("event") - .element("affiliations").attributeValue("node")); - Assert.assertTrue(packet.toXML().contains( - JabberPubsub.NS_PUBSUB_EVENT)); - Assert.assertEquals(Affiliations.moderator.toString(), packet - .getElement().element("event").element("affiliations") - .element("affiliation").attributeValue("affiliation")); - Assert.assertEquals( - subscriber, - packet.getElement().element("event") - .element("affiliations").element("affiliation") - .attributeValue("jid")); - } - - if (packet.getElement().getName().equals("message") - && packet.getTo().equals(new JID("hamlet@shakespeare.lit"))) { - hasNotification2 = true; - - Assert.assertEquals(node, packet.getElement().element("event") - .element("affiliations").attributeValue("node")); - Assert.assertTrue(packet.toXML().contains( - JabberPubsub.NS_PUBSUB_EVENT)); - Assert.assertEquals(Affiliations.moderator.toString(), packet - .getElement().element("event").element("affiliations") - .element("affiliation").attributeValue("affiliation")); - Assert.assertEquals( - subscriber, - packet.getElement().element("event") - .element("affiliations").element("affiliation") - .attributeValue("jid")); - } - } - - assertTrue("IQ result not sent", hasIqResult); - assertTrue("Notification to romeo@shakespeare.lit not sent", - hasNotification1); - assertTrue("Notification to hamlet@shakespeare.lit not sent", - hasNotification2); - } - - public void canNotUpdateOwnAffiliation() throws Exception { - - event.process(element, jid, request, null); - - IQ response = (IQ) queue.poll(); - Assert.assertEquals(IQ.Type.error, response.getType()); - PacketError error = response.getError(); - Assert.assertEquals(PacketError.Type.cancel, error.getType()); - Assert.assertEquals(PacketError.Condition.not_allowed, - error.getCondition()); - Assert.assertEquals(event.CAN_NOT_MODIFY_OWN_AFFILIATION, - error.getApplicationConditionName()); - Assert.assertEquals(Buddycloud.NS_ERROR, - error.getApplicationConditionNamespaceURI()); - } - - @Test - public void moderatorsCantCreateOtherModerators() throws Exception { - IQ request = toIq(readStanzaAsString( - "/iq/pubsub/affiliation/affiliationChange.stanza") - .replaceFirst("affiliation='member'", "affiliation='moderator'")); - - Mockito.when( - channelManager.getNodeMembership(Mockito.anyString(), - Mockito.eq(jid))).thenReturn( - new NodeMembershipImpl(node, jid, Subscriptions.subscribed, - Affiliations.moderator, null)); - - event.process(element, jid, request, null); - - IQ response = (IQ) queue.poll(); - Assert.assertEquals(IQ.Type.error, response.getType()); - PacketError error = response.getError(); - Assert.assertEquals(PacketError.Type.auth, error.getType()); - Assert.assertEquals(PacketError.Condition.forbidden, - error.getCondition()); - } + assertTrue("IQ result not sent", hasIqResult); + assertTrue("Notification to romeo@shakespeare.lit not sent", hasNotification1); + assertTrue("Notification to hamlet@shakespeare.lit not sent", hasNotification2); + } + + public void canNotUpdateOwnAffiliation() throws Exception { + + event.process(element, jid, request, null); + + IQ response = (IQ) queue.poll(); + Assert.assertEquals(IQ.Type.error, response.getType()); + PacketError error = response.getError(); + Assert.assertEquals(PacketError.Type.cancel, error.getType()); + Assert.assertEquals(PacketError.Condition.not_allowed, error.getCondition()); + Assert.assertEquals(event.CAN_NOT_MODIFY_OWN_AFFILIATION, error.getApplicationConditionName()); + Assert.assertEquals(Buddycloud.NS_ERROR, error.getApplicationConditionNamespaceURI()); + } + + @Test + public void moderatorsCantCreateOtherModerators() throws Exception { + IQ request = + toIq(readStanzaAsString("/iq/pubsub/affiliation/affiliationChange.stanza").replaceFirst( + "affiliation='member'", "affiliation='moderator'")); + + Mockito.when(channelManager.getNodeMembership(Mockito.anyString(), Mockito.eq(jid))) + .thenReturn( + new NodeMembershipImpl(node, jid, Subscriptions.subscribed, Affiliations.moderator, + null)); + + event.process(element, jid, request, null); + + IQ response = (IQ) queue.poll(); + Assert.assertEquals(IQ.Type.error, response.getType()); + PacketError error = response.getError(); + Assert.assertEquals(PacketError.Type.auth, error.getType()); + Assert.assertEquals(PacketError.Condition.forbidden, error.getCondition()); + } + + @Test + public void ephemeralNodesCanOnlyHaveOwnersAndModerators() throws Exception { + + Mockito.when(channelManager.isEphemeralNode(Mockito.anyString())).thenReturn(true); + + event.process(element, jid, request, null); + + IQ response = (IQ) queue.poll(); + Assert.assertEquals(IQ.Type.error, response.getType()); + PacketError error = response.getError(); + Assert.assertEquals(PacketError.Type.cancel, error.getType()); + Assert.assertEquals(PacketError.Condition.not_allowed, error.getCondition()); + } }