Mercurial > prosody-hg
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 |
| parents | c2dc7f7eed94 |
| children | 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; |
