Commit fd99960a authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Update implementation based on...

Update implementation based on http://www.jabber.org/jeps/tmp/jep-0060-1.8.html#owner-subscriptions and http://www.jabber.org/jeps/tmp/jep-0060-1.8.html#owner-affiliations. JM-672

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3839 b35dd754-fafc-0310-a699-88a17e54d16e
parent 9d379819
...@@ -1861,33 +1861,48 @@ public abstract class Node { ...@@ -1861,33 +1861,48 @@ public abstract class Node {
} }
/** /**
* Sends the list of affiliated entities with the node to the owner that sent the IQ * Sends the list of affiliations with the node to the owner that sent the IQ
* request. * request.
* *
* @param iqRequest IQ request sent by an owner of the node. * @param iqRequest IQ request sent by an owner of the node.
*/ */
void sendAffiliatedEntities(IQ iqRequest) { void sendAffiliations(IQ iqRequest) {
IQ reply = IQ.createResultIQ(iqRequest); IQ reply = IQ.createResultIQ(iqRequest);
Element childElement = iqRequest.getChildElement().createCopy(); Element childElement = iqRequest.getChildElement().createCopy();
reply.setChildElement(childElement); reply.setChildElement(childElement);
for (NodeAffiliate affiliate : affiliates) { for (NodeAffiliate affiliate : affiliates) {
Collection<NodeSubscription> subscriptions = affiliate.getSubscriptions(); if (affiliate.getAffiliation() == NodeAffiliate.Affiliation.none) {
if (subscriptions.isEmpty()) { continue;
Element entity = childElement.addElement("entity");
entity.addAttribute("jid", affiliate.getJID().toString());
entity.addAttribute("affiliation", affiliate.getAffiliation().name());
entity.addAttribute("subscription", "none");
} }
else { Element entity = childElement.addElement("affiliation");
for (NodeSubscription subscription : subscriptions) { entity.addAttribute("jid", affiliate.getJID().toString());
Element entity = childElement.addElement("entity"); entity.addAttribute("affiliation", affiliate.getAffiliation().name());
entity.addAttribute("jid", subscription.getJID().toString()); }
entity.addAttribute("affiliation", affiliate.getAffiliation().name()); }
entity.addAttribute("subscription", subscription.getState().name());
if (isMultipleSubscriptionsEnabled()) { /**
entity.addAttribute("subid", subscription.getID()); * Sends the list of subscriptions with the node to the owner that sent the IQ
} * request.
*
* @param iqRequest IQ request sent by an owner of the node.
*/
void sendSubscriptions(IQ iqRequest) {
IQ reply = IQ.createResultIQ(iqRequest);
Element childElement = iqRequest.getChildElement().createCopy();
reply.setChildElement(childElement);
for (NodeAffiliate affiliate : affiliates) {
for (NodeSubscription subscription : affiliate.getSubscriptions()) {
if (subscription.isAuthorizationPending()) {
continue;
}
Element entity = childElement.addElement("subscription");
entity.addAttribute("jid", subscription.getJID().toString());
//entity.addAttribute("affiliation", affiliate.getAffiliation().name());
entity.addAttribute("subscription", subscription.getState().name());
if (isMultipleSubscriptionsEnabled()) {
entity.addAttribute("subid", subscription.getID());
} }
} }
} }
......
...@@ -221,14 +221,25 @@ public class PubSubEngine { ...@@ -221,14 +221,25 @@ public class PubSubEngine {
deleteNode(iq, action); deleteNode(iq, action);
return true; return true;
} }
action = childElement.element("entities"); action = childElement.element("subscriptions");
if (action != null) { if (action != null) {
if (IQ.Type.get == iq.getType()) { if (IQ.Type.get == iq.getType()) {
// Owner requests all affiliated entities // Owner requests all affiliated entities
getAffiliatedEntities(iq, action); getNodeSubscriptions(iq, action);
} }
else { else {
modifyAffiliations(iq, action); modifyNodeSubscriptions(iq, action);
}
return true;
}
action = childElement.element("affiliations");
if (action != null) {
if (IQ.Type.get == iq.getType()) {
// Owner requests all affiliated entities
getNodeAffiliations(iq, action);
}
else {
modifyNodeAffiliations(iq, action);
} }
return true; return true;
} }
...@@ -1397,8 +1408,8 @@ public class PubSubEngine { ...@@ -1397,8 +1408,8 @@ public class PubSubEngine {
router.route(IQ.createResultIQ(iq)); router.route(IQ.createResultIQ(iq));
} }
private void getAffiliatedEntities(IQ iq, Element affiliatedElement) { private void getNodeSubscriptions(IQ iq, Element affiliationsElement) {
String nodeID = affiliatedElement.attributeValue("node"); String nodeID = affiliationsElement.attributeValue("node");
if (nodeID == null) { if (nodeID == null) {
// NodeID was not provided. Return bad-request error. // NodeID was not provided. Return bad-request error.
sendErrorPacket(iq, PacketError.Condition.bad_request, null); sendErrorPacket(iq, PacketError.Condition.bad_request, null);
...@@ -1416,11 +1427,11 @@ public class PubSubEngine { ...@@ -1416,11 +1427,11 @@ public class PubSubEngine {
return; return;
} }
// Ask the node to send the list of affiliated entities to the owner // Ask the node to send the list of subscriptions to the owner
node.sendAffiliatedEntities(iq); node.sendSubscriptions(iq);
} }
private void modifyAffiliations(IQ iq, Element entitiesElement) { private void modifyNodeSubscriptions(IQ iq, Element entitiesElement) {
String nodeID = entitiesElement.attributeValue("node"); String nodeID = entitiesElement.attributeValue("node");
if (nodeID == null) { if (nodeID == null) {
// NodeID was not provided. Return bad-request error. // NodeID was not provided. Return bad-request error.
...@@ -1440,74 +1451,124 @@ public class PubSubEngine { ...@@ -1440,74 +1451,124 @@ public class PubSubEngine {
} }
IQ reply = IQ.createResultIQ(iq); IQ reply = IQ.createResultIQ(iq);
Collection<JID> invalidAffiliates = new ArrayList<JID>();
// Process modifications or creations of affiliations and subscriptions. // Process modifications or creations of affiliations and subscriptions.
for (Iterator it = entitiesElement.elementIterator("entity"); it.hasNext();) { for (Iterator it = entitiesElement.elementIterator("subscription"); it.hasNext();) {
Element entity = (Element) it.next(); Element entity = (Element) it.next();
JID subscriber = new JID(entity.attributeValue("jid")); JID subscriber = new JID(entity.attributeValue("jid"));
// TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field. // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
JID owner = new JID(subscriber.toBareJID()); JID owner = new JID(subscriber.toBareJID());
String newAffiliation = entity.attributeValue("affiliation");
String subStatus = entity.attributeValue("subscription"); String subStatus = entity.attributeValue("subscription");
String subID = entity.attributeValue("subid"); String subID = entity.attributeValue("subid");
if (newAffiliation != null) { // Process subscriptions changes
// Get current affiliation of this user (if any) // Get current subscription (if any)
NodeAffiliate affiliate = node.getAffiliate(owner); NodeSubscription subscription = null;
if (node.isMultipleSubscriptionsEnabled()) {
// Check that we are not removing the only owner of the node if (subID != null) {
if (affiliate != null && !affiliate.getAffiliation().name().equals(newAffiliation)) { subscription = node.getSubscription(subID);
// Trying to modify an existing affiliation
if (affiliate.getAffiliation() == NodeAffiliate.Affiliation.owner &&
node.getOwners().size() == 1) {
// Trying to remove the unique owner of the node. Include in error answer.
invalidAffiliates.add(owner);
continue;
}
}
// Owner is setting affiliations for new entities or modifying
// existing affiliations
if ("owner".equals(newAffiliation)) {
node.addOwner(owner);
}
else if ("publisher".equals(newAffiliation)) {
node.addPublisher(owner);
}
else if ("none".equals(newAffiliation)) {
node.addNoneAffiliation(owner);
}
else {
node.addOutcast(owner);
} }
} }
// Process subscriptions changes else {
if (subStatus != null) { subscription = node.getSubscription(subscriber);
// Get current subscription (if any) }
NodeSubscription subscription = null; if ("none".equals(subStatus) && subscription != null) {
if (node.isMultipleSubscriptionsEnabled()) { // Owner is cancelling an existing subscription
if (subID != null) { node.cancelSubscription(subscription);
subscription = node.getSubscription(subID); }
} else if ("subscribed".equals(subStatus)) {
if (subscription != null) {
// Owner is approving a subscription (i.e. making active)
node.approveSubscription(subscription, true);
} }
else { else {
subscription = node.getSubscription(subscriber); // Owner is creating a subscription for an entity to the node
node.createSubscription(null, owner, subscriber, false, null);
} }
if ("none".equals(subStatus) && subscription != null) { }
// Owner is cancelling an existing subscription }
node.cancelSubscription(subscription);
} // Send reply
else if ("subscribed".equals(subStatus)) { router.route(reply);
if (subscription != null) { }
// Owner is approving a subscription (i.e. making active)
node.approveSubscription(subscription, true); private void getNodeAffiliations(IQ iq, Element affiliationsElement) {
} String nodeID = affiliationsElement.attributeValue("node");
else { if (nodeID == null) {
// Owner is creating a subscription for an entity to the node // NodeID was not provided. Return bad-request error.
node.createSubscription(null, owner, subscriber, false, null); sendErrorPacket(iq, PacketError.Condition.bad_request, null);
} return;
}
Node node = service.getNode(nodeID);
if (node == null) {
// Node does not exist. Return item-not-found error.
sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
return;
}
if (!node.isAdmin(iq.getFrom())) {
// Requesting entity is prohibited from getting affiliates list. Return forbidden error.
sendErrorPacket(iq, PacketError.Condition.forbidden, null);
return;
}
// Ask the node to send the list of affiliations to the owner
node.sendAffiliations(iq);
}
private void modifyNodeAffiliations(IQ iq, Element entitiesElement) {
String nodeID = entitiesElement.attributeValue("node");
if (nodeID == null) {
// NodeID was not provided. Return bad-request error.
sendErrorPacket(iq, PacketError.Condition.bad_request, null);
return;
}
Node node = service.getNode(nodeID);
if (node == null) {
// Node does not exist. Return item-not-found error.
sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
return;
}
if (!node.isAdmin(iq.getFrom())) {
// Requesting entity is prohibited from getting affiliates list. Return forbidden error.
sendErrorPacket(iq, PacketError.Condition.forbidden, null);
return;
}
IQ reply = IQ.createResultIQ(iq);
Collection<JID> invalidAffiliates = new ArrayList<JID>();
// Process modifications or creations of affiliations
for (Iterator it = entitiesElement.elementIterator("affiliation"); it.hasNext();) {
Element affiliation = (Element) it.next();
JID owner = new JID(affiliation.attributeValue("jid"));
String newAffiliation = affiliation.attributeValue("affiliation");
// Get current affiliation of this user (if any)
NodeAffiliate affiliate = node.getAffiliate(owner);
// Check that we are not removing the only owner of the node
if (affiliate != null && !affiliate.getAffiliation().name().equals(newAffiliation)) {
// Trying to modify an existing affiliation
if (affiliate.getAffiliation() == NodeAffiliate.Affiliation.owner &&
node.getOwners().size() == 1) {
// Trying to remove the unique owner of the node. Include in error answer.
invalidAffiliates.add(owner);
continue;
} }
} }
// Owner is setting affiliations for new entities or modifying
// existing affiliations
if ("owner".equals(newAffiliation)) {
node.addOwner(owner);
}
else if ("publisher".equals(newAffiliation)) {
node.addPublisher(owner);
}
else if ("none".equals(newAffiliation)) {
node.addNoneAffiliation(owner);
}
else {
node.addOutcast(owner);
}
} }
// Process invalid entities that tried to remove node owners. Send original affiliation // Process invalid entities that tried to remove node owners. Send original affiliation
...@@ -1516,30 +1577,15 @@ public class PubSubEngine { ...@@ -1516,30 +1577,15 @@ public class PubSubEngine {
reply.setError(PacketError.Condition.not_acceptable); reply.setError(PacketError.Condition.not_acceptable);
Element child = Element child =
reply.setChildElement("pubsub", "http://jabber.org/protocol/pubsub#owner"); reply.setChildElement("pubsub", "http://jabber.org/protocol/pubsub#owner");
Element entities = child.addElement("entities"); Element entities = child.addElement("affiliations");
if (!node.isRootCollectionNode()) { if (!node.isRootCollectionNode()) {
entities.addAttribute("node", node.getNodeID()); entities.addAttribute("node", node.getNodeID());
} }
for (JID affiliateJID : invalidAffiliates) { for (JID affiliateJID : invalidAffiliates) {
NodeAffiliate affiliate = node.getAffiliate(affiliateJID); NodeAffiliate affiliate = node.getAffiliate(affiliateJID);
Collection<NodeSubscription> subscriptions = affiliate.getSubscriptions(); Element entity = entities.addElement("affiliation");
if (subscriptions.isEmpty()) { entity.addAttribute("jid", affiliate.getJID().toString());
Element entity = entities.addElement("entity"); entity.addAttribute("affiliation", affiliate.getAffiliation().name());
entity.addAttribute("jid", affiliate.getJID().toString());
entity.addAttribute("affiliation", affiliate.getAffiliation().name());
entity.addAttribute("subscription", "none");
}
else {
for (NodeSubscription subscription : subscriptions) {
Element entity = entities.addElement("entity");
entity.addAttribute("jid", subscription.getJID().toString());
entity.addAttribute("affiliation", affiliate.getAffiliation().name());
entity.addAttribute("subscription", subscription.getState().name());
if (node.isMultipleSubscriptionsEnabled()) {
entity.addAttribute("subid", subscription.getID());
}
}
}
} }
} }
// Send reply // Send reply
......
...@@ -512,6 +512,8 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di ...@@ -512,6 +512,8 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
features.add("http://jabber.org/protocol/pubsub#meta-data"); features.add("http://jabber.org/protocol/pubsub#meta-data");
// Node owners may modify affiliations // Node owners may modify affiliations
features.add("http://jabber.org/protocol/pubsub#modify-affiliations"); features.add("http://jabber.org/protocol/pubsub#modify-affiliations");
// Node owners may manage subscriptions.
features.add("http://jabber.org/protocol/pubsub#manage-subscriptions");
// A single entity may subscribe to a node multiple times // A single entity may subscribe to a node multiple times
features.add("http://jabber.org/protocol/pubsub#multi-subscribe"); features.add("http://jabber.org/protocol/pubsub#multi-subscribe");
// The outcast affiliation is supported // The outcast affiliation is supported
...@@ -530,8 +532,12 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di ...@@ -530,8 +532,12 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
features.add("http://jabber.org/protocol/pubsub#retract-items"); features.add("http://jabber.org/protocol/pubsub#retract-items");
// Retrieval of current affiliations is supported // Retrieval of current affiliations is supported
features.add("http://jabber.org/protocol/pubsub#retrieve-affiliations"); features.add("http://jabber.org/protocol/pubsub#retrieve-affiliations");
// Retrieval of default node configuration is supported.
features.add("http://jabber.org/protocol/pubsub#retrieve-default");
// Item retrieval is supported // Item retrieval is supported
features.add("http://jabber.org/protocol/pubsub#retrieve-items"); features.add("http://jabber.org/protocol/pubsub#retrieve-items");
// Retrieval of current subscriptions is supported.
features.add("http://jabber.org/protocol/pubsub#retrieve-subscriptions");
// Subscribing and unsubscribing are supported // Subscribing and unsubscribing are supported
features.add("http://jabber.org/protocol/pubsub#subscribe"); features.add("http://jabber.org/protocol/pubsub#subscribe");
// Configuration of subscription options is supported // Configuration of subscription options is supported
......
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