Annotate

mod_lastlog2/mod_lastlog2.lua @ 6310:30adcea825c3

mod_conversejs: Fix hostname set as default username (thanks roughnecks) In login mode, it seems jid is used as default value in the login field but it was only needed in anonymous mode.
author Kim Alvefur <zash@zash.se>
date Wed, 18 Jun 2025 14:28:38 +0200
parent 6196:1447f076c970
child 6211:750d64c47ec6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
1 local jid = require "util.jid";
615
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
2 local time = os.time;
616
884ae37d76bf mod_lastlog: Add option to also log the users IP address.
Kim Alvefur <zash@zash.se>
parents: 615
diff changeset
3 local log_ip = module:get_option_boolean("lastlog_ip_address", false);
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
4
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
5 local store;
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
6 if module.host ~= "*" then -- workaround for prosodyctl loading into global context
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
7 store = module:open_store(nil, "map");
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
8 end
615
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
9
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
10 module:hook("authentication-success", function(event)
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
11 local session = event.session;
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
12 if session.username then
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
13 store:set(session.username, "login", {
1047
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
14 timestamp = time(),
1493
d5e8758d391d mod_lastlog: Fix traceback if no session included with event (eg from mod_register_web) (thanks biszkopcik)
Kim Alvefur <zash@zash.se>
parents: 1343
diff changeset
15 ip = log_ip and session and session.ip or nil,
1047
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
16 });
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
17 end
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
18 end);
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
19
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
20 module:hook("resource-unbind", function(event)
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
21 local session = event.session;
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
22 if session.username then
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
23 store:set(session.username, "logout", {
615
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
24 timestamp = time(),
1493
d5e8758d391d mod_lastlog: Fix traceback if no session included with event (eg from mod_register_web) (thanks biszkopcik)
Kim Alvefur <zash@zash.se>
parents: 1343
diff changeset
25 ip = log_ip and session and session.ip or nil,
615
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
26 });
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
27 end
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
28 end);
1039
3f91f17ddaca mod_lastlog: Add prosodyctl command (prosodyctl mod_lastlog JID) to show last login time and IP of user (if available)
Matthew Wild <mwild1@gmail.com>
parents: 616
diff changeset
29
1173
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
30 module:hook("user-registered", function(event)
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
31 local session = event.session;
4102
4e7ff27c212c mod_lastlog2: Fix 'registered' event (Thanks Ge0rG)
Kim Alvefur <zash@zash.se>
parents: 4012
diff changeset
32 store:set(event.username, "registered", {
1173
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
33 timestamp = time(),
1493
d5e8758d391d mod_lastlog: Fix traceback if no session included with event (eg from mod_register_web) (thanks biszkopcik)
Kim Alvefur <zash@zash.se>
parents: 1343
diff changeset
34 ip = log_ip and session and session.ip or nil,
1173
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
35 });
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
36 end);
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
37
1174
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
38
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
39 if module:get_host_type() == "component" then
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
40 module:hook("message/bare", function(event)
1175
9eac4e2386d2 mod_lastlog: Fix jid.split call
Kim Alvefur <zash@zash.se>
parents: 1174
diff changeset
41 local room = jid.split(event.stanza.attr.to);
1174
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
42 if room then
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
43 store:set(room, module.host, "message", {
1174
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
44 timestamp = time(),
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
45 });
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
46 end
bd7901fef71b mod_lastlog: If loaded on a component, store a timestamp of the last message sent, eg to a MUC room
Kim Alvefur <zash@zash.se>
parents: 1173
diff changeset
47 end);
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
48 end
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
49
6195
886c985ece61 mod_lastlog2: Skip initializing internal API (and storage) in prosodyctl
Kim Alvefur <zash@zash.se>
parents: 5900
diff changeset
50 if module.host ~= "*" then
5797
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
51 local user_sessions = prosody.hosts[module.host].sessions;
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
52 local kv_store = module:open_store();
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
53 function get_last_active(username) --luacheck: ignore 131/get_last_active
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
54 if user_sessions[username] then
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
55 return os.time(); -- Currently connected
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
56 else
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
57 local last_activity = kv_store:get(username);
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
58 if not last_activity then return nil; end
5799
5239ed05bd71 mod_lastlog2: Fix to interpret stored data structure correctly
Matthew Wild <mwild1@gmail.com>
parents: 5797
diff changeset
59 local last_login = last_activity.login;
5239ed05bd71 mod_lastlog2: Fix to interpret stored data structure correctly
Matthew Wild <mwild1@gmail.com>
parents: 5797
diff changeset
60 local last_logout = last_activity.logout;
5239ed05bd71 mod_lastlog2: Fix to interpret stored data structure correctly
Matthew Wild <mwild1@gmail.com>
parents: 5797
diff changeset
61 local latest = math.max(last_login and last_login.timestamp or 0, last_logout and last_logout.timestamp or 0);
5797
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
62 if latest == 0 then
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
63 return nil; -- Never logged in
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
64 end
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
65 return latest;
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
66 end
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
67 end
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
68 end
7b722955c59b mod_lastlog2: Expose API to query the last active time of a user
Matthew Wild <mwild1@gmail.com>
parents: 4103
diff changeset
69
6196
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
70 module:add_item("shell-command", {
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
71 section = "lastlog";
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
72 section_desc = "View and manage user activity data";
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
73 name = "show";
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
74 desc = "View recorded user activity for user";
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
75 args = { { name = "jid"; type = "string" } };
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
76 host_selector = "jid";
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
77 handler = function(self, userjid)
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
78 local kv_store = module:open_store();
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
79 local username = jid.prepped_split(userjid);
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
80 local lastlog, err = kv_store:get(username);
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
81 if err then return false, err; end
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
82 if not lastlog then return true, "No record found"; end
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
83 local print = self.session.print;
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
84 for event, data in pairs(lastlog) do
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
85 print(("Last %s: %s"):format(event,
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
86 data.timestamp and os.date("%Y-%m-%d %H:%M:%S", data.timestamp) or "<unknown>"));
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
87 if data.ip then
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
88 print("IP address: "..data.ip);
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
89 end
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
90 end
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
91 return true, "Record shown"
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
92 end;
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
93 });
1447f076c970 mod_lastlog2: Add a shell command
Kim Alvefur <zash@zash.se>
parents: 6195
diff changeset
94
1039
3f91f17ddaca mod_lastlog: Add prosodyctl command (prosodyctl mod_lastlog JID) to show last login time and IP of user (if available)
Matthew Wild <mwild1@gmail.com>
parents: 616
diff changeset
95 function module.command(arg)
1103
59657e03c25c mod_lastlog: Make the command show a help message instead of a traceback when no user given
Kim Alvefur <zash@zash.se>
parents: 1049
diff changeset
96 if not arg[1] or arg[1] == "--help" then
5900
c5df6d53f17f mod_lastlog2: Fix typo from original copy-paste
aidan@jmad.org
parents: 5799
diff changeset
97 require"util.prosodyctl".show_usage([[mod_lastlog2 <user@host>]], [[Show when user last logged in or out]]);
1103
59657e03c25c mod_lastlog: Make the command show a help message instead of a traceback when no user given
Kim Alvefur <zash@zash.se>
parents: 1049
diff changeset
98 return 1;
59657e03c25c mod_lastlog: Make the command show a help message instead of a traceback when no user given
Kim Alvefur <zash@zash.se>
parents: 1049
diff changeset
99 end
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
100 local user, host = jid.prepped_split(table.remove(arg, 1));
1048
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
101 require"core.storagemanager".initialize_host(host);
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
102 store = module:context(host):open_store();
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
103 local lastlog = store:get(user);
1048
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
104 if lastlog then
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
105 for event, data in pairs(lastlog) do
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
106 print(("Last %s: %s"):format(event,
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
107 data.timestamp and os.date("%Y-%m-%d %H:%M:%S", data.timestamp) or "<unknown>"));
4103
ecc6ad057383 mod_lastlog2: Fix reporting of IP address (thanks Ge0rG)
Kim Alvefur <zash@zash.se>
parents: 4102
diff changeset
108 if data.ip then
ecc6ad057383 mod_lastlog2: Fix reporting of IP address (thanks Ge0rG)
Kim Alvefur <zash@zash.se>
parents: 4102
diff changeset
109 print("IP address: "..data.ip);
4012
fd582067c732 mod_lastlog2: Store last timestamp per account event
Kim Alvefur <zash@zash.se>
parents: 1493
diff changeset
110 end
1048
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
111 end
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
112 else
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
113 print("No record found");
1172
1e8b793d8ff9 mod_lastlog: Return a non-zero exit code if no lastlog records were found
Kim Alvefur <zash@zash.se>
parents: 1103
diff changeset
114 return 1;
1039
3f91f17ddaca mod_lastlog: Add prosodyctl command (prosodyctl mod_lastlog JID) to show last login time and IP of user (if available)
Matthew Wild <mwild1@gmail.com>
parents: 616
diff changeset
115 end
3f91f17ddaca mod_lastlog: Add prosodyctl command (prosodyctl mod_lastlog JID) to show last login time and IP of user (if available)
Matthew Wild <mwild1@gmail.com>
parents: 616
diff changeset
116 return 0;
3f91f17ddaca mod_lastlog: Add prosodyctl command (prosodyctl mod_lastlog JID) to show last login time and IP of user (if available)
Matthew Wild <mwild1@gmail.com>
parents: 616
diff changeset
117 end