mirror of
https://github.com/plausible/analytics.git
synced 2024-11-23 03:04:43 +03:00
Rate limit e-mail changes (#3667)
This commit is contained in:
parent
5c8f39ac4c
commit
9cb44291f7
@ -300,6 +300,8 @@ defmodule PlausibleWeb.AuthController do
|
||||
|
||||
@login_interval 60_000
|
||||
@login_limit 5
|
||||
@email_change_limit 2
|
||||
@email_change_interval :timer.hours(1)
|
||||
|
||||
defp check_ip_rate_limit(conn) do
|
||||
ip_address = PlausibleWeb.RemoteIp.get(conn)
|
||||
@ -550,20 +552,42 @@ defmodule PlausibleWeb.AuthController do
|
||||
|
||||
def update_email(conn, %{"user" => user_params}) do
|
||||
user = conn.assigns.current_user
|
||||
changes = Auth.User.email_changeset(user, user_params)
|
||||
|
||||
case Repo.update(changes) do
|
||||
{:ok, user} ->
|
||||
if user.email_verified do
|
||||
handle_email_updated(conn)
|
||||
else
|
||||
Auth.EmailVerification.issue_code(user)
|
||||
redirect(conn, to: Routes.auth_path(conn, :activate_form))
|
||||
case RateLimit.check_rate(
|
||||
"email-change:user:#{user.id}",
|
||||
@email_change_interval,
|
||||
@email_change_limit
|
||||
) do
|
||||
{:allow, _} ->
|
||||
changes = Auth.User.email_changeset(user, user_params)
|
||||
|
||||
case Repo.update(changes) do
|
||||
{:ok, user} ->
|
||||
if user.email_verified do
|
||||
handle_email_updated(conn)
|
||||
else
|
||||
Auth.EmailVerification.issue_code(user)
|
||||
redirect(conn, to: Routes.auth_path(conn, :activate_form))
|
||||
end
|
||||
|
||||
{:error, changeset} ->
|
||||
settings_changeset = Auth.User.settings_changeset(user)
|
||||
|
||||
render_settings(conn,
|
||||
settings_changeset: settings_changeset,
|
||||
email_changeset: changeset
|
||||
)
|
||||
end
|
||||
|
||||
{:error, changeset} ->
|
||||
{:deny, _} ->
|
||||
settings_changeset = Auth.User.settings_changeset(user)
|
||||
|
||||
{:error, changeset} =
|
||||
user
|
||||
|> Auth.User.email_changeset(user_params)
|
||||
|> Ecto.Changeset.add_error(:email, "too many requests, try again in an hour")
|
||||
|> Ecto.Changeset.apply_action(:validate)
|
||||
|
||||
render_settings(conn,
|
||||
settings_changeset: settings_changeset,
|
||||
email_changeset: changeset
|
||||
|
@ -1193,6 +1193,24 @@ defmodule PlausibleWeb.AuthControllerTest do
|
||||
assert subject =~ "is your Plausible email verification code"
|
||||
end
|
||||
|
||||
test "renders an error on third change attempt (allows 2 per hour)", %{conn: conn, user: user} do
|
||||
payload = %{
|
||||
"user" => %{"email" => "new" <> user.email, "password" => "badpass"}
|
||||
}
|
||||
|
||||
resp1 = conn |> put("/settings/email", payload) |> html_response(200)
|
||||
assert resp1 =~ "is invalid"
|
||||
refute resp1 =~ "too many requests, try again in an hour"
|
||||
|
||||
resp2 = conn |> put("/settings/email", payload) |> html_response(200)
|
||||
assert resp2 =~ "is invalid"
|
||||
refute resp2 =~ "too many requests, try again in an hour"
|
||||
|
||||
resp3 = conn |> put("/settings/email", payload) |> html_response(200)
|
||||
assert resp3 =~ "is invalid"
|
||||
assert resp3 =~ "too many requests, try again in an hour"
|
||||
end
|
||||
|
||||
test "renders form with error on no fields filled", %{conn: conn} do
|
||||
conn = put(conn, "/settings/email", %{"user" => %{}})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user