diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index 559076ae2..f65c346c6 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -38,7 +38,7 @@ description = <<"">> :: binary(), allow_change_subj = true :: boolean(), allow_query_users = true :: boolean(), - allow_private_messages = true :: boolean(), + allowpm = anyone :: anyone | participants | moderators | none, allow_private_messages_from_visitors = anyone :: anyone | moderators | nobody , allow_visitor_status = true :: boolean(), allow_visitor_nickchange = true :: boolean(), diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 3af28e156..f7531df53 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -1193,6 +1193,13 @@ opts_to_binary(Opts) -> {subject, iolist_to_binary(Subj)}; ({subject_author, Author}) -> {subject_author, iolist_to_binary(Author)}; + ({allow_private_messages, Value}) -> % ejabberd 23.04 or older + Value2 = case Value of + true -> anyone; + false -> none; + _ -> Value + end, + {allowpm, Value2}; ({AffOrRole, Affs}) when (AffOrRole == affiliation) or (AffOrRole == role) -> {affiliations, lists:map( fun({{U, S, R}, Aff}) -> @@ -1289,7 +1296,8 @@ mod_opt_type(cleanup_affiliations_on_start) -> mod_opt_type(default_room_options) -> econf:options( #{allow_change_subj => econf:bool(), - allow_private_messages => econf:bool(), + allowpm => + econf:enum([anyone, participants, moderators, none]), allow_private_messages_from_visitors => econf:enum([anyone, moderators, nobody]), allow_query_users => econf:bool(), @@ -1373,7 +1381,7 @@ mod_options(Host) -> {cleanup_affiliations_on_start, false}, {default_room_options, [{allow_change_subj,true}, - {allow_private_messages,true}, + {allowpm,anyone}, {allow_query_users,true}, {allow_user_invites,false}, {allow_visitor_nickchange,true}, @@ -1667,11 +1675,11 @@ mod_doc() -> desc => ?T("Allow occupants to change the subject. " "The default value is 'true'.")}}, - {allow_private_messages, - #{value => "true | false", + {allowpm, + #{value => "anyone | participants | moderators | none", desc => - ?T("Occupants can send private messages to other occupants. " - "The default value is 'true'.")}}, + ?T("Who can send private messages. " + "The default value is 'anyone'.")}}, {allow_query_users, #{value => "true | false", desc => diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 234f065d3..5264eaa4b 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -1276,7 +1276,7 @@ room_diagnostics(Name, Service) -> change_option(Option, Value, Config) -> case Option of allow_change_subj -> Config#config{allow_change_subj = Value}; - allow_private_messages -> Config#config{allow_private_messages = Value}; + allowpm -> Config#config{allowpm = Value}; allow_private_messages_from_visitors -> Config#config{allow_private_messages_from_visitors = Value}; allow_query_users -> Config#config{allow_query_users = Value}; allow_subscription -> Config#config{allow_subscription = Value}; diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 057e4edcd..d5a8d461f 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -811,8 +811,8 @@ get_roomconfig_text(members_by_default, Lang) -> tr(Lang, ?T("Default users as participants")); get_roomconfig_text(allow_change_subj, Lang) -> tr(Lang, ?T("Allow users to change the subject")); -get_roomconfig_text(allow_private_messages, Lang) -> - tr(Lang, ?T("Allow users to send private messages")); +get_roomconfig_text(allowpm, Lang) -> + tr(Lang, ?T("Who can send private messages")); get_roomconfig_text(allow_private_messages_from_visitors, Lang) -> tr(Lang, ?T("Allow visitors to send private messages to")); get_roomconfig_text(allow_query_users, Lang) -> diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl index 4a5192d2f..4b422f998 100644 --- a/src/mod_muc_mnesia.erl +++ b/src/mod_muc_mnesia.erl @@ -401,6 +401,15 @@ need_transform({muc_room, {N, H}, _}) when is_list(N) orelse is_list(H) -> ?INFO_MSG("Mnesia table 'muc_room' will be converted to binary", []), true; +need_transform({muc_room, {_N, _H}, Opts}) -> + case lists:keymember(allow_private_messages, 1, Opts) of + true -> + ?INFO_MSG("Mnesia table 'muc_room' will be converted to allowpm", []), + true; + false -> + false + end; + need_transform({muc_registered, {{U, S}, H}, Nick}) when is_list(U) orelse is_list(S) orelse is_list(H) orelse is_list(Nick) -> ?INFO_MSG("Mnesia table 'muc_registered' will be converted to binary", []), @@ -408,9 +417,22 @@ need_transform({muc_registered, {{U, S}, H}, Nick}) need_transform(_) -> false. -transform(#muc_room{name_host = {N, H}, opts = Opts} = R) -> +transform({muc_room, {N, H}, Opts} = R) + when is_list(N) orelse is_list(H) -> R#muc_room{name_host = {iolist_to_binary(N), iolist_to_binary(H)}, opts = mod_muc:opts_to_binary(Opts)}; +transform(#muc_room{opts = Opts} = R) -> + Opts2 = case lists:keyfind(allow_private_messages, 1, Opts) of + {_, Value} when is_boolean(Value) -> + Value2 = case Value of + true -> anyone; + false -> none + end, + lists:keyreplace(allow_private_messages, 1, Opts, {allowpm, Value2}); + _ -> + Opts + end, + R#muc_room{opts = Opts2}; transform(#muc_registered{us_host = {{U, S}, H}, nick = Nick} = R) -> R#muc_registered{us_host = {{iolist_to_binary(U), iolist_to_binary(S)}, iolist_to_binary(H)}, diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 9c9b328d7..926b478e1 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -593,7 +593,7 @@ normal_state({route, ToNick, forget_message -> {next_state, normal_state, StateData}; continue_delivery -> - case {(StateData#state.config)#config.allow_private_messages, + case {is_user_allowed_private_message(From, StateData), is_user_online(From, StateData) orelse is_subscriber(From, StateData) orelse is_user_allowed_message_nonparticipant(From, StateData)} of @@ -630,7 +630,7 @@ normal_state({route, ToNick, ejabberd_router:route(xmpp:set_to(PrivMsg, ToJID)) end, ToJIDs); true -> - ErrText = ?T("It is not allowed to send private messages"), + ErrText = ?T("You are not allowed to send private messages"), Err = xmpp:err_forbidden(ErrText, Lang), ejabberd_router:route_error(Packet, Err) end @@ -641,7 +641,7 @@ normal_state({route, ToNick, Err = xmpp:err_not_acceptable(ErrText, Lang), ejabberd_router:route_error(Packet, Err); {false, _} -> - ErrText = ?T("It is not allowed to send private messages"), + ErrText = ?T("You are not allowed to send private messages"), Err = xmpp:err_forbidden(ErrText, Lang), ejabberd_router:route_error(Packet, Err) end, @@ -1329,6 +1329,24 @@ is_user_allowed_message_nonparticipant(JID, _ -> false end. +-spec is_user_allowed_private_message(jid(), state()) -> boolean(). +is_user_allowed_private_message(JID, StateData) -> + case {(StateData#state.config)#config.allowpm, + get_role(JID, StateData)} of + {anyone, _} -> + true; + {participants, moderator} -> + true; + {participants, participant} -> + true; + {moderators, moderator} -> + true; + {none, _} -> + false; + {_, _} -> + false + end. + %% @doc Get information of this participant, or default values. %% If the JID is not a participant, return values for a service message. -spec get_participant_data(jid(), state()) -> {binary(), role()}. @@ -3788,7 +3806,7 @@ get_config(Lang, StateData, From) -> {moderatedroom, Config#config.moderated}, {members_by_default, Config#config.members_by_default}, {changesubject, Config#config.allow_change_subj}, - {allow_private_messages, Config#config.allow_private_messages}, + {allowpm, Config#config.allowpm}, {allow_private_messages_from_visitors, Config#config.allow_private_messages_from_visitors}, {allow_query_users, Config#config.allow_query_users}, @@ -3859,8 +3877,8 @@ set_config(Opts, Config, ServerHost, Lang) -> ({roomdesc, Desc}, C) -> C#config{description = Desc}; ({changesubject, V}, C) -> C#config{allow_change_subj = V}; ({allow_query_users, V}, C) -> C#config{allow_query_users = V}; - ({allow_private_messages, V}, C) -> - C#config{allow_private_messages = V}; + ({allowpm, V}, C) -> + C#config{allowpm = V}; ({allow_private_messages_from_visitors, V}, C) -> C#config{allow_private_messages_from_visitors = V}; ({allow_visitor_status, V}, C) -> C#config{allow_visitor_status = V}; @@ -4026,9 +4044,9 @@ set_opts2([{Opt, Val} | Opts], StateData) -> StateData#state{config = (StateData#state.config)#config{allow_query_users = Val}}; - allow_private_messages -> + allowpm -> StateData#state{config = - (StateData#state.config)#config{allow_private_messages + (StateData#state.config)#config{allowpm = Val}}; allow_private_messages_from_visitors -> StateData#state{config = @@ -4221,7 +4239,7 @@ make_opts(StateData, Hibernation) -> [?MAKE_CONFIG_OPT(#config.title), ?MAKE_CONFIG_OPT(#config.description), ?MAKE_CONFIG_OPT(#config.allow_change_subj), ?MAKE_CONFIG_OPT(#config.allow_query_users), - ?MAKE_CONFIG_OPT(#config.allow_private_messages), + ?MAKE_CONFIG_OPT(#config.allowpm), ?MAKE_CONFIG_OPT(#config.allow_private_messages_from_visitors), ?MAKE_CONFIG_OPT(#config.allow_visitor_status), ?MAKE_CONFIG_OPT(#config.allow_visitor_nickchange), @@ -4481,20 +4499,12 @@ process_iq_disco_info(From, #iq{type = get, lang = Lang, -spec iq_disco_info_extras(binary(), state(), boolean()) -> xdata(). iq_disco_info_extras(Lang, StateData, Static) -> Config = StateData#state.config, - AllowPM = case Config#config.allow_private_messages of - false -> none; - true -> - case Config#config.allow_private_messages_from_visitors of - nobody -> participants; - _ -> anyone - end - end, Fs1 = [{roomname, Config#config.title}, {description, Config#config.description}, {changesubject, Config#config.allow_change_subj}, {allowinvites, Config#config.allow_user_invites}, {allow_query_users, Config#config.allow_query_users}, - {allowpm, AllowPM}, + {allowpm, Config#config.allowpm}, {lang, Config#config.lang}], Fs2 = case Config#config.pubsub of Node when is_binary(Node), Node /= <<"">> -> diff --git a/test/muc_tests.erl b/test/muc_tests.erl index 0cfbc9967..21a8488a6 100644 --- a/test/muc_tests.erl +++ b/test/muc_tests.erl @@ -1242,7 +1242,7 @@ config_private_messages_master(Config) -> [104] = set_config(Config, [{allow_private_messages_from_visitors, nobody}]), wait_for_slave(Config), [104] = set_config(Config, [{allow_private_messages_from_visitors, anyone}, - {allow_private_messages, false}]), + {allowpm, none}]), ct:comment("Fail trying to send a private message"), send(Config, #message{to = PeerNickJID, type = chat}), #message{from = PeerNickJID, type = error} = ErrMsg = recv_message(Config),