diff options
author | Matthew Wild <mwild1@gmail.com> | 2019-12-19 10:03:16 +0000 |
---|---|---|
committer | Matthew Wild <mwild1@gmail.com> | 2019-12-19 10:03:16 +0000 |
commit | 173990157fad6d4507e8ce2dc214e7bf35a17822 (patch) | |
tree | 1d7cba4384d9413b605b7e06c729b3fb44dfa1fa | |
parent | ad26a3b047ab0ae2efa0d61553e32f77da2ccac4 (diff) | |
download | prosody-173990157fad6d4507e8ce2dc214e7bf35a17822.tar.gz prosody-173990157fad6d4507e8ce2dc214e7bf35a17822.zip |
rostermanager, mod_presence: Support for subscription preapproval (fixes #686)
-rw-r--r-- | core/rostermanager.lua | 23 | ||||
-rw-r--r-- | plugins/mod_presence.lua | 12 | ||||
-rw-r--r-- | spec/scansion/presence_preapproval.scs | 74 |
3 files changed, 104 insertions, 5 deletions
diff --git a/core/rostermanager.lua b/core/rostermanager.lua index d551a1b1..7b104339 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -301,6 +301,11 @@ function is_contact_pending_out(username, host, jid) 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 @@ local function unsubscribe(username, host, jid) 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 @@ local function subscribed(username, host, jid) 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 @@ return { 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; diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index f7f458ca..b874277c 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -181,8 +181,10 @@ function handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_ 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 @@ function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_b 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 diff --git a/spec/scansion/presence_preapproval.scs b/spec/scansion/presence_preapproval.scs new file mode 100644 index 00000000..ce6158d2 --- /dev/null +++ b/spec/scansion/presence_preapproval.scs @@ -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 |