summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/lite.new.sql1
-rw-r--r--sql/lite.sql1
-rw-r--r--sql/mssql.sql1
-rw-r--r--sql/mysql.new.sql1
-rw-r--r--sql/mysql.sql1
-rw-r--r--sql/pg.new.sql1
-rw-r--r--sql/pg.sql1
-rw-r--r--src/mod_muc.erl39
-rw-r--r--src/mod_muc_opt.erl7
-rw-r--r--src/mod_muc_room.erl20
-rw-r--r--src/mod_muc_sql.erl9
11 files changed, 80 insertions, 2 deletions
diff --git a/sql/lite.new.sql b/sql/lite.new.sql
index 96c88035..cb8add8a 100644
--- a/sql/lite.new.sql
+++ b/sql/lite.new.sql
@@ -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 (
diff --git a/sql/lite.sql b/sql/lite.sql
index 087035d7..56e8c915 100644
--- a/sql/lite.sql
+++ b/sql/lite.sql
@@ -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 (
diff --git a/sql/mssql.sql b/sql/mssql.sql
index bb786152..f8b65edc 100644
--- a/sql/mssql.sql
+++ b/sql/mssql.sql
@@ -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,
diff --git a/sql/mysql.new.sql b/sql/mysql.new.sql
index 01aeffbc..c4e021ab 100644
--- a/sql/mysql.new.sql
+++ b/sql/mysql.new.sql
@@ -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,
diff --git a/sql/mysql.sql b/sql/mysql.sql
index 7feaf5d0..751552e1 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -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,
diff --git a/sql/pg.new.sql b/sql/pg.new.sql
index 6a0743f2..5ffbedde 100644
--- a/sql/pg.new.sql
+++ b/sql/pg.new.sql
@@ -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 (
diff --git a/sql/pg.sql b/sql/pg.sql
index 0e3d4c8b..733856ed 100644
--- a/sql/pg.sql
+++ b/sql/pg.sql
@@ -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 (
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index b2ebc5c6..2853632c 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -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 =>
diff --git a/src/mod_muc_opt.erl b/src/mod_muc_opt.erl
index 760a5d7c..4b9e8b80 100644
--- a/src/mod_muc_opt.erl
+++ b/src/mod_muc_opt.erl
@@ -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);
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index e8b0d1bc..ec1c551e 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -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
diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl
index 1310cde7..8aa7ad62 100644
--- a/src/mod_muc_sql.erl
+++ b/src/mod_muc_sql.erl
@@ -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
%%%===================================================================