Comparison

util/pubsub.lua @ 6054:7a5ddbaf758d

Merge 0.9->0.10
author Matthew Wild <mwild1@gmail.com>
date Wed, 02 Apr 2014 17:41:38 +0100
parent 5972:f365d3c8fd2c
child 5973:905b4fd863b4
child 6435:689cb04ff9fd
comparison
equal deleted inserted replaced
6053:2f93a04564b2 6054:7a5ddbaf758d
1 local events = require "util.events"; 1 local events = require "util.events";
2 local t_remove = table.remove;
2 3
3 module("pubsub", package.seeall); 4 module("pubsub", package.seeall);
4 5
5 local service = {}; 6 local service = {};
6 local service_mt = { __index = service }; 7 local service_mt = { __index = service };
16 return setmetatable({ 17 return setmetatable({
17 config = setmetatable(config, { __index = default_config }); 18 config = setmetatable(config, { __index = default_config });
18 affiliations = {}; 19 affiliations = {};
19 subscriptions = {}; 20 subscriptions = {};
20 nodes = {}; 21 nodes = {};
22 data = {};
21 events = events.new(); 23 events = events.new();
22 }, service_mt); 24 }, service_mt);
23 end 25 end
24 26
25 function service:jids_equal(jid1, jid2) 27 function service:jids_equal(jid1, jid2)
27 return normalize(jid1) == normalize(jid2); 29 return normalize(jid1) == normalize(jid2);
28 end 30 end
29 31
30 function service:may(node, actor, action) 32 function service:may(node, actor, action)
31 if actor == true then return true; end 33 if actor == true then return true; end
32 34
33 local node_obj = self.nodes[node]; 35 local node_obj = self.nodes[node];
34 local node_aff = node_obj and node_obj.affiliations[actor]; 36 local node_aff = node_obj and node_obj.affiliations[actor];
35 local service_aff = self.affiliations[actor] 37 local service_aff = self.affiliations[actor]
36 or self.config.get_affiliation(actor, node, action) 38 or self.config.get_affiliation(actor, node, action)
37 or "none"; 39 or "none";
38 40
39 -- Check if node allows/forbids it 41 -- Check if node allows/forbids it
40 local node_capabilities = node_obj and node_obj.capabilities; 42 local node_capabilities = node_obj and node_obj.capabilities;
41 if node_capabilities then 43 if node_capabilities then
42 local caps = node_capabilities[node_aff or service_aff]; 44 local caps = node_capabilities[node_aff or service_aff];
43 if caps then 45 if caps then
45 if can ~= nil then 47 if can ~= nil then
46 return can; 48 return can;
47 end 49 end
48 end 50 end
49 end 51 end
50 52
51 -- Check service-wide capabilities instead 53 -- Check service-wide capabilities instead
52 local service_capabilities = self.config.capabilities; 54 local service_capabilities = self.config.capabilities;
53 local caps = service_capabilities[node_aff or service_aff]; 55 local caps = service_capabilities[node_aff or service_aff];
54 if caps then 56 if caps then
55 local can = caps[action]; 57 local can = caps[action];
56 if can ~= nil then 58 if can ~= nil then
57 return can; 59 return can;
58 end 60 end
59 end 61 end
60 62
61 return false; 63 return false;
62 end 64 end
63 65
64 function service:set_affiliation(node, actor, jid, affiliation) 66 function service:set_affiliation(node, actor, jid, affiliation)
65 -- Access checking 67 -- Access checking
209 end 211 end
210 -- 212 --
211 if self.nodes[node] then 213 if self.nodes[node] then
212 return false, "conflict"; 214 return false, "conflict";
213 end 215 end
214 216
217 self.data[node] = {};
215 self.nodes[node] = { 218 self.nodes[node] = {
216 name = node; 219 name = node;
217 subscribers = {}; 220 subscribers = {};
218 config = {}; 221 config = {};
219 data = {};
220 affiliations = {}; 222 affiliations = {};
221 }; 223 };
224 setmetatable(self.nodes[node], { __index = { data = self.data[node] } }); -- COMPAT
225 self.events.fire_event("node-created", { node = node, actor = actor });
222 local ok, err = self:set_affiliation(node, true, actor, "owner"); 226 local ok, err = self:set_affiliation(node, true, actor, "owner");
223 if not ok then 227 if not ok then
224 self.nodes[node] = nil; 228 self.nodes[node] = nil;
229 self.data[node] = nil;
225 end 230 end
226 return ok, err; 231 return ok, err;
227 end 232 end
228 233
229 function service:delete(node, actor) 234 function service:delete(node, actor)
235 local node_obj = self.nodes[node]; 240 local node_obj = self.nodes[node];
236 if not node_obj then 241 if not node_obj then
237 return false, "item-not-found"; 242 return false, "item-not-found";
238 end 243 end
239 self.nodes[node] = nil; 244 self.nodes[node] = nil;
245 self.data[node] = nil;
246 self.events.fire_event("node-deleted", { node = node, actor = actor });
240 self.config.broadcaster("delete", node, node_obj.subscribers); 247 self.config.broadcaster("delete", node, node_obj.subscribers);
241 return true; 248 return true;
249 end
250
251 local function remove_item_by_id(data, id)
252 if not data[id] then return end
253 data[id] = nil;
254 for i, _id in ipairs(data) do
255 if id == _id then
256 t_remove(data, i);
257 return i;
258 end
259 end
242 end 260 end
243 261
244 function service:publish(node, actor, id, item) 262 function service:publish(node, actor, id, item)
245 -- Access checking 263 -- Access checking
246 if not self:may(node, actor, "publish") then 264 if not self:may(node, actor, "publish") then
256 if not ok then 274 if not ok then
257 return ok, err; 275 return ok, err;
258 end 276 end
259 node_obj = self.nodes[node]; 277 node_obj = self.nodes[node];
260 end 278 end
261 node_obj.data[id] = item; 279 local node_data = self.data[node];
280 remove_item_by_id(node_data, id);
281 node_data[#self.data[node] + 1] = id;
282 node_data[id] = item;
262 self.events.fire_event("item-published", { node = node, actor = actor, id = id, item = item }); 283 self.events.fire_event("item-published", { node = node, actor = actor, id = id, item = item });
263 self.config.broadcaster("items", node, node_obj.subscribers, item); 284 self.config.broadcaster("items", node, node_obj.subscribers, item);
264 return true; 285 return true;
265 end 286 end
266 287
269 if not self:may(node, actor, "retract") then 290 if not self:may(node, actor, "retract") then
270 return false, "forbidden"; 291 return false, "forbidden";
271 end 292 end
272 -- 293 --
273 local node_obj = self.nodes[node]; 294 local node_obj = self.nodes[node];
274 if (not node_obj) or (not node_obj.data[id]) then 295 if (not node_obj) or (not self.data[node][id]) then
275 return false, "item-not-found"; 296 return false, "item-not-found";
276 end 297 end
277 node_obj.data[id] = nil; 298 self.events.fire_event("item-retracted", { node = node, actor = actor, id = id });
299 remove_item_by_id(self.data[node], id);
278 if retract then 300 if retract then
279 self.config.broadcaster("items", node, node_obj.subscribers, retract); 301 self.config.broadcaster("items", node, node_obj.subscribers, retract);
280 end 302 end
281 return true 303 return true
282 end 304 end
289 -- 311 --
290 local node_obj = self.nodes[node]; 312 local node_obj = self.nodes[node];
291 if not node_obj then 313 if not node_obj then
292 return false, "item-not-found"; 314 return false, "item-not-found";
293 end 315 end
294 node_obj.data = {}; -- Purge 316 self.data[node] = {}; -- Purge
317 self.events.fire_event("node-purged", { node = node, actor = actor });
295 if notify then 318 if notify then
296 self.config.broadcaster("purge", node, node_obj.subscribers); 319 self.config.broadcaster("purge", node, node_obj.subscribers);
297 end 320 end
298 return true 321 return true
299 end 322 end
307 local node_obj = self.nodes[node]; 330 local node_obj = self.nodes[node];
308 if not node_obj then 331 if not node_obj then
309 return false, "item-not-found"; 332 return false, "item-not-found";
310 end 333 end
311 if id then -- Restrict results to a single specific item 334 if id then -- Restrict results to a single specific item
312 return true, { [id] = node_obj.data[id] }; 335 return true, { id, [id] = self.data[node][id] };
313 else 336 else
314 return true, node_obj.data; 337 return true, self.data[node];
315 end 338 end
316 end 339 end
317 340
318 function service:get_nodes(actor) 341 function service:get_nodes(actor)
319 -- Access checking 342 -- Access checking