• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

processone / ejabberd / 1246

10 Dec 2025 12:12PM UTC coverage: 33.632% (+0.1%) from 33.528%
1246

push

github

badlop
ejabberd_web_admin: Show menu system only when can view vhosts

0 of 5 new or added lines in 1 file covered. (0.0%)

11084 existing lines in 174 files now uncovered.

15552 of 46242 relevant lines covered (33.63%)

1078.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

45.5
/src/mod_roster_sql.erl
1
%%%-------------------------------------------------------------------
2
%%% File    : mod_roster_sql.erl
3
%%% Author  : Evgeny Khramtsov <ekhramtsov@process-one.net>
4
%%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
5
%%%
6
%%%
7
%%% ejabberd, Copyright (C) 2002-2025   ProcessOne
8
%%%
9
%%% This program is free software; you can redistribute it and/or
10
%%% modify it under the terms of the GNU General Public License as
11
%%% published by the Free Software Foundation; either version 2 of the
12
%%% License, or (at your option) any later version.
13
%%%
14
%%% This program is distributed in the hope that it will be useful,
15
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
16
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
%%% General Public License for more details.
18
%%%
19
%%% You should have received a copy of the GNU General Public License along
20
%%% with this program; if not, write to the Free Software Foundation, Inc.,
21
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
%%%
23
%%%----------------------------------------------------------------------
24

25
-module(mod_roster_sql).
26

27

28
-behaviour(mod_roster).
29
-behaviour(ejabberd_db_serialize).
30

31
%% API
32
-export([init/2, read_roster_version/2, write_roster_version/4,
33
         get_roster/2, get_roster_item/3, roster_subscribe/4,
34
         read_subscription_and_groups/3, remove_user/2,
35
         update_roster/4, del_roster/3, transaction/2,
36
         process_rosteritems/5,
37
         import/3, export/1, raw_to_record/2]).
38
-export([sql_schemas/0]).
39
-export([serialize/3, deserialize_start/1, deserialize/2]).
40

41
-include("mod_roster.hrl").
42
-include("ejabberd_sql_pt.hrl").
43
-include("logger.hrl").
44
-include_lib("xmpp/include/jid.hrl").
45
-include("ejabberd_db_serialize.hrl").
46

47
%%%===================================================================
48
%%% API
49
%%%===================================================================
50
init(Host, _Opts) ->
UNCOV
51
    ejabberd_sql_schema:update_schema(Host, ?MODULE, sql_schemas()),
6✔
UNCOV
52
    ok.
6✔
53

54
sql_schemas() ->
UNCOV
55
    [#sql_schema{
6✔
56
        version = 1,
57
        tables =
58
            [#sql_table{
59
                name = <<"rosterusers">>,
60
                columns =
61
                    [#sql_column{name = <<"username">>, type = text},
62
                     #sql_column{name = <<"server_host">>, type = text},
63
                     #sql_column{name = <<"jid">>, type = text},
64
                     #sql_column{name = <<"nick">>, type = text},
65
                     #sql_column{name = <<"subscription">>, type = {char, 1}},
66
                     #sql_column{name = <<"ask">>, type = {char, 1}},
67
                     #sql_column{name = <<"askmessage">>, type = text},
68
                     #sql_column{name = <<"server">>, type = {char, 1}},
69
                     #sql_column{name = <<"subscribe">>, type = text},
70
                     #sql_column{name = <<"type">>, type = text},
71
                     #sql_column{name = <<"created_at">>, type = timestamp,
72
                                 default = true}],
73
                indices = [#sql_index{
74
                              columns = [<<"server_host">>, <<"username">>,
75
                                         <<"jid">>],
76
                              unique = true},
77
                           #sql_index{
78
                              columns = [<<"server_host">>, <<"jid">>]}]},
79
             #sql_table{
80
                name = <<"rostergroups">>,
81
                columns =
82
                    [#sql_column{name = <<"username">>, type = text},
83
                     #sql_column{name = <<"server_host">>, type = text},
84
                     #sql_column{name = <<"jid">>, type = text},
85
                     #sql_column{name = <<"grp">>, type = text}],
86
                indices = [#sql_index{
87
                              columns = [<<"server_host">>, <<"username">>,
88
                                         <<"jid">>]}]},
89
             #sql_table{
90
                name = <<"roster_version">>,
91
                columns =
92
                    [#sql_column{name = <<"username">>, type = text},
93
                     #sql_column{name = <<"server_host">>, type = text},
94
                     #sql_column{name = <<"version">>, type = text}],
95
                indices = [#sql_index{
96
                              columns = [<<"server_host">>, <<"username">>],
97
                              unique = true}]}]}].
98

99
read_roster_version(LUser, LServer) ->
UNCOV
100
    case ejabberd_sql:sql_query(
2,382✔
101
           LServer,
UNCOV
102
           ?SQL("select @(version)s from roster_version"
2,382✔
103
                " where username = %(LUser)s and %(LServer)H")) of
UNCOV
104
        {selected, [{Version}]} -> {ok, Version};
2,382✔
105
        {selected, []} -> error;
×
106
        _ -> {error, db_failure}
×
107
    end.
108

109
write_roster_version(LUser, LServer, InTransaction, Ver) ->
UNCOV
110
    if InTransaction ->
1,074✔
UNCOV
111
            set_roster_version(LUser, LServer, Ver);
1,074✔
112
       true ->
113
            transaction(
×
114
              LServer,
115
              fun () -> set_roster_version(LUser, LServer, Ver) end)
×
116
    end.
117

118
get_roster(LUser, LServer) ->
UNCOV
119
    case ejabberd_sql:sql_query(
2,412✔
120
           LServer,
UNCOV
121
           ?SQL("select @(username)s, @(jid)s, @(nick)s, @(subscription)s, "
2,412✔
122
                "@(ask)s, @(askmessage)s, @(server)s, @(subscribe)s, "
123
                "@(type)s from rosterusers "
124
                "where username=%(LUser)s and %(LServer)H")) of
125
        {selected, Items} when is_list(Items) ->
UNCOV
126
            JIDGroups = case get_roster_jid_groups(LServer, LUser) of
2,412✔
127
                            {selected, JGrps} when is_list(JGrps) ->
UNCOV
128
                                JGrps;
2,412✔
129
                            _ ->
130
                                []
×
131
                        end,
UNCOV
132
            GroupsDict = lists:foldl(fun({J, G}, Acc) ->
2,412✔
UNCOV
133
                                             Gs = maps:get(J, Acc, []),
42✔
UNCOV
134
                                             maps:put(J, [G | Gs], Acc)
42✔
135
                                     end,
136
                                     maps:new(), JIDGroups),
UNCOV
137
            {ok, lists:flatmap(
2,412✔
138
                   fun(I) ->
UNCOV
139
                           case raw_to_record(LServer, I) of
1,590✔
140
                               %% Bad JID in database:
141
                               error -> [];
×
142
                               R ->
UNCOV
143
                                   SJID = jid:encode(R#roster.jid),
1,590✔
UNCOV
144
                                   Groups = maps:get(SJID, GroupsDict, []),
1,590✔
UNCOV
145
                                   [R#roster{groups = Groups}]
1,590✔
146
                           end
147
                   end, Items)};
148
        _ ->
149
            error
×
150
    end.
151

152
roster_subscribe(_LUser, _LServer, _LJID, Item) ->
UNCOV
153
    ItemVals = record_to_row(Item),
804✔
UNCOV
154
    roster_subscribe(ItemVals).
804✔
155

156
transaction(LServer, F) ->
UNCOV
157
    ejabberd_sql:sql_transaction(LServer, F).
2,922✔
158

159
get_roster_item(LUser, LServer, LJID) ->
UNCOV
160
    SJID = jid:encode(LJID),
2,550✔
UNCOV
161
    case get_roster_by_jid(LServer, LUser, SJID) of
2,550✔
162
        {selected, [I]} ->
UNCOV
163
            case raw_to_record(LServer, I) of
1,764✔
164
                error ->
165
                    error;
×
166
                R ->
UNCOV
167
                    Groups = case get_roster_groups(LServer, LUser, SJID) of
1,764✔
168
                                 {selected, JGrps} when is_list(JGrps) ->
UNCOV
169
                                     [JGrp || {JGrp} <- JGrps];
1,764✔
170
                                 _ -> []
×
171
                             end,
UNCOV
172
                    {ok, R#roster{groups = Groups}}
1,764✔
173
            end;
174
        {selected, []} ->
UNCOV
175
            error
786✔
176
    end.
177

178
remove_user(LUser, LServer) ->
UNCOV
179
    transaction(
12✔
180
      LServer,
181
      fun () ->
UNCOV
182
              ejabberd_sql:sql_query_t(
12✔
UNCOV
183
                ?SQL("delete from rosterusers"
12✔
184
                     " where username=%(LUser)s and %(LServer)H")),
UNCOV
185
              ejabberd_sql:sql_query_t(
12✔
UNCOV
186
                ?SQL("delete from rostergroups"
12✔
187
                     " where username=%(LUser)s and %(LServer)H"))
188
      end),
UNCOV
189
    ok.
12✔
190

191
update_roster(LUser, LServer, LJID, Item) ->
UNCOV
192
    SJID = jid:encode(LJID),
198✔
UNCOV
193
    ItemVals = record_to_row(Item),
198✔
UNCOV
194
    ItemGroups = Item#roster.groups,
198✔
UNCOV
195
    roster_subscribe(ItemVals),
198✔
UNCOV
196
    ejabberd_sql:sql_query_t(
198✔
UNCOV
197
      ?SQL("delete from rostergroups"
198✔
198
           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")),
UNCOV
199
    lists:foreach(
198✔
200
      fun(ItemGroup) ->
UNCOV
201
              ejabberd_sql:sql_query_t(
18✔
UNCOV
202
                ?SQL_INSERT(
18✔
203
                   "rostergroups",
204
                   ["username=%(LUser)s",
205
                    "server_host=%(LServer)s",
206
                    "jid=%(SJID)s",
207
                    "grp=%(ItemGroup)s"]))
208
      end,
209
      ItemGroups).
210

211
del_roster(LUser, LServer, LJID) ->
UNCOV
212
    SJID = jid:encode(LJID),
516✔
UNCOV
213
    ejabberd_sql:sql_query_t(
516✔
UNCOV
214
      ?SQL("delete from rosterusers"
516✔
215
           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")),
UNCOV
216
    ejabberd_sql:sql_query_t(
516✔
UNCOV
217
      ?SQL("delete from rostergroups"
516✔
218
           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
219

220
read_subscription_and_groups(LUser, LServer, LJID) ->
221
    SJID = jid:encode(LJID),
×
222
    case get_subscription(LServer, LUser, SJID) of
×
223
        {selected, [{SSubscription, SAsk}]} ->
224
            Subscription = decode_subscription(LUser, LServer, SSubscription),
×
225
            Ask = decode_ask(LUser, LServer, SAsk),
×
226
            Groups = case get_rostergroup_by_jid(LServer, LUser, SJID) of
×
227
                         {selected, JGrps} when is_list(JGrps) ->
228
                             [JGrp || {JGrp} <- JGrps];
×
229
                         _ -> []
×
230
                     end,
231
            {ok, {Subscription, Ask, Groups}};
×
232
        _ ->
233
            error
×
234
    end.
235

236
export(_Server) ->
237
    [{roster,
×
238
      fun(Host, #roster{usj = {_LUser, LServer, _LJID}} = R)
239
            when LServer == Host ->
240
              ItemVals = record_to_row(R),
×
241
              ItemGroups = R#roster.groups,
×
242
              update_roster_sql(ItemVals, ItemGroups);
×
243
        (_Host, _R) ->
244
              []
×
245
      end},
246
     {roster_version,
247
      fun(Host, #roster_version{us = {LUser, LServer}, version = Ver})
248
            when LServer == Host ->
249
              [?SQL("delete from roster_version"
×
250
                    " where username=%(LUser)s and %(LServer)H;"),
251
               ?SQL_INSERT(
×
252
                  "roster_version",
253
                  ["username=%(LUser)s",
254
                   "server_host=%(LServer)s",
255
                   "version=%(Ver)s"])];
256
         (_Host, _R) ->
257
              []
×
258
      end}].
259

260
import(_, _, _) ->
261
    ok.
×
262

263
%%%===================================================================
264
%%% Internal functions
265
%%%===================================================================
266
set_roster_version(LUser, LServer, Version) ->
UNCOV
267
    ?SQL_UPSERT_T(
1,074✔
268
       "roster_version",
269
       ["!username=%(LUser)s",
270
        "!server_host=%(LServer)s",
271
        "version=%(Version)s"]).
272

273
get_roster_jid_groups(LServer, LUser) ->
UNCOV
274
    ejabberd_sql:sql_query(
2,412✔
275
      LServer,
UNCOV
276
      ?SQL("select @(jid)s, @(grp)s from rostergroups where "
2,412✔
277
           "username=%(LUser)s and %(LServer)H")).
278

279
get_roster_groups(LServer, LUser, SJID) ->
UNCOV
280
    ejabberd_sql:sql_query_t(
1,764✔
UNCOV
281
      ?SQL("select @(grp)s from rostergroups"
1,764✔
282
           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
283

284
roster_subscribe({LUser, LServer, SJID, Name, SSubscription, SAsk, AskMessage}) ->
UNCOV
285
    ?SQL_UPSERT_T(
1,002✔
286
       "rosterusers",
287
       ["!username=%(LUser)s",
288
        "!server_host=%(LServer)s",
289
        "!jid=%(SJID)s",
290
        "nick=%(Name)s",
291
        "subscription=%(SSubscription)s",
292
        "ask=%(SAsk)s",
293
        "askmessage=%(AskMessage)s",
294
        "server='N'",
295
        "subscribe=''",
296
        "type='item'"]).
297

298
get_roster_by_jid(LServer, LUser, SJID) ->
UNCOV
299
    ejabberd_sql:sql_query_t(
2,550✔
UNCOV
300
      ?SQL("select @(username)s, @(jid)s, @(nick)s, @(subscription)s,"
2,550✔
301
           " @(ask)s, @(askmessage)s, @(server)s, @(subscribe)s,"
302
           " @(type)s from rosterusers"
303
           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
304

305
get_rostergroup_by_jid(LServer, LUser, SJID) ->
306
    ejabberd_sql:sql_query(
×
307
      LServer,
308
      ?SQL("select @(grp)s from rostergroups"
×
309
           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
310

311
get_subscription(LServer, LUser, SJID) ->
312
    ejabberd_sql:sql_query(
×
313
      LServer,
314
      ?SQL("select @(subscription)s, @(ask)s from rosterusers "
×
315
           "where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
316

317
update_roster_sql({LUser, LServer, SJID, Name, SSubscription, SAsk, AskMessage},
318
                  ItemGroups) ->
319
    [?SQL("delete from rosterusers where"
×
320
          " username=%(LUser)s and %(LServer)H and jid=%(SJID)s;"),
321
     ?SQL_INSERT(
×
322
        "rosterusers",
323
        ["username=%(LUser)s",
324
         "server_host=%(LServer)s",
325
         "jid=%(SJID)s",
326
         "nick=%(Name)s",
327
         "subscription=%(SSubscription)s",
328
         "ask=%(SAsk)s",
329
         "askmessage=%(AskMessage)s",
330
         "server='N'",
331
         "subscribe=''",
332
         "type='item'"]),
333
     ?SQL("delete from rostergroups where"
×
334
          " username=%(LUser)s and %(LServer)H and jid=%(SJID)s;")]
335
      ++
×
336
      [?SQL_INSERT(
×
337
          "rostergroups",
338
          ["username=%(LUser)s",
339
           "server_host=%(LServer)s",
340
           "jid=%(SJID)s",
341
           "grp=%(ItemGroup)s"])
342
       || ItemGroup <- ItemGroups].
×
343

344
raw_to_record(LServer,
345
              [User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
346
               SServer, SSubscribe, SType]) ->
347
    raw_to_record(LServer,
×
348
                  {User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
349
                   SServer, SSubscribe, SType});
350
raw_to_record(LServer,
351
              {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
352
               SServer, SSubscribe, SType}) ->
UNCOV
353
    raw_to_record(LServer,
3,354✔
354
                  {User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
355
                   SServer, SSubscribe, SType});
356
raw_to_record(LServer,
357
              {User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
358
               _SServer, _SSubscribe, _SType}) ->
UNCOV
359
    try jid:decode(SJID) of
3,354✔
360
      JID ->
UNCOV
361
          LJID = jid:tolower(JID),
3,354✔
UNCOV
362
          Subscription = decode_subscription(User, LServer, SSubscription),
3,354✔
UNCOV
363
          Ask = decode_ask(User, LServer, SAsk),
3,354✔
UNCOV
364
          #roster{usj = {User, LServer, LJID},
3,354✔
365
                  us = {User, LServer}, jid = LJID, name = Nick,
366
                  subscription = Subscription, ask = Ask,
367
                  askmessage = SAskMessage}
368
    catch _:{bad_jid, _} ->
369
            ?ERROR_MSG("~ts", [format_row_error(User, LServer, {jid, SJID})]),
×
370
            error
×
371
    end.
372

373
record_to_row(
374
  #roster{us = {LUser, LServer},
375
          jid = JID, name = Name, subscription = Subscription,
376
          ask = Ask, askmessage = AskMessage}) ->
UNCOV
377
    SJID = jid:encode(jid:tolower(JID)),
1,002✔
UNCOV
378
    {LUser,
1,002✔
379
     LServer,
380
     SJID,
381
     Name,
382
     encode_subscription(Subscription),
383
     encode_ask(Ask),
384
     AskMessage}.
385

386

387
encode_subscription(Subscription) ->
UNCOV
388
    case Subscription of
1,002✔
389
        any -> <<"_">>;
×
UNCOV
390
        both -> <<"B">>;
204✔
UNCOV
391
        to -> <<"T">>;
78✔
UNCOV
392
        from -> <<"F">>;
138✔
UNCOV
393
        none -> <<"N">>
582✔
394
    end.
395

396

397
encode_ask(Ask) ->
UNCOV
398
    case Ask of
1,002✔
399
        any -> <<"_">>;
×
400
        subscribe -> <<"S">>;
×
401
        unsubscribe -> <<"U">>;
×
UNCOV
402
        both -> <<"B">>;
30✔
UNCOV
403
        out -> <<"O">>;
198✔
UNCOV
404
        in -> <<"I">>;
156✔
UNCOV
405
        none -> <<"N">>
618✔
406
    end.
407

408

409

410
decode_subscription(User, Server, S) ->
UNCOV
411
    case S of
3,354✔
UNCOV
412
        <<"B">> -> both;
444✔
UNCOV
413
        <<"T">> -> to;
252✔
UNCOV
414
        <<"F">> -> from;
348✔
UNCOV
415
        <<"N">> -> none;
2,310✔
416
        <<"">> -> none;
×
417
        _ ->
418
            ?ERROR_MSG("~ts", [format_row_error(User, Server, {subscription, S})]),
×
419
            none
×
420
    end.
421

422
decode_ask(User, Server, A) ->
UNCOV
423
    case A of
3,354✔
424
        <<"S">> -> subscribe;
×
425
        <<"U">> -> unsubscribe;
×
UNCOV
426
        <<"B">> -> both;
108✔
UNCOV
427
        <<"O">> -> out;
720✔
UNCOV
428
        <<"I">> -> in;
708✔
UNCOV
429
        <<"N">> -> none;
1,818✔
430
        <<"">> -> none;
×
431
        _ ->
432
            ?ERROR_MSG("~ts", [format_row_error(User, Server, {ask, A})]),
×
433
            none
×
434
    end.
435

436
format_row_error(User, Server, Why) ->
437
    [case Why of
×
438
         {jid, JID} -> ["Malformed 'jid' field with value '", JID, "'"];
×
439
         {subscription, Sub} -> ["Malformed 'subscription' field with value '", Sub, "'"];
×
440
         {ask, Ask} -> ["Malformed 'ask' field with value '", Ask, "'"]
×
441
     end,
442
     " detected for ", User, "@", Server, " in table 'rosterusers'"].
443

444
process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
445
    process_rosteritems_sql(ActionS, list_to_atom(SubsS), list_to_atom(AsksS),
×
446
        list_to_binary(UsersS), list_to_binary(ContactsS)).
447

448
process_rosteritems_sql(ActionS, Subscription, Ask, SLocalJID, SJID) ->
449
    [LUser, LServer] = binary:split(SLocalJID, <<"@">>),
×
450
    SSubscription = encode_subscription(Subscription),
×
451
    SAsk = encode_ask(Ask),
×
452
    {selected, List} = ejabberd_sql:sql_query(
×
453
      LServer,
454
      ?SQL("select @(username)s, @(jid)s from rosterusers "
×
455
           "where username LIKE %(LUser)s"
456
           " and %(LServer)H"
457
           " and jid LIKE %(SJID)s"
458
           " and subscription LIKE %(SSubscription)s"
459
           " and ask LIKE %(SAsk)s")),
460
    case ActionS of
×
461
        "delete" -> [mod_roster:del_roster(User, LServer, jid:tolower(jid:decode(Contact))) || {User, Contact} <- List];
×
462
        "list" -> ok
×
463
    end,
464
    List.
×
465

466

467
serialize(LServer, BatchSize, Last) ->
468
    Offset = case Last of
×
469
                 undefined -> 0;
×
470
                 _ -> Last
×
471
             end,
472
    case ejabberd_sql:sql_query(
×
473
           LServer,
474
           ?SQL("select distinct @(username)s from rosterusers "
×
475
                "where %(LServer)H "
476
                "order by username "
477
                "limit %(BatchSize)d offset %(Offset)d")) of
478
        {selected, Rows} ->
479
            Data = lists:foldl(
×
480
                     fun(_, {error, _} = Err) ->
481
                             Err;
×
482
                        ({Username}, Res) ->
483
                             case get_roster(Username, LServer) of
×
484
                                 error ->
485
                                     {error, io_lib:format("Error when retrieving roster for ~s@~s", [Username, LServer])};
×
486
                                 {ok, Items} ->
487
                                     Entries = lists:map(
×
488
                                                 fun(#roster{jid = Jid, name = Name, groups = Groups, ask = Ask, subscription = Sub, askmessage = AskMsg}) ->
489
                                                         {jid:encode(Jid), Name, Groups, Sub, Ask, AskMsg}
×
490
                                                 end,
491
                                                 Items),
492
                                     case read_roster_version(Username, LServer) of
×
493
                                         error ->
494
                                             [#serialize_roster_v1{
×
495
                                                serverhost = LServer,
496
                                                username = Username,
497
                                                entries = Entries
498
                                               } | Res];
499
                                         {ok, Ver} ->
500
                                             [#serialize_roster_v1{
×
501
                                                serverhost = LServer,
502
                                                username = Username,
503
                                                version = Ver,
504
                                                entries = Entries
505
                                               } | Res];
506
                                         _ ->
507
                                             {error, io_lib:format("Error when retrieving roster version for ~s@~s",
×
508
                                                                   [Username, LServer])}
509
                                     end
510
                             end
511
                     end,
512
                     [],
513
                     Rows),
514
            {ok, Data, Offset + length(Rows)};
×
515
        _ ->
516
            {error, io_lib:format("Error when retrieving list of users rosters", [])}
×
517
    end.
518

519

520
deserialize_start(LServer) ->
521
    ejabberd_sql:sql_query(
×
522
      LServer,
523
      ?SQL("delete from rosterusers where %(LServer)H")),
×
524
    ejabberd_sql:sql_query(
×
525
      LServer,
526
      ?SQL("delete from rostergroups where %(LServer)H")),
×
527
    ejabberd_sql:sql_query(
×
528
      LServer,
529
      ?SQL("delete from roster_version where %(LServer)H")).
×
530

531

532
deserialize(LServer, Batch) ->
533
    F = fun() ->
×
534
                lists:foreach(
×
535
                  fun(#serialize_roster_v1{username = Username, version = Version, entries = Entries}) ->
536
                          lists:foreach(
×
537
                            fun({Jid, Name, Groups, Sub, Ask, AskMsg}) ->
538
                                    SSubscription = encode_subscription(Sub),
×
539
                                    SAsk = encode_ask(Ask),
×
540
                                    ejabberd_sql:sql_query_t(?SQL_INSERT(
×
541
                                                               "rosterusers",
542
                                                               ["username=%(Username)s",
543
                                                                "server_host=%(LServer)s",
544
                                                                "jid=%(Jid)s",
545
                                                                "nick=%(Name)s",
546
                                                                "subscription=%(SSubscription)s",
547
                                                                "ask=%(SAsk)s",
548
                                                                "askmessage=%(AskMsg)s",
549
                                                                "server='N'",
550
                                                                "subscribe=''",
551
                                                                "type='item'"])),
552
                                    lists:foreach(
×
553
                                      fun(Group) ->
554
                                              ejabberd_sql:sql_query_t(?SQL_INSERT(
×
555
                                                                         "rostergroups",
556
                                                                         ["username=%(Username)s",
557
                                                                          "server_host=%(LServer)s",
558
                                                                          "jid=%(Jid)s",
559
                                                                          "grp=%(Group)s"]))
560
                                      end,
561
                                      Groups)
562
                            end,
563
                            Entries),
564
                          case Version of
×
565
                              undefined -> ok;
×
566
                              _ ->
567
                                  ejabberd_sql:sql_query_t(?SQL_INSERT(
×
568
                                                             "roster_version",
569
                                                             ["username=%(Username)s",
570
                                                              "server_host=%(LServer)s",
571
                                                              "version=%(Version)s"]))
572
                          end
573
                  end,
574
                  Batch)
575
        end,
576
    case ejabberd_sql:sql_transaction(LServer, F) of
×
577
        {atomic, _} -> ok;
×
578
        _ -> {error, io_lib:format("Error when writing roster data", [])}
×
579
    end.
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc