From 3f4066aba0a7a4d4a44a30b269ab665a9f36fc07 Mon Sep 17 00:00:00 2001 From: Nelson Vides Date: Tue, 15 Feb 2022 16:21:49 +0100 Subject: [PATCH] Implement remove marker on user leaves room --- big_tests/tests/smart_markers_SUITE.erl | 18 ++++++++++++ src/smart_markers/mod_smart_markers.erl | 28 +++++++++++++++++-- .../mod_smart_markers_backend.erl | 10 +++++++ src/smart_markers/mod_smart_markers_rdbms.erl | 10 ++++++- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/big_tests/tests/smart_markers_SUITE.erl b/big_tests/tests/smart_markers_SUITE.erl index d7dfbf44a2e..ed2d395150b 100644 --- a/big_tests/tests/smart_markers_SUITE.erl +++ b/big_tests/tests/smart_markers_SUITE.erl @@ -30,6 +30,7 @@ groups() -> {muclight, [], [ marker_is_stored_for_room, + marker_is_removed_when_user_leaves_room, markers_are_removed_when_room_is_removed ]} ]. @@ -107,6 +108,23 @@ marker_is_stored_for_room(Config) -> fun() -> length(fetch_markers_for_users(BobJid, jid:from_binary(RoomBinJid))) > 0 end, true) end). +marker_is_removed_when_user_leaves_room(Config) -> + escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], + fun(Alice, Bob) -> + Users = [Alice, Bob], + RoomId = create_room(Alice, [Bob], Config), + RoomBinJid = muc_light_helper:room_bin_jid(RoomId), + RoomJid = jid:from_binary(RoomBinJid), + one_marker_in_room(Users, RoomBinJid, Alice, Bob), + BobJid = jid:from_binary(escalus_client:full_jid(Bob)), + mongoose_helper:wait_until( + fun() -> length(fetch_markers_for_users(BobJid, RoomJid)) > 0 end, true), + % Remove Bob from the room + muc_light_helper:user_leave(RoomId, Bob, [Alice]), + mongoose_helper:wait_until( + fun() -> length(fetch_markers_for_users(BobJid, RoomJid)) end, 0) + end). + markers_are_removed_when_room_is_removed(Config) -> escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> Users = [Alice, Bob], diff --git a/src/smart_markers/mod_smart_markers.erl b/src/smart_markers/mod_smart_markers.erl index 6918b1d4a4d..c8e8722d97c 100644 --- a/src/smart_markers/mod_smart_markers.erl +++ b/src/smart_markers/mod_smart_markers.erl @@ -56,6 +56,7 @@ -module(mod_smart_markers). -include("jlib.hrl"). +-include("mod_muc_light.hrl"). -xep([{xep, 333}, {version, "0.3"}]). -behaviour(gen_mod). @@ -69,8 +70,10 @@ -export([get_chat_markers/3]). %% Hook handlers --export([user_send_packet/4, remove_user/3, remove_domain/3, forget_room/4]). --ignore_xref([user_send_packet/4, remove_user/3, remove_domain/3, forget_room/4]). +-export([user_send_packet/4, remove_user/3, remove_domain/3, + forget_room/4, room_new_affiliations/4]). +-ignore_xref([user_send_packet/4, remove_user/3, remove_domain/3, + forget_room/4, room_new_affiliations/4]). %%-------------------------------------------------------------------- %% Type declarations @@ -111,7 +114,8 @@ hooks(HostType) -> [{user_send_packet, HostType, ?MODULE, user_send_packet, 90}, {remove_user, HostType, ?MODULE, remove_user, 60}, {remove_domain, HostType, ?MODULE, remove_domain, 60}, - {forget_room, HostType, ?MODULE, forget_room, 85} + {forget_room, HostType, ?MODULE, forget_room, 85}, + {room_new_affiliations, HostType, ?MODULE, room_new_affiliations, 60} ]. -spec user_send_packet(mongoose_acc:t(), jid:jid(), jid:jid(), exml:element()) -> @@ -143,6 +147,24 @@ forget_room(Acc, HostType, RoomS, RoomU) -> mod_smart_markers_backend:remove_to(HostType, jid:make_noprep(RoomU, RoomS, <<>>)), Acc. +%% The new affs can be found in the Acc:element, where we can scan for 'none' ones +-spec room_new_affiliations(mongoose_acc:t(), jid:jid(), mod_muc_light:aff_users(), binary()) -> + mongoose_acc:t(). +room_new_affiliations(Acc, RoomJid, _NewAffs, _NewVersion) -> + HostType = mod_muc_light_utils:acc_to_host_type(Acc), + Packet = mongoose_acc:element(Acc), + case exml_query:paths(Packet, [{element_with_ns, ?NS_MUC_LIGHT_AFFILIATIONS}, + {element_with_attr, <<"affiliation">>, <<"none">>}, + cdata]) of + [] -> Acc; + Users -> + [begin + FromJid = jid:to_bare(jid:from_binary(User)), + mod_smart_markers_backend:remove_to_for_user(HostType, FromJid, RoomJid) + end || User <- Users ], + Acc + end. + %%-------------------------------------------------------------------- %% Other API %%-------------------------------------------------------------------- diff --git a/src/smart_markers/mod_smart_markers_backend.erl b/src/smart_markers/mod_smart_markers_backend.erl index 1fca9d486e3..20711c224dc 100644 --- a/src/smart_markers/mod_smart_markers_backend.erl +++ b/src/smart_markers/mod_smart_markers_backend.erl @@ -8,6 +8,7 @@ -export([remove_domain/2]). -export([remove_user/2]). -export([remove_to/2]). +-export([remove_to_for_user/3]). %%-------------------------------------------------------------------- %% DB backend behaviour definition @@ -34,6 +35,8 @@ -callback remove_to(mongooseim:host_type(), jid:jid()) -> term(). +-callback remove_to_for_user(mongooseim:host_type(), From :: jid:jid(), To :: jid:jid()) -> term(). + -spec init(mongooseim:host_type(), gen_mod:module_opts()) -> ok. init(HostType, Opts) -> FOpts = add_default_backend(Opts), @@ -76,6 +79,13 @@ remove_to(HostType, To) -> Args = [HostType, To], mongoose_backend:call(HostType, ?MAIN_MODULE, ?FUNCTION_NAME, Args). +%% @doc remove markers a user sent to a given other +%% Useful for when a user leaves a room, but the room still exists +-spec remove_to_for_user(mongooseim:host_type(), From :: jid:jid(), To :: jid:jid()) -> term(). +remove_to_for_user(HostType, From, To) -> + Args = [HostType, From, To], + mongoose_backend:call(HostType, ?MAIN_MODULE, ?FUNCTION_NAME, Args). + add_default_backend(Opts) -> case lists:keyfind(backend, 2, Opts) of false -> [{backend, rdbms} | Opts]; diff --git a/src/smart_markers/mod_smart_markers_rdbms.erl b/src/smart_markers/mod_smart_markers_rdbms.erl index 2dbc12c0a27..7c3fde4cbc6 100644 --- a/src/smart_markers/mod_smart_markers_rdbms.erl +++ b/src/smart_markers/mod_smart_markers_rdbms.erl @@ -11,7 +11,7 @@ -include("jlib.hrl"). -export([init/2, update_chat_marker/2, get_chat_markers/4]). --export([remove_domain/2, remove_user/2, remove_to/2]). +-export([remove_domain/2, remove_user/2, remove_to/2, remove_to_for_user/3]). %%-------------------------------------------------------------------- %% API @@ -33,6 +33,9 @@ init(HostType, _) -> [lserver, from_luser], <<"DELETE FROM smart_markers WHERE lserver=? AND from_luser=?">>), mongoose_rdbms:prepare(markers_remove_to, smart_markers, [to_jid], <<"DELETE FROM smart_markers WHERE to_jid=?">>), + mongoose_rdbms:prepare(markers_remove_to_for_user, smart_markers, + [lserver, from_luser, to_jid], + <<"DELETE FROM smart_markers WHERE lserver=? AND from_luser=? AND to_jid=?">>), ok. %%% @doc @@ -89,6 +92,11 @@ remove_user(HostType, #jid{luser = LU, lserver = LS}) -> remove_to(HostType, To) -> mongoose_rdbms:execute_successfully(HostType, markers_remove_to, [encode_jid(To)]). +-spec remove_to_for_user(mongooseim:host_type(), From :: jid:jid(), To :: jid:jid()) -> + mongoose_rdbms:query_result(). +remove_to_for_user(HostType, #jid{luser = LU, lserver = LS}, To) -> + mongoose_rdbms:execute_successfully(HostType, markers_remove_to_for_user, [LS, LU, encode_jid(To)]). + %%-------------------------------------------------------------------- %% local functions %%--------------------------------------------------------------------