From dfe4884d16e640e7065c2ada293aaa5b6a2b9e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 20 Feb 2023 13:03:46 +0100 Subject: [PATCH] Allow passing affiliations and subscribers to create_room_with_opts command --- src/mod_muc_admin.erl | 63 ++++++++++++++++++++++++++++++++++++++++++- src/mod_muc_room.erl | 20 +++++++------- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index c13dd92ca..dde9fd6c5 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -162,9 +162,14 @@ get_commands_spec() -> result = {res, rescode}}, #ejabberd_commands{name = create_room_with_opts, tags = [muc_room], desc = "Create a MUC room name@service in host with given options", + longdesc = "To set affilitions string value must have format 'Type:JID,Type:JID' " + "for example 'owner:bob@example.com,member:peter@example.com'. Subscribers can be " + "define with string 'JID:Nick:Node1:Node2,JID:Nick:Node3' for example " + "'bob@example.com:Bob:messages:subject,anne@example.com:Anne:messages'.", module = ?MODULE, function = create_room_with_opts, args_desc = ["Room name", "MUC service", "Server host", "List of options"], - args_example = ["room1", "muc.example.com", "localhost", [{"members_only","true"}]], + args_example = ["room1", "muc.example.com", "localhost", + [{"members_only","true"}, {"subscribers", "bob@example.com:Bob:messages"}]], args = [{name, binary}, {service, binary}, {host, binary}, {options, {list, @@ -1166,10 +1171,66 @@ format_room_option(OptionString, ValueString) -> ValueString; lang -> ValueString; pubsub -> ValueString; + affiliations -> + [parse_affiliation_string(Opt) || Opt <- str:tokens(ValueString, <<",">>)]; + subscribers -> + [parse_subscription_string(Opt) || Opt <- str:tokens(ValueString, <<",">>)]; _ -> misc:binary_to_atom(ValueString) end, {Option, Value}. +parse_affiliation_string(String) -> + {Type, JidS} = case String of + <<"owner:", Jid/binary>> -> {owner, Jid}; + <<"admin:", Jid/binary>> -> {admin, Jid}; + <<"member:", Jid/binary>> -> {member, Jid}; + <<"outcast:", Jid/binary>> -> {outcast, Jid}; + _ -> throw({error, "Invalid 'affiliation'"}) + end, + try jid:decode(JidS) of + #jid{luser = U, lserver = S, lresource = R} -> + {{U, S, R}, {Type, <<>>}} + catch _:{bad_jid, _} -> + throw({error, "Malformed JID in affiliation"}) + end. + +parse_subscription_string(String) -> + case str:tokens(String, <<":">>) of + [_] -> + throw({error, "Invalid 'subscribers' - missing nick"}); + [_, _] -> + throw({error, "Invalid 'subscribers' - missing nodes"}); + [JidS, Nick | Nodes] -> + Nodes2 = parse_nodes(Nodes, []), + try jid:decode(JidS) of + Jid -> + {Jid, Nick, Nodes2} + catch _:{bad_jid, _} -> + throw({error, "Malformed JID in 'subscribers'"}) + end + end. + +parse_nodes([], Acc) -> + Acc; +parse_nodes([<<"presence">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_PRESENCE | Acc]); +parse_nodes([<<"messages">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_MESSAGES | Acc]); +parse_nodes([<<"participants">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_PARTICIPANTS | Acc]); +parse_nodes([<<"affiliations">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_AFFILIATIONS | Acc]); +parse_nodes([<<"subject">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_SUBJECT | Acc]); +parse_nodes([<<"config">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_CONFIG | Acc]); +parse_nodes([<<"system">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_SYSTEM | Acc]); +parse_nodes([<<"subscribers">> | Rest], Acc) -> + parse_nodes(Rest, [?NS_MUCSUB_NODES_SUBSCRIBERS | Acc]); +parse_nodes(_, _) -> + throw({error, "Invalid 'subscribers' - unknown node name used"}). + %% @doc Get the Pid of an existing MUC room, or 'room_not_found'. -spec get_room_pid(binary(), binary()) -> pid() | room_not_found | invalid_service. get_room_pid(Name, Service) -> diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 2b9a30e13..237246ef4 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -294,15 +294,15 @@ init([Host, ServerHost, Access, Room, HistorySize, process_flag(trap_exit, true), Shaper = ejabberd_shaper:new(RoomShaper), RoomQueue = room_queue_new(ServerHost, Shaper, QueueType), - State = set_affiliation(Creator, owner, - #state{host = Host, server_host = ServerHost, - access = Access, room = Room, - history = lqueue_new(HistorySize, QueueType), - jid = jid:make(Room, Host), - just_created = true, - room_queue = RoomQueue, - room_shaper = Shaper}), - State1 = set_opts(DefRoomOpts, State), + State = set_opts(DefRoomOpts, + #state{host = Host, server_host = ServerHost, + access = Access, room = Room, + history = lqueue_new(HistorySize, QueueType), + jid = jid:make(Room, Host), + just_created = true, + room_queue = RoomQueue, + room_shaper = Shaper}), + State1 = set_affiliation(Creator, owner, State), store_room(State1), ?INFO_MSG("Created MUC room ~ts@~ts by ~ts", [Room, Host, jid:encode(Creator)]), @@ -4038,7 +4038,7 @@ set_opts([{Opt, Val} | Opts], StateData) -> end, muc_subscribers_new(), Val), StateData#state{muc_subscribers = MUCSubscribers}; affiliations -> - StateData#state{affiliations = maps:from_list(Val)}; + set_affiliations(maps:from_list(Val), StateData); roles -> StateData#state{roles = maps:from_list(Val)}; subject ->