Files
EventHubBack/test/unit/logic_password_reset_tests.erl
T
aleksey 61816e15b1
CI / test (push) Successful in 7m20s
CI / deploy-ift (push) Successful in 6m9s
CI / e2e-ift (push) Successful in 1m28s
CI / deploy-stage (push) Successful in 2m34s
CI / e2e-stage (push) Successful in 1m11s
feat: forgot/reset password API (variant A). Fixes EventHub/EventHubBack#57
2026-07-24 20:12:53 +03:00

83 lines
3.1 KiB
Erlang
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-module(logic_password_reset_tests).
-include_lib("eunit/include/eunit.hrl").
-include("records.hrl").
-define(TABLES, [user, password_reset, auth_session]).
setup() ->
eh_test_support:start_mnesia(),
eh_test_support:ensure_tables(?TABLES),
catch ets:new(eventhub_counters, [named_table, public, set, {write_concurrency, true}]),
ok.
cleanup(_) ->
catch ets:delete(eventhub_counters),
eh_test_support:delete_tables(?TABLES),
eh_test_support:stop_mnesia(),
ok.
logic_password_reset_test_() ->
{foreach, fun setup/0, fun cleanup/1, [
{"request_reset active sends token", {timeout, 60, fun test_request_active/0}},
{"request_reset pending silent", {timeout, 60, fun test_request_pending/0}},
{"reset_password happy path + revoke sessions", {timeout, 60, fun test_reset_ok/0}},
{"reset_password expired", {timeout, 60, fun test_reset_expired/0}},
{"reset_password short password", {timeout, 60, fun test_short_password/0}}
]}.
seed_active() ->
{ok, Hash} = logic_auth:hash_password(<<"OldPass123">>),
User = eh_test_support:make_user(#{
id => <<"u_active_pw">>,
email => <<"active-pw@test.local">>,
status => active,
password_hash => Hash
}),
ok = mnesia:dirty_write(User),
User.
seed_pending() ->
User = eh_test_support:make_user(#{
id => <<"u_pending_pw">>,
email => <<"pending-pw@test.local">>,
status => pending
}),
ok = mnesia:dirty_write(User),
User.
test_request_active() ->
User = seed_active(),
?assertEqual({ok, sent}, logic_password_reset:request_reset(User#user.email)),
Matches = mnesia:dirty_match_object(#password_reset{user_id = User#user.id, _ = '_'}),
?assertMatch([_], Matches).
test_request_pending() ->
User = seed_pending(),
?assertEqual({ok, sent}, logic_password_reset:request_reset(User#user.email)),
Matches = mnesia:dirty_match_object(#password_reset{user_id = User#user.id, _ = '_'}),
?assertEqual([], Matches).
test_reset_ok() ->
User = seed_active(),
{ok, Session} = core_auth_session:create(User#user.id, user, <<"web">>),
{ok, Token, _} = core_password_reset:create_token(User#user.id),
?assertEqual(ok, logic_password_reset:reset_password(Token, <<"NewPass456">>)),
{ok, Updated} = core_user:get_by_id(User#user.id),
?assertMatch({ok, true}, logic_auth:verify_password(<<"NewPass456">>, Updated#user.password_hash)),
{ok, Sess2} = core_auth_session:get(Session#auth_session.session_id),
?assertEqual(true, Sess2#auth_session.revoked),
?assertEqual({error, not_found}, core_password_reset:verify_token(Token)).
test_reset_expired() ->
User = seed_active(),
Past = calendar:gregorian_seconds_to_datetime(
calendar:datetime_to_gregorian_seconds(calendar:universal_time()) - 10),
Token = <<"expired_tok">>,
mnesia:dirty_write(#password_reset{token = Token, user_id = User#user.id, expires_at = Past}),
?assertEqual({error, expired}, logic_password_reset:reset_password(Token, <<"NewPass456">>)).
test_short_password() ->
User = seed_active(),
{ok, Token, _} = core_password_reset:create_token(User#user.id),
?assertEqual({error, invalid_password}, logic_password_reset:reset_password(Token, <<"short">>)).