aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMickael Remond <mremond@process-one.net>2019-05-07 14:09:22 +0200
committerMickael Remond <mremond@process-one.net>2019-05-07 14:09:22 +0200
commit945c58d3dbaba5fcaface2ff8e08964df80b0b76 (patch)
treedf579bc86f659b8b3d7663b7ed4611ed3c736c13
parentPut back the presence and s2s tests in the no_db section. (diff)
parentRaise api hook right before performing the call (diff)
Merge branch 'master' of github.com:processone/ejabberd
-rw-r--r--src/ejabberd_auth_anonymous.erl18
-rw-r--r--src/mod_mam.erl7
-rw-r--r--src/mod_muc.erl14
-rw-r--r--src/mod_muc_room.erl2
-rw-r--r--src/mod_offline.erl65
-rw-r--r--src/rest.erl2
-rw-r--r--test/offline_tests.erl81
7 files changed, 150 insertions, 39 deletions
diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl
index 21aecc341..767d99bf2 100644
--- a/src/ejabberd_auth_anonymous.erl
+++ b/src/ejabberd_auth_anonymous.erl
@@ -114,10 +114,16 @@ anonymous_user_exist(User, Server) ->
%% Register connection
-spec register_connection(ejabberd_sm:sid(), jid(), ejabberd_sm:info()) -> ok.
register_connection(_SID,
- #jid{luser = LUser, lserver = LServer}, Info) ->
+ #jid{luser = LUser, lserver = LServer, lresource = LResource}, Info) ->
case proplists:get_value(auth_module, Info) of
?MODULE ->
- ejabberd_hooks:run(register_user, LServer, [LUser, LServer]);
+ % Register user only if we are first resource
+ case ejabberd_sm:get_user_resources(LUser, LServer) of
+ [LResource] ->
+ ejabberd_hooks:run(register_user, LServer, [LUser, LServer]);
+ _ ->
+ ok
+ end;
_ ->
ok
end.
@@ -128,7 +134,13 @@ unregister_connection(_SID,
#jid{luser = LUser, lserver = LServer}, Info) ->
case proplists:get_value(auth_module, Info) of
?MODULE ->
- ejabberd_hooks:run(remove_user, LServer, [LUser, LServer]);
+ % Remove user data only if there is no more resources around
+ case ejabberd_sm:get_user_resources(LUser, LServer) of
+ [] ->
+ ejabberd_hooks:run(remove_user, LServer, [LUser, LServer]);
+ _ ->
+ ok
+ end;
_ ->
ok
end.
diff --git a/src/mod_mam.erl b/src/mod_mam.erl
index ba00d74e5..f050128cd 100644
--- a/src/mod_mam.erl
+++ b/src/mod_mam.erl
@@ -250,11 +250,8 @@ reload(Host, NewOpts, OldOpts) ->
ok
end.
-depends(_Host, Opts) ->
- case proplists:get_bool(user_mucsub_from_muc_archive, Opts) of
- true -> [{mod_muc, hard}, {mod_muc_admin, hard}];
- false -> []
- end.
+depends(_Host, _Opts) ->
+ [].
-spec register_iq_handlers(binary()) -> ok.
register_iq_handlers(Host) ->
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index 76fce1f8e..edc570eed 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -758,6 +758,10 @@ get_subscribed_rooms(Host, User) ->
ServerHost = ejabberd_router:host_of_route(Host),
get_subscribed_rooms(ServerHost, Host, User).
+-record(subscriber, {jid :: jid(),
+ nick = <<>> :: binary(),
+ nodes = [] :: [binary()]}).
+
-spec get_subscribed_rooms(binary(), binary(), jid()) ->
{ok, [{jid(), [binary()]}]} | {error, any()}.
get_subscribed_rooms(ServerHost, Host, From) ->
@@ -768,7 +772,15 @@ get_subscribed_rooms(ServerHost, Host, From) ->
false ->
Rooms = get_online_rooms(ServerHost, Host),
{ok, lists:flatmap(
- fun({Name, _, Pid}) ->
+ fun({Name, _, Pid}) when Pid == self() ->
+ USR = jid:split(BareFrom),
+ case erlang:get(muc_subscribers) of
+ #{USR := #subscriber{nodes = Nodes}} ->
+ [{jid:make(Name, Host), Nodes}];
+ _ ->
+ []
+ end;
+ ({Name, _, Pid}) ->
case p1_fsm:sync_send_all_state_event(
Pid, {is_subscribed, BareFrom}) of
{true, Nodes} ->
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index f972a5feb..94c430197 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -538,6 +538,7 @@ handle_sync_event({change_config, Config}, _From,
{reply, {ok, NSD#state.config}, StateName, NSD};
handle_sync_event({change_state, NewStateData}, _From,
StateName, _StateData) ->
+ erlang:put(muc_subscribers, NewStateData#state.subscribers),
{reply, {ok, NewStateData}, StateName, NewStateData};
handle_sync_event({process_item_change, Item, UJID}, _From, StateName, StateData) ->
case process_item_change(Item, StateData, UJID) of
@@ -4373,6 +4374,7 @@ store_room(StateData) ->
store_room(StateData, []).
store_room(StateData, ChangesHints) ->
% Let store persistent rooms or on those backends that have get_subscribed_rooms
+ erlang:put(muc_subscribers, StateData#state.subscribers),
ShouldStore = case (StateData#state.config)#config.persistent of
true ->
true;
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index 0c70ae065..63a0d6763 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -195,7 +195,7 @@ store_offline_msg(#offline_msg{us = {User, Server}, packet = Pkt} = Msg) ->
infinity ->
Mod:store_message(Msg);
Limit ->
- Num = count_offline_messages(User, Server),
+ Num = count_messages_in_db(User, Server),
if Num < Limit ->
Mod:store_message(Msg);
true ->
@@ -405,31 +405,38 @@ need_to_store(_LServer, #message{type = error}) -> false;
need_to_store(LServer, #message{type = Type} = Packet) ->
case xmpp:has_subtag(Packet, #offline{}) of
false ->
- case check_store_hint(Packet) of
- store ->
- true;
- no_store ->
- false;
- none ->
- Store = case Type of
- groupchat ->
- gen_mod:get_module_opt(
- LServer, ?MODULE, store_groupchat);
- headline ->
- false;
- _ ->
- true
- end,
- case {Store, gen_mod:get_module_opt(
- LServer, ?MODULE, store_empty_body)} of
- {false, _} ->
- false;
- {_, true} ->
+ case misc:unwrap_mucsub_message(Packet) of
+ #message{type = groupchat} = Msg ->
+ need_to_store(LServer, Msg#message{type = chat});
+ #message{} = Msg ->
+ need_to_store(LServer, Msg);
+ _ ->
+ case check_store_hint(Packet) of
+ store ->
true;
- {_, false} ->
- Packet#message.body /= [];
- {_, unless_chat_state} ->
- not misc:is_standalone_chat_state(Packet)
+ no_store ->
+ false;
+ none ->
+ Store = case Type of
+ groupchat ->
+ gen_mod:get_module_opt(
+ LServer, ?MODULE, store_groupchat);
+ headline ->
+ false;
+ _ ->
+ true
+ end,
+ case {Store, gen_mod:get_module_opt(
+ LServer, ?MODULE, store_empty_body)} of
+ {false, _} ->
+ false;
+ {_, true} ->
+ true;
+ {_, false} ->
+ Packet#message.body /= [];
+ {_, unless_chat_state} ->
+ not misc:is_standalone_chat_state(Packet)
+ end
end
end;
true ->
@@ -1046,10 +1053,14 @@ count_offline_messages(User, Server) ->
Res = read_db_messages(LUser, LServer),
count_mam_messages(LUser, LServer, Res);
_ ->
- Mod = gen_mod:db_mod(LServer, ?MODULE),
- Mod:count_messages(LUser, LServer)
+ count_messages_in_db(LUser, LServer)
end.
+-spec count_messages_in_db(binary(), binary()) -> non_neg_integer().
+count_messages_in_db(LUser, LServer) ->
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:count_messages(LUser, LServer).
+
-spec add_delay_info(message(), binary(),
undefined | erlang:timestamp()) -> message().
add_delay_info(Packet, LServer, TS) ->
diff --git a/src/rest.erl b/src/rest.erl
index 05d1b9d4a..9c1b28068 100644
--- a/src/rest.erl
+++ b/src/rest.erl
@@ -100,6 +100,7 @@ request(Server, Method, Path, Params, Mime, Data) ->
{URI, Hdrs}
end,
Begin = os:timestamp(),
+ ejabberd_hooks:run(backend_api_call, Server, [Server, Method, Path]),
Result = try httpc:request(Method, Req, HttpOpts, [{body_format, binary}]) of
{ok, {{_, Code, _}, RetHdrs, Body}} ->
try decode_json(Body) of
@@ -118,7 +119,6 @@ request(Server, Method, Path, Params, Mime, Data) ->
exit:Reason ->
{error, {http_error, {error, Reason}}}
end,
- ejabberd_hooks:run(backend_api_call, Server, [Server, Method, Path]),
case Result of
{error, {http_error, {error, timeout}}} ->
ejabberd_hooks:run(backend_api_timeout, Server,
diff --git a/test/offline_tests.erl b/test/offline_tests.erl
index 179a2415c..97d9ee58b 100644
--- a/test/offline_tests.erl
+++ b/test/offline_tests.erl
@@ -27,7 +27,8 @@
-compile(export_all).
-import(suite, [send/2, disconnect/1, my_jid/1, send_recv/2, recv_message/1,
get_features/1, recv/1, get_event/1, server_jid/1,
- wait_for_master/1, wait_for_slave/1]).
+ wait_for_master/1, wait_for_slave/1,
+ connect/1, open_session/1, bind/1, auth/1]).
-include("suite.hrl").
%%%===================================================================
@@ -147,7 +148,9 @@ master_slave_cases(DB) ->
master_slave_test(send_all)] ++
case DB of
riak -> [];
- _ -> [master_slave_test(from_mam)]
+ _ -> [
+ master_slave_test(from_mam),
+ master_slave_test(mucsub_mam)]
end
}.
@@ -194,6 +197,80 @@ from_mam_slave(Config) ->
C4 = lists:keydelete(mam_enabled, 1, C3),
mam_tests:clean(C4).
+mucsub_mam_master(Config) ->
+ Room = suite:muc_room_jid(Config),
+ Peer = ?config(peer, Config),
+ wait_for_slave(Config),
+ ct:comment("Joining muc room"),
+ ok = muc_tests:join_new(Config),
+
+ ct:comment("Enabling mam in room"),
+ CfgOpts = muc_tests:get_config(Config),
+ %% Find the MAM field in the config
+ ?match(true, proplists:is_defined(mam, CfgOpts)),
+ ?match(true, proplists:is_defined(allow_subscription, CfgOpts)),
+ %% Enable MAM
+ [104] = muc_tests:set_config(Config, [{mam, true}, {allow_subscription, true}]),
+
+ ct:comment("Subscribing peer to room"),
+ ?send_recv(#iq{to = Room, type = set, sub_els = [
+ #muc_subscribe{jid = Peer, nick = <<"peer">>,
+ events = [?NS_MUCSUB_NODES_MESSAGES]}
+ ]}, #iq{type = result}),
+
+ ?match(#message{type = groupchat},
+ send_recv(Config, #message{type = groupchat, to = Room, body = xmpp:mk_text(<<"1">>)})),
+ ?match(#message{type = groupchat},
+ send_recv(Config, #message{type = groupchat, to = Room, body = xmpp:mk_text(<<"2">>),
+ sub_els = [#hint{type = 'no-store'}]})),
+ ?match(#message{type = groupchat},
+ send_recv(Config, #message{type = groupchat, to = Room, body = xmpp:mk_text(<<"3">>)})),
+
+ ct:comment("Cleaning up"),
+ suite:put_event(Config, ready),
+ ready = get_event(Config),
+ muc_tests:leave(Config),
+ mam_tests:clean(clean(disconnect(Config))).
+
+mucsub_mam_slave(Config) ->
+ Server = ?config(server, Config),
+ gen_mod:update_module_opts(Server, mod_offline, [{use_mam_for_storage, true}]),
+ gen_mod:update_module_opts(Server, mod_mam, [{user_mucsub_from_muc_archive, true}]),
+
+ Room = suite:muc_room_jid(Config),
+ MyJID = my_jid(Config),
+ MyJIDBare = jid:remove_resource(MyJID),
+ ok = mam_tests:set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ send(Config, #presence{type = unavailable}),
+
+ wait_for_master(Config),
+ ready = get_event(Config),
+ ct:sleep(100),
+
+ ct:comment("Receiving offline messages"),
+
+ ?match(#presence{}, suite:send_recv(Config, #presence{})),
+
+ lists:foreach(
+ fun(N) ->
+ Body = xmpp:mk_text(integer_to_binary(N)),
+ Msg = ?match(#message{from = Room, type = normal} = Msg, recv_message(Config), Msg),
+ PS = ?match(#ps_event{items = #ps_items{node = ?NS_MUCSUB_NODES_MESSAGES, items = [
+ #ps_item{} = PS
+ ]}}, xmpp:get_subtag(Msg, #ps_event{}), PS),
+ ?match(#message{type = groupchat, body = Body}, xmpp:get_subtag(PS, #message{}))
+ end, [1, 3]),
+
+ % Unsubscribe yourself
+ ?send_recv(#iq{to = Room, type = set, sub_els = [
+ #muc_unsubscribe{}
+ ]}, #iq{type = result}),
+ suite:put_event(Config, ready),
+ mam_tests:clean(clean(disconnect(Config))),
+ gen_mod:update_module_opts(Server, mod_offline, [{use_mam_for_storage, false}]),
+ gen_mod:update_module_opts(Server, mod_mam, [{user_mucsub_from_muc_archive, false}]).
+
send_all_master(Config) ->
wait_for_slave(Config),
Peer = ?config(peer, Config),