From 62808297e012389abfaa9906aa1d80cbf9b8a74d Mon Sep 17 00:00:00 2001 From: Andrew Hebert Date: Tue, 12 Mar 2024 16:28:23 -0400 Subject: [PATCH] fixed: cache clear and retry redirect * settings cache cleared on 2fa confirm * redirect to retry after confirming with incorrect code --- .../accounts/user_settings_controller.ex | 8 +-- .../user_settings_controller_test.exs | 50 ++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/lib/recognizer_web/controllers/accounts/user_settings_controller.ex b/lib/recognizer_web/controllers/accounts/user_settings_controller.ex index 9805e0af..6c6b4328 100644 --- a/lib/recognizer_web/controllers/accounts/user_settings_controller.ex +++ b/lib/recognizer_web/controllers/accounts/user_settings_controller.ex @@ -30,14 +30,16 @@ defmodule RecognizerWeb.Accounts.UserSettingsController do case Accounts.confirm_and_save_two_factor_settings(two_factor_code, user) do {:ok, _updated_user} -> + Accounts.clear_two_factor_settings(user) + conn - |> put_flash(:info, "Two factor code verified.") + |> put_flash(:info, "Two factor code verified") |> redirect(to: Routes.user_settings_path(conn, :edit)) _ -> conn - |> put_flash(:error, "Two factor code is invalid.") - |> redirect(to: Routes.user_settings_path(conn, :confirm_two_factor)) + |> put_flash(:error, "Two factor code is invalid") + |> redirect(to: Routes.user_settings_path(conn, :two_factor_confirm)) end end diff --git a/test/recognizer_web/controllers/accounts/user_settings_controller_test.exs b/test/recognizer_web/controllers/accounts/user_settings_controller_test.exs index 22651339..c7031c55 100644 --- a/test/recognizer_web/controllers/accounts/user_settings_controller_test.exs +++ b/test/recognizer_web/controllers/accounts/user_settings_controller_test.exs @@ -6,6 +6,10 @@ defmodule RecognizerWeb.Accounts.UserSettingsControllerTest do import Recognizer.BigCommerceTestHelpers alias Recognizer.Accounts + alias Recognizer.Accounts.User + alias Recognizer.Repo + alias RecognizerWeb.Authentication + setup :register_and_log_in_user @@ -113,9 +117,11 @@ defmodule RecognizerWeb.Accounts.UserSettingsControllerTest do end end + + describe "GET /users/settings/two-factor/review (backup codes)" do test "gets review page after 2fa setup", %{conn: conn, user: user} do - Recognizer.Accounts.generate_and_cache_new_two_factor_settings(user, "app") + Accounts.generate_and_cache_new_two_factor_settings(user, "app") conn = get(conn, Routes.user_settings_path(conn, :review)) _response = html_response(conn, 200) end @@ -123,7 +129,47 @@ defmodule RecognizerWeb.Accounts.UserSettingsControllerTest do test "review 2fa without cached codes is redirected with flash error", %{conn: conn} do conn = get(conn, Routes.user_settings_path(conn, :review)) _response = html_response(conn, 302) - assert get_flash(conn, :error) == "Two factor setup not yet initiated" + assert get_flash(conn, :error) == "Two factor setup expired or not yet initiated" end end + + describe "GET /users/settings/two-factor (confirmation)" do + test "/two-factor page is rendered with settings", %{conn: conn, user: user} do + Accounts.generate_and_cache_new_two_factor_settings(user, "app") + conn = get(conn, Routes.user_settings_path(conn, :two_factor)) + assert html_response(conn, 200) =~ "Configure App" + end + + test "/two-factor/confirm saves and clears", %{conn: conn, user: user} do + settings = Accounts.generate_and_cache_new_two_factor_settings(user, "app") + + token = Authentication.generate_token(settings) + params = %{"two_factor_code" => token} + + conn = post(conn, Routes.user_settings_path(conn, :two_factor_confirm), params) + + assert redirected_to(conn) =~ "/settings" + assert get_flash(conn, :info) =~ "Two factor code verified" + + %{recovery_codes: recovery_codes} = + User + |> Repo.get(user.id) + |> Repo.preload(:recovery_codes) + + refute Enum.empty?(recovery_codes) + + assert {:ok, nil} = Accounts.get_new_two_factor_settings(user) + end + + test "/two-factor/confirm redirects without cached settings", %{conn: conn, user: user} do + settings = Accounts.generate_and_cache_new_two_factor_settings(user, "app") + token = Authentication.generate_token(settings) + Accounts.clear_two_factor_settings(user) + params = %{"two_factor_code" => token} + conn = post(conn, Routes.user_settings_path(conn, :two_factor_confirm), params) + assert redirected_to(conn) =~ "/two-factor" + assert get_flash(conn, :error) =~ "Two factor code is invalid" + end + end + end