Software /
code /
prosody
Changeset
10514:f0e9e5bda415
rostermanager, mod_presence: Support for subscription preapproval (fixes #686)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Thu, 19 Dec 2019 10:03:16 +0000 |
parents | 10513:7a82f7ecf0ce |
children | 10515:35bf3b80480f |
files | core/rostermanager.lua plugins/mod_presence.lua spec/scansion/presence_preapproval.scs |
diffstat | 3 files changed, 104 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/core/rostermanager.lua Tue Dec 17 00:34:39 2019 +0100 +++ b/core/rostermanager.lua Thu Dec 19 10:03:16 2019 +0000 @@ -301,6 +301,11 @@ local item = roster[jid]; return item and item.ask; end +local function is_contact_preapproved(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + return item and (item.approved == "true"); +end local function set_contact_pending_out(username, host, jid) -- subscribe local roster = load_roster(username, host); local item = roster[jid]; @@ -331,9 +336,10 @@ return save_roster(username, host, roster, jid); end local function subscribed(username, host, jid) + local roster = load_roster(username, host); + local item = roster[jid]; + if is_contact_pending_in(username, host, jid) then - local roster = load_roster(username, host); - local item = roster[jid]; if not item then -- FIXME should roster item be auto-created? item = {subscription = "none", groups = {}}; roster[jid] = item; @@ -345,7 +351,17 @@ end roster[false].pending[jid] = nil; return save_roster(username, host, roster, jid); - end -- TODO else implement optional feature pre-approval (ask = subscribed) + elseif not item or item.subscription == "none" or item.subscription == "to" then + -- Contact is not subscribed and has not sent a subscription request. + -- We store a pre-approval as per RFC6121 3.4 + if not item then + item = {subscription = "none", groups = {}}; + roster[jid] = item; + end + item.approved = "true"; + log("debug", "Storing preapproval for %s", jid); + return save_roster(username, host, roster, jid); + end end local function unsubscribed(username, host, jid) local roster = load_roster(username, host); @@ -403,6 +419,7 @@ set_contact_pending_in = set_contact_pending_in; is_contact_pending_out = is_contact_pending_out; set_contact_pending_out = set_contact_pending_out; + is_contact_preapproved = is_contact_preapproved; unsubscribe = unsubscribe; subscribed = subscribed; unsubscribed = unsubscribed;
--- a/plugins/mod_presence.lua Tue Dec 17 00:34:39 2019 +0100 +++ b/plugins/mod_presence.lua Thu Dec 19 10:03:16 2019 +0000 @@ -181,8 +181,10 @@ if rostermanager.subscribed(node, host, to_bare) then rostermanager.roster_push(node, host, to_bare); end - core_post_stanza(origin, stanza); - send_presence_of_available_resources(node, host, to_bare, origin); + if rostermanager.is_contact_subscribed(node, host, to_bare) then + core_post_stanza(origin, stanza); + send_presence_of_available_resources(node, host, to_bare, origin); + end if rostermanager.is_user_subscribed(node, host, to_bare) then core_post_stanza(origin, st.presence({ type = "probe", from = from_bare, to = to_bare })); end @@ -229,6 +231,12 @@ if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"}), true); -- TODO send last activity end + elseif rostermanager.is_contact_preapproved(node, host, from_bare) then + if not rostermanager.is_contact_pending_in(node, host, from_bare) then + if rostermanager.set_contact_pending_in(node, host, from_bare, stanza) then + core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="subscribed"}), true); + end -- TODO else return error, unable to save + end else core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"}), true); -- acknowledging receipt if not rostermanager.is_contact_pending_in(node, host, from_bare) then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spec/scansion/presence_preapproval.scs Thu Dec 19 10:03:16 2019 +0000 @@ -0,0 +1,74 @@ +# server supports contact subscription pre-approval (RFC 6121 3.4) + +[Client] Alice + jid: preappove-a@localhost + password: password + +[Client] Bob + jid: preapprove-b@localhost + password: password + +--------- + +Alice connects + +Alice sends: + <presence/> + +Alice receives: + <presence/> + +Alice sends: + <presence to="${Bob's JID}" type="subscribed"/> + +Bob connects + +Bob sends: + <iq type="get" id="roster1"> + <query xmlns="jabber:iq:roster"/> + </iq> + +Bob receives: + <iq type="result" id="roster1"> + <query xmlns="jabber:iq:roster" ver="{scansion:any}"> + </query> + </iq> + +Bob sends: + <presence/> + +Bob receives: + <presence from="${Bob's full JID}"/> + +Bob sends: + <presence to="${Alice's JID}" type="subscribe" /> + +Bob receives: + <iq type='set' id='{scansion:any}'> + <query ver='1' xmlns='jabber:iq:roster'> + <item jid="${Alice's JID}" subscription='none' ask='subscribe' /> + </query> + </iq> + + + +Bob receives: + <presence from="${Alice's JID}" type="subscribed" /> + +Bob disconnects + +Alice sends: + <iq type="get" id="roster1"> + <query xmlns="jabber:iq:roster"/> + </iq> + +Alice receives: + <iq type="result" id="roster1"> + <query xmlns="jabber:iq:roster" ver="{scansion:any}"> + <item jid="${Bob's JID}" subscription="from" /> + </query> + </iq> + +Alice disconnects + +Bob disconnects