Diff

util/pubsub.lua @ 3938:a3ecaf46bd82

util.pubsub: Add service-wide subscription tracking, and add :get_subscriptions()
author Matthew Wild <mwild1@gmail.com>
date Wed, 22 Dec 2010 03:46:32 +0000
parent 3937:843ee23cc91a
child 3942:0323beb7183c
line wrap: on
line diff
--- a/util/pubsub.lua	Wed Dec 22 03:46:07 2010 +0000
+++ b/util/pubsub.lua	Wed Dec 22 03:46:32 2010 +0000
@@ -14,6 +14,7 @@
 	return setmetatable({
 		config = setmetatable(config, { __index = default_config });
 		affiliations = {};
+		subscriptions = {};
 		nodes = {};
 	}, service_mt);
 end
@@ -112,6 +113,17 @@
 		end
 	end
 	node_obj.subscribers[jid] = options or true;
+	local normal_jid = self.config.normalize_jid(jid);
+	local subs = self.subscriptions[normal_jid];
+	if subs then
+		if not subs[jid] then
+			subs[jid] = { [node] = true };
+		else
+			subs[jid][node] = true;
+		end
+	else
+		self.subscriptions[normal_jid] = { [jid] = { [node] = true } };
+	end
 	return true;
 end
 
@@ -138,6 +150,20 @@
 		return false, "not-subscribed";
 	end
 	node_obj.subscribers[jid] = nil;
+	local normal_jid = self.config.normalize_jid(jid);
+	local subs = self.subscriptions[normal_jid];
+	if subs then
+		local jid_subs = subs[jid];
+		if jid_subs then
+			jid_subs[node] = nil;
+			if next(jid_subs) == nil then
+				subs[jid] = nil;
+			end
+		end
+		if next(subs) == nil then
+			self.subscriptions[normal_jid] = nil;
+		end
+	end
 	return true;
 end
 
@@ -249,6 +275,55 @@
 	return true, self.nodes;
 end
 
+function service:get_subscriptions(node, actor, jid)
+	-- Access checking
+	local cap;
+	if jid == actor or self:jids_equal(actor, jid) then
+		cap = "get_subscriptions";
+	else
+		cap = "get_subscriptions_other";
+	end
+	if not self:may(node, actor, cap) then
+		return false, "forbidden";
+	end
+	--
+	local node_obj;
+	if node then
+		node_obj = self.nodes[node];
+		if not node_obj then
+			return false, "item-not-found";
+		end
+	end
+	local normal_jid = self.config.normalize_jid(jid);
+	local subs = self.subscriptions[normal_jid];
+	-- We return the subscription object from the node to save
+	-- a get_subscription() call for each node.
+	local ret = {};
+	if subs then
+		for jid, subscribed_nodes in pairs(subs) do
+			if node then -- Return only subscriptions to this node
+				if subscribed_nodes[node] then
+					ret[#ret+1] = {
+						node = node;
+						jid = jid;
+						subscription = node_obj.subscribers[jid];
+					};
+				end
+			else -- Return subscriptions to all nodes
+				local nodes = self.nodes;
+				for subscribed_node in pairs(subscribed_nodes) do
+					ret[#ret+1] = {
+						node = node;
+						jid = jid;
+						subscription = nodes[subscribed_node].subscribers[jid];
+					};
+				end
+			end
+		end
+	end
+	return true, ret;
+end
+
 -- Access models only affect 'none' affiliation caps, service/default access level...
 function service:set_node_capabilities(node, actor, capabilities)
 	-- Access checking