Mercurial > 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 |
| parents | 5ec9125575fc |
| children | 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 |
