diff --git a/lib/recognizer_web/controllers/accounts/user_settings_controller.ex b/lib/recognizer_web/controllers/accounts/user_settings_controller.ex index 606c5dd..d3df06b 100644 --- a/lib/recognizer_web/controllers/accounts/user_settings_controller.ex +++ b/lib/recognizer_web/controllers/accounts/user_settings_controller.ex @@ -33,14 +33,30 @@ defmodule RecognizerWeb.Accounts.UserSettingsController do end def resend(conn, _params) do - conn = - conn - |> put_session(:two_factor_sent, false) - |> put_session(:two_factor_issue_time, System.system_time(:second)) + user = Authentication.fetch_current_user(conn) + current_user = Accounts.get_new_two_factor_settings(user) - conn - |> put_flash(:info, "Two factor code has been resent") - |> redirect(to: Routes.user_settings_path(conn, :two_factor_init)) + case current_user do + {:error, _} -> + conn + |> put_flash(:error, "Two factor setup expired or not yet initiated") + |> redirect(to: Routes.user_settings_path(conn, :edit)) + + {:ok, nil} -> + conn + |> put_flash(:error, "Two factor setup expired or not yet initiated") + |> redirect(to: Routes.user_settings_path(conn, :edit)) + + {:ok, _setting_user} -> + conn = + conn + |> put_session(:two_factor_sent, false) + |> put_session(:two_factor_issue_time, System.system_time(:second)) + + conn + |> put_flash(:info, "Two factor code has been resent") + |> redirect(to: Routes.user_settings_path(conn, :two_factor_init)) + end end @doc """ @@ -49,36 +65,37 @@ defmodule RecognizerWeb.Accounts.UserSettingsController do def two_factor_init(conn, _params) do user = Authentication.fetch_current_user(conn) current_user = Accounts.get_new_two_factor_settings(user) - {:ok, %{two_factor_seed: seed, notification_preference: %{two_factor: method}} = setting_user} = current_user - method_atom = normalize_to_atom(method) + case current_user do + {:error, _} -> + conn + |> put_flash(:error, "Two factor setup expired or not yet initiated") + |> redirect(to: Routes.user_settings_path(conn, :edit)) - if method in [:app, "app"] do - render(conn, "confirm_two_factor.html", - barcode: Authentication.generate_totp_barcode(user, seed), - totp_app_url: Authentication.get_totp_app_url(user, seed) - ) - else - conn = - if get_session(conn, :two_factor_issue_time) == nil do - put_session(conn, :two_factor_issue_time, System.system_time(:second)) - else - conn - end + {:ok, nil} -> + conn + |> put_flash(:error, "Two factor setup expired or not yet initiated") + |> redirect(to: Routes.user_settings_path(conn, :edit)) - two_factor_sent = get_session(conn, :two_factor_sent) + {:ok, setting_user} -> + %{two_factor_seed: seed, notification_preference: %{two_factor: method}} = setting_user - conn = - if two_factor_sent do - conn + method_atom = normalize_to_atom(method) + + if method in [:app, "app"] do + render(conn, "confirm_two_factor.html", + barcode: Authentication.generate_totp_barcode(user, seed), + totp_app_url: Authentication.get_totp_app_url(user, seed) + ) else - conn = put_session(conn, :two_factor_sent, true) + current_time = System.system_time(:second) + + conn = ensure_two_factor_issue_time(conn, current_time) + conn = two_factor_init_two_factor_sent(conn, setting_user, user, method_atom) conn - |> send_two_factor_notification(setting_user, user, method_atom) + |> render("confirm_two_factor_external.html") end - - render(conn, "confirm_two_factor_external.html") end end @@ -129,6 +146,22 @@ defmodule RecognizerWeb.Accounts.UserSettingsController do end end + def two_factor_init_two_factor_sent(conn, setting_user, user, method_atom) do + two_factor_sent = get_session(conn, :two_factor_sent) + + conn_session = + if two_factor_sent do + conn + else + conn + |> send_two_factor_notification(setting_user, user, method_atom) + + put_session(conn, :two_factor_sent, true) + end + + conn_session + end + defp handle_two_factor_settings(conn, user, two_factor_code, method) do two_factor_issue_time = get_session(conn, :two_factor_issue_time) diff --git a/lib/recognizer_web/controllers/accounts/user_two_factor_controller.ex b/lib/recognizer_web/controllers/accounts/user_two_factor_controller.ex index 929d049..0c66787 100644 --- a/lib/recognizer_web/controllers/accounts/user_two_factor_controller.ex +++ b/lib/recognizer_web/controllers/accounts/user_two_factor_controller.ex @@ -36,32 +36,38 @@ defmodule RecognizerWeb.Accounts.UserTwoFactorController do current_user_id = get_session(conn, :two_factor_user_id) current_user = Accounts.get_user!(current_user_id) current_time = System.system_time(:second) - %{notification_preference: %{two_factor: two_factor_method}} = Accounts.load_notification_preferences(current_user) - - conn = - if get_session(conn, :two_factor_issue_time) == nil do - conn - |> put_session(:two_factor_issue_time, current_time) - else - conn - end - - two_factor_sent = get_session(conn, :two_factor_sent) + current_user = Accounts.load_notification_preferences(current_user) + + case current_user do + %{notification_preference: %{two_factor: two_factor_method}} -> + conn = + if get_session(conn, :two_factor_issue_time) == nil do + conn + |> put_session(:two_factor_issue_time, current_time) + else + conn + end + + two_factor_sent = get_session(conn, :two_factor_sent) + + conn = + if two_factor_sent == false do + conn + |> maybe_send_two_factor_notification(current_user, two_factor_method) + + conn + |> put_session(:two_factor_sent, true) + |> put_session(:two_factor_issue_time, current_time) + else + conn + end - conn = - if two_factor_sent == false do conn - |> maybe_send_two_factor_notification(current_user, two_factor_method) + |> render("new.html", two_factor_method: two_factor_method) - conn - |> put_session(:two_factor_sent, true) - |> put_session(:two_factor_issue_time, current_time) - else - conn - end - - conn - |> render("new.html", two_factor_method: two_factor_method) + _ -> + conn.redirect(to: Routes.user_session_path(conn, :new)) + end end @doc """ diff --git a/lib/recognizer_web/router.ex b/lib/recognizer_web/router.ex index 0aa358e..fffe625 100644 --- a/lib/recognizer_web/router.ex +++ b/lib/recognizer_web/router.ex @@ -140,6 +140,6 @@ defmodule RecognizerWeb.Router do get "/settings/two-factor/review", UserSettingsController, :review get "/settings/two-factor", UserSettingsController, :two_factor_init post "/settings/two-factor", UserSettingsController, :two_factor_confirm - get "/setting/two-factor/resend", UserSettingsController, :resend + get "/settings/two-factor/resend", UserSettingsController, :resend end end diff --git a/mix.exs b/mix.exs index befded9..8593f22 100644 --- a/mix.exs +++ b/mix.exs @@ -33,7 +33,7 @@ defmodule Recognizer.MixProject do defp deps do [ {:argon2_elixir, "~> 2.0"}, - {:bottle, github: "system76/bottle", ref: "1a49e7bc7d8f7bf556c5780b70e9eb60a06a8ca7"}, + {:bottle, github: "system76/bottle", ref: "ea81e3024965a2b8e72b1f345c040d4e209ef259"}, {:cors_plug, "~> 2.0"}, {:cowboy, "~> 2.8", override: true}, {:cowlib, "~> 2.9.1", override: true},