mod_lastlog/mod_lastlog.lua
author Kim Alvefur <zash@zash.se>
Sun, 03 Mar 2024 11:23:40 +0100
changeset 5857 97c9b76867ca
parent 1493 d5e8758d391d
permissions -rw-r--r--
mod_log_ringbuffer: Detach event handlers on logging reload (thanks Menel) Otherwise the global event handlers accumulate, one added each time logging is reoladed, and each invocation of the signal or event triggers one dump of each created ringbuffer.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1343
7dbde05b48a9 all the things: Remove trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 1176
diff changeset
     1
local datamanager = require "util.datamanager";
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
     2
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
     3
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
     4
local log_ip = module:get_option_boolean("lastlog_ip_address", false);
1047
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
     5
local host = module.host;
615
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     6
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
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
     8
	local session = event.session;
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
	if session.username then
1047
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    10
		datamanager.store(session.username, host, "lastlog", {
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    11
			event = "login";
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    12
			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
    13
			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
    14
		});
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    15
	end
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    16
end);
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    17
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    18
module:hook("resource-unbind", function(event)
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    19
	local session = event.session;
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    20
	if session.username then
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    21
		datamanager.store(session.username, host, "lastlog", {
38781835c911 mod_lastlog: Keep track of last logout time
Kim Alvefur <zash@zash.se>
parents: 1039
diff changeset
    22
			event = "logout";
615
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    23
			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
    24
			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
    25
		});
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    26
	end
4134d0e25242 mod_lastlog: New module to record last time a user authenticated
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    27
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
    28
1173
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
    29
module:hook("user-registered", function(event)
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
    30
	local session = event.session;
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
    31
	datamanager.store(event.username, host, "lastlog", {
8999967fc4fe mod_lastlog: Collect timestamp on registration
Kim Alvefur <zash@zash.se>
parents: 1172
diff changeset
    32
		event = "registered";
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
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
    43
			datamanager.store(room, module.host, "lastlog", {
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
				event = "message";
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
				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
    46
			});
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
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
    48
	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
    49
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
    50
elseif module:get_option_boolean("lastlog_stamp_offline") then
1176
06e0c279f6a8 mod_lastlog: Import util.datetime
Kim Alvefur <zash@zash.se>
parents: 1175
diff changeset
    51
	local datetime = require"util.datetime".datetime;
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    52
	local function offline_stamp(event)
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    53
		local stanza = event.stanza;
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    54
		local node, to_host = jid.split(stanza.attr.from);
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    55
		if to_host == host and event.origin == hosts[host] and stanza.attr.type == "unavailable" then
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    56
			local data = datamanager.load(node, host, "lastlog");
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    57
			local timestamp = data and data.timestamp;
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    58
			if timestamp then
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    59
				stanza:tag("delay", {
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    60
					xmlns = "urn:xmpp:delay",
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    61
					from = host,
1176
06e0c279f6a8 mod_lastlog: Import util.datetime
Kim Alvefur <zash@zash.se>
parents: 1175
diff changeset
    62
					stamp = datetime(timestamp),
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    63
				}):up();
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    64
			end
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    65
		end
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    66
	end
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    67
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    68
	module:hook("pre-presence/bare", offline_stamp);
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    69
	module:hook("pre-presence/full", offline_stamp);
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    70
end
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    71
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
    72
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
    73
	if not arg[1] or arg[1] == "--help" then
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
    74
		require"util.prosodyctl".show_usage([[mod_lastlog <user@host>]], [[Show when user last logged in or out]]);
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
    75
		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
    76
	end
1049
59f031d1cd38 mod_last_offline: Merge into an option of mod_lastlog
Kim Alvefur <zash@zash.se>
parents: 1048
diff changeset
    77
	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
    78
	require"core.storagemanager".initialize_host(host);
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
    79
	local lastlog = datamanager.load(user, host, "lastlog");
1048
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    80
	if lastlog then
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    81
		print(("Last %s: %s"):format(lastlog.event or "login",
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    82
		lastlog.timestamp and os.date("%Y-%m-%d %H:%M:%S", lastlog.timestamp) or "<unknown>"));
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    83
		if lastlog.ip then
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    84
			print("IP address: "..lastlog.ip);
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    85
		end
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    86
	else
50bed746aa16 mod_lastlog: Fix command
Kim Alvefur <zash@zash.se>
parents: 1047
diff changeset
    87
		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
    88
		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
    89
	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
    90
	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
    91
end