view mod_nodeinfo2/mod_nodeinfo2.lua @ 5519:83ebfc367169

mod_http_oauth2: Return Authentication Time per OpenID Core Section 2 Mandatory To Implement, either MUST include or OPTIONAL depending on things we don't look at, so might as well include it all the time. Since we do not persist authentication state with cookies or such, the authentication time will always be some point between the user being sent to the authorization endpoint and the time they are sent back to the client application.
author Kim Alvefur <zash@zash.se>
date Mon, 05 Jun 2023 22:32:44 +0200
parents bac3dae031ee
children
line wrap: on
line source

local json = require "util.json";
local array = require "util.array";
local add_task = require "util.timer".add_task;
local get_stats = require "core.statsmanager".get_stats;
local list_users = require "core.usermanager".users;
local os_time = os.time;

assert(get_stats, "not compatible with trunk based on openmetrics");

module:depends("http");

local expose_users = module:get_option_boolean("nodeinfo2_expose_users", true);
if expose_users then
	module:depends("lastlog");
end

local expose_posts = module:get_option_boolean("nodeinfo2_expose_posts", true);
if expose_posts then
	module:depends("measure_message_e2ee");
end

local main_store = module:open_store();
local lastlog_store = module:open_store("lastlog");

local data;
if expose_posts then
	data = main_store:get("nodeinfo2") or { message_count = 0 };
end

local total_users = 0;
local week_users = 0;
local month_users = 0;
local half_year_users = 0;

local function update_user_list()
	for user in list_users(module.host) do
		total_users = total_users + 1;
		local lastlog = lastlog_store:get(user);
		if lastlog and lastlog.timestamp then
			local delta = os_time() - lastlog.timestamp;
			if delta < 7 * 86400 then
				week_users = week_users + 1;
			end
			if delta < 30 * 86400 then
				month_users = month_users + 1;
			end
			if delta < 6 * 30 * 86400 then
				half_year_users = half_year_users + 1;
			end
		end
	end

	-- Remove the properties if we couldn’t find a single active user.  It most likely means mod_lastlog isn’t in use.
	if half_year_users == 0 and month_users == 0 and week_users == 0 then
		week_users = nil;
		month_users = nil;
		half_year_users = nil;
	end
end

if expose_users then
	add_task(86400, update_user_list);
	update_user_list();
end

module:provides("http", {
	default_path = "/.well-known/x-nodeinfo2";
	route = {
		GET = function (event)
			local usage = {};
			if expose_users then
				usage.users = {
					total = total_users;
					activeWeek = week_users;
					activeMonth = month_users;
					activeHalfyear = half_year_users;
				};
			end

			if expose_posts then
				local stats, changed_only, extras = get_stats();
				for stat, _ in pairs(stats) do
					if stat == "/"..module.host.."/mod_measure_message_e2ee/message:rate" then
						local new_message_count = extras[stat].total;
						if new_message_count ~= data.message_count then
							data = { message_count = new_message_count };
							main_store:set("nodeinfo2", data);
						end
					end
				end
				usage.localPosts = data.message_count;
				-- TODO: also count PubSub replies here.
				usage.localComments = 0;
			end

			event.response.headers.content_type = "application/json";
			return json.encode({
				version = "1.0";
				server = {
					baseUrl = module:http_url("","/");
					name = module.host;
					software = "Prosody";
					version = prosody.version;
				};
				--[[ TODO re-use data from mod_server_contact_info ?
				organization = {
					name = "";
					contact = "";
					account = "";
				};
				--]]
				protocols = array {
					"xmpp",
				};
				services = {
					inbound = array {
						"xmpp";
					};
					outbound = array {
						"xmpp";
					};
				};
				openRegistrations = module:get_option_boolean("allow_registration", false);
				usage = usage;
			});
		end;
	}
});