Software /
code /
prosody
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; |