annotate mod_devices/mod_devices.lua @ 5342:e28ba69b5307

mod_rest: Implement use of refresh tokens in rest.sh example Because having access tokens expire daily was becoming annoying. Now this is starting to be in dire need of refactoring.
author Kim Alvefur <zash@zash.se>
date Wed, 12 Apr 2023 11:24:50 +0200
parents 4cf65afd90f4
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3397
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local it = require "util.iterators";
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 local new_id = require "util.id".medium;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 local max_user_devices = module:get_option_number("max_user_devices", 5);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 local device_store = module:open_store("devices");
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 local device_map_store = module:open_store("devices", "map");
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 --- Helper functions
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 local function _compare_device_timestamps(a, b)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 return (a.last_activity_at or 0) < (b.last_activity_at or 0);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 local function sorted_devices(devices)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 return it.sorted_pairs(devices, _compare_device_timestamps);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 local function new_device(username, alt_ids)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 local current_time = os.time();
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 local device = {
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 id = "dv-"..new_id();
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 created_at = current_time;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 last_activity = "created";
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 last_activity_at = current_time;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 alt_ids = alt_ids or {};
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 };
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 local devices = device_store:get(username);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 if not devices then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 devices = {};
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 devices[device.id] = device;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 local devices_ordered = {};
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 for id in sorted_devices(devices) do
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 table.insert(devices_ordered, id);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 if #devices_ordered > max_user_devices then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 -- Iterate through oldest devices that are above limit, backwards
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 for i = #devices_ordered, max_user_devices+1, -1 do
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 local id = table.remove(devices_ordered, i);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 devices[id] = nil;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 module:log("debug", "Removing old device for %s: %s", username, id);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 device_store:set(username, devices);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 return device;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 local function get_device_with_alt_id(username, alt_id_type, alt_id)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 local devices = device_store:get(username);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 if not devices then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 return nil;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 for _, device in pairs(devices) do
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 if device.alt_ids[alt_id_type] == alt_id then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 return device;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 local function set_device_alt_id(username, device_id, alt_id_type, alt_id)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 local devices = device_store:get(username);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 if not devices or not devices[device_id] then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 return nil, "no such device";
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 devices[device_id].alt_ids[alt_id_type] = alt_id;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 local function record_device_state(username, device_id, activity, time)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 local device = device_map_store:get(username, device_id);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 device.last_activity = activity;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 device.last_activity_at = time or os.time();
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 device_map_store:set(username, device_id, device);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 local function find_device(username, info)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 for _, alt_id_type in ipairs({ "resumption_token", "resource" }) do
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 local alt_id = info[alt_id_type];
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 if alt_id then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 local device = get_device_with_alt_id(username, alt_id_type, alt_id);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 if device then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 return device, alt_id_type;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 --- Information gathering
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 module:hook("pre-resource-bind", function (event)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 event.session.device_requested_resource = event.resource;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 end, 1000);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 local function store_resumption_token(session, stanza)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 session.device_requested_resume = stanza.attr.previd;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
99 module:hook_stanza("urn:xmpp:sm:2", "resume", store_resumption_token, 5);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 module:hook_stanza("urn:xmpp:sm:3", "resume", store_resumption_token, 5);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 --- Identify device after resource bind
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 module:hook("resource-bind", function (event)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 local info = {
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 resource = event.session.device_requested_resource;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107 resumption_token = event.session.device_requested_resume;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 };
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 local device, source = find_device(event.session.username, info);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 if device then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 event.session.log("debug", "Associated with device %s (from %s)", device.id, source);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 event.session.device_id = device.id;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 else
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 device = new_device(event.session.username, info);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115 event.session.log("debug", "Creating new device %s for session", device.id);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 event.session.device_id = device.id;
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
118 record_device_state(event.session.username, device.id, "login");
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 end, 1000);
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 module:hook("resource-unbind", function (event)
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122 if event.session.device_id then
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 record_device_state(event.session.username, event.session.device_id, "logout");
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124 end
4cf65afd90f4 mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
125 end);