Software /
code /
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 |
child | 1710: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) |