use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.
the class IQPEPHandler method getUserItems.
/**
* Implements UserItemsProvider, adding PEP related items to a disco#items
* result.
*/
@Override
public Iterator<Element> getUserItems(String name, JID senderJID) {
ArrayList<Element> items = new ArrayList<>();
String recipientJID = XMPPServer.getInstance().createJID(name, null, true).toBareJID();
PEPService pepService = pepServiceManager.getPEPService(recipientJID);
if (pepService != null) {
CollectionNode rootNode = pepService.getRootCollectionNode();
Element defaultItem = DocumentHelper.createElement("item");
defaultItem.addAttribute("jid", recipientJID);
for (Node node : pepService.getNodes()) {
// Do not include the root node as an item element.
if (node == rootNode) {
continue;
}
AccessModel accessModel = node.getAccessModel();
if (accessModel.canAccessItems(node, senderJID, new JID(recipientJID))) {
Element item = defaultItem.createCopy();
item.addAttribute("node", node.getNodeID());
items.add(item);
}
}
}
return items.iterator();
}
use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.
the class PubSubEngine method getPublishedItems.
private void getPublishedItems(PubSubService service, IQ iq, Element itemsElement) {
String nodeID = itemsElement.attributeValue("node");
String subID = itemsElement.attributeValue("subid");
Node node;
if (nodeID == null) {
// User must specify a leaf node ID so return a nodeid-required error
Element pubsubError = DocumentHelper.createElement(QName.get("nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
return;
} else {
// Look for the specified 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.isCollectionNode()) {
// Node is a collection node. Return feature-not-implemented error
Element pubsubError = DocumentHelper.createElement(QName.get("unsupported", "http://jabber.org/protocol/pubsub#errors"));
pubsubError.addAttribute("feature", "retrieve-items");
sendErrorPacket(iq, PacketError.Condition.feature_not_implemented, pubsubError);
return;
}
// Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
JID subscriberJID = iq.getFrom();
// TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
JID owner = subscriberJID.asBareJID();
// Check if the node's access model allows the subscription to proceed
AccessModel accessModel = node.getAccessModel();
if (!accessModel.canAccessItems(node, owner, subscriberJID)) {
sendErrorPacket(iq, accessModel.getSubsriptionError(), accessModel.getSubsriptionErrorDetail());
return;
}
// Check that the requester is not an outcast
NodeAffiliate affiliate = node.getAffiliate(owner);
if (affiliate != null && affiliate.getAffiliation() == NodeAffiliate.Affiliation.outcast) {
sendErrorPacket(iq, PacketError.Condition.forbidden, null);
return;
}
// Get the user's subscription
NodeSubscription subscription = null;
if (node.isMultipleSubscriptionsEnabled() && (node.getSubscriptions(owner).size() > 1)) {
if (subID == null) {
// No subid was specified and the node supports multiple subscriptions and the user
// has multiple subscriptions
Element pubsubError = DocumentHelper.createElement(QName.get("subid-required", "http://jabber.org/protocol/pubsub#errors"));
sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
return;
} else {
// Check if the specified subID belongs to an existing node subscription
subscription = node.getSubscription(subID);
if (subscription == null) {
Element pubsubError = DocumentHelper.createElement(QName.get("invalid-subid", "http://jabber.org/protocol/pubsub#errors"));
sendErrorPacket(iq, PacketError.Condition.not_acceptable, pubsubError);
return;
}
}
}
if (subscription != null && !subscription.isActive()) {
Element pubsubError = DocumentHelper.createElement(QName.get("not-subscribed", "http://jabber.org/protocol/pubsub#errors"));
sendErrorPacket(iq, PacketError.Condition.not_authorized, pubsubError);
return;
}
LeafNode leafNode = (LeafNode) node;
// Get list of items to send to the user
boolean forceToIncludePayload = false;
List<PublishedItem> items;
String max_items = itemsElement.attributeValue("max_items");
int recentItems = 0;
if (max_items != null) {
try {
// Parse the recent number of items requested
recentItems = Integer.parseInt(max_items);
} catch (NumberFormatException e) {
// There was an error parsing the number so assume that all items were requested
Log.warn("Assuming that all items were requested", e);
max_items = null;
}
}
if (max_items != null) {
// Get the N most recent published items
items = new ArrayList<>(leafNode.getPublishedItems(recentItems));
} else {
List requestedItems = itemsElement.elements("item");
if (requestedItems.isEmpty()) {
// Get all the active items that were published to the node
items = new ArrayList<>(leafNode.getPublishedItems());
} else {
items = new ArrayList<>();
// Indicate that payload should be included (if exists) no matter
// the node configuration
forceToIncludePayload = true;
// Get the items as requested by the user
for (Iterator it = requestedItems.iterator(); it.hasNext(); ) {
Element element = (Element) it.next();
String itemID = element.attributeValue("id");
PublishedItem item = leafNode.getPublishedItem(itemID);
if (item != null) {
items.add(item);
}
}
}
}
if (subscription != null && subscription.getKeyword() != null) {
// Filter items that do not match the subscription keyword
for (Iterator<PublishedItem> it = items.iterator(); it.hasNext(); ) {
PublishedItem item = it.next();
if (!subscription.isKeywordMatched(item)) {
// Remove item that does not match keyword
it.remove();
}
}
}
// Send items to the user
leafNode.sendPublishedItems(iq, items, forceToIncludePayload);
}
use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.
the class PEPService method sendNotification.
@Override
public void sendNotification(Node node, Message message, JID recipientJID) {
message.setTo(recipientJID);
message.setFrom(getAddress());
message.setID(StringUtils.randomString(8));
// If the recipient subscribed with a bare JID and this PEPService can retrieve
// presence information for the recipient, collect all of their full JIDs and
// send the notification to each below.
Set<JID> recipientFullJIDs = new HashSet<>();
if (XMPPServer.getInstance().isLocal(recipientJID)) {
if (recipientJID.getResource() == null) {
for (ClientSession clientSession : SessionManager.getInstance().getSessions(recipientJID.getNode())) {
recipientFullJIDs.add(clientSession.getAddress());
}
}
} else {
// Since recipientJID is not local, try to get presence info from cached known remote
// presences.
// TODO: OF-605 the old code depends on a cache that would contain presence state on all (?!) JIDS on all (?!)
// remote domains. As we cannot depend on this information to be correct (even if we could ensure that this
// potentially unlimited amount of data would indeed be manageable in the first place), this code was removed.
recipientFullJIDs.add(recipientJID);
}
if (recipientFullJIDs.isEmpty()) {
router.route(message);
return;
}
for (JID recipientFullJID : recipientFullJIDs) {
// to the service owner.
try {
JID publisher = null;
// Get the ID of the node that had an item published to or retracted from.
Element itemsElement = message.getElement().element("event").element("items");
String nodeID = itemsElement.attributeValue("node");
// Get the ID of the item that was published or retracted.
String itemID = null;
Element itemElement = itemsElement.element("item");
if (itemElement == null) {
Element retractElement = itemsElement.element("retract");
if (retractElement != null) {
itemID = retractElement.attributeValue("id");
}
} else {
itemID = itemElement.attributeValue("id");
}
// Check if the recipientFullJID is interested in notifications for this node.
// If the recipient has not yet requested any notification filtering, continue and send
// the notification.
EntityCapabilities entityCaps = entityCapsManager.getEntityCapabilities(recipientFullJID);
if (entityCaps != null) {
if (!entityCaps.containsFeature(nodeID + "+notify")) {
return;
}
}
// This full JID will be used as the "replyto" address in the addressing extension.
if (node.isCollectionNode()) {
for (Node leafNode : node.getNodes()) {
if (leafNode.getNodeID().equals(nodeID)) {
publisher = leafNode.getPublishedItem(itemID).getPublisher();
// Ensure the recipientJID has access to receive notifications for items published to the leaf node.
AccessModel accessModel = leafNode.getAccessModel();
if (!accessModel.canAccessItems(leafNode, recipientFullJID, publisher)) {
return;
}
break;
}
}
} else {
publisher = node.getPublishedItem(itemID).getPublisher();
}
// Ensure the recipient is subscribed to the service owner's (publisher's) presence.
if (canProbePresence(publisher, recipientFullJID)) {
Element addresses = DocumentHelper.createElement(QName.get("addresses", "http://jabber.org/protocol/address"));
Element address = addresses.addElement("address");
address.addAttribute("type", "replyto");
address.addAttribute("jid", publisher.toString());
Message extendedMessage = message.createCopy();
extendedMessage.addExtension(new PacketExtension(addresses));
extendedMessage.setTo(recipientFullJID);
router.route(extendedMessage);
}
} catch (IndexOutOfBoundsException e) {
// Do not add addressing extension to message.
} catch (UserNotFoundException e) {
// Do not add addressing extension to message.
router.route(message);
} catch (NullPointerException e) {
try {
if (canProbePresence(getAddress(), recipientFullJID)) {
message.setTo(recipientFullJID);
}
} catch (UserNotFoundException e1) {
// Do nothing
}
router.route(message);
}
}
}
use of org.jivesoftware.openfire.pubsub.models.AccessModel in project Openfire by igniterealtime.
the class PubSubEngine method subscribeNode.
private void subscribeNode(PubSubService service, IQ iq, Element childElement, Element subscribeElement) {
String nodeID = subscribeElement.attributeValue("node");
Node node;
if (nodeID == null) {
if (service.isCollectionNodesSupported()) {
// Entity subscribes to root collection node
node = service.getRootCollectionNode();
} else {
// Service does not have a root collection node so return a nodeid-required error
Element pubsubError = DocumentHelper.createElement(QName.get("nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
return;
}
} else {
// Look for the specified 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;
}
}
// Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
JID from = iq.getFrom();
JID subscriberJID = new JID(subscribeElement.attributeValue("jid"));
if (!from.toBareJID().equals(subscriberJID.toBareJID()) && !service.isServiceAdmin(from)) {
// JIDs do not match and requestor is not a service admin so return an error
Element pubsubError = DocumentHelper.createElement(QName.get("invalid-jid", "http://jabber.org/protocol/pubsub#errors"));
sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
return;
}
// TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
JID owner = subscriberJID.asBareJID();
// Check if the node's access model allows the subscription to proceed
AccessModel accessModel = node.getAccessModel();
if (!accessModel.canSubscribe(node, owner, subscriberJID)) {
sendErrorPacket(iq, accessModel.getSubsriptionError(), accessModel.getSubsriptionErrorDetail());
return;
}
// Check if the subscriber is an anonymous user
if (!UserManager.getInstance().isRegisteredUser(subscriberJID)) {
// Anonymous users cannot subscribe to the node. Return forbidden error
sendErrorPacket(iq, PacketError.Condition.forbidden, null);
return;
}
// Check if the subscription owner is a user with outcast affiliation
NodeAffiliate nodeAffiliate = node.getAffiliate(owner);
if (nodeAffiliate != null && nodeAffiliate.getAffiliation() == NodeAffiliate.Affiliation.outcast) {
// Subscriber is an outcast. Return forbidden error
sendErrorPacket(iq, PacketError.Condition.forbidden, null);
return;
}
// Check that subscriptions to the node are enabled
if (!node.isSubscriptionEnabled() && !service.isServiceAdmin(from)) {
// Sender is not a sysadmin and subscription is disabled so return an error
sendErrorPacket(iq, PacketError.Condition.not_allowed, null);
return;
}
// Get any configuration form included in the options element (if any)
DataForm optionsForm = null;
Element options = childElement.element("options");
if (options != null) {
Element formElement = options.element(QName.get("x", "jabber:x:data"));
if (formElement != null) {
optionsForm = new DataForm(formElement);
}
}
// creating another subscription or not
if (!node.isCollectionNode() && !node.isMultipleSubscriptionsEnabled()) {
NodeSubscription existingSubscription = node.getSubscription(subscriberJID);
if (existingSubscription != null) {
// User is trying to create another subscription so
// return current subscription state
existingSubscription.sendSubscriptionState(iq);
return;
}
}
// Check if subscribing twice to a collection node using same subscription type
if (node.isCollectionNode()) {
// By default assume that new subscription is of type node
boolean isNodeType = true;
if (optionsForm != null) {
FormField field = optionsForm.getField("pubsub#subscription_type");
if (field != null) {
if ("items".equals(field.getValues().get(0))) {
isNodeType = false;
}
}
}
if (nodeAffiliate != null) {
for (NodeSubscription subscription : nodeAffiliate.getSubscriptions()) {
if (isNodeType) {
// User is requesting a subscription of type "nodes"
if (NodeSubscription.Type.nodes == subscription.getType()) {
// Cannot have 2 subscriptions of the same type. Return conflict error
sendErrorPacket(iq, PacketError.Condition.conflict, null);
return;
}
} else if (!node.isMultipleSubscriptionsEnabled()) {
// multiple subscriptions is not allowed
if (NodeSubscription.Type.items == subscription.getType()) {
// User is trying to create another subscription so
// return current subscription state
subscription.sendSubscriptionState(iq);
return;
}
}
}
}
}
// Create a subscription and an affiliation if the subscriber doesn't have one
node.createSubscription(iq, owner, subscriberJID, accessModel.isAuthorizationRequired(), optionsForm);
}
Aggregations