1 |
|
-module(mongoose_client_api_rooms). |
2 |
|
-behaviour(cowboy_rest). |
3 |
|
|
4 |
|
-export([trails/0]). |
5 |
|
|
6 |
|
-export([init/2]). |
7 |
|
-export([content_types_provided/2]). |
8 |
|
-export([content_types_accepted/2]). |
9 |
|
-export([is_authorized/2]). |
10 |
|
-export([allowed_methods/2]). |
11 |
|
-export([resource_exists/2]). |
12 |
|
-export([assert_room_id_set/2]). |
13 |
|
|
14 |
|
-export([to_json/2]). |
15 |
|
-export([from_json/2]). |
16 |
|
|
17 |
|
-ignore_xref([ |
18 |
|
from_json/2, to_json/2, trails/0 |
19 |
|
]). |
20 |
|
|
21 |
|
-include("mongoose.hrl"). |
22 |
|
-include("jlib.hrl"). |
23 |
|
-include_lib("exml/include/exml.hrl"). |
24 |
|
|
25 |
|
trails() -> |
26 |
80 |
mongoose_client_api_rooms_doc:trails(). |
27 |
|
|
28 |
|
init(Req, Opts) -> |
29 |
37 |
mongoose_client_api:init(Req, Opts). |
30 |
|
|
31 |
|
is_authorized(Req, State) -> |
32 |
37 |
mongoose_client_api:is_authorized(Req, State). |
33 |
|
|
34 |
|
content_types_provided(Req, State) -> |
35 |
64 |
{[ |
36 |
|
{{<<"application">>, <<"json">>, '*'}, to_json} |
37 |
|
], Req, State}. |
38 |
|
|
39 |
|
content_types_accepted(Req, State) -> |
40 |
45 |
{[ |
41 |
|
{{<<"application">>, <<"json">>, '*'}, from_json} |
42 |
|
], Req, State}. |
43 |
|
|
44 |
|
allowed_methods(Req, State) -> |
45 |
37 |
{[<<"OPTIONS">>, <<"GET">>, <<"POST">>, <<"PUT">>], Req, State}. |
46 |
|
|
47 |
|
resource_exists(Req, #{jid := #jid{lserver = Server}} = State) -> |
48 |
64 |
RoomIDOrJID = cowboy_req:binding(id, Req), |
49 |
64 |
MUCLightDomain = muc_light_domain(Server), |
50 |
64 |
case RoomIDOrJID of |
51 |
|
undefined -> |
52 |
21 |
Method = cowboy_req:method(Req), |
53 |
21 |
case Method of |
54 |
|
<<"GET">> -> |
55 |
3 |
{true, Req, State}; |
56 |
|
_ -> |
57 |
18 |
{false, Req, State} |
58 |
|
end; |
59 |
|
_ -> |
60 |
43 |
case validate_room_id(RoomIDOrJID, Server, Req) of |
61 |
|
{ok, RoomID} -> |
62 |
42 |
State2 = set_room_id(RoomID, State), |
63 |
42 |
does_room_exist(MUCLightDomain, Req, State2); |
64 |
|
_ -> |
65 |
1 |
mongoose_client_api:bad_request(Req, <<"invalid_room_id">>, State) |
66 |
|
end |
67 |
|
end. |
68 |
|
|
69 |
|
set_room_id(RoomID, State = #{}) -> |
70 |
42 |
State#{room_id => RoomID}. |
71 |
|
|
72 |
|
does_room_exist(RoomS, Req, #{room_id := RoomU, jid := JID} = State) -> |
73 |
42 |
HostType = mod_muc_light_utils:muc_host_to_host_type(RoomS), |
74 |
42 |
case mod_muc_light_db_backend:get_info(HostType, {RoomU, RoomS}) of |
75 |
|
{ok, Config, Users, Version} -> |
76 |
38 |
Room = #{config => Config, |
77 |
|
users => Users, |
78 |
|
version => Version, |
79 |
|
jid => jid:make_noprep(RoomU, RoomS, <<>>)}, |
80 |
38 |
CallerRole = determine_role(jid:to_lus(JID), Users), |
81 |
38 |
{true, Req, State#{room => Room, role_in_room => CallerRole}}; |
82 |
|
_ -> |
83 |
4 |
{false, Req, State} |
84 |
|
end. |
85 |
|
|
86 |
|
to_json(Req, #{room := Room} = State) -> |
87 |
11 |
Config = maps:get(config, Room), |
88 |
11 |
Users = maps:get(users, Room), |
89 |
11 |
Resp = #{name => proplists:get_value(roomname, Config), |
90 |
|
subject => proplists:get_value(subject, Config), |
91 |
16 |
participants => [user_to_json(U) || U <- Users] |
92 |
|
}, |
93 |
11 |
{jiffy:encode(Resp), Req, State}; |
94 |
|
to_json(Req, #{jid := #jid{luser = User, lserver = Server}} = State) -> |
95 |
3 |
HostType = mod_muc_light_utils:server_host_to_host_type(Server), |
96 |
3 |
Rooms = mod_muc_light_db_backend:get_user_rooms(HostType, {User, Server}, undefined), |
97 |
3 |
RoomsMap = [get_room_details(RoomUS) || RoomUS <- Rooms], |
98 |
3 |
{jiffy:encode(lists:flatten(RoomsMap)), Req, State}. |
99 |
|
|
100 |
|
get_room_details({RoomID, RoomS} = RoomUS) -> |
101 |
2 |
HostType = mod_muc_light_utils:muc_host_to_host_type(RoomS), |
102 |
2 |
case mod_muc_light_db_backend:get_config(HostType, RoomUS) of |
103 |
|
{ok, Config, _} -> |
104 |
2 |
#{id => RoomID, |
105 |
|
name => proplists:get_value(roomname, Config), |
106 |
|
subject => proplists:get_value(subject, Config)}; |
107 |
|
_ -> |
108 |
:-( |
[] |
109 |
|
end. |
110 |
|
|
111 |
|
|
112 |
|
from_json(Req, State = #{was_replied := true}) -> |
113 |
:-( |
{true, Req, State}; |
114 |
|
from_json(Req, State) -> |
115 |
22 |
Method = cowboy_req:method(Req), |
116 |
22 |
{ok, Body, Req2} = cowboy_req:read_body(Req), |
117 |
22 |
case mongoose_client_api:json_to_map(Body) of |
118 |
|
{ok, #{<<"name">> := N, <<"subject">> := S} = JSONData} when is_binary(N), is_binary(S) -> |
119 |
22 |
handle_request(Method, JSONData, Req2, State); |
120 |
|
_ -> |
121 |
:-( |
mongoose_client_api:bad_request(Req, <<"Failed to parse parameters">>, State) |
122 |
|
end. |
123 |
|
|
124 |
|
handle_request(Method, JSONData, Req, State) -> |
125 |
22 |
case handle_request_by_method(Method, JSONData, Req, State) of |
126 |
|
{ok, #{jid := RoomJID}} -> |
127 |
22 |
RespBody = #{<<"id">> => RoomJID#jid.luser}, |
128 |
22 |
RespReq = cowboy_req:set_resp_body(jiffy:encode(RespBody), Req), |
129 |
22 |
{true, RespReq, State}; |
130 |
|
{Short, Desc} -> |
131 |
:-( |
mongoose_client_api:bad_request(Req, format_error(Short, Desc), State) |
132 |
|
end. |
133 |
|
|
134 |
|
format_error(Short, Desc) -> |
135 |
:-( |
jiffy:encode(#{module => <<"mongoose_client_api_rooms">>, |
136 |
|
what => <<"Failed to create room">>, |
137 |
|
reason => term_to_bin(Short), |
138 |
|
description => term_to_bin(Desc)}). |
139 |
|
|
140 |
|
term_to_bin(Term) -> |
141 |
:-( |
iolist_to_binary(io_lib:format("~p", [Term])). |
142 |
|
|
143 |
|
handle_request_by_method(<<"POST">>, JSONData, _Req, |
144 |
|
#{jid := #jid{lserver = LServer} = UserJID}) -> |
145 |
18 |
#{<<"name">> := RoomName, <<"subject">> := Subject} = JSONData, |
146 |
18 |
MUCServer = muc_light_domain(LServer), |
147 |
18 |
mod_muc_light_api:create_room(MUCServer, UserJID, RoomName, Subject); |
148 |
|
handle_request_by_method(<<"PUT">>, JSONData, Req, State) -> |
149 |
4 |
assert_room_id_set(Req, State), |
150 |
4 |
#{jid := #jid{lserver = LServer} = UserJID, room_id := RoomID} = State, |
151 |
4 |
#{<<"name">> := RoomName, <<"subject">> := Subject} = JSONData, |
152 |
4 |
MUCServer = muc_light_domain(LServer), |
153 |
4 |
mod_muc_light_api:create_room(MUCServer, RoomID, UserJID, RoomName, Subject). |
154 |
|
|
155 |
|
assert_room_id_set(_Req, #{room_id := _} = _State) -> |
156 |
7 |
ok. |
157 |
|
|
158 |
|
user_to_json({UserServer, Role}) -> |
159 |
16 |
#{user => jid:to_binary(UserServer), |
160 |
|
role => Role}. |
161 |
|
|
162 |
|
muc_light_domain(Server) -> |
163 |
129 |
HostType = mod_muc_light_utils:server_host_to_host_type(Server), |
164 |
129 |
mod_muc_light_utils:server_host_to_muc_host(HostType, Server). |
165 |
|
|
166 |
|
determine_role(US, Users) -> |
167 |
38 |
case lists:keyfind(US, 1, Users) of |
168 |
2 |
false -> none; |
169 |
|
{_, Role} -> |
170 |
36 |
Role |
171 |
|
end. |
172 |
|
|
173 |
|
-spec validate_room_id(RoomIDOrJID :: binary(), Server :: binary(), |
174 |
|
Req :: cowboy_req:req()) -> |
175 |
|
{ok, RoomID :: binary()} | error. |
176 |
|
validate_room_id(RoomIDOrJID, Server, Req) -> |
177 |
43 |
MUCLightDomain = muc_light_domain(Server), |
178 |
43 |
case jid:from_binary(RoomIDOrJID) of |
179 |
|
#jid{luser = <<>>, lserver = RoomID, lresource = <<>>} -> |
180 |
33 |
{ok, RoomID}; |
181 |
|
#jid{luser = RoomID, lserver = MUCLightDomain, lresource = <<>>} -> |
182 |
9 |
{ok, RoomID}; |
183 |
|
Other -> |
184 |
1 |
?LOG_WARNING(#{what => muc_invalid_room_id, |
185 |
|
text => <<"REST received room_id field is invalid " |
186 |
|
"or of unknown format">>, |
187 |
|
server => Server, room => RoomIDOrJID, reason => Other, |
188 |
:-( |
req => Req}), |
189 |
1 |
error |
190 |
|
end. |