From 790cb104cdbe9f90e0b48ac8fe7c8020cdb9f743 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 3 Dec 2024 01:45:05 +0100 Subject: [PATCH] Change arguments and result to consistent names (API v3) Commands accept as argument: user, host, room, service and return as result JIDs Commands that change in API v3: get_room_affiliations muc_register_nick muc_unregister_nick set_room_affiliation status_list status_list_host subscribe_room subscribe_room_many unsubscribe_room --- src/ejabberd_sm.erl | 4 +- src/mod_admin_extra.erl | 46 ++++++++++- src/mod_muc_admin.erl | 174 +++++++++++++++++++++++++++++++++++++--- test/muc_tests.erl | 4 +- 4 files changed, 213 insertions(+), 15 deletions(-) diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 4db90e5ee..4745c57d9 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -1034,8 +1034,8 @@ get_commands_spec() -> desc = "List all established sessions", policy = admin, module = ?MODULE, function = connected_users, args = [], - result_desc = "List of users sessions", - result_example = [<<"user1@example.com">>, <<"user2@example.com">>], + result_desc = "List of users sessions full JID", + result_example = [<<"user1@example.com/Home">>, <<"user2@example.com/54134">>], result = {connected_users, {list, {sessions, string}}}}, #ejabberd_commands{name = connected_users_number, tags = [session, statistics], desc = "Get the number of established sessions", diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 4e203eb83..85ab9a367 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -43,7 +43,8 @@ % Sessions num_resources/2, resource_num/3, kick_session/4, status_num/2, status_num/1, - status_list/2, status_list/1, connected_users_info/0, + status_list/2, status_list_v3/2, + status_list/1, status_list_v3/1, connected_users_info/0, connected_users_vhost/1, set_presence/7, get_presence/2, user_sessions_info/2, get_last/2, set_last/4, @@ -380,6 +381,21 @@ get_commands_spec() -> {status, string} ]}} }}}, + #ejabberd_commands{name = status_list_host, tags = [session], + desc = "List of users logged in host with their statuses", + module = ?MODULE, function = status_list_v3, + version = 3, + note = "updated in 24.12", + args = [{host, binary}, {status, binary}], + args_example = [<<"myserver.com">>, <<"dnd">>], + args_desc = ["Server name", "Status type to check"], + result_example = [{<<"peter@myserver.com/tka">>,6,<<"Busy">>}], + result = {users, {list, + {userstatus, {tuple, [{jid, string}, + {priority, integer}, + {status, string} + ]}} + }}}, #ejabberd_commands{name = status_list, tags = [session], desc = "List of logged users with this status", module = ?MODULE, function = status_list, @@ -396,6 +412,21 @@ get_commands_spec() -> {status, string} ]}} }}}, + #ejabberd_commands{name = status_list, tags = [session], + desc = "List of logged users with this status", + module = ?MODULE, function = status_list_v3, + version = 3, + note = "updated in 24.12", + args = [{status, binary}], + args_example = [<<"dnd">>], + args_desc = ["Status type to check"], + result_example = [{<<"peter@myserver.com/tka">>,6,<<"Busy">>}], + result = {users, {list, + {userstatus, {tuple, [{jid, string}, + {priority, integer}, + {status, string} + ]}} + }}}, #ejabberd_commands{name = connected_users_info, tags = [session], desc = "List all established sessions and their information", @@ -426,8 +457,9 @@ get_commands_spec() -> module = ?MODULE, function = connected_users_vhost, args_example = [<<"myexample.com">>], args_desc = ["Server name"], - result_example = [<<"user1@myserver.com/tka">>, <<"user2@localhost/tka">>], args = [{host, binary}], + result_example = [<<"user1@myserver.com/tka">>, <<"user2@localhost/tka">>], + result_desc = "List of sessions full JIDs", result = {connected_users_vhost, {list, {sessions, string}}}}, #ejabberd_commands{name = user_sessions_info, tags = [session], @@ -683,6 +715,7 @@ get_commands_spec() -> module = ?MODULE, function = get_roster, args = [], args_rename = [{server, host}], + result_example = [{<<"user2@localhost">>, <<"User 2">>, <<"none">>, <<"subscribe">>, [<<"Group1">>]}], result = {contacts, {list, {contact, {tuple, [ {jid, string}, {nick, string}, @@ -696,6 +729,7 @@ get_commands_spec() -> policy = user, module = ?MODULE, function = get_roster_count, args = [], + args_example = [<<"sun">>, <<"localhost">>], args_rename = [{server, host}], result_example = 5, result_desc = "Number", @@ -1333,6 +1367,14 @@ status_list(Host, Status) -> status_list(Status) -> status_list(<<"all">>, Status). +status_list_v3(ArgHost, Status) -> + List = status_list(ArgHost, Status), + [{jid:encode(jid:make(User, Host, Resource)), Priority, StatusText} + || {User, Host, Resource, Priority, StatusText} <- List]. + +status_list_v3(Status) -> + status_list_v3(<<"all">>, Status). + get_status_list(Host, Status_required) -> %% Get list of all logged users diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index dfc4fb182..40795afee 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -30,7 +30,8 @@ -export([start/2, stop/1, reload/3, depends/2, mod_doc/0, muc_online_rooms/1, muc_online_rooms_by_regex/2, - muc_register_nick/3, muc_unregister_nick/2, + muc_register_nick/3, muc_register_nick/4, + muc_unregister_nick/2, muc_unregister_nick/3, create_room_with_opts/4, create_room/3, destroy_room/2, create_rooms_file/1, destroy_rooms_file/1, rooms_unused_list/2, rooms_unused_destroy/2, @@ -38,9 +39,11 @@ get_user_rooms/2, get_user_subscriptions/2, get_room_occupants/2, get_room_occupants_number/2, send_direct_invitation/5, change_room_option/4, get_room_options/2, - set_room_affiliation/4, get_room_affiliations/2, get_room_affiliation/3, - subscribe_room/4, subscribe_room_many/3, - unsubscribe_room/2, get_subscribers/2, + set_room_affiliation/4, set_room_affiliation/5, get_room_affiliations/2, + get_room_affiliations_v3/2, get_room_affiliation/3, + subscribe_room/4, subscribe_room/6, + subscribe_room_many/3, subscribe_room_many_v3/4, + unsubscribe_room/2, unsubscribe_room/4, get_subscribers/2, get_room_serverhost/1, web_menu_main/2, web_page_main/2, web_menu_host/3, web_page_host/3, @@ -102,7 +105,7 @@ get_commands_spec() -> module = ?MODULE, function = muc_online_rooms, args_desc = ["MUC service, or `global` for all"], args_example = ["conference.example.com"], - result_desc = "List of rooms", + result_desc = "List of rooms JIDs", result_example = ["room1@conference.example.com", "room2@conference.example.com"], args = [{service, binary}], args_rename = [{host, service}], @@ -133,6 +136,16 @@ get_commands_spec() -> args = [{nick, binary}, {jid, binary}, {service, binary}], args_rename = [{host, service}], result = {res, rescode}}, + #ejabberd_commands{name = muc_register_nick, tags = [muc], + desc = "Register a nick to a User JID in a MUC service", + module = ?MODULE, function = muc_register_nick, + version = 3, + note = "updated in 24.12", + args_desc = ["nick", "user name", "user host", "MUC service"], + args_example = [<<"Tim">>, <<"tim">>, <<"example.org">>, <<"conference.example.org">>], + args = [{nick, binary}, {user, binary}, {host, binary}, {service, binary}], + args_rename = [{host, service}], + result = {res, rescode}}, #ejabberd_commands{name = muc_unregister_nick, tags = [muc], desc = "Unregister the nick registered by that account in the MUC service", module = ?MODULE, function = muc_unregister_nick, @@ -141,6 +154,16 @@ get_commands_spec() -> args = [{jid, binary}, {service, binary}], args_rename = [{host, service}], result = {res, rescode}}, + #ejabberd_commands{name = muc_unregister_nick, tags = [muc], + desc = "Unregister the nick registered by that account in the MUC service", + module = ?MODULE, function = muc_unregister_nick, + version = 3, + note = "updated in 24.12", + args_desc = ["user name", "user host", "MUC service"], + args_example = [<<"tim">>, <<"example.org">>, <<"conference.example.org">>], + args = [{user, binary}, {host, binary}, {service, binary}], + args_rename = [{host, service}], + result = {res, rescode}}, #ejabberd_commands{name = create_room, tags = [muc_room], desc = "Create a MUC room name@service in host", @@ -393,6 +416,21 @@ get_commands_spec() -> args = [{user, binary}, {nick, binary}, {room, binary}, {nodes, {list, {node, binary}}}], result = {nodes, {list, {node, string}}}}, + #ejabberd_commands{name = subscribe_room, tags = [muc_room, muc_sub], + desc = "Subscribe to a MUC conference", + module = ?MODULE, function = subscribe_room, + version = 3, + note = "updated in 24.12", + args_desc = ["user name", "user host", "user nick", + "room name", "MUC service", "list of nodes"], + args_example = ["tom", "localhost", "Tom", "room1", "conference.localhost", + ["urn:xmpp:mucsub:nodes:messages", "urn:xmpp:mucsub:nodes:affiliations"]], + result_desc = "The list of nodes that has subscribed", + result_example = ["urn:xmpp:mucsub:nodes:messages", + "urn:xmpp:mucsub:nodes:affiliations"], + args = [{user, binary}, {host, binary}, {nick, binary}, {room, binary}, + {service, binary}, {nodes, {list, {node, binary}}}], + result = {nodes, {list, {node, string}}}}, #ejabberd_commands{name = subscribe_room_many, tags = [muc_room, muc_sub], desc = "Subscribe several users to a MUC conference", note = "added in 22.05", @@ -440,6 +478,32 @@ get_commands_spec() -> {room, binary}, {nodes, {list, {node, binary}}}], result = {res, rescode}}, + #ejabberd_commands{name = subscribe_room_many, tags = [muc_room, muc_sub], + desc = "Subscribe several users to a MUC conference", + longdesc = "This command accepts up to 50 users at once " + "(this is configurable with the _`mod_muc_admin`_ option " + "`subscribe_room_many_max_users`)", + module = ?MODULE, function = subscribe_room_many_v3, + version = 3, + note = "updated in 24.12", + args_desc = ["List of tuples with users name, host and nick", + "room name", + "MUC service", + "nodes separated by commas: `,`"], + args_example = [[{"tom", "localhost", "Tom"}, + {"jerry", "localhost", "Jerry"}], + "room1", "conference.localhost", + ["urn:xmpp:mucsub:nodes:messages", "urn:xmpp:mucsub:nodes:affiliations"]], + args = [{users, {list, + {user, {tuple, + [{user, binary}, + {host, binary}, + {nick, binary} + ]}} + }}, + {name, binary}, {service, binary}, + {nodes, {list, {node, binary}}}], + result = {res, rescode}}, #ejabberd_commands{name = unsubscribe_room, tags = [muc_room, muc_sub], desc = "Unsubscribe from a MUC conference", module = ?MODULE, function = unsubscribe_room, @@ -447,6 +511,15 @@ get_commands_spec() -> args_example = ["tom@localhost", "room1@conference.localhost"], args = [{user, binary}, {room, binary}], result = {res, rescode}}, + #ejabberd_commands{name = unsubscribe_room, tags = [muc_room, muc_sub], + desc = "Unsubscribe from a MUC conference", + module = ?MODULE, function = unsubscribe_room, + version = 3, + note = "updated in 24.12", + args_desc = ["user name", "user host", "room name", "MUC service"], + args_example = ["tom", "localhost", "room1", "conference.localhost"], + args = [{user, binary}, {host, binary}, {room, binary}, {service, binary}], + result = {res, rescode}}, #ejabberd_commands{name = get_subscribers, tags = [muc_room, muc_sub], desc = "List subscribers of a MUC conference", module = ?MODULE, function = get_subscribers, @@ -454,7 +527,8 @@ get_commands_spec() -> args_example = ["room1", "conference.example.com"], result_desc = "The list of users that are subscribed to that room", result_example = ["user2@example.com", "user3@example.com"], - args = [{name, binary}, {service, binary}], + args = [{room, binary}, {service, binary}], + args_rename = [{name, room}], result = {subscribers, {list, {jid, string}}}}, #ejabberd_commands{name = set_room_affiliation, tags = [muc_room], desc = "Change an affiliation in a MUC room", @@ -464,6 +538,19 @@ get_commands_spec() -> args = [{name, binary}, {service, binary}, {jid, binary}, {affiliation, binary}], result = {res, rescode}}, + #ejabberd_commands{name = set_room_affiliation, tags = [muc_room], + desc = "Change an affiliation in a MUC room", + longdesc = "If affiliation is `none`, then the affiliation is removed.", + module = ?MODULE, function = set_room_affiliation, + version = 3, + note = "updated in 24.12", + args_desc = ["room name", "MUC service", "user name", "user host", "affiliation to set"], + args_example = ["room1", "conference.example.com", "sun", "localhost", "member"], + args = [{room, binary}, {service, binary}, + {user, binary}, {host, binary}, {affiliation, binary}], + result = {res, rescode}}, + + #ejabberd_commands{name = get_room_affiliations, tags = [muc_room], desc = "Get the list of affiliations of a MUC room", module = ?MODULE, function = get_room_affiliations, @@ -480,6 +567,25 @@ get_commands_spec() -> {reason, string} ]}} }}}, + #ejabberd_commands{name = get_room_affiliations, tags = [muc_room], + desc = "Get the list of affiliations of a MUC room", + module = ?MODULE, function = get_room_affiliations_v3, + version = 3, + note = "updated in 24.12", + args_desc = ["Room name", "MUC service"], + args_example = ["room1", "conference.example.com"], + result_desc = "The list of affiliations with jid, affiliation and reason", + result_example = [{"user1@example.com", member, "member"}], + args = [{name, binary}, {service, binary}], + result = {affiliations, {list, + {affiliation, {tuple, + [{jid, string}, + {affiliation, atom}, + {reason, string} + ]}} + }}}, + + #ejabberd_commands{name = get_room_affiliation, tags = [muc_room], desc = "Get affiliation of a user in MUC room", module = ?MODULE, function = get_room_affiliation, @@ -547,6 +653,9 @@ build_summary_room(Name, Host, Pid) -> Participants }. +muc_register_nick(Nick, User, Host, Service) -> + muc_register_nick(Nick, makeencode(User, Host), Service). + muc_register_nick(Nick, FromBinary, Service) -> try {get_room_serverhost(Service), jid:decode(FromBinary)} of {ServerHost, From} -> @@ -569,6 +678,9 @@ muc_register_nick(Nick, FromBinary, Service) -> throw({error, "Internal error"}) end. +muc_unregister_nick(User, Host, Service) -> + muc_unregister_nick(makeencode(User, Host), Service). + muc_unregister_nick(FromBinary, Service) -> muc_register_nick(<<"">>, FromBinary, Service). @@ -733,8 +845,11 @@ webadmin_muc_host(_Host, Get = [make_command(get_room_affiliations, R, [{<<"name">>, Name}, {<<"service">>, Service}], - [{table_options, {20, RPath}}])], + [{table_options, {20, RPath}}, + {result_links, [{jid, user, 3 + Level, <<"">>}]}])], Title ++ Breadcrumb ++ Get ++ Set; + + webadmin_muc_host(_Host, Service, [<<"rooms">>, <<"room">>, Name, <<"history">> | RPath], @@ -816,11 +931,11 @@ webadmin_muc_host(_Host, make_breadcrumb({room_section, Level, Service, <<"Subscribers">>, Name, R, RPath}), Set = [make_command(subscribe_room, R, - [{<<"room">>, jid:encode({Name, Service, <<"">>})}], + [{<<"name">>, Name}, {<<"service">>, Service}], []), make_command(unsubscribe_room, R, - [{<<"room">>, jid:encode({Name, Service, <<"">>})}], + [{<<"name">>, Name}, {<<"service">>, Service}], [{style, danger}])], Get = [make_command(get_subscribers, R, @@ -1784,7 +1899,7 @@ get_options(Config) -> %%---------------------------- %% @spec(Name::binary(), Service::binary()) -> -%% [{JID::string(), Domain::string(), Role::string(), Reason::string()}] +%% [{Username::string(), Domain::string(), Role::string(), Reason::string()}] %% @doc Get the affiliations of the room Name@Service. get_room_affiliations(Name, Service) -> case get_room_pid_validate(Name, Service, <<"name">>, <<"service">>) of @@ -1802,6 +1917,27 @@ get_room_affiliations(Name, Service) -> throw({error, "The room does not exist."}) end. +%% @spec(Name::binary(), Service::binary()) -> +%% [{JID::string(), Role::string(), Reason::string()}] +%% @doc Get the affiliations of the room Name@Service. +get_room_affiliations_v3(Name, Service) -> + case get_room_pid_validate(Name, Service, <<"name">>, <<"service">>) of + {Pid, _, _} when is_pid(Pid) -> + %% Get the PID of the online room, then request its state + {ok, StateData} = mod_muc_room:get_state(Pid), + Affiliations = maps:to_list(StateData#state.affiliations), + lists:map( + fun({{Uname, Domain, _Res}, {Aff, Reason}}) when is_atom(Aff)-> + Jid = makeencode(Uname, Domain), + {Jid, Aff, Reason}; + ({{Uname, Domain, _Res}, Aff}) when is_atom(Aff)-> + Jid = makeencode(Uname, Domain), + {Jid, Aff, <<>>} + end, Affiliations); + _ -> + throw({error, "The room does not exist."}) + end. + get_room_history(Name, Service) -> case get_room_pid_validate(Name, Service, <<"name">>, <<"service">>) of {Pid, _, _} when is_pid(Pid) -> @@ -1843,6 +1979,9 @@ get_room_affiliation(Name, Service, JID) -> %% Change Room Affiliation %%---------------------------- +set_room_affiliation(Name, Service, User, Host, AffiliationString) -> + set_room_affiliation(Name, Service, makeencode(User, Host), AffiliationString). + %% @spec(Name, Service, JID, AffiliationString) -> ok | {error, Error} %% Name = binary() %% Service = binary() @@ -1880,6 +2019,10 @@ set_room_affiliation(Name, Service, JID, AffiliationString) -> %%% MUC Subscription %%% +subscribe_room(Username, Host, Nick, Name, Service, Nodes) -> + subscribe_room(makeencode(Username, Host), Nick, + makeencode(Name, Service), Nodes). + subscribe_room(_User, Nick, _Room, _Nodes) when Nick == <<"">> -> throw({error, "Nickname must be set"}); subscribe_room(User, Nick, Room, Nodes) when is_binary(Nodes) -> @@ -1912,6 +2055,10 @@ subscribe_room(User, Nick, Room, NodeList) -> throw({error, "Malformed room JID"}) end. +subscribe_room_many_v3(List, Name, Service, Nodes) -> + List2 = [{makeencode(User, Host), Nick} || {User, Host, Nick} <- List], + subscribe_room_many(List2, makeencode(Name, Service), Nodes). + subscribe_room_many(Users, Room, Nodes) -> MaxUsers = mod_muc_admin_opt:subscribe_room_many_max_users(global), if @@ -1924,6 +2071,10 @@ subscribe_room_many(Users, Room, Nodes) -> end, Users) end. +unsubscribe_room(User, Host, Name, Service) -> + unsubscribe_room(makeencode(User, Host), + makeencode(Name, Service)). + unsubscribe_room(User, Room) -> try jid:decode(Room) of #jid{luser = Name, lserver = Host} when Name /= <<"">> -> @@ -1962,6 +2113,9 @@ get_subscribers(Name, Host) -> %% Utils %%---------------------------- +makeencode(User, Host) -> + jid:encode(jid:make(User, Host)). + -spec validate_host(Name :: binary(), ArgName::binary()) -> binary(). validate_host(Name, ArgName) -> case jid:nameprep(Name) of diff --git a/test/muc_tests.erl b/test/muc_tests.erl index f7e080aee..a63567481 100644 --- a/test/muc_tests.erl +++ b/test/muc_tests.erl @@ -259,7 +259,9 @@ set_room_affiliation(Config) -> RequestURL = "http://" ++ ServerHost ++ ":" ++ integer_to_list(WebPort) ++ "/api/set_room_affiliation", Headers = [{"X-Admin", "true"}], ContentType = "application/json", - Body = misc:json_encode(#{name => RoomName, service => RoomService, jid => jid:encode(PeerJID), affiliation => member}), + Body = misc:json_encode(#{room => RoomName, service => RoomService, + user => PeerJID#jid.luser, host => PeerJID#jid.lserver, + affiliation => member}), {ok, {{_, 200, _}, _, _}} = httpc:request(post, {RequestURL, Headers, ContentType, Body}, [], []), #message{id = _, from = RoomJID, to = MyJID, sub_els = [