mirror of
https://github.com/plausible/analytics.git
synced 2024-09-11 18:07:33 +03:00
Handle missing or expired token in password reset action and LV gracefully (#3387)
This change addresses two problems: * controller action crashing missing "token" param - it's handled gracefully now and will not pollute Sentry anymore with http://sentry.plausible.io/organizations/sentry/issues/4319 * LiveView receives email extracted from token on initial page load instead of reverifying token on every re-mount (which can happen when somebody leaves form open for an extended period of time; rare but happens and needlessly pollutes Sentry as well)
This commit is contained in:
parent
e67850c11d
commit
16ce0f1ea8
@ -194,12 +194,12 @@ defmodule PlausibleWeb.AuthController do
|
||||
end
|
||||
end
|
||||
|
||||
def password_reset_form(conn, %{"token" => token}) do
|
||||
case Auth.Token.verify_password_reset(token) do
|
||||
{:ok, _} ->
|
||||
def password_reset_form(conn, params) do
|
||||
case Auth.Token.verify_password_reset(params["token"]) do
|
||||
{:ok, %{email: email}} ->
|
||||
render(conn, "password_reset_form.html",
|
||||
connect_live_socket: true,
|
||||
token: token,
|
||||
email: email,
|
||||
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
||||
)
|
||||
|
||||
|
@ -11,11 +11,9 @@ defmodule PlausibleWeb.Live.ResetPasswordForm do
|
||||
alias Plausible.Auth
|
||||
alias Plausible.Repo
|
||||
|
||||
def mount(_params, %{"reset_token" => reset_token}, socket) do
|
||||
def mount(_params, %{"email" => email}, socket) do
|
||||
socket =
|
||||
assign_new(socket, :user, fn ->
|
||||
# by that point token should be already verified
|
||||
{:ok, %{email: email}} = Auth.Token.verify_password_reset(reset_token)
|
||||
Repo.get_by!(Auth.User, email: email)
|
||||
end)
|
||||
|
||||
@ -24,7 +22,6 @@ defmodule PlausibleWeb.Live.ResetPasswordForm do
|
||||
{:ok,
|
||||
assign(socket,
|
||||
form: to_form(changeset),
|
||||
reset_token: reset_token,
|
||||
password_strength: Auth.User.password_strength(changeset),
|
||||
trigger_submit: false
|
||||
)}
|
||||
@ -60,7 +57,6 @@ defmodule PlausibleWeb.Live.ResetPasswordForm do
|
||||
class="transition bg-gray-100 dark:bg-gray-900 outline-none appearance-none border border-transparent rounded w-full p-2 text-gray-700 dark:text-gray-300 leading-normal appearance-none focus:outline-none focus:bg-white dark:focus:bg-gray-800 focus:border-gray-300 dark:focus:border-gray-500"
|
||||
/>
|
||||
</div>
|
||||
<input name="token" type="hidden" value={@reset_token} />
|
||||
<button id="set" type="submit" class="button mt-4 w-full">
|
||||
Set password →
|
||||
</button>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<%= live_render(@conn, PlausibleWeb.Live.ResetPasswordForm,
|
||||
container: {:div, class: "contents"},
|
||||
session: %{"reset_token" => @token}
|
||||
session: %{"email" => @email}
|
||||
) %>
|
||||
|
@ -409,16 +409,17 @@ defmodule PlausibleWeb.AuthControllerTest do
|
||||
|
||||
assert html_response(conn, 401) =~ "Your token is invalid"
|
||||
end
|
||||
|
||||
test "without token - shows error page", %{conn: conn} do
|
||||
conn = get(conn, "/password/reset", %{})
|
||||
|
||||
assert html_response(conn, 401) =~ "Your token is invalid"
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /password/reset" do
|
||||
alias Plausible.Auth.Token
|
||||
|
||||
test "redirects the user to login and shows success message", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
token = Token.sign_password_reset(user.email)
|
||||
|
||||
conn = post(conn, "/password/reset", %{token: token})
|
||||
conn = post(conn, "/password/reset", %{})
|
||||
|
||||
assert location = "/login" = redirected_to(conn, 302)
|
||||
|
||||
|
@ -18,9 +18,8 @@ defmodule PlausibleWeb.Live.ResetPasswordFormTest do
|
||||
type_into_passowrd(lv, "very-secret-and-very-long-123")
|
||||
html = lv |> element("form") |> render_submit()
|
||||
|
||||
assert [csrf_input, password_input, token_input | _] = find(html, "input")
|
||||
assert [csrf_input, password_input | _] = find(html, "input")
|
||||
assert String.length(text_of_attr(csrf_input, "value")) > 0
|
||||
assert text_of_attr(token_input, "value") == token
|
||||
assert text_of_attr(password_input, "value") == "very-secret-and-very-long-123"
|
||||
assert %{password_hash: new_hash} = Repo.one(User)
|
||||
assert new_hash != user.password_hash
|
||||
|
Loading…
Reference in New Issue
Block a user