Handle user removal in mod_muc

This commit is contained in:
Alexey Shchepin 2021-12-14 09:54:00 +03:00
parent a94209a0e0
commit 8b7da70b57
11 changed files with 80 additions and 2 deletions

View File

@ -330,6 +330,7 @@ CREATE TABLE muc_room_subscribers (
);
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers(host, jid);
CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers(jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers(host, room, jid);
CREATE TABLE motd (

View File

@ -302,6 +302,7 @@ CREATE TABLE muc_room_subscribers (
);
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers(host, jid);
CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers(jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers(host, room, jid);
CREATE TABLE motd (

View File

@ -150,6 +150,7 @@ CREATE TABLE [dbo].[muc_room_subscribers] (
CREATE UNIQUE CLUSTERED INDEX [muc_room_subscribers_host_room_jid] ON [muc_room_subscribers] (host, room, jid);
CREATE INDEX [muc_room_subscribers_host_jid] ON [muc_room_subscribers] (host, jid);
CREATE INDEX [muc_room_subscribers_jid] ON [muc_room_subscribers] (jid);
CREATE TABLE [dbo].[privacy_default_list] (
[username] [varchar] (250) NOT NULL,

View File

@ -347,6 +347,7 @@ CREATE TABLE muc_room_subscribers (
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE INDEX i_muc_room_subscribers_host_jid USING BTREE ON muc_room_subscribers(host, jid);
CREATE INDEX i_muc_room_subscribers_jid USING BTREE ON muc_room_subscribers(jid);
CREATE TABLE motd (
username varchar(191) NOT NULL,

View File

@ -319,6 +319,7 @@ CREATE TABLE muc_room_subscribers (
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE INDEX i_muc_room_subscribers_host_jid USING BTREE ON muc_room_subscribers(host, jid);
CREATE INDEX i_muc_room_subscribers_jid USING BTREE ON muc_room_subscribers(jid);
CREATE TABLE motd (
username varchar(191) PRIMARY KEY,

View File

@ -495,6 +495,7 @@ CREATE TABLE muc_room_subscribers (
);
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers USING btree (host, jid);
CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers USING btree (jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers USING btree (host, room, jid);
CREATE TABLE motd (

View File

@ -320,6 +320,7 @@ CREATE TABLE muc_room_subscribers (
);
CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers USING btree (host, jid);
CREATE INDEX i_muc_room_subscribers_jid ON muc_room_subscribers USING btree (jid);
CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers USING btree (host, room, jid);
CREATE TABLE motd (

View File

@ -69,6 +69,7 @@
get_online_rooms_by_user/3,
can_use_nick/4,
get_subscribed_rooms/2,
remove_user/2,
procname/2,
route/1, unhibernate_room/3]).
@ -122,6 +123,8 @@
start(Host, Opts) ->
case mod_muc_sup:start(Host) of
{ok, _} ->
ejabberd_hooks:add(remove_user, Host, ?MODULE,
remove_user, 50),
MyHosts = gen_mod:get_opt_hosts(Opts),
Mod = gen_mod:db_mod(Opts, ?MODULE),
RMod = gen_mod:ram_db_mod(Opts, ?MODULE),
@ -133,6 +136,8 @@ start(Host, Opts) ->
end.
stop(Host) ->
ejabberd_hooks:delete(remove_user, Host, ?MODULE,
remove_user, 50),
Proc = mod_muc_sup:procname(Host),
supervisor:terminate_child(ejabberd_gen_mod_sup, Proc),
supervisor:delete_child(ejabberd_gen_mod_sup, Proc).
@ -1122,6 +1127,32 @@ count_online_rooms(ServerHost, Host) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
RMod:count_online_rooms(ServerHost, Host).
-spec remove_user(binary(), binary()) -> ok.
remove_user(User, Server) ->
LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server),
Mod = gen_mod:db_mod(LServer, ?MODULE),
case erlang:function_exported(Mod, remove_user, 2) of
true ->
Mod:remove_user(LUser, LServer);
false ->
ok
end,
JID = jid:make(User, Server),
lists:foreach(
fun(Host) ->
lists:foreach(
fun({_, _, Pid}) ->
mod_muc_room:change_item(
Pid, JID, affiliation, none, <<"User removed">>),
mod_muc_room:change_item(
Pid, JID, role, none, <<"User removed">>)
end,
get_online_rooms(LServer, Host))
end,
gen_mod:get_module_opt_hosts(LServer, mod_muc)),
ok.
opts_to_binary(Opts) ->
lists:map(
fun({title, Title}) ->
@ -1225,6 +1256,8 @@ mod_opt_type(user_message_shaper) ->
econf:atom();
mod_opt_type(user_presence_shaper) ->
econf:atom();
mod_opt_type(cleanup_affiliations_on_start) ->
econf:bool();
mod_opt_type(default_room_options) ->
econf:options(
#{allow_change_subj => econf:bool(),
@ -1302,6 +1335,7 @@ mod_options(Host) ->
{preload_rooms, true},
{hibernation_timeout, infinity},
{vcard, undefined},
{cleanup_affiliations_on_start, false},
{default_room_options,
[{allow_change_subj,true},
{allow_private_messages,true},
@ -1580,6 +1614,11 @@ mod_doc() ->
" -",
" work: true",
" street: Elm Street"]}]}},
{cleanup_affiliations_on_start,
#{value => "true | false",
desc =>
?T("Remove affiliations for non-existing local users on startup. "
"The default value is 'false'.")}},
{default_room_options,
#{value => ?T("Options"),
desc =>

View File

@ -9,6 +9,7 @@
-export([access_mam/1]).
-export([access_persistent/1]).
-export([access_register/1]).
-export([cleanup_affiliations_on_start/1]).
-export([db_type/1]).
-export([default_room_options/1]).
-export([hibernation_timeout/1]).
@ -73,6 +74,12 @@ access_register(Opts) when is_map(Opts) ->
access_register(Host) ->
gen_mod:get_module_opt(Host, mod_muc, access_register).
-spec cleanup_affiliations_on_start(gen_mod:opts() | global | binary()) -> boolean().
cleanup_affiliations_on_start(Opts) when is_map(Opts) ->
gen_mod:get_opt(cleanup_affiliations_on_start, Opts);
cleanup_affiliations_on_start(Host) ->
gen_mod:get_module_opt(Host, mod_muc, cleanup_affiliations_on_start).
-spec db_type(gen_mod:opts() | global | binary()) -> atom().
db_type(Opts) when is_map(Opts) ->
gen_mod:get_opt(db_type, Opts);

View File

@ -306,7 +306,8 @@ init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts, QueueType])
room_shaper = Shaper}),
add_to_log(room_existence, started, State),
ejabberd_hooks:run(start_room, ServerHost, [ServerHost, Room, Host]),
{ok, normal_state, reset_hibernate_timer(State)}.
State1 = cleanup_affiliations(State),
{ok, normal_state, reset_hibernate_timer(State1)}.
normal_state({route, <<"">>,
#message{from = From, type = Type, lang = Lang} = Packet},
@ -5337,6 +5338,23 @@ muc_subscribers_put(Subscriber, MUCSubscribers) ->
subscriber_nodes = NewSubNodes}.
cleanup_affiliations(State) ->
case mod_muc_opt:cleanup_affiliations_on_start(State#state.server_host) of
true ->
Affiliations =
maps:filter(
fun({LUser, LServer, _}, _) ->
case ejabberd_router:is_my_host(LServer) of
true ->
ejabberd_auth:user_exists(LUser, LServer);
false ->
true
end
end, State#state.affiliations),
State#state{affiliations = Affiliations};
false ->
State
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Detect messange stanzas that don't have meaningful content

View File

@ -38,7 +38,7 @@
register_online_user/4, unregister_online_user/4,
count_online_rooms_by_user/3, get_online_rooms_by_user/3,
get_subscribed_rooms/3, get_rooms_without_subscribers/2,
find_online_room_by_pid/2]).
find_online_room_by_pid/2, remove_user/2]).
-export([set_affiliation/6, set_affiliations/4, get_affiliation/5,
get_affiliations/3, search_affiliation/4]).
@ -465,6 +465,13 @@ get_subscribed_rooms(LServer, Host, Jid) ->
{error, db_failure}
end.
remove_user(LUser, LServer) ->
SJID = jid:encode(jid:make(LUser, LServer)),
ejabberd_sql:sql_query(
LServer,
?SQL("delete from muc_room_subscribers where jid=%(SJID)s")),
ok.
%%%===================================================================
%%% Internal functions
%%%===================================================================