view mod_cloud_notify_filters/mod_cloud_notify_filters.lua @ 5715:8488ebde5739

mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted This follows the intent behind the OpenID Connect 'prompt' parameter when it does not include the 'consent' keyword, that is the client wishes to skip the consent screen. If the user has already granted the exact same scopes to the exact same client in the past, then one can assume that they may grant it again.
author Kim Alvefur <zash@zash.se>
date Tue, 14 Nov 2023 23:03:37 +0100
parents ba94a5301985
children
line wrap: on
line source

local jid = require "util.jid";

local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed;

local xmlns_push = "urn:xmpp:push:0";
local xmlns_push_filter_unknown = "tigase:push:filter:ignore-unknown:0";
local xmlns_push_filter_muted = "tigase:push:filter:muted:0";
local xmlns_push_filter_groupchat = "tigase:push:filter:groupchat:0";
local xmlns_references = "urn:xmpp:reference:0";

-- https://xeps.tigase.net//docs/push-notifications/encrypt/#41-discovering-support
local function account_disco_info(event)
	event.reply:tag("feature", {var=xmlns_push_filter_unknown}):up();
	event.reply:tag("feature", {var=xmlns_push_filter_muted}):up();
	event.reply:tag("feature", {var=xmlns_push_filter_groupchat}):up();
end
module:hook("account-disco-info", account_disco_info);

function handle_register(event)
	local enable = event.stanza:get_child("enable", xmlns_push);

	local filter_unknown = enable:get_child("ignore-unknown", xmlns_push_filter_unknown);
	if filter_unknown then
		event.push_info.filter_unknown = true;
	end

	local filter_muted = enable:get_child("muted", xmlns_push_filter_muted);
	if filter_muted then
		local muted_jids = {};
		for item in filter_muted:childtags("item") do
			local room_jid = jid.prep(item.attr.jid);
			if not room_jid then
				module:log("warn", "Skipping invalid JID: <%s>", room_jid);
			else
				muted_jids[room_jid] = true;
			end
		end
		event.push_info.muted_jids = muted_jids;
	end

	local filter_groupchat = enable:get_child("groupchat", xmlns_push_filter_groupchat);
	if filter_groupchat then
		local groupchat_rules = {};
		for item in filter_groupchat:childtags("room") do
			local room_jid = jid.prep(item.attr.jid);
			if not room_jid then
				module:log("warn", "Skipping invalid JID: <%s>", item.attr.jid);
			else
				groupchat_rules[room_jid] = {
					when = item.attr.allow;
					nick = item.attr.nick;
				};
			end
		end
		event.push_info.groupchat_rules = groupchat_rules;
	end
end

function handle_push(event)
	local push_info = event.push_info;
	local stanza = event.original_stanza;
	local user_name, user_host = jid.split(stanza.attr.to);
	local sender_jid = jid.bare(stanza.attr.from);

	if push_info.filter_unknown then
		if user_host == module.host and not is_contact_subscribed(user_name, user_host, sender_jid) then
			event.reason = "Filtering: unknown sender";
			return true;
		end
	end

	if push_info.muted_jids then
		if push_info.muted_jids[sender_jid] then
			event.reason = "Filtering: muted";
			return true;
		end
	end

	if stanza.attr.type == "groupchat" and push_info.groupchat_rules then
		local rule = push_info.groupchat_rules[sender_jid];
		if rule then
			if rule.when == "never" then
				event.reason = "Filtering: muted group chat";
				return true;
			elseif rule.when == "mentioned" then
				local mentioned = false;
				local our_uri = "xmpp:"..jid.bare(stanza.attr.to);
				local our_muc_uri = rule.nick and "xmpp:"..sender_jid.."/"..rule.nick;
				for reference in stanza:childtags("reference", xmlns_references) do
					if reference.attr.type == "mention" then
						local mention_uri = reference.attr.uri;
						if mention_uri == our_uri or mention_uri == our_muc_uri then
							mentioned = true;
							break;
						end
					end
				end
				if not mentioned then
					event.reason = "Filtering: not mentioned";
					return true;
				end
			end
		end
	end
end

module:hook("cloud_notify/registration", handle_register);
module:hook("cloud_notify/push", handle_push);