1 |
|
%%%---------------------------------------------------------------------- |
2 |
|
%%% File : mod_muc_light_db_rdbms.erl |
3 |
|
%%% Author : Piotr Nosek <piotr.nosek@erlang-solutions.com> |
4 |
|
%%% Purpose : RDBMS backend for mod_muc_light |
5 |
|
%%% Created : 24 Nov 2016 by Piotr Nosek <piotr.nosek@erlang-solutions.com> |
6 |
|
%%% |
7 |
|
%%% This program is free software; you can redistribute it and/or |
8 |
|
%%% modify it under the terms of the GNU General Public License as |
9 |
|
%%% published by the Free Software Foundation; either version 2 of the |
10 |
|
%%% License, or (at your option) any later version. |
11 |
|
%%% |
12 |
|
%%% This program is distributed in the hope that it will be useful, |
13 |
|
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 |
|
%%% General Public License for more details. |
16 |
|
%%% |
17 |
|
%%% You should have received a copy of the GNU General Public License |
18 |
|
%%% along with this program; if not, write to the Free Software |
19 |
|
%%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 |
|
%%% |
21 |
|
%%%---------------------------------------------------------------------- |
22 |
|
|
23 |
|
-module(mod_muc_light_db_rdbms). |
24 |
|
-author('piotr.nosek@erlang-solutions.com'). |
25 |
|
|
26 |
|
-behaviour(mod_muc_light_db_backend). |
27 |
|
|
28 |
|
%% API |
29 |
|
-export([ |
30 |
|
start/2, |
31 |
|
stop/1, |
32 |
|
create_room/5, |
33 |
|
destroy_room/2, |
34 |
|
room_exists/2, |
35 |
|
get_user_rooms/3, |
36 |
|
get_user_rooms_count/2, |
37 |
|
remove_user/3, |
38 |
|
remove_domain/3, |
39 |
|
get_config/2, |
40 |
|
set_config/4, |
41 |
|
get_blocking/3, |
42 |
|
get_blocking/4, |
43 |
|
set_blocking/4, |
44 |
|
get_aff_users/2, |
45 |
|
modify_aff_users/5, |
46 |
|
get_info/2 |
47 |
|
]). |
48 |
|
|
49 |
|
%% Extra API for testing |
50 |
|
-export([force_clear/0, |
51 |
|
select_room_id/3, |
52 |
|
select_affs_by_room_id/2, |
53 |
|
select_config_by_room_id/2 |
54 |
|
]). |
55 |
|
|
56 |
|
-ignore_xref([force_clear/0, |
57 |
|
select_room_id/3, |
58 |
|
select_affs_by_room_id/2, |
59 |
|
select_config_by_room_id/2]). |
60 |
|
|
61 |
|
-type room_id() :: non_neg_integer(). |
62 |
|
|
63 |
|
-include("mongoose.hrl"). |
64 |
|
-include("mod_muc_light.hrl"). |
65 |
|
|
66 |
|
%%==================================================================== |
67 |
|
%% API |
68 |
|
%%==================================================================== |
69 |
|
|
70 |
|
%% ------------------------ Backend start/stop ------------------------ |
71 |
|
|
72 |
|
-spec start(HostType :: mongooseim:host_type(), gen_mod:module_opts()) -> ok. |
73 |
|
start(_HostType, _) -> |
74 |
71 |
prepare_queries(), |
75 |
71 |
ok. |
76 |
|
|
77 |
|
-spec stop(HostType :: mongooseim:host_type()) -> ok. |
78 |
|
stop(_HostType) -> |
79 |
71 |
ok. |
80 |
|
|
81 |
|
%% ------------------------ SQL ------------------------------------------- |
82 |
|
|
83 |
|
prepare_queries() -> |
84 |
71 |
prepare_cleaning_queries(), |
85 |
71 |
prepare_room_queries(), |
86 |
71 |
prepare_affiliation_queries(), |
87 |
71 |
prepare_config_queries(), |
88 |
71 |
prepare_blocking_queries(), |
89 |
71 |
prepare_domain_removal_queries(), |
90 |
71 |
ok. |
91 |
|
|
92 |
|
prepare_cleaning_queries() -> |
93 |
71 |
mongoose_rdbms:prepare(muc_light_config_delete_all, muc_light_config, [], |
94 |
|
<<"DELETE FROM muc_light_config">>), |
95 |
71 |
mongoose_rdbms:prepare(muc_light_occupants_delete_all, muc_light_occupants, [], |
96 |
|
<<"DELETE FROM muc_light_occupants">>), |
97 |
71 |
mongoose_rdbms:prepare(muc_light_rooms_delete_all, muc_light_rooms, [], |
98 |
|
<<"DELETE FROM muc_light_rooms">>), |
99 |
71 |
mongoose_rdbms:prepare(muc_light_blocking_delete_all, muc_light_blocking, [], |
100 |
|
<<"DELETE FROM muc_light_blocking">>), |
101 |
71 |
ok. |
102 |
|
|
103 |
|
prepare_room_queries() -> |
104 |
|
%% Returns maximum 1 record |
105 |
71 |
mongoose_rdbms:prepare(muc_light_select_room_id, muc_light_rooms, |
106 |
|
[luser, lserver], |
107 |
|
<<"SELECT id FROM muc_light_rooms " |
108 |
|
"WHERE luser = ? AND lserver = ?">>), |
109 |
71 |
mongoose_rdbms:prepare(muc_light_select_room_id_and_version, muc_light_rooms, |
110 |
|
[luser, lserver], |
111 |
|
<<"SELECT id, version FROM muc_light_rooms " |
112 |
|
"WHERE luser = ? AND lserver = ?">>), |
113 |
71 |
mongoose_rdbms:prepare(muc_light_insert_room, muc_light_rooms, |
114 |
|
[luser, lserver, version], |
115 |
|
<<"INSERT INTO muc_light_rooms (luser, lserver, version)" |
116 |
|
" VALUES (?, ?, ?)">>), |
117 |
71 |
mongoose_rdbms:prepare(muc_light_update_room_version, muc_light_rooms, |
118 |
|
[luser, lserver, version], |
119 |
|
<<"UPDATE muc_light_rooms SET version = ? " |
120 |
|
" WHERE luser = ? AND lserver = ?">>), |
121 |
71 |
mongoose_rdbms:prepare(muc_light_delete_room, muc_light_rooms, |
122 |
|
[luser, lserver], |
123 |
|
<<"DELETE FROM muc_light_rooms" |
124 |
|
" WHERE luser = ? AND lserver = ?">>), |
125 |
|
%% These queries use multiple tables |
126 |
71 |
mongoose_rdbms:prepare(muc_light_select_user_rooms, muc_light_occupants, |
127 |
|
[luser, lserver], |
128 |
|
<<"SELECT r.luser, r.lserver " |
129 |
|
" FROM muc_light_occupants AS o " |
130 |
|
" INNER JOIN muc_light_rooms AS r ON o.room_id = r.id" |
131 |
|
" WHERE o.luser = ? AND o.lserver = ?">>), |
132 |
71 |
mongoose_rdbms:prepare(muc_light_select_user_rooms_count, muc_light_occupants, |
133 |
|
[luser, lserver], |
134 |
|
<<"SELECT count(*) " |
135 |
|
" FROM muc_light_occupants AS o " |
136 |
|
" INNER JOIN muc_light_rooms AS r ON o.room_id = r.id" |
137 |
|
" WHERE o.luser = ? AND o.lserver = ?">>), |
138 |
71 |
ok. |
139 |
|
|
140 |
|
prepare_affiliation_queries() -> |
141 |
|
%% This query uses multiple tables |
142 |
|
%% Also returns a room version |
143 |
71 |
mongoose_rdbms:prepare(muc_light_select_affs_by_us, muc_light_rooms, |
144 |
|
[luser, lserver], |
145 |
|
<<"SELECT version, o.luser, o.lserver, aff" |
146 |
|
" FROM muc_light_rooms AS r " |
147 |
|
" LEFT OUTER JOIN muc_light_occupants AS o ON r.id = o.room_id" |
148 |
|
" WHERE r.luser = ? AND r.lserver = ?">>), |
149 |
71 |
mongoose_rdbms:prepare(muc_light_select_affs_by_room_id, muc_light_occupants, |
150 |
|
[room_id], |
151 |
|
<<"SELECT luser, lserver, aff " |
152 |
|
"FROM muc_light_occupants WHERE room_id = ?">>), |
153 |
71 |
mongoose_rdbms:prepare(muc_light_insert_aff, muc_light_occupants, |
154 |
|
[room_id, luser, lserver, aff], |
155 |
|
<<"INSERT INTO muc_light_occupants" |
156 |
|
" (room_id, luser, lserver, aff)" |
157 |
|
" VALUES(?, ?, ?, ?)">>), |
158 |
71 |
mongoose_rdbms:prepare(muc_light_update_aff, muc_light_occupants, |
159 |
|
[aff, room_id, luser, lserver], |
160 |
|
<<"UPDATE muc_light_occupants SET aff = ? " |
161 |
|
"WHERE room_id = ? AND luser = ? AND lserver = ?">>), |
162 |
71 |
mongoose_rdbms:prepare(muc_light_delete_affs, muc_light_occupants, |
163 |
|
[room_id], |
164 |
|
<<"DELETE FROM muc_light_occupants WHERE room_id = ?">>), |
165 |
71 |
mongoose_rdbms:prepare(muc_light_delete_aff, muc_light_occupants, |
166 |
|
[room_id, luser, lserver], |
167 |
|
<<"DELETE FROM muc_light_occupants " |
168 |
|
"WHERE room_id = ? AND luser = ? AND lserver = ?">>), |
169 |
71 |
ok. |
170 |
|
|
171 |
|
prepare_config_queries() -> |
172 |
71 |
mongoose_rdbms:prepare(muc_light_select_config_by_room_id, muc_light_config, |
173 |
|
[room_id], |
174 |
|
<<"SELECT opt, val FROM muc_light_config WHERE room_id = ?">>), |
175 |
|
%% This query uses multiple tables |
176 |
71 |
mongoose_rdbms:prepare(muc_light_select_config_by_us, muc_light_rooms, |
177 |
|
[luser, lserver], |
178 |
|
<<"SELECT version, opt, val " |
179 |
|
"FROM muc_light_rooms AS r " |
180 |
|
"LEFT OUTER JOIN muc_light_config AS c ON r.id = c.room_id " |
181 |
|
"WHERE r.luser = ? AND r.lserver = ?">>), |
182 |
71 |
mongoose_rdbms:prepare(muc_light_insert_config, muc_light_config, |
183 |
|
[room_id, opt, val], |
184 |
|
<<"INSERT INTO muc_light_config (room_id, opt, val)" |
185 |
|
" VALUES(?, ?, ?)">>), |
186 |
71 |
mongoose_rdbms:prepare(muc_light_update_config, muc_light_config, |
187 |
|
[val, room_id, opt], |
188 |
|
<<"UPDATE muc_light_config SET val = ? " |
189 |
|
"WHERE room_id = ? AND opt = ?">>), |
190 |
71 |
mongoose_rdbms:prepare(muc_light_delete_config, muc_light_config, |
191 |
|
[room_id], |
192 |
|
<<"DELETE FROM muc_light_config WHERE room_id = ?">>), |
193 |
71 |
ok. |
194 |
|
|
195 |
|
prepare_blocking_queries() -> |
196 |
71 |
mongoose_rdbms:prepare(muc_light_select_blocking, muc_light_blocking, |
197 |
|
[luser, lserver], |
198 |
|
<<"SELECT what, who FROM muc_light_blocking " |
199 |
|
"WHERE luser = ? AND lserver = ?">>), |
200 |
71 |
mongoose_rdbms:prepare(muc_light_select_blocking_cnt, muc_light_blocking, |
201 |
|
[luser, lserver, what, who], |
202 |
|
<<"SELECT COUNT(*) FROM muc_light_blocking " |
203 |
|
"WHERE luser = ? AND lserver = ? AND " |
204 |
|
"what = ? AND who = ?">>), |
205 |
71 |
mongoose_rdbms:prepare(muc_light_select_blocking_cnt2, muc_light_blocking, |
206 |
|
[luser, lserver, what, who, what, who], |
207 |
|
<<"SELECT COUNT(*) FROM muc_light_blocking " |
208 |
|
"WHERE luser = ? AND lserver = ? AND " |
209 |
|
"((what = ? AND who = ?) OR (what = ? AND who = ?))">>), |
210 |
71 |
mongoose_rdbms:prepare(muc_light_insert_blocking, muc_light_blocking, |
211 |
|
[luser, lserver, what, who], |
212 |
|
<<"INSERT INTO muc_light_blocking" |
213 |
|
" (luser, lserver, what, who)" |
214 |
|
" VALUES (?, ?, ?, ?)">>), |
215 |
71 |
mongoose_rdbms:prepare(muc_light_delete_blocking1, muc_light_blocking, |
216 |
|
[luser, lserver, what, who], |
217 |
|
<<"DELETE FROM muc_light_blocking " |
218 |
|
"WHERE luser = ? AND lserver = ? AND what = ? AND who = ?">>), |
219 |
71 |
mongoose_rdbms:prepare(muc_light_delete_blocking, muc_light_blocking, |
220 |
|
[luser, lserver], |
221 |
|
<<"DELETE FROM muc_light_blocking" |
222 |
|
" WHERE luser = ? AND lserver = ?">>), |
223 |
71 |
ok. |
224 |
|
|
225 |
|
prepare_domain_removal_queries() -> |
226 |
|
%% RoomS argument |
227 |
71 |
mongoose_rdbms:prepare(muc_light_occupants_remove_room_domain, muc_light_occupants, |
228 |
|
['muc_light_rooms.lserver'], |
229 |
|
<<"DELETE FROM muc_light_occupants WHERE room_id IN " |
230 |
|
"(SELECT id FROM muc_light_rooms WHERE lserver = ?)">>), |
231 |
|
%% User's LServer argument |
232 |
71 |
mongoose_rdbms:prepare(muc_light_occupants_remove_user_domain, muc_light_occupants, |
233 |
|
[lserver], |
234 |
|
<<"DELETE FROM muc_light_occupants WHERE lserver = ?">>), |
235 |
|
%% RoomS argument |
236 |
71 |
mongoose_rdbms:prepare(muc_light_config_remove_room_domain, muc_light_config, |
237 |
|
['muc_light_rooms.lserver'], |
238 |
|
<<"DELETE FROM muc_light_config WHERE room_id IN " |
239 |
|
"(SELECT id FROM muc_light_rooms WHERE lserver = ?)">>), |
240 |
|
%% User's LServer argument |
241 |
71 |
mongoose_rdbms:prepare(muc_light_blocking_remove_user_domain, muc_light_blocking, |
242 |
|
[lserver], |
243 |
|
<<"DELETE FROM muc_light_blocking WHERE lserver = ?">>), |
244 |
|
%% RoomS argument |
245 |
71 |
mongoose_rdbms:prepare(muc_light_rooms_remove_room_domain, muc_light_rooms, |
246 |
|
[lserver], |
247 |
|
<<"DELETE FROM muc_light_rooms WHERE lserver = ?">>), |
248 |
71 |
ok. |
249 |
|
|
250 |
|
%% ------------------------ Room SQL functions ------------------------ |
251 |
|
|
252 |
|
select_room_id(HostType, RoomU, RoomS) -> |
253 |
1148 |
mongoose_rdbms:execute_successfully( |
254 |
|
HostType, muc_light_select_room_id, [RoomU, RoomS]). |
255 |
|
|
256 |
|
select_room_id_and_version(HostType, RoomU, RoomS) -> |
257 |
445 |
mongoose_rdbms:execute_successfully( |
258 |
|
HostType, muc_light_select_room_id_and_version, [RoomU, RoomS]). |
259 |
|
|
260 |
|
select_user_rooms(HostType, LUser, LServer) -> |
261 |
995 |
mongoose_rdbms:execute_successfully( |
262 |
|
HostType, muc_light_select_user_rooms, [LUser, LServer]). |
263 |
|
|
264 |
|
select_user_rooms_count(HostType, LUser, LServer) -> |
265 |
3 |
mongoose_rdbms:execute_successfully( |
266 |
|
HostType, muc_light_select_user_rooms_count, [LUser, LServer]). |
267 |
|
|
268 |
|
insert_room(HostType, RoomU, RoomS, Version) -> |
269 |
479 |
mongoose_rdbms:execute_successfully( |
270 |
|
HostType, muc_light_insert_room, [RoomU, RoomS, Version]). |
271 |
|
|
272 |
|
update_room_version(HostType, RoomU, RoomS, Version) -> |
273 |
390 |
mongoose_rdbms:execute_successfully( |
274 |
|
HostType, muc_light_update_room_version, [Version, RoomU, RoomS]). |
275 |
|
|
276 |
|
delete_room(HostType, RoomU, RoomS) -> |
277 |
181 |
mongoose_rdbms:execute_successfully( |
278 |
|
HostType, muc_light_delete_room, [RoomU, RoomS]). |
279 |
|
|
280 |
|
%% ------------------------ Affiliation SQL functions ------------------------ |
281 |
|
|
282 |
|
%% Returns affiliations with a version |
283 |
|
select_affs_by_us(HostType, RoomU, RoomS) -> |
284 |
769 |
mongoose_rdbms:execute_successfully( |
285 |
|
HostType, muc_light_select_affs_by_us, [RoomU, RoomS]). |
286 |
|
|
287 |
|
%% Returns affiliations without a version |
288 |
|
select_affs_by_room_id(HostType, RoomID) -> |
289 |
406 |
mongoose_rdbms:execute_successfully( |
290 |
|
HostType, muc_light_select_affs_by_room_id, [RoomID]). |
291 |
|
|
292 |
|
insert_aff(HostType, RoomID, UserU, UserS, Aff) -> |
293 |
795 |
DbAff = aff_atom2db(Aff), |
294 |
795 |
mongoose_rdbms:execute_successfully( |
295 |
|
HostType, muc_light_insert_aff, [RoomID, UserU, UserS, DbAff]). |
296 |
|
|
297 |
|
update_aff(HostType, RoomID, UserU, UserS, Aff) -> |
298 |
59 |
DbAff = aff_atom2db(Aff), |
299 |
59 |
mongoose_rdbms:execute_successfully( |
300 |
|
HostType, muc_light_update_aff, [DbAff, RoomID, UserU, UserS]). |
301 |
|
|
302 |
|
delete_affs(HostType, RoomID) -> |
303 |
181 |
mongoose_rdbms:execute_successfully( |
304 |
|
HostType, muc_light_delete_affs, [RoomID]). |
305 |
|
|
306 |
|
delete_aff(HostType, RoomID, UserU, UserS) -> |
307 |
313 |
mongoose_rdbms:execute_successfully( |
308 |
|
HostType, muc_light_delete_aff, [RoomID, UserU, UserS]). |
309 |
|
|
310 |
|
%% ------------------------ Config SQL functions --------------------------- |
311 |
|
select_config_by_room_id(HostType, RoomID) -> |
312 |
43 |
mongoose_rdbms:execute_successfully( |
313 |
|
HostType, muc_light_select_config_by_room_id, [RoomID]). |
314 |
|
|
315 |
|
select_config_by_us(HostType, RoomU, RoomS) -> |
316 |
48 |
mongoose_rdbms:execute_successfully( |
317 |
|
HostType, muc_light_select_config_by_us, [RoomU, RoomS]). |
318 |
|
|
319 |
|
insert_config(HostType, RoomID, Key, Val) -> |
320 |
964 |
mongoose_rdbms:execute_successfully( |
321 |
|
HostType, muc_light_insert_config, [RoomID, Key, Val]). |
322 |
|
|
323 |
|
update_config(HostType, RoomID, Key, Val) -> |
324 |
45 |
mongoose_rdbms:execute_successfully( |
325 |
|
HostType, muc_light_update_config, [Val, RoomID, Key]). |
326 |
|
|
327 |
|
delete_config(HostType, RoomID) -> |
328 |
181 |
mongoose_rdbms:execute_successfully( |
329 |
|
HostType, muc_light_delete_config, [RoomID]). |
330 |
|
|
331 |
|
%% ------------------------ Blocking SQL functions ------------------------- |
332 |
|
|
333 |
|
select_blocking(HostType, LUser, LServer) -> |
334 |
26 |
mongoose_rdbms:execute_successfully( |
335 |
|
HostType, muc_light_select_blocking, [LUser, LServer]). |
336 |
|
|
337 |
|
select_blocking_cnt(HostType, LUser, LServer, [{What, Who}]) -> |
338 |
10 |
DbWhat = what_atom2db(What), |
339 |
10 |
DbWho = jid:to_binary(Who), |
340 |
10 |
mongoose_rdbms:execute_successfully( |
341 |
|
HostType, muc_light_select_blocking_cnt, |
342 |
|
[LUser, LServer, DbWhat, DbWho]); |
343 |
|
select_blocking_cnt(HostType, LUser, LServer, [{What1, Who1}, {What2, Who2}]) -> |
344 |
240 |
DbWhat1 = what_atom2db(What1), |
345 |
240 |
DbWhat2 = what_atom2db(What2), |
346 |
240 |
DbWho1 = jid:to_binary(Who1), |
347 |
240 |
DbWho2 = jid:to_binary(Who2), |
348 |
240 |
mongoose_rdbms:execute_successfully( |
349 |
|
HostType, muc_light_select_blocking_cnt2, |
350 |
|
[LUser, LServer, DbWhat1, DbWho1, DbWhat2, DbWho2]). |
351 |
|
|
352 |
|
insert_blocking(HostType, LUser, LServer, What, Who) -> |
353 |
16 |
DbWhat = what_atom2db(What), |
354 |
16 |
DbWho = jid:to_binary(Who), |
355 |
16 |
mongoose_rdbms:execute_successfully( |
356 |
|
HostType, muc_light_insert_blocking, |
357 |
|
[LUser, LServer, DbWhat, DbWho]). |
358 |
|
|
359 |
|
delete_blocking1(HostType, LUser, LServer, What, Who) -> |
360 |
10 |
DbWhat = what_atom2db(What), |
361 |
10 |
DbWho = jid:to_binary(Who), |
362 |
10 |
mongoose_rdbms:execute_successfully( |
363 |
|
HostType, muc_light_delete_blocking1, |
364 |
|
[LUser, LServer, DbWhat, DbWho]). |
365 |
|
|
366 |
|
delete_blocking(HostType, UserU, UserS) -> |
367 |
951 |
mongoose_rdbms:execute_successfully( |
368 |
|
HostType, muc_light_delete_blocking, [UserU, UserS]). |
369 |
|
|
370 |
|
%% ------------------------ General room management ------------------------ |
371 |
|
|
372 |
|
-spec create_room(HostType :: mongooseim:host_type(), |
373 |
|
RoomUS :: jid:simple_bare_jid(), Config :: mod_muc_light_room_config:kv(), |
374 |
|
AffUsers :: aff_users(), Version :: binary()) -> |
375 |
|
{ok, FinalRoomUS :: jid:simple_bare_jid()} | {error, exists}. |
376 |
|
create_room(HostType, {<<>>, RoomS}, Config, AffUsers, Version) -> |
377 |
127 |
create_room_with_random_name(HostType, RoomS, Config, AffUsers, Version, 10); |
378 |
|
create_room(HostType, RoomUS, Config, AffUsers, Version) -> |
379 |
261 |
create_room_with_specified_name(HostType, RoomUS, Config, AffUsers, Version). |
380 |
|
|
381 |
|
create_room_with_random_name(_HostType, RoomS, _Config, _AffUsers, _Version, 0) -> |
382 |
:-( |
?LOG_ERROR(#{what => muc_create_room_with_random_name_failed, |
383 |
:-( |
sub_host => RoomS}), |
384 |
:-( |
error(create_room_with_random_name_failed); |
385 |
|
create_room_with_random_name(HostType, RoomS, Config, AffUsers, Version, Retries) |
386 |
|
when Retries > 0 -> |
387 |
128 |
RoomU = mongoose_bin:gen_from_timestamp(), |
388 |
128 |
RoomUS = {RoomU, RoomS}, |
389 |
128 |
F = fun() -> create_room_transaction(HostType, RoomUS, Config, AffUsers, Version) end, |
390 |
128 |
case mongoose_rdbms:sql_transaction(HostType, F) of |
391 |
|
{atomic, ok} -> |
392 |
127 |
{ok, RoomUS}; |
393 |
|
Other -> |
394 |
1 |
?LOG_ERROR(#{what => muc_create_room_with_random_name_retry, |
395 |
:-( |
candidate_room => RoomU, sub_host => RoomS, reason => Other}), |
396 |
1 |
create_room_with_random_name(HostType, RoomS, Config, AffUsers, Version, Retries-1) |
397 |
|
end. |
398 |
|
|
399 |
|
create_room_with_specified_name(HostType, RoomUS, Config, AffUsers, Version) -> |
400 |
261 |
F = fun() -> create_room_transaction(HostType, RoomUS, Config, AffUsers, Version) end, |
401 |
261 |
case mongoose_rdbms:sql_transaction(HostType, F) of |
402 |
|
{atomic, ok} -> |
403 |
253 |
{ok, RoomUS}; |
404 |
|
Other -> |
405 |
8 |
case room_exists(HostType, RoomUS) of |
406 |
|
true -> |
407 |
8 |
{error, exists}; |
408 |
|
false -> %% Some unknown error condition |
409 |
:-( |
{RoomU, RoomS} = RoomUS, |
410 |
:-( |
?LOG_ERROR(#{what => muc_create_room_with_specified_name_failed, |
411 |
:-( |
room => RoomU, sub_host => RoomS, reason => Other}), |
412 |
:-( |
error(create_room_with_specified_name_failed) |
413 |
|
end |
414 |
|
end. |
415 |
|
|
416 |
|
-spec destroy_room(HostType :: mongooseim:host_type(), |
417 |
|
RoomUS :: jid:simple_bare_jid()) -> |
418 |
|
ok | {error, not_exists}. |
419 |
|
destroy_room(HostType, RoomUS) -> |
420 |
192 |
F = fun() -> destroy_room_transaction(HostType, RoomUS) end, |
421 |
192 |
{atomic, Res} = mongoose_rdbms:sql_transaction(HostType, F), |
422 |
192 |
Res. |
423 |
|
|
424 |
|
-spec room_exists(HostType :: mongooseim:host_type(), |
425 |
|
RoomUS :: jid:simple_bare_jid()) -> boolean(). |
426 |
|
room_exists(HostType, {RoomU, RoomS}) -> |
427 |
575 |
{selected, Res} = select_room_id(HostType, RoomU, RoomS), |
428 |
575 |
Res /= []. |
429 |
|
|
430 |
|
-spec get_user_rooms(HostType :: mongooseim:host_type(), |
431 |
|
UserUS :: jid:simple_bare_jid(), |
432 |
|
MUCServer :: jid:lserver() | undefined) -> |
433 |
|
[RoomUS :: jid:simple_bare_jid()]. |
434 |
|
get_user_rooms(HostType, {LUser, LServer}, undefined) -> |
435 |
|
%% Only one hosttype is handled here |
436 |
|
%% It is used to be map over MYHOSTS |
437 |
967 |
{selected, Rooms} = select_user_rooms(HostType, LUser, LServer), |
438 |
967 |
lists:usort(Rooms); |
439 |
|
get_user_rooms(HostType, {LUser, LServer}, _MUCServer) -> |
440 |
28 |
{selected, Rooms} = select_user_rooms(HostType, LUser, LServer), |
441 |
28 |
Rooms. |
442 |
|
|
443 |
|
-spec get_user_rooms_count(HostType :: mongooseim:host_type(), |
444 |
|
UserUS :: jid:simple_bare_jid()) -> |
445 |
|
non_neg_integer(). |
446 |
|
get_user_rooms_count(HostType, {LUser, LServer}) -> |
447 |
3 |
{selected, [{Cnt}]} = select_user_rooms_count(HostType, LUser, LServer), |
448 |
3 |
mongoose_rdbms:result_to_integer(Cnt). |
449 |
|
|
450 |
|
-spec remove_user(HostType :: mongooseim:host_type(), |
451 |
|
UserUS :: jid:simple_bare_jid(), |
452 |
|
Version :: binary()) -> |
453 |
|
mod_muc_light_db_backend:remove_user_return() | {error, term()}. |
454 |
|
remove_user(HostType, {_, UserS} = UserUS, Version) -> |
455 |
951 |
F = fun() -> remove_user_transaction(HostType, UserUS, Version) end, |
456 |
951 |
{atomic, Res} = mongoose_rdbms:sql_transaction(UserS, F), |
457 |
951 |
Res. |
458 |
|
|
459 |
|
-spec remove_domain(mongooseim:host_type(), jid:lserver(), jid:lserver()) -> ok. |
460 |
|
remove_domain(HostType, RoomS, LServer) -> |
461 |
7 |
F = fun() -> |
462 |
7 |
mongoose_rdbms:execute_successfully( |
463 |
|
HostType, muc_light_occupants_remove_room_domain, [RoomS]), |
464 |
7 |
mongoose_rdbms:execute_successfully( |
465 |
|
HostType, muc_light_occupants_remove_user_domain, [LServer]), |
466 |
7 |
mongoose_rdbms:execute_successfully( |
467 |
|
HostType, muc_light_config_remove_room_domain, [RoomS]), |
468 |
7 |
mongoose_rdbms:execute_successfully( |
469 |
|
HostType, muc_light_blocking_remove_user_domain, [LServer]), |
470 |
7 |
mongoose_rdbms:execute_successfully( |
471 |
|
HostType, muc_light_rooms_remove_room_domain, [RoomS]), |
472 |
7 |
ok |
473 |
|
end, |
474 |
7 |
{atomic, ok} = mongoose_rdbms:sql_transaction(HostType, F), |
475 |
7 |
ok. |
476 |
|
|
477 |
|
%% ------------------------ Configuration manipulation ------------------------ |
478 |
|
|
479 |
|
-spec get_config(HostType :: mongooseim:host_type(), |
480 |
|
RoomUS :: jid:simple_bare_jid()) -> |
481 |
|
{ok, mod_muc_light_room_config:kv(), Version :: binary()} | {error, not_exists}. |
482 |
|
get_config(HostType, {RoomU, RoomS}) -> |
483 |
48 |
{selected, Result} = select_config_by_us(HostType, RoomU, RoomS), |
484 |
48 |
case Result of |
485 |
|
[] -> |
486 |
:-( |
{error, not_exists}; |
487 |
|
[{Version, null, null}] -> |
488 |
:-( |
{ok, [], Version}; |
489 |
|
[{Version, _, _} | _] -> |
490 |
48 |
RawConfig = [{Key, Val} || {_, Key, Val} <- Result], |
491 |
48 |
{ok, Config} = mod_muc_light_room_config:from_binary_kv( |
492 |
|
RawConfig, mod_muc_light:config_schema(RoomS)), |
493 |
48 |
{ok, Config, Version} |
494 |
|
end. |
495 |
|
|
496 |
|
-spec set_config(HostType :: mongooseim:host_type(), |
497 |
|
RoomUS :: jid:simple_bare_jid(), Config :: mod_muc_light_room_config:kv(), |
498 |
|
Version :: binary()) -> |
499 |
|
{ok, PrevVersion :: binary()} | {error, not_exists}. |
500 |
|
set_config(HostType, RoomUS, ConfigChanges, Version) -> |
501 |
29 |
{atomic, Res} |
502 |
|
= mongoose_rdbms:sql_transaction( |
503 |
29 |
HostType, fun() -> set_config_transaction(RoomUS, ConfigChanges, Version) end), |
504 |
29 |
Res. |
505 |
|
|
506 |
|
%% ------------------------ Blocking manipulation ------------------------ |
507 |
|
|
508 |
|
-spec get_blocking(HostType :: mongooseim:host_type(), |
509 |
|
UserUS :: jid:simple_bare_jid(), MUCServer :: jid:lserver()) -> |
510 |
|
[blocking_item()]. |
511 |
|
get_blocking(HostType, {LUser, LServer}, _MUCServer) -> |
512 |
26 |
{selected, WhatWhos} = select_blocking(HostType, LUser, LServer), |
513 |
26 |
decode_blocking(WhatWhos). |
514 |
|
|
515 |
|
-spec get_blocking(HostType :: mongooseim:host_type(), |
516 |
|
UserUS :: jid:simple_bare_jid(), |
517 |
|
MUCServer :: jid:lserver(), |
518 |
|
WhatWhos :: [{blocking_what(), jid:simple_bare_jid()}]) -> |
519 |
|
blocking_action(). |
520 |
|
get_blocking(HostType, {LUser, LServer}, _MUCServer, WhatWhos) -> |
521 |
250 |
{selected, [{Count}]} = select_blocking_cnt(HostType, LUser, LServer, WhatWhos), |
522 |
250 |
case mongoose_rdbms:result_to_integer(Count) of |
523 |
246 |
0 -> allow; |
524 |
4 |
_ -> deny |
525 |
|
end. |
526 |
|
|
527 |
|
-spec set_blocking(HostType :: mongooseim:host_type(), |
528 |
|
UserUS :: jid:simple_bare_jid(), |
529 |
|
MUCServer :: jid:lserver(), |
530 |
|
BlockingItems :: [blocking_item()]) -> ok. |
531 |
|
set_blocking(HostType, UserUS, MUCServer, BlockingItems) -> |
532 |
21 |
set_blocking_loop(HostType, UserUS, MUCServer, BlockingItems). |
533 |
|
|
534 |
|
set_blocking_loop(_HostType, _UserUS, _MUCServer, []) -> |
535 |
21 |
ok; |
536 |
|
set_blocking_loop(HostType, {LUser, LServer} = UserUS, MUCServer, |
537 |
|
[{What, deny, Who} | RBlockingItems]) -> |
538 |
16 |
{updated, _} = insert_blocking(HostType, LUser, LServer, What, Who), |
539 |
16 |
set_blocking_loop(HostType, UserUS, MUCServer, RBlockingItems); |
540 |
|
set_blocking_loop(HostType, {LUser, LServer} = UserUS, MUCServer, |
541 |
|
[{What, allow, Who} | RBlockingItems]) -> |
542 |
10 |
{updated, _} = delete_blocking1(HostType, LUser, LServer, What, Who), |
543 |
10 |
set_blocking_loop(HostType, UserUS, MUCServer, RBlockingItems). |
544 |
|
|
545 |
|
%% ------------------------ Affiliations manipulation ------------------------ |
546 |
|
|
547 |
|
-spec get_aff_users(HostType :: mongooseim:host_type(), |
548 |
|
RoomUS :: jid:simple_bare_jid()) -> |
549 |
|
{ok, aff_users(), Version :: binary()} | {error, not_exists}. |
550 |
|
get_aff_users(HostType, {RoomU, RoomS}) -> |
551 |
769 |
case select_affs_by_us(HostType, RoomU, RoomS) of |
552 |
|
{selected, []} -> |
553 |
19 |
{error, not_exists}; |
554 |
|
{selected, [{Version, null, null, null}]} -> |
555 |
:-( |
{ok, [], Version}; |
556 |
|
{selected, [{Version, _, _, _} | _] = Res} -> |
557 |
750 |
AffUsers = decode_affs_with_versions(Res), |
558 |
750 |
{ok, AffUsers, Version} |
559 |
|
end. |
560 |
|
|
561 |
|
-spec modify_aff_users(HostType :: mongooseim:host_type(), |
562 |
|
RoomUS :: jid:simple_bare_jid(), |
563 |
|
AffUsersChanges :: aff_users(), |
564 |
|
ExternalCheck :: external_check_fun(), |
565 |
|
Version :: binary()) -> |
566 |
|
mod_muc_light_db_backend:modify_aff_users_return(). |
567 |
|
modify_aff_users(HostType, RoomUS, AffUsersChanges, ExternalCheck, Version) -> |
568 |
142 |
F = fun() -> modify_aff_users_transaction(HostType, RoomUS, AffUsersChanges, |
569 |
|
ExternalCheck, Version) end, |
570 |
142 |
{atomic, Res} = mongoose_rdbms:sql_transaction(HostType, F), |
571 |
142 |
Res. |
572 |
|
|
573 |
|
%% ------------------------ Misc ------------------------ |
574 |
|
|
575 |
|
-spec get_info(HostType :: mongooseim:host_type(), |
576 |
|
RoomUS :: jid:simple_bare_jid()) -> |
577 |
|
{ok, mod_muc_light_room_config:kv(), aff_users(), Version :: binary()} |
578 |
|
| {error, not_exists}. |
579 |
|
get_info(HostType, {RoomU, RoomS}) -> |
580 |
53 |
case select_room_id_and_version(HostType, RoomU, RoomS) of |
581 |
|
{selected, [{DbRoomID, Version}]} -> |
582 |
41 |
RoomID = mongoose_rdbms:result_to_integer(DbRoomID), |
583 |
41 |
{selected, AffUsersDB} = select_affs_by_room_id(HostType, RoomID), |
584 |
41 |
AffUsers = decode_affs(AffUsersDB), |
585 |
41 |
{selected, ConfigDB} = select_config_by_room_id(HostType, RoomID), |
586 |
41 |
{ok, Config} = mod_muc_light_room_config:from_binary_kv( |
587 |
|
ConfigDB, mod_muc_light:config_schema(RoomS)), |
588 |
|
|
589 |
41 |
{ok, Config, AffUsers, Version}; |
590 |
|
{selected, []} -> |
591 |
12 |
{error, not_exists} |
592 |
|
end. |
593 |
|
|
594 |
|
%% ------------------------ Conversions ------------------------ |
595 |
|
|
596 |
|
decode_affs(AffUsersDB) -> |
597 |
404 |
US2Aff = [{{UserU, UserS}, aff_db2atom(Aff)} |
598 |
404 |
|| {UserU, UserS, Aff} <- AffUsersDB], |
599 |
404 |
lists:sort(US2Aff). |
600 |
|
|
601 |
|
decode_affs_with_versions(AffUsersDB) -> |
602 |
750 |
US2Aff = [{{UserU, UserS}, aff_db2atom(Aff)} |
603 |
750 |
|| {_Version, UserU, UserS, Aff} <- AffUsersDB], |
604 |
750 |
lists:sort(US2Aff). |
605 |
|
|
606 |
|
decode_blocking(WhatWhos) -> |
607 |
26 |
[ {what_db2atom(What), deny, jid:to_lus(jid:from_binary(Who))} |
608 |
26 |
|| {What, Who} <- WhatWhos ]. |
609 |
|
|
610 |
|
-spec what_db2atom(binary() | pos_integer()) -> blocking_what(). |
611 |
3 |
what_db2atom(1) -> room; |
612 |
9 |
what_db2atom(2) -> user; |
613 |
:-( |
what_db2atom(Bin) -> what_db2atom(mongoose_rdbms:result_to_integer(Bin)). |
614 |
|
|
615 |
|
-spec what_atom2db(blocking_what()) -> non_neg_integer(). |
616 |
247 |
what_atom2db(room) -> 1; |
617 |
269 |
what_atom2db(user) -> 2. |
618 |
|
|
619 |
|
-spec aff_atom2db(aff()) -> non_neg_integer(). |
620 |
435 |
aff_atom2db(owner) -> 1; |
621 |
419 |
aff_atom2db(member) -> 2. |
622 |
|
|
623 |
|
-spec aff_db2atom(binary() | pos_integer()) -> aff(). |
624 |
1154 |
aff_db2atom(1) -> owner; |
625 |
1109 |
aff_db2atom(2) -> member; |
626 |
:-( |
aff_db2atom(Bin) -> aff_db2atom(mongoose_rdbms:result_to_integer(Bin)). |
627 |
|
|
628 |
|
%%==================================================================== |
629 |
|
%% API for tests |
630 |
|
%%==================================================================== |
631 |
|
|
632 |
|
force_clear_statements() -> |
633 |
312 |
[muc_light_config_delete_all, |
634 |
|
muc_light_occupants_delete_all, |
635 |
|
muc_light_rooms_delete_all, |
636 |
|
muc_light_blocking_delete_all]. |
637 |
|
|
638 |
|
-spec force_clear() -> ok. |
639 |
|
force_clear() -> |
640 |
104 |
[mongoose_rdbms:execute_successfully(Host, Statement, []) |
641 |
104 |
|| Host <- ?MYHOSTS, Statement <- force_clear_statements()], |
642 |
104 |
ok. |
643 |
|
|
644 |
|
%%==================================================================== |
645 |
|
%% Internal functions |
646 |
|
%%==================================================================== |
647 |
|
|
648 |
|
%% ------------------------ General room management ------------------------ |
649 |
|
|
650 |
|
%% Expects config to have unique fields! |
651 |
|
-spec create_room_transaction(HostType :: mongooseim:host_type(), |
652 |
|
RoomUS :: jid:simple_bare_jid(), |
653 |
|
Config :: mod_muc_light_room_config:kv(), |
654 |
|
AffUsers :: aff_users(), |
655 |
|
Version :: binary()) -> ok. |
656 |
|
create_room_transaction(HostType, {RoomU, RoomS}, Config, AffUsers, Version) -> |
657 |
479 |
insert_room(HostType, RoomU, RoomS, Version), |
658 |
380 |
RoomID = mongoose_rdbms:selected_to_integer(select_room_id(HostType, RoomU, RoomS)), |
659 |
380 |
Schema = mod_muc_light:config_schema(RoomS), |
660 |
380 |
{ok, ConfigFields} = mod_muc_light_room_config:to_binary_kv(Config, Schema), |
661 |
380 |
[insert_aff_tuple(HostType, RoomID, AffUser) || AffUser <- AffUsers], |
662 |
380 |
[insert_config_kv(HostType, RoomID, KV) || KV <- ConfigFields], |
663 |
380 |
ok. |
664 |
|
|
665 |
|
insert_aff_tuple(HostType, RoomID, {{UserU, UserS}, Aff}) -> |
666 |
739 |
insert_aff(HostType, RoomID, UserU, UserS, Aff). |
667 |
|
|
668 |
|
insert_config_kv(HostType, RoomID, {Key, Val}) -> |
669 |
964 |
insert_config(HostType, RoomID, Key, Val). |
670 |
|
|
671 |
|
-spec destroy_room_transaction(HostType :: mongooseim:host_type(), |
672 |
|
RoomUS :: jid:simple_bare_jid()) -> |
673 |
|
ok | {error, not_exists}. |
674 |
|
destroy_room_transaction(HostType, {RoomU, RoomS}) -> |
675 |
192 |
case select_room_id(HostType, RoomU, RoomS) of |
676 |
|
{selected, [{DbRoomID}]} -> |
677 |
181 |
RoomID = mongoose_rdbms:result_to_integer(DbRoomID), |
678 |
181 |
{updated, _} = delete_affs(HostType, RoomID), |
679 |
181 |
{updated, _} = delete_config(HostType, RoomID), |
680 |
181 |
{updated, _} = delete_room(HostType, RoomU, RoomS), |
681 |
181 |
ok; |
682 |
|
{selected, []} -> |
683 |
11 |
{error, not_exists} |
684 |
|
end. |
685 |
|
|
686 |
|
-spec remove_user_transaction(HostType :: mongooseim:host_type(), |
687 |
|
UserUS :: jid:simple_bare_jid(), |
688 |
|
Version :: binary()) -> |
689 |
|
mod_muc_light_db_backend:remove_user_return(). |
690 |
|
remove_user_transaction(HostType, {UserU, UserS} = UserUS, Version) -> |
691 |
951 |
Rooms = get_user_rooms(HostType, UserUS, undefined), |
692 |
951 |
{updated, _} = delete_blocking(HostType, UserU, UserS), |
693 |
951 |
lists:map( |
694 |
|
fun(RoomUS) -> |
695 |
221 |
{RoomUS, modify_aff_users_transaction(HostType, |
696 |
221 |
RoomUS, [{UserUS, none}], fun(_, _) -> ok end, Version)} |
697 |
|
end, Rooms). |
698 |
|
|
699 |
|
%% ------------------------ Configuration manipulation ------------------------ |
700 |
|
|
701 |
|
-spec set_config_transaction(RoomUS :: jid:simple_bare_jid(), |
702 |
|
ConfigChanges :: mod_muc_light_room_config:kv(), |
703 |
|
Version :: binary()) -> |
704 |
|
{ok, PrevVersion :: binary()} | {error, not_exists}. |
705 |
|
set_config_transaction({RoomU, RoomS} = RoomUS, ConfigChanges, Version) -> |
706 |
29 |
HostType = room_us_to_host_type(RoomUS), |
707 |
29 |
case select_room_id_and_version(HostType, RoomU, RoomS) of |
708 |
|
{selected, [{DbRoomID, PrevVersion}]} -> |
709 |
29 |
RoomID = mongoose_rdbms:result_to_integer(DbRoomID), |
710 |
29 |
{updated, _} = update_room_version(HostType, RoomU, RoomS, Version), |
711 |
29 |
{ok, Config} = mod_muc_light_room_config:to_binary_kv_diff( |
712 |
|
ConfigChanges, mod_muc_light:config_schema(RoomS)), |
713 |
29 |
lists:foreach( |
714 |
|
fun({Key, Val}) -> |
715 |
45 |
{updated, _} = update_config(HostType, RoomID, Key, Val) |
716 |
|
end, Config), |
717 |
29 |
{ok, PrevVersion}; |
718 |
|
{selected, []} -> |
719 |
:-( |
{error, not_exists} |
720 |
|
end. |
721 |
|
|
722 |
|
%% ------------------------ Blocking manipulation ------------------------ |
723 |
|
|
724 |
|
%% ------------------------ Affiliations manipulation ------------------------ |
725 |
|
|
726 |
|
-spec modify_aff_users_transaction(HostType :: mongooseim:host_type(), |
727 |
|
RoomUS :: jid:simple_bare_jid(), |
728 |
|
AffUsersChanges :: aff_users(), |
729 |
|
CheckFun :: external_check_fun(), |
730 |
|
Version :: binary()) -> |
731 |
|
mod_muc_light_db_backend:modify_aff_users_return(). |
732 |
|
modify_aff_users_transaction(HostType, {RoomU, RoomS} = RoomUS, |
733 |
|
AffUsersChanges, CheckFun, Version) -> |
734 |
363 |
case select_room_id_and_version(HostType, RoomU, RoomS) of |
735 |
|
{selected, [{DbRoomID, PrevVersion}]} -> |
736 |
363 |
RoomID = mongoose_rdbms:result_to_integer(DbRoomID), |
737 |
363 |
modify_aff_users_transaction(HostType, |
738 |
|
RoomUS, RoomID, AffUsersChanges, CheckFun, PrevVersion, Version); |
739 |
|
{selected, []} -> |
740 |
:-( |
{error, not_exists} |
741 |
|
end. |
742 |
|
|
743 |
|
-spec modify_aff_users_transaction(HostType :: mongooseim:host_type(), |
744 |
|
RoomUS :: jid:simple_bare_jid(), |
745 |
|
RoomID :: room_id(), |
746 |
|
AffUsersChanges :: aff_users(), |
747 |
|
CheckFun :: external_check_fun(), |
748 |
|
PrevVersion :: binary(), |
749 |
|
Version :: binary()) -> |
750 |
|
mod_muc_light_db_backend:modify_aff_users_return(). |
751 |
|
modify_aff_users_transaction(HostType, RoomUS, RoomID, AffUsersChanges, |
752 |
|
CheckFun, PrevVersion, Version) -> |
753 |
363 |
{selected, AffUsersDB} = select_affs_by_room_id(HostType, RoomID), |
754 |
363 |
AffUsers = decode_affs(AffUsersDB), |
755 |
363 |
case mod_muc_light_utils:change_aff_users(AffUsers, AffUsersChanges) of |
756 |
|
{ok, NewAffUsers, AffUsersChanged, JoiningUsers, _LeavingUsers} -> |
757 |
362 |
case CheckFun(RoomUS, NewAffUsers) of |
758 |
|
ok -> |
759 |
361 |
apply_aff_users_transaction(HostType, RoomID, AffUsersChanged, JoiningUsers), |
760 |
361 |
{RoomU, RoomS} = RoomUS, |
761 |
361 |
{updated, _} = update_room_version(HostType, RoomU, RoomS, Version), |
762 |
361 |
{ok, AffUsers, NewAffUsers, AffUsersChanged, PrevVersion}; |
763 |
|
Error -> |
764 |
1 |
Error |
765 |
|
end; |
766 |
|
Error -> |
767 |
1 |
Error |
768 |
|
end. |
769 |
|
|
770 |
|
-spec apply_aff_users_transaction(HostType :: mongooseim:host_type(), |
771 |
|
RoomID :: room_id(), |
772 |
|
AffUsersChanges :: aff_users(), |
773 |
|
JoiningUsers :: [jid:simple_bare_jid()]) -> ok. |
774 |
|
apply_aff_users_transaction(HostType, RoomID, AffUsersChanged, JoiningUsers) -> |
775 |
361 |
lists:foreach( |
776 |
|
fun({{UserU, UserS}, none}) -> |
777 |
313 |
{updated, _} = delete_aff(HostType, RoomID, UserU, UserS); |
778 |
|
({{UserU, UserS} = UserUS, Aff}) -> |
779 |
115 |
case lists:member(UserUS, JoiningUsers) of |
780 |
|
true -> |
781 |
56 |
{updated, _} = insert_aff(HostType, RoomID, UserU, UserS, Aff); |
782 |
|
false -> |
783 |
59 |
{updated, _} = update_aff(HostType, RoomID, UserU, UserS, Aff) |
784 |
|
end |
785 |
|
end, AffUsersChanged). |
786 |
|
|
787 |
|
%% ------------------------ Common ------------------------ |
788 |
|
|
789 |
|
-spec room_us_to_host_type(jid:simple_bare_jid()) -> mongooseim:host_type(). |
790 |
|
room_us_to_host_type({_, RoomS}) -> |
791 |
29 |
muc_server_to_host_type(RoomS). |
792 |
|
|
793 |
|
-spec muc_server_to_host_type(jid:lserver()) -> mongooseim:host_type(). |
794 |
|
muc_server_to_host_type(MUCServer) -> |
795 |
29 |
mod_muc_light_utils:muc_host_to_host_type(MUCServer). |