Comparison

util/pubsub.lua @ 3910:80fe910f912a

util.pubsub: Too many changes to list or split sensibly. Added access control to all methods, with capabilities support. Renamed get() -> get_items() and changed it to return true, result on success. Support for autocreate_on_subscribe and autocreate_on_publish config options.
author Matthew Wild <mwild1@gmail.com>
date Tue, 21 Dec 2010 03:26:06 +0000
parent 3909:c2dc7f7eed94
child 3917:263a133bdf5a
comparison
equal deleted inserted replaced
3909:c2dc7f7eed94 3910:80fe910f912a
16 affiliations = {}; 16 affiliations = {};
17 nodes = {}; 17 nodes = {};
18 }, service_mt); 18 }, service_mt);
19 end 19 end
20 20
21 function service:add_subscription(node, actor, jid) 21 function service:may(node, actor, action)
22 local node_obj = self.nodes[node]; 22 if actor == true then return true; end
23 if not node_obj then 23
24 return false, "item-not-found"; 24
25 end 25 local node_obj = self.nodes[node];
26 node_obj.subscribers[jid] = true; 26 local node_aff = node_obj and node_obj.affiliations[actor];
27 local service_aff = self.affiliations[actor]
28 or self.config.get_affiliation(actor, node, action)
29 or "none";
30
31 local node_capabilities = node_obj and node_obj.capabilities;
32 local service_capabilities = self.config.capabilities;
33
34 -- Check if node allows/forbids it
35 if node_capabilities then
36 local caps = node_capabilities[node_aff or service_aff];
37 if caps then
38 local can = caps[action];
39 if can ~= nil then
40 return can;
41 end
42 end
43 end
44 -- Check service-wide capabilities instead
45 local caps = service_capabilities[node_aff or service_aff];
46 if caps then
47 local can = caps[action];
48 if can ~= nil then
49 return can;
50 end
51 end
52
53 return false;
54 end
55
56 function service:set_affiliation(node, actor, jid, affiliation)
57 -- Access checking
58 if not self:may(node, actor, "set_affiliation") then
59 return false, "forbidden";
60 end
61 --
62 local node_obj = self.nodes[node];
63 if not node_obj then
64 return false, "item-not-found";
65 end
66 node_obj.affiliations[jid] = affiliation;
67 local _, jid_sub = self:get_subscription(node, nil, jid);
68 if not jid_sub and not self:may(node, jid, "be_unsubscribed") then
69 local ok, err = self:add_subscription(node, nil, jid);
70 if not ok then
71 return ok, err;
72 end
73 elseif jid_sub and not self:may(node, jid, "be_subscribed") then
74 local ok, err = self:add_subscription(node, nil, jid);
75 if not ok then
76 return ok, err;
77 end
78 end
79 return true;
80 end
81
82 function service:add_subscription(node, actor, jid, options)
83 -- Access checking
84 local cap;
85 if jid == actor or self.config.jids_equal(actor, jid) then
86 cap = "subscribe";
87 else
88 cap = "subscribe_other";
89 end
90 if not self:may(node, actor, cap) then
91 return false, "forbidden";
92 end
93 if not self:may(node, jid, "be_subscribed") then
94 return false, "forbidden";
95 end
96 --
97 local node_obj = self.nodes[node];
98 if not node_obj then
99 if not self.config.autocreate_on_subscribe then
100 return false, "item-not-found";
101 else
102 local ok, err = self:create(node, actor);
103 if not ok then
104 return ok, err;
105 end
106 end
107 end
108 node_obj.subscribers[jid] = options or true;
27 return true; 109 return true;
28 end 110 end
29 111
30 function service:remove_subscription(node, actor, jid) 112 function service:remove_subscription(node, actor, jid)
113 -- Access checking
114 local cap;
115 if jid == actor or self.config.jids_equal(actor, jid) then
116 cap = "unsubscribe";
117 else
118 cap = "unsubscribe_other";
119 end
120 if not self:may(node, actor, cap) then
121 return false, "forbidden";
122 end
123 if not self:may(node, jid, "be_unsubscribed") then
124 return false, "forbidden";
125 end
126 --
31 local node_obj = self.nodes[node]; 127 local node_obj = self.nodes[node];
32 if not node_obj then 128 if not node_obj then
33 return false, "item-not-found"; 129 return false, "item-not-found";
34 end 130 end
35 if not node_obj.subscribers[jid] then 131 if not node_obj.subscribers[jid] then
38 node_obj.subscribers[jid] = nil; 134 node_obj.subscribers[jid] = nil;
39 return true; 135 return true;
40 end 136 end
41 137
42 function service:get_subscription(node, actor, jid) 138 function service:get_subscription(node, actor, jid)
139 -- Access checking
140 local cap;
141 if jid == actor or self.config.jids_equal(actor, jid) then
142 cap = "get_subscription";
143 else
144 cap = "get_subscription_other";
145 end
146 if not self:may(node, actor, cap) then
147 return false, "forbidden";
148 end
149 --
43 local node_obj = self.nodes[node]; 150 local node_obj = self.nodes[node];
44 if node_obj then 151 if node_obj then
45 return node_obj.subscribers[jid]; 152 return true, node_obj.subscribers[jid];
46 end 153 end
47 end 154 end
48 155
49 function service:create(node, actor) 156 function service:create(node, actor)
50 if not self.nodes[node] then 157 -- Access checking
51 self.nodes[node] = { name = node, subscribers = {}, config = {}, data = {} }; 158 if not self:may(node, actor, "create") then
52 return true; 159 return false, "forbidden";
53 end 160 end
54 return false, "conflict"; 161 --
162 if self.nodes[node] then
163 return false, "conflict";
164 end
165
166 self.nodes[node] = {
167 name = node;
168 subscribers = {};
169 config = {};
170 data = {};
171 affiliations = {};
172 };
173 local ok, err = self:set_affiliation(node, true, actor, "owner");
174 if not ok then
175 self.nodes[node] = nil;
176 end
177 return ok, err;
55 end 178 end
56 179
57 function service:publish(node, actor, id, item) 180 function service:publish(node, actor, id, item)
58 local node_obj = self.nodes[node]; 181 -- Access checking
59 if not node_obj then 182 if not self:may(node, actor, "publish") then
60 node_obj = { name = node, subscribers = {}, config = {}, data = {} }; 183 return false, "forbidden";
61 self.nodes[node] = node_obj; 184 end
185 --
186 local node_obj = self.nodes[node];
187 if not node_obj then
188 if not self.config.autocreate_on_publish then
189 return false, "item-not-found";
190 end
191 local ok, err = self:create(node, actor);
192 if not ok then
193 return ok, err;
194 end
195 node_obj = self.nodes[node];
62 end 196 end
63 node_obj.data[id] = item; 197 node_obj.data[id] = item;
64 self.cb.broadcaster(node, node_obj.subscribers, item); 198 self.config.broadcaster(node, node_obj.subscribers, item);
65 return true; 199 return true;
66 end 200 end
67 201
68 function service:retract(node, actor, id, retract) 202 function service:retract(node, actor, id, retract)
203 -- Access checking
204 if not self:may(node, actor, "retract") then
205 return false, "forbidden";
206 end
207 --
69 local node_obj = self.nodes[node]; 208 local node_obj = self.nodes[node];
70 if (not node_obj) or (not node_obj.data[id]) then 209 if (not node_obj) or (not node_obj.data[id]) then
71 return false, "item-not-found"; 210 return false, "item-not-found";
72 end 211 end
73 node_obj.data[id] = nil; 212 node_obj.data[id] = nil;
74 if retract then 213 if retract then
75 self.cb.broadcaster(node, node_obj.subscribers, retract); 214 self.config.broadcaster(node, node_obj.subscribers, retract);
76 end 215 end
77 return true 216 return true
78 end 217 end
79 218
80 function service:get(node, actor, id) 219 function service:get_items(node, actor, id)
81 local node_obj = self.nodes[node]; 220 -- Access checking
82 if node_obj then 221 if not self:may(node, actor, "get_items") then
83 if id then 222 return false, "forbidden";
84 return { node_obj.data[id] }; 223 end
85 else 224 --
86 return node_obj.data; 225 local node_obj = self.nodes[node];
87 end 226 if not node_obj then
227 return false, "item-not-found";
228 end
229 if id then -- Restrict results to a single specific item
230 return true, { node_obj.data[id] };
231 else
232 return true, node_obj.data;
88 end 233 end
89 end 234 end
90 235
91 function service:get_nodes(actor) 236 function service:get_nodes(actor)
237 -- Access checking
238 if not self:may(node, actor, "get_nodes") then
239 return false, "forbidden";
240 end
241 --
92 return true, self.nodes; 242 return true, self.nodes;
93 end 243 end
94 244
95 return _M; 245 return _M;