Software / code / prosody
Comparison
core/rostermanager.lua @ 10563:e8db377a2983
Merge 0.11->trunk
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Tue, 24 Dec 2019 00:39:45 +0100 |
| parent | 10514:f0e9e5bda415 |
| child | 10570:962efe23975d |
comparison
equal
deleted
inserted
replaced
| 10562:670afc079f68 | 10563:e8db377a2983 |
|---|---|
| 10 | 10 |
| 11 | 11 |
| 12 local log = require "util.logger".init("rostermanager"); | 12 local log = require "util.logger".init("rostermanager"); |
| 13 | 13 |
| 14 local new_id = require "util.id".short; | 14 local new_id = require "util.id".short; |
| 15 local new_cache = require "util.cache".new; | |
| 15 | 16 |
| 16 local pairs = pairs; | 17 local pairs = pairs; |
| 17 local tostring = tostring; | 18 local tostring = tostring; |
| 18 local type = type; | 19 local type = type; |
| 19 | 20 |
| 109 if roster then return roster; end | 110 if roster then return roster; end |
| 110 log("debug", "load_roster: loading for new user: %s", jid); | 111 log("debug", "load_roster: loading for new user: %s", jid); |
| 111 else -- Attempt to load roster for non-loaded user | 112 else -- Attempt to load roster for non-loaded user |
| 112 log("debug", "load_roster: loading for offline user: %s", jid); | 113 log("debug", "load_roster: loading for offline user: %s", jid); |
| 113 end | 114 end |
| 115 local roster_cache = hosts[host] and hosts[host].roster_cache; | |
| 116 if not roster_cache then | |
| 117 if hosts[host] then | |
| 118 roster_cache = new_cache(1024); | |
| 119 hosts[host].roster_cache = roster_cache; | |
| 120 end | |
| 121 else | |
| 122 roster = roster_cache:get(jid); | |
| 123 if roster then | |
| 124 log("debug", "load_roster: cache hit"); | |
| 125 roster_cache:set(jid, roster); | |
| 126 if user then user.roster = roster; end | |
| 127 return roster; | |
| 128 else | |
| 129 log("debug", "load_roster: cache miss, loading from storage"); | |
| 130 end | |
| 131 end | |
| 114 local roster_store = storagemanager.open(host, "roster", "keyval"); | 132 local roster_store = storagemanager.open(host, "roster", "keyval"); |
| 115 local data, err = roster_store:get(username); | 133 local data, err = roster_store:get(username); |
| 116 roster = data or {}; | 134 roster = data or {}; |
| 117 if user then user.roster = roster; end | 135 if user then user.roster = roster; end |
| 118 local legacy_pending = roster.pending and type(roster.pending.subscription) ~= "string"; | 136 local legacy_pending = roster.pending and type(roster.pending.subscription) ~= "string"; |
| 132 end | 150 end |
| 133 end | 151 end |
| 134 if not err then | 152 if not err then |
| 135 hosts[host].events.fire_event("roster-load", { username = username, host = host, roster = roster }); | 153 hosts[host].events.fire_event("roster-load", { username = username, host = host, roster = roster }); |
| 136 end | 154 end |
| 155 if roster_cache and not user then | |
| 156 log("debug", "load_roster: caching loaded roster"); | |
| 157 roster_cache:set(jid, roster); | |
| 158 end | |
| 137 return roster, err; | 159 return roster, err; |
| 138 end | 160 end |
| 139 | 161 |
| 140 function save_roster(username, host, roster, jid) | 162 function save_roster(username, host, roster, jid) |
| 141 if not um_user_exists(username, host) then | 163 if not um_user_exists(username, host) then |
| 261 return item and (item.subscription == "to" or item.subscription == "both"), err; | 283 return item and (item.subscription == "to" or item.subscription == "both"), err; |
| 262 end | 284 end |
| 263 | 285 |
| 264 function is_contact_pending_in(username, host, jid) | 286 function is_contact_pending_in(username, host, jid) |
| 265 local roster = load_roster(username, host); | 287 local roster = load_roster(username, host); |
| 266 return roster[false].pending[jid]; | 288 return roster[false].pending[jid] ~= nil; |
| 267 end | 289 end |
| 268 local function set_contact_pending_in(username, host, jid) | 290 local function set_contact_pending_in(username, host, jid, stanza) |
| 269 local roster = load_roster(username, host); | 291 local roster = load_roster(username, host); |
| 270 local item = roster[jid]; | 292 local item = roster[jid]; |
| 271 if item and (item.subscription == "from" or item.subscription == "both") then | 293 if item and (item.subscription == "from" or item.subscription == "both") then |
| 272 return; -- false | 294 return; -- false |
| 273 end | 295 end |
| 274 roster[false].pending[jid] = true; | 296 roster[false].pending[jid] = st.is_stanza(stanza) and st.preserialize(stanza) or true; |
| 275 return save_roster(username, host, roster, jid); | 297 return save_roster(username, host, roster, jid); |
| 276 end | 298 end |
| 277 function is_contact_pending_out(username, host, jid) | 299 function is_contact_pending_out(username, host, jid) |
| 278 local roster = load_roster(username, host); | 300 local roster = load_roster(username, host); |
| 279 local item = roster[jid]; | 301 local item = roster[jid]; |
| 280 return item and item.ask; | 302 return item and item.ask; |
| 303 end | |
| 304 local function is_contact_preapproved(username, host, jid) | |
| 305 local roster = load_roster(username, host); | |
| 306 local item = roster[jid]; | |
| 307 return item and (item.approved == "true"); | |
| 281 end | 308 end |
| 282 local function set_contact_pending_out(username, host, jid) -- subscribe | 309 local function set_contact_pending_out(username, host, jid) -- subscribe |
| 283 local roster = load_roster(username, host); | 310 local roster = load_roster(username, host); |
| 284 local item = roster[jid]; | 311 local item = roster[jid]; |
| 285 if item and (item.ask or item.subscription == "to" or item.subscription == "both") then | 312 if item and (item.ask or item.subscription == "to" or item.subscription == "both") then |
| 307 item.subscription = "none"; | 334 item.subscription = "none"; |
| 308 end | 335 end |
| 309 return save_roster(username, host, roster, jid); | 336 return save_roster(username, host, roster, jid); |
| 310 end | 337 end |
| 311 local function subscribed(username, host, jid) | 338 local function subscribed(username, host, jid) |
| 339 local roster = load_roster(username, host); | |
| 340 local item = roster[jid]; | |
| 341 | |
| 312 if is_contact_pending_in(username, host, jid) then | 342 if is_contact_pending_in(username, host, jid) then |
| 313 local roster = load_roster(username, host); | |
| 314 local item = roster[jid]; | |
| 315 if not item then -- FIXME should roster item be auto-created? | 343 if not item then -- FIXME should roster item be auto-created? |
| 316 item = {subscription = "none", groups = {}}; | 344 item = {subscription = "none", groups = {}}; |
| 317 roster[jid] = item; | 345 roster[jid] = item; |
| 318 end | 346 end |
| 319 if item.subscription == "none" then | 347 if item.subscription == "none" then |
| 321 else -- subscription == to | 349 else -- subscription == to |
| 322 item.subscription = "both"; | 350 item.subscription = "both"; |
| 323 end | 351 end |
| 324 roster[false].pending[jid] = nil; | 352 roster[false].pending[jid] = nil; |
| 325 return save_roster(username, host, roster, jid); | 353 return save_roster(username, host, roster, jid); |
| 326 end -- TODO else implement optional feature pre-approval (ask = subscribed) | 354 elseif not item or item.subscription == "none" or item.subscription == "to" then |
| 355 -- Contact is not subscribed and has not sent a subscription request. | |
| 356 -- We store a pre-approval as per RFC6121 3.4 | |
| 357 if not item then | |
| 358 item = {subscription = "none", groups = {}}; | |
| 359 roster[jid] = item; | |
| 360 end | |
| 361 item.approved = "true"; | |
| 362 log("debug", "Storing preapproval for %s", jid); | |
| 363 return save_roster(username, host, roster, jid); | |
| 364 end | |
| 327 end | 365 end |
| 328 local function unsubscribed(username, host, jid) | 366 local function unsubscribed(username, host, jid) |
| 329 local roster = load_roster(username, host); | 367 local roster = load_roster(username, host); |
| 330 local item = roster[jid]; | 368 local item = roster[jid]; |
| 331 local pending = is_contact_pending_in(username, host, jid); | 369 local pending = is_contact_pending_in(username, host, jid); |
| 379 is_user_subscribed = is_user_subscribed; | 417 is_user_subscribed = is_user_subscribed; |
| 380 is_contact_pending_in = is_contact_pending_in; | 418 is_contact_pending_in = is_contact_pending_in; |
| 381 set_contact_pending_in = set_contact_pending_in; | 419 set_contact_pending_in = set_contact_pending_in; |
| 382 is_contact_pending_out = is_contact_pending_out; | 420 is_contact_pending_out = is_contact_pending_out; |
| 383 set_contact_pending_out = set_contact_pending_out; | 421 set_contact_pending_out = set_contact_pending_out; |
| 422 is_contact_preapproved = is_contact_preapproved; | |
| 384 unsubscribe = unsubscribe; | 423 unsubscribe = unsubscribe; |
| 385 subscribed = subscribed; | 424 subscribed = subscribed; |
| 386 unsubscribed = unsubscribed; | 425 unsubscribed = unsubscribed; |
| 387 process_outbound_subscription_request = process_outbound_subscription_request; | 426 process_outbound_subscription_request = process_outbound_subscription_request; |
| 388 }; | 427 }; |