[#114] Added :user_id component to email confirmation path to improve the security.
Added tests for `confirm_email` action.
This commit is contained in:
parent
8adcd1e80f
commit
f69cbf4755
5 changed files with 26 additions and 10 deletions
|
@ -70,6 +70,7 @@ def account_confirmation_email(user) do
|
||||||
Router.Helpers.confirm_email_url(
|
Router.Helpers.confirm_email_url(
|
||||||
Endpoint,
|
Endpoint,
|
||||||
:confirm_email,
|
:confirm_email,
|
||||||
|
user.id,
|
||||||
to_string(user.info.confirmation_token)
|
to_string(user.info.confirmation_token)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -396,10 +396,6 @@ def get_or_fetch_by_nickname(nickname) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_by_confirmation_token(token) do
|
|
||||||
Repo.one(from(u in User, where: fragment("? ->> 'confirmation_token' = ?", u.info, ^token)))
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_followers_query(%User{id: id, follower_address: follower_address}) do
|
def get_followers_query(%User{id: id, follower_address: follower_address}) do
|
||||||
from(
|
from(
|
||||||
u in User,
|
u in User,
|
||||||
|
|
|
@ -282,7 +282,12 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/account/register", TwitterAPI.Controller, :register)
|
post("/account/register", TwitterAPI.Controller, :register)
|
||||||
post("/account/password_reset", TwitterAPI.Controller, :password_reset)
|
post("/account/password_reset", TwitterAPI.Controller, :password_reset)
|
||||||
|
|
||||||
get("/account/confirm_email/:token", TwitterAPI.Controller, :confirm_email, as: :confirm_email)
|
get(
|
||||||
|
"/account/confirm_email/:user_id/:token",
|
||||||
|
TwitterAPI.Controller,
|
||||||
|
:confirm_email,
|
||||||
|
as: :confirm_email
|
||||||
|
)
|
||||||
|
|
||||||
post("/account/resend_confirmation_email", TwitterAPI.Controller, :resend_confirmation_email)
|
post("/account/resend_confirmation_email", TwitterAPI.Controller, :resend_confirmation_email)
|
||||||
|
|
||||||
|
|
|
@ -382,9 +382,11 @@ def password_reset(conn, params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def confirm_email(conn, %{"token" => token}) do
|
def confirm_email(conn, %{"user_id" => uid, "token" => token}) do
|
||||||
with %User{} = user <- User.get_by_confirmation_token(token),
|
with %User{} = user <- Repo.get(User, uid),
|
||||||
true <- user.local,
|
true <- user.local,
|
||||||
|
true <- user.info.confirmation_pending,
|
||||||
|
true <- user.info.confirmation_token == token,
|
||||||
info_change <- User.Info.confirmation_changeset(user.info, :confirmed),
|
info_change <- User.Info.confirmation_changeset(user.info, :confirmed),
|
||||||
changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_change),
|
changeset <- Changeset.change(user) |> Changeset.put_embed(:info, info_change),
|
||||||
{:ok, _} <- User.update_and_set_cache(changeset) do
|
{:ok, _} <- User.update_and_set_cache(changeset) do
|
||||||
|
|
|
@ -873,7 +873,7 @@ test "it returns 500 when user is not local", %{conn: conn, user: user} do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /api/account/confirm_email/:token" do
|
describe "GET /api/account/confirm_email/:id/:token" do
|
||||||
setup do
|
setup do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
|
info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
|
||||||
|
@ -890,19 +890,31 @@ test "it returns 500 when user is not local", %{conn: conn, user: user} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it redirects to root url", %{conn: conn, user: user} do
|
test "it redirects to root url", %{conn: conn, user: user} do
|
||||||
conn = get(conn, "/api/account/confirm_email/#{user.info.confirmation_token}")
|
conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
|
||||||
|
|
||||||
assert 302 == conn.status
|
assert 302 == conn.status
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it confirms the user account", %{conn: conn, user: user} do
|
test "it confirms the user account", %{conn: conn, user: user} do
|
||||||
get(conn, "/api/account/confirm_email/#{user.info.confirmation_token}")
|
get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
|
||||||
|
|
||||||
user = Repo.get(User, user.id)
|
user = Repo.get(User, user.id)
|
||||||
|
|
||||||
refute user.info.confirmation_pending
|
refute user.info.confirmation_pending
|
||||||
refute user.info.confirmation_token
|
refute user.info.confirmation_token
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
|
||||||
|
conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
|
||||||
|
|
||||||
|
assert 500 == conn.status
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns 500 if token is invalid", %{conn: conn, user: user} do
|
||||||
|
conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
|
||||||
|
|
||||||
|
assert 500 == conn.status
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /api/account/resend_confirmation_email" do
|
describe "POST /api/account/resend_confirmation_email" do
|
||||||
|
|
Loading…
Reference in a new issue