From 9d87a4a6d4cb8f679fcfc0c32addab594ce5fd8a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 20 May 2016 01:28:16 +0200 Subject: [PATCH] mod_muc_room: Notify on affiliation changes Notify the current room occupants if the affiliation of a non-occupant is changed as per example 195 of XEP-0045. In anonymous rooms, only moderators are notified, though. --- src/mod_muc_room.erl | 53 +++++++++++++++++++++++++++++++++++++++++ test/ejabberd_SUITE.erl | 5 ++++ 2 files changed, 58 insertions(+) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index c9c785757..211b1eaa8 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -266,6 +266,8 @@ normal_state({route, From, <<"">>, none -> NSD = set_affiliation(IJID, member, StateData), + send_affiliation(IJID, member, + StateData), case (NSD#state.config)#config.persistent of @@ -2440,6 +2442,51 @@ send_nick_changing(JID, OldNick, StateData, end, (?DICT):to_list(StateData#state.users)). +maybe_send_affiliation(JID, Affiliation, StateData) -> + LJID = jid:tolower(JID), + IsOccupant = case LJID of + {LUser, LServer, <<"">>} -> + not (?DICT):is_empty( + (?DICT):filter(fun({U, S, _}, _) -> + U == LUser andalso + S == LServer + end, StateData#state.users)); + {_LUser, _LServer, _LResource} -> + (?DICT):is_key(LJID, StateData#state.users) + end, + case IsOccupant of + true -> + ok; % The new affiliation is published via presence. + false -> + send_affiliation(LJID, Affiliation, StateData) + end. + +send_affiliation(LJID, Affiliation, StateData) -> + ItemAttrs = [{<<"jid">>, jid:to_string(LJID)}, + {<<"affiliation">>, affiliation_to_list(Affiliation)}, + {<<"role">>, <<"none">>}], + Message = #xmlel{name = <<"message">>, + attrs = [{<<"id">>, randoms:get_string()}], + children = + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_MUC_USER}], + children = + [#xmlel{name = <<"item">>, + attrs = ItemAttrs}]}]}, + Recipients = case (StateData#state.config)#config.anonymous of + true -> + (?DICT):filter(fun(_, #user{role = moderator}) -> + true; + (_, _) -> + false + end, StateData#state.users); + false -> + StateData#state.users + end, + send_multiple(StateData#state.jid, + StateData#state.server_host, + Recipients, Message). + status_els(IsInitialPresence, JID, #user{jid = JID}, StateData) -> Status = case IsInitialPresence of true -> @@ -2722,11 +2769,13 @@ process_item_change(E, SD, UJID) -> <<"321">>, none, SD), + maybe_send_affiliation(JID, none, SD), SD1 = set_affiliation(JID, none, SD), set_role(JID, none, SD1); _ -> SD1 = set_affiliation(JID, none, SD), send_update_presence(JID, SD1, SD), + maybe_send_affiliation(JID, none, SD1), SD1 end; {JID, affiliation, outcast, Reason} -> @@ -2736,6 +2785,7 @@ process_item_change(E, SD, UJID) -> <<"301">>, outcast, SD), + maybe_send_affiliation(JID, outcast, SD), set_affiliation(JID, outcast, set_role(JID, none, SD), @@ -2745,11 +2795,13 @@ process_item_change(E, SD, UJID) -> SD1 = set_affiliation(JID, A, SD, Reason), SD2 = set_role(JID, moderator, SD1), send_update_presence(JID, Reason, SD2, SD), + maybe_send_affiliation(JID, A, SD2), SD2; {JID, affiliation, member, Reason} -> SD1 = set_affiliation(JID, member, SD, Reason), SD2 = set_role(JID, participant, SD1), send_update_presence(JID, Reason, SD2, SD), + maybe_send_affiliation(JID, member, SD2), SD2; {JID, role, Role, Reason} -> SD1 = set_role(JID, Role, SD), @@ -2759,6 +2811,7 @@ process_item_change(E, SD, UJID) -> {JID, affiliation, A, _Reason} -> SD1 = set_affiliation(JID, A, SD), send_update_presence(JID, SD1, SD), + maybe_send_affiliation(JID, A, SD1), SD1 end of diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index aa465fb66..ea99a3b76 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1435,6 +1435,11 @@ muc_master(Config) -> items = [#muc_item{affiliation = member, jid = PeerJID, role = participant}]}]}), + ?recv1(#message{from = Room, + sub_els = [#muc_user{ + items = [#muc_item{affiliation = member, + jid = Localhost, + role = none}]}]}), %% BUG: We should not receive any sub_els! ?recv1(#iq{type = result, id = I1, sub_els = [_|_]}), %% Receive groupchat message from the peer