diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index 56eddeaa4..48d72b111 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -122,6 +122,7 @@ robots = #{} :: robots(), nicks = #{} :: nicks(), affiliations = #{} :: affiliations(), + roles = #{} :: roles(), history = #lqueue{} :: lqueue(), subject = [] :: [text()], subject_author = <<"">> :: binary(), @@ -137,3 +138,4 @@ -type robots() :: #{jid() => {binary(), stanza()}}. -type nicks() :: #{binary() => [ljid()]}. -type affiliations() :: #{ljid() => affiliation() | {affiliation(), binary()}}. +-type roles() :: #{ljid() => role() | {role(), binary()}}. diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 8ad16a10f..c1c1c7f2a 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -1177,7 +1177,7 @@ opts_to_binary(Opts) -> {subject, iolist_to_binary(Subj)}; ({subject_author, Author}) -> {subject_author, iolist_to_binary(Author)}; - ({affiliations, Affs}) -> + ({AffOrRole, Affs}) when (AffOrRole == affiliation) or (AffOrRole == role) -> {affiliations, lists:map( fun({{U, S, R}, Aff}) -> NewAff = diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 0df7b420d..044725bd4 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1732,7 +1732,8 @@ set_role(JID, Role, StateData) -> end, StateData#state.users, LJIDs), StateData#state.nicks} end, - StateData#state{users = Users, nicks = Nicks}. + Roles = maps:put(jid:remove_resource(LJID), Role, StateData#state.roles), + StateData#state{users = Users, nicks = Nicks, roles = Roles}. -spec get_role(jid(), state()) -> role(). get_role(JID, StateData) -> @@ -2144,7 +2145,7 @@ add_new_user(From, Nick, Packet, StateData) -> Collision, mod_muc:can_use_nick(StateData#state.server_host, StateData#state.host, From, Nick), - get_default_role(Affiliation, StateData)} + get_occupant_initial_role(From, Affiliation, StateData)} of {false, _, _, _} when NUsers >= MaxUsers orelse NUsers >= MaxAdminUsers -> Txt = ?T("Too many users in this conference"), @@ -4010,6 +4011,8 @@ set_opts([{Opt, Val} | Opts], StateData) -> StateData#state{muc_subscribers = MUCSubscribers}; affiliations -> StateData#state{affiliations = maps:from_list(Val)}; + roles -> + StateData#state{roles = maps:from_list(Val)}; subject -> Subj = if Val == <<"">> -> []; is_binary(Val) -> [#text{data = Val}]; @@ -4022,7 +4025,9 @@ set_opts([{Opt, Val} | Opts], StateData) -> lists:map(fun({U, H}) -> {U, maps:from_list(H)} end, Val)), StateData#state{hats_users = Hats}; - _ -> StateData + Other -> + ?INFO_MSG("Unknown MUC room option, will be discarded: ~p", [Other]), + StateData end, set_opts(Opts, NSD). @@ -4041,6 +4046,18 @@ set_vcard_xupdate(#state{config = set_vcard_xupdate(State) -> State. +get_occupant_initial_role(Jid, Affiliation, #state{roles = Roles} = StateData) -> + DefaultRole = get_default_role(Affiliation, StateData), + case (StateData#state.config)#config.moderated of + true -> + get_occupant_stored_role(Jid, Roles, DefaultRole); + false -> + DefaultRole + end. + +get_occupant_stored_role(Jid, Roles, DefaultRole) -> + maps:get(jid:split(jid:remove_resource(Jid)), Roles, DefaultRole). + -define(MAKE_CONFIG_OPT(Opt), {get_config_opt_name(Opt), element(Opt, Config)}). @@ -4084,6 +4101,7 @@ make_opts(StateData, Hibernation) -> (?SETS):to_list((StateData#state.config)#config.captcha_whitelist)}, {affiliations, maps:to_list(StateData#state.affiliations)}, + {roles, maps:to_list(StateData#state.roles)}, {subject, StateData#state.subject}, {subject_author, StateData#state.subject_author}, {hats_users,