Mercurial > prosody-modules
comparison mod_delegation/mod_delegation.lua @ 1709:59ba224bf145
mod_delegation: XEP-0355 implementation, first draft (configuration management + delegations advertising)
| author | Goffi <goffi@goffi.org> |
|---|---|
| date | Fri, 17 Apr 2015 21:02:22 +0200 |
| parents | |
| children | b68eed25b880 |
comparison
equal
deleted
inserted
replaced
| 1708:ad7afcf86131 | 1709:59ba224bf145 |
|---|---|
| 1 -- XEP-0355 (Namespace Delegation) | |
| 2 -- Copyright (C) 2015 Jérôme Poisson | |
| 3 -- | |
| 4 -- This module is MIT/X11 licensed. Please see the | |
| 5 -- COPYING file in the source package for more information. | |
| 6 | |
| 7 | |
| 8 local jid = require("util/jid") | |
| 9 local st = require("util/stanza") | |
| 10 local set = require("util/set") | |
| 11 | |
| 12 local delegation_session = module:shared("/*/delegation/session") | |
| 13 | |
| 14 if delegation_session.connected_cb == nil then | |
| 15 -- set used to have connected event listeners | |
| 16 -- which allow a host to react on events from | |
| 17 -- other hosts | |
| 18 delegation_session.connected_cb = set.new() | |
| 19 end | |
| 20 local connected_cb = delegation_session.connected_cb | |
| 21 | |
| 22 local _DELEGATION_NS = 'urn:xmpp:delegation:1' | |
| 23 -- local _FORWARDED_NS = 'urn:xmpp:forward:0' | |
| 24 | |
| 25 | |
| 26 module:log("debug", "Loading namespace delegation module "); | |
| 27 | |
| 28 | |
| 29 --> Configuration management <-- | |
| 30 | |
| 31 local ns_delegations = module:get_option("delegations", {}) | |
| 32 | |
| 33 local jid2ns = {} | |
| 34 for namespace, config in pairs(ns_delegations) do | |
| 35 -- "connected" contain the full jid of connected managing entity | |
| 36 config.connected = nil | |
| 37 if config.jid then | |
| 38 if jid2ns[config.jid] == nil then | |
| 39 jid2ns[config.jid] = {} | |
| 40 end | |
| 41 jid2ns[config.jid][namespace] = config | |
| 42 else | |
| 43 module:log("warn", "Ignoring delegation for %s: no jid specified", tostring(namespace)) | |
| 44 ns_delegations[namespace] = nil | |
| 45 end | |
| 46 end | |
| 47 | |
| 48 | |
| 49 local function advertise_delegations(session, to_jid) | |
| 50 -- send <message/> stanza to advertise delegations | |
| 51 -- as expained in § 4.2 | |
| 52 local message = st.message({from=module.host, to=to_jid}) | |
| 53 :tag("delegation", {xmlns=_DELEGATION_NS}) | |
| 54 | |
| 55 -- we need to check if a delegation is granted because the configuration | |
| 56 -- can be complicated if some delegations are granted to bare jid | |
| 57 -- and other to full jids, and several resources are connected. | |
| 58 local have_delegation = false | |
| 59 | |
| 60 for namespace, config in pairs(jid2ns[to_jid]) do | |
| 61 if config.connected == to_jid then | |
| 62 have_delegation = true | |
| 63 message:tag("delegated", {namespace=namespace}) | |
| 64 if type(config.filtering) == "table" then | |
| 65 for _, attribute in pairs(config.filtering) do | |
| 66 message:tag("attribute", {name=attribute}):up() | |
| 67 end | |
| 68 message:up() | |
| 69 end | |
| 70 end | |
| 71 end | |
| 72 | |
| 73 if have_delegation then | |
| 74 session.send(message) | |
| 75 end | |
| 76 end | |
| 77 | |
| 78 local function set_connected(entity_jid) | |
| 79 -- set the "connected" key for all namespace managed by entity_jid | |
| 80 -- if the namespace has already a connected entity, ignore the new one | |
| 81 local function set_config(jid_) | |
| 82 for _, config in pairs(jid2ns[jid_]) do | |
| 83 if config.connected == nil then | |
| 84 config.connected = entity_jid | |
| 85 end | |
| 86 end | |
| 87 end | |
| 88 local bare_jid = jid.bare(entity_jid) | |
| 89 set_config(bare_jid) | |
| 90 -- We can have a bare jid of a full jid specified in configuration | |
| 91 -- so we try our luck with both (first connected resource will | |
| 92 -- manage the namespaces in case of bare jid) | |
| 93 if bare_jid ~= entity_jid then | |
| 94 set_config(entity_jid) | |
| 95 jid2ns[entity_jid] = jid2ns[bare_jid] | |
| 96 end | |
| 97 end | |
| 98 | |
| 99 local function on_presence(event) | |
| 100 local session = event.origin | |
| 101 local bare_jid = jid.bare(session.full_jid) | |
| 102 | |
| 103 if jid2ns[bare_jid] or jid2ns[session.full_jid] then | |
| 104 set_connected(session.full_jid) | |
| 105 advertise_delegations(session, session.full_jid) | |
| 106 end | |
| 107 end | |
| 108 | |
| 109 local function on_component_connected(event) | |
| 110 -- method called by the module loaded by the component | |
| 111 -- /!\ the event come from the component host, | |
| 112 -- not from the host of this module | |
| 113 local session = event.session | |
| 114 local bare_jid = jid.join(session.username, session.host) | |
| 115 | |
| 116 local jid_delegations = jid2ns[bare_jid] | |
| 117 if jid_delegations ~= nil then | |
| 118 set_connected(bare_jid) | |
| 119 advertise_delegations(session, bare_jid) | |
| 120 end | |
| 121 end | |
| 122 | |
| 123 local function on_component_auth(event) | |
| 124 -- react to component-authenticated event from this host | |
| 125 -- and call the on_connected methods from all other hosts | |
| 126 -- needed for the component to get delegations advertising | |
| 127 for callback in connected_cb:items() do | |
| 128 callback(event) | |
| 129 end | |
| 130 end | |
| 131 | |
| 132 connected_cb:add(on_component_connected) | |
| 133 module:hook('component-authenticated', on_component_auth) | |
| 134 module:hook('presence/initial', on_presence) |
