• 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

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

26
-module(mod_push_sql).
27
-behaviour(mod_push).
28

29
%% API
30
-export([init/2, store_session/6, lookup_session/4, lookup_session/3,
31
         lookup_sessions/3, lookup_sessions/2, lookup_sessions/1,
32
         delete_session/3, delete_old_sessions/2, export/1]).
33
-export([sql_schemas/0]).
34

35
-include_lib("xmpp/include/xmpp.hrl").
36
-include("logger.hrl").
37
-include("ejabberd_sql_pt.hrl").
38
-include("mod_push.hrl").
39

40
%%%===================================================================
41
%%% API
42
%%%===================================================================
43
init(Host, _Opts) ->
UNCOV
44
    ejabberd_sql_schema:update_schema(Host, ?MODULE, sql_schemas()),
6✔
UNCOV
45
    ok.
6✔
46

47
sql_schemas() ->
UNCOV
48
    [#sql_schema{
6✔
49
        version = 1,
50
        tables =
51
            [#sql_table{
52
                name = <<"push_session">>,
53
                columns =
54
                    [#sql_column{name = <<"username">>, type = text},
55
                     #sql_column{name = <<"server_host">>, type = text},
56
                     #sql_column{name = <<"timestamp">>, type = bigint},
57
                     #sql_column{name = <<"service">>, type = text},
58
                     #sql_column{name = <<"node">>, type = text},
59
                     #sql_column{name = <<"xml">>, type = text}],
60
                indices = [#sql_index{
61
                              columns = [<<"server_host">>, <<"username">>,
62
                                         <<"timestamp">>],
63
                              unique = true},
64
                           #sql_index{
65
                              columns = [<<"server_host">>, <<"username">>,
66
                                         <<"service">>, <<"node">>],
67
                              unique = true}]}]}].
68

69
store_session(LUser, LServer, NowTS, PushJID, Node, XData) ->
UNCOV
70
    XML = encode_xdata(XData),
12✔
UNCOV
71
    TS = misc:now_to_usec(NowTS),
12✔
UNCOV
72
    PushLJID = jid:tolower(PushJID),
12✔
UNCOV
73
    Service = jid:encode(PushLJID),
12✔
UNCOV
74
    MaxSessions = ejabberd_sm:get_max_user_sessions(LUser, LServer),
12✔
UNCOV
75
    enforce_max_sessions(LUser, LServer, MaxSessions),
12✔
UNCOV
76
    case ?SQL_UPSERT(LServer, "push_session",
12✔
77
                     ["!username=%(LUser)s",
78
                      "!server_host=%(LServer)s",
79
                      "timestamp=%(TS)d",
80
                      "!service=%(Service)s",
81
                      "!node=%(Node)s",
82
                      "xml=%(XML)s"]) of
83
        ok ->
UNCOV
84
            {ok, {NowTS, PushLJID, Node, XData}};
12✔
85
        _Err ->
86
            {error, db_failure}
×
87
    end.
88

89
lookup_session(LUser, LServer, PushJID, Node) ->
UNCOV
90
    PushLJID = jid:tolower(PushJID),
18✔
UNCOV
91
    Service = jid:encode(PushLJID),
18✔
UNCOV
92
    case ejabberd_sql:sql_query(
18✔
93
           LServer,
UNCOV
94
           ?SQL("select @(timestamp)d, @(xml)s from push_session "
18✔
95
                "where username=%(LUser)s and %(LServer)H "
96
                "and service=%(Service)s "
97
                "and node=%(Node)s")) of
98
        {selected, [{TS, XML}]} ->
UNCOV
99
            NowTS = misc:usec_to_now(TS),
12✔
UNCOV
100
            XData = decode_xdata(XML, LUser, LServer),
12✔
UNCOV
101
            {ok, {NowTS, PushLJID, Node, XData}};
12✔
102
        {selected, []} ->
UNCOV
103
            {error, notfound};
6✔
104
        _Err ->
105
            {error, db_failure}
×
106
    end.
107

108
lookup_session(LUser, LServer, NowTS) ->
109
    TS = misc:now_to_usec(NowTS),
×
110
    case ejabberd_sql:sql_query(
×
111
           LServer,
112
           ?SQL("select @(service)s, @(node)s, @(xml)s "
×
113
                "from push_session where username=%(LUser)s and %(LServer)H "
114
                "and timestamp=%(TS)d")) of
115
        {selected, [{Service, Node, XML}]} ->
116
            PushLJID = jid:tolower(jid:decode(Service)),
×
117
            XData = decode_xdata(XML, LUser, LServer),
×
118
            {ok, {NowTS, PushLJID, Node, XData}};
×
119
        {selected, []} ->
120
            {error, notfound};
×
121
        _Err ->
122
            {error, db_failure}
×
123
    end.
124

125
lookup_sessions(LUser, LServer, PushJID) ->
126
    PushLJID = jid:tolower(PushJID),
×
127
    Service = jid:encode(PushLJID),
×
128
    case ejabberd_sql:sql_query(
×
129
           LServer,
130
           ?SQL("select @(timestamp)d, @(xml)s, @(node)s from push_session "
×
131
                "where username=%(LUser)s and %(LServer)H "
132
                "and service=%(Service)s")) of
133
        {selected, Rows} ->
134
            {ok, lists:map(
×
135
                   fun({TS, XML, Node}) ->
136
                           NowTS = misc:usec_to_now(TS),
×
137
                           XData = decode_xdata(XML, LUser, LServer),
×
138
                           {NowTS, PushLJID, Node, XData}
×
139
                   end, Rows)};
140
        _Err ->
141
            {error, db_failure}
×
142
    end.
143

144
lookup_sessions(LUser, LServer) ->
UNCOV
145
    case ejabberd_sql:sql_query(
54✔
146
           LServer,
UNCOV
147
           ?SQL("select @(timestamp)d, @(xml)s, @(node)s, @(service)s "
54✔
148
                "from push_session "
149
                "where username=%(LUser)s and %(LServer)H")) of
150
        {selected, Rows} ->
UNCOV
151
            {ok, lists:map(
54✔
152
                   fun({TS, XML, Node, Service}) ->
UNCOV
153
                           NowTS = misc:usec_to_now(TS),
6✔
UNCOV
154
                           XData = decode_xdata(XML, LUser, LServer),
6✔
UNCOV
155
                           PushLJID = jid:tolower(jid:decode(Service)),
6✔
UNCOV
156
                           {NowTS, PushLJID,Node, XData}
6✔
157
                   end, Rows)};
158
        _Err ->
159
            {error, db_failure}
×
160
    end.
161

162
lookup_sessions(LServer) ->
163
    case ejabberd_sql:sql_query(
×
164
           LServer,
165
           ?SQL("select @(username)s, @(timestamp)d, @(xml)s, "
×
166
                "@(node)s, @(service)s from push_session "
167
                "where %(LServer)H")) of
168
        {selected, Rows} ->
169
            {ok, lists:map(
×
170
                   fun({LUser, TS, XML, Node, Service}) ->
171
                           NowTS = misc:usec_to_now(TS),
×
172
                           XData = decode_xdata(XML, LUser, LServer),
×
173
                           PushLJID = jid:tolower(jid:decode(Service)),
×
174
                           {NowTS, PushLJID, Node, XData}
×
175
                   end, Rows)};
176
        _Err ->
177
            {error, db_failure}
×
178
    end.
179

180
delete_session(LUser, LServer, NowTS) ->
UNCOV
181
    TS = misc:now_to_usec(NowTS),
12✔
UNCOV
182
    case ejabberd_sql:sql_query(
12✔
183
           LServer,
UNCOV
184
           ?SQL("delete from push_session where "
12✔
185
                "username=%(LUser)s and %(LServer)H and timestamp=%(TS)d")) of
186
        {updated, _} ->
UNCOV
187
            ok;
12✔
188
        _Err ->
189
            {error, db_failure}
×
190
    end.
191

192
delete_old_sessions(LServer, Time) ->
193
    TS = misc:now_to_usec(Time),
×
194
    case ejabberd_sql:sql_query(
×
195
           LServer,
196
           ?SQL("delete from push_session where timestamp<%(TS)d "
×
197
                "and %(LServer)H")) of
198
        {updated, _} ->
199
            ok;
×
200
        _Err ->
201
            {error, db_failure}
×
202
    end.
203

204
export(_Server) ->
205
    [{push_session,
×
206
      fun(Host, #push_session{us = {LUser, LServer},
207
                              timestamp = NowTS,
208
                              service = PushLJID,
209
                              node = Node,
210
                              xml = XData})
211
            when LServer == Host ->
212
              TS = misc:now_to_usec(NowTS),
×
213
              Service = jid:encode(PushLJID),
×
214
              XML = encode_xdata(XData),
×
215
              [?SQL("delete from push_session where "
×
216
                    "username=%(LUser)s and %(LServer)H and "
217
                    "timestamp=%(TS)d and "
218
                    "service=%(Service)s and node=%(Node)s and "
219
                    "xml=%(XML)s;"),
220
               ?SQL_INSERT(
×
221
                  "push_session",
222
                  ["username=%(LUser)s",
223
                   "server_host=%(LServer)s",
224
                   "timestamp=%(TS)d",
225
                   "service=%(Service)s",
226
                   "node=%(Node)s",
227
                   "xml=%(XML)s"])];
228
         (_Host, _R) ->
229
              []
×
230
      end}].
231

232
%%%===================================================================
233
%%% Internal functions
234
%%%===================================================================
235
enforce_max_sessions(_LUser, _LServer, infinity) ->
236
    ok;
×
237
enforce_max_sessions(LUser, LServer, MaxSessions) ->
UNCOV
238
    case lookup_sessions(LUser, LServer) of
12✔
239
        {ok, Sessions} when length(Sessions) >= MaxSessions ->
240
            ?INFO_MSG("Disabling old push session(s) of ~ts@~ts",
×
241
                      [LUser, LServer]),
×
242
            Sessions1 = lists:sort(fun({TS1, _, _, _}, {TS2, _, _, _}) ->
×
243
                                           TS1 >= TS2
×
244
                                   end, Sessions),
245
            OldSessions = lists:nthtail(MaxSessions - 1, Sessions1),
×
246
            lists:foreach(fun({TS, _, _, _}) ->
×
247
                                  delete_session(LUser, LServer, TS)
×
248
                          end, OldSessions);
249
        _ ->
UNCOV
250
            ok
12✔
251
    end.
252

253
decode_xdata(<<>>, _LUser, _LServer) ->
254
    undefined;
×
255
decode_xdata(XML, LUser, LServer) ->
UNCOV
256
    case fxml_stream:parse_element(XML) of
18✔
257
        #xmlel{} = El ->
UNCOV
258
            try xmpp:decode(El)
18✔
259
            catch _:{xmpp_codec, Why} ->
260
                    ?ERROR_MSG("Failed to decode ~ts for user ~ts@~ts "
×
261
                               "from table 'push_session': ~ts",
262
                               [XML, LUser, LServer, xmpp:format_error(Why)]),
×
263
                    undefined
×
264
            end;
265
        Err ->
266
            ?ERROR_MSG("Failed to decode ~ts for user ~ts@~ts from "
×
267
                       "table 'push_session': ~p",
268
                       [XML, LUser, LServer, Err]),
×
269
            undefined
×
270
    end.
271

272
encode_xdata(undefined) ->
273
    <<>>;
×
274
encode_xdata(XData) ->
UNCOV
275
    fxml:element_to_binary(xmpp:encode(XData)).
12✔
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

© 2025 Coveralls, Inc