Skip to content

Commit 0d6c069

Browse files
committed
allow roster invite tokens to create account
only if inviter is allowed to issue create account invites always return create account uri with ";register" suffix
1 parent c01f46a commit 0d6c069

File tree

6 files changed

+76
-33
lines changed

6 files changed

+76
-33
lines changed

src/mod_invites.erl

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434

3535
-export([depends/2, mod_doc/0, mod_options/1, mod_opt_type/1, reload/3, start/2, stop/1]).
3636
-export([adhoc_commands/4, adhoc_items/4, c2s_unauthenticated_packet/2, cleanup_expired/0,
37-
expire_tokens/2, gen_invite/1, gen_invite/2, get_invite/2, is_reserved/3,
38-
is_token_valid/2, list_invites/1, remove_user/2, roster_add/2,
37+
create_account_allowed/2, expire_tokens/2, gen_invite/1, gen_invite/2, get_invite/2,
38+
is_reserved/3, is_token_valid/2, list_invites/1, remove_user/2, roster_add/2,
3939
s2s_receive_packet/1, send_presence/3, set_invitee/3, sm_receive_packet/1,
4040
stream_feature_register/2, token_uri/1, xdata_field/3]).
4141

@@ -649,10 +649,12 @@ invite_token(Type, Host, Inviter, AccountName0) ->
649649
account_name = AccountName},
650650
mod_invites_opt:token_expire_seconds(Host)).
651651

652-
token_uri(#invite_token{type = account_only,
652+
token_uri(#invite_token{type = Type,
653653
token = Token,
654654
account_name = AccountName,
655-
inviter = {_User, Host}}) ->
655+
inviter = {_User, Host}})
656+
when Type =:= account_only;
657+
Type =:= account_subscription ->
656658
Invitee =
657659
case AccountName of
658660
<<>> ->
@@ -661,16 +663,20 @@ token_uri(#invite_token{type = account_only,
661663
<<AccountName/binary, "@", Host/binary>>
662664
end,
663665
<<"xmpp:", Invitee/binary, "?register;preauth=", Token/binary>>;
664-
token_uri(#invite_token{type = account_subscription,
665-
token = Token,
666-
inviter = {User, Host}}) ->
667-
Inviter = jid:to_string(jid:make(User, Host)),
668-
<<"xmpp:", Inviter/binary, "?roster;preauth=", Token/binary, ";ibr=y">>;
669666
token_uri(#invite_token{type = roster_only,
670667
token = Token,
671668
inviter = {User, Host}}) ->
669+
IBR = maybe_add_ibr_allowed(User, Host),
672670
Inviter = jid:to_string(jid:make(User, Host)),
673-
<<"xmpp:", Inviter/binary, "?roster;preauth=", Token/binary>>.
671+
<<"xmpp:", Inviter/binary, "?roster;preauth=", Token/binary, IBR/binary>>.
672+
673+
maybe_add_ibr_allowed(User, Host) ->
674+
case create_account_allowed(Host, jid:make(User, Host)) of
675+
ok ->
676+
<<";ibr=y">>;
677+
{error, not_allowed} ->
678+
<<>>
679+
end.
674680

675681
landing_page(Host, Invite) ->
676682
mod_invites_http:landing_page(Host, Invite).

src/mod_invites_http.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ process([?STATIC | StaticFile], #request{host = Host} = Request) ->
8383
end;
8484
process([Token | _] = LocalPath, #request{host = Host, lang = Lang} = Request) ->
8585
?DEBUG("Requested:~n~p", [Request]),
86-
case mod_invites:is_token_valid(Host, Token) of
86+
try mod_invites:is_token_valid(Host, Token) of
8787
true ->
8888
case mod_invites:get_invite(Host, Token) of
8989
#invite_token{type = 'roster_only'} = Invite ->
@@ -93,6 +93,9 @@ process([Token | _] = LocalPath, #request{host = Host, lang = Lang} = Request) -
9393
end;
9494
false ->
9595
?NOT_FOUND(render(Host, Lang, <<"invite_invalid.html">>, ctx(Request)))
96+
catch
97+
_:not_found ->
98+
?NOT_FOUND
9699
end;
97100
process([], _Request) ->
98101
?NOT_FOUND.

src/mod_invites_mnesia.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ is_token_valid(Host, Token, Scope) ->
9797
[#invite_token{}] ->
9898
false;
9999
[] ->
100-
false
100+
throw(not_found)
101101
end.
102102

103103
list_invites(Host) ->

src/mod_invites_register.erl

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,21 +161,33 @@ maybe_create_mutual_subscription(#invite_token{inviter = {User, Server}, invitee
161161

162162
process_token(#{server := Host} = State, Token, #iq{lang = Lang} = IQ) ->
163163
?DEBUG("checking token (~s): ~s", [Host, Token]),
164-
case mod_invites:is_token_valid(Host, Token) of
164+
try mod_invites:is_token_valid(Host, Token) of
165165
true ->
166-
case mod_invites:get_invite(Host, Token) of
167-
#invite_token{type = 'roster_only'} ->
168-
Text = ?T("The token provided is either invalid or expired."),
169-
{State, make_stripped_error(IQ, #preauth{}, xmpp:err_item_not_found(Text, Lang))};
170-
Invite ->
166+
Invite = #invite_token{inviter = {User, Host}} =
167+
mod_invites:get_invite(Host, Token),
168+
case create_account_allowed(User, Host) of
169+
ok ->
171170
NewState = State#{invite => Invite},
172-
{NewState, xmpp:make_iq_result(IQ)}
171+
{NewState, xmpp:make_iq_result(IQ)};
172+
{error, not_allowed} ->
173+
{State, preauth_invalid(IQ, Lang)}
173174
end;
174175
false ->
175-
Text = ?T("The token provided is either invalid or expired."),
176-
{State, make_stripped_error(IQ, #preauth{}, xmpp:err_item_not_found(Text, Lang))}
176+
{State, preauth_invalid(IQ, Lang)}
177+
catch
178+
_:not_found ->
179+
{State, preauth_invalid(IQ, Lang)}
177180
end.
178181

182+
create_account_allowed(<<>>, _Host) ->
183+
ok;
184+
create_account_allowed(User, Host) ->
185+
mod_invites:create_account_allowed(Host, jid:make(User, Host)).
186+
187+
preauth_invalid(IQ, Lang) ->
188+
Text = ?T("The token provided is either invalid or expired."),
189+
make_stripped_error(IQ, #preauth{}, xmpp:err_item_not_found(Text, Lang)).
190+
179191
try_register(Token,
180192
User,
181193
Server,

src/mod_invites_sql.erl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,17 @@ is_token_valid(Host, Token, {User, Host}) ->
143143
ejabberd_sql:sql_query(Host,
144144
?SQL("SELECT @(token)s FROM invite_token WHERE %(Host)H AND token = %(Token)s AND "
145145
"invitee = '' AND expires > now() AND (%(User)s = '' OR username = %(User)s)")),
146-
Rows /= [].
146+
case Rows /= [] of
147+
true ->
148+
true;
149+
false ->
150+
case get_invite(Host, Token) of
151+
{error, not_found} ->
152+
throw(not_found);
153+
_ ->
154+
false
155+
end
156+
end.
147157

148158
list_invites(Host) ->
149159
{selected, Rows} =

test/invites_tests.erl

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,19 +189,21 @@ adhoc_command_create_account(Config) ->
189189
re:run(xdata_field(<<"uri">>, ResultXDataFields2),
190190
<<"xmpp:foobar@", Server/binary, "\\?register;preauth=(.+)">>)),
191191
ResultXDataFields3 = test_create_account(Config, <<>>, <<"1">>),
192-
Inviter = ?config(user, Config),
193-
?match({match, [Inviter, _]},
192+
?match({match, _},
194193
re:run(xdata_field(<<"uri">>, ResultXDataFields3),
195-
<<"xmpp:(.+)", "@", Server/binary, "\\?roster;preauth=([a-zA-Z0-9]+);ibr=y">>,
194+
<<"xmpp:", Server/binary, "\\?register;preauth=([a-zA-Z0-9]+)">>,
196195
[{capture, all_but_first, binary}])),
197-
Token = token_from_uri(xdata_field(<<"uri">>, ResultXDataFields3, <<>>)),
196+
Token3 = token_from_uri(xdata_field(<<"uri">>, ResultXDataFields3, <<>>)),
198197
#invite_token{account_name = <<>>, type = account_subscription} =
199-
mod_invites:get_invite(Server, Token),
198+
mod_invites:get_invite(Server, Token3),
200199
ResultXDataFields4 = test_create_account(Config, <<"foobar">>, <<"1">>),
201-
?match({match, [Inviter, _]},
200+
?match({match, _},
202201
re:run(xdata_field(<<"uri">>, ResultXDataFields4),
203-
<<"xmpp:(.+)", "@", Server/binary, "\\?roster;preauth=([a-zA-Z0-9]+);ibr=y">>,
202+
<<"xmpp:foobar@", Server/binary, "\\?register;preauth=([a-zA-Z0-9]+)">>,
204203
[{capture, all_but_first, binary}])),
204+
Token4 = token_from_uri(xdata_field(<<"uri">>, ResultXDataFields4, <<>>)),
205+
#invite_token{account_name = <<"foobar">>, type = account_subscription} =
206+
mod_invites:get_invite(Server, Token4),
205207
update_module_opts(Server, mod_invites, OldOpts),
206208
User = jid:nodeprep(?config(user, Config)),
207209
mod_invites:remove_user(User, Server),
@@ -217,7 +219,12 @@ token_valid(Config) ->
217219
#invite_token{token = AccountToken} =
218220
create_account_invite(Server, Inviter),
219221
?match(true, mod_invites:is_token_valid(Server, AccountToken, Inviter)),
220-
?match(false, mod_invites:is_token_valid(Server, <<"madeUptoken">>)),
222+
try mod_invites:is_token_valid(Server, <<"madeUptoken">>) of
223+
break -> broken
224+
catch
225+
_:E ->
226+
?match(not_found, E)
227+
end,
221228
?match(false,
222229
mod_invites:is_token_valid(Server, AccountToken, {<<"someoneElse">>, Server})),
223230
mod_invites:expire_tokens(<<"foo">>, Server),
@@ -386,15 +393,19 @@ ibr_subscription(Config0) ->
386393
NewAccount = <<"new_friend">>,
387394
NewAccountJID = jid:make(NewAccount, Server),
388395
gen_mod:stop_module_keep_config(Server, mod_vcard_xupdate),
396+
OldOpts = gen_mod:get_module_opts(Server, mod_invites),
397+
NewOpts = gen_mod:set_opt(access_create_account, account_invite, OldOpts),
398+
update_module_opts(Server, mod_invites, NewOpts),
399+
389400
self_presence(Config0, available),
390401

391402
#invite_token{token = Token} =
392403
mod_invites:create_account_invite(Server, {User, Server}, NewAccount, true),
393404

394405
Config1 = set_opts([{user, NewAccount},
395-
{password, <<"mySecret">>},
396-
{resource, <<"invite_tests">>},
397-
{receiver, undefined}], Config0),
406+
{password, <<"mySecret">>},
407+
{resource, <<"invite_tests">>},
408+
{receiver, undefined}], Config0),
398409
Config = connect(Config1),
399410

400411
?match(#iq{type = result}, send_pars(Config, Token)),
@@ -429,6 +440,7 @@ ibr_subscription(Config0) ->
429440
mod_roster:del_roster(User, Server, jid:tolower(NewAccountJID)),
430441
mod_roster:del_roster(NewAccount, Server, jid:tolower(UserJID)),
431442

443+
update_module_opts(Server, mod_invites, OldOpts),
432444
disconnect(Config0),
433445
disconnect(Config).
434446

0 commit comments

Comments
 (0)