Skip to content

Commit

Permalink
Wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Premwoik committed Apr 12, 2022
1 parent f18fe47 commit f5727d4
Show file tree
Hide file tree
Showing 14 changed files with 943 additions and 30 deletions.
9 changes: 7 additions & 2 deletions big_tests/tests/graphql_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
-export([execute/3, execute_auth/2, execute_user/3, get_listener_port/1, get_listener_config/1]).
-export([init_admin_handler/1]).
-export([get_ok_value/2, get_err_msg/1, get_err_msg/2, make_creds/1,
user_to_bin/1, user_to_jid/1, user_to_full_bin/1]).
user_to_bin/1, user_to_full_bin/1, user_to_jid/1, user_to_lower_jid/1]).

-include_lib("common_test/include/ct.hrl").
-include_lib("escalus/include/escalus.hrl").
Expand Down Expand Up @@ -94,7 +94,12 @@ user_to_bin(#client{} = Client) -> escalus_client:short_jid(Client);
user_to_bin(Bin) when is_binary(Bin) -> Bin.

user_to_jid(#client{jid = JID}) -> jid:to_bare(jid:from_binary(JID));
user_to_jid(Bin) when is_binary(Bin) -> jid:from_binary(Bin).
user_to_jid(Bin) when is_binary(Bin) -> jid:to_bare(jid:from_binary(Bin)).

user_to_lower_jid(#client{} = C) ->
jid:from_binary(escalus_utils:jid_to_lower(escalus_client:short_jid(C)));
user_to_lower_jid(Bin) when is_binary(Bin) ->
jid:to_bare(jid:from_binary(escalus_utils:jid_to_lower(Bin))).

%% Internal

Expand Down
557 changes: 553 additions & 4 deletions big_tests/tests/graphql_muc_SUITE.erl

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion priv/graphql/schemas/admin/muc.gql
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ type MUCAdminMutation @protected{
inviteUser(room: JID!, sender: JID!, recipient: JID!, reason: String): String
"Kick a user from a MUC room"
kickUser(room: JID!, nick: String!, reason: String): String
"Send a message to a MUC room"
"Send a message to a MUC room, from with res"
sendMessageToRoom(room: JID!, from: JID!, body: String!): String
"Send a message to a MUC room, from with res"
sendPrivateMessage(room: JID!, from: JID!, toNick: String!, body: String!): String
"Remove a MUC room"
deleteRoom(room: JID!, reason: String): String
"Change configuration of a MUC room"
changeRoomConfiguration(room: JID!, config: MUCRoomConfigInput!): MUCRoomConfig
"Change a user role"
setUserRole(room: JID!, nick: String!, role: MUCRole!): String
"Change a user affiliation"
setUserAffiliation(room: JID!, user: JID!, affiliation: MUCAffiliation!): String
"Enter the room with the given resource"
enterRoom(room: JID!, user: JID!, nick: String!, password: String): String
"Exit the room with the given resource"
exitRoom(room: JID!, user: JID!, nick: String!): String
}

"""
Expand All @@ -26,6 +36,8 @@ type MUCAdminQuery @protected{
getRoomConfig(room: JID!): MUCRoomConfig
"Get users list of given MUC room"
listRoomUsers(room: JID!): [MUCRoomUser!]
"Get affiliations list of given MUC room"
listRoomAffiliations(room: JID!, affiliation: MUCAffiliation): [MUCRoomAffiliation!]
"Get the MUC room archived messages"
getRoomMessages(room: JID!, pageSize: Int, before: DateTime): StanzasPayload
}
15 changes: 13 additions & 2 deletions priv/graphql/schemas/global/muc.gql
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
enum MUCRoomRole{
enum MUCAffiliation{
OWNER
ADMIN
MEMBER
NONE
}

enum MUCRole{
VISITOR
PARTICIPANT
MODERATOR
Expand All @@ -8,7 +14,12 @@ enum MUCRoomRole{
type MUCRoomUser{
jid: JID
nick: String!
role: MUCRoomRole!
role: MUCRole!
}

type MUCRoomAffiliation{
jid: JID!
affiliation: MUCAffiliation!
}

type MUCRoomDesc{
Expand Down
16 changes: 15 additions & 1 deletion priv/graphql/schemas/user/muc.gql
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,22 @@ type MUCUserMutation @protected{
kickUser(room: JID!, nick: String!, reason: String): String
"Send a message to a MUC room"
sendMessageToRoom(room: JID!, body: String!, resource: String): String
"Send a private message to a MUC room user, from with res"
sendPrivateMessage(room: JID!, toNick: String!, body: String!, resource: String): String
"Remove a MUC room"
deleteRoom(room: JID!, reason: String): String
"Change configuration of a MUC room"
changeRoomConfiguration(room: JID!, config: MUCRoomConfigInput!): MUCRoomConfig
"Change a user role"
setUserRole(room: JID!, nick: String!, role: MUCRole!): String
"Change a user affiliation"
setUserAffiliation(room: JID!, user: JID!, affiliation: MUCAffiliation!): String
"Enter the room with the given resource"
enterRoom(room: JID!, nick: String!, resource: String!, password: String): String
"Exit the room with the given resource"
exitRoom(room: JID!, nick: String!, resource: String!): String
"Change nickname"
changeNick(room: JID!, nick: String!): String
}

"""
Expand All @@ -24,8 +36,10 @@ type MUCUserQuery @protected{
listRooms(mucDomain: String!, limit: Int, index: Int): MUCRoomsPayload!
"Get configuration of the MUC room"
getRoomConfig(room: JID!): MUCRoomConfig
"Get user list of a given MUC room"
"Get users list of a given MUC room"
listRoomUsers(room: JID!): [MUCRoomUser!]
"Get affiliations list of given MUC room"
listRoomAffiliations(room: JID!, affiliation: MUCAffiliation): [MUCRoomAffiliation!]
"Get the MUC room archived messages"
getRoomMessages(room: JID!, pageSize: Int, before: DateTime): StanzasPayload
}
46 changes: 44 additions & 2 deletions src/graphql/admin/mongoose_graphql_muc_admin_mutation.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

-include("../mongoose_graphql_types.hrl").

-import(mongoose_graphql_helper, [make_error/2, format_result/2, null_to_default/2]).
-import(mongoose_graphql_helper, [make_error/2, format_result/2, null_to_default/2,
null_to_undefined/1]).

execute(_Ctx, _Obj, <<"createInstantRoom">>, Args) ->
create_instant_room(Args);
Expand All @@ -17,10 +18,20 @@ execute(_Ctx, _Obj, <<"kickUser">>, Args) ->
kick_user(Args);
execute(_Ctx, _Obj, <<"sendMessageToRoom">>, Args) ->
send_message_to_room(Args);
execute(_Ctx, _Obj, <<"sendPrivateMessage">>, Args) ->
send_private_message(Args);
execute(_Ctx, _Obj, <<"changeRoomConfiguration">>, Args) ->
change_room_config(Args);
execute(_Ctx, _Obj, <<"deleteRoom">>, Args) ->
delete_room(Args).
delete_room(Args);
execute(_Ctx, _Obj, <<"setUserRole">>, Args) ->
set_user_role(Args);
execute(_Ctx, _Obj, <<"setUserAffiliation">>, Args) ->
set_user_affiliation(Args);
execute(_Ctx, _Obj, <<"enterRoom">>, Args) ->
enter_room(Args);
execute(_Ctx, _Obj, <<"exitRoom">>, Args) ->
exit_room(Args).

-spec create_instant_room(map()) -> {ok, map()} | {error, resolver_error()}.
create_instant_room(#{<<"mucDomain">> := MUCDomain, <<"name">> := Name,
Expand Down Expand Up @@ -53,6 +64,13 @@ send_message_to_room(#{<<"room">> := RoomJID, <<"from">> := SenderJID, <<"body">
format_result(Res, #{room => jid:to_binary(RoomJID),
from => jid:to_binary(SenderJID)}).

-spec send_private_message(map()) -> {ok, binary()} | {error, resolver_error()}.
send_private_message(#{<<"room">> := RoomJID, <<"from">> := SenderJID,
<<"toNick">> := ToNick, <<"body">> := Message}) ->
Res = mod_muc_api:send_private_message(RoomJID, SenderJID, ToNick, Message),
format_result(Res, #{room => jid:to_binary(RoomJID),
from => jid:to_binary(SenderJID)}).

-spec change_room_config(map()) -> {ok, map()} | {error, resolver_error()}.
change_room_config(#{<<"room">> := RoomJID, <<"config">> := ConfigInput}) ->
Fun = fun(Config) -> mongoose_graphql_muc_helper:make_muc_room_config(ConfigInput, Config) end,
Expand All @@ -69,3 +87,27 @@ delete_room(#{<<"room">> := RoomJID, <<"reason">> := Reason}) ->
mongoose_graphql_muc_helper:default_room_removal_reason("admin")),
Res = mod_muc_api:delete_room(RoomJID, Reason2),
format_result(Res, #{room => jid:to_binary(RoomJID)}).

-spec set_user_role(map()) -> {ok, binary()} | {error, resolver_error()}.
set_user_role(#{<<"room">> := RoomJID, <<"nick">> := Nick, <<"role">> := Role}) ->
Result = mod_muc_api:set_role(RoomJID, Nick, Role),
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec set_user_affiliation(map()) -> {ok, binary()} | {error, resolver_error()}.
set_user_affiliation(#{<<"room">> := RoomJID, <<"user">> := UserJID, <<"affiliation">> := Aff}) ->
Result = mod_muc_api:set_affiliation(RoomJID, UserJID, Aff),
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec enter_room(map()) -> {ok, binary()} | {error, resolver_error()}.
enter_room(#{<<"room">> := RoomJID, <<"user">> := UserJID, <<"nick">> := Nick,
<<"password">> := Password}) ->
RoomJIDRes = jid:replace_resource(RoomJID, Nick),
Password2 = null_to_undefined(Password),
Result = mod_muc_api:enter_room(RoomJIDRes, UserJID, Password2),
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec exit_room(map()) -> {ok, binary()} | {error, resolver_error()}.
exit_room(#{<<"room">> := RoomJID, <<"user">> := UserJID, <<"nick">> := Nick}) ->
RoomJIDRes = jid:replace_resource(RoomJID, Nick),
Result = mod_muc_api:exit_room(RoomJIDRes, UserJID),
format_result(Result, #{room => jid:to_binary(RoomJID)}).
12 changes: 12 additions & 0 deletions src/graphql/admin/mongoose_graphql_muc_admin_query.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ execute(_Ctx, _Obj, <<"listRooms">>, Args) ->
list_rooms(Args);
execute(_Ctx, _Obj, <<"listRoomUsers">>, Args) ->
list_room_users(Args);
execute(_Ctx, _Obj, <<"listRoomAffiliations">>, Args) ->
list_room_affiliations(Args);
execute(_Ctx, _Obj, <<"getRoomMessages">>, Args) ->
get_room_messages(Args);
execute(_Ctx, _Obj, <<"getRoomConfig">>, Args) ->
Expand All @@ -36,6 +38,16 @@ list_room_users(#{<<"room">> := RoomJID}) ->
make_error(Error, #{room => jid:to_binary(RoomJID)})
end.

-spec list_room_affiliations(map()) -> {ok, [{ok, map()}]} | {error, resolver_error()}.
list_room_affiliations(#{<<"room">> := RoomJID, <<"affiliation">> := Aff}) ->
Aff2 = null_to_undefined(Aff),
case mod_muc_api:get_room_affiliation(RoomJID, Aff2) of
{ok, Affs} ->
{ok, mongoose_graphql_muc_helper:format_affs(Affs)};
Error ->
make_error(Error, #{room => jid:to_binary(RoomJID)})
end.

-spec get_room_config(map()) -> {ok, map()} | {error, resolver_error()}.
get_room_config(#{<<"room">> := RoomJID}) ->
case mod_muc_api:get_room_config(RoomJID) of
Expand Down
18 changes: 12 additions & 6 deletions src/graphql/mongoose_graphql_enum.erl
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ input(<<"SubAction">>, <<"DECLINE">>) -> {ok, decline};
input(<<"SubAction">>, <<"CANCEL">>) -> {ok, cancel};
input(<<"MutualSubAction">>, <<"CONNECT">>) -> {ok, connect};
input(<<"MutualSubAction">>, <<"DISCONNECT">>) -> {ok, disconnect};
input(<<"MUCRoomRole">>, <<"NONE">>) -> {ok, none};
input(<<"MUCRoomRole">>, <<"VISITOR">>) -> {ok, visitor};
input(<<"MUCRoomRole">>, <<"PARTICIPANT">>) -> {ok, participant};
input(<<"MUCRoomRole">>, <<"MODERATOR">>) -> {ok, moderator}.
input(<<"MUCRole">>, <<"VISITOR">>) -> {ok, visitor};
input(<<"MUCRole">>, <<"PARTICIPANT">>) -> {ok, participant};
input(<<"MUCRole">>, <<"MODERATOR">>) -> {ok, moderator};
input(<<"MUCAffiliation">>, <<"NONE">>) -> {ok, none};
input(<<"MUCAffiliation">>, <<"MEMBER">>) -> {ok, member};
input(<<"MUCAffiliation">>, <<"OUTCAST">>) -> {ok, outcast};
input(<<"MUCAffiliation">>, <<"ADMIN">>) -> {ok, admin};
input(<<"MUCAffiliation">>, <<"OWNER">>) -> {ok, owner}.

output(<<"PresenceShow">>, Show) ->
{ok, list_to_binary(string:to_upper(binary_to_list(Show)))};
Expand All @@ -52,5 +56,7 @@ output(<<"ContactAsk">>, Type) when Type =:= subscrube;
Type =:= both;
Type =:= none ->
{ok, list_to_binary(string:to_upper(atom_to_list(Type)))};
output(<<"MUCRoomRole">>, Role) ->
{ok, list_to_binary(string:to_upper(atom_to_list(Role)))}.
output(<<"MUCRole">>, Role) ->
{ok, list_to_binary(string:to_upper(atom_to_list(Role)))};
output(<<"MUCAffiliation">>, Aff) ->
{ok, list_to_binary(string:to_upper(atom_to_list(Aff)))}.
2 changes: 1 addition & 1 deletion src/graphql/mongoose_graphql_errors.erl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ format_error(#{error_term := _, phase := Phase} = Err) when Phase =:= execute;
Phase =:= validate;
Phase =:= uncategorized ->
Err2 = maps:merge(#{path => []}, Err),
[ErrMsg] = graphql:format_errors(#{}, [Err2]),
[ErrMsg | _] = graphql:format_errors(#{}, [Err2]),
{400, ErrMsg};
format_error(internal_crash) ->
Msg = #{message => <<"GraphQL Internal Server Error">>,
Expand Down
8 changes: 7 additions & 1 deletion src/graphql/mongoose_graphql_muc_helper.erl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-module(mongoose_graphql_muc_helper).

-export([make_rooms_payload/2, make_room_desc/1, muc_room_config_to_map/1, make_muc_room_config/2,
format_user/1, format_users/1, add_user_resource/2]).
format_user/1, format_users/1, add_user_resource/2, format_affs/1]).

-export([default_kick_reason/1, default_invite_reason/1, default_room_removal_reason/1]).

Expand Down Expand Up @@ -48,6 +48,12 @@ format_users(Users) ->
format_user(#{jid := JID, role := Role, nick := Nick}) ->
#{<<"jid">> => JID, <<"role">> => Role, <<"nick">> => Nick}.

format_affs(Affs) ->
[{ok, format_aff(A)} || A <- Affs].

format_aff({JID, Aff}) ->
#{<<"jid">> => JID, <<"affiliation">> => Aff}.

-spec muc_room_config_to_map(mod_muc_room:config()) -> map().
muc_room_config_to_map(Conf) ->
#{<<"title">> => Conf#config.title,
Expand Down
55 changes: 53 additions & 2 deletions src/graphql/user/mongoose_graphql_muc_user_mutation.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

-include("../mongoose_graphql_types.hrl").

-import(mongoose_graphql_helper, [make_error/2, format_result/2, null_to_default/2]).
-import(mongoose_graphql_helper, [make_error/2, format_result/2, null_to_default/2,
null_to_undefined/1]).

execute(Ctx, _Obj, <<"createInstantRoom">>, Args) ->
create_instant_room(Ctx, Args);
Expand All @@ -17,10 +18,37 @@ execute(Ctx, _Obj, <<"kickUser">>, Args) ->
kick_user(Ctx, Args);
execute(Ctx, _Obj, <<"sendMessageToRoom">>, Args) ->
send_message_to_room(Ctx, Args);
execute(Ctx, _Obj, <<"sendPrivateMessage">>, Args) ->
send_private_message(Ctx, Args);
execute(Ctx, _Obj, <<"changeRoomConfiguration">>, Args) ->
change_room_config(Ctx, Args);
execute(Ctx, _Obj, <<"deleteRoom">>, Args) ->
delete_room(Ctx, Args).
delete_room(Ctx, Args);
execute(Ctx, _Obj, <<"setUserRole">>, Args) ->
set_user_role(Ctx, Args);
execute(Ctx, _Obj, <<"setUserAffiliation">>, Args) ->
set_user_affiliation(Ctx, Args);
execute(Ctx, _Obj, <<"enterRoom">>, Args) ->
enter_room(Ctx, Args);
execute(Ctx, _Obj, <<"exitRoom">>, Args) ->
exit_room(Ctx, Args).

-spec enter_room(map(), map()) -> {ok, binary()} | {error, resolver_error()}.
enter_room(#{user := UserJID}, #{<<"room">> := RoomJID, <<"nick">> := Nick,
<<"resource">> := Resource, <<"password">> := Password}) ->
UserJIDRes = jid:replace_resource(UserJID, Resource),
RoomJIDRes = jid:replace_resource(RoomJID, Nick),
Password2 = null_to_undefined(Password),
Res = mod_muc_api:enter_room(RoomJIDRes, UserJIDRes, Password2),
format_result(Res, #{room => jid:to_binary(RoomJID)}).

-spec exit_room(map(), map()) -> {ok, binary()} | {error, resolver_error()}.
exit_room(#{user := UserJID}, #{<<"room">> := RoomJID, <<"nick">> := Nick,
<<"resource">> := Resource}) ->
UserJIDRes = jid:replace_resource(UserJID, Resource),
RoomJIDRes = jid:replace_resource(RoomJID, Nick),
Res = mod_muc_api:exit_room(RoomJIDRes, UserJIDRes),
format_result(Res, #{room => jid:to_binary(RoomJID)}).

-spec create_instant_room(map(), map()) -> {ok, map()} | {error, resolver_error()}.
create_instant_room(#{user := UserJID}, #{<<"mucDomain">> := MUCDomain, <<"name">> := Name,
Expand Down Expand Up @@ -52,6 +80,17 @@ send_message_to_room(#{user := UserJID}, #{<<"room">> := RoomJID, <<"body">> :=
Result = do_send_message_to_room(RoomJID, UserJID, Message, Res),
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec send_private_message(map(), map()) -> {ok, binary()} | {error, resolver_error()}.
send_private_message(#{user := UserJID}, #{<<"room">> := RoomJID, <<"body">> := Message,
<<"toNick">> := ToNick, <<"resource">> := Res}) ->
Result = case mongoose_graphql_muc_helper:add_user_resource(UserJID, Res) of
{ok, UserJIDRes} ->
mod_muc_api:send_private_message(RoomJID, UserJIDRes, ToNick, Message);
Error ->
Error
end,
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec change_room_config(map(), map()) -> {ok, map()} | {error, resolver_error()}.
change_room_config(#{user := UserJID}, #{<<"room">> := RoomJID, <<"config">> := ConfigInput}) ->
Fun = fun(Config) -> mongoose_graphql_muc_helper:make_muc_room_config(ConfigInput, Config) end,
Expand All @@ -69,6 +108,18 @@ delete_room(#{user := UserJID}, #{<<"room">> := RoomJID, <<"reason">> := Reason}
Res = mod_muc_api:delete_room(RoomJID, UserJID, Reason2),
format_result(Res, #{room => jid:to_binary(RoomJID)}).

-spec set_user_role(map(), map()) -> {ok, binary()} | {error, resolver_error()}.
set_user_role(#{user := UserJID}, #{<<"room">> := RoomJID, <<"nick">> := Nick,
<<"role">> := Role}) ->
Result = mod_muc_api:set_role(RoomJID, UserJID, Nick, Role),
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec set_user_affiliation(map(), map()) -> {ok, binary()} | {error, resolver_error()}.
set_user_affiliation(#{user := FromJID}, #{<<"room">> := RoomJID, <<"user">> := UserJID,
<<"affiliation">> := Aff}) ->
Result = mod_muc_api:set_affiliation(RoomJID, FromJID, UserJID, Aff),
format_result(Result, #{room => jid:to_binary(RoomJID)}).

-spec do_send_message_to_room(jid:jid(), jid:jid(), binary(), binary() | null) ->
{ok | no_session, iolist()}.
do_send_message_to_room(RoomJID, UserJID, Message, Res) ->
Expand Down
12 changes: 12 additions & 0 deletions src/graphql/user/mongoose_graphql_muc_user_query.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ execute(Ctx, _Obj, <<"listRooms">>, Args) ->
list_rooms(Ctx, Args);
execute(Ctx, _Obj, <<"listRoomUsers">>, Args) ->
list_room_users(Ctx, Args);
execute(Ctx, _Obj, <<"listRoomAffiliations">>, Args) ->
list_room_affiliations(Ctx, Args);
execute(Ctx, _Obj, <<"getRoomMessages">>, Args) ->
get_room_messages(Ctx, Args);
execute(Ctx, _Obj, <<"getRoomConfig">>, Args) ->
Expand All @@ -36,6 +38,16 @@ list_room_users(#{user := UserJID}, #{<<"room">> := RoomJID}) ->
make_error(Error, #{room => jid:to_binary(RoomJID)})
end.

-spec list_room_affiliations(map(), map()) -> {ok, [{ok, map()}]} | {error, resolver_error()}.
list_room_affiliations(#{user := UserJID}, #{<<"room">> := RoomJID, <<"affiliation">> := Aff}) ->
Aff2 = null_to_undefined(Aff),
case mod_muc_api:get_room_affiliation(RoomJID, UserJID, Aff2) of
{ok, Affs} ->
{ok, mongoose_graphql_muc_helper:format_affs(Affs)};
Error ->
make_error(Error, #{room => jid:to_binary(RoomJID)})
end.

-spec get_room_config(map(), map()) -> {ok, map()} | {error, resolver_error()}.
get_room_config(#{user := UserJID}, #{<<"room">> := RoomJID}) ->
case mod_muc_api:get_room_config(RoomJID, UserJID) of
Expand Down
Loading

0 comments on commit f5727d4

Please sign in to comment.