Software /
code /
prosody-modules
Comparison
mod_admin_web/admin_web/mod_admin_web.lua @ 317:4f78f5020aa9
mod_admin_web: Get rid of the mod_pubsub dependency
author | Florian Zeitz <florob@babelmonkeys.de> |
---|---|
date | Fri, 14 Jan 2011 01:54:39 +0100 |
parent | 309:5ec9125575fc |
child | 319:ba2e78661ea8 |
comparison
equal
deleted
inserted
replaced
316:c86fc337d56f | 317:4f78f5020aa9 |
---|---|
13 -- <encrypted/> | 13 -- <encrypted/> |
14 -- <compressed/> | 14 -- <compressed/> |
15 -- <in/> / <out/> | 15 -- <in/> / <out/> |
16 -- </session> | 16 -- </session> |
17 | 17 |
18 local stanza = require "util.stanza"; | 18 local st = require "util.stanza"; |
19 local uuid_generate = require "util.uuid".generate; | 19 local uuid_generate = require "util.uuid".generate; |
20 local is_admin = require "usermanager".is_admin; | |
21 local pubsub = require "util.pubsub"; | |
20 local httpserver = require "net.httpserver"; | 22 local httpserver = require "net.httpserver"; |
23 local jid_bare = require "util.jid".bare; | |
21 local lfs = require "lfs"; | 24 local lfs = require "lfs"; |
22 local open = io.open; | 25 local open = io.open; |
23 local stat = lfs.attributes; | 26 local stat = lfs.attributes; |
24 | 27 |
25 local host = module:get_host(); | 28 local host = module:get_host(); |
26 local service = config.get("*", "core", "webadmin_pubsub_host") or ("pubsub." .. host); | 29 local service; |
27 | 30 |
28 local http_base = (prosody.paths.plugins or "./plugins/") .. "admin_web/www_files"; | 31 local http_base = (prosody.paths.plugins or "./plugins/") .. "admin_web/www_files"; |
29 | 32 |
33 local xmlns_adminsub = "http://prosody.im/adminsub"; | |
30 local xmlns_c2s_session = "http://prosody.im/streams/c2s"; | 34 local xmlns_c2s_session = "http://prosody.im/streams/c2s"; |
31 local xmlns_s2s_session = "http://prosody.im/streams/s2s"; | 35 local xmlns_s2s_session = "http://prosody.im/streams/s2s"; |
32 | 36 |
33 local response_301 = { status = "301 Moved Permanently" }; | 37 local response_301 = { status = "301 Moved Permanently" }; |
34 local response_400 = { status = "400 Bad Request", body = "<h1>Bad Request</h1>Sorry, we didn't understand your request :(" }; | 38 local response_400 = { status = "400 Bad Request", body = "<h1>Bad Request</h1>Sorry, we didn't understand your request :(" }; |
49 local id = idmap[name]; | 53 local id = idmap[name]; |
50 if not id then | 54 if not id then |
51 id = uuid_generate(); | 55 id = uuid_generate(); |
52 idmap[name] = id; | 56 idmap[name] = id; |
53 end | 57 end |
54 local item = stanza.stanza("item", { id = id }):tag("session", {xmlns = xmlns_c2s_session, jid = name}):up(); | 58 local item = st.stanza("item", { id = id }):tag("session", {xmlns = xmlns_c2s_session, jid = name}):up(); |
55 if session.secure then | 59 if session.secure then |
56 item:tag("encrypted"):up(); | 60 item:tag("encrypted"):up(); |
57 end | 61 end |
58 if session.compressed then | 62 if session.compressed then |
59 item:tag("compressed"):up(); | 63 item:tag("compressed"):up(); |
60 end | 64 end |
61 hosts[service].modules.pubsub.service:publish(xmlns_c2s_session, service, id, item); | 65 service:publish(xmlns_c2s_session, host, id, item); |
62 module:log("debug", "Added client " .. name); | 66 module:log("debug", "Added client " .. name); |
63 end | 67 end |
64 | 68 |
65 function del_client(session) | 69 function del_client(session) |
66 local name = session.full_jid; | 70 local name = session.full_jid; |
67 local id = idmap[name]; | 71 local id = idmap[name]; |
68 if id then | 72 if id then |
69 local notifier = stanza.stanza("retract", { id = id }); | 73 local notifier = st.stanza("retract", { id = id }); |
70 hosts[service].modules.pubsub.service:retract(xmlns_c2s_session, service, id, notifier); | 74 service:retract(xmlns_c2s_session, host, id, notifier); |
71 end | 75 end |
72 end | 76 end |
73 | 77 |
74 function add_host(session, type) | 78 function add_host(session, type) |
75 local name = (type == "out" and session.to_host) or (type == "in" and session.from_host); | 79 local name = (type == "out" and session.to_host) or (type == "in" and session.from_host); |
76 local id = idmap[name.."_"..type]; | 80 local id = idmap[name.."_"..type]; |
77 if not id then | 81 if not id then |
78 id = uuid_generate(); | 82 id = uuid_generate(); |
79 idmap[name.."_"..type] = id; | 83 idmap[name.."_"..type] = id; |
80 end | 84 end |
81 local item = stanza.stanza("item", { id = id }):tag("session", {xmlns = xmlns_s2s_session, jid = name}) | 85 local item = st.stanza("item", { id = id }):tag("session", {xmlns = xmlns_s2s_session, jid = name}) |
82 :tag(type):up(); | 86 :tag(type):up(); |
83 if session.secure then | 87 if session.secure then |
84 item:tag("encrypted"):up(); | 88 item:tag("encrypted"):up(); |
85 end | 89 end |
86 if session.compressed then | 90 if session.compressed then |
87 item:tag("compressed"):up(); | 91 item:tag("compressed"):up(); |
88 end | 92 end |
89 hosts[service].modules.pubsub.service:publish(xmlns_s2s_session, service, id, item); | 93 service:publish(xmlns_s2s_session, host, id, item); |
90 module:log("debug", "Added host " .. name .. " s2s" .. type); | 94 module:log("debug", "Added host " .. name .. " s2s" .. type); |
91 end | 95 end |
92 | 96 |
93 function del_host(session, type) | 97 function del_host(session, type) |
94 local name = (type == "out" and session.to_host) or (type == "in" and session.from_host); | 98 local name = (type == "out" and session.to_host) or (type == "in" and session.from_host); |
95 local id = idmap[name.."_"..type]; | 99 local id = idmap[name.."_"..type]; |
96 if id then | 100 if id then |
97 local notifier = stanza.stanza("retract", { id = id }); | 101 local notifier = st.stanza("retract", { id = id }); |
98 hosts[service].modules.pubsub.service:retract(xmlns_s2s_session, service, id, notifier); | 102 service:retract(xmlns_s2s_session, host, id, notifier); |
99 end | 103 end |
100 end | 104 end |
101 | 105 |
102 local function preprocess_path(path) | 106 local function preprocess_path(path) |
103 if path:sub(1,1) ~= "/" then | 107 if path:sub(1,1) ~= "/" then |
131 return response_403; | 135 return response_403; |
132 end | 136 end |
133 local f, err = open(full_path, "rb"); | 137 local f, err = open(full_path, "rb"); |
134 if not f then return response_404; end | 138 if not f then return response_404; end |
135 local data = f:read("*a"); | 139 local data = f:read("*a"); |
136 data = data:gsub("%%PUBSUBHOST%%", service); | 140 data = data:gsub("%%ADMINSUBHOST%%", host); |
137 f:close(); | 141 f:close(); |
138 if not data then | 142 if not data then |
139 return response_403; | 143 return response_403; |
140 end | 144 end |
141 local ext = path:match("%.([^.]*)$"); | 145 local ext = path:match("%.([^.]*)$"); |
159 httpserver.new_from_config(http_conf, handle_file_request, { base = "admin" }); | 163 httpserver.new_from_config(http_conf, handle_file_request, { base = "admin" }); |
160 end | 164 end |
161 | 165 |
162 prosody.events.add_handler("server-started", function () | 166 prosody.events.add_handler("server-started", function () |
163 local host_session = prosody.hosts[host]; | 167 local host_session = prosody.hosts[host]; |
164 if not select(2, hosts[service].modules.pubsub.service:get_nodes(service))[xmlns_s2s_session] then | 168 if not select(2, service:get_nodes(true))[xmlns_s2s_session] then |
165 local ok, errmsg = hosts[service].modules.pubsub.service:create(xmlns_s2s_session, service); | 169 local ok, errmsg = service:create(xmlns_s2s_session, true); |
166 if not ok then | 170 if not ok then |
167 module:log("warn", "Could not create node " .. xmlns_s2s_session .. ": " .. tostring(errmsg)); | 171 module:log("warn", "Could not create node " .. xmlns_s2s_session .. ": " .. tostring(errmsg)); |
172 else | |
173 service:set_affiliation(xmlns_s2s_session, true, host, "owner") | |
168 end | 174 end |
169 end | 175 end |
170 | 176 |
171 for remotehost, session in pairs(host_session.s2sout) do | 177 for remotehost, session in pairs(host_session.s2sout) do |
172 if session.type ~= "s2sout_unauthed" then | 178 if session.type ~= "s2sout_unauthed" then |
177 if session.to_host == host then | 183 if session.to_host == host then |
178 add_host(session, "in"); | 184 add_host(session, "in"); |
179 end | 185 end |
180 end | 186 end |
181 | 187 |
182 if not select(2, hosts[service].modules.pubsub.service:get_nodes(service))[xmlns_c2s_session] then | 188 if not select(2, service:get_nodes(true))[xmlns_c2s_session] then |
183 local ok, errmsg = hosts[service].modules.pubsub.service:create(xmlns_c2s_session, service); | 189 local ok, errmsg = service:create(xmlns_c2s_session, true); |
184 if not ok then | 190 if not ok then |
185 module:log("warn", "Could not create node " .. xmlns_c2s_session .. ": " .. tostring(errmsg)); | 191 module:log("warn", "Could not create node " .. xmlns_c2s_session .. ": " .. tostring(errmsg)); |
192 else | |
193 service:set_affiliation(xmlns_c2s_session, true, host, "owner") | |
186 end | 194 end |
187 end | 195 end |
188 | 196 |
189 for username, user in pairs(host_session.sessions or {}) do | 197 for username, user in pairs(host_session.sessions or {}) do |
190 for resource, session in pairs(user.sessions or {}) do | 198 for resource, session in pairs(user.sessions or {}) do |
191 add_client(session); | 199 add_client(session); |
192 end | 200 end |
193 end | 201 end |
194 end); | 202 end); |
195 | 203 |
204 function simple_broadcast(node, jids, item) | |
205 item = st.clone(item); | |
206 item.attr.xmlns = nil; -- Clear the pubsub namespace | |
207 local message = st.message({ from = module.host, type = "headline" }) | |
208 :tag("event", { xmlns = xmlns_adminsub .. "#event" }) | |
209 :tag("items", { node = node }) | |
210 :add_child(item); | |
211 for jid in pairs(jids) do | |
212 module:log("debug", "Sending notification to %s", jid); | |
213 message.attr.to = jid; | |
214 core_post_stanza(hosts[host], message); | |
215 end | |
216 end | |
217 | |
218 function get_affiliation(jid) | |
219 local bare_jid = jid_bare(jid); | |
220 if is_admin(bare_jid, host) then | |
221 return "member"; | |
222 else | |
223 return "none"; | |
224 end | |
225 end | |
226 | |
227 module:hook("iq/host/http://prosody.im/adminsub:adminsub", function(event) | |
228 local origin, stanza = event.origin, event.stanza; | |
229 local adminsub = stanza.tags[1]; | |
230 local action = adminsub.tags[1]; | |
231 local reply; | |
232 if action.name == "subscribe" then | |
233 local ok, ret = service:add_subscription(action.attr.node, stanza.attr.from, stanza.attr.from); | |
234 if ok then | |
235 reply = st.reply(stanza) | |
236 :tag("adminsub", { xmlns = xmlns_adminsub }); | |
237 else | |
238 reply = st.error_reply(stanza, "cancel", ret); | |
239 end | |
240 elseif action.name == "items" then | |
241 local node = action.attr.node; | |
242 local ok, ret = service:get_items(node, stanza.attr.from); | |
243 if not ok then | |
244 return origin.send(st.error_reply(stanza, "cancel", ret)); | |
245 end | |
246 | |
247 local data = st.stanza("items", { node = node }); | |
248 for _, entry in pairs(ret) do | |
249 data:add_child(entry); | |
250 end | |
251 if data then | |
252 reply = st.reply(stanza) | |
253 :tag("adminsub", { xmlns = xmlns_adminsub }) | |
254 :add_child(data); | |
255 else | |
256 reply = st.error_reply(stanza, "cancel", "item-not-found"); | |
257 end | |
258 else | |
259 reply = st.error_reply(stanza, "feature-not-implemented"); | |
260 end | |
261 return origin.send(reply); | |
262 end); | |
263 | |
196 module:hook("resource-bind", function(event) | 264 module:hook("resource-bind", function(event) |
197 add_client(event.session); | 265 add_client(event.session); |
198 end); | 266 end); |
199 | 267 |
200 module:hook("resource-unbind", function(event) | 268 module:hook("resource-unbind", function(event) |
201 del_client(event.session); | 269 del_client(event.session); |
270 service:remove_subscription(xmlns_c2s_session, host, event.session.full_jid); | |
271 service:remove_subscription(xmlns_s2s_session, host, event.session.full_jid); | |
202 end); | 272 end); |
203 | 273 |
204 module:hook("s2sout-established", function(event) | 274 module:hook("s2sout-established", function(event) |
205 add_host(event.session, "out"); | 275 add_host(event.session, "out"); |
206 end); | 276 end); |
214 end); | 284 end); |
215 | 285 |
216 module:hook("s2sin-destroyed", function(event) | 286 module:hook("s2sin-destroyed", function(event) |
217 del_host(event.session, "in"); | 287 del_host(event.session, "in"); |
218 end); | 288 end); |
289 | |
290 service = pubsub.new({ | |
291 broadcaster = simple_broadcast; | |
292 normalize_jid = jid_bare; | |
293 get_affiliation = get_affiliation; | |
294 capabilities = { | |
295 member = { | |
296 create = false; | |
297 publish = false; | |
298 retract = false; | |
299 get_nodes = true; | |
300 | |
301 subscribe = true; | |
302 unsubscribe = true; | |
303 get_subscription = true; | |
304 get_subscriptions = true; | |
305 get_items = true; | |
306 | |
307 subscribe_other = false; | |
308 unsubscribe_other = false; | |
309 get_subscription_other = false; | |
310 get_subscriptions_other = false; | |
311 | |
312 be_subscribed = true; | |
313 be_unsubscribed = true; | |
314 | |
315 set_affiliation = false; | |
316 }; | |
317 | |
318 owner = { | |
319 create = true; | |
320 publish = true; | |
321 retract = true; | |
322 get_nodes = true; | |
323 | |
324 subscribe = true; | |
325 unsubscribe = true; | |
326 get_subscription = true; | |
327 get_subscriptions = true; | |
328 get_items = true; | |
329 | |
330 subscribe_other = true; | |
331 unsubscribe_other = true; | |
332 get_subscription_other = true; | |
333 get_subscriptions_other = true; | |
334 | |
335 be_subscribed = true; | |
336 be_unsubscribed = true; | |
337 | |
338 set_affiliation = true; | |
339 }; | |
340 }; | |
341 }); | |
342 |