Skip to content

Commit 19fb5c6

Browse files
Arkadiusz Gilarkgil
authored andcommitted
Allow JIDs from all MUC light domains in HTTP room API
1 parent 9dfbf5d commit 19fb5c6

File tree

4 files changed

+112
-20
lines changed

4 files changed

+112
-20
lines changed

big_tests/tests/rest_client_SUITE.erl

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ muc_test_cases() ->
6464
room_is_not_created_with_jid_not_matching_hostname,
6565
room_can_be_fetched_by_jid,
6666
messages_can_be_sent_and_fetched_by_room_jid,
67-
user_can_be_added_and_removed_by_room_jid
67+
user_can_be_added_and_removed_by_room_jid,
68+
room_cant_be_created_given_jid_in_a_non_muc_light_domain,
69+
user_cant_be_invited_given_room_jid_in_a_non_muc_light_domain,
70+
user_cant_be_removed_given_room_jid_in_a_non_muc_light_domain,
71+
message_cant_be_sent_given_room_jid_in_a_non_muc_light_domain,
72+
messages_cant_be_read_given_room_jid_in_a_non_muc_light_domain
6873
].
6974

7075
roster_test_cases() ->
@@ -83,7 +88,9 @@ init_per_suite(C) ->
8388
dynamic_modules:start(Host, mod_muc_light,
8489
[{host, binary_to_list(MUCLightHost)},
8590
{rooms_in_rosters, true}]),
86-
[{muc_light_host, MUCLightHost} | escalus:init_per_suite(C1)].
91+
NonMUCLightHost = <<"nonmuclight.", Host/binary>>, % register!
92+
[{muc_light_host, MUCLightHost},
93+
{non_muc_light_host, NonMUCLightHost} | escalus:init_per_suite(C1)].
8794

8895
end_per_suite(Config) ->
8996
escalus_fresh:clean(),
@@ -387,6 +394,63 @@ user_can_be_added_and_removed_by_room_jid(Config) ->
387394
?assertEqual(<<"204">>, Status)
388395
end).
389396

397+
room_cant_be_created_given_jid_in_a_non_muc_light_domain(Config) ->
398+
escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
399+
RoomID = <<"some_id">>,
400+
RoomJID = <<RoomID/binary, "@", (?config(non_muc_light_host, Config))/binary>>,
401+
Creds = credentials({alice, Alice}),
402+
403+
{{Status, _}, _} = create_room_with_id_request(Creds,
404+
<<"some_name">>,
405+
<<"some subject">>,
406+
RoomJID),
407+
?assertEqual(<<"400">>, Status)
408+
end).
409+
410+
user_cant_be_invited_given_room_jid_in_a_non_muc_light_domain(Config) ->
411+
escalus:fresh_story(Config, [{alice, 1}], fun(Alice) ->
412+
RoomID = given_new_room({alice, Alice}),
413+
RoomJID = <<RoomID/binary, "@", (?config(non_muc_light_host, Config))/binary>>,
414+
Creds = credentials({alice, Alice}),
415+
416+
{{Status, _}, _} = invite_to_room({alice, Alice}, RoomJID, <<"auser@domain.com">>),
417+
418+
?assertEqual(<<"400">>, Status)
419+
end).
420+
421+
user_cant_be_removed_given_room_jid_in_a_non_muc_light_domain(Config) ->
422+
escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
423+
RoomID = given_new_room({alice, Alice}),
424+
RoomJID = <<RoomID/binary, "@", (?config(non_muc_light_host, Config))/binary>>,
425+
Creds = credentials({alice, Alice}),
426+
427+
{{Status, _}, _} = remove_user_from_a_room({alice, Alice}, RoomJID, Bob),
428+
429+
?assertEqual(<<"400">>, Status)
430+
end).
431+
432+
message_cant_be_sent_given_room_jid_in_a_non_muc_light_domain(Config) ->
433+
escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
434+
RoomID = given_new_room({alice, Alice}),
435+
RoomJID = <<RoomID/binary, "@", (?config(non_muc_light_host, Config))/binary>>,
436+
Creds = credentials({alice, Alice}),
437+
438+
{{Status, _}, _} = send_message_to_room({alice, Alice}, RoomJID),
439+
440+
?assertEqual(<<"400">>, Status)
441+
end).
442+
443+
messages_cant_be_read_given_room_jid_in_a_non_muc_light_domain(Config) ->
444+
escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
445+
RoomID = given_new_room({alice, Alice}),
446+
RoomJID = <<RoomID/binary, "@", (?config(non_muc_light_host, Config))/binary>>,
447+
Creds = credentials({alice, Alice}),
448+
449+
{{Status, _}, _} = get_room_messages({alice, Alice}, RoomJID),
450+
451+
?assertEqual(<<"400">>, Status)
452+
end).
453+
390454
assert_room_messages(RecvMsg, {_ID, _GenFrom, GenMsg}) ->
391455
escalus:assert(is_chat_message, [maps:get(body, RecvMsg)], GenMsg),
392456
ok.
@@ -413,15 +477,12 @@ wait_for_room_msg(Msg, User) ->
413477
Stanza = escalus:wait_for_stanza(User),
414478
escalus:assert(is_groupchat_message, [maps:get(body, Msg)], Stanza).
415479

416-
given_message_sent_to_room(RoomID, Sender) ->
417-
{UserJID, _} = Creds = credentials(Sender),
418-
Path = <<"/rooms/", RoomID/binary, "/messages">>,
419-
Body = #{body => <<"Hi all!">>},
420-
{{<<"200">>, <<"OK">>}, {Result}} = rest_helper:post(client, Path, Body, Creds),
480+
given_message_sent_to_room(RoomID, {_, ClientOrSpec} = Sender) ->
481+
Body = <<"Hi all!">>,
482+
{{<<"200">>, <<"OK">>}, {Result}} = send_message_to_room(Sender, RoomID, Body),
421483
MsgId = proplists:get_value(<<"id">>, Result),
422484
true = is_binary(MsgId),
423-
424-
Body#{id => MsgId, from => UserJID}.
485+
#{body => Body, id => MsgId, from => user_jid(ClientOrSpec)}.
425486

426487
given_new_room_with_users(Owner, Users) ->
427488
RoomID = given_new_room(Owner),
@@ -501,6 +562,14 @@ get_messages(MeCreds, Other, Before, Count) ->
501562
"&limit=", integer_to_list(Count)]),
502563
get_messages(GetPath, MeCreds).
503564

565+
send_message_to_room(Client, RoomID) ->
566+
send_message_to_room(Client, RoomID, <<"Hi all!">>).
567+
568+
send_message_to_room(Client, RoomID, Body) ->
569+
{UserJID, _} = Creds = credentials(Client),
570+
Path = <<"/rooms/", RoomID/binary, "/messages">>,
571+
Payload = #{body => Body},
572+
rest_helper:post(client, Path, Payload, Creds).
504573

505574
get_room_messages(Client, RoomID, Count) ->
506575
get_room_messages(Client, RoomID, Count, undefined).

doc/rest-api/Client-frontend_swagger.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ info:
1010
This is to ensure integration between the **REST API** users and regular **XMPP** users.
1111
* All requests requiring a room ID (i.e. most of the requests fired at `/room` endpoint) accept either
1212
a bare room ID (e.g. `656c6f656c6f`) or a room JID (e.g. `656c6f656c6f@muclight.somedomain.com`).
13-
The host part of the room JID must be the host name of a MUC light service running in user's domain.
13+
The host part of the room JID must be the host name of a registered MUC light service.
1414
* All requests require authentication.
1515
This is to make sure the server can identify who sent the request and if it comes from an authorized user.
1616
Currently the only supported method is **Basic Auth**.

src/ejabberd_router.erl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
dirty_get_all_domains/0,
4242
dirty_get_all_routes/1,
4343
dirty_get_all_domains/1,
44+
dirty_get_route_handler_module/1,
4445
register_components/2,
4546
register_components/3,
4647
register_components/4,
@@ -374,6 +375,15 @@ all_routes(only_public) ->
374375
++
375376
mnesia:dirty_select(external_component_global, [MatchNonHidden]).
376377

378+
-spec dirty_get_route_handler_module(Domain :: binary()) -> {ok, module()} | error.
379+
dirty_get_route_handler_module(Domain) ->
380+
Routes = mnesia:dirty_match_object(#route{domain = Domain, handler = '_'}),
381+
case Routes of
382+
[#route{handler = {packet_handler, Module, _}}] ->
383+
{ok, Module};
384+
_ ->
385+
error
386+
end.
377387

378388
%%====================================================================
379389
%% gen_server callbacks

src/mongoose_client_api_rooms.erl

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ allowed_methods(Req, State) ->
4141

4242
resource_exists(Req, #{jid := #jid{lserver = Server}} = State) ->
4343
{RoomIDOrJID, Req2} = cowboy_req:binding(id, Req),
44-
MUCLightDomain = muc_light_domain(Server),
4544
case RoomIDOrJID of
4645
undefined ->
4746
{Method, Req3} = cowboy_req:method(Req2),
@@ -53,8 +52,8 @@ resource_exists(Req, #{jid := #jid{lserver = Server}} = State) ->
5352
end;
5453
_ ->
5554
case validate_room_id(RoomIDOrJID, Server) of
56-
{ok, RoomID} ->
57-
does_room_exist(RoomID, MUCLightDomain, Req2, State);
55+
{ok, RoomID, RoomHost} ->
56+
does_room_exist(RoomID, RoomHost, Req2, State);
5857
_ ->
5958
bad_request(Req2, State)
6059
end
@@ -150,15 +149,29 @@ determine_role(US, Users) ->
150149
Role
151150
end.
152151

153-
-spec validate_room_id(RoomIDOrJID :: binary(), Server :: binary()) ->
154-
{ok, RoomID :: binary()} | error.
155-
validate_room_id(RoomIDOrJID, Server) ->
156-
MUCLightDomain = muc_light_domain(Server),
152+
-spec validate_room_id(RoomIDOrJID :: binary() | term(), Server :: binary()) ->
153+
{ok, RoomID :: binary(), RoomHost :: binary()} | error.
154+
validate_room_id(RoomIDOrJID, Server) when is_binary(RoomIDOrJID) ->
157155
case jid:from_binary(RoomIDOrJID) of
158156
#jid{luser = <<>>, lserver = RoomID, lresource = <<>>} ->
159-
{ok, RoomID};
160-
#jid{luser = RoomID, lserver = MUCLightDomain, lresource = <<>>} ->
161-
{ok, RoomID};
157+
DefaultMucLightDomain = muc_light_domain(Server),
158+
{ok, RoomID, DefaultMucLightDomain};
159+
#jid{luser = RoomID, lserver = RoomHost, lresource = <<>>} ->
160+
case validate_room_host(RoomHost) of
161+
ok ->
162+
{ok, RoomID, RoomHost};
163+
error ->
164+
error
165+
end;
166+
_ ->
167+
error
168+
end.
169+
170+
-spec validate_room_host(binary()) -> ok | error.
171+
validate_room_host(RoomHost) ->
172+
case ejabberd_router:dirty_get_route_handler_module(RoomHost) of
173+
{ok, mod_muc_light} ->
174+
ok;
162175
_ ->
163176
error
164177
end.

0 commit comments

Comments
 (0)