Mercurial > prosody-modules
diff mod_privilege/mod_privilege.lua @ 1725:d85d5b0bf977
Merge with Goffi
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 07 May 2015 23:39:54 +0200 |
parents | ad7afcf86131 |
children | 0d78bb31348e |
line wrap: on
line diff
--- a/mod_privilege/mod_privilege.lua Wed May 06 01:02:00 2015 +0200 +++ b/mod_privilege/mod_privilege.lua Thu May 07 23:39:54 2015 +0200 @@ -18,15 +18,18 @@ local priv_session = module:shared("/*/privilege/session") --- the folowing sets are used to forward presence stanza -if not priv_session.presence_man_ent then - priv_session.presence_man_ent = set.new() +if priv_session.connected_cb == nil then + -- set used to have connected event listeners + -- which allows a host to react on events from + -- other hosts + priv_session.connected_cb = set.new() end -local presence_man_ent = priv_session.presence_man_ent -if not priv_session.presence_roster then - priv_session.presence_roster = set.new() -end -local presence_roster = priv_session.presence_roster +local connected_cb = priv_session.connected_cb + +-- the folowing sets are used to forward presence stanza +-- the folowing sets are used to forward presence stanza +local presence_man_ent = set.new() +local presence_roster = set.new() local _ALLOWED_ROSTER = set.new({'none', 'get', 'set', 'both'}) local _ROSTER_GET_PERM = set.new({'get', 'both'}) @@ -44,12 +47,12 @@ --> Permissions management <-- -privileges = module:get_option("privileged_entities", {}) +local privileges = module:get_option("privileged_entities", {}) -function advertise_perm(session, to_jid, perms) +local function advertise_perm(session, to_jid, perms) -- send <message/> stanza to advertise permissions -- as expained in § 4.2 - local message = st.message({to=to_jid}) + local message = st.message({from=module.host, to=to_jid}) :tag("privilege", {xmlns=_PRIV_ENT_NS}) for _, perm in pairs({'roster', 'message', 'presence'}) do @@ -60,8 +63,8 @@ session.send(message) end -function set_presence_perm_set(to_jid, perms) - -- fill the global presence sets according to perms +local function set_presence_perm_set(to_jid, perms) + -- fill the presence sets according to perms if _PRESENCE_MANAGED:contains(perms.presence) then presence_man_ent:add(to_jid) end @@ -70,7 +73,7 @@ end end -function advertise_presences(session, to_jid, perms) +local function advertise_presences(session, to_jid, perms) -- send presence status for already conencted entities -- as explained in § 7.1 -- people in roster are probed only for active sessions @@ -92,7 +95,7 @@ local bare_jid = jid.bare(user_session.full_jid) for entity, item in pairs(user_session.roster) do if entity~=false and entity~="pending" and (item.subscription=="both" or item.subscription=="to") then - _, host = jid.split(entity) + local _, host = jid.split(entity) if not hosts[host] then -- we don't probe jid from hosts we manage -- using a table with entity as key avoid probing several time the same one to_probe[entity] = bare_jid @@ -104,14 +107,14 @@ end -- now we probe peoples for "roster" presence permission - for to_jid, from_jid in pairs(to_probe) do - module:log("debug", "probing presence for %s (on behalf of %s)", tostring(to_jid), tostring(from_jid)) - local probe = st.presence({from=from_jid, to=to_jid, type="probe"}) + for probe_to, probe_from in pairs(to_probe) do + module:log("debug", "probing presence for %s (on behalf of %s)", tostring(probe_to), tostring(probe_from)) + local probe = st.presence({from=probe_from, to=probe_to, type="probe"}) prosody.core_route_stanza(nil, probe) end end -function on_auth(event) +local function on_auth(event) -- Check if entity is privileged according to configuration, -- and set session.privileges accordingly @@ -138,7 +141,7 @@ if ent_priv.permission == 'roster' and not _ROSTER_GET_PERM:contains(session.privileges.roster) then module:log("warn", "Can't allow roster presence privilege without roster \"get\" privilege") module:log("warn", "Setting presence permission to none") - end_priv.permission = nil + ent_priv.permission = nil end if session.type == "component" then @@ -153,10 +156,10 @@ session.privileges = ent_priv end -function on_presence(event) +local function on_presence(event) -- Permission are already checked at this point, -- we only advertise them to the entity - local session, stanza = event.origin, event.stanza; + local session = event.origin if session.privileges then advertise_perm(session, session.full_jid, session.privileges) set_presence_perm_set(session.full_jid, session.privileges) @@ -164,8 +167,18 @@ end end +local function on_component_auth(event) + -- react to component-authenticated event from this host + -- and call the on_auth methods from all other hosts + -- needed for the component to get delegations advertising + for callback in connected_cb:items() do + callback(event) + end +end + +connected_cb:add(on_auth) module:hook('authentication-success', on_auth) -module:hook('component-authenticated', on_auth) +module:hook('component-authenticated', on_component_auth) module:hook('presence/initial', on_presence) @@ -188,17 +201,16 @@ local reply = st.reply(stanza):query("jabber:iq:roster"); for entity_jid, item in pairs(roster) do if entity_jid and entity_jid ~= "pending" then - local node, host = jid.split(entity_jid); - reply:tag("item", { - jid = entity_jid, - subscription = item.subscription, - ask = item.ask, - name = item.name, - }); - for group in pairs(item.groups) do - reply:tag("group"):text(group):up(); - end - reply:up(); -- move out from item + reply:tag("item", { + jid = entity_jid, + subscription = item.subscription, + ask = item.ask, + name = item.name, + }); + for group in pairs(item.groups) do + reply:tag("group"):text(group):up(); + end + reply:up(); -- move out from item end end -- end of code adapted from mod_remote_roster @@ -228,20 +240,19 @@ if not(roster) then return; end local query = stanza.tags[1]; - for i_, item in ipairs(query.tags) do + for _, item in ipairs(query.tags) do if item.name == "item" and item.attr.xmlns == "jabber:iq:roster" and item.attr.jid -- Protection against overwriting roster.pending, until we move it and item.attr.jid ~= "pending" then local item_jid = jid.prep(item.attr.jid); - local node, host, resource = jid.split(item_jid); + local _, host, resource = jid.split(item_jid); if not resource then if item_jid ~= stanza.attr.to then -- not self-item_jid if item.attr.subscription == "remove" then local r_item = roster[item_jid]; if r_item then - local to_bare = node and (node.."@"..host) or host; -- bare jid roster[item_jid] = nil; if roster_manager.save_roster(from_node, from_host, roster) then session.send(st.reply(stanza)); @@ -315,7 +326,7 @@ and privilege_elt.tags[1].attr.xmlns==_FORWARDED_NS then local message_elt = privilege_elt.tags[1]:get_child('message', 'jabber:client') if message_elt ~= nil then - local from_node, from_host, from_resource = jid.split(message_elt.attr.from) + local _, from_host, from_resource = jid.split(message_elt.attr.from) if from_resource == nil and hosts[from_host] then -- we only accept bare jids from one of the server hosts -- at this point everything should be alright, we can send the message prosody.core_route_stanza(nil, message_elt) @@ -340,7 +351,7 @@ --> presence permission <-- -function same_tags(tag1, tag2) +local function same_tags(tag1, tag2) -- check if two tags are equivalent if tag1.name ~= tag2.name then return false; end @@ -362,7 +373,7 @@ return true end -function same_presences(presence1, presence2) +local function same_presences(presence1, presence2) -- check that 2 <presence/> stanzas are equivalent (except for "to" attribute) -- /!\ if the id change but everything else is equivalent, this method return false -- this behaviour may change in the future @@ -386,8 +397,8 @@ return true end -function forward_presence(presence, to_jid) - presence_fwd = st.clone(presence) +local function forward_presence(presence, to_jid) + local presence_fwd = st.clone(presence) presence_fwd.attr.to = to_jid module:log("debug", "presence forwarded to "..to_jid..": "..tostring(presence_fwd)) module:send(presence_fwd) @@ -398,7 +409,7 @@ module:hook("presence/bare", function(event) if presence_man_ent:empty() and presence_roster:empty() then return; end - local session, stanza = event.origin, event.stanza; + local stanza = event.stanza if stanza.attr.type == nil or stanza.attr.type == "unavailable" then if not stanza.attr.to then for entity in presence_man_ent:items() do @@ -406,7 +417,7 @@ end else -- directed presence -- we ignore directed presences from our own host, as we already have them - _, from_host = jid.split(stanza.attr.from) + local _, from_host = jid.split(stanza.attr.from) if hosts[from_host] then return; end -- we don't send several time the same presence, as recommended in §7 #2