Skip to content

Commit a3a2e7b

Browse files
committed
Add sql backend for mod_auth_fast module
1 parent 22d3782 commit a3a2e7b

6 files changed

Lines changed: 199 additions & 0 deletions

File tree

src/mod_auth_fast_sql.erl

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
%%%-------------------------------------------------------------------
2+
%%% File : mod_auth_fast_sql.erl
3+
%%% Author : Pawel Chmielowski <pawel@process-one.net>
4+
%%% Created : 1 Dec 2024 by Pawel Chmielowski <pawel@process-one.net>
5+
%%%
6+
%%%
7+
%%% ejabberd, Copyright (C) 2002-2026 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_auth_fast_sql).
26+
27+
-behaviour(mod_auth_fast).
28+
29+
%% API
30+
-export([init/2]).
31+
-export([get_tokens/3, del_token/4, del_tokens/2, set_token/6, rotate_token/3]).
32+
-export([sql_schemas/0]).
33+
34+
-include_lib("xmpp/include/xmpp.hrl").
35+
36+
-include("ejabberd_sql_pt.hrl").
37+
-include("logger.hrl").
38+
39+
40+
%%%===================================================================
41+
%%% API
42+
%%%===================================================================
43+
init(Host, _Opts) ->
44+
ejabberd_sql_schema:update_schema(Host, ?MODULE, sql_schemas()),
45+
ok.
46+
47+
48+
sql_schemas() ->
49+
[#sql_schema{
50+
version = 1,
51+
tables =
52+
[#sql_table{
53+
name = <<"auth_fast_tokens">>,
54+
columns =
55+
[#sql_column{name = <<"username">>, type = text},
56+
#sql_column{name = <<"server_host">>, type = text},
57+
#sql_column{name = <<"ua">>, type = text},
58+
#sql_column{name = <<"type">>, type = {char, 1}},
59+
#sql_column{name = <<"token">>, type = text},
60+
#sql_column{name = <<"created_at">>, type = timestamp, default = true},
61+
#sql_column{name = <<"expires">>, type = timestamp}],
62+
indices = [#sql_index{
63+
columns = [<<"server_host">>, <<"username">>, <<"ua">>, <<"type">>],
64+
unique = true
65+
}]
66+
}]
67+
}].
68+
69+
70+
-spec get_tokens(binary(), binary(), binary()) ->
71+
[{current | next, binary(), non_neg_integer()}].
72+
get_tokens(LServer, LUser, UA) ->
73+
Now = calendar:now_to_datetime(erlang:timestamp()),
74+
UAs = base64:encode(UA),
75+
F = fun() ->
76+
case ejabberd_sql:sql_query_t(?SQL("select @(type)s, @(token)s, @(created_at)t, @(expires)t from auth_fast_tokens where "
77+
"username=%(LUser)s and ua=%(UAs)s and %(LServer)H")) of
78+
{selected, Entries} ->
79+
lists:filtermap(
80+
fun({<<"c">>, _Token, _Created, Expires}) when Expires < Now ->
81+
ejabberd_sql:sql_query_t(?SQL("delete from auth_fast_tokens where "
82+
"username=%(LUser)s and ua=%(UAs)s and type='c' and %(LServer)H")),
83+
false;
84+
({<<"c">>, Token, Created, _Expires}) ->
85+
CreatedTS = system_time_seconds_from_datetime(Created),
86+
{true, {current, Token, CreatedTS}};
87+
({<<"n">>, _Token, _Created, Expires}) when Expires < Now ->
88+
ejabberd_sql:sql_query_t(?SQL("delete from auth_fast_tokens where "
89+
"username=%(LUser)s and ua=%(UAs)s and type='n' and %(LServer)H")),
90+
false;
91+
({<<"n">>, Token, Created, _Expires}) ->
92+
CreatedTS = system_time_seconds_from_datetime(Created),
93+
{true, {next, Token, CreatedTS}};
94+
(_) ->
95+
false
96+
end,
97+
Entries);
98+
_ -> []
99+
end
100+
end,
101+
102+
case ejabberd_sql:sql_transaction(LServer, F) of
103+
{atomic, Ret} ->
104+
Ret;
105+
_ ->
106+
[]
107+
end.
108+
109+
110+
-spec rotate_token(binary(), binary(), binary()) ->
111+
ok | {error, atom()}.
112+
rotate_token(LServer, LUser, UA) ->
113+
UAs = base64:encode(UA),
114+
F = fun() ->
115+
case ejabberd_sql:sql_query_t(?SQL("select @(1)d from auth_fast_tokens where "
116+
"username=%(LUser)s and ua=%(UAs)s and type='n' and %(LServer)H")) of
117+
{selected, [_]} ->
118+
ejabberd_sql:sql_query_t(?SQL("delete from auth_fast_tokens where "
119+
"username=%(LUser)s and ua=%(UAs)s and type='c' and %(LServer)H")),
120+
ejabberd_sql:sql_query_t(?SQL("update auth_fast_tokens set type='c' where "
121+
"username=%(LUser)s and ua=%(UAs)s and type='n' and %(LServer)H"));
122+
_ ->
123+
ok
124+
end
125+
end,
126+
case ejabberd_sql:sql_transaction(LServer, F) of
127+
{atomic, _} ->
128+
ok;
129+
_ ->
130+
{error, db_error}
131+
end.
132+
133+
134+
-spec del_token(binary(), binary(), binary(), current | next) ->
135+
ok | {error, atom()}.
136+
del_token(LServer, LUser, UA, Type) ->
137+
UAs = base64:encode(UA),
138+
TypeS = case Type of
139+
current -> <<"c">>;
140+
_ -> <<"n">>
141+
end,
142+
case ejabberd_sql:sql_query(LServer,
143+
?SQL("delete from auth_fast_tokens where "
144+
"username=%(LUser)s and ua=%(UAs)s and type=%(TypeS)s and %(LServer)H")) of
145+
{updated, _} ->
146+
ok;
147+
_ ->
148+
{error, db_error}
149+
end.
150+
151+
152+
-spec del_tokens(binary(), binary()) -> ok | {error, atom()}.
153+
del_tokens(LServer, LUser) ->
154+
case ejabberd_sql:sql_query(LServer,
155+
?SQL("delete from auth_fast_tokens where "
156+
"username=%(LUser)s and %(LServer)H")) of
157+
{updated, _} ->
158+
ok;
159+
_ ->
160+
{error, db_error}
161+
end.
162+
163+
164+
-spec set_token(binary(), binary(), binary(), current | next, binary(), non_neg_integer()) ->
165+
ok | {error, atom()}.
166+
set_token(LServer, LUser, UA, Type, Token, Expires) ->
167+
UAs = base64:encode(UA),
168+
TypeS = case Type of
169+
current -> <<"c">>;
170+
_ -> <<"n">>
171+
end,
172+
ExpiresT = calendar:now_to_datetime(misc:usec_to_now(Expires * 1000000)),
173+
case ?SQL_UPSERT(
174+
LServer,
175+
"auth_fast_tokens",
176+
["!username=%(LUser)s",
177+
"!server_host=%(LServer)s",
178+
"!ua=%(UAs)s",
179+
"!type=%(TypeS)s",
180+
"token=%(Token)s",
181+
"expires=%(ExpiresT)t"]) of
182+
ok ->
183+
ok;
184+
_ ->
185+
{error, db_error}
186+
end.
187+
188+
189+
system_time_seconds_from_datetime(DateTime) ->
190+
calendar:datetime_to_gregorian_seconds(DateTime) - 719528 * 86400.

test/ejabberd_SUITE.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ db_tests(DB) ->
470470
[test_register,
471471
legacy_auth_tests(),
472472
auth_plain,
473+
auth_sasl2,
473474
auth_md5,
474475
presence_broadcast,
475476
last,

test/ejabberd_SUITE_data/ejabberd.mssql.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ define_macro:
6464
mod_stream_mgmt:
6565
resume_timeout: 3
6666
mod_legacy_auth: []
67+
mod_auth_fast:
68+
db_type: sql
6769
mod_register:
6870
welcome_message:
6971
subject: "Welcome!"

test/ejabberd_SUITE_data/ejabberd.mysql.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ define_macro:
6565
mod_stream_mgmt:
6666
resume_timeout: 3
6767
mod_legacy_auth: []
68+
mod_auth_fast:
69+
db_type: sql
6870
mod_register:
6971
welcome_message:
7072
subject: "Welcome!"

test/ejabberd_SUITE_data/ejabberd.pgsql.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ define_macro:
6565
mod_stream_mgmt:
6666
resume_timeout: 3
6767
mod_legacy_auth: []
68+
mod_auth_fast:
69+
db_type: sql
6870
mod_register:
6971
welcome_message:
7072
subject: "Welcome!"

test/ejabberd_SUITE_data/ejabberd.sqlite.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ define_macro:
6262
mod_stream_mgmt:
6363
resume_timeout: 3
6464
mod_legacy_auth: []
65+
mod_auth_fast:
66+
db_type: sql
6567
mod_register:
6668
welcome_message:
6769
subject: "Welcome!"

0 commit comments

Comments
 (0)